GitHub Actions以前調べたのですが、いろいろあって個人プロジェクトでサクッとビルドするのみに使っていました。 今回改めて調べを進めたのでメモ。
幾つかのリポジトリをGitHub Actionsに移行したけど、記事にしようとまとめていたらやった内容以上に調べてめちゃめちゃ時間かかった。
TL;DR
- とりあえず公式ドキュメント読めばok
- 公式ドキュメントにないのはだいたいフォーラムみればok
- 基本はAzure pipelineだけど、結構使いやすい感じになってる
- Azure Pipelinesと違って、stepのnameを省略するとコマンドがそのまま表示されるのでnameは基本省略で行ける。 (これ重要)
- public repoならGithub Actionsもいい感じ。WindowsやmacOS依存はこっちに移植する
- private repoは、GitHubを新料金プランにしているか次第。CircleCIのPerformance Planのユーザー課金が納得いかないのでこっちに移行していきたい
- クラウドホストランナーが基本でよさそうだけど、Kubernetes上でのCDを考えるとセルフホストわんちゃんある
- AppVeyorでやってたことはほぼ移行できる
- CircleCIもだいたい行ける。Orbだけ代替あるかが問題になるぽ
トレンド
GitHub Actionsの今のスタイルがブログでアナウンスされた2019/Aug/8ぐらいからトレンド上がってるんですね。
GitHub Actions の基本
基本的な情報を裏取りする。
使用条件
- Orgは新GitHub Pricingに移行していること (旧プランの場合Actions自体使えない)
旧プランで使えないのは、最近のGitHubの新サービスによくあることですが、なるほど困るケース結構多いです。
旧プランと新プランは、リポジトリ数課金or人数課金の違い。 小規模な会社で30リポジトリ100ユーザーとかだと、新旧で桁が違うレベルで料金が変わるため移行に踏み切れないのはままある。
- 旧プランは、人数無制限、リポジトリ数で段階的なプラン選択
- 新プランは、人数課金、リポジトリ数制約なし
旧プランのほうがお得なケースは多数あってなかなか新プランに移行が難しいケースも見かけるので難しい。とはいえ、新プラン一択でしょう。
使用制限
並列数やAPI、実行時間で制限がある。
Usage limits, billing, and administration
- 1リポジトリあたりの同時並列は20(Free)、40(Pro)、60(Team)、500(Enterprise)
- 1時間当たりリポジトリの全アクションで1000 APIリクエスト
- ワークフローは実行時間6時間が上限 (指定しないと6時間たつまでタイムアウトしないので長すぎ)
- 無料、有料で同時実行上限がある
GitHub plan | Total concurrent jobs | Maximum concurrent macOS jobs |
---|---|---|
Free | 20 | 5 |
Pro | 40 | 5 |
Team | 60 | 5 |
Enterprise | 500 (以前は180) | 50 (以前は15) |
マイニングがダメとかその辺は当然あるので見ておきましょう。 Serverless Computingがダメなのもそれはそうなんだけど、いい感じにやってみた的にやりそうな人も出てきそうなので規約でしばるのでいいですね。
料金
OSSは無料で並列度高いので気軽に利用できていい感じ。CircleCIより緩くてAzure PipelineやTravis並みに楽。
会社などPrivate Repoだと、Teamでも3000min/month (旧:10000min/month) しかつかないので、十分ではなく追加購入必要になる感じ。
従量課金の体系はシンプルで、GitHubユーザー課金ある前提と合わせて追加なので、もともとGitHub使ってたこと考えるとCircleCIのPerformance Planより納得度は圧倒的にある。だからこそ新料金プランに限定するんでしょうが。
- パブリックリポジトリ : 無料
- プライベートリポジトリ : 含まれる利用時間 + 追加購入
含まれる利用時間
利用時間は毎月リセットされるけど、ストレージはリセットされない。
2020/4/13までは以下でしたが、2020/4/14~ 変更になりました。
~2020/4/13プラン | 1か月あたり利用時間 | ストレージ |
---|---|---|
Free | 2,000分 | 500 MB |
Pro | 3,000分 | 1 GB |
Team | 10,000分 | 2 GB |
Enterprise | 50,000分 | 50 GB |
2020/4/13~プラン | 1か月あたり利用時間 | ストレージ |
---|---|---|
Free | 2,000分 | 500 MB |
Team | 3,000分 | 2 GB |
Enterprise | 50,000分 | 50 GB |
GitHub One | 50,000分 | 50 GB |
利用時間的には、GitHub Team が 旧Pro 相当になった感じ。
ストレージ価格がおもむろに出てきたけど、publicは無料。 privateの場合に、アカウントの持つGitHub packagesとGitHub Actionsアーティファクトの利用合計らしい。 制限を超えてアカウントが利用していて、$0を超えるLimit spendingを設定していると料金がかかるので注意がいりそう。 そんなに大きなサイズのArtifactを設定するなという話なのですが、要注意。
アカウント > Settings > Billing > Cost management > Limit spending で設定できる。デフォ $0
ビリングのstorageに関してを見ておくほうがよさそう。ちょっと細かいので随時確認するといいでしょう。
About billing for GitHub Actions
OS別時間消費
Linuxを1として、WindowsやmacOSは利用時間の倍率がついているという考え。
Operating system | Minute multiplier |
---|---|
Linux | 1 |
macOS | 10 |
Windows | 2 |
追加購入
倍率に応じてなので、結果としてOS別に価格差が生じる。
Windows高いです。 macOSの価格は10倍なので課金するならセルフホストをまず検討したほうがいいでしょう。
ホストランナー | vCPUs | 料金 |
---|---|---|
Linux | 2 | $0.008 1分あたり |
Linux | 4 | $0.016 1分あたり |
Linux | 8 | $0.032 1分あたり |
Linux | 16 | $0.064 1分あたり |
Linux | 32 | $0.128 1分あたり |
Linux | 64 | $0.256 1分あたり |
Windows | 2 | $0.016 1分あたり |
Windows | 4 | $0.032 1分あたり |
Windows | 8 | $0.064 1分あたり |
Windows | 16 | $0.128 1分あたり |
Windows | 32 | $0.256 1分あたり |
Windows | 64 | $0.512 1分あたり |
macOS | 3 or 4 (M1 or intel) | $0.08 1分あたり |
macOS | 12 | $0.12 1分あたり |
macOS | 6 (M1) | $0.16 1分あたり |
セルフホスト | - | Free |
料金例
5,000 (3,000 Linux and 2,000 Windows) minutes = $56 USD ($24 USD + $32 USD).
- 3,000 Linux minutes at $0.008 USD per minute = $24 USD
- 2,000 Windows minutes at $0.016 USD per minute = $32 USD
ホストランナーの指定
GitHub ActionsはAzure Pipeline同様にホストランナー1をどこで実行するか選択できる。
GitHub ホステッド ランナーの概要 - GitHub Docs
マネージド、セルフホストの選択
ホストランナーはマネージド、セルフホストが選択できる。
- GitHubホストランナー :マシンメンテナンス、アップグレードがマネージドに提供される
- セルフホストランナー : 物理、仮想、コンテナ、オンプレミス、クラウドに自分でインストールする
通常はクラウドホストランナー (GitHubが提供するホスト) を選ぶし、それが最も手早く楽。
セルフホストランナーは既にビルドを実行する環境がある、けどビルドの管理をしたくない、何かしらマシンに事前インストールが必要など融通をきかせたいときに便利。ようはAzure PipelineのSelf Hosted Agentと一緒ですし、Jenkinsのようなものです。
例えば、自分たちのKubernetesクラスターにセルフホストランナーを入れてビルドをすることで、クラスターの認証への考慮を減らしてクラスターへのデプロイできる。あるいは、クラウド上のVMに導入することで、クラウド認証を減らしてデプロイできます。
発表当時は、actions-runner-kubernetesは個人プロジェクトでしたが、2024年現在は公式リポジトリになっています。チュートリアルもあります。
アクション ランナー コントローラーのクイック スタート - GitHub Docs
本記事では個人のプロジェクトで考えるので、ここではGitHubホストランナーを前提としてみていく。
ハードウェアリソース
GitHubホストランナーはAzure VM上で動作するのでスペックはVMと同じで素直です。
2024年1月17日にパブリックリポジトリのVMは4CPUへ機能強化されました。ブライベートリポジトリは2 CPU(発表当時、Standard DS_v2相当)のままです。
パブリックリポジトリの性能は次の通り。
- 4コアCPU
- 16GBのRAMメモリー
- 14GBのSSDディスク容量
Virtual Machine | Processor (CPU) | Memory (RAM) | Storage (SSD) | OS (YAML workflow label) | Notes |
---|---|---|---|---|---|
Linux | 4 | 16 GB | 14 GB | Ubuntu-latest, Ubuntu-22.04, Ubuntu-20.04 | The Ubuntu-latest label currently uses the Ubuntu 22.04 runner image. |
Windows | 4 | 16 GB | 14 GB | windows-latest, windows-2022, windows-2019 | The windows-latest label currently uses the Windows 2022 runner image. |
macOS | 3 | 14 GB | 14 GB | macos-latest, macos-12, macos-11 | The macos-latest workflow label currently uses the macOS 12 runner image. |
macOS | 4 | 14 GB | 14 GB | macos-13 | N/A |
macOS | 3 (M1) | 7 GB | 14 GB | macos-14 (Beta) | N/A |
プライベートリポジトリの性能は次の通り。
- 2コアCPU
- 7GBのRAMメモリー
- 14GBのSSDディスク容量
Virtual Machine | Processor (CPU) | Memory (RAM) | Storage (SSD) | OS (YAML workflow label) | Notes |
---|---|---|---|---|---|
Linux | 2 | 7 GB | 14 GB | Ubuntu-latest, Ubuntu-22.04, Ubuntu-20.04 | The Ubuntu-latest label currently uses the Ubuntu 22.04 runner image. |
Windows | 2 | 7 GB | 14 GB | windows-latest, windows-2022, windows-2019 | The windows-latest label currently uses the Windows 2022 runner image. |
macOS | 3 | 14 GB | 14 GB | macos-latest, macos-12, macos-11 | The macos-latest workflow label currently uses the macOS 12 runner image. |
macOS | 4 | 14 GB | 14 GB | macos-13 | N/A |
macOS | 3 (M1) | 7 GB | 14 GB | macos-14 (Beta) | N/A |
あるいはLarger Runnerというものもあり、こちらはパブリックリポジトリのみで利用可能です。
インストールされるツール
OS毎に一覧があるので入ってないツールはインストールして対応で。
https://docs.github.com/en/actions/using-GitHub-hosted-runners/about-GitHub-hosted-runners/about-GitHub-hosted-runners#preinstalled-softwaredocs.github.com
IP
現在は、https://api.github.com/metaでIPを取得できるようになりました。やったね!
以前はGitHubのIPとは違ったのでIPレンジではなかったので、全てAzure VMでのホスト、かつ現状はus-east-2 regionなのでIPもそこ縛りでした。2
OSの選択
GitHubホストランナーの実行可能な環境は3種類あり、Azure Pipelineと同じ。 ほとんどのケースではLinux選んでおけばいいけど、.NET FrameworkのようなWindows固定、XcodeのようなmacOS固定もあるので用途に応じて。
- Linux
- Windows
- macOS
Azure Pipeline同様にマトリックスビルドには対応しているので、OSSで各種OSむけのビルドはCircleCIより書きやすく、Travis CIの代替になりえる筋はある。
実行権限
CIではツールインストールなど権限を必要とすることが多い。 Linux/Windowsいずれにおいても管理者権限があるので権限で悩むことはないかな。
- Linux, macOS: パスワードレスsudo状態
- Windows: UAC無効、管理者状態
ファイルパス
実パスを気にせず、GitHubが提供している環境変数でアクセスできる。
$HOME
: ユーザーパス。ログイン認証情報を含めてokらしい$GITHUB_WORKSPACE
: アクションとシェルコマンドの実行パス、変更可能$GITHUB_EVENT_PATH
: webhookイベントのPOSTペイロードへアクセスできる
ホスト仮想マシン
ファイルパスは静的でないため、GitHubが提供している環境変数を使う必要がある。
- home
- workspace
- workflow/event.json
コンテナ
静的にパスを利用するため、USER
を指定すると$GITHUB_WORKSPACE
にアクセスできなくなる。
/github
Path Prefixを予約しているので自分でボリュームマウントするときは気を付ける。
- /github/home
- /github/workspace
- /github/workflow/event.json
環境変数
CircleCIのようにspin upした環境の変数は出してくれない。Azure Pipelineと一緒で不親切、正直なんでやねんっていつも思ってる。
自分で拾う必要があるので、適当にデフォルトの環境変数は把握しておく。
GitHub が使う環境変数は、
GITHUB_
prefixがついており、GITHUB_
prefixを使用して環境変数またはシークレットは設定できない。(エラーになる)
シークレット
Settings > Secretsからシークレットを設定できる。
Azure Pipeline同様に、ログからは自動的にマスクされる。 制約として、ワークフローで最大100シークレット、容量は64K 。
Using secrets in GitHub Actions - GitHub Docs
構造化データを値にするのは避けるべきというのは注意。
GitHubがログのシークレットを確実に削除するよう、構造化データをシークレットの値として使用することは避けてください。たとえば、JSONやエンコードされたGit blobを含むシークレットは作成しないでください。
GITHUB_TOKEN
GitHub Actionsで何気に一番うれしいやつ。GitHubへの操作多いので、Token自動的に生成してくれるの最高。
前提として、writeアクセスがあるユーザーになってるので注意。
リポジトリに対してwriteアクセスがあるユーザなら、誰でもシークレットの作成、読み取りおよび使用ができます。
GitHub Appsをインストールするアクセストークンとして、GITHUB_TOKEN
が自動生成される。
ジョブごとに「60分で期限切れ」になる一方で、ワークフローはデフォルト6hまでタイムアウトにならないので注意です。(デフォルトが長い)
Automatic token authentication - GitHub Docs
権限は一通り書き込み権限があり、リリースにパッケージ投げたりコメント書いたりは十分。逆に言うと結構強いので注意がいりそう。(もちろんOrg / Team権限はない)
Forkリポジトリからはreadがあるけどwriteがない。PRトリガーのワークフローで書き込み操作ははまりやすいです。
Permission | Access type | Access by forked repos |
---|---|---|
checks | read/write | read |
contents | read/write | read |
deployments | read/write | read |
issues | read/write | read |
metadata | read | read |
packages | read/write | read |
pull requests | read/write | read |
repository projects | read/write | read |
statuses | read/write | read |
コンテキスト
コンテキストはかなり便利でメインで使っていくことになります。
github
コンテキストはREST APIでとれるレスポンス/webhookレスポンスに近く、そのコミットの情報が結構とれます。コミットメッセージまででるので、skip ci
に似た処理を自作するときに便利です。env
やsecrets
もコンテキストの一種です。
環境変数GITHUB_
でほとんどとれるとか書いてるけど取れるのはよくCIにある情報程度で、少し深くなるとコンテキスト触るしかない。
コンテキストは「stepsじゃなくても参照できる」のが重要で、jobs.if
でも利用できるのでコンテキストが一致するかでjob自体を実行するかとかも制御できます。
Artifact
アーティファクトでjob間のデータ永続はAzure Pipelineまんまです。
GitHub Actions のアーティファクトとは、ワークフロー実行中に生成されるファイル、またはファイルのコレクション。
ワークフロー内の各ジョブが異なるインスタンスで実行されるため、ワークフロー内のジョブ間でデータを受け渡すのには必須となります。ビルドパッケージを置いたり、ログを置いたり何かと使うのはCIサービスでよくあるパターンですね。
Storing workflow data as artifacts - GitHub Docs
アーティファクトはアップロードされるとzipになるけど、ダウンロードは生データが取れるので取り回しは楽。
- ジョブが終了する前にデータをアップロードして、ワークフロー実行の内部にファイルを保存できる。 アーカイブをアップロードするときは、名前を付ける
- ファイルをアップロードすると、同じワークフロー実行内の別のジョブでダウンロードできる。 アーカイブをダウンロードするとき、アーカイブは名前で参照できる。 アップロードされているアーティファクトをダウンロードできるのは、同じワークフロー実行中だけ
ワークフロー終了後、ジョブごとにArtifactをWebから取得できるので便利。
トリガーイベント
1つ以上のイベントをトリガーに設定できる。 pushやIssue、PR、webhookなどの各種イベント以外にも定期実行も可能。 ここがCircleCIでは厳しかったのでGitHub Actionsでうれしいところ。
GITHUB_SHA
やGITHUB_REF
環境変数に現在のイベントに応じた状態がでるのでなるほど。(イベントごとに変わる)
Wikiページの作成、更新はgollum
イベントらしい。
Events that trigger workflows - GitHub Docs
ただ、ワークフローから別のワークフローはトリガーできないので、コメントなり適当なイベントを仲介する必要がある。
実行しているワークフローのアクションからは、新しいワークフローの実行をトリガーできない。
pushイベントでファイルの変更を完全に終えず、REST APIを使って取得が必要なのもなるほど。
GitHub Actionsが利用できるwebhookのペイロードには、commitオブジェクト中のadded、removed、modified属性は含まれない。
Forkされたリポジトリでは動かず、別途動くように設定する必要があります。もし実行するようにしても、ForkされたリポジトリのGitHub Actionsはベースリポジトリではトリガーされず、Fork先のリポジトリで許可が必要なのは普通のCIでよいところです。
Cache
なるほど、CircleCIとよく似てるけど、微妙に違う。
マッチングルールは、keyで完全一致を見て、失敗したらrestore-keysを上から順に前方一致で検索なのでよくあるとおり「長いキーから順に書き並べる」のが王道。さらにrestore-keysで複数一致したら最近のキャッシュが利用されるので素直な印象。
- keyの完全一致
- restore-keysを上から評価
- より最新のもの
Caching dependencies to speed up workflows - GitHub Docs
CacheとRestoreがセットになってるのはうれしいですね。actions/cache
しておくと、指定したキャッシュ対象パスに変更が合った時「Jobの終了時にpost actionとして自動的にキャッシュされる」のは普通に便利。この時キャッシュキーがすでにあればスキップされるので、意図通りの挙動です。
GitHub Actions でキャッシュを使った高速化 - 生産性向上ブログ
OS別なら${{ runner.os }}
をキーに入れるのはよくあるパターンです。キャッシュ上書きがなく、7日でキャッシュ消えるものの任意のキャッシュクリアがないので、環境変数などでcache-version
を定義してキャッシュキーに含めるのも王道。
pushとpull_requestイベントだけ使えること、7日間以上アクセスされていないキャッシュエントリは削除されることに注意です。また、リポジトリのキャッシュサイズ制限が2GBと小さいのもはまる。
- 400MBを超えないキャッシュ内の個々のファイル。 この制限を超えた場合、400 - Bad Requestが返さる
- リポジトリ内のすべてのキャッシュの合計サイズが2GBを超えない
相変わらずWindows \
とmacOS/Linux /
でパス文字の解釈が違ってkeyの指定がコケるのはつらい。
hashFiles() does not work for valid patterns · Issue #39 · actions/cache
Actions
CircleCI Orbsじゃないけど、似たような処理の塊はActionsと呼ばれていて、Marketplaceで公開されている。Actionsでやっていることを知りたいときは、追っていくとGitHubリポジトリにたどりつくので、やってることも読めるしいい感じになってます。
GitHub Marketplace · Actions to improve your workflow
Actionsについて概要はドキュメントがあるのでみればok。
Finding and customizing actions - GitHub Docs
ActionsをGitHub Web上で編集する時、右にポップアップが出ます。
シンタックスエラーを検出したり、インテリセンスとかも利くので、こっち使うのが楽。
通知
WebとEmailが設定できる。
なるほどビルドがコケると通知される。
YAML
実際書くときは、YAML書いてみて、わからないものを調べるという流れで慣れていっている。 ではYAMLで実際にどう書くのかざくっと使うものを見てみる。
Azure Pipeline風味が残ってるような感じで、もうちょっと砕けててほど良さもある。
Getting started
はじめてのYAMLテンプレートは、Actions選択したときに選択できるテンプレートを使うのが楽。
https://help.github.com/en/actions/automating-your-workflow-with-GitHub-actions/starting-with-preconfigured-workflow-templateshelp.github.com
YAMLシンタックス
どのような要素があるのかは、まずはシンタックスを把握すればok。
https://help.github.com/en/actions/automating-your-workflow-with-GitHub-actions/workflow-syntax-for-GitHub-actionshelp.github.com
最低限の定義はこんな感じ。何の意味もないやつ。
on: push jobs: build: runs-on: ubuntu-latest steps: - run: echo Hello
次の要素が必須だと分かる。
- name : Workflowの名前でリポジトリのActions画面で表示される名前。省略するとパスになるので付けたほうがいい
- on: 必須。実行するイベントやブランチなどの指定をする
- jobs: 必須。とりあえず
jobs:
でok - jobs.
.runs-on: 動作させるホストランナーの指定。GitHub hostedかSelf-hostedかはここで決まる - jobs.
.steps: 必須。とりあえず steps:
でok。jobsを書くときは、最低1つのstepsが必要 - jobs.
.steps.step : stepsの中は最低1つのstepが必要。例はrun stepを使っている
on
実行するトリガーの定義をここでする。 GitHub Actionsが他のCIと決定的に違うのが、ここでGitHubイベントと楽にバインドできることでしょう。
# push のみ on: push # push と pull request なら on: [push, pull_request]
ブランチも含めた制御ができるのはいい感じ。
on: # Trigger the workflow on push or pull request, # but only for the master branch push: branches: - master pull_request: branches: - master # Also trigger on page_build, as well as release created events page_build: release: types: # This configuration does not affect the page_build event above - created
定期実行は、schedule
イベントで実行できる。
on: schedule: # * is a special character in YAML so you have to quote this string - cron: '*/15 * * * *'
env
グローバルに、全Job、全stepから参照する環境変数はここで指定する。
特定のジョブでならjobs.<job_id>.env
でいいし、特定のStepでならjobs.<job_id>.steps.env
があるので、あまり使いたくない。
jobs.<job_id>.needs
依存するjobを指定できる。大事。 ここで指定しないと並列に回るので、直列で回すときはCircleCI同様依存関係を作る必要がある。
jobs: prepare: runs-on: ubuntu-latest steps: - run: echo prepare build: runs-on: ubuntu-latest needs: prepare steps: - run: echo build
jobs.<job_id>.runs-on
実行するホストのOSをあらかじめ定義された値から選んで使う。
- Windows Server 2019: windows-latestまたはwindows-2019
- Ubuntu 18.04: Ubuntu-latestまたはUbuntu-18.04
- Ubuntu 16.04: Ubuntu-16.04
- macOS Catalina 10.15: macos-latest, macOS-10.15
jobs: build: runs-on: ubuntu-latest
jobs.<job_id>.container
ジョブをコンテナで実行したいときに使う。
jobs: my_job: runs-on: ubuntu-latest container: node:10.16-jessie
何気にイメージ指定するだけじゃなくて、細かくDockerの実行時パラメーターも調整できる。
jobs: my_job: runs-on: ubuntu-latest container: image: node:10.16-jessie env: NODE_ENV: development ports: - 80 volumes: - my_docker_volume:/volume_mount options: --cpus 1
jobs.<job_id>.services
追加のコンテナを動かすときはservicesを用いる。 例えば、CI上でDatabase起動させてテストするとかはこれ。
jobs: container-job: runs-on: ubuntu-latest container: image: node:10.16-jessie services: redis: image: redis ports: - 6379/tcp
jobやactionをコンテナで実行しているときにservicesのコンテナの参照をするときは、ホスト名でok。
そのステップがホストで実行しているときにservicesのコンテナの参照をするときは、localhost
+ マッピングしているホストのポート
でアクセスする。
ホストでマッピングされたポートは${{ job.services.<service_name>.ports[<port>] }}
でとれる。
上のRedisなら、${{ job.services.redis.ports['6379'] }}
。
jobs.<job_id>.if
ジョブの実行自体をここで制御できる。circleciのwhenをjobで指定するみたいなやつ。 ifではコンテキスト参照できるので、特定のコミットメッセージの場合はジョブを実行しないとかが書ける。
jobs: my_first_job: runs-on: ubuntu-latest if: github.event_name == 'pull_request' && github.event.action == 'unassigned'
あと、ifではコンテキスト参照するときに${{ }}
で囲まなくていい。
演算子とか書式はドキュメント見るのがいい。
https://help.github.com/en/actions/automating-your-workflow-with-GitHub-actions/contexts-and-expression-syntax-for-GitHub-actionshelp.github.com
jobじゃなくてstepを条件で実行制御したい場合は、jobs.<job_id>.steps.if
があるので、stepに対してifを付ければok。
jobs: my_first_job: runs-on: ubuntu-latest steps: - name: My first step if: github.event_name == 'pull_request' && github.event.action == 'unassigned' run: echo This event is a pull request that had an assignee removed.
jobs.<job_id>.steps
ここにやりたい処理を書いていく。
uses
でGitHub Actionsを利用したり、runs
でシェルのコマンドを実行したりできる。
usesは、stepで特定のコンテナ実行とかもできるのでこれは結構便利。
- パブリックRepositoryの任意のリリースやブランチ、コミットを指定できる
- 自分のリポジトリで定義したactionの参照
- public registoryのdockerをステップで実行
jobs: my_first_job: runs-on: ubuntu-latest steps: # use GitHub Actions - uses: actions/setup-node@v1 # use a specific version tag of a public repository - name: use AWS Repo uses: actions/aws@v2.0.1 # use a action in workflow repository - uses: ./.github/actions/my-action # use a docker in public registory - uses: docker://gcr.io/cloud-builders/gradle
jobs.<job_id>.steps.run
一行、複数行、所定のパスで実行というのがよく使うパターン。
複数行は、安定の|
なのでまぁ大丈夫そう。
jobs: my_first_job: runs-on: ubuntu-latest steps: # single line - run: sudo apt-get update # multi line - run: | sudo apt-get install google-cloud-sdk && \ kubectl
他のシェルを指定するにはshell:
で指定する。
jobs: my_first_job: runs-on: ubuntu-latest steps: - run: sudo apt-get update shell: bash - run: Get-Location shell: pwsh
Windowsのrun
、あるいはpowershell
やpwsh
などを指定してPowerShellがシェルの場合、自動的に頭に$ErrorActionPreference = 'stop'
が追加されてFail fastになるのと、末尾にif ((Test-Path -LiteralPath variable:\LASTEXITCODE)) { exit $LASTEXITCODE }
を追加して実行結果でrunステップが失敗するように処理が差し込まれているので注意。
jobs.<job_id>.steps.with
いわゆるパラメーター。Actionsとかでパラメーター渡すときはwithの中にmap(KeyValue)を書くことになる。
withで指定したキーは、INPUT_
prefixつきで大文字に変換されてActions内部から参照できる。例えばfirst_name
というキーで指定したならINPUT_FIRST_NAME
を指定することで値に参照できる。
jobs: my_first_job: runs-on: ubuntu-latest steps: - name: My first step uses: actions/hello_world@master with: first_name: Mona middle_name: The last_name: Octocat
環境変数
stepのrun実行時に渡したいなら、env: で指定する。
jobs: my_first_job: runs-on: ubuntu-latest steps: - name: Hello world run: echo Hello world $FIRST_NAME $middle_name $Last_Name! env: FIRST_NAME: Mona middle_name: The Last_Name: Octocat
stepのrunの中でいじるなら、シェルに従って環境変数を触ればいい。
# windows $env:PATH += ";$pwd\build\lib"
step間で環境変数を保持したい場合は、set-env
をecho出力する。Azure Pipelineに似た感じだけど微妙に違う。
::set-env name={name}::{value}
action_state
という環境変数にyellow
という値をいれる場合はこうなる。
echo "::set-env name=action_state::yellow"
先ほどのPATHをstep間で保持するならこう。
# windows $env:PATH += ";$pwd\build\lib" echo "::set-env name=PATH::$env:PATH"
PATH環境変数への追加は、 echo "::add-path::/path/to/dir"
が用意されている。
echo "::set-env name=PATH::${PATH}:/path/to/dir"
でも動くけど、楽なほうで。
https://help.github.com/en/actions/automating-your-workflow-with-GitHub-actions/development-tools-for-GitHub-actions#set-an-environment-variable-set-envhelp.github.com
シークレット
シークレットの利用は、secretsコンテキスト経由で利用できる。 例えばSuperSecretというキーで登録したなら、${{ secrets.SuperSecret }}
。
利用する際は、with
構文かenv
など環境変数経由で参照する。
steps: - name: Hello world action with: # Set the secret as an input super_secret: ${{ secrets.SuperSecret }} env: # Or as an environment variable super_secret: ${{ secrets.SuperSecret }}
GITHUB_TOKENもシークレットコンテキスト経由で利用できます。
name: Pull request labeler on: - pull_request jobs: triage: runs-on: ubuntu-latest steps: - uses: actions/labeler@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }}
ログの表示で任意の文字列をマスクするために::add-mask::{value}
もある。
Artifact
アップロード操作は$GITHUB_WORKSPACE
を起点にパスで指定できます。
常に相対パスでいいので、絶対パスを気にする機会が減っていい感じです。
アップロードしてダウンロードする例は次のようになる。
jobs: job_1: name: Add 3 and 7 runs-on: ubuntu-latest steps: - shell: bash run: | expr 3 + 7 > math-homework.txt - name: Upload math result for job 1 uses: actions/upload-artifact@v4 with: name: homework path: math-homework.txt job_2: name: Multiply by 9 needs: job_1 runs-on: windows-latest steps: - name: Download math result for job 1 uses: actions/download-artifact@v4 with: name: homework - shell: bash run: cat homework/math-homework.txt
Cache
サンプルはいくつかあるのでそれをみるのが手っ取り早い。
.NET Coreのnugetを例で考えます。(.NET Frameworkは忘れましょう)
.NET CoreはPackage Referencesにしているとcsprojにpackage情報が入り厄介です。もしcsprojが1つならこれでいいでしょう。あるいはManage Package Centrrallyを使ってパッケージを一元管理するならDirectory.Packages.propsを使えるでしょう。
steps: - uses: actions/cache@v1 with: path: ~/.nuget/packages key: ${{ env.cache-version }}-${{ runner.os }}-nuget-${{ hashFiles('src/project.csproj') }} restore-keys: | ${{ env.cache-version }}-${{ runner.os }}-nuget-${{ hashFiles(''src/project.csproj') }} ${{ env.cache-version }}-${{ runner.os }}-nuget-
1つだけプロジェクトがあるならいいのですが、複数のcsprojに分離していると当然パッケージとバージョンの同一性を担保する方法がlockファイルに比べて面倒です。 CirclrCIでやったように、csprojを拾ってきてmd5あたりをキャッシュキーにするのもありです。 CircleCIの例を載せておきます。
steps: - run: name: Calculate cache key for csproj command: | { md5sum $(find << parameters.search_path >> -name << parameters.target_file_pattern >> | sort -r) } > ~/cache-key-source-<< parameters.project >> working_directory: << parameters.working_directory >> - save_cache: name: Cache nuget pacakges key: nuget-<< parameters.cache_key >>-<< parameters.project >>-{{ checksum "~/cache-key-source-<< parameters.project >>" }} paths: - "~/.nuget"
なお、nugetは、macOSはXamarinなどでキャッシュサイズが半端なくなるので、こういうのを避けるためにNuGet Packageのパスを明示的に設定するのはあり。
その場合は、NUGET_PACKAGES
環境変数にパスを指定して、actions/cacheのパスにも指定する。
env: NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages steps: - uses: actions/cache@v1 with: path: ${{ github.workspace }}/.nuget/packages key: ${{ env.cache-version }}-${{ runner.os }}-nuget-${{ hashFiles('src/project.csproj') }} restore-keys: | ${{ env.cache-version }}-${{ runner.os }}-nuget-${{ hashFiles(''src/project.csproj') }} ${{ env.cache-version }}-${{ runner.os }}-nuget-
TIPS
細かいけど知っておくといいTIPSがたまってきたのでメモ。
step の name
stepごとにnameを指定することで、GitHub上の表示を設定できる。
省略するとコマンドがそのままでるので、CircleCIのようにname指定しないのもありです。ただ、個人的にはnanemを付けることで意図を示せるので、そういうささいな努力は欠かさないほうがいいと考えています。
Azure Pipelieは、コマンドの内容ではなくcommand@1
とかのモジュール名の表示になってたので、GitHub Actionsで改善して本当に良かった、神。
タイムアウト
timeout-minutes
で指定できる。デフォルトが6hourと長いので、指定した方がいいケースは多い。
タイムアウトは、jobとstepごとの両方に指定可能。
jobs: build: runs-on: ubuntu-latest timeout-minutes: 15 steps: - run: sleep 300 timeout-minutes: 3
skip ci / ci skip
2021/2/10に、push/pull_requestトリガーで標準サポートされました。
競合でもよく使われる[skip ci], [ci skip], [no ci], [skip actions], or [actions skip]
が網羅されて、なるほど。
以前は、jobのifで制御してましたがもう不要。
Organization の他の private repo の参照
ssh-agent
Actionを使えばSSHキーでknown_hosts
設定したりできるけど、あんまり使いたくはない。
自動生成されるTokenでその制御はできないので、専用のTokenを生成するのが一番手っ取り早い。
- uses: actions/checkout@v1 with: repository: organization_name/repo_name token: ${{ secrets.ACCESS_TOKEN }}
Badge
サポートされてた。ドキュメントないけど。
いい感じの Action どこ
安定のawesomeで。
ローカルで構文チェックするCLIとかないの
Circle CLIのようなローカル実行向けのCLIはないです。 残念。