在 wps-office
因为分发许可的原因移出 archlinuxcn
源之后,自建一个 arch repo
的需求就越来越强烈,我之前也搞过 github action
来打 archlinux
的包,但并不能完全满足我的需求,于是我准备大刀阔斧改上一波,并写点脚本辅助自动化打包流程。
这篇文章可能会有点长,因为我打算把我的踩坑过程也写进去,没时间看的可以直接到文末我的仓库链接查看具体实现。
1 需求分析
需求 | 预计解决方案 |
---|---|
定时打包 | github action cron |
打完的时候通知 | telegram bot api |
能够打有依赖在 AUR 的包 | aur helper yay |
打自己修改过的 PKGBUILD |
保证目录形式以兼容 aurpublish ,以文件夹的形式上传 |
有一个 web 页面提供单独的下载,因为用户不一定都愿意导入你的 key |
目前选用keybase |
2 具体思路
首先想到的当然是依云写的 lilac 啦,但我看了看,貌似远远高于我的需求,我只是想打几个类似于 wps-office 这样的包应该用 github action 就能搞定,不过完全可以借鉴思路。
这里顺便提一下两位群友的方案:GitHub Actions 打造 AUR 打包下载一条龙服务 和 利用 GitHub Actions 编译 AUR 包并建立自己的软件源,我接下来的操作和他们有很大的相似之处,只有一些具体细节并不相同。
2.1 解决 docker 权限问题
makepkg
和 yay
因为安全原因不允许在 root
下运行。这是有点糟心的,docker
默认不就是 root
么,群友 DuckSoft 提供了一个 dirty hack
来让 makepkg
在 root
下运行
sed -i '/E_ROOT/d' /usr/bin/makepkg
这下好了,可以打没有依赖在 AUR
的包了,就像下面三行就完事了
# entrypoint.sh
git clone "https://aur.archlinux.org/$1.git"
cd "$1"
makepkg -sf --noconfirm
但是 yay
还是不能在 root
下运行,于是乎想到新建一个没有密码的普通用户然后通过解析 .SRCINFO
来递归安装依赖,这是 edlanglois/pkgbuild-action 的做法。
# Extract dependencies from .SRCINFO (depends or depends_x86_64) and install
mapfile -t PKGDEPS < \
<(sed -n -e 's/^[[:space:]]*\(make\)\?depends\(_x86_64\)\? = \([[:alnum:][:punct:]]*\)[[:space:]]*$/\3/p' .SRCINFO)
sudo -H -u builder yay --sync --noconfirm "${PKGDEPS[@]}"
我具体看了看他的实现,感觉做法过于复杂了,而且在 root
下采用 sudo -u
还要额外考虑传递环境变量的问题。难道就没有一个内置 yay
并默认是普通用户的 docker
上游吗?
嗯,终于等到你 martynas/archlinux,它内置了 yay
用来构建 AUR
包并且有个默认的名为 build
的 passwordless
用户,事情瞬间变得简单多了,这里是我写的 pkgbuild-aur。
2.2 同时管理自己修改过的 PKGBUILD 和 AUR
为了能够同时方便的使用 aurpublish
来管理我自己手里的 AUR
包,我采用了以下的目录要求
# there should be a subdirectory with the same name of pkgname to satisfy `aurpublish`
if [[ ! -d $pkgbuild_dir ]]; then
echo "$pkgbuild_dir should be a directory."
exit 1
fi
if [[ ! -e $pkgbuild_dir/PKGBUILD ]]; then
echo "$pkgbuild_dir does not contain a PKGBUILD file."
exit 1
fi
if [[ ! -e $pkgbuild_dir/.SRCINFO ]]; then
echo "$pkgbuild_dir does not contain a .SRCINFO file."
exit 1
fi
需要在项目根目录下放置与包同名的文件夹,同时里面要包含 PKGBUILD
和 .SRCINFO
,后者是 AUR web
的必须要求同时也用来解析依赖,可以通过 makepkg --printsrcinfo > .SRCINFO
来生成。
同时要注意最好先改一下目录权限,据说 /github/workspace
默认 owner
是 root
,所以推荐如下改动。
# fix directory permissions
sudo chown -R build "$pkgbuild_dir"
sudo chown -R build /github/home
2.3 定时打包以及完成之后通知我
首先 github action
就支持 cron
定时,详见文档,作为一名良心资本家,我允许它周末休息,遵循 996
每天只干两次活。
on:
push:
branches:
- master
schedule:
- cron: '0 9,21 * * 1-6' # build pkgs via 996 rules (;′⌒`)
workflow_dispatch: # allow manual trigger
当然我开启了每次 push
运行和手动开启运行 CI
以便随时压榨(
github action
失败的话会有邮件提醒,但为了维护自己的个人源在 build
成功的时候我也需要提醒。这时候 oldherl 提醒了我,为什么不试试 telegram bot api
呢?这着实是个好主意,我翻查了一下文档,究极简单,以后提醒不用邮件了,全改用 telegram
,顺便推荐比较完善的 telegram-action。
2.4 打包之后的存放位置
首选当然是 github release
啦,我预想是将 github release
当成一个 archive repo
,里面存放着前几个版本的包。Arch 是滚动更新的,自己的个人源自然只放最新的版本包,我目前选用的是 keybase
,因为它提供 250 G 免费直链网盘和一个免费二级域名(这不就巧了么,正好符合需求),于是我写了个 repo-helper 方便使用
#!/usr/bin/bash
# Usage:
# ./repo-helper add <pkg_file_name> # add package
# ./repo-helper remove <pkgname> # remove package
# ./repo-helper list # list packages in repo
# ./repo-helper pull # download packages from personal github release
repo_name="zjuyk"
repo_ext=".db.tar.gz"
repo_dir="/run/user/1000/keybase/kbfs/public/$repo_name/x86_64/"
github_release_url="https://api.github.com/repos/zjuyk/repo/releases/latest"
db_path=$repo_dir$repo_name$repo_ext
case $1 in
pull)
echo "Pull update from github release..."
curl -s $github_release_url | \
grep browser_download_url | \
cut -d : -f 2,3 | \
tr -d \" | \
xargs -n 1 curl -O -sSL -o $repo_dir -C -
repo-add $db_path $repo_dir/*.zst --remove --sign --quiet
index-generator --human $repo_dir
echo "Done!"
;;
add)
echo "Add $2 to $repo_name..."
mv -n ./$2 $repo_dir
repo-add $db_path $repo_dir/$2 --remove --sign --quiet
index-generator --human $repo_dir
echo "Done!"
;;
remove)
echo "Remove $2 from $repo_name..."
repo-remove $db_path $2
index-generator --human $repo_dir
echo "Done!"
;;
list)
ls $repo_dir/*.zst | sed 's/-x86_64.pkg.tar.zst//g' | awk -F "/" '{print $NF}'
;;
*)
echo "args should be one of 'pull', 'add', 'remove' and 'list'!"
esac
脚本中的 index-generator 是 兔兔 他们在几年前用 Jinja
写的,我打算有时间的话用 rust
的 tera 库重构一个。
2.5 维护更新
说到检查版本首先想到的就是依云的 nvchecker 写个配置文件跑一跑,然后改一下包信息就完事了
# bump pkg version in PKGBUILD
# update checksums
$ updpkgsums
# update .SRCINFO
$ makepkg --printsrcinfo > .SRCINFO
3 不足与改进计划
-
因为
keybase
非常注重安全性,所以我没办法直接从github
将产物推到keybase
上(也许可以,但也会十分复杂,需要专用的工具)。这导致我目前只能半自动化,需要手动pull release
到运行着keybase
的机器上同步。虽然可以定时运行,但keybase
本身的运行会占用一定的资源,我正在考虑是否直接塞到(属于对github repo
里然后开github pages
github
的究极滥用,实际上我不会考虑这么做) -
ArchLinux
除了x86_64
架构外还额外划分了any
,这个我目前没有考虑,因为目前我并没有维护any
的包,或许以后会加入 -
同步是需要消耗流量的,出于未来保留若干版本包用于回滚的考虑,我目前是用
api
把所有的release
全下下来了,没有做筛选,如果代理流量不够的话建议开一个cloudflare worker
做反代