pubspec.yamlのバージョンをGithub Actionsで更新する
はじめに
GitHub Actionsをあまり書いたことのない人間だったのですが、挑戦する機会があったので内容をまとめたいと思います。
また、題材について、似たようなことをやりたい人の一助になれば幸いです。
※ 補足 作成当初は気づいていませんでしたが、題材については似た先人の記事もありました!
(改めてzennにまとめる際に参考にさせてもらいました)
対象者
後述の「題材」に近い内容をGitHub Actionsで記述したい人
※ GitHub Actionsの知識は不問。
バージョン情報
バージョンみたいなものはなさそうなので、日付でしか書けないですが、2024年1月時点・無料アカウントで確認しています。
Github Actionsに関わるChangelog
記事記載時点での最新情報
書いていること・書いていないこと
書いていること
- サンプル
- ワークフローの記述
- 各記述の説明
書いていないこと
- GitHub Actionsのオンボーディング
- アクションの記述
オンボーディングに近いところは小さなコミュニティで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にプルリクエストが作成されたタイミング」です。
トリガー部分の参考
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」でいいと思います。
その他の情報
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」部分は、有志の方が作ってくださっている処理です。
詳細は以下
今回は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 }}"
コミットの実施。以下を利用
コミットメッセージは新しいバージョンにしてます。
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 }}
プルリクの作成。以下を利用
developに向けてバージョン名でプルリクを作成します。
他参考
Discussion