GitHub Actions で学ぶシェル芸
GitHub Actions は run
でシェルを実行していくのが基本です。
シェルに詳しければサードパーティアクションを使わなくて済んだり[1]、複雑なロジックを組まずに済んだりするので、改めてシェルを学ぶきっかけにいいのではないかと思いました。
ネタ募集。
-
サードパーティアクションを使用するとセキュリティへの配慮が必要だったり、 Enterprise だと GitHub Connect の設定をしたり actions-sync したりしないといけなかったりするので意外と面倒です ↩︎
主に Bash を扱いますが shell
を指定することもでき、 PowerShell や Python も使えます。
- run: echo shell
shell: bash
変数展開
結構色々できます。
具体例 1
文字列の一部を除去。ブランチ名を取得。
branch-name
でも refs/heads/branch-name
でも branch-name
が返ってきます。
- run: git switch -C ${GITHUB_REF#refs/heads/}
具体例 2
大文字を小文字へ変換。
- name: Build
run: docker build -t ghcr.io/${OWNER,,}/texturepacker:${VERSION} .
env:
OWNER: ${{ github.repository_owner }}
VERSION: ${{ matrix.version }}
ファイルへの書き込み
具体例
- name: 単行
run: echo "line" > one-line.txt
- name: 複数行
run: |
cat <<<EOF > multi-line.txt
line1
line2
EOF
GitHub API
GitHub CLI を使うとシンプルに書けます。
具体例
Pull request (PR) へコメント。
- run: gh pr comment --body "Comment via GitHub Actions"
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
代替可能なアクション
actions/github-script
- uses: actions/github-script@v4
with:
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Comment via GitHub Actions'
})
octokit/request-action
- uses: octokit/request-action@v2.x
with:
route: POST /repos/{repository}/issues/{issue_number}/comments
repository: ${{ github.repository }}
issue_number: ${{ github.event.number }}
body: Comment via GitHub Actions
env:
GITHUB_TOKEN: ${{ github.token }}
ディレクトリがなければ作る
mkdir
の -p
オプションを使うと if を書かずに済みます。
具体例
- run: mkdir -p path/to/
- run: pwd
working-directory: path/to/
jq
具体例
TODO: 思いついたら書く
if
具体例 1
空文字列の判定。
- name: 差分があったらエラー
run: |
DIFF=$(git diff --name-only)
if [ -n "$DIFF" ]; then
exit 1
fi
具体例 2
exit code で判定。
- name: 差分があったらエラー
run: |
if ! git diff --exit-code --quiet; then
exit 1
fi
- name: 差分があったらエラー
run: |
git diff --exit-code --quiet
if [ $? -ne 0 ]; then
exit 1
fi
zcat, zgrep
圧縮されたファイルのまま cat
や grep
をすることができます。
具体例
TODO: 思いついたら書く。
git grep
Git 管理下のファイルを grep
できます。
具体例
TODO: 思いついたら書く。
一定時間待機
sleep
コマンドが使えます。
秒数を指定しますが suffix を付けることもできます。
具体例
- run: sleep 90
- run: sleep 1m 30s
条件で待機
while
を使うことが多いかもしれませんが until
コマンドもあります。
while
の反対で条件式の終了コードが 0
ではない間ループします。
具体例
Docker コンテナが起動するまで待機。
- run: |
until [ "$(docker inspect --format='{{.State.Health.Status}}' $(docker-compose ps -q mysql))" = 'healthy' ]; do
sleep 1s
done
絶対パスを取得
realpath
はシンボリックリンクを展開して絶対パスを返します。
具体例
- run: realpath "${PATH_TO}"