GitHub Actions 實用參考

語言: CN / TW / HK

假設你對 GitHub Actions 已經有了最基本的瞭解。

比如,你知道下面這個配置表示當 push 到 master 分支時會觸發 action,作用是在 ubuntu 環境中把程式碼 checkout 出來,然後使用 node 12 先後執行 npm inpm run test

name: test
on:
  push:
    branches: [ master ]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v1
      with:
        node-version: 12
    - name: install
      run: npm i
    - name: test
      run: npm run test
複製程式碼

那麼接下來告訴你們一些人生的經驗總結一點感覺比較實用的操作。

修改檔案後推送回倉庫

通常使用 actions/checkout@v2 檢出程式碼。

由於環境中已經提供了 git 命令,那麼就可以修改、提交併推送回倉庫了。

GitHub Marketplace 裡肯定有提供了這種功能的 action,不過懶得找,而且還得看文件。這裡只說一下直接執行命令列的方式。

有這麼一些需要注意的地方:

可能需要修改 token

可以發現,就算是私有倉庫也可以使用 actions/checkout@v2,因為這個 action 使用的預設 token 有檢出本倉庫的許可權。但是在其他一些情況下這個 token 的許可權就不夠用了。

舉個栗子,如果 action 會新建一個 ./github/workflows/another.yaml 配置檔案,這時 push 的話會報錯:

refusing to allow a GitHub App to create or update workflow `.github/workflows/another.yaml` without `workflows` permission
複製程式碼

因為這個 token 沒有修改 workflows 的許可權。需要建立一個具有相應許可權的 Personal Access Token,並提供給 actions/checkout 使用。

建立 PAT 的過程就不細說了。另外,安全起見 PAT 需要儲存到 secrets 裡。

避免無限迴圈

很多 action 通常都會通過 push 觸發,如果 action 還能繼續觸發 push,就有可能導致無限迴圈了。

這個要根據實際需求,看是修改 action 還是修改程式碼。

需要配置 git 使用者

就是 git config --global user.email "[email protected]"git config --global user.name "name"

如果檔案沒有發生變化

理想情況是修改、提交、推送,但是或許存在一些情況,導致其實檔案沒有發生變化。如果這時執行 git commit,會提示 nothing to commit, working tree clean

注意了,這是一個報錯,意味著 action 執行失敗。

這裡提供一個自己寫的 bash 指令碼作為 workaround,只有檔案發生變化時才執行提交:

#!/bin/bash
status_log=$(git status -sb)
# 這裡使用的是 master 分支,根據需求自行修改
if [ "$status_log" == "## master...origin/master" ];then
  echo "nothing to commit, working tree clean"
else
  git add .&&git commit -m "update by github actions"&&git push origin master
fi
複製程式碼

需要執行 chmod +x 新增執行許可權。

總結一下,下面是一個可用的 action 配置檔案:

name: demo
on:
  # 這是一個由定時任務觸發的場景,不會導致無限迴圈
  schedule:
    - cron: '0 */12 * * *'
jobs:
  modify:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [10.x]
    steps:
    - uses: actions/checkout@v2
      with:
        # personal access token
        token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    # 修改檔案的操作
    - name: modify files
      run: node ./operations.js
    # 配置 git
    - name: config git
      run: git config --global user.email "[email protected]"&&git config --global user.name "name"
    # 使用上面的 sh 指令碼提交和推送
    - name: run script
      run: chmod +x ./update-repo.sh&&./update-repo.sh
    # 或者使用 git 命令
    - name: check for changes
      run: git status
    - name: stage changed files
      run: git add .
    - name: commit changed files
      run: git commit -m "update by github actions"
    - name: push code to master
      run: git push origin master
複製程式碼

操作另一個倉庫

當然也可以通過 git 命令列 clone 其他倉庫,然後這樣那樣。

需要注意的是,如果要 push,或者 clone 的是私有倉庫,就要考慮許可權的問題了,就算私有倉庫是自己的也不行。這裡只說使用 SSH 的場景。

Marketplace 裡肯定有這種 action,不過也不去找了。這裡介紹一個簡單明瞭的,這是原連結

把私鑰儲存到 secrets.ID_RSA,並新增以下配置。然後哪裡需要金鑰的時候,設定一下 SSH_AUTH_SOCK 環境變數就可以了。

- name: setup SSH keys and known_hosts
  run: |
    mkdir -p ~/.ssh
    ssh-keyscan github.com >> ~/.ssh/known_hosts
    ssh-agent -a $SSH_AUTH_SOCK > /dev/null
    ssh-add - <<< "${{ secrets.ID_RSA }}"
  env:
    SSH_AUTH_SOCK: /tmp/ssh_agent.sock
- name: clone repository
  # clone 一個私有倉庫
  run: git clone [email protected]:private/repo.git
  # 設定一下 env,就可以使用金鑰了
  env:
    SSH_AUTH_SOCK: /tmp/ssh_agent.sock
複製程式碼

部署檔案到其他伺服器

使用 ssh-deploy,不多說了。

示例:

- name: deploy
  uses: easingthemes/[email protected]
  env:
    SSH_PRIVATE_KEY: ${{ secrets.ID_RSA }}
    ARGS: "-avzr --delete"
    SOURCE: "dist/"
    REMOTE_HOST: "server ip"
    REMOTE_USER: "root"
    TARGET: "/home/webroot/dist"
複製程式碼

切換工作目錄

如果要執行的操作都是在一個子目錄下的,可以直接把預設的工作目錄切換到該目錄下。

name: build
on:
  push:
    branches: [ master ]
defaults:
  run:
    working-directory: client
jobs:
  # 現在預設目錄是 ./client 了
複製程式碼

注意,如果在一個 step 中 cd 到某個目錄下,那麼後續的 step 是不受影響的,還是在原來的目錄中。

想問一下有沒有辦法使得切換工作目錄之後一直有效?