こんにちは!株式会社iimonでエンジニアをしている「まるお」です。
先日、拡張機能アプリの最新版をリリースする際に、manifest.json
のバージョンを更新する前にタグを誤って先にプッシュしてしまいました。こうしたミスを防ぐために、リリース作業を少しずつ自動化していけたらと思い、GitHub Actionsのワークフローの書き方を一から学びました。
今回の最終的な目標は、 リモートリポジトリのmanifest.json
とタグのバージョンを比較して、異なる場合はタグをプッシュできないようにするワークフローを作成する ことです!
GitHub Actionsを初めて触る方にお役に立つ記事になれば嬉しいです。
GitHub Actionsとは何か?
GitHub Actionsは、コードを更新した際に、自動でテストを実行したり、ビルドやデプロイを行うことができる機能です。.github/workflows
ディレクトリ内にymlファイルを作成し、ワークフローをファイル内に書きます。トリガーとなるイベント(例: push
, pull_request
)が発生すると、ワークフローが実行されます。
ワークフローとは?
GitHub Actionsのワークフローは、1 つ以上のジョブを実行する構成可能な自動化プロセスです。 たとえば「コードをプッシュしたらテストを行う」といった操作を自動化できます。 手動でトリガーしたり、定義されたスケジュールでトリガーしたりすることもできます。 1 つのリポジトリで複数のワークフローが使用可能。
ワークフローの書き方を学ぶ
ワークフロー例
下記のワークフローを使って書き方を学んでいきたいと思います。
.github/workflows/publish.yml name: 'Publish' on: workflow_dispatch: push: tags: - 'v*.*.*' permissions: id-token: write contents: write actions: read jobs: releaseAndUpload: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Get app version name id: get_tag_version run: echo "TAG_VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_OUTPUT - name: Get manifest version id: get_app_version run: echo "APP_VERSION=$(jq -r .version manifest/manifest.json)" >> $GITHUB_OUTPUT - name: Version check run: | echo "tag version: ${{ steps.get_tag_version.outputs.TAG_VERSION }}" echo "manifest version: ${{ steps.get_app_version.outputs.APP_VERSION }}" echo 'manifest.jsonのバージョンとタグのバージョンが異なります' exit 1 if: ${{!contains(steps.get_tag_version.outputs.tag_VERSION , steps.get_app_version.outputs.APP_VERSION)}}
解説
name
: ワークフローの名前name: 'Publish'
on
: イベントトリガー- 手動でトリガー可能
v*.*.*
の形式に一致するタグのプッシュでトリガー
on: workflow_dispatch: push: tags: - 'v*.*.*'
- その他
イベント 説明 push リモートリポジトリへpush時 pull_request プルリクエスト作成時 deployment デプロイ時 release リリース時 issues GitHub Issues関連の処理発生時 schedule cronによる定期実行 workflow_dispatch 手動で実行 permissions
: ワークフロー内での権限設定- 最上位のキーとして、ワークフロー内のすべてのジョブに適用するか、 特定のジョブ内に permissions キーを追加するとそのジョブ内で使用可能。
- 使用可能なアクセス許可ごとに、read、write、none のいずれかのアクセス レベルを割り当てることができる(write には read が含まれる)。
- 指定されていないすべてのアクセス許可が none に設定。
- IDトークンの書き込み、読み込み権限、リリース作成(リポジトリの操作が可能)、他のアクションの読み取り権限
permissions: id-token: write contents: write actions: read
jobs
: 処理の最上位単位(ワークフローはジョブ単位で分けられてる)- jobsの中に1つ以上のジョブIDと共に処理が設定され並列で実行
releaseAndUpload
というジョブが定義
jobs: releaseAndUpload:
runs-on
: ジョブを実行するOS(ランナー)を指定- 各ジョブは、runs-on で指定されたランナー環境で実行
- 最新のUbuntu
runs-on: ubuntu-latest
steps
: ジョブはさらにステップ単位で分けられており、ステップ内にコマンドなどの処理が実行- uses: actions/checkout@v3
- アプリのタグバージョンを取得
- name: Get app version name id: get_tag_version run: echo "TAG_VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_OUTPUT
- マニフェストのバージョン取得
- name: Get manifest version id: get_app_version run: echo "APP_VERSION=$(jq -r .version manifest/manifest.json)" >> $GITHUB_OUTPUT
manifest/manifest.json
が次のようなJSONファイルだった場合{ "name": "Iimon Chrome Extension", "version": "1.2.3" }
jq -r .version
を実行すると、”1.2.3”
という文字列が取得。- バージョン確認
- name: Version check run: | echo "tag version: ${{ steps.get_tag_version.outputs.TAG_VERSION }}" echo "manifest version: ${{ steps.get_app_version.outputs.APP_VERSION }}" echo 'manifest.jsonのバージョンとタグのバージョンが異なります' exit 1 if: ${{!contains(steps.get_tag_version.outputs.TAG_VERSION , steps.get_app_version.outputs.APP_VERSION)}}
ちなみに、、
タグとマニフェストのバージョンは、どのリポジトリを見ているのか?(リモート?ローカル?)
タグバージョンは、、
マニフェストのバージョンは、、
ステップactions/checkout@v3
によって リモートリポジトリがローカル環境にクローンされたもの を見ているので、ローカルのmanifest.json
ファイルを見ています。- ローカルのファイルを参照しているわけではないようなので、原因を引き続き調査していきます。
よって、
今回やりたいこと
リモートの manifest.json
とタグのバージョンが一致するか確認
既存の「マニフェスト」バージョン取得のステップの前に、下記処理を追加
jobs: releaseAndUpload: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Get app version name id: get_tag_version run: echo "TAG_VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_OUTPUT # リモートの manifest.json を取得 - name: Fetch remote manifest.json run: | git fetch origin main git checkout origin/main -- manifest/manifest.json - name: Get manifest version id: get_app_version run: echo "APP_VERSION=$(jq -r .version manifest/rent-manifest/manifest.json)" >> $GITHUB_OUTPUT - name: Version check run: | echo "tag version: ${{ steps.get_tag_version.outputs.TAG_VERSION }}" echo "manifest version: ${{ steps.get_app_version.outputs.APP_VERSION }}" echo 'manifest.jsonのバージョンとタグのバージョンが異なります' exit 1 if: ${{!contains(steps.get_tag_version.outputs.tag_VERSION , steps.get_app_version.outputs.APP_VERSION)}}
コードの解説
1. git fetch origin main
- リモートリポジトリの
main
ブランチの最新情報をローカルに取得 - 現在の作業ブランチには影響与えず
2. git checkout origin/main -- manifest/manifest.json
- リモートリポジトリの
main
ブランチのmanifest/manifest.json
ファイルをローカルの作業ディレクトリにコピー - リモートリポジトリのの
manifest.json
ファイルを直接ローカルで使用できるように
結果
上記追加コードにより、ローカルのマニフェストバージョンをpushする前にタグをpushしてしまったら、途中でステップが中断するようになりました。
まとめ
初めてワークフローを見た時はどれが何をしているか分からなかったのですが、仕組みや書き方をある程度理解すればやっていて楽しいなと感じました。
今回は基本的な書き方しか学んでいないですが、今後さらに書き方を学んで、本番申請など今手作業でやっている業務の部分をgithub Actionsでさらに自動化させたいと思いました!
最後になりますが、現在弊社ではエンジニアを募集しています!
この記事を読んで少しでも興味を持ってくださった方は、ぜひカジュアル面談でお話ししましょう!
iimon採用サイト / Wantedly / Green
最後まで読んでいただきありがとうございました!!!