🌟

pubspec.yamlのバージョンをGithub Actionsで更新する

2024/02/04に公開

はじめに

GitHub Actionsをあまり書いたことのない人間だったのですが、挑戦する機会があったので内容をまとめたいと思います。

また、題材について、似たようなことをやりたい人の一助になれば幸いです。

※ 補足 作成当初は気づいていませんでしたが、題材については似た先人の記事もありました!
(改めてzennにまとめる際に参考にさせてもらいました)
https://naipaka.hatenablog.com/entry/2022/03/18/204856

対象者

後述の「題材」に近い内容をGitHub Actionsで記述したい人
※ GitHub Actionsの知識は不問。

バージョン情報

バージョンみたいなものはなさそうなので、日付でしか書けないですが、2024年1月時点・無料アカウントで確認しています。

Github Actionsに関わるChangelog
記事記載時点での最新情報

書いていること・書いていないこと

書いていること

書いていないこと

オンボーディングに近いところは小さなコミュニティでLTとして発表したので、
以下のScrapboxの資料をご参照ください。(題材の仕様を少し緩く設定しています)
Github Actions事始め

題材

アプリのリリース媒体用のプルリクを作ったときに、
pubspec.yamlのバージョンを適切にアップデートするプルリクを作成する。

仕様
トリガー

  • mainにプルリクエストが作成されたタイミング

詳細

  • バージョンアップの変更はdevelop向けのプルリクとして作成する。
  • 「developからmain」へのプルリクのタイトル文言によって、バージョンアップの仕方を変える。
    • 「メジャー」が含まれた場合 : メジャーバージョンを上げる。
    • 「マイナー」が含まれた場合 : マイナーバージョンを上げる。
    • 「パッチ」が含まれた場合 : パッチバージョンを上げる。
    • 上記いずれも含まれなかった場合 : パッチバージョンを上げる。
  • ビルド番号はどの場合でも無条件で上げる。

運用想定

  • 「developからmain」へリリースブランチを作成する。
    • ※「メジャー」「マイナー」「パッチ」いずれか適切な名称をつける。
  • いざリリースできるとなった際、新規作成されたバージョンアップのプルリクエストをdevelopにマージ。
  • 元々作成したブランチをmainにマージ。

背景
作成のモチベーションとしては、バージョンアップを忘れることがよくあったからでした(汗
また他にも前提として以下のような状況がありました。

  • Git Flowを使っている(developとmainブランチが存在する)
  • ローカル環境で媒体作成をしている。

外部のCDツール等を利用している場合は、求められる処理は違ってくる可能性があります。

全容

最初に全容です。

name: version up
on:
  pull_request:
    types: [opened]
    branches:
      - main
jobs:
  create-version-up-pr:
    runs-on: ubuntu-latest
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      FILE_PATH: pubspec.yaml
      TZ: 'Asia/Tokyo'
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: develop

      - name: Set current datetime as env variable
        run: echo "CURRENT_DATETIME=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV

      - name: Create new branch
        run: |
          git switch -c fix/versionup_${{ env.CURRENT_DATETIME }}
          git push -u origin fix/versionup_${{ env.CURRENT_DATETIME }}

      - name: Determine version type from PR title
        id: version_type
        run: |
          PR_TITLE="${{ github.event.pull_request.title }}"
          if [[ "$PR_TITLE" == *"メジャー"* ]]; then
            echo "VERSION_TYPE=major" >> $GITHUB_ENV
          elif [[ "$PR_TITLE" == *"マイナー"* ]]; then
            echo "VERSION_TYPE=minor" >> $GITHUB_ENV
          else
            echo "VERSION_TYPE=patch" >> $GITHUB_ENV
          fi

      - name: version up
        run: |
          OLD_VERSION=$(awk '/version:/ {print $2; exit}' ${{ env.FILE_PATH }})
          IFS='.' read -r -a version_parts <<< "${OLD_VERSION%+*}"
          IFS='+' read -r -a build_parts <<< "${OLD_VERSION##*.}"
          new_build=$((build_parts[1] + 1))
          new_major=${version_parts[0]}
          new_minor=${version_parts[1]}
          new_patch=${version_parts[2]}
          case $VERSION_TYPE in
            major)
              new_major=$((new_major + 1))
              new_minor=0
              new_patch=0
              ;;
            minor)
              new_minor=$((new_minor + 1))
              new_patch=0
              ;;
            patch)
              new_patch=$((new_patch + 1))
              ;;
          esac
          NEW_VERSION="${new_major}.${new_minor}.$new_patch+$new_build"
          echo "NEW_VERSION=${NEW_VERSION}" >> $GITHUB_ENV
          sed -i "0,/version: .*/s//version: $NEW_VERSION/" "${{ env.FILE_PATH }}"

      - name: Add and Commit
        uses: EndBug/add-and-commit@v9
        with:
          branch: fix/versionup_${{ env.CURRENT_DATETIME }}
          message: ${{ env.NEW_VERSION }}
          add: "${{ env.FILE_PATH }}"

      - name: Create pull request
        uses: repo-sync/pull-request@v2
        with:
          source_branch: fix/versionup_${{ env.CURRENT_DATETIME }}
          destination_branch: develop
          pr_title: ${{ env.NEW_VERSION }}

各ブロックごとの説明

name・on

name: version up
on:
  pull_request:
    types: [opened]
    branches:
      - main

このワークフローの名前と、ワークフローの実行タイミング(トリガー)を指定しています。
設定は仕様通りで「mainにプルリクエストが作成されたタイミング」です。

トリガー部分の参考
https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#on

typesは「opened」とだけ書くことで、「作成されたタイミング」のみに実行されるようにしました。
「opened」を指定していないと、developに何かしら更新がある度に、バージョンアップのプルリクが作成されてしまいます。

