You've already forked wakapi-readme-stats
Verbose logging environmental variable added
This commit is contained in:
@@ -18,5 +18,7 @@ INPUT_SHOW_DAYS_OF_WEEK=True
|
||||
INPUT_SHOW_LANGUAGE_PER_REPO=True
|
||||
INPUT_SHOW_UPDATED_DATE=True
|
||||
INPUT_UPDATED_DATE_FORMAT=%d/%m/%Y %H:%M:%S
|
||||
INPUT_COMMIT_BY_ME=False
|
||||
INPUT_COMMIT_BY_ME=True
|
||||
INPUT_COMMIT_MESSAGE=Updated with Dev Metrics
|
||||
INPUT_DEBUG_LOGGING=True
|
||||
DEBUG_RUN=True
|
||||
|
||||
@@ -260,6 +260,8 @@ CSS 2 repos █░░░░░░░░░░░░░░░░
|
||||
| 2 | ⣿ | ⣀ |
|
||||
| 3 | ⬛ | ⬜ |
|
||||
|
||||
`DEBUG_LOGGING` flag can be set to increase action output verbosity, by default equals internal runner debug property
|
||||
|
||||
**Timeline**
|
||||
|
||||

|
||||
|
||||
@@ -132,6 +132,11 @@ inputs:
|
||||
description: "Version of the symbol block and empty of the progress bar"
|
||||
default: "1"
|
||||
|
||||
DEBUG_LOGGING:
|
||||
required: false
|
||||
description: "Whether to enable action debug logging"
|
||||
default: ${{ runner.debug }}
|
||||
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'docker://wakareadmestats/waka-readme-stats:master'
|
||||
|
||||
@@ -5,12 +5,13 @@ from asyncio import run
|
||||
from datetime import datetime
|
||||
from urllib.parse import quote
|
||||
|
||||
from humanize import intword, naturalsize, intcomma, precisedelta
|
||||
from humanize import intword, naturalsize, intcomma
|
||||
|
||||
from manager_download import init_download_manager, DownloadManager as DM
|
||||
from manager_environment import EnvironmentManager as EM
|
||||
from manager_github import init_github_manager, GitHubManager as GHM
|
||||
from manager_localization import init_localization_manager, LocalizationManager as LM
|
||||
from manager_debug import init_debug_manager, DebugManager as DBM
|
||||
from graphics_chart_drawer import create_loc_graph, GRAPH_PATH
|
||||
from yearly_commit_calculator import calculate_yearly_commit_data
|
||||
from graphics_list_formatter import make_list, make_commit_day_time_list, make_language_per_repo_list
|
||||
@@ -23,10 +24,12 @@ async def get_waka_time_stats() -> str:
|
||||
|
||||
:returns: String representation of the info.
|
||||
"""
|
||||
DBM.i("Adding short WakaTime stats...")
|
||||
stats = str()
|
||||
|
||||
data = await DM.get_remote_json("waka_latest")
|
||||
if EM.SHOW_COMMIT:
|
||||
DBM.i("Adding user commit day time info...")
|
||||
stats += f"{await make_commit_day_time_list(data['data']['timezone'])}\n\n"
|
||||
|
||||
if EM.SHOW_TIMEZONE or EM.SHOW_LANGUAGE or EM.SHOW_EDITORS or EM.SHOW_PROJECTS or EM.SHOW_OS:
|
||||
@@ -34,27 +37,33 @@ async def get_waka_time_stats() -> str:
|
||||
stats += f"📊 **{LM.t('This Week I Spend My Time On')}** \n\n```text\n"
|
||||
|
||||
if EM.SHOW_TIMEZONE:
|
||||
DBM.i("Adding user timezone info...")
|
||||
time_zone = data["data"]["timezone"]
|
||||
stats += f"🕑︎ {LM.t('Timezone')}: {time_zone}\n\n"
|
||||
|
||||
if EM.SHOW_LANGUAGE:
|
||||
DBM.i("Adding user top languages info...")
|
||||
lang_list = no_activity if len(data["data"]["languages"]) == 0 else make_list(data["data"]["languages"])
|
||||
stats += f"💬 {LM.t('Languages')}: \n{lang_list}\n\n"
|
||||
|
||||
if EM.SHOW_EDITORS:
|
||||
DBM.i("Adding user editors info...")
|
||||
edit_list = no_activity if len(data["data"]["editors"]) == 0 else make_list(data["data"]["editors"])
|
||||
stats += f"🔥 {LM.t('Editors')}: \n{edit_list}\n\n"
|
||||
|
||||
if EM.SHOW_PROJECTS:
|
||||
DBM.i("Adding user projects info...")
|
||||
project_list = no_activity if len(data["data"]["projects"]) == 0 else make_list(data["data"]["projects"])
|
||||
stats += f"🐱💻 {LM.t('Projects')}: \n{project_list}\n\n"
|
||||
|
||||
if EM.SHOW_OS:
|
||||
DBM.i("Adding user operating systems info...")
|
||||
os_list = no_activity if len(data["data"]["operating_systems"]) == 0 else make_list(data["data"]["operating_systems"])
|
||||
stats += f"💻 {LM.t('operating system')}: \n{os_list}\n\n"
|
||||
|
||||
stats = f"{stats[:-1]}```\n\n"
|
||||
|
||||
DBM.g("WakaTime stats added!")
|
||||
return stats
|
||||
|
||||
|
||||
@@ -65,38 +74,47 @@ async def get_short_github_info() -> str:
|
||||
|
||||
:returns: String representation of the info.
|
||||
"""
|
||||
DBM.i("Adding short GitHub info...")
|
||||
stats = f"**🐱 {LM.t('My GitHub Data')}** \n\n"
|
||||
|
||||
DBM.i("Adding user disk usage info...")
|
||||
if GHM.USER.disk_usage is None:
|
||||
disk_usage = LM.t("Used in GitHub's Storage") % "?"
|
||||
print("Please add new github personal access token with user permission!")
|
||||
DBM.w("Please add new github personal access token with user permission!")
|
||||
else:
|
||||
disk_usage = LM.t("Used in GitHub's Storage") % naturalsize(GHM.USER.disk_usage)
|
||||
stats += f"> 📦 {disk_usage} \n > \n"
|
||||
|
||||
data = await DM.get_remote_json("github_stats")
|
||||
DBM.i("Adding contributions info...")
|
||||
if len(data["years"]) > 0:
|
||||
contributions = LM.t("Contributions in the year") % (intcomma(data["years"][0]["total"]), data["years"][0]["year"])
|
||||
stats += f"> 🏆 {contributions}\n > \n"
|
||||
else:
|
||||
DBM.w("GitHub contributions data unavailable!")
|
||||
|
||||
DBM.i("Adding opted for hire info...")
|
||||
opted_to_hire = GHM.USER.hireable
|
||||
if opted_to_hire:
|
||||
stats += f"> 💼 {LM.t('Opted to Hire')}\n > \n"
|
||||
else:
|
||||
stats += f"> 🚫 {LM.t('Not Opted to Hire')}\n > \n"
|
||||
|
||||
DBM.i("Adding public repositories info...")
|
||||
public_repo = GHM.USER.public_repos
|
||||
if public_repo != 1:
|
||||
stats += f"> 📜 {LM.t('public repositories') % public_repo} \n > \n"
|
||||
else:
|
||||
stats += f"> 📜 {LM.t('public repository') % public_repo} \n > \n"
|
||||
|
||||
DBM.i("Adding private repositories info...")
|
||||
private_repo = GHM.USER.owned_private_repos if GHM.USER.owned_private_repos is not None else 0
|
||||
if public_repo != 1:
|
||||
stats += f"> 🔑 {LM.t('private repositories') % private_repo} \n > \n"
|
||||
else:
|
||||
stats += f"> 🔑 {LM.t('private repository') % private_repo} \n > \n"
|
||||
|
||||
DBM.g("Short GitHub info added!")
|
||||
return stats
|
||||
|
||||
|
||||
@@ -107,6 +125,8 @@ async def get_stats() -> str:
|
||||
|
||||
:returns: String representation of README.md contents.
|
||||
"""
|
||||
DBM.i("Collecting stats for README...")
|
||||
|
||||
stats = str()
|
||||
repositories = await DM.get_remote_graphql("user_repository_list", username=GHM.USER.login, id=GHM.USER.node_id)
|
||||
|
||||
@@ -114,16 +134,20 @@ async def get_stats() -> str:
|
||||
yearly_data = await calculate_yearly_commit_data(repositories)
|
||||
else:
|
||||
yearly_data = (None, dict())
|
||||
DBM.w("User yearly data not needed, skipped.")
|
||||
|
||||
if EM.SHOW_TOTAL_CODE_TIME:
|
||||
DBM.i("Adding total code time info...")
|
||||
data = await DM.get_remote_json("waka_all")
|
||||
stats += f"}-{quote(str(data['data']['text']))}-blue)\n\n"
|
||||
|
||||
if EM.SHOW_PROFILE_VIEWS:
|
||||
DBM.i("Adding profile views info...")
|
||||
data = GHM.REPO.get_views_traffic(per="week")
|
||||
stats += f")}-{data['count']}-blue)\n\n"
|
||||
|
||||
if EM.SHOW_LINES_OF_CODE:
|
||||
DBM.i("Adding lines of code info...")
|
||||
total_loc = sum([yearly_data[y][q][d] for y in yearly_data.keys() for q in yearly_data[y].keys() for d in yearly_data[y][q].keys()])
|
||||
data = f"{intword(total_loc)} {LM.t('Lines of code')}"
|
||||
stats += f")}-{quote(data)}-blue)\n\n"
|
||||
@@ -134,6 +158,7 @@ async def get_stats() -> str:
|
||||
stats += await get_waka_time_stats()
|
||||
|
||||
if EM.SHOW_LANGUAGE_PER_REPO:
|
||||
DBM.i("Adding language per repository info...")
|
||||
stats += f"{make_language_per_repo_list(repositories)}\n\n"
|
||||
|
||||
if EM.SHOW_LOC_CHART:
|
||||
@@ -143,8 +168,10 @@ async def get_stats() -> str:
|
||||
stats += f"**{LM.t('Timeline')}**\n\n\n\n"
|
||||
|
||||
if EM.SHOW_UPDATED_DATE:
|
||||
DBM.i("Adding last updated time...")
|
||||
stats += f"\n Last Updated on {datetime.now().strftime(EM.UPDATED_DATE_FORMAT)} UTC"
|
||||
|
||||
DBM.g("Stats for README collected!")
|
||||
return stats
|
||||
|
||||
|
||||
@@ -156,14 +183,18 @@ async def main():
|
||||
init_github_manager()
|
||||
await init_download_manager()
|
||||
init_localization_manager()
|
||||
DBM.i("Managers initialized.")
|
||||
|
||||
if GHM.update_readme(await get_stats()):
|
||||
print("Readme updated!")
|
||||
DBM.g("Readme updated!")
|
||||
await DM.close_remote_resources()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
init_debug_manager()
|
||||
start_time = datetime.now()
|
||||
DBM.g("Program execution started at $date.", date=start_time)
|
||||
run(main())
|
||||
run_delta = datetime.now() - start_time
|
||||
print(f"Program processed in {precisedelta(run_delta, minimum_unit='microseconds')}.")
|
||||
end_time = datetime.now()
|
||||
DBM.g("Program execution finished at $date.", date=end_time)
|
||||
DBM.p("Program processed in $time.", time=end_time - start_time)
|
||||
|
||||
65
sources/manager_debug.py
Normal file
65
sources/manager_debug.py
Normal file
@@ -0,0 +1,65 @@
|
||||
from datetime import datetime
|
||||
from logging import getLogger, Logger, StreamHandler
|
||||
from string import Template
|
||||
from typing import Dict
|
||||
|
||||
from humanize import precisedelta
|
||||
|
||||
from manager_environment import EnvironmentManager as EM
|
||||
|
||||
|
||||
def init_debug_manager():
|
||||
"""
|
||||
Initialize download manager:
|
||||
- Setup headers for GitHub GraphQL requests.
|
||||
- Launch static queries in background.
|
||||
"""
|
||||
DebugManager.create_logger("DEBUG" if EM.DEBUG_LOGGING else "ERROR")
|
||||
|
||||
|
||||
class DebugManager:
|
||||
_COLOR_RESET = "\u001B[0m"
|
||||
_COLOR_RED = "\u001B[31m"
|
||||
_COLOR_GREEN = "\u001B[32m"
|
||||
_COLOR_BLUE = "\u001B[34m"
|
||||
_COLOR_YELLOW = "\u001B[33m"
|
||||
|
||||
_DATE_TEMPLATE = "date"
|
||||
_TIME_TEMPLATE = "time"
|
||||
|
||||
_logger: Logger
|
||||
|
||||
@staticmethod
|
||||
def create_logger(level: str):
|
||||
DebugManager._logger = getLogger(__name__)
|
||||
DebugManager._logger.setLevel(level)
|
||||
DebugManager._logger.addHandler(StreamHandler())
|
||||
|
||||
@staticmethod
|
||||
def _process_template(message: str, kwargs: Dict) -> str:
|
||||
if DebugManager._DATE_TEMPLATE in kwargs:
|
||||
kwargs[DebugManager._DATE_TEMPLATE] = f"{datetime.strftime(kwargs[DebugManager._DATE_TEMPLATE], '%d-%m-%Y %H:%M:%S:%f')}"
|
||||
if DebugManager._TIME_TEMPLATE in kwargs:
|
||||
kwargs[DebugManager._TIME_TEMPLATE] = precisedelta(kwargs[DebugManager._TIME_TEMPLATE], minimum_unit="microseconds")
|
||||
|
||||
return Template(message).substitute(kwargs)
|
||||
|
||||
@staticmethod
|
||||
def g(message: str, **kwargs):
|
||||
message = DebugManager._process_template(message, kwargs)
|
||||
DebugManager._logger.info(f"{DebugManager._COLOR_GREEN}{message}{DebugManager._COLOR_RESET}")
|
||||
|
||||
@staticmethod
|
||||
def i(message: str, **kwargs):
|
||||
message = DebugManager._process_template(message, kwargs)
|
||||
DebugManager._logger.debug(f"{DebugManager._COLOR_BLUE}{message}{DebugManager._COLOR_RESET}")
|
||||
|
||||
@staticmethod
|
||||
def w(message: str, **kwargs):
|
||||
message = DebugManager._process_template(message, kwargs)
|
||||
DebugManager._logger.warning(f"{DebugManager._COLOR_YELLOW}{message}{DebugManager._COLOR_RESET}")
|
||||
|
||||
@staticmethod
|
||||
def p(message: str, **kwargs):
|
||||
message = DebugManager._process_template(message, kwargs)
|
||||
DebugManager._logger.error(message)
|
||||
@@ -9,6 +9,7 @@ from yaml import safe_load
|
||||
|
||||
from manager_environment import EnvironmentManager as EM
|
||||
from manager_github import GitHubManager as GHM
|
||||
from manager_debug import DebugManager as DBM
|
||||
|
||||
|
||||
GITHUB_API_QUERIES = {
|
||||
@@ -188,9 +189,14 @@ class DownloadManager:
|
||||
By default `response.json()` is used.
|
||||
:return: Response dictionary.
|
||||
"""
|
||||
DBM.i(f"\tMaking a remote API query named '{resource}'...")
|
||||
if isinstance(DownloadManager._REMOTE_RESOURCES_CACHE[resource], Awaitable):
|
||||
res = await DownloadManager._REMOTE_RESOURCES_CACHE[resource]
|
||||
DownloadManager._REMOTE_RESOURCES_CACHE[resource] = res
|
||||
DBM.g(f"\tQuery '{resource}' finished, result saved!")
|
||||
else:
|
||||
res = DownloadManager._REMOTE_RESOURCES_CACHE[resource]
|
||||
DBM.g(f"\tQuery '{resource}' loaded from cache!")
|
||||
if res.status_code == 200:
|
||||
if convertor is None:
|
||||
return res.json()
|
||||
|
||||
@@ -43,3 +43,6 @@ class EnvironmentManager:
|
||||
UPDATED_DATE_FORMAT = getenv("INPUT_UPDATED_DATE_FORMAT", "%d/%m/%Y %H:%M:%S")
|
||||
IGNORED_REPOS = getenv("INPUT_IGNORED_REPOS", "").replace(" ", "").split(",")
|
||||
SYMBOL_VERSION = int(getenv("INPUT_SYMBOL_VERSION"))
|
||||
|
||||
DEBUG_LOGGING = getenv("INPUT_DEBUG_LOGGING", "0").lower() in _TRUTHY
|
||||
DEBUG_RUN = getenv("DEBUG_RUN", "False").lower() in _TRUTHY
|
||||
|
||||
@@ -4,6 +4,7 @@ from re import sub
|
||||
from github import Github, AuthenticatedUser, Repository, ContentFile, InputGitAuthor, UnknownObjectException
|
||||
|
||||
from manager_environment import EnvironmentManager as EM
|
||||
from manager_debug import DebugManager as DBM
|
||||
|
||||
|
||||
def init_github_manager():
|
||||
@@ -12,7 +13,7 @@ def init_github_manager():
|
||||
Current user, user readme repo and readme file are downloaded.
|
||||
"""
|
||||
GitHubManager.prepare_github_env()
|
||||
print(f"Current user: {GitHubManager.USER.login}")
|
||||
DBM.i(f"Current user: {GitHubManager.USER.login}")
|
||||
|
||||
|
||||
class GitHubManager:
|
||||
@@ -82,6 +83,7 @@ class GitHubManager:
|
||||
|
||||
:returns: whether the README.md file was updated or not.
|
||||
"""
|
||||
DBM.i("Updating README...")
|
||||
new_readme = GitHubManager._generate_new_readme(stats)
|
||||
if new_readme != GitHubManager._README_CONTENTS:
|
||||
GitHubManager.REPO.update_file(
|
||||
@@ -92,8 +94,10 @@ class GitHubManager:
|
||||
branch=GitHubManager.branch(),
|
||||
committer=GitHubManager._get_author(),
|
||||
)
|
||||
DBM.g("README updated!")
|
||||
return True
|
||||
else:
|
||||
DBM.w("README update not needed!")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
@@ -104,10 +108,13 @@ class GitHubManager:
|
||||
|
||||
:param chart_path: path to saved lines of code chart.
|
||||
"""
|
||||
DBM.i("Updating lines of code chart...")
|
||||
with open(chart_path, "rb") as input_file:
|
||||
data = input_file.read()
|
||||
try:
|
||||
contents = GitHubManager.REPO.get_contents(chart_path)
|
||||
GitHubManager.REPO.update_file(contents.path, "Charts Updated", data, contents.sha, committer=GitHubManager._get_author())
|
||||
DBM.g("Lines of code chart updated!")
|
||||
except UnknownObjectException:
|
||||
GitHubManager.REPO.create_file(chart_path, "Charts Added", data, committer=GitHubManager._get_author())
|
||||
DBM.g("Lines of code chart created!")
|
||||
|
||||
@@ -5,6 +5,7 @@ from typing import Dict
|
||||
from manager_download import DownloadManager as DM
|
||||
from manager_environment import EnvironmentManager as EM
|
||||
from manager_github import GitHubManager as GHM
|
||||
from manager_debug import DebugManager as DBM
|
||||
|
||||
|
||||
async def calculate_yearly_commit_data(repositories: Dict) -> Dict:
|
||||
@@ -15,12 +16,14 @@ async def calculate_yearly_commit_data(repositories: Dict) -> Dict:
|
||||
:param repositories: user repositories info dictionary.
|
||||
:returns: Commit quarter yearly data dictionary.
|
||||
"""
|
||||
DBM.i("Calculating yearly commit data...")
|
||||
yearly_data = dict()
|
||||
total = len(repositories["data"]["user"]["repositories"]["nodes"])
|
||||
for ind, repo in enumerate(repositories["data"]["user"]["repositories"]["nodes"]):
|
||||
if repo["name"] not in EM.IGNORED_REPOS:
|
||||
print(f"{ind + 1}/{total}", "Retrieving repo:", repo["owner"]["login"], repo["name"])
|
||||
DBM.i(f"\t{ind + 1}/{total} Retrieving repo: {repo['owner']['login']}/{repo['name']}")
|
||||
await update_yearly_data_with_commit_stats(repo, yearly_data)
|
||||
DBM.g("Yearly commit data calculated!")
|
||||
return yearly_data
|
||||
|
||||
|
||||
@@ -35,7 +38,7 @@ async def update_yearly_data_with_commit_stats(repo_details: Dict, yearly_data:
|
||||
owner = repo_details["owner"]["login"]
|
||||
branch_data = await DM.get_remote_graphql("repo_branch_list", owner=owner, name=repo_details["name"])
|
||||
if branch_data["data"]["repository"] is None:
|
||||
print(f"\tSkipping repo: {repo_details['name']}")
|
||||
DBM.w(f"\t\tSkipping repo: {repo_details['name']}")
|
||||
return dict()
|
||||
|
||||
for branch in branch_data["data"]["repository"]["refs"]["nodes"]:
|
||||
|
||||
Reference in New Issue
Block a user