如何使用

点击这里这个仓库提交一个 issue.

issue 的标题是你要执行的 docker pull 命令, 内容不需要写。

几分钟后,在这个 issue 下会收到一个包含下载链接的评论。

点击这个链接即可下载镜像到本地。

执行 docker load < xxx.tar.gz 即可加载镜像。

如何实现

issue 标题作为下载镜像的命令,Actions 获取到 issue 的标题后执行命令下载 Docker 镜像,然后上传到 Onedrive 网盘上。

上传工具使用 rclone,这样就可以避免自己写代码和 Onedrive API 交互。

直接 rclone copy 即可。

最后,使用 GitHub API 为 issue 发送一个评论,包含下载链接。

name: Docker Pull
on:
  issues:
    types: [opened] # 只有 issue 被打开时触发

jobs:
  new-issue-job:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v2

      - name: Docker Pull
        run: |          
          sudo -v; curl https://rclone.org/install.sh | sudo bash # 安装 rclone
          rclone version
          issue_title="${{ github.event.issue.title }}" # 获取 issue 标题
          issue_number="${{ github.event.issue.number }}" # 获取 issue 编号
          if [[ $issue_title =~ ^docker\ pull\ (.+)$ ]]; then # 正则匹配 issue 标题,应该以 docker pull 开头
            echo "Issue title is valid."
            $issue_title # 执行 docker pull 命令
            image_name="${BASH_REMATCH[1]}" # 获取镜像名
            save_image_name=${image_name//[:\/]/_} # 替换镜像名中的 : 和 / 为 _ , 用于保存文件名
            docker save $image_name | gzip > ./$save_image_name.tar.gz # 保存镜像
            rclone copy ./$save_image_name.tar.gz E5:/DockerPull/$issue_number/ # 上传到 Onedrive
            gh issue comment ${{ github.event.issue.number }} -b "Docker image has been pulled and uploaded to E5. Please download it from the following link: https://e5.1881997.xyz/DockerPull/$issue_number/$save_image_name.tar.gz" # 为 issue 发送评论
          else
            echo "Issue title is invalid."
            exit 1
          fi
        shell: bash
        env:
          RCLONE_CONFIG_PASS: ${{ secrets.RCLONE_CONFIG_PASS }} # rclone 配置文件的密码
          GH_TOKEN: ${{ secrets.PAT }} # GitHub token, 用于发送评论。GitHub Actions 的默认 token 无法发送评论,需要自己生成一个有权限的 token
          RCLONE_CONFIG: ./config/rclone.conf # rclone 配置文件路径

整体实现非常简单,只需要几行代码。

再简单解释一下这里面可能会令人疑惑的两个地方:

  1. rclone copy 是如何上传到我的 Onedrive 的?

这里需要首先在本地配置好 rclone,然后将配置文件进行加密,上传到 GitHub 仓库中。

https://github.com/WANG-Guangxin/DockerPull/blob/master/config/rclone.conf

这里是我的 rclone 配置文件,里面包含了我 Onedrive 的配置信息。

RCLONE_CONFIG 环境变量用于指定 rclone 配置文件的路径。

RCLONE_CONFIG_PASS 环境变量用于指定 rclone 配置文件的密码。这个环境变量需要用 secrets 存储。

这两个环境变量在 Actions 的 yaml 中,当执行 rclone copy 时,会自动解密配置文件,然后上传。

2. https://e5.1881997.xyz/DockerPull/$issue_number/$save_image_name.tar.gz 是如何生成的?

https://e5.1881997.xyz 其实是我搭建的一个网盘列表程序,我用的是 OneManager-php

我曾经在这篇文章 中介绍过这个程序。

至于后面的路径,就是 issue 编号和镜像名,这样就可以保证每个 issue 的镜像都是唯一的。

只要保证上传和下载的路径一致,就可以了。

可能的扩展

  1. 只有 star 了这个仓库的人才能使用

下面是一个可能的方案,但还未经测试。

- name: Check if user starred the repo
  run: |
    user="${{ github.event.issue.user.login }}"
    repo="${{ github.repository }}"
    starred=$(curl -H 'Authorization: token ${{ secrets.GITHUB_TOKEN }}' https://api.github.com/user/starred/$repo | grep -c "$user")
    if [ "$starred" -eq "0" ]; then
      echo "User has not starred the repo, aborting."
      exit 1
    fi
  1. 删除过早的镜像

同样也是未经测试的代码。


issue_number="${{ github.event.issue.number }}"
issue_number_minus_ten=$((issue_number - 10))

if rclone lsf E5:/DockerPull/$issue_number_minus_ten/ > /dev/null 2>&1; then
    rclone delete remote:path
else
    echo "Path does not exist, skipping."
fi

最后

目前只有两个人使用过这个机器人,有一个人 fork 了这个仓库,但实际上仅仅 fork 这个仓库是无法使用的。

有兴趣的话可以参考这篇文章自己实现一个。

但实际上用我的就够了,希望使用的用户给个 star ⭐