GitHub Actions/semantic-release を使ったGitHubタグとAmazon ECRイメージタグを連携するセマンティックバージョニング術

GitHub Actions/semantic-release を使ったGitHubタグとAmazon ECRイメージタグを連携するセマンティックバージョニング術

Clock Icon2025.02.26

はじめに

コンテナサービスでイメージタグをどのように管理・運用すべきかは悩ましいです。

たとえば、以下のようなアプローチが考えられます。

  1. 割り切って latest 運用
  2. 一意なハッシュ値(Gitのコミットハッシュ等を用いる)
  3. バージョン採番

本記事では、セマンティック・コミット・メッセージを採用し、リリースのたびにコミットメッセージを元に MAJOR.MINOR.PATCH というセマンティックバージョンを採番し、Git(GitHub)とコンテナイメージ(Amazon ECR)で同じバージョンタグを割り振る方法を紹介します。

github-semver-action

セマンティックバージョニングには semantic-release を用い、このプログラムをラップした GitHub Tag Action のワークフロー実行でバージョンをバンプし、このバージョン情報をタグとしてGit(GitHub)とコンテナイメージ(Amazon ECR)に付与します。

GitHub Workflowサンプル

GitHub Workflowsで手動デプロイを実行し、ECRのイメージ・タグを更新し、ECSのタスク定義も更新するサンプルが以下です。

name: bump version and publish

on:
  workflow_dispatch

env:
  AWS_REGION: ap-northeast-1
  ECR_REPOSITORY: your-ecr-repository-name
  TFSTATE_BUCKET: your-s3-bucket-name
  TFSTATE_BUCKET_PATH: your-app/prod
  ROLE_ARN: arn:aws:iam::123456789012:role/GitHubOIDCActions

permissions:
  contents: write
  id-token: write

jobs:
  build-and-push:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ env.ROLE_ARN }}
          role-session-name: gh-oidc-${{ github.run_id }}-${{ github.run_attempt}}
          aws-region: ${{ env.AWS_REGION }}

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      - name: Bump version and push tag
        id: tag-version
        uses: mathieudutour/github-tag-action@v6.2
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}

      - name: Create a GitHub release
        uses: ncipollo/release-action@v1
        with:
          tag: ${{ steps.tag-version.outputs.new_tag }}
          name: Release ${{ steps.tag-version.outputs.new_tag }}
          body: ${{ steps.tag-version.outputs.changelog }}

      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        uses: docker/build-push-action@v6
        with:
          tags: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ steps.tag-version.outputs.new_tag }}
          context: .
          push: true

      - uses: kayac/ecspresso@v2
        with:
          version: v2.4.5

      - name: ecspresso validate
        id: task-validate
        env:
          IMAGE_TAG: ${{ steps.tag-version.outputs.new_tag }}
        run: |
          ecspresso verify

      - name: ecspresso deploy
        id: task-deploy
        env:
          IMAGE_TAG: ${{ steps.tag-version.outputs.new_tag }}
        run: |
          ecspresso deploy

上記の例では、Terraformで管理されたインフラに対して ecspresso で ECSのサービス・タスク定義を更新しています。

JSON のタスク定義ファイルで環境変数としてイメージタグを受け取る({{ must_env IMAGE_TAG }})ようにしておくと、GitHub Actionsとの連携がシームレスになります。

