この記事は Akerun - Qiita Advent Calendar 2024 - Qiita の24日目の記事です。
はじめましてyellow-seedです。webエンジニアとして既存サービスのフロントエンド、バックエンドの運用保守、機能改善を担当しています。入社して1年経ちました。時間の流れは早いものです。
主担当業務のかたわらで、担当しているサービスのリポジトリのCI/CDをCircle CIからGitHub Actions へのリプレイスする活動を実施しています。リプレイスの狙いはCircle CIとGitHub Actionsが混在している現状の技術スタックをシンプルにすることにあります。
GitHub Actionsを導入するにあたって、お作法を守りつつスピーディーに実装する方法について色々と考える機会となりました。今回は現時点での考えを書きたいと思います。
はじめに
GitHub Actionsの導入をするにあたって、自身の中では実装の流れを以下のようにパターン化して捉えることとしています。
- nektos/act を使用してローカルでワークフローのSetupからLintにあたる部分を実装、動作確認
- GitHub Actionsの環境でUnit Testの実行, ビルドやデプロイ部分を実装
- (ステージング用の環境がある場合) 順次適用
- 本番環境への導入
執筆時点でもまだまだ作業中なこともあり、上記の1, 2にあたる部分の自分なりのtipsについて今回は記述することにします。
※ 備考
nektos/actはGitHub Actionsのワークフローをローカル環境で再現実行するツールです。完全な再現ではないし、act自体のコマンドオプションなども追加で把握しないといけないため、無理にactで動作確認する必要はないと考えます(筆者はある程度慣れたので使うことにしています)。詳細な説明はここでは省きますので公式のドキュメントを参照してください。
注意事項
2025年1月時点での情報をもとにした記事になります。tipsは当時の情報に基づいて記載されています。
SetupからLintにあたる部分を実装、動作確認
tips: Setup処理の共通化
Composite ActionをつかってSetup処理を呼び出せるようにしておきます。Setup処理はどのワークフローでもほぼ共通の最初のステップになるので、共通化のデメリットが小さいと考えられるからです。また、Composite Actionを一つ作っておくと、他に共通化したい処理が生まれた時に他のメンバーでも使い方の例がある状態で実装できるので、スムーズに進めやすくなります。
以下は実装例です。利用する場合の実装は後述のワークフローファイルに含まれていますので、そちらを参照してください。
# .github/workflows/setup/action.yml
name: Setup
description: パッケージのインストール処理を共通化
runs:
using: composite
steps:
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
- name: Install dependencies
shell: bash
run: npm install
GitHub Actionsの環境でUnit Testの実行, ビルドやデプロイ部分を実装
tips1: ワークフローの雛形テンプレートを用意する
GitHub Actionsのベストプラクティスについて調べると、検索結果に色々なtipsが出てくるため、導入時に機能をどんどん盛り込みたい誘惑にかられますが、マイルストーンを線引きして諦めることも必要です。この場合のひとつの考え方として、「導入時点での考えることは最初に設定ファイルで書いておく」と割り切るとどこまでのセオリーを遵守するかで時間を使わなくて済みます。
わかりやすい例として、テンプレートとなるymlファイルをベースとしていつも参照するようにします。実装していく場合はそのテンプレートに付け足していくという方針です。
なんとなくから脱却する GitHub Actionsグッドプラクティス11選に記載されているテンプレートが考える上でとても参考になりました。
以下は上記リンクを参考に自分なりの修正および捕捉コメントを加えたものです。
name: Example
# description:
# ワークフローの目的:
# - 目的を簡潔に書く
# ワークフローの影響範囲:
# - 何に作用するものかを簡潔に書く
# 関連URL
# - 参考情報や関連リポジトリの情報について書く
on:
# 動作確認しやすいように手動起動をサポート
workflow_dispatch:
push:
# ワークフローレベルでパーミッションをすべて無効化
permissions: {}
# デフォルトシェルでパイプエラーを有効化
defaults:
run:
shell: bash
# ワークフローが複数起動したら自動キャンセル
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
example:
# バージョンを明示. latestだと差すものが不透明なため
runs-on: ubuntu-22.04
# タイムアウトを設定
timeout-minutes: 5
# ジョブレベルで必要最小限のパーミッションを定義
# OIDC準拠ならデプロイ時には id-token: write 権限も必要
permissions:
contents: read
steps:
# コミットハッシュで固定がベター
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# Setup部分はCompsitionを利用する
- name: Setup
uses: ./.github/workflows/setup
# ワークフロー構文及び構文内シェルスクリプトに対するLint (必要に応じて. Lint処理を共通化してそこに入れるのも良さそう.)
- name: Run actionlint
uses: reviewdog/action-actionlint@fafbcd6731647e01e0a960020fb00370382c46a7 #v1.64.1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-check
level: error
fail_level: error
tips2: ワークフローで使用するActionの継続更新の仕組みをいれておく
Dependabotを利用して、手動に頼らずにワークフローを更新しやすくする仕組みもこの時点で導入しておくのが良いと思います。ファイルの内容もGitHub Actionsを使っているのであれば有効なのでコピペが効きます。
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'daily'
まとめ
GitHub Actionsの導入時の実装は規模にもよりますが、一人で進めていくことが多いのではないでしょうか。考えることをシンプルにすることで導入までのスピードをあげつつ、グッドプラクティスを効率よく実現する助けになればと思います。
今後もさらなるCI/CD改善のための実装を追加していきたいと思います。
参考
株式会社フォトシンスでは、一緒にプロダクトを成長させる様々なレイヤのエンジニアを募集しています。 photosynth.co.jp Akerunにご興味のある方はこちらから akerun.com