(*/ω\*) TOP

照葫芦画瓢的打卡 GitHub Actions

2020 6月 30日 周二 tech
Cover Image

本文最后更新于 天前,文中部分描述可能已经过时。

昨天逛博客看到了使用 GitHub Actions 定时任务调用 Microsoft 365 E5 API 以帮助续订的文章,我转念一想这是不是也可以用来跑定时任务打卡呢?说干就干我开了一个小的坑:用 GitHub Actions 跑之前写的 Python 打卡脚本。

参考项目是 wangziyingwen/AutoApiSecret,查看他的工作流 文件

  1. 事先将一些重要信息写在仓库 Secrets 中,以 name=value 的形式定义
  2. 在 workflow 中执行 echo 将 Secrets 内容写入临时文本并将要执行的脚本复制一份
  3. 在 workflow 中使用 sed -i '10 r tmp.txt' tmp.py
    没怎么了解过 sed 这个命令,运行后发现它将 tmp.txt 的内容写入了 tmp.py 的指定行 11 。哦,在执行工作流的过程中才输入私密信息,避免将私密信息直接写在仓库文件中
  4. 在 workflow 中执行 python tmp.py 运行填入了 Serects 的临时文件
    前面将重要信息以赋值语句的形式写到 Secrets,在执行工作流时直接将 Secrets 内容引入脚本前面行,这样赋值妙啊
  5. 在 workflow 中删除所有临时文件
  6. 以上为一次工作流,定时任务要靠 on.schedule.cron ,按 Linux Crontab 格式写

我的学习过程就是这么奇妙,让我自己写出这么一个流程我肯定是不会的:不了解 GitHub Actions 怎么用 Secrets 和 schedule.cron ,不熟悉 Linux sed 命令,没想过在工作流中新建临时文件……我就这么被拒绝白嫖了。

此刻,白嫖是第一生产力。了解了这样的流程部署自己的自动打卡就容易多了。照葫芦画瓢,我的瓢诞生了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
name: Auto Checkin

on:
release:
types: [published]
push:
tags:
- 'v*'
# Coordinated Universal Time (UTC)
schedule:
- cron: '0 0 * * *' # 定时任务依靠 cron 实现
watch:
types: [started]

jobs:
build:
runs-on: ubuntu-latest
if: github.event.repository.owner.id == github.event.sender.id # 自己点的 star
steps:
- name: Checkout
uses: actions/checkout@master
- name: Python Setup
uses: actions/setup-python@v1
with:
python-version: 3.8
- name: Pip Cache # 按照官方仓库 actions/cache 添加
uses: actions/cache@v2
with:
path: ~/.cache/pip # Ubuntu 的缓存位置,不同系统不同位置需要修改
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Addons Install # 安装脚本必须组件 lxml requests
run: |
pip install lxml requests
- name: Secrets Get # 获取 Secrets
env:
SECRET_ID: ${{ secrets.SECRET_ID }}
SECRET_PASS: ${{ secrets.SECRET_PASS }}
SECRET_BOUND: ${{ secrets.SECRET_BOUND }}
SECRET_DATA: ${{ secrets.SECRET_DATA }}
# 先复制一个临时文件,然后写入 Secrets 到文本,再将其写入临时脚本文件指定行
run: |
cp checkin.py action.py
echo $SECRET_ID > action-id.txt
echo $SECRET_PASS > action-pass.txt
echo $SECRET_BOUND > action-bound.txt
echo $SECRET_DATA > action-data.txt
sed -i '19 r action-id.txt' action.py
sed -i '20 r action-pass.txt' action.py
sed -i '21 r action-bound.txt' action.py
sed -i '22 r action-data.txt' action.py
- name: Checkin Action
env:
TZ: Asia/Shanghai # 设定时区为北京时间
# 工作流过程中新建 log 文件夹存放待会发布到另外一个分支的内容
run: |
mkdir log
echo `date +"%Y-%m-%d %H:%M:%S %A"` >> log/time.log
python action.py >> log/time.log
- name: Secrets Delete # 删除临时文件
run: |
rm -f action*
- name: Deploy Log # 发布 log 文件夹下的记录文件到 log 分支
uses: docker://peaceiris/gh-pages:v2
env:
TZ: Asia/Shanghai
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PUBLISH_BRANCH: log
PUBLISH_DIR: ./log
with:
emptyCommits: false

看起来有点臃肿,不过管他呢,确实能用。除去定时任务的框架,这个工作流还引入了 pip 模块缓存发布 log 记录文件到分支 的两个小功能。

