假設你對 GitHub Actions 已經有了最基本的瞭解。
比如,你知道下面這個配置表示當 push 到 master 分支時會觸發 action,作用是在 ubuntu 環境中把程式碼 checkout 出來,然後使用 node 12 先後執行 npm i
和 npm 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 是不受影響的,還是在原來的目錄中。
想問一下有沒有辦法使得切換工作目錄之後一直有效?