30 Commits

Author SHA1 Message Date
c0345cb5d9 Merge branch 'dev-gitea' of https://git.mamahaha.work/sangge/waka-readme into dev-gitea 2024-01-18 23:03:17 +08:00
632b13121d update some readme 2024-01-18 22:59:49 +08:00
8b0ab3bd76 Merge branch 'master' into dev-gitea 2024-01-18 22:43:30 +08:00
7a6d95d436 remove requirements.txt 2024-01-18 22:42:21 +08:00
fd26197e70 Merge pull request 'use pyproject.toml to control deps' (#1) from dev-gitea into master
Reviewed-on: #1
2024-01-18 22:40:43 +08:00
99b6b3f887 remove dev file 2024-01-18 22:35:01 +08:00
c2f0b9de48 use pyproject.toml to control deps 2024-01-18 22:29:09 +08:00
95c7f84451 use slim image 2024-01-16 00:19:01 +08:00
d1558ad6db update readme 2024-01-15 23:46:39 +08:00
76d3c7249a update gitea url 2024-01-15 21:17:44 +08:00
450ba61d22 Merge branch 'master' of https://git.mamahaha.work/sangge/waka-readme 2024-01-15 21:06:50 +08:00
3d3239a2e3 use 3.11 2024-01-15 21:06:17 +08:00
830c76c07a update requirement 2024-01-15 21:01:33 +08:00
6125862010 mute useless ci 2024-01-15 20:53:58 +08:00
b88da2af7d update requirements
Some checks failed
WakaReadme CI / UnitTests (push) Failing after 13s
2024-01-15 20:52:49 +08:00
b55e75a74d update container
Some checks failed
WakaReadme CI / UnitTests (push) Failing after 13s
2024-01-15 20:38:23 +08:00
3bc9d82ee4 feat: update action 2024-01-15 20:36:55 +08:00
980f869999 finish dev version
Some checks failed
WakaReadme CI / UnitTests (push) Failing after 26s
2024-01-15 20:02:19 +08:00
108a90abce test: update
Some checks failed
WakaReadme CI / UnitTests (push) Failing after 19s
2024-01-15 02:38:12 +08:00
Jovial Joe Jayarson
5dc349128a Merge pull request #152 from yozachar/workshop
chore: monthly updates for Dec'23
2023-12-25 13:06:38 +05:30
Jovial Joe Jayarson
d2e7ba7208 chore: monthly updates for Dec'23 2023-12-24 22:17:15 +05:30
Jovial Joe Jayarson
2dd14d3fd8 Merge pull request #149 from yozachar/workshop
chore: monthly updates for Nov'23
2023-11-09 08:44:27 +05:30
Jovial Joe Jayarson
e644272268 chore: monthly updates for Nov'23 2023-11-08 11:48:30 +05:30
Jovial Joe Jayarson
2aab71918a Merge pull request #148 from yozachar/workshop
chore: monthly updates for Oct'23; bump version
2023-10-23 09:48:07 +05:30
Jovial Joe Jayarson
3f2f9d748e chore: monthly updates for Oct'23; bump version 2023-10-21 08:12:29 +05:30
Andrew Hong
54c3312012 feat: adds flag IGNORE_LANGUAGES (#146)
- feat: adds flag `IGNORE_LANGUAGES`  (#146)

---------

Co-authored-by: Jovial Joe Jayarson <jovial7joe@hotmail.com>
2023-10-21 07:58:43 +05:30
Jovial Joe Jayarson
dd576f44c6 Merge pull request #144 from joe733/workshop
chore: monthly updates for Sep'23; bump version
2023-09-19 16:23:00 +05:30
Jovial Joe Jayarson
b2363ac606 chore: monthly updates for Sep'23; bump version
- fix: 0 discovered test in container
- uses containerfile for testing
- update dependencies, bump version
2023-09-17 15:55:22 +05:30
Jovial Joe Jayarson
519a95b477 Merge pull request #143 from joe733/workshop
chore: monthly updates for Aug'23; bump version
2023-08-18 08:36:43 +05:30
Jovial Joe Jayarson
ac8e6017f5 chore: monthly updates for Aug'23; bump version
- revised readme, better theming support, improved wording where needed
- granular config for ruff linter & pyright type checker, re-format code
- update dependencies, bump version
2023-08-17 11:59:26 +05:30
13 changed files with 289 additions and 179 deletions

View File

@@ -17,6 +17,7 @@ INPUT_SHOW_TIME=
INPUT_SHOW_TOTAL= INPUT_SHOW_TOTAL=
INPUT_SHOW_MASKED_TIME= INPUT_SHOW_MASKED_TIME=
INPUT_STOP_AT_OTHER= INPUT_STOP_AT_OTHER=
INPUT_IGNORED_LANGUAGES=
# commit # commit
INPUT_COMMIT_MESSAGE= INPUT_COMMIT_MESSAGE=
INPUT_TARGET_BRANCH= INPUT_TARGET_BRANCH=

View File

@@ -2,9 +2,9 @@ name: WakaReadme CI
on: on:
push: push:
branches: [master] branches: [main]
pull_request: pull_request:
branches: [master] branches: [main]
workflow_dispatch: workflow_dispatch:
jobs: jobs:

4
.gitignore vendored
View File

@@ -107,6 +107,7 @@ poetry.lock
# However, this project does not rely on pdm for production. # However, this project does not rely on pdm for production.
pdm.lock pdm.lock
.pdm-python .pdm-python
.pdm-build
# PEP 582; used by e.g. github.com/David-OConnor/pyflow # PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/ __pypackages__/
@@ -162,8 +163,9 @@ cython_debug/
# VSCode # VSCode
.vscode/ .vscode/
# asdf # asdf/rtx
.tool-versions .tool-versions
.rtx.toml
# ruff # ruff
.ruff_cache .ruff_cache

View File

@@ -1,6 +1,6 @@
# Contributing # Contributing
![python_ver](https://img.shields.io/badge/Python-%3E%3D3.11-blue.svg) ![python_ver](https://img.shields.io/badge/Python-%3E%3D3.12-blue.svg)
> First off, thank you! Please follow along. > First off, thank you! Please follow along.
@@ -21,6 +21,7 @@ INPUT_TIME_RANGE=last_7_days
INPUT_SHOW_MASKED_TIME=false INPUT_SHOW_MASKED_TIME=false
INPUT_LANG_COUNT=0 INPUT_LANG_COUNT=0
INPUT_STOP_AT_OTHER=true INPUT_STOP_AT_OTHER=true
INPUT_IGNORED_LANGUAGES=
``` ```
**NEVER commit this `.env` file!** **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. > Replace `podman` with `docker` everywhere, if you're using the latter.
```sh ```sh
# Build # Build and watch logs
$ podman-compose -p waka-readme -f ./docker-compose.yml up -d $ podman-compose -p waka-readme -f ./docker-compose.yml up
# Logs
$ podman logs WakaReadmeDev
# Cleanup # Cleanup
$ podman-compose -p waka-readme -f ./docker-compose.yml down $ 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 1. Inside the cloned folder run the following commands to install dependencies
```console ```sh
$ python -m venv .venv $ python -m venv .venv
$ . ./.venv/bin/activate $ . ./.venv/bin/activate
$ python -m pip install . $ python -m pip install .
# ... install decencies ...
``` ```
to activate virtual environment & install dependencies. to activate virtual environment & install dependencies.
2. To test or execute the program in development, run: 2. To test or execute the program in development, run:
```console ```sh
(.venv)$ python -m unittest discover # run tests (.venv)$ python -m unittest discover # run tests
(.venv)$ python -m main --dev # execute program in dev mode (.venv)$ python -m main --dev # execute program in dev mode
``` ```

159
README.md
View File

@@ -1,22 +1,16 @@
<center> # Dev Metrics in Readme
![waka-readme](https://socialify.git.ci/athul/waka-readme/image?description=1&forks=1&name=1&pulls=1&stargazers=1&theme=Light) fork from [waka-readme](https://github/athul/waka-readme)
edit for Gitea use.
</center> [WakaTime](https://wakatime.com) coding metrics on your profile readme.
# Dev Metrics in Readme [![Unit Tests](https://github.com/athul/waka-readme/actions/workflows/testing.yml/badge.svg?branch=master)](https://github.com/athul/waka-readme/actions/workflows/testing.yml) ![Python Version](https://img.shields.io/badge/Python-^3.11-blue)
[WakaTime](https://wakatime.com) weekly metrics on your profile readme.
![Project Preview](https://user-images.githubusercontent.com/8397274/87243943-e6b45c00-c457-11ea-94c9-2aa0bf241be8.png)
:speech_balloon: **Forum** | [GitHub discussions][gh_discuss]
## New to WakaTime? ## 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. 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/>. 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. 4. Paste in your API key to start telemetry.
:information_source: **Info** | You can read [WakaTime help][waka_help] to know more about configurations. :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 ## 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. - 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. `<!--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. - 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.
> ![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.
```yml ```yml
name: Waka Readme name: Waka Readme
on: on:
workflow_dispatch: # for manual workflow trigger # for manual workflow trigger
workflow_dispatch:
schedule: schedule:
- cron: "0 0 * * *" # runs at every 12AM UTC # runs at 12 AM UTC (5:30 AM IST)
- cron: "0 0 * * *"
jobs: jobs:
update-readme: update-readme:
name: WakaReadme DevMetrics name: WakaReadme DevMetrics
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: athul/waka-readme@master - uses: https://git.mamahaha.work/sangge/waka-readme@master # this action name
with: with:
WAKATIME_API_KEY: ${{ secrets.WAKATIME_API_KEY }} 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. Refer [#Example](#example) section for a full blown workflow file.
## Tweaks ## 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 ### Meta Tweaks
@@ -87,18 +74,19 @@ There are many flags that you can tweak as you wish!
### Content Tweaks ### Content Tweaks
| Environment flag | Options (`Default`, `Other`, ...) | Description | | Environment flag | Options (`Default`, `Other`, ...) | Description |
| ------------------ | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------- | | ------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `SHOW_TITLE` | `false`, `true` | Add title to waka-readme stats blob | | `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. | | `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 | | `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 | | `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 | | `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 | | `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_TIME` | `true`, `false` | Displays the amount of time spent for each language |
| `SHOW_TOTAL` | `false`, `true` | Show total coding time | | `SHOW_TOTAL` | `false`, `true` | Show total coding time |
| `SHOW_MASKED_TIME` | `false`, `true` | Adds total coding time including unclassified languages (overrides: `SHOW_TOTAL`) | | `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`) | | `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 ### Commit Tweaks
@@ -112,9 +100,9 @@ There are many flags that you can tweak as you wish!
| `AUTHOR_NAME` | `NOT_SET`, author name | | `AUTHOR_NAME` | `NOT_SET`, author name |
| `AUTHOR_EMAIL` | `NOT_SET`, author email | | `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`** **`waka-readme.yml`**
@@ -122,9 +110,10 @@ All of these flags are _optional_.
name: Waka Readme name: Waka Readme
on: on:
# for manual workflow trigger
workflow_dispatch: workflow_dispatch:
schedule: schedule:
# Runs at 12am UTC # runs at 12 AM UTC (5:30 AM IST)
- cron: "0 0 * * *" - cron: "0 0 * * *"
jobs: jobs:
@@ -132,45 +121,42 @@ jobs:
name: WakaReadme DevMetrics name: WakaReadme DevMetrics
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: 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: with:
GH_TOKEN: ${{ secrets.GH_TOKEN }} GH_TOKEN: ${{ secrets.GH_TOKEN }} # optional if on profile readme
WAKATIME_API_KEY: ${{ secrets.WAKATIME_API_KEY }} WAKATIME_API_KEY: ${{ secrets.WAKATIME_API_KEY }} # required
# meta ### meta
API_BASE_URL: https://wakatime.com/api API_BASE_URL: https://wakatime.com/api # optional
REPOSITORY: athul/athul REPOSITORY: YOUR_GITEA_USERNAME/YOUR_REPOSITORY_NAME # optional
# content ### content
SHOW_TITLE: true SHOW_TITLE: true # optional
SECTION_NAME: waka SECTION_NAME: waka # optional
BLOCKS: -> BLOCKS: -> # optional
CODE_LANG: all_time CODE_LANG: rust # optional
TIME_RANGE: true TIME_RANGE: all_time # optional
LANG_COUNT: 10 LANG_COUNT: 10 # optional
SHOW_TIME: true SHOW_TIME: true # optional
SHOW_TOTAL: true SHOW_TOTAL: true # optional
SHOW_MASKED_TIME: false SHOW_MASKED_TIME: false # optional
STOP_AT_OTHER: true STOP_AT_OTHER: true # optional
# commit IGNORED_LANGUAGES: YAML JSON TOML # optional
COMMIT_MESSAGE: Updated waka-readme graph with new metrics ### commit
TARGET_BRANCH: master COMMIT_MESSAGE: Updated waka-readme graph with new metrics # optional
TARGET_PATH: README.md TARGET_BRANCH: master # optional
COMMITTER_NAME: GitHubActionBot TARGET_PATH: README.md # optional
COMMITTER_EMAIL: action-bot@github.org COMMITTER_NAME: GitHubActionBot # optional
AUTHOR_NAME: Athul COMMITTER_EMAIL: action-bot@github.com # optional
AUTHOR_EMAIL: athul@example.org AUTHOR_NAME: YOUR_NAME # optional
AUTHOR_EMAIL: YOUR@EMAIL.com # optional
# you can populate email-id with secretes instead # you can populate email-id with secretes instead
``` ```
> Note: _Rendered `markdown`:_
>
> - 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.
**`README.md`** <!-- prettier-ignore-start -->
```md ```rust
From: 10 July 2020 - To: 06 August 2022 From: 10 July 2020 - To: 06 August 2022
Total Time: 1,464 hrs 54 mins 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 % 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? ## 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: 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_plugins]: https://wakatime.com/plugins
[waka_help]: https://wakatime.com/help/editors [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 [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

View File

@@ -3,7 +3,7 @@ author: "Athul Cyriac Ajay"
description: "WakaTime coding activity graph in your profile readme" description: "WakaTime coding activity graph in your profile readme"
inputs: inputs:
GH_TOKEN: GITEA_TOKEN:
description: "GitHub access token with Repo scope" description: "GitHub access token with Repo scope"
default: ${{ github.token }} default: ${{ github.token }}
required: true required: true
@@ -62,6 +62,10 @@ inputs:
description: "Stop data retrieval when language marked 'Other' is reached" description: "Stop data retrieval when language marked 'Other' is reached"
default: "false" default: "false"
required: false required: false
IGNORED_LANGUAGES:
description: "Ignore space separated, listed languages"
default: ""
required: false
# commit tweaks # commit tweaks
COMMIT_MESSAGE: COMMIT_MESSAGE:

View File

@@ -5,7 +5,6 @@ services:
- .env.template - .env.template
build: build:
context: . context: .
dockerfile: dockerfile dockerfile: containerfile
image: waka-readme:testing image: waka-readme:testing
container_name: WakaReadmeTesting container_name: WakaReadmeTesting
command: python -m unittest discover

51
containerfile Normal file
View 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/

View File

@@ -16,6 +16,7 @@ ENV INPUT_GH_TOKEN \
INPUT_SHOW_TOTAL \ INPUT_SHOW_TOTAL \
INPUT_SHOW_MASKED_TIME \ INPUT_SHOW_MASKED_TIME \
INPUT_STOP_AT_OTHER \ INPUT_STOP_AT_OTHER \
INPUT_IGNORED_LANGUAGES \
# commit # commit
INPUT_COMMIT_MESSAGE \ INPUT_COMMIT_MESSAGE \
INPUT_TARGET_BRANCH \ INPUT_TARGET_BRANCH \
@@ -41,7 +42,7 @@ ENV PATH="${PATH}:/root/.local/bin" \
COPY --chown=root:root pyproject.toml main.py /app/ COPY --chown=root:root pyproject.toml main.py /app/
# install dependencies # install dependencies
RUN python -m pip install /app/ RUN python -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple
# execute program # execute program
CMD python /app/main.py CMD python /app/main.py

153
main.py
View File

@@ -28,28 +28,28 @@ Contents := Title + Byline + Body
""" """
# standard # standard
from base64 import b64encode, b64decode
from dataclasses import dataclass from dataclasses import dataclass
from random import SystemRandom
from functools import partial
from datetime import datetime from datetime import datetime
from base64 import b64encode from functools import partial
import logging as logger import logging as logger
import os
from random import SystemRandom
import re
import sys
from time import sleep from time import sleep
from typing import Any from typing import Any
import sys
import re
import os
# external # 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 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 ################### ################### setup ###################
print() print()
# hush existing loggers # hush existing loggers
for lgr_name in logger.root.manager.loggerDict: for lgr_name in logger.root.manager.loggerDict:
@@ -71,8 +71,12 @@ try:
# comment this out to disable colored logging # comment this out to disable colored logging
from loguru import logger from loguru import logger
logger.debug("loguru loaded")
# load from .env before class def gets parsed # load from .env before class def gets parsed
load_dotenv() load_dotenv()
logger.debug("dotenv loaded")
waka_key: str | None = os.getenv("INPUT_WAKATIME_API_KEY")
except ImportError as im_err: except ImportError as im_err:
logger.warning(im_err) logger.warning(im_err)
@@ -128,7 +132,8 @@ class WakaInput:
# mapped environment variables # mapped environment variables
# # required # # 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") 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") api_base_url: str | None = os.getenv("INPUT_API_BASE_URL", "https://wakatime.com/api")
repository: str | None = os.getenv("INPUT_REPOSITORY") 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 show_masked_time: str | bool = os.getenv("INPUT_SHOW_MASKED_TIME") or False
language_count: str | int = os.getenv("INPUT_LANG_COUNT") or 5 language_count: str | int = os.getenv("INPUT_LANG_COUNT") or 5
stop_at_other: str | bool = os.getenv("INPUT_STOP_AT_OTHER") or False stop_at_other: str | bool = os.getenv("INPUT_STOP_AT_OTHER") or False
ignored_languages: str = os.getenv("INPUT_IGNORED_LANGUAGES", "")
# # optional meta # # optional meta
target_branch: str = os.getenv("INPUT_TARGET_BRANCH", "NOT_SET") target_branch: str = os.getenv("INPUT_TARGET_BRANCH", "NOT_SET")
target_path: str = os.getenv("INPUT_TARGET_PATH", "NOT_SET") target_path: str = os.getenv("INPUT_TARGET_PATH", "NOT_SET")
@@ -161,7 +167,12 @@ class WakaInput:
def validate_input(self): def validate_input(self):
"""Validate Input Env Variables.""" """Validate Input Env Variables."""
logger.debug("Validating input 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.error("Invalid inputs")
logger.info("Refer https://github.com/athul/waka-readme") logger.info("Refer https://github.com/athul/waka-readme")
return False return False
@@ -271,7 +282,7 @@ def make_graph(block_style: str, percent: float, gr_len: int, lg_nm: str = "", /
return graph_bar 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. """WakaReadme Prepare Markdown.
Prepared markdown content from the fetched statistics. 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) max((str(lng["name"]) for lng in lang_info), key=len)
# and then do not for get to set `pad_len` to say 13 :) # 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( logger.debug(
"Set INPUT_LANG_COUNT to -1 to retrieve all language" "Set INPUT_LANG_COUNT to -1 to retrieve all language"
+ " or specify a positive number (ie. above 0)" + " or specify a positive number (ie. above 0)"
) )
return contents.rstrip("\n") 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): for idx, lang in enumerate(lang_info):
lang_name = str(lang["name"]) lang_name = str(lang["name"])
# >>> add languages to filter here <<< if ignored_languages and lang_name.lower() in ignored_languages:
# if lang_name in {...}: continue continue
lang_time = str(lang["text"]) if wk_i.show_time else "" lang_time = str(lang["text"]) if wk_i.show_time else ""
lang_ratio = float(lang["percent"]) lang_ratio = float(lang["percent"])
lang_bar = make_graph(wk_i.block_style, lang_ratio, wk_i.graph_length, lang_name) 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) sys.exit(1)
# preparing contents # preparing contents
try: try:
generated_content = prep_content( generated_content = prep_content(waka_stats)
waka_stats, int(wk_i.language_count), bool(wk_i.stop_at_other)
)
except (AttributeError, KeyError, ValueError) as err: except (AttributeError, KeyError, ValueError) as err:
logger.error(f"Unable to read API data | {err}\n") logger.error(f"Unable to read API data | {err}\n")
sys.exit(1) 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}", 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, string=old_readme,
) )
logger.debug(new_readme)
if len(sys.argv) == 2 and sys.argv[1] == "--dev": if len(sys.argv) == 2 and sys.argv[1] == "--dev":
logger.debug("Detected run in `dev` mode.") logger.debug("Detected run in `dev` mode.")
# to avoid accidentally writing back to Github # to avoid accidentally writing back to Github
# when developing or testing waka-readme # when developing or testing waka-readme
return None return None
return None if new_readme == old_readme else new_readme 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.""" """Qualify target repository defaults."""
@dataclass @dataclass
class TargetRepository: class TargetRepository:
this: ContentFile.ContentFile # this: ContentFile.ContentFile
this: Content
path: str path: str
commit_message: str commit_message: str
sha: str sha: str
branch: str branch: str
committer: InputGitAuthor | None # committer: InputGitAuthor | None
author: InputGitAuthor | None # author: InputGitAuthor | None
committer: None
author: None
gh_branch = gh_repo.default_branch gitea_branch = gitea_repo.get_branches()[0].name
if wk_i.target_branch != "NOT_SET": # if wk_i.target_branch != "NOT_SET":
gh_branch = gh_repo.get_branch(wk_i.target_branch) # gitea_branch = gitea_repo.get_branch(wk_i.target_branch)
target = gh_repo.get_readme() readme_content = Content(gitea_connect)
if wk_i.target_path != "NOT_SET": readme_content.path = "README.md"
target = gh_repo.get_contents( readme_content.type = Content.FILE
path=wk_i.target_path, target = gitea_repo.get_file_content(readme_content) # base64 encoded
ref=gh_branch if isinstance(gh_branch, str) else gh_branch.commit.sha, # 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): if isinstance(target, list):
raise RuntimeError("Cannot handle multiple files.") raise RuntimeError("Cannot handle multiple files.")
committer, author = None, None committer, author = None, None
if wk_i.committer_name != "NOT_SET" and wk_i.committer_email != "NOT_SET": # 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) # 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": # 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) # author = InputGitAuthor(name=wk_i.author_name, email=wk_i.author_email)
sha = ""
return TargetRepository( return TargetRepository(
this=target, this=target,
path=target.path, path="README.md",
commit_message=wk_i.commit_message, commit_message=wk_i.commit_message,
sha=target.sha, sha=sha,
branch=gh_branch if isinstance(gh_branch, str) else gh_branch.name, branch=gitea_branch if isinstance(gitea_branch, str) else gitea_branch.name,
committer=committer, committer=committer,
author=author, author=author,
) )
@@ -462,34 +482,45 @@ def qualify_target(gh_repo: Repository.Repository):
def genesis(): def genesis():
"""Run Program.""" """Run Program."""
logger.debug("Connecting to GitHub") logger.debug("Connecting to Gitea")
gh_connect = Github(wk_i.gh_token) gitea_connect = Gitea(wk_i.gitea_url, wk_i.gitea_token)
# since a validator is being used earlier, casting # since a validator is being used earlier, casting
# `wk_i.ENV_VARIABLE` to a string here, is okay # `wk_i.ENV_VARIABLE` to a string here, is okay
gh_repo = gh_connect.get_repo(str(wk_i.repository)) # gitea_repo = gitea_connect.get_repo(str(wk_i.repository))
target = qualify_target(gh_repo) 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") 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)): if not (new_content := churn(readme_contents)):
logger.info("WakaReadme was not updated") logger.info("WakaReadme was not updated")
return return
logger.debug("WakaReadme stats has changed") logger.debug("WakaReadme stats has changed")
update_metric = partial( # update_metric = partial(
gh_repo.update_file, # gitea_repo.update_file,
path=target.path, # path=target.path,
message=target.commit_message, # message=target.commit_message,
content=new_content, # content=new_content,
sha=target.sha, # sha=target.sha,
branch=target.branch, # branch=target.branch,
) # )
if target.committer: # if target.committer:
update_metric = partial(update_metric, committer=target.committer) # update_metric = partial(update_metric, committer=target.committer)
if target.author: # if target.author:
update_metric = partial(update_metric, author=target.author) # update_metric = partial(update_metric, author=target.author)
update_metric() # 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") logger.info("Stats updated successfully")
return
################### driver ################### ################### driver ###################
@@ -518,7 +549,7 @@ if __name__ == "__main__":
except RuntimeError as err: except RuntimeError as err:
logger.error(f"{type(err).__name__}: {err}\n") logger.error(f"{type(err).__name__}: {err}\n")
sys.exit(1) sys.exit(1)
except (GithubException, RequestException) as rq_exp: # except (GithubException, RequestException) as rq_exp:
logger.critical(f"{rq_exp}\n") # logger.critical(f"{rq_exp}\n")
sys.exit(1) # sys.exit(1)
print("\nThanks for using WakaReadme!\n") print("\nThanks for using WakaReadme!\n")

View File

@@ -4,20 +4,19 @@
[project] [project]
name = "waka-readme" name = "waka-readme"
version = "0.2.3" version = "0.3.0"
description = "Wakatime Weekly Metrics on your Profile Readme." description = "Wakatime Weekly Metrics on your Profile Readme."
authors = [{ name = "Athul Cyriac Ajay", email = "athul8720@gmail.com" }]
license = { text = "MIT" } license = { text = "MIT" }
readme = "README.md" readme = "README.md"
keywords = ["readme", "profile-page", "wakatime"] keywords = ["readme", "profile-page", "wakatime"]
authors = [{ name = "Athul Cyriac Ajay", email = "athul8720@gmail.com" }]
maintainers = [{ name = "Jovial Joe Jayarson" }]
classifiers = [ classifiers = [
"Development Status :: 5 - Production/Stable", "Development Status :: 5 - Production/Stable",
"Programming Language :: Python", "Programming Language :: Python",
"Typing :: Typed", "Typing :: Typed",
] ]
requires-python = ">=3.11" requires-python = ">=3.12"
dependencies = ["faker>=19.1.0", "pygithub>=1.59.0", "requests>=2.31.0"] dependencies = ["faker>=21.0.0", "pygithub>=2.1.1", "requests>=2.31.0", "py-gitea>=0.2.6"]
[project.urls] [project.urls]
Homepage = "https://github.com/athul/waka-readme" 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" Repository = "https://github.com/athul/waka-readme"
Changelog = "https://github.com/athul/waka-readme/commits/master" Changelog = "https://github.com/athul/waka-readme/commits/master"
############################# #############################
# Optional Dependencies # # Optional Dependencies #
############################# #############################
[project.optional-dependencies] [project.optional-dependencies]
dev = ["loguru>=0.7.0", "python-dotenv>=1.0.0"] extra = ["loguru>=0.7.2", "python-dotenv>=1.0.0"]
tooling = ["bandit>=1.7.5", "black>=23.7.0", "ruff>=0.0.278"]
#############################
# Development Dependencies #
#############################
[tool.pdm.dev-dependencies]
tooling = ["bandit>=1.7.6", "black>=23.12.1", "ruff>=0.1.9", "pyright>=1.1.342"]
#################### ####################
# Configurations # # Configurations #
#################### ####################
[tool.bandit]
exclude_dirs = [".github", "tests", ".venv", ".vscode"]
[tool.black] [tool.black]
line-length = 100 line-length = 100
target-version = ["py311"] target-version = ["py312"]
[tool.bandit] [tool.pyright]
exclude_dirs = [".github", ".pytest_cache", ".tox", ".vscode", "site", "tests"] exclude = ["**/__pycache__", ".venv/"]
pythonVersion = "3.12"
pythonPlatform = "All"
typeCheckingMode = "strict"
[tool.ruff] [tool.ruff]
select = [
# Pyflakes
"F",
# pycodestyle
"W",
"E",
# mccabe
# C90
# isort
"I",
# pep8-naming
"N",
# pydocstyle
"D",
]
line-length = 100 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] [tool.ruff.pydocstyle]
convention = "google" convention = "google"
[tool.ruff.isort]
force-sort-within-sections = true
relative-imports-order = "closest-to-furthest"

View File

@@ -1,6 +1,4 @@
""" """Initialize test module."""
Initialize test module
"""
# standard # standard
import logging import logging

View File

@@ -1,12 +1,12 @@
"""Unit Tests.""" """Unit Tests."""
# standard # standard
from importlib import import_module
from dataclasses import dataclass # , field from dataclasses import dataclass # , field
from importlib import import_module
from itertools import product from itertools import product
import unittest
import sys
import os import os
import sys
import unittest
# from pathlib import Path # from pathlib import Path
# from inspect import cleandoc # from inspect import cleandoc