jobsの設定

jobs:
  create-version-up-pr:
    runs-on: ubuntu-latest
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      FILE_PATH: pubspec.yaml
      TZ: 'Asia/Tokyo'

create-version-up-pr
job idです。(参考)
この指定で動いたんですが、公式みるとスネークケース(create_version_up_pr)の方が良さそうです。(今の記述が動作確認取れているので一旦このままにしてます)

runs-on: ubuntu-latest
処理を動かすOSの指定。基本は「ubuntu-latest」でいいと思います。
その他の情報
https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#github-ホステッド-ランナーの選択

env
処理で利用する環境変数

GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
呪文レベルかも。Githubに対して操作させたいときはGH_TOKENの指定が必要です。
GitHubは枠ーフローで使用するシークレットキーを自動的に生成してくれています。別で何かGithubの設定変更するとかない。

FILE_PATH: pubspec.yaml
今回変更を加えるファイル名

TZ: 'Asia/Tokyo'
ブランチ作成時などに時間を利用したいので、タイムゾーンの指定。

ちなみにGPT4からのフィードバックですが、
基本は「envフィールドは各ステップではなく、ジョブのレベルで定義されるべきです」とのことです。

step 「Checkout」

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: develop

Git操作をするワークフローでは半分呪文のようなのですが。
最初にリポジトリのソースコードを取得する意味でcheckoutします。
(私の解釈を含んだ説明です)

「uses: actions/checkout@v4」部分は、有志の方が作ってくださっている処理です。
詳細は以下
https://github.com/actions/checkout

今回はdevelopのブランチのソースコードを扱いたいので「ref: develop」を指定しています。
指定しなかった場合は、ワークフローのトリガーとなったmainブランチのソースコードが対象になります。

step 「Set current datetime as env variable」

      - name: Set current datetime as env variable
        run: echo "CURRENT_DATETIME=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV

現在時刻を$GITHUB_ENVとして登録します。
$GITHUB_ENVに登録することで別のstepで、現在時刻を利用可能です。

step 「Create new branch」

      - name: Create new branch
        run: |
          git switch -c fix/versionup_${{ env.CURRENT_DATETIME }}
          git push -u origin fix/versionup_${{ env.CURRENT_DATETIME }}

先ほどの現在時刻の値を利用して、ブランチ作成し新規ブランチpushします。
※ 現在時刻を利用するのは名前が被らないようにするため

上述のようにrunでgitコマンドを実行することも可能です。

step 「Determine version type from PR title」

      - name: Determine version type from PR title
        id: version_type
        run: |
          PR_TITLE="${{ github.event.pull_request.title }}"
          if [[ "$PR_TITLE" == *"メジャー"* ]]; then
            echo "VERSION_TYPE=major" >> $GITHUB_ENV
          elif [[ "$PR_TITLE" == *"マイナー"* ]]; then
            echo "VERSION_TYPE=minor" >> $GITHUB_ENV
          else
            echo "VERSION_TYPE=patch" >> $GITHUB_ENV
          fi

プルリクのタイトルから、どのバージョンを上げるか判定します。
今回タイトルにしましたが、プルリクのラベルとかで判定してもいいかもしれません。

※ shell部分はGPT4を利用しながら実装しました。

step 「version up」

      - name: version up
        run: |
          OLD_VERSION=$(awk '/version:/ {print $2; exit}' ${{ env.FILE_PATH }})
          IFS='.' read -r -a version_parts <<< "${OLD_VERSION%+*}"
          IFS='+' read -r -a build_parts <<< "${OLD_VERSION##*.}"
          new_build=$((build_parts[1] + 1))
          new_major=${version_parts[0]}
          new_minor=${version_parts[1]}
          new_patch=${version_parts[2]}
          case $VERSION_TYPE in
            major)
              new_major=$((new_major + 1))
              new_minor=0
              new_patch=0
              ;;
            minor)
              new_minor=$((new_minor + 1))
              new_patch=0
              ;;
            patch)
              new_patch=$((new_patch + 1))
              ;;
          esac
          NEW_VERSION="${new_major}.${new_minor}.$new_patch+$new_build"
          echo "NEW_VERSION=${NEW_VERSION}" >> $GITHUB_ENV
          sed -i "0,/version: .*/s//version: $NEW_VERSION/" "${{ env.FILE_PATH }}"

shell部分はGPT4を利用しながら実装しました。(実力でないことが後ろめたくて先に書きたくなる<汗)

本当に、よく指定通りに書いてくれます。
題材くらい、仕様まとめられれば、GPT4に叩きを作ってもらって、動作確認→調整で割と完成できる印象です。

step 「Add and Commit」

      - name: Add and Commit
        uses: EndBug/add-and-commit@v9
        with:
          branch: fix/versionup_${{ env.CURRENT_DATETIME }}
          message: ${{ env.NEW_VERSION }}
          add: "${{ env.FILE_PATH }}"

コミットの実施。以下を利用
https://github.com/EndBug/add-and-commit

コミットメッセージは新しいバージョンにしてます。

step 「Create pull request」

      - name: Create pull request
        uses: repo-sync/pull-request@v2
        with:
          source_branch: fix/versionup_${{ env.CURRENT_DATETIME }}
          destination_branch: develop
          pr_title: ${{ env.NEW_VERSION }}

プルリクの作成。以下を利用
https://github.com/repo-sync/pull-request

developに向けてバージョン名でプルリクを作成します。

他参考

https://zenn.dev/spacemarket/articles/ce43faa3ba0e81
https://zenn.dev/itouuuuuuuuu/articles/ad75acc2a22828

Discussion