为 GitHub 主页添加「年进度」和「最近更新的博客文章」

午饭前看到一个 issue:[开源自荐] 利用Github Actions获取网站的Rss数据,并更新到个人主页

标题勾起了我学习的兴趣。自己也想进一步学习 GitHub Actions 的使用。

添加「年进度」

用到了 JavaScript 的知识,代码:

 1const thisYear = new Date().getFullYear()
 2const startTimeOfThisYear = new Date(`${thisYear}-01-01T00:00:00+00:00`).getTime()
 3const endTimeOfThisYear = new Date(`${thisYear}-12-31T23:59:59+00:00`).getTime()
 4const progressOfThisYear = (Date.now() - startTimeOfThisYear) / (endTimeOfThisYear - startTimeOfThisYear)
 5const progressBarOfThisYear = generateProgressBar()
 6
 7function generateProgressBar() {
 8    const progressBarCapacity = 30
 9    const passedProgressBarIndex = parseInt(progressOfThisYear * progressBarCapacity)
10    const progressBar = Array(progressBarCapacity)
11        .fill('_')
12        .map((value, index) => index < passedProgressBarIndex ? '█' : value)
13        .join('')
14    return ` ${progressBar}`
15}
16
17const readme =`
18Annual balance  ${progressBarOfThisYear} ${(progressBarOfThisYear * 100).toFixed(2)} %
19⏰ Updated on ${new Date().toUTCString()}`;
20console.log(readme)

注释

  1. const 定义常量名,需要初始化
  2. thisYear 当前年份
  3. startTimeOfThisYear 今年的开始时间
  4. endTimeOfThisYear 今年的结束时间
  5. progressOfThisYear 今年的进度(百分比)
  6. progressBarOfThisYear 今年的进度条
  7. generateProgressBar 生成进度条
  8. function 定义函数

添加「最近更新的博客文章」

使用了 pipenv 这个 Python 开发工作流。在与个人用户名相同的仓库中添加 Pipfile

 1[[source]]
 2name = "pypi"
 3url = "https://pypi.org/simple"
 4verify_ssl = true
 5
 6[scripts]
 7build = "python main.py"
 8
 9[dev-packages]
10
11[packages]
12requests = "2.25.1"
13feedparser = "6.0.2"
14pytz = "2020.5"
15
16[requires]
17python_version = "3.7"

python_version 必须是 3.7,改成其他的会报错(错误地址1):

1Warning: Python 3.8 was not found on your system...
2Neither 'pyenv' nor 'asdf' could be found to install Python.
3You can specify specific versions of Python with:
4$ pipenv --python path/to/python

因为好奇是否必须是 3.7,我改成 3.8,3.9,3.x。发现都出现错误。改成 3.x 报错(错误地址2):

1ValueError: invalid literal for int() with base 10: '3.x'

本地运行的话,需要使用 pippipenv 命令。我的本地环境是 WSL2-Ubuntu20.04。我已经安装了最新版本的 pip,直接安装 pipenv 即可:

1pip install pipenv

然后,在本地仓库中新建上述文件 Pipfile,执行:

1pipenv install

安装依赖,会自动生成 Pipfile.lock,可以选择不同步至远程仓库,因为在运行 GitHub Actions 时,环境会自动生成相关依赖文件。

另外一个主要文件就是 main.py

 1import feedparser
 2import time
 3import os
 4import re
 5import pytz
 6from datetime import datetime
 7
 8def get_link_info(feed_url, num):
 9
10    result = ""
11    feed = feedparser.parse(feed_url)
12    feed_entries = feed["entries"]
13    feed_entries_length = len(feed_entries)
14    all_number = 0;
15
16    if(num > feed_entries_length):
17        all_number = feed_entries_length
18    else:
19        all_number = num
20    
21    for entrie in feed_entries[0: all_number]:
22        title = entrie["title"]
23        link = entrie["link"]
24        result = result + "\n" + "[" + title + "](" + link + ")" + "\n"
25    
26    return result
27
28def main():
29    blog =  get_link_info("https://blog.yidajiabei.xyz/index.xml", 3)
30    insert_info = blog
31
32    # 替换 ---start--- 到 ---end--- 之间的内容
33    # pytz.timezone('Asia/Shanghai')).strftime('%Y年%m月%d日%H时M分')
34    fmt = '%Y-%m-%d %H:%M:%S %Z%z'
35    insert_info = "---start---\n\n**最近更新文章(" + "更新时间:"+  datetime.fromtimestamp(int(time.time()),pytz.timezone('Asia/Shanghai')).strftime('%Y-%m-%d %H:%M:%S') + " | 通过Github Actions自动更新)**" +"\n" + insert_info + "\n---end---"
36    # 获取README.md内容
37    with open (os.path.join(os.getcwd(), "README.md"), 'r', encoding='utf-8') as f:
38        readme_md_content = f.read()
39
40    print(insert_info)
41
42    new_readme_md_content = re.sub(r'---start---(.|\n)*---end---', insert_info, readme_md_content)
43
44    with open (os.path.join(os.getcwd(), "README.md"), 'w', encoding='utf-8') as f:
45        f.write(new_readme_md_content)
46
47main()

