diff --git a/README.md b/README.md index f5aee2a..027e576 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,46 @@ # Dev Metrics in Readme with added feature flags 🎌 -![Project Preview](https://user-images.githubusercontent.com/15426564/87876319-0b2eac00-c9f5-11ea-9049-233c1b260e7f.png) +![Project Preview](https://user-images.githubusercontent.com/15426564/88030180-8e1c4780-cb58-11ea-8a8b-b3576dd73652.png) + +

+ + ![Project Preview](https://user-images.githubusercontent.com/25841814/79395484-5081ae80-7fac-11ea-9e27-ac91472e31dd.png) + +

πŸ“Œβœ¨Awesome Readme Stats

+

+ ---- -[WakaTime](https://wakatime.com) Weekly Metrics on your Profile Readme: +

+ + + + +

+

+ Are you an early 🐀 or a night πŸ¦‰? +
+ When are you most productive during the day? +
+ The languages you code in +
+ Let's check out in your readme! +

## Prep Work 1. You need to update the markdown file(.md) with 2 comments. You can refer [here](#update-your-readme) for updating it. 2. You'll need a WakaTime API Key. You can get that from your WakaTime Account Settings - You can refer [here](#new-to-wakatime), if you're new to WakaTime -3. **Optional** You'll need a GitHub API Token with `repo` scope from [here](https://github.com/settings/tokens) if you're running the action not in your Profile Repository - - You can use [this](#other-repository-not-profile) example to work it out -4. You need to save the WakaTime API Key (and the GitHub API Token, if you need it) in the repository secrets. You can find that in the Settings of your Repository.Be sure to save those as the following. +3. You'll need a GitHub API Token with `repo` scope from [here](https://github.com/settings/tokens) if you're running the action to get commit metrics + > enable `repo` scope seems **DANGEROUS**
+ > but this GitHub Action only accesses your commit timestamp in repository you contributed. + - You can use [this](#profile-repository) example to work it out +4. You need to save the WakaTime API Key and the GitHub API Token in the repository secrets. You can find that in the Settings of your Repository.Be sure to save those as the following. - WakaTime-api-key as `WAKATIME_API_KEY = `and - The GitHub Access Token as `GH_TOKEN=` -5. You can follow either of the Two Examples according to your needs to get started with. +5. You can enable and disable feature flags based on requirements. -> I strongly suggest you to run the Action in your Profile Repo since you won't be needing a GitHub Access Token This Action will run everyday at 00.00 IST @@ -43,34 +66,6 @@ WakaTime gives you an idea of the time you really spent on coding. This helps yo ### Profile Repository -*If you're executing the workflow on your Profile Repository (`/`)* - -> You wouldn't need an GitHub Access Token since GitHub Actions already makes one for you. - -Here is a sample workflow file for you to get started: - -```yml -name: Waka Readme - -on: - schedule: - # Runs at 12am IST - - cron: '30 18 * * *' - -jobs: - update-readme: - name: Update this repo's README - runs-on: ubuntu-latest - steps: - - uses: anmol098/waka-readme-stats@master - with: - WAKATIME_API_KEY: ${{ secrets.WAKATIME_API_KEY }} -``` - -### Other Repository (not Profile) - -*If you're executing the workflow on another repo other than `/`* - You'll need to get a [GitHub Access Token](https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token) with a `repo` scope and save it in the Repo Secrets `GH_TOKEN = ` Here is Sample Workflow File for running it: @@ -109,7 +104,18 @@ jobs: ``` #### Flags Available -`SHOW_OS` flag can be set to `False` to hide the OS details +`SHOW_COMMIT` flag can be set to `False` to hide the commit stats + +**I'm an early 🐀** +```text +🌞 Morning 95 commits β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 30.55% +πŸŒ† Daytime 78 commits β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 25.08% +πŸŒƒ Evening 112 commits β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 36.01% +πŸŒ™ Night 26 commits β–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 8.36% + +``` + +`SHOW_LANGUAGE` flag can be set to `False` to hide the Coding Language You use ```text πŸ’¬ Languages: @@ -118,7 +124,12 @@ PHP 1 hr 35 mins β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘ Markdown 1 hr 9 mins β–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 13.3% Python 22 mins β–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 4.32% XML 8 mins β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 1.62% +``` + +`SHOW_OS` flag can be set to `False` to hide the OS details + +```text πŸ’» Operating Systems: Windows 8 hrs 46 mins β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 100.0% ``` @@ -126,53 +137,30 @@ Windows 8 hrs 46 mins β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ `SHOW_PROJECTS` flag can be set to `False` to hide the Projects worked on ```text -πŸ’¬ Languages: -JavaScript 5 hrs 26 mins β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 61.97% -PHP 1 hr 35 mins β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 18.07% -Markdown 1 hr 9 mins β–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 13.3% -Python 22 mins β–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 4.32% -XML 8 mins β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 1.62% - πŸ±β€πŸ’» Projects: ctx_connector 4 hrs 3 mins β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 46.33% NetSuite-Connector 1 hr 31 mins β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 17.29% mango-web-master 1 hr 12 mins β–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 13.77% cable 54 mins β–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 10.41% denAPI 40 mins β–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 7.66% - ``` `SHOW_TIMEZONE` flag can be set to `False` to hide the time zone you are in ```text ⌚︎ Timezone: Asia/Calcutta - -πŸ’¬ Languages: -JavaScript 5 hrs 26 mins β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 61.97% -PHP 1 hr 35 mins β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 18.07% -Markdown 1 hr 9 mins β–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 13.3% -Python 22 mins β–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 4.32% -XML 8 mins β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 1.62% - ``` `SHOW_EDITORS` flag can be set to `False` to hide the list of code-editors used ```text -πŸ’¬ Languages: -JavaScript 5 hrs 26 mins β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 61.97% -PHP 1 hr 35 mins β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 18.07% -Markdown 1 hr 9 mins β–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 13.3% -Python 22 mins β–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 4.32% -XML 8 mins β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 1.62% - πŸ”₯ Editors: WebStorm 6 hrs 47 mins β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘ 77.43% PhpStorm 1 hr 35 mins β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 18.07% PyCharm 23 mins β–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘ 4.49% - ``` -This project is inspired from [athul/waka-readme](https://github.com/athul/waka-readme) with added extra feature. +> This project is inspired by an awesome pinned-gist project [Awesome Pinned Gists](https://github.com/matchai/awesome-pinned-gists)
+>This project is inspired from [athul/waka-readme](https://github.com/athul/waka-readme) ### Don't forget to leave a ⭐ if you found this useful. diff --git a/action.yml b/action.yml index 1b18060..713ed84 100644 --- a/action.yml +++ b/action.yml @@ -37,6 +37,16 @@ inputs: description: 'Show the time zone in the dev metrics' default: "True" + SHOW_COMMIT: + required: false + description: "Shows the number of commit graph in the dev metrics" + default: "True" + + SHOW_LANGUAGE: + required: false + description: "Show the Coding language used in dev metrics" + default: "True" + diff --git a/main.py b/main.py index 41acb41..b056db2 100644 --- a/main.py +++ b/main.py @@ -1,14 +1,14 @@ ''' -WakaTime progress visualizer +Readme Development Metrics With waka time progress ''' import re import os import base64 -import datetime -import pytz import requests from github import Github +import datetime +from string import Template START_COMMENT = '' END_COMMENT = '' @@ -21,17 +21,59 @@ showTimeZone = os.getenv('INPUT_SHOW_TIMEZONE') showProjects = os.getenv('INPUT_SHOW_PROJECTS') showEditors = os.getenv('INPUT_SHOW_EDITORS') showOs = os.getenv('INPUT_SHOW_OS') +showCommit = os.getenv('INPUT_SHOW_COMMIT') +showLanguage = os.getenv('INPUT_SHOW_LANGUAGE') -print(showTimeZone + " " + showOs + " " + showProjects + " " + showEditors) +# The GraphQL query to get commit data. +userInfoQuery = """ +{ + viewer { + login + id + } + } +""" +createContributedRepoQuery = Template("""query { + user(login: "$username") { + repositoriesContributedTo(last: 100, includeUserRepositories: true) { + nodes { + isFork + name + owner { + login + } + } + } + } + } +""") +createCommittedDateQuery = Template(""" +query { + repository(owner: "$owner", name: "$name") { + ref(qualifiedName: "master") { + target { + ... on Commit { + history(first: 100, author: { id: "$id" }) { + edges { + node { + committedDate + } + } + } + } + } + } + } + } +""") -def this_week(): - '''Returns current week span''' - week_number = datetime.date.today().isocalendar()[1] - month = datetime.date.today().strftime('%B') - week_start = datetime.datetime.today().day - datetime.datetime.today().weekday() - week_end = week_start + 5 - return f"Week #{week_number} : {month} {week_start} - {week_end}" +def run_query(query): + request = requests.post('https://api.github.com/graphql', json={'query': query}, headers=headers) + if request.status_code == 200: + return request.json() + else: + raise Exception("Query failed to run by returning code of {}. {}".format(request.status_code, query)) def make_graph(percent: float): @@ -53,32 +95,108 @@ def make_list(data: list): return ' \n'.join(data_list) +def make_commit_list(data: list): + '''Make List''' + data_list = [] + for l in data[:5]: + ln = len(l['name']) + ln_text = len(l['text']) + op = f"{l['name']}{' ' * (13 - ln)}{l['text']}{' ' * (15 - ln_text)}{make_graph(l['percent'])} {l['percent']}%" + data_list.append(op) + return ' \n'.join(data_list) + + +def generate_commit_list(): + result = run_query(userInfoQuery) # Execute the query + username = result["data"]["viewer"]["login"] + id = result["data"]["viewer"]["id"] + print("user {} id {}".format(username, id)) + + result = run_query(createContributedRepoQuery.substitute(username=username)) + nodes = result["data"]["user"]["repositoriesContributedTo"]["nodes"] + repos = [d for d in nodes if d['isFork'] is False] + + morning = 0 # 6 - 12 + daytime = 0 # 12 - 18 + evening = 0 # 18 - 24 + night = 0 # 0 - 6 + + for repository in repos: + result = run_query( + createCommittedDateQuery.substitute(owner=repository["owner"]["login"], name=repository["name"], id=id)) + committed_dates = result["data"]["repository"]["ref"]["target"]["history"]["edges"] + for committedDate in committed_dates: + date = datetime.datetime.strptime(committedDate["node"]["committedDate"], "%Y-%m-%dT%H:%M:%SZ") + hour = date.hour + if 6 <= hour < 12: + morning += 1 + if 12 <= hour < 18: + daytime += 1 + if 18 <= hour < 24: + evening += 1 + if 0 <= hour < 6: + night += 1 + + sumAll = morning + daytime + evening + night + if morning + daytime >= evening + night: + title = "I'm an early 🐀" + else: + title = "I'm a night πŸ¦‰" + one_day = [ + {"name": "🌞 Morning", "text": str(morning) + " commits", "percent": round((morning / sumAll) * 100, 2)}, + {"name": "πŸŒ† Daytime", "text": str(daytime) + " commits", "percent": round((daytime / sumAll) * 100, 2)}, + {"name": "πŸŒƒ Evening", "text": str(evening) + " commits", "percent": round((evening / sumAll) * 100, 2)}, + {"name": "πŸŒ™ Night", "text": str(night) + " commits", "percent": round((night / sumAll) * 100, 2)}, + ] + + return '**' + title + '** \n\n' + '```text\n' + make_commit_list(one_day) + '\n\n```\n' + + def get_stats(): '''Gets API data and returns markdown progress''' - data = requests.get( - f"https://wakatime.com/api/v1/users/current/stats/last_7_days?api_key={waka_key}").json() - stats = '' - if showTimeZone.lower() in ['true', '1', 't', 'y', 'yes']: - timezone = data['data']['timezone'] - stats = stats + '⌚︎ Timezone: ' + timezone + '\n\n' - lang_list = make_list(data['data']['languages']) - stats = stats + 'πŸ’¬ Languages: \n' + lang_list + '\n\n' + if showCommit.lower() in ['true', '1', 't', 'y', 'yes']: + try: + stats = stats + generate_commit_list() + '\n\n' + except Exception as ex: + print("GitHub Personal access token not configured properly or invalid" + str(ex)) - if showEditors.lower() in ['true', '1', 't', 'y', 'yes']: - edit_list = make_list(data['data']['editors']) - stats = stats + 'πŸ”₯ Editors: \n' + edit_list + '\n\n' + try: + request = requests.get( + f"https://wakatime.com/api/v1/users/current/stats/last_7_days?api_key={waka_key}") - if showProjects.lower() in ['true', '1', 't', 'y', 'yes']: - project_list = make_list(data['data']['projects']) - stats = stats + 'πŸ±β€πŸ’» Projects: \n' + project_list + '\n\n' + if request.status_code == 200: + data = request.json() + stats = stats + 'πŸ“Š **This week I spent my time on** \n\n' + stats = stats + '```text\n' + if showTimeZone.lower() in ['true', '1', 't', 'y', 'yes']: + timezone = data['data']['timezone'] + stats = stats + '⌚︎ Timezone: ' + timezone + '\n\n' - if showOs.lower() in ['true', '1', 't', 'y', 'yes']: - os_list = make_list(data['data']['operating_systems']) - stats = stats + 'πŸ’» Operating Systems: \n' + os_list + '\n\n' + if showLanguage.lower() in ['true', '1', 't', 'y', 'yes']: + lang_list = make_list(data['data']['languages']) + stats = stats + 'πŸ’¬ Languages: \n' + lang_list + '\n\n' - return '```text\n' + stats + '```' + if showEditors.lower() in ['true', '1', 't', 'y', 'yes']: + edit_list = make_list(data['data']['editors']) + stats = stats + 'πŸ”₯ Editors: \n' + edit_list + '\n\n' + + if showProjects.lower() in ['true', '1', 't', 'y', 'yes']: + project_list = make_list(data['data']['projects']) + stats = stats + 'πŸ±β€πŸ’» Projects: \n' + project_list + '\n\n' + + if showOs.lower() in ['true', '1', 't', 'y', 'yes']: + os_list = make_list(data['data']['operating_systems']) + stats = stats + 'πŸ’» Operating Systems: \n' + os_list + '\n\n' + + stats = stats + '```\n\n' + else: + print("Waka Time Api Key Not Configured Properly") + except Exception as e: + print("Waka Time Api Key Not Configured" + str(e)) + + return stats def decode_readme(data: str): @@ -94,12 +212,16 @@ def generate_new_readme(stats: str, readme: str): if __name__ == '__main__': - g = Github(ghtoken) - repo = g.get_repo(f"{user}/{user}") - contents = repo.get_readme() - waka_stats = get_stats() - rdmd = decode_readme(contents.content) - new_readme = generate_new_readme(stats=waka_stats, readme=rdmd) - if new_readme != rdmd: - repo.update_file(path=contents.path, message='Updated with Dev Metrics', - content=new_readme, sha=contents.sha, branch='master') + try: + g = Github(ghtoken) + repo = g.get_repo(f"{user}/{user}") + contents = repo.get_readme() + headers = {"Authorization": "Bearer " + ghtoken} + waka_stats = get_stats() + rdmd = decode_readme(contents.content) + new_readme = generate_new_readme(stats=waka_stats, readme=rdmd) + if new_readme != rdmd: + repo.update_file(path=contents.path, message='Updated with Dev Metrics', + content=new_readme, sha=contents.sha, branch='master') + except Exception as e: + print("Exception Occurred" + str(e))