Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c0345cb5d9 | |||
| 632b13121d | |||
| 8b0ab3bd76 | |||
| 7a6d95d436 | |||
| fd26197e70 | |||
| 99b6b3f887 | |||
| c2f0b9de48 | |||
| 95c7f84451 | |||
| d1558ad6db | |||
| 76d3c7249a | |||
| 450ba61d22 | |||
| 3d3239a2e3 | |||
| 830c76c07a | |||
| 6125862010 | |||
| b88da2af7d | |||
| b55e75a74d | |||
| 3bc9d82ee4 | |||
| 980f869999 | |||
| 108a90abce | |||
|
|
5dc349128a | ||
|
|
d2e7ba7208 | ||
|
|
2dd14d3fd8 | ||
|
|
e644272268 | ||
|
|
2aab71918a | ||
|
|
3f2f9d748e | ||
|
|
54c3312012 | ||
|
|
dd576f44c6 | ||
|
|
b2363ac606 | ||
|
|
519a95b477 | ||
|
|
ac8e6017f5 |
@@ -17,6 +17,7 @@ INPUT_SHOW_TIME=
|
||||
INPUT_SHOW_TOTAL=
|
||||
INPUT_SHOW_MASKED_TIME=
|
||||
INPUT_STOP_AT_OTHER=
|
||||
INPUT_IGNORED_LANGUAGES=
|
||||
# commit
|
||||
INPUT_COMMIT_MESSAGE=
|
||||
INPUT_TARGET_BRANCH=
|
||||
|
||||
4
.github/workflows/testing.yml
vendored
4
.github/workflows/testing.yml
vendored
@@ -2,9 +2,9 @@ name: WakaReadme CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -107,6 +107,7 @@ poetry.lock
|
||||
# However, this project does not rely on pdm for production.
|
||||
pdm.lock
|
||||
.pdm-python
|
||||
.pdm-build
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
@@ -162,8 +163,9 @@ cython_debug/
|
||||
# VSCode
|
||||
.vscode/
|
||||
|
||||
# asdf
|
||||
# asdf/rtx
|
||||
.tool-versions
|
||||
.rtx.toml
|
||||
|
||||
# ruff
|
||||
.ruff_cache
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contributing
|
||||
|
||||

|
||||