{
  "containerDefinitions": [
    {
      "cpu": 128,
      "image": "{{ tfstate `module.frontend-ecr.aws_ecr_repository.myecr.repository_url` }}:{{ must_env `IMAGE_TAG` }}",
      ...

セマンティックバージョニングについて

セマンティックバージョニング(SemVer)とは、ソフトウェアのバージョン番号を MAJOR.MINOR.PATCH の形式で管理する概念です。

  • MAJOR: 破壊的変更があった場合(例: 1.x.x → 2.0.0)
  • MINOR: 機能追加(例: 1.2.x → 1.3.0)
  • PATCH: バグ修正等、小さな修正があった場合(例: 1.2.3 → 1.2.4)

詳細は次のサイトをご確認ください。

https://semver.org/

セマンティックバージョニングを容易にする semantic-release について

手動で運用すると負荷の高いセマンティックバージョニングを軽減するのが semantic-release です。

MAJOR/MINOR/PATCH に対応する コミットメッセージのフォーマット定義し、前回のリリースからのコミットログからバージョンを上げます。

より具体的には、コミットメッセージのフォーマットは Angular Commit Message Conventions に従っており、以下の通りです。

リリースタイプ Commit message
Patch fix: stop graphite breaking when too much pressure applied
Minor feat: add 'graphiteWidth' option
Major perf: remove graphiteWidth option

BREAKING CHANGE: The graphiteWidth option has been removed.
The default graphite width of 10mm is always used for performance reasons.

スコープを付与して fix*(pencil)**: stop graphite breaking when too much pressure applied* というようにすることもできます。

また、ルールに従わないコミットメッセージの場合、デフォルトでは Patch バージョンが上がります。後述のGitHub Actions版でもデフォルトの振る舞いを変更できます。

コミットのバンプの例

具体的にコミット履歴とタグ(バージョン)がどのように上がっていくか確認します。

$ git log --oneline
f0b4dc1 (HEAD -> main, tag: v3.0.0, origin/main, origin/HEAD) perf: test
cad45c2 feat: test
c839cd2 fix: test
088f872 (tag: v2.2.0) fix: Update README.md
862e0be feat: Update release.yml
24c84b8 (tag: v2.1.5) fix: Update README.md
a4e227a (tag: v2.1.4) fix: Update README.md
  • a4e227a (tag: v2.1.4)をベースラインに、 fix の修正のみがあると、パッチバージョンだけが上がります(2.1.4 -> 2.1.5)。
  • 24c84b8 (tag: v2.1.5)をベースラインに、 fixfeat があると、より上位のマイナーバージョンに繰り上がります(2.1.5 -> 2.2.0)。
  • 088f872 (tag: v2.2.0) をベースラインに、fixfeatmajor があると、、最上位のメジャーバージョンが繰り上がります(2.minor.patch -> 3.0.0)

semantic-release を GitHub Actions から呼び出す

この semantic-release を GitHub Actions向けにラップしたのが mathieudutour/github-tag-action です。

上記サンプルでは、 mathieudutour/github-tag-action 経由で semantic-release も間接的に呼び出しています。

使い方は簡単で、GitHubリポジトリへのアクセス権限が必要なため github_token を指定し、以下のように呼び出すだけです。

    - name: Bump version and push tag
      id: tag-version
      uses: mathieudutour/github-tag-action@v6.2
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}

後続のステップでは、採番されたバージョン(タグ)を ${{ steps.tag-version.outputs.new_tag }} で参照できます。

例えば、Amazon ECR 向けのビルド&プッシュは以下の通りです

     - name: Build, tag, and push image to Amazon ECR
      id: build-image
      uses: docker/build-push-action@v6
      with:
        tags: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ steps.tag-version.outputs.new_tag }}
        context: .
        push: true

GitHub Release と連携

ncipollo/release-action アクションを用いると、GitHub Release と連動できます。

      - name: Create a GitHub release
        uses: ncipollo/release-action@v1
        with:
          tag: ${{ steps.tag-version.outputs.new_tag }}
          name: Release ${{ steps.tag-version.outputs.new_tag }}
          body: ${{ steps.tag-version.outputs.changelog }}

特に、規則通りにコミットログを残すと、リリースノートもきれいになります。

github-release-semver

モノレポの場合

一つのレポジトリ内に複数のプロジェクトが管理されている場合、プロジェクトごとにバージニングしたいケースもあるかもしれません。
そのような場合は、次のモノレポ版の semantic-release-monorepo をご検討下さい。

https://github.com/pmowrer/semantic-release-monorepo

最後に

GitHub Tag Action を用いてセマンティックバージョンを採番し、Gitのタグとコンテナイメージ(Amazon ECR)のイメージタグを連動させる方法を紹介しました。

コンテナイメージの latest 運用を避けたい、一方で、Gitのコミットハッシュ値は味気ないとお思いのチームの一案になれば幸いです。

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.