mirror of
https://github.com/avinal/avinal.github.io.git
synced 2026-07-04 07:40:09 +05:30
add tekton results blog
Signed-off-by: Avinal Kumar <avinal.xlvii@gmail.com>
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
---
|
||||
title: How I implemented WakaTime embeddable Coding Graph GHA?
|
||||
date: 2021-02-02 21:47
|
||||
tags: [wakatime, github-action, coding]
|
||||
category: development
|
||||
image: "/images/waka.webp"
|
||||
description: 'If you use WakaTime to track your coding activity. You can add that to
|
||||
your README as a bar graph or embed it in your blog/portfolio. Just add this
|
||||
action to any of your repositories and there you have it.'
|
||||
---
|
||||
|
||||
# How I implemented WakaTime embeddable Coding Graph GHA?
|
||||
|
||||
If you use WakaTime to track your coding activity. You can add that to
|
||||
your README as a bar graph or embed it in your blog/portfolio. Just add this
|
||||
action to any of your repositories and there you have it.
|
||||
|
||||
## Implementation Details
|
||||
|
||||
This GitHub Action is divided into three parts. I didn't want to use
|
||||
Docker but it seems it doesn't work well without it. Let dive a little
|
||||
into technical details. Three parts are as below.
|
||||
|
||||
1. [main.py](https://github.com/avinal/Profile-Readme-WakaTime/blob/master/main.py)
|
||||
python script. This script contains many procedures.
|
||||
|
||||
- [Getting JSON data file via WakaTime
|
||||
API](https://github.com/avinal/Profile-Readme-WakaTime/blob/master/main.py#L52)
|
||||
|
||||
```python
|
||||
def get_stats() -> list:
|
||||
...
|
||||
return data_list
|
||||
```
|
||||
|
||||
This function parses the JSON file received and scraps out the useful
|
||||
data as a list of lists. Data scraped are language list, time spent on
|
||||
each language, percentage of the time, start date, and end date. For
|
||||
this action, I have limited the number of languages to 5 however it
|
||||
should be very easy to increase that number.
|
||||
|
||||
- [Setting the
|
||||
Timeline](https://github.com/avinal/Profile-Readme-WakaTime/blob/master/main.py#L13)
|
||||
|
||||
```python
|
||||
def this_week(dates: list) -> str:
|
||||
...
|
||||
return f"Coding Activity During: {week_start.strftime('%d %B, %Y')} to {week_end.strftime('%d %B, %Y')}"
|
||||
```
|
||||
|
||||
The start date and end date scraped in the last function are used here
|
||||
to set the timeline. Because date in JSON is provided in UTC as below
|
||||
:
|
||||
|
||||
```json
|
||||
date: "YYYY-MM-DDTHH:MM:SSZ"
|
||||
```
|
||||
|
||||
I striped it to simple dates only. We can set them manually by taking
|
||||
the current time from the system. But that method is flawed. But this
|
||||
method ensures that JSON was received latest and the request was
|
||||
successful. Any anomaly will point to a failure in request.
|
||||
|
||||
- [Creating a bar
|
||||
graph](https://github.com/avinal/Profile-Readme-WakaTime/blob/master/main.py#L21)
|
||||
|
||||
```python
|
||||
def make_graph(data: list):
|
||||
...
|
||||
savefig(...)
|
||||
```
|
||||
|
||||
Lastly, it is time to generate the graph and save them as an image.
|
||||
This function uses the data scraped in the first step. Creating a bar
|
||||
graph using matplotlib is easy.
|
||||
Decorating was a bit difficult. I wanted this graph to merge with
|
||||
GitHub's look so I chose to color the bar as GitHub colors the
|
||||
languages. That data is stored as colors.json. Many of the languages have
|
||||
slightly different spelling in GitHub as compared to WakaTime. So some
|
||||
languages are shown in default color. That can be improved if we
|
||||
notice that language and change its color manually. Lastly, the graph
|
||||
is saved both as SVG and PNG. SVGs are better to put on a responsive
|
||||
page.
|
||||
|
||||
2. [entrypoint.py](https://github.com/avinal/Profile-Readme-WakaTime/blob/master/entrypoint.sh)
|
||||
shell script. This shell script clones the repository copies the
|
||||
image and pushes changes to the master. There were several problems.
|
||||
First of all authentication. This was solved by using a remote
|
||||
repository address using GitHub Token. And it seems that GitHub
|
||||
doesn't allow to commit without a username and email. So I used
|
||||
**github-actions** bot email.
|
||||
|
||||
```bash
|
||||
remote_repo-"https://${GITHUB_ACTOR}:${INPUT_GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git config user.name "GitHub Actions"
|
||||
```
|
||||
|
||||
`41898282` is the id assigned to the github-actions bot. Don't ask
|
||||
where I found them 🙂.
|
||||
|
||||
Another problem was to separate repository name from combined
|
||||
*username/repository-name* provided by `${GITHUB_REPOSITORY}`. GitHub doesn't
|
||||
provides a direct way to get just the repo name. We used *Internal
|
||||
Field Separator*. It returns an array and works similar to `split()`
|
||||
command in Python and Java.
|
||||
|
||||
```bash
|
||||
# '/' is the seperator
|
||||
IFS-'/' read -ra reponame <<< "${GITHUB_REPOSITORY}"
|
||||
# returned {username, repository}
|
||||
repository-"${reponame[1]}"
|
||||
```
|
||||
|
||||
After that, all other commands are pretty straight. Commit the added
|
||||
files and push them.
|
||||
|
||||
3. [Dockerfile](https://github.com/avinal/Profile-Readme-WakaTime/blob/master/Dockerfile)
|
||||
**IMPORTANT** It took a lot of time to reach this state 🥱. This is
|
||||
where all the magic happens. I am running <span
|
||||
class="title-ref">ubuntu:latest</span> inside the container. I first
|
||||
update the distribution. Then install the required python packages.
|
||||
Lastly, I invoke the python script and shell script.
|
||||
|
||||
There was an almost impossible problem, I searched hundreds of posts
|
||||
that *how can I access the generated files inside Docker container*, but
|
||||
no luck. But at last, I found a workaround(obviously otherwise you
|
||||
wouldn't be reading this by now 🤣) each command is run in a separate
|
||||
virtual sub-container. As the command ends its output is also lost but
|
||||
not when you club multiple commands together. At least not until every
|
||||
command is finished. The generated files are available to the next
|
||||
clubbed process. I did that by combining the python script run and shell
|
||||
script run.
|
||||
|
||||
```dockerfile
|
||||
CMD python3 /main.py && /entrypoint.sh
|
||||
```
|
||||
|
||||
This part is the smallest yet took the most time and tries while
|
||||
developing this action.
|
||||
|
||||
## How to use this GitHub Actions?
|
||||
|
||||
1. First get your WakaTime API Key. You can get it from your
|
||||
[WakaTime](<https://wakatime.com>) account settings.
|
||||
|
||||
2. Save WakaTime API Key to Repository Secret. Find that by clicking
|
||||
the Settings tab. Keep the name of the secret as
|
||||
**WAKATIME_API_KEY**.
|
||||
|
||||
3. Add the following line in your README.md of your repo.
|
||||
|
||||
```html
|
||||
<img src="https://github.com/<username>/<repository-name>/blob/<branch-name>/images/stat.svg" alt="Alternative Text"/>
|
||||
Example: <img src="https://github.com/avinal/avinal/blob/main/images/stat.svg" alt="Avinal WakaTime Activity"/>
|
||||
```
|
||||
|
||||
> You can use this method to embed in web pages too. **Do not use the
|
||||
> markdown method of inserting images. It does not work sometimes.**
|
||||
|
||||
4. Click the **Action** tab and **choose to set up a workflow
|
||||
yourself**.
|
||||
|
||||
5. Copy the following code into the opened file, you can search for
|
||||
**WakaTime Stat** in the marketplace tab for assistance.
|
||||
|
||||
```yaml
|
||||
name: WakaTime status update
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Runs at 12 am '0 0 * * *' UTC
|
||||
- cron: "1 0 * * *"
|
||||
|
||||
jobs:
|
||||
update-readme:
|
||||
name: Update the WakaTime Stat
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Use avinal/Profile-Readme-WakaTime@<latest-release-tag> for latest stable release
|
||||
# Do not change the line below except the word master with tag number maybe
|
||||
# If you have forked this project you can use <username>/Profile-Readme-WakaTime@master instead
|
||||
- uses: avinal/Profile-Readme-WakaTime@master
|
||||
with:
|
||||
# WakaTime API key stored in secrets, do not directly paste it here
|
||||
WAKATIME_API_KEY: ${{ secrets.WAKATIME_API_KEY }}
|
||||
# Automatic github token
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
# Branch - newer GitHub repositories have "main" as default branch, change to main in that case, default is master
|
||||
BRANCH: "master"
|
||||
# Manual Commit messages - write your own messages here
|
||||
COMMIT_MSG: "Automated Coding Activity Update :alien:"
|
||||
```
|
||||
|
||||
6. Please wait till 12 AM UTC to run this workflow automatically. Or
|
||||
you can force run it by going to the Actions tab. Or you can add the
|
||||
following lines under `on:` to run with
|
||||
every push. Search for 12 AM UTC to find the equivalent time in your
|
||||
time zone.
|
||||
|
||||
```yaml
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
schedule:
|
||||
- cron: '1 0 * * *'
|
||||
```
|
||||
|
||||
## My Coding Activity
|
||||
|
||||

|
||||
Reference in New Issue
Block a user