|
||||
|
||||
> First off, thank you! Please follow along.
|
||||
|
||||
@@ -21,6 +21,7 @@ INPUT_TIME_RANGE=last_7_days
|
||||
INPUT_SHOW_MASKED_TIME=false
|
||||
INPUT_LANG_COUNT=0
|
||||
INPUT_STOP_AT_OTHER=true
|
||||
INPUT_IGNORED_LANGUAGES=
|
||||
```
|
||||
|
||||
**NEVER commit this `.env` file!**
|
||||
@@ -32,10 +33,8 @@ INPUT_STOP_AT_OTHER=true
|
||||
> Replace `podman` with `docker` everywhere, if you're using the latter.
|
||||
|
||||
```sh
|
||||
# Build
|
||||
$ podman-compose -p waka-readme -f ./docker-compose.yml up -d
|
||||
# Logs
|
||||
$ podman logs WakaReadmeDev
|
||||
# Build and watch logs
|
||||
$ podman-compose -p waka-readme -f ./docker-compose.yml up
|
||||
# Cleanup
|
||||
$ podman-compose -p waka-readme -f ./docker-compose.yml down
|
||||
```
|
||||
@@ -48,17 +47,18 @@ $ podman-compose -p waka-readme -f ./docker-compose.yml down
|
||||
|
||||
1. Inside the cloned folder run the following commands to install dependencies
|
||||
|
||||
```console
|
||||
```sh
|
||||
$ python -m venv .venv
|
||||
$ . ./.venv/bin/activate
|
||||
$ python -m pip install .
|
||||
# ... install decencies ...
|
||||
```
|
||||
|
||||
to activate virtual environment & install dependencies.
|
||||
|
||||
2. To test or execute the program in development, run:
|
||||
|
||||
```console
|
||||
```sh
|
||||
(.venv)$ python -m unittest discover # run tests
|
||||
(.venv)$ python -m main --dev # execute program in dev mode
|
||||
```
|
||||
|
||||
159
README.md
159
README.md
@@ -1,22 +1,16 @@
|
||||
<center>
|
||||
# Dev Metrics in Readme
|
||||
|
||||

|
||||
fork from [waka-readme](https://github/athul/waka-readme)
|
||||
edit for Gitea use.
|
||||
|
||||
</center>
|
||||
|
||||
# Dev Metrics in Readme [](https://github.com/athul/waka-readme/actions/workflows/testing.yml) 
|
||||
|
||||
[WakaTime](https://wakatime.com) weekly metrics on your profile readme.
|
||||
|
||||

|
||||
|
||||
:speech_balloon: **Forum** | [GitHub discussions][gh_discuss]
|
||||
[WakaTime](https://wakatime.com) coding metrics on your profile readme.
|
||||
|
||||
## New to WakaTime?
|
||||
|
||||
> Nope? Skip to [prep work](#prep-work).
|
||||
> Nope? Skip to [#Prep work](#prep-work).
|
||||
|
||||
WakaTime gives you an idea of the time you spent on coding. This helps you boost your productivity and competitive edge.
|
||||
WakaTime gives you an idea of the time you spent on coding.
|
||||
This helps you boost your productivity and competitive edge (aka _flex_ :muscle:).
|
||||
|
||||
1. Head over to <https://wakatime.com/> and create an account.
|
||||
2. After logging in get your WakaTime API Key from <https://wakatime.com/api-key/>.
|
||||
@@ -24,11 +18,11 @@ WakaTime gives you an idea of the time you spent on coding. This helps you boost
|
||||
4. Paste in your API key to start telemetry.
|
||||
|
||||
:information_source: **Info** | You can read [WakaTime help][waka_help] to know more about configurations.
|
||||
Alternatively, you can also fetch data from WakaTime compatible services like [Wakapi][wakapi] or [Hakatime][hakatime].
|
||||
Alternatively, you can fetch data from WakaTime compatible services such as [Wakapi][wakapi] or [Hakatime][hakatime].
|
||||
|
||||
## Prep Work
|
||||
|
||||
A GitHub repository and a `README.md` file is required. We'll be making use of readme in the [profile repository][profile_readme].
|
||||
A Gitea repository and a `README.md` file is required. We'll be making use of readme in the [profile repository][profile_readme].
|
||||
|
||||
- Save the `README.md` file after copy-pasting the following special comments. Your dev-metics will show up in between.
|
||||
|
||||
@@ -39,44 +33,37 @@ A GitHub repository and a `README.md` file is required. We'll be making use of r
|
||||
|
||||
`<!--START_SECTION: -->` and `<!--END_SECTION: -->` are placeholders and must be retained as is. Whereas "`waka`" can be replaced by any alphanumeric string. See [#Tweaks](#tweaks) section for more.
|
||||
|
||||
- Navigate to your repo's `Settings > Secrets` and add a new secret _named_ `WAKATIME_API_KEY` with your API key as it's _value_.
|
||||
- Navigate to your repo's `Settings`:
|
||||
- Go to `Secrets` (at `https://your_gitea_url/username/.profile/settings/actions/secrets` by replacing the `USERNAME` with your own username) and add a new secret "_Named_" `WAKATIME_API_KEY` with your API key as it's "_Secret_".
|
||||
|
||||
> Or use the url <https://github.com/USERNAME/USERNAME/settings/secrets/actions/new> by replacing the `USERNAME` with your own username.
|
||||
>
|
||||
> ![new_secrets_actions][new_secrets_actions]
|
||||
|
||||
- If you're not using [profile repository][profile_readme], add another secret _named_ `GH_TOKEN` and insert your [GitHub token][gh_access_token]\* in place of _value_.
|
||||
|
||||
- Create a new workflow file (`waka-readme.yml`) inside `.github/workflows/` folder of your repository. You can create it from a template using the _actions tab_ of your repository too.
|
||||
- Clear any existing contents, add the following lines and save the `waka-readme.yml` workflow file.
|
||||
- Create a new workflow file named `waka-readme.yml` inside `.gitea/workflows/` folder of your profile repository.
|
||||
- Clear all existing contents, add following lines and save the file.
|
||||
|
||||
```yml
|
||||
name: Waka Readme
|
||||
|
||||
on:
|
||||
workflow_dispatch: # for manual workflow trigger
|
||||
# for manual workflow trigger
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # runs at every 12AM UTC
|
||||
# runs at 12 AM UTC (5:30 AM IST)
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
update-readme:
|
||||
name: WakaReadme DevMetrics
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: athul/waka-readme@master
|
||||
- uses: https://git.mamahaha.work/sangge/waka-readme@master # this action name
|
||||
with:
|
||||
WAKATIME_API_KEY: ${{ secrets.WAKATIME_API_KEY }}
|
||||
# following flags are required, only if this is not on
|
||||
# profile readme, remove the leading `#` to use them
|
||||
#GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
#REPOSITORY: <gh_username/gh_username>
|
||||
```
|
||||
|
||||
Refer [#Example](#example) section for a full blown workflow file.
|
||||
|
||||
## Tweaks
|
||||
|
||||
There are many flags that you can tweak as you wish!
|
||||
There are many flags that you can modify as you see fit.
|
||||
|
||||
### Meta Tweaks
|
||||
|
||||
@@ -87,18 +74,19 @@ There are many flags that you can tweak as you wish!
|
||||
|
||||
### Content Tweaks
|
||||
|
||||
| Environment flag | Options (`Default`, `Other`, ...) | Description |
|
||||
| ------------------ | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| `SHOW_TITLE` | `false`, `true` | Add title to waka-readme stats blob |
|
||||
| `SECTION_NAME` | `waka`, any alphanumeric string | The generator will look for section name to fill up the readme. |
|
||||
| `BLOCKS` | `░▒▓█`, `⣀⣄⣤⣦⣶⣷⣿`, `-#`, `=>`, you can be creative | Ascii art used to build stats graph |
|
||||
| `CODE_LANG` | `txt`, `python` `ruby` `json` , you can use other languages also | Language syntax based highlighted text |
|
||||
| `TIME_RANGE` | `last_7_days`, `last_30_days`, `last_6_months`, `last_year`, `all_time` | String representing a dispensation from which stats are aggregated |
|
||||
| `LANG_COUNT` | `5`, any plausible number | Number of languages to be displayed |
|
||||
| `SHOW_TIME` | `true`, `false` | Displays the amount of time spent for each language |
|
||||
| `SHOW_TOTAL` | `false`, `true` | Show total coding time |
|
||||
| `SHOW_MASKED_TIME` | `false`, `true` | Adds total coding time including unclassified languages (overrides: `SHOW_TOTAL`) |
|
||||
| `STOP_AT_OTHER` | `false`, `true` | Stop when language marked as `Other` is retrieved (overrides: `LANG_COUNT`) |
|
||||
| Environment flag | Options (`Default`, `Other`, ...) | Description |
|
||||
| ------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
||||
| `SHOW_TITLE` | `false`, `true` | Add title to waka-readme stats blob |
|
||||
| `SECTION_NAME` | `waka`, any alphanumeric string | The generator will look for section name to fill up the readme. |
|
||||
| `BLOCKS` | `░▒▓█`, `⣀⣄⣤⣦⣶⣷⣿`, `-#`, `=>`, you can be creative | Ascii art used to build stats graph |
|
||||
| `CODE_LANG` | `txt`, `python` `ruby` `json` , you can use other languages also | Language syntax based highlighted text |
|
||||
| `TIME_RANGE` | `last_7_days`, `last_30_days`, `last_6_months`, `last_year`, `all_time` | String representing a dispensation from which stats are aggregated |
|
||||
| `LANG_COUNT` | `5`, any plausible number | Number of languages to be displayed |
|
||||
| `SHOW_TIME` | `true`, `false` | Displays the amount of time spent for each language |
|
||||
| `SHOW_TOTAL` | `false`, `true` | Show total coding time |
|
||||
| `SHOW_MASKED_TIME` | `false`, `true` | Adds total coding time including unclassified languages (overrides: `SHOW_TOTAL`) |
|
||||
| `STOP_AT_OTHER` | `false`, `true` | Stop when language marked as `Other` is retrieved (overrides: `LANG_COUNT`) |
|
||||
| `IGNORED_LANGUAGES` | <code> </code>, `Binary YAML JSON TOML` | Hide languages from your stats |
|
||||
|
||||
### Commit Tweaks
|
||||
|
||||
@@ -112,9 +100,9 @@ There are many flags that you can tweak as you wish!
|
||||
| `AUTHOR_NAME` | `NOT_SET`, author name |
|
||||
| `AUTHOR_EMAIL` | `NOT_SET`, author email |
|
||||
|
||||
All of these flags are _optional_.
|
||||
The first option is the _default_ value of the _flag_, subsequent options are valid values available for the _flag_.
|
||||
|
||||
# Example
|
||||
## Example
|
||||
|
||||
**`waka-readme.yml`**
|
||||
|
||||
@@ -122,9 +110,10 @@ All of these flags are _optional_.
|
||||
name: Waka Readme
|
||||
|
||||
on:
|
||||
# for manual workflow trigger
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Runs at 12am UTC
|
||||
# runs at 12 AM UTC (5:30 AM IST)
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
@@ -132,45 +121,42 @@ jobs:
|
||||
name: WakaReadme DevMetrics
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: athul/waka-readme@master
|
||||
# this action name
|
||||
- uses: https://git.mamahaha.work/sangge/waka-readme@master # do NOT replace with anything else
|
||||
with:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
WAKATIME_API_KEY: ${{ secrets.WAKATIME_API_KEY }}
|
||||
# meta
|
||||
API_BASE_URL: https://wakatime.com/api
|
||||
REPOSITORY: athul/athul
|
||||
# content
|
||||
SHOW_TITLE: true
|
||||
SECTION_NAME: waka
|
||||
BLOCKS: ->
|
||||
CODE_LANG: all_time
|
||||
TIME_RANGE: true
|
||||
LANG_COUNT: 10
|
||||
SHOW_TIME: true
|
||||
SHOW_TOTAL: true
|
||||
SHOW_MASKED_TIME: false
|
||||
STOP_AT_OTHER: true
|
||||
# commit
|
||||
COMMIT_MESSAGE: Updated waka-readme graph with new metrics
|
||||
TARGET_BRANCH: master
|
||||
TARGET_PATH: README.md
|
||||
COMMITTER_NAME: GitHubActionBot
|
||||
COMMITTER_EMAIL: action-bot@github.org
|
||||
AUTHOR_NAME: Athul
|
||||
AUTHOR_EMAIL: athul@example.org
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }} # optional if on profile readme
|
||||
WAKATIME_API_KEY: ${{ secrets.WAKATIME_API_KEY }} # required
|
||||
### meta
|
||||
API_BASE_URL: https://wakatime.com/api # optional
|
||||
REPOSITORY: YOUR_GITEA_USERNAME/YOUR_REPOSITORY_NAME # optional
|
||||
### content
|
||||
SHOW_TITLE: true # optional
|
||||
SECTION_NAME: waka # optional
|
||||
BLOCKS: -> # optional
|
||||
CODE_LANG: rust # optional
|
||||
TIME_RANGE: all_time # optional
|
||||
LANG_COUNT: 10 # optional
|
||||
SHOW_TIME: true # optional
|
||||
SHOW_TOTAL: true # optional
|
||||
SHOW_MASKED_TIME: false # optional
|
||||
STOP_AT_OTHER: true # optional
|
||||
IGNORED_LANGUAGES: YAML JSON TOML # optional
|
||||
### commit
|
||||
COMMIT_MESSAGE: Updated waka-readme graph with new metrics # optional
|
||||
TARGET_BRANCH: master # optional
|
||||
TARGET_PATH: README.md # optional
|
||||
COMMITTER_NAME: GitHubActionBot # optional
|
||||
COMMITTER_EMAIL: action-bot@github.com # optional
|
||||
AUTHOR_NAME: YOUR_NAME # optional
|
||||
AUTHOR_EMAIL: YOUR@EMAIL.com # optional
|
||||
# you can populate email-id with secretes instead
|
||||
```
|
||||
|
||||
> Note:
|
||||
>
|
||||
> - Flags `REPOSITORY` and `GH_TOKEN` are required, ONLY if you're NOT using [profile readme][profile_readme].
|
||||
> - `WAKATIME_API_KEY` is a required secret.
|
||||
> - Every other environment variables is optional.
|
||||
> - The above example does not show proper default values, refer [#Tweaks](#tweaks) for the same.
|
||||
_Rendered `markdown`:_
|
||||
|
||||
**`README.md`**
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
```md
|
||||
```rust
|
||||
From: 10 July 2020 - To: 06 August 2022
|
||||
|
||||
Total Time: 1,464 hrs 54 mins
|
||||
@@ -183,6 +169,16 @@ Nim 64 hrs 31 mins >------------------------ 04.11 %
|
||||
Other 47 hrs 58 mins >------------------------ 03.05 %
|
||||
```
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
## Notes
|
||||
|
||||
- Flags `REPOSITORY` and `GH_TOKEN` are required ONLY if, you are NOT using [profile readme][profile_readme].
|
||||
- If you are using `GH_TOKEN`, make sure set the [fine grained token](https://github.com/settings/tokens?type=beta) scope to repository contents with `read-and-write` access. See [#141 (comment)](https://github.com/athul/waka-readme/issues/141#issuecomment-1679831949).
|
||||
- `WAKATIME_API_KEY` is a **required** secret. All other environment variables are optional.
|
||||
- The above example does NOT show proper default values, refer [#Tweaks](#tweaks) for the same.
|
||||
- `IGNORED_LANGUAGES` is suggested for [.NET](https://dotnet.microsoft.com) users, as WakaTime assumes you're working with `Binary`, while debugging.
|
||||
|
||||
## Why only the language stats (and not other data) from the API?
|
||||
|
||||
I am a fan of minimal designs and the profile readme is a great way to show off your skills and interests. The WakaTime API, gets us a **lot of data** about a person's **coding activity including the editors and Operating Systems you used and the projects you worked on**. Some of these projects maybe secretive and should not be shown out to the public. Using up more data via the Wakatime API will clutter the profile readme and hinder your chances on displaying what you provide **value to the community** like the pinned Repositories. I believe that **Coding Stats is nerdiest of all** since you can tell the community that you are **_exercising these languages or learning a new language_**, this will also show that you spend some amount of time to learn and exercise your development skills. That's what matters in the end :heart:
|
||||
@@ -193,6 +189,3 @@ I am a fan of minimal designs and the profile readme is a great way to show off
|
||||
[waka_plugins]: https://wakatime.com/plugins
|
||||
[waka_help]: https://wakatime.com/help/editors
|
||||
[profile_readme]: https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme
|
||||
[new_secrets_actions]: https://user-images.githubusercontent.com/52720626/151221742-bc37d139-2bb3-4554-b27c-46b107d1f408.png
|
||||
[gh_access_token]: https://docs.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token
|
||||
[gh_discuss]: https://github.com/athul/waka-readme/discussions
|
||||
|
||||
@@ -3,7 +3,7 @@ author: "Athul Cyriac Ajay"
|
||||
description: "WakaTime coding activity graph in your profile readme"
|
||||
|
||||
inputs:
|
||||
GH_TOKEN:
|
||||
GITEA_TOKEN:
|
||||
description: "GitHub access token with Repo scope"
|
||||
default: ${{ github.token }}
|
||||
required: true
|
||||
@@ -62,6 +62,10 @@ inputs:
|
||||
description: "Stop data retrieval when language marked 'Other' is reached"
|
||||
default: "false"
|
||||
required: false
|
||||
IGNORED_LANGUAGES:
|
||||
description: "Ignore space separated, listed languages"
|
||||
default: ""
|
||||
required: false
|
||||
|
||||
# commit tweaks
|
||||
COMMIT_MESSAGE:
|
||||
|
||||
@@ -5,7 +5,6 @@ services:
|
||||
- .env.template
|
||||
build:
|
||||
context: .
|
||||
dockerfile: dockerfile
|
||||
dockerfile: containerfile
|
||||
image: waka-readme:testing
|
||||
container_name: WakaReadmeTesting
|
||||
command: python -m unittest discover
|
||||
|
||||
51
containerfile
Normal file
51
containerfile
Normal file
@@ -0,0 +1,51 @@
|
||||
FROM docker.io/python:3-slim
|
||||
|
||||
ENV INPUT_GITEA_TOKEN \
|
||||
INPUT_WAKATIME_API_KEY \
|
||||
# meta
|
||||
INPUT_API_BASE_URL \
|
||||
INPUT_REPOSITORY \
|
||||
# content
|
||||
INPUT_SHOW_TITLE \
|
||||
INPUT_SECTION_NAME \
|
||||
INPUT_BLOCKS \
|
||||
INPUT_CODE_LANG \
|
||||
INPUT_TIME_RANGE \
|
||||
INPUT_LANG_COUNT \
|
||||
INPUT_SHOW_TIME \
|
||||
INPUT_SHOW_TOTAL \
|
||||
INPUT_SHOW_MASKED_TIME \
|
||||
INPUT_STOP_AT_OTHER \
|
||||
INPUT_IGNORED_LANGUAGES \
|
||||
# commit
|
||||
INPUT_COMMIT_MESSAGE \
|
||||
INPUT_TARGET_BRANCH \
|
||||
INPUT_TARGET_PATH \
|
||||
INPUT_COMMITTER_NAME \
|
||||
INPUT_COMMITTER_EMAIL \
|
||||
INPUT_AUTHOR_NAME \
|
||||
INPUT_AUTHOR_EMAIL
|
||||
|
||||
|
||||
ENV PATH="${PATH}:/root/.local/bin" \
|
||||
# python
|
||||
PYTHONFAULTHANDLER=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
PYTHONHASHSEED=random \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
# pip
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
||||
PIP_NO_CACHE_DIR=1 \
|
||||
PIP_DEFAULT_TIMEOUT=100
|
||||
|
||||
# copy project files
|
||||
COPY --chown=root:root pyproject.toml main.py /app/
|
||||
|
||||
# install dependencies
|
||||
RUN python -m pip install /app/ -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
|
||||
# copy tests
|
||||
COPY --chown=root:root tests /app/tests/
|
||||
|
||||
# run tests
|
||||
CMD python -m unittest discover /app/
|
||||
@@ -16,6 +16,7 @@ ENV INPUT_GH_TOKEN \
|
||||
INPUT_SHOW_TOTAL \
|
||||
INPUT_SHOW_MASKED_TIME \
|
||||
INPUT_STOP_AT_OTHER \
|
||||
INPUT_IGNORED_LANGUAGES \
|
||||
# commit
|
||||
INPUT_COMMIT_MESSAGE \
|
||||
INPUT_TARGET_BRANCH \
|
||||
@@ -41,7 +42,7 @@ ENV PATH="${PATH}:/root/.local/bin" \
|
||||
COPY --chown=root:root pyproject.toml main.py /app/
|
||||
|
||||
# install dependencies
|
||||
RUN python -m pip install /app/
|
||||
RUN python -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
|
||||
# execute program
|
||||
CMD python /app/main.py
|
||||
|
||||
153
main.py
153
main.py
@@ -28,28 +28,28 @@ Contents := Title + Byline + Body
|
||||
"""
|
||||
|
||||
# standard
|
||||
from base64 import b64encode, b64decode
|
||||
from dataclasses import dataclass
|
||||
from random import SystemRandom
|
||||
from functools import partial
|
||||
from datetime import datetime
|
||||
from base64 import b64encode
|
||||
from functools import partial
|
||||
import logging as logger
|
||||
import os
|
||||
from random import SystemRandom
|
||||
import re
|
||||
import sys
|
||||
from time import sleep
|
||||
from typing import Any
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
|
||||
# external
|
||||
from github import ContentFile, Github, GithubException, InputGitAuthor, Repository
|
||||
from requests.exceptions import RequestException
|
||||
from requests import get as rq_get
|
||||
from faker import Faker
|
||||
|
||||
# from github import ContentFile, Github, GithubException, InputGitAuthor, Repository
|
||||
from gitea import *
|
||||
from requests import get as rq_get
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
################### setup ###################
|
||||
|
||||
|
||||
print()
|
||||
# hush existing loggers
|
||||
for lgr_name in logger.root.manager.loggerDict:
|
||||
@@ -71,8 +71,12 @@ try:
|
||||
# comment this out to disable colored logging
|
||||
from loguru import logger
|
||||
|
||||
logger.debug("loguru loaded")
|
||||
|
||||
# load from .env before class def gets parsed
|
||||
load_dotenv()
|
||||
logger.debug("dotenv loaded")
|
||||
waka_key: str | None = os.getenv("INPUT_WAKATIME_API_KEY")
|
||||
except ImportError as im_err:
|
||||
logger.warning(im_err)
|
||||
|
||||
@@ -128,7 +132,8 @@ class WakaInput:
|
||||
|
||||
# mapped environment variables
|
||||
# # required
|
||||
gh_token: str | None = os.getenv("INPUT_GH_TOKEN")
|
||||
gitea_token: str | None = os.getenv("INPUT_GITEA_TOKEN")
|
||||
gitea_url: str | None = os.getenv("GITHUB_SERVER_URL", "https://gitea.com")
|
||||
waka_key: str | None = os.getenv("INPUT_WAKATIME_API_KEY")
|
||||
api_base_url: str | None = os.getenv("INPUT_API_BASE_URL", "https://wakatime.com/api")
|
||||
repository: str | None = os.getenv("INPUT_REPOSITORY")
|
||||
@@ -150,6 +155,7 @@ class WakaInput:
|
||||
show_masked_time: str | bool = os.getenv("INPUT_SHOW_MASKED_TIME") or False
|
||||
language_count: str | int = os.getenv("INPUT_LANG_COUNT") or 5
|
||||
stop_at_other: str | bool = os.getenv("INPUT_STOP_AT_OTHER") or False
|
||||
ignored_languages: str = os.getenv("INPUT_IGNORED_LANGUAGES", "")
|
||||
# # optional meta
|
||||
target_branch: str = os.getenv("INPUT_TARGET_BRANCH", "NOT_SET")
|
||||
target_path: str = os.getenv("INPUT_TARGET_PATH", "NOT_SET")
|
||||
@@ -161,7 +167,12 @@ class WakaInput:
|
||||
def validate_input(self):
|
||||
"""Validate Input Env Variables."""
|
||||
logger.debug("Validating input variables")
|
||||
if not self.gh_token or not self.waka_key or not self.api_base_url or not self.repository:
|
||||
if (
|
||||
not self.gitea_token
|
||||
or not self.waka_key
|
||||
or not self.api_base_url
|
||||
or not self.repository
|
||||
):
|
||||
logger.error("Invalid inputs")
|
||||
logger.info("Refer https://github.com/athul/waka-readme")
|
||||
return False
|
||||
@@ -271,7 +282,7 @@ def make_graph(block_style: str, percent: float, gr_len: int, lg_nm: str = "", /
|
||||
return graph_bar
|
||||
|
||||
|
||||
def prep_content(stats: dict[str, Any], language_count: int = 5, stop_at_other: bool = False, /):
|
||||
def prep_content(stats: dict[str, Any], /):
|
||||
"""WakaReadme Prepare Markdown.
|
||||
|
||||
Prepared markdown content from the fetched statistics.
|
||||
@@ -307,17 +318,19 @@ def prep_content(stats: dict[str, Any], language_count: int = 5, stop_at_other:
|
||||
max((str(lng["name"]) for lng in lang_info), key=len)
|
||||
# and then do not for get to set `pad_len` to say 13 :)
|
||||
)
|
||||
if language_count == 0 and not stop_at_other:
|
||||
language_count, stop_at_other = int(wk_i.language_count), bool(wk_i.stop_at_other)
|
||||
if language_count == 0 and not wk_i.stop_at_other:
|
||||
logger.debug(
|
||||
"Set INPUT_LANG_COUNT to -1 to retrieve all language"
|
||||
+ " or specify a positive number (ie. above 0)"
|
||||
)
|
||||
return contents.rstrip("\n")
|
||||
|
||||
ignored_languages = set[str](igl.lower() for igl in wk_i.ignored_languages.strip().split())
|
||||
for idx, lang in enumerate(lang_info):
|
||||
lang_name = str(lang["name"])
|
||||
# >>> add languages to filter here <<<
|
||||
# if lang_name in {...}: continue
|
||||
if ignored_languages and lang_name.lower() in ignored_languages:
|
||||
continue
|
||||
lang_time = str(lang["text"]) if wk_i.show_time else ""
|
||||
lang_ratio = float(lang["percent"])
|
||||
lang_bar = make_graph(wk_i.block_style, lang_ratio, wk_i.graph_length, lang_name)
|
||||
@@ -394,9 +407,7 @@ def churn(old_readme: str, /):
|
||||
sys.exit(1)
|
||||
# preparing contents
|
||||
try:
|
||||
generated_content = prep_content(
|
||||
waka_stats, int(wk_i.language_count), bool(wk_i.stop_at_other)
|
||||
)
|
||||
generated_content = prep_content(waka_stats)
|
||||
except (AttributeError, KeyError, ValueError) as err:
|
||||
logger.error(f"Unable to read API data | {err}\n")
|
||||
sys.exit(1)
|
||||
@@ -407,54 +418,63 @@ def churn(old_readme: str, /):
|
||||
repl=f"{wk_i.start_comment}\n\n```{wk_i.code_lang}\n{generated_content}\n```\n\n{wk_i.end_comment}",
|
||||
string=old_readme,
|
||||
)
|
||||
logger.debug(new_readme)
|
||||
if len(sys.argv) == 2 and sys.argv[1] == "--dev":
|
||||
logger.debug("Detected run in `dev` mode.")
|
||||
# to avoid accidentally writing back to Github
|
||||
# when developing or testing waka-readme
|
||||
return None
|
||||
|
||||
return None if new_readme == old_readme else new_readme
|
||||
|
||||
|
||||
def qualify_target(gh_repo: Repository.Repository):
|
||||
# def qualify_target(gitea_repo: Repository.Repository):
|
||||
def qualify_target(gitea_repo: Repository, gitea_connect: Gitea):
|
||||
"""Qualify target repository defaults."""
|
||||
|
||||
@dataclass
|
||||
class TargetRepository:
|
||||
this: ContentFile.ContentFile
|
||||
# this: ContentFile.ContentFile
|
||||
this: Content
|
||||
path: str
|
||||
commit_message: str
|
||||
sha: str
|
||||
branch: str
|
||||
committer: InputGitAuthor | None
|
||||
author: InputGitAuthor | None
|
||||
# committer: InputGitAuthor | None
|
||||
# author: InputGitAuthor | None
|
||||
committer: None
|
||||
author: None
|
||||
|
||||
gh_branch = gh_repo.default_branch
|
||||
if wk_i.target_branch != "NOT_SET":
|
||||
gh_branch = gh_repo.get_branch(wk_i.target_branch)
|
||||
gitea_branch = gitea_repo.get_branches()[0].name
|
||||
# if wk_i.target_branch != "NOT_SET":
|
||||
# gitea_branch = gitea_repo.get_branch(wk_i.target_branch)
|
||||
|
||||
target = gh_repo.get_readme()
|
||||
if wk_i.target_path != "NOT_SET":
|
||||
target = gh_repo.get_contents(
|
||||
path=wk_i.target_path,
|
||||
ref=gh_branch if isinstance(gh_branch, str) else gh_branch.commit.sha,
|
||||
)
|
||||
readme_content = Content(gitea_connect)
|
||||
readme_content.path = "README.md"
|
||||
readme_content.type = Content.FILE
|
||||
target = gitea_repo.get_file_content(readme_content) # base64 encoded
|
||||
# target = gitea_repo.get_readme()
|
||||
|
||||
# if wk_i.target_path != "NOT_SET":
|
||||
# target = gitea_repo.get_contents(
|
||||
# path=wk_i.target_path,
|
||||
# ref=gitea_branch if isinstance(gitea_branch, str) else gitea_branch.commit.sha,
|
||||
# )
|
||||
if isinstance(target, list):
|
||||
raise RuntimeError("Cannot handle multiple files.")
|
||||
|
||||
committer, author = None, None
|
||||
if wk_i.committer_name != "NOT_SET" and wk_i.committer_email != "NOT_SET":
|
||||
committer = InputGitAuthor(name=wk_i.committer_name, email=wk_i.committer_email)
|
||||
if wk_i.author_name != "NOT_SET" and wk_i.author_email != "NOT_SET":
|
||||
author = InputGitAuthor(name=wk_i.author_name, email=wk_i.author_email)
|
||||
# if wk_i.committer_name != "NOT_SET" and wk_i.committer_email != "NOT_SET":
|
||||
# committer = InputGitAuthor(name=wk_i.committer_name, email=wk_i.committer_email)
|
||||
# if wk_i.author_name != "NOT_SET" and wk_i.author_email != "NOT_SET":
|
||||
# author = InputGitAuthor(name=wk_i.author_name, email=wk_i.author_email)
|
||||
sha = ""
|
||||
|
||||
return TargetRepository(
|
||||
this=target,
|
||||
path=target.path,
|
||||
path="README.md",
|
||||
commit_message=wk_i.commit_message,
|
||||
sha=target.sha,
|
||||
branch=gh_branch if isinstance(gh_branch, str) else gh_branch.name,
|
||||
sha=sha,
|
||||
branch=gitea_branch if isinstance(gitea_branch, str) else gitea_branch.name,
|
||||
committer=committer,
|
||||
author=author,
|
||||
)
|
||||
@@ -462,34 +482,45 @@ def qualify_target(gh_repo: Repository.Repository):
|
||||
|
||||
def genesis():
|
||||
"""Run Program."""
|
||||
logger.debug("Connecting to GitHub")
|
||||
gh_connect = Github(wk_i.gh_token)
|
||||
logger.debug("Connecting to Gitea")
|
||||
gitea_connect = Gitea(wk_i.gitea_url, wk_i.gitea_token)
|
||||
|
||||
# since a validator is being used earlier, casting
|
||||
# `wk_i.ENV_VARIABLE` to a string here, is okay
|
||||
gh_repo = gh_connect.get_repo(str(wk_i.repository))
|
||||
target = qualify_target(gh_repo)
|
||||
# gitea_repo = gitea_connect.get_repo(str(wk_i.repository))
|
||||
owner = "sangge"
|
||||
repo_name = ".profile"
|
||||
gitea_repo = Repository.request(gitea_connect, owner, repo_name)
|
||||
target = qualify_target(gitea_repo, gitea_connect)
|
||||
logger.debug("Decoding readme contents\n")
|
||||
|
||||
readme_contents = str(target.this.decoded_content, encoding="utf-8")
|
||||
readme_contents = str(b64decode(target.this), encoding="utf-8")
|
||||
if not (new_content := churn(readme_contents)):
|
||||
logger.info("WakaReadme was not updated")
|
||||
return
|
||||
|
||||
logger.debug("WakaReadme stats has changed")
|
||||
update_metric = partial(
|
||||
gh_repo.update_file,
|
||||
path=target.path,
|
||||
message=target.commit_message,
|
||||
content=new_content,
|
||||
sha=target.sha,
|
||||
branch=target.branch,
|
||||
)
|
||||
if target.committer:
|
||||
update_metric = partial(update_metric, committer=target.committer)
|
||||
if target.author:
|
||||
update_metric = partial(update_metric, author=target.author)
|
||||
update_metric()
|
||||
# update_metric = partial(
|
||||
# gitea_repo.update_file,
|
||||
# path=target.path,
|
||||
# message=target.commit_message,
|
||||
# content=new_content,
|
||||
# sha=target.sha,
|
||||
# branch=target.branch,
|
||||
# )
|
||||
# if target.committer:
|
||||
# update_metric = partial(update_metric, committer=target.committer)
|
||||
# if target.author:
|
||||
# update_metric = partial(update_metric, author=target.author)
|
||||
# update_metric()
|
||||
b64_new_content = b64encode(bytes(new_content, "utf-8"))
|
||||
repo_content = gitea_repo.get_git_content()
|
||||
readmes = [c for c in repo_content if c.name == "README.md"]
|
||||
sha = readmes[0].sha
|
||||
str_new_content = b64_new_content.decode("utf-8")
|
||||
gitea_repo.change_file(readmes[0].name, readmes[0].sha, str_new_content)
|
||||
logger.info("Stats updated successfully")
|
||||
return
|
||||
|
||||
|
||||
################### driver ###################
|
||||
@@ -518,7 +549,7 @@ if __name__ == "__main__":
|
||||
except RuntimeError as err:
|
||||
logger.error(f"{type(err).__name__}: {err}\n")
|
||||
sys.exit(1)
|
||||
except (GithubException, RequestException) as rq_exp:
|
||||
logger.critical(f"{rq_exp}\n")
|
||||
sys.exit(1)
|
||||
# except (GithubException, RequestException) as rq_exp:
|
||||
# logger.critical(f"{rq_exp}\n")
|
||||
# sys.exit(1)
|
||||
print("\nThanks for using WakaReadme!\n")
|
||||
|
||||
@@ -4,20 +4,19 @@
|
||||
|
||||
[project]
|
||||
name = "waka-readme"
|
||||
version = "0.2.3"
|
||||
version = "0.3.0"
|
||||
description = "Wakatime Weekly Metrics on your Profile Readme."
|
||||
authors = [{ name = "Athul Cyriac Ajay", email = "athul8720@gmail.com" }]
|
||||
license = { text = "MIT" }
|
||||
readme = "README.md"
|
||||
keywords = ["readme", "profile-page", "wakatime"]
|
||||
authors = [{ name = "Athul Cyriac Ajay", email = "athul8720@gmail.com" }]
|
||||
maintainers = [{ name = "Jovial Joe Jayarson" }]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Programming Language :: Python",
|
||||
"Typing :: Typed",
|
||||
]
|
||||
requires-python = ">=3.11"
|
||||
dependencies = ["faker>=19.1.0", "pygithub>=1.59.0", "requests>=2.31.0"]
|
||||
requires-python = ">=3.12"
|
||||
dependencies = ["faker>=21.0.0", "pygithub>=2.1.1", "requests>=2.31.0", "py-gitea>=0.2.6"]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/athul/waka-readme"
|
||||
@@ -25,32 +24,63 @@ Documentation = "https://github.com/athul/waka-readme#readme"
|
||||
Repository = "https://github.com/athul/waka-readme"
|
||||
Changelog = "https://github.com/athul/waka-readme/commits/master"
|
||||
|
||||
|
||||
#############################
|
||||
# Optional Dependencies #
|
||||
#############################
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = ["loguru>=0.7.0", "python-dotenv>=1.0.0"]
|
||||
tooling = ["bandit>=1.7.5", "black>=23.7.0", "ruff>=0.0.278"]
|
||||
extra = ["loguru>=0.7.2", "python-dotenv>=1.0.0"]
|
||||
|
||||
#############################
|
||||
# Development Dependencies #
|
||||
#############################
|
||||
|
||||
[tool.pdm.dev-dependencies]
|
||||
tooling = ["bandit>=1.7.6", "black>=23.12.1", "ruff>=0.1.9", "pyright>=1.1.342"]
|
||||
|
||||
####################
|
||||
# Configurations #
|
||||
####################
|
||||
|
||||
[tool.bandit]
|
||||
exclude_dirs = [".github", "tests", ".venv", ".vscode"]
|
||||
|
||||
[tool.black]
|
||||
line-length = 100
|
||||
target-version = ["py311"]
|
||||
target-version = ["py312"]
|
||||
|
||||
[tool.bandit]
|
||||
exclude_dirs = [".github", ".pytest_cache", ".tox", ".vscode", "site", "tests"]
|
||||
[tool.pyright]
|
||||
exclude = ["**/__pycache__", ".venv/"]
|
||||
pythonVersion = "3.12"
|
||||
pythonPlatform = "All"
|
||||
typeCheckingMode = "strict"
|
||||
|
||||
[tool.ruff]
|
||||
select = [
|
||||
# Pyflakes
|
||||
"F",
|
||||
# pycodestyle
|
||||
"W",
|
||||
"E",
|
||||
# mccabe
|
||||
# C90
|
||||
# isort
|
||||
"I",
|
||||
# pep8-naming
|
||||
"N",
|
||||
# pydocstyle
|
||||
"D",
|
||||
]
|
||||
line-length = 100
|
||||
target-version = "py312"
|
||||
extend-exclude = ["**/__pycache__"]
|
||||
|
||||
[tool.ruff.isort]
|
||||
# case-sensitive = true
|
||||
combine-as-imports = true
|
||||
force-sort-within-sections = true
|
||||
force-wrap-aliases = true
|
||||
relative-imports-order = "closest-to-furthest"
|
||||
|
||||
[tool.ruff.pydocstyle]
|
||||
convention = "google"
|
||||
|
||||
[tool.ruff.isort]
|
||||
force-sort-within-sections = true
|
||||
relative-imports-order = "closest-to-furthest"
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
"""
|
||||
Initialize test module
|
||||
"""
|
||||
"""Initialize test module."""
|
||||
|
||||
# standard
|
||||
import logging
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
"""Unit Tests."""
|
||||
|
||||
# standard
|
||||
from importlib import import_module
|
||||
from dataclasses import dataclass # , field
|
||||
from importlib import import_module
|
||||
from itertools import product
|
||||
import unittest
|
||||
import sys
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
# from pathlib import Path
|
||||
# from inspect import cleandoc
|
||||
|
||||
Reference in New Issue
Block a user