它是一个 Python 源文件,主要作用就是在 README.md 文件的 ---start------end--- 插入我最近更新的三篇文章。

整合 GitHub Actions

我想让 GitHub Actions 帮我完成这两件事。我需要怎么做呢?

首先,新建文件 ~\.github\workflows\main.yml,并添加以下内容:

 1name: update tianheg profile
 2
 3on:
 4  workflow_dispatch:
 5  schedule:
 6    - cron: '0 */6 * * *'
 7
 8jobs:
 9  build:
10    runs-on: ubuntu-latest
11    steps:
12    - uses: actions/[email protected]
13    - name: Use Node.js
14      uses: actions/[email protected]
15      with:
16        node-version: '14.x'
17    - name: Update README.md
18      run: node index.js > README.md
19    - name: Install dependecies
20      uses: tianheg/[email protected]
21      with:
22        command: install --dev # Install all dependencies, including development ones
23    - name: Build
24      uses: tianheg/[email protected]
25      with:
26        command: run build
27    - name: Commit change & Push
28      run: |
29          git diff
30          git config user.name 'github-actions[bot]'
31          git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
32          git commit -am "bot: update README.md automatically"
33          git push          

注释

  1. name 名字是任取的,能表达意思即可
  2. on 何时运行。workflow_dispatch 能让我手动执行工作流,0 */6 * * * 是一种表示周期时间的语法,当前含义:每六个小时执行一次(了解更多
  3. jobs 它后面就是具体的工作流
  4. build 第一个工作的名称,单个任意单词即可
  5. runs-on: ubuntu-latest 表示在 Ubuntu 最新版(此时最新版指 18.04LTS,不久将更换为 20.04LTS)运行
  6. steps 步骤
  7. uses: actions/[email protected] 使用 actions/[email protected] 将当前仓库复制到虚拟环境(ubuntu-latest)中。
  8. uses: actions/[email protected]node-version: '14.x' 安装 Node.js 14.x
  9. run: node index.js > README.md 把「年进度」更新到 README.md 中
  10. uses: tianheg/[email protected]command: install --devcommand: run build 安装 pipenv 环境(因为会用到很多 GitHub Actions,于是就把有用的整成一个仓库),并执行命令 pipenv install --dev,然后执行命令 pipenv run build
  11. 最后一部分就是使用 github-actions[bot] 机器人作为提交者,提交这次 commit

解释 tianheg/[email protected]

这是我使用的关于 pipenv 的 GitHub Actions,它位于我的 GitHub 仓库的 pipenv 分支中。

文件结构:

1Dockerfile
2LICENSE
3README.md
4action.yml
5entrypoint.sh

主要发挥作用的是 Dockerfileentrypoint.sh

Dockerfile 内容:

 1ARG PYTHON_IMAGE_VERSION=3
 2FROM python:$PYTHON_IMAGE_VERSION
 3
 4RUN pip install --upgrade pip \
 5 && pip install pipenv \
 6 && python --version ; pip --version ; pipenv --version
 7
 8COPY entrypoint.sh /
 9RUN chmod +x /entrypoint.sh
10ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh 内容:

1#!/bin/sh
2
3sh -c "pipenv $*"

对于 Dockerfile 我不了解它的使用细节,但从这个文件里,我看出它完成了这几件事:获得 Python3;升级 pip;安装 pipenv;复制 entrypoint.sh 到根目录;给 entrypoint.sh 执行权限。

对于 entrypoint.sh 它完成的是输入了 pipenv。这样在执行命令时,才能够只输入 install --devrun build


参考资料

  1. https://github.com/zhaoolee/zhaoolee