pip 模块缓存 是从 苏卡大大 向 Cloudflare Workers Sites 部署 Hexo 博客的 文章 中学到的。项目 Nodejs 构建时需要的依赖挺多,没有缓存的话每次 GitHub Action 得跑很长分钟,于是苏卡大大给出了在 GitHub Actions 中缓存 node_modules 的办法: uses: actions/cache@v2 检查缓存特征 Key 是否存在(比如 Nodejs 就检测 package-lock.json 文件)。我在尝试过程中将两分钟的工作流成功优化到一分半,提升没有我想的那么大,但是学到了这个操作很快乐。我也在自己二次开发的一个仓库 Life-in-HEU 中使用了这一特性,引申到这个项目就是缓存 pip 模块,照葫芦画瓢检查 requirements.txt 文件。

发布 log 记录文件到分支 这个操作是从 Typecho-Theme-VOID 二次开发过程中学到的。主题自带的 Action 将构建完毕的主题文件存放在 build 文件夹下然后发布到 nightly 分支,我也照葫芦画瓢做出了将日志文件存放在 log 文件夹下然后发布到 log 分支的功能。仅需在 workflows file 中给 uses: docker://peaceiris/gh-pages:v2 添加两个环境变量 PUBLISH_BRANCHPUBLISH_DIR 即可。

此外,借助 GitHub Actions 我还告别了在 Python 中配置 SMTP 发送打卡邮件提醒,因为只需要开启 GitHub 工作流的运行提醒就好啦。

以上仅是 GitHub Actions 妙用的冰山一角,之前关注的一个博客 P3TERX ZONE 中写了挺多关于 GitHub Actions 的文章,有时间的话要去学习学习!让我想想我还有什么定时任务之类的东西能放到 GitHub 上白嫖……

哦,忘记放 GitHub 仓库链接了,monsterxcn/HEU-Checkin-COVID-19,有一说一我觉得我的 Readme 写的真好! 蛆音娘_不愧是我

唔,不过和我一个学校并关注 GitHub 项目的人似乎少得可怜,也许是我的圈子太小了,但如果不是那我就纳闷了,咱家校友不逛 GitHub 吗?我这么详细的文档写给空气看,失落


上次那篇关于 Python 打卡的 文章 下有校友 XYenon 给出了仅需用户名和密码的 Ruby 版本,代码在 Gist

代码仅 60 行,在下看完大呼“妙啊”,只要脚本代替人执行 确认信息 + 提交表单 两步就完事了。但是我不是很清楚提交的表单数据缓存在浏览器还是服务器。现有的 Python 打卡每次都将事先定义的表单数据提交一遍,不考虑缓存(视为缓存在浏览器),在 GitHub Actions 下运行起来更直白。但如果表单数据在服务器上一直都有缓存,那 Python 每次提交表单的行为看起来就有点笨了,用这个 Ruby 替换我觉得无论是在工作效率上还是 Actions 部署上都会更好。

外行看热闹,以上是我第一次看 Ruby 版的想法,但是自己实际使用之后发现不是说的这样容易的。表单的数据是访问打卡网页时服务器随页面一同发送到浏览器的。Ruby 版的代码确实代替人执行 确认信息 + 提交表单 两步,但是前提是引入了 webdrivers 并打开一个模拟的浏览器。每发送一个用户行为都耗费了很长时间,尤其是在国外服务器上运行时。这个 webdrivers 库在 GitHub Actions 上配置起来有点麻烦,每一次修改、运行 workflow、报错、打回重新修改的过程也相当繁琐。最后我找到了一个现成的可用于 GitHub Actions 的环境:ianwalter/bff-webdriver,在 jobs 中添加 service 块即可(也许可以参考下方 ruby.yml)。Ruby 这几十行的代码在 GitHub Actions 里跑起来却慢的令人捉急,Python 版跑了三十秒完成、Ruby 的一般都要七八分钟。

查看仓库当前的工作流文件:Python auto.yml / Ruby ruby.yml

我对 Python、Ruby 和 GitHub Actions 都了解非常浅,欢迎就本文提出改进建议以及错误纠正,不甚感激。

本文作者:TingleDev

本文链接:https://tingle.dev/tech/GitHub-Actions-Checkin.html

最后修订:2020 7月 3日 周五

若无特殊声明,作品默认基于 CC BY-NC-SA 4.0 协议许可,请注意遵守协议规定

tech

评论