Closed14
GitHub CI/CD実践ガイドの感想メモ
こちら読了したので感想というかメモを残しておく
2章 GitHub Actionsの概念
- GitHub Actionsは何かしらのトリガーで自動実行されるもののみと思い込んでいたが
workflow_dispatch
を指定することで手動実行のワークフローを作成できる - 無理に自動化させようとして無駄に複雑になることがあったので手動実行のワークフローという引き出しが増えたのは嬉しい
- cronによる定期実行も可能。昔やったことがあるがけっこう起動時間ずれた記憶があるが、やはりだいぶずれるらしいので厳密な定期実行は避けたほうが無難。逆に1日一回みたいなざっくりな定期実行なら問題ない
- GitHub Actionsはランナーはジョブを起動するときに開始し終了時に破棄される。そのため、毎回クリーンな環境でジョブを実行できる。この特性をエフェメラルと言う。
- 同じジョブ内ではステップ間でワークスペースを共有しているので前段のステップで作成したファイルを後続のステップで使うなどはできる。
- パフォーマンスなどを考えるとキャッシュやアーティファクトを検討したほうがいいかもしれない
リソースの共有について
- GitHub Actionsはランナー単位で実行環境が用意される
- 実行環境はジョブ内の各ステップで共有のため前段で作成したファイルを後続のステップで使うなどはできる
- ツールのインストールなどをするのであればキャッシュを使うことを検討するとパフォーマンスがよくなるかもしれない
- ステップ間で出力された値を共有したいとかでれば
$GITHUB_OUTPUTS
にkey=value
の形式で出力することで${{ steps.current.outputs.message }}
のような形式で参照できる - ジョブをまたいでファイルを共有したい場合などにはアーティファクトが使用できる
成果物
ここに使用例を置いときます
3章 ワークフロー構文の基礎
- GitHub Actionsではいくつかのコンテキストが使え
gihubコンテキスト
やrunnerコンテキスト
などがある。 - デフォルトの環境変数はコンテキストをそのまま環境変数にしたもので、置き換えが可能
- コンテキストの使用も一度環境変数に入れてから使用したほうがいい。これは後述のセキュリティ的な観点から
環境変数の扱い
- GitHub Actionsの構文というかシェルの構文
-
$TEST
と${TEST}
の違いについて -
{}
をつけた方が明示的に変数を区切れるので予期せぬ挙動を防げそう - 基本的には
{}
ありで環境変数を使っておいた方が無難そう - シェル以外の場所で環境変数を使いたい場合、
${{ env.TEST }}
のような形式で使える - ダブルクォーテーションで変数は囲っておかないと変数が展開されないことがある
- なので基本的にはダブルクォーテーションで囲ったほうがいい
- また、後半のセキュリティのところで出てくるがスクリプトインジェクションのように展開されることで良きせぬコマンドを実行してしまうこともあるので、基本的にはinputの値は一度環境変数に設定してから使うと良い。
オブジェクトフィルター
- コンテキスト参照の特殊記法
- 配列やオブジェクトから指定したプロパティのみ抜き出し、配列を作成する
-
${{ github.event.*.html_url }}
のようにアスタリスクを使って書く - オブジェクトフィルターは関数と一緒に使われることが多い
- jsonの組み込み関数と合わせて以下のように使ってみた
- name: Output Json
id: json
run: echo "json=[{\"name\":\"user1\"},{\"name\":\"user2\"}]" >> "${GITHUB_OUTPUT}"
- name: Json Function
run: |
echo "${NAMES}"
env:
NAMES: ${{ toJson(fromJson(steps.json.outputs.json).*.name) }}
- 最初envでfromJson()の結果を変数に設定しようとしてエラーになった
- 環境変数に配列型のデータを設定しようとしてエラーになってた
- なのでtoJsonで文字列に戻して環境変数に設定した
条件分岐
- ifで条件分岐
- ステータスチェックの組み込み関数を使うことで前段のステップのステータスによって条件分岐ができる
steps:
- name: Success
run: exit 0
- name: Echo success
if: ${{ success() }}
run: echo success!!
- name: Failure
run: exit 1
- name: Echo failure
if: ${{ failure() }}
run: echo failure!!
- name: Echo always
if: ${{ always() }}
run: echo always!
permission
- デフォルトではcontentsのread権限が与えられているのでpermissionを設定しなくてもリポジトリのソースコードを参照できる
- しかし、何かしらのpermissionを設定して、contentsのpermissionを設定しないとcontentsのread権限がない状態になってしまうので注意が必要
4章 継続的インテグレーションの実践
actionlint
GitHub Actionsのワークフローの静的解析ができる。インストール方法はいろいろあるが以下はdockerで実行する例。
name: Actionlint
on: workflow_dispatch
defaults:
run:
shell: bash
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- name: Lint
run: docker run --rm -v "$(pwd):$(pwd)" -w "$(pwd)" rhysd/actionlint:latest
- actionlintは関係ないがdockerで実行すると毎回docker imageのpullが発生するのでキャッシュを使いたい気がする
- ただ、pullしてきたimageをキャッシュする方法はあんまりなさそう
- dockerのレイヤーデータは
/var/lib/docker
にあるようだがこれをキャッシュするのはあまりやりたくない - go installでもインストールできるようなので実行バイナリを配置した一時ディレクトリを指定してキャッシュを取った方が簡単そう
同時実行のキャンセル
以下のようにすると古いワークフローの実行をキャンセルできる。
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
タイムアウト
- タイムアウトは基本的に全てのワークフローに設定したほうがいい
- デフォルトでは6時間に設定されているので最悪6時間動き続ける
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 5
シェル
- 基本的には全てのワークフローでデフォルトシェルを指定した方が良い
defaults:
run:
shell: bash
- シェルの指定を省略してもbashで起動するが、パイプエラーを拾えない
- なので、全てのワークフローで明示的に指定した方が良い
第5章 運用しやすいワークフロー
- デバッグログを有効化すればデバッグがだせる
-
::<ワークフローコマンド>::
をechoで出力すると自分でも見やすいログを出力できる - 使い方の例は以下の記事を
- bashの
set -x
でコマンドの実行結果を見れるようにするのも簡単 -
GITHUB_STEP_SUMMARY
環境変数にマークダウン形式で出力することでサマリーも出せる - これはサードパーティーのactionとか使ってるとサマリー出してくれるやつがそれだと思う
- slackの通知はslack公式のactionがあったようだが今はGitHub Appsを使った方が簡単そう
- 以下の記事が参考になる
https://zenn.dev/k_saito7/articles/notification-github-actions-workflow-to-slack - environmentsを指定することで環境別のvariablesとsecretを使うことができる。
- GitHub Actionsで使えるvariablesとsecretsはenvironmentsとrepositoryに設定するのとOrganizationとで3つある
第6章 アクションによるモジュール化
- GitHub Actionsの実装方法には3種類あり、compositとJavaScriptとDockerがある。
- GitHub Actionsはリモートアクションとして公開するだけでなくローカルに配置して使う、ローカルアクションとして使うこともできる。
- GitHub Actionsを作成する場合、インターフェースとしてメタデータファイルを作成する必要があり、これに入力と出力の定義などを記載する
第8章 Dependabot
以下の記事によるバージョンアップ戦略がわかりやすい
第9章 リリースノート
Goに限った話ではgoreleaserがとても便利そう
上記Dependabotによるバージョニング戦略に加えて、バージョンが上がったときにリリースノートまで作成されるようになってると良さそう
第10章 GitHub Pacakages
- GitHub のリポジトリと合わせてパッケージを管理できるので楽
- Javaのgradleプラグインやnpm, Docker imageなどがサポートされている
- GitHub Pacagesの話ではないが
docker login ghcr.io
のようにdocker loginコマンドの後には使用するレジストリサービスのドメインを指定できる - デフォルトではDocker Hubだが
ghcr.io
を指定するとGitHub Pacagesを使うしgcr.io
を指定するとGoogle Container Registryを使える。
docker/metadata-action
- GitHub Pacagesの話ではないがGitHub Actionsでdocker imageをビルドしレジストリにpushするとき、バージョンタグやメタデータを簡単に付与できるアクション。
- あんまり気にしたことなかったけどdocker imageにはタグの他にラベルというメタデータを付与することができるようになっている。
docker/login-action
- ついでにdocker loginを簡単にできるやつ
docker/build-push-action
- docker buildとdocker pushが簡単にできるアクション
- cache-fromやcache-toを指定することでキャッシュを有効化してビルド時間を短縮することも可能
docker/setup-buidx-action
- 前述したbuild-push-actionがbuildxに依存しているらしく使用するのにセットアップが必要らしい
buildxについて
- あんまり理解してなかったので
- まずMobyというDocker社が作ったOSSプロジェクトがある
- そのMobyのなかにBuildKitというコンテナビルドを高速化させるようなさまざまな機能がありbuildxはBuidKitをDockerから使えるようにする拡張のよう
- buildxを使うことでマルチプラットフォームビルドや分散ビルド、キャッシュ機能の性能向上などのメリットがある
- GitHub Actionsでは上述したように公式からactionが提供されているので全て使ってビルドプッシュするようにすると必然的にbuidxのセットアップもしているはず
- buildxによるビルドで通常のビルドよりも性能が上がっている可能性もあるが、よりビルド時間を短縮させたければ--cache-from, --cache-toを使いレジストリに保存したレイヤーキャッシュを使えるようにするとビルド時間が短縮できそう
- しかし、レジストリに保存するキャッシュはもう一つキャッシュ用のイメージを保存するような感じらしいのでレジストリの容量を圧迫することになる
- なのでもしキャッシュまで有効にするならそこらへんも考えて有効にしたほうがいいかもしれない
参考
公式dockerのactionへの置き換えのまとめ
BuildKit周辺の用語説明
第11章 OIDC
- AWSのようなクラウドベンダーの長命なクレデンシャルを直接使うのはアンチパターン
- セキュアに運用するならば一時クレデンシャルを使用する
- 一時クレデンシャルの取得にはOIDCの技術が使われ、GitHub ProviderのようなID Providerから取得したOIDCトークンを一時クレデンシャルと交換する
- これを実現するには以下の2つが必要
- クラウドプロバイダー側でOIDCに必要なコンポーネントを作成する
- GitHub Actionsのワークフローにクラウドプロバイダーが提供する認証アクションを組み込む
OIDC TrustとCloud Roles
- 前述した一時クレデンシャルの交換にはAWSのようなクラウドプロバイダーがGitHub Providerを信用している必要がある。
- その仕組みがOIDC Trust
- 一時クレデンシャルのアクセス元とアクセス先を管理するのがCloud Roles
認証アクション
主要なクラウドベンダーからは認証アクションが提供されている
AWS
- AWSでGitHub Actionsのワークフローから一時クレデンシャルを取得するにはOIDC TrustとしてOpen ID Connect Provider、Cloud RolesとしてIAMロールを作成することで実現できる。
Google Cloud
- Google Cloudの例はこちらの記事を参考にすると良さそう
- ぱっと見AWSより複雑そうに見えちゃう
第13章 アクションのオープンソース化
- GitHub Actionsのワークフロー内で以下の記事にあるように特定のメールアドレスとユーザー名を指定することで非公式ではあるもののGitHub botアカウントを使うことができる
- GitHub Actionsもテストを書こうと思えば書けるので書けるときは書いていこうと思います。
第14章 GitHub Actionsの高度な使い方
Reusable Workflows
- actionを作成することでGitHub Actionsのワークフローをモジュール分割するようなやり方を学んだがReusable Workflowsを使うとより大きな括りで再利用できる処理を切り出す
- 具体的に言うとワークフロー自体を切り出して再利用する
- 利用側は独立したジョブとして扱う。アクションのようにステップで呼び出すことはできない。
- Reusable Workflowsはリモートに配置することも可能なためリポジトリを跨いだジョブの共通化を実現させることができる
型変換
-
fromJson()
を使うことで文字列をbooleanやnumber型に変換して使うことができる - これはGitHub Actionsの構文内で文字列以外の型の指定が必要なときに役立ちそう
第15章 GitHub Actions のセキュリティ
OpenSSF
- リポジトリのセキュリティをスコアにしてくれるやつ
- 書籍ではdockerで実行していたけどactionがあるっぽい?
このスクラップは3ヶ月前にクローズされました