GitHub

通过GitHub Actions实现自动爬取Bing壁纸并保存

由于Bing每天的壁纸都很好看,所以我想每天都保存一下当天的壁纸,供以后看。但是因为人工操作总会有各种问题,遗忘、误操作等,就存在会遗漏的情况。当然还有另外一个情况,就是懒,不想每天去执行,程序员不应该做这种无趣的事情。

附上项目地址

随机图片

壁纸爬取程序的发展历史

通过Python,每次电脑开机时爬取最新的7天壁纸

缺点:

  • 如果电脑有7天没开机,那么就会至少丢失一天的壁纸
  • 通过打包程序打包成一个EXE程序,每次开机时会弹窗,影响开机使用体验,不知道的还以为中毒了

通过Java,写一个SpringBoot程序,跑在常年开启的主机上,通过定时任务爬取最新的7天的壁纸

缺点

  • 主机长期开机,存在不确定的问题。
  • 可能会有网络、系统不大稳定的情况,导致保存失败

通过JavaGithub Actions,依托于Github的高可用性,以及Github的网络环境,通过定时任务自动保存壁纸

这是第一个版本,虽然达到了标题的目的,但是有一个很明显的痛点,就是因为每次都是拉取仓库,然后执行程序,然后提交并推送变更。由于仓库较大且后续可能会变得更大,每次任务的执行时间会变得越来越长,目前已经需要执行10分钟+

新的思路

  1. 创建两个分支,一个是保存图片的分支(main),一个是保存代码的分支(code)
  2. 执行时拉取并签出code分支,然后打包、编译、执行。这样就会在本地产生变更
  3. 将变更提交并推送到一个非main/code分支的一个临时分支(pr-branch)
  4. 创建一个Push Request,由pr-branch分支到main分支
  5. 自动合并合并请求

分析

原先的时间较长的版本已经完成了第一步和第二步,比较复杂的就是提交到临时分支,创建PR请求,然后自动合并PR请求

实操

  • 提交到临时分支
    - name: Push changes
      uses:  ad-m/github-push-action@master
      with:
        github_token: ${{ secrets.MY_GIT_TOKEN }}
        branch: pr-branch
        force: "true"

    在原先推送的基础上指定一下分支即可

  • 创建PR请求

最开始的时候找到的action是peter-evans/create-pull-request@v6,这个方法确实可以创建PR请求,并且把上一步推送也进行了合并,直接2合1,但是有一个缺点,他是在本地通过Git命令进行分支合并,同样需要签出main分支,那结果还是一样的慢。

# 最开始的版本
    - name: Create pull request
      id: cpr
      uses: peter-evans/create-pull-request@v6
      with:
        base: main
        branch: pr-branch
        commit-message: update resources
        title: update resources
        body: update resources

当我还在想是不是有别的方法的时候,我发现通过Github的界面可以直接创建PR,且速度很快,不需要签出分支等杂七杂八的操作,然后就往这个方面去思考,最后找到了actions/github-script@v6。这个action其实就是对github的api的一些封装,通过方法并指定函数来请求api。这里还给PR打上了automerge标签,目的是为了区分action创建的PR和自己创建的PR,避免搞混了

    - name: Create Pull Request
      id: cpr
      uses: actions/github-script@v6
      with:
        script: |
          const { repo, owner } = context.repo;
          const result = await github.rest.pulls.create({
            title: 'pr-title',
            owner,
            repo,
            head: 'pr-branch',
            base: 'main',
            body: 'pr-body'
          });
          github.rest.issues.addLabels({
              owner,
              repo,
              issue_number: result.data.number,
              labels: ['automerge']
          });
          return result.data.number
  • 自动合并请求
    - id: automerge
      name: automerge
      uses: "pascalgn/automerge-action@v0.16.3"
      env:
        GITHUB_TOKEN: "${{ secrets.MY_GIT_TOKEN }}"
        MERGE_DELETE_BRANCH: "true"
        PULL_REQUEST: ${{ steps.cpr.outputs.result }}

    很轻松的找到了这个指令,但是不能确定应该自动合并的是哪一个请求,发现上一步最终可以返回一些自定义的结果信息,且这个接口有返回创建的PR Number。所以又要回到上一步,在返回的地方添加了PR Number,并在这一步指定,直接合并。为了避免分支的异常,还在合并之后删除原分支