個人サイトにメモを書き続けていましたが、知見が溜まってきたのでこちらでも共有することにしました。
About
GitHubのリポジトリに対してCI/CD等のワークフローを自動実行できるサービス。
2019年11月に正式リリースされた。
Documentation
- Workflow syntax for GitHub Actions - GitHub Help
-
Virtual environments for GitHub-hosted runners - GitHub Help ...
runs-on
でサポートされている実行環境 -
Context and expression syntax for GitHub Actions - GitHub Help ...
${{ <expression> }}
形式でYAMLに埋め込める式表現とか、if: ${{ <expression> }}
によるガード条件について
既知の制限事項
2020-05-03更新
- ビルドを手動トリガーするネイティブ機能がない
- 2020-05-03に調べたログ
- ※ワークアラウンドは可能
- YAMLアンカーがサポートされていない
- デフォルトでは公式のSlackインテグレーションで、ビルド結果通知を受け取れない。
- 該当するfeatureがない
- 3rd Partyのactionを使えば可能。incoming webhookと組み合わせる
- プルリクエストに紐付いたビルドの結果はわかるようだ
Getting Started
https://github.com/actions/starter-workflows ... 初心者向けワークフローサンプル集
アクションについて
アクションは、ワークフロー内で実行される個々のタスク。
Marketplaceで公開したり、公開されたアクションを利用することができる。
下の個人サイトに専用ページを設けているが、ここでは詳細は省く。
Workflowの作成
NOTE:
- プロジェクトの
.github/workflows/
ディレクトリ下にYAMLファイルを作成する - pushをトリガーにしたり、定期的に実行したりできる
プルリクエストで実行する
任意のプルリクエストでtestを実行し、masterブランチへのマージでのみdeployを実行する設定例(2ファイル):
# test.yml
name: test
on: pull_request
jobs:
test:
runs-on: ubuntu-latest
steps:
# tasks for testing
---
# deploy.yml
name: deploy
on:
pull_request:
branches:
- master
types: [closed]
jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ github.event.pull_request.merged == true }}
steps:
# tasks for deployment
NOTE:
- デフォルトでは
pull_request
eventではtypes: [opened, synchronize, reopend]
でしか実行されない。test
のときはこれになっている。
参考:
- Solved: Re: Trigger workflow only on pull request MERGE - GitHub Community Forum ... Solutionは間違ってるので注意
定期的に実行する
crontabと同じ書式でワークフローを定期実行するタイミングを指定することができる。
Example:
on:
schedule:
# JSTで月曜から金曜の9:05 - 17:05の間、2時間毎に実行
- cron: '5 0-8/2 * * MON-FRI'
NOTE:
- cronのタイムゾーンはUTCなので注意
リファレンス:
対象branchやpathをフィルタする
Example:
on:
push:
branches:
- master
- 'releases/**'
- '!releases/**-alpha' # alpha版は含めない
tags:
- v1
# file paths to consider in the event. Optional; defaults to all.
paths:
- 'test/*'
paths-ignore:
- 'docs/**'
NOTE:
-
branches
とbranches-ignore
は併用不可 -
tags
とtags-ignore
は併用不可 -
paths
とpaths-ignore
は(たぶん)併用可
リファレンス:
- branchやtagについて -> on.<push|pull_request>.<branches|tags>
- pathについて -> on.<push|pull_request>.paths
複数の実行環境に対応する
複数のOSプラットフォームや、ランタイムのバージョンに対応する方法。
下のようなbuild matrixを設定すると良い。
Example:
jobs:
node-test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-16.04, ubuntu-18.04]
node: [6, 8, 10]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}
NG例:
runs-on: [ubuntu-16.04, ubuntu-18.04]
リファレンス:
参考:
Dockerコンテナ上でビルド実行
jobs.<job_id>.container
で指定する。
Examples:
jobs:
my_job:
container: node:10.16-jessie
---
jobs:
my_job:
container:
image: node:10.16-jessie
env:
NODE_ENV: development
ports:
- 80
volumes:
- my_docker_volume:/volume_mount
options: --cpus 1
starter-workflowsにも参考になるサンプルがある。以下は例:
環境変数を設定する
いくつかの箇所で設定できる。それぞれ適用範囲が異なる。
設定位置 | 適用範囲 |
---|---|
env |
for all jobs and steps |
jobs.<job_id>.env |
for all steps in the job |
jobs.<job_id>.steps.env |
for the step |
jobs.<job_id>.container.env |
for the container to run steps in the job |
Examples:
env:
SERVER: production
---
jobs:
my-job:
name: My Job
runs-on: ubuntu-latest
env:
MY_VAR: Hi there! My name is
steps:
- name: Print a greeting
env:
FIRST_NAME: Mona
MIDDLE_NAME: The
LAST_NAME: Octocat
run: |
echo $MY_VAR $FIRST_NAME $MIDDLE_NAME $LAST_NAME.
See also #変数やシークレットの利用
jobやstepを特定の条件で実行する
jobs.<job_id>.if
や jobs.<job_id>.steps.if
の値に条件式を記述することで、該当のjobやstepを条件が真のときのみ実行することができる。
Examples:
jobs:
deploy:
# プルリクエストがマージされた時のみ実行
if: ${{ github.event.pull_request.merged == true }}
steps:
- name: Deploy
# some deploy action
# このstepは常に実行する
- name: Notify
if: ${{ always() }}
# some notify action
# ジョブ失敗時に実行するstep
- name: Clean up on Failure
if: ${{ failure() }}
# some clean up action
NOTE:
-
if:
に渡す条件式では${{ }}
は省略可能 - ワークフロー内でタスクが失敗すると、デフォルトでは後続のタスクはスキップされる
- 後述のリファレンスに下の記述がある:
A job or step will not run when a critical failure prevents the task from running. For example, if getting sources failed.
リファレンス:
参考:
変数やシークレットの利用
Documents:
GITHUB_TOKENによる認証
Authenticating with the GITHUB_TOKEN - GitHub Help
GitHubは、ワークフローで利用する
GITHUB_TOKEN
シークレットを自動的に生成します。 このGITHUB_TOKEN
は、ワークフローの実行内での認証に利用できます。
How-to
Workflow内でgit commit & push
ユースケースの例:
- コードフォーマッタや、静的解析による修正を自動実行する
- ビルドしたアーティファクトを追加する
checkoutアクションでチェックアウトしたものと同じリポジトリであれば、そのままpushできるようだ。
Example:
jobs:
update:
steps:
- uses: actions/checkout@v2
- run: |
git config --global user.name "Your Name"
git config --global user.email "your-address@example.com"
./do-something.sh
git add .
git commit -m "Update by GitHub Action"
git push
checkoutアクションではデフォルトで ${{ github.token }}
が使われており、これにリポジトリへの書込み権限もついているからだろう。
git commit & pushを行うActionもある:
参考:
別ブランチを更新するには
権限は ${{ github.token }}
で十分なので、上と同様にcheckoutアクションを使って、オプションで別ブランチをチェックアウトして更新を行えばよい。
Example:
jobs:
publish:
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v2
with:
ref: gh-pages
path: public
- run: |
git config --global user.name "Your Name"
git config --global user.email "your-address@example.com"
make build
cd public
git add .
git commit -m "Update by GitHub Action"
git push
上の設定自体は試してないが、やり方的には合っているはず。
個人プロジェクトのprogrhyme/binq-indexではこのやり方を取っている。
Workflow内でパッケージインストール
Ubuntuだったら単純に sudo apt install <package>
を run
すればいい。
jobs:
install-zsh:
runs-on: ubuntu-latest
steps:
- run: sudo apt install zsh
- run: zsh --version
参考:
-
Virtual environments for GitHub-hosted runners - GitHub Help ... 特権の必要な操作には
sudo
が使えるよと書いてある - How to apt-get install in a GitHub action? - Stack Overflow