目次
問題の状況
Release Drafterは、PRのラベルに基づいてリリースノートのドラフトを自動生成するGitHub Actionです。モノレポでサービスごとにRelease Drafterの設定を分離して使用していましたが、リリースノートに含まれるべきPRが漏れたり、含まれるべきでないPRが含まれてしまう問題が発生しました。
Release Drafterを使用したRelease notesの自動化方法とラベル検査方法については、以下のブログ記事をご参照ください。
Release Drafterの動作原理
Release Drafterは以下の順序でリリースノートを生成します。
tag-prefixで最新のタグ(前回リリース)を検索する- 前回リリースタグから
commitish(対象ブランチ)のHEADまでのコミット履歴を取得する - 該当コミットに関連するPRを検出し、PRのラベルに基づいてカテゴリを分類する
- テンプレートに沿ってリリースノートのドラフトを生成する
ここで重要なのは**commitish**です。この値がどのブランチを指すかによって、リリースノートに含まれるPRの範囲が決まります。
commitish: mainの問題点
既存の設定ではrelease-drafter.ymlのcommitishがmainに固定されていました。
# .github/release-drafter.yml(修正前)
commitish: main
この場合、以下の問題が発生します。
1. releaseブランチのみの変更が漏れる
ホットフィックスやcherry-pickでreleaseブランチに直接反映した変更はmainブランチに存在しないため、リリースノートに含まれません。
hotfix ──────┐
▼
release: ──A──B──C─┼──H── ← H(hotfix)はmainにないためリリースノートから漏れる
│
main: ──A──B──C──D──E──F──
2. releaseブランチ作成後にmainにマージされた内容が含まれる
releaseブランチを作成した時点以降にmainにマージされたPRもリリースノートに含まれます。これらは実際には今回のリリースに含まれない変更です。
main: ──A──B──C──D──E──F── ← E, Fは次のリリース対象だがリリースノートに含まれる
│
release: ──A──B──C─┘
解決方法
核心アイデア: ワークフローの分離
Release Drafterは大きく2つの機能を提供します。
| 機能 | 説明 | 実行タイミング |
|---|---|---|
| Autolabeler | PRにラベルを自動付与 | PRが作成・更新された時 |
| Release note生成 | ラベルに基づいてリリースノートを作成 | リリース対象ブランチに変更があった時 |
既存では1つのワークフローで両方の機能を同時に実行していましたが、各機能の実行タイミングと対象ブランチが異なるため、分離するのが合理的です。
- Autolabel: PRイベントで実行 → mainブランチ対象
- Release note生成: releaseブランチへのpush時に実行 → releaseブランチ対象
ワークフロー1: PR Label Checker(autolabel専用)
PRが作成または更新された時にラベルのみを自動付与するワークフローです。disable-releaser: trueでリリースノート生成機能を無効化します。
# .github/workflows/pr-label-checker.yml
name: PR Label Checker
on:
pull_request:
types: [opened, reopened, synchronize]
permissions:
contents: read
jobs:
check_pr_labels:
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Extract branch and service name
id: extract
uses: ./.github/actions/extract_branch_and_service_name
- name: Set environment variables
run: |
echo "SERVICE_NAME=${{ steps.extract.outputs.SERVICE_NAME }}" >> $GITHUB_ENV
- name: Autolabel
uses: release-drafter/release-drafter@v6
with:
config-name: release-drafter.yml
disable-releaser: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
disable-releaser: trueを設定すると、Release Drafterがリリースノートのドラフトを生成せず、autolabel機能のみを実行します。
ワークフロー2: Release Drafter(リリースノート専用)
releaseブランチへのpush時にリリースノートを生成するワークフローです。disable-autolabeler: trueでラベル付与機能を無効化し、commitishを該当releaseブランチに動的設定します。
# .github/workflows/release-drafter-on-release-branch.yml
name: Release Drafter (on release branch)
on:
push:
branches:
- 'release/**'
permissions:
contents: read
jobs:
update_release_draft:
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Extract branch and service name
id: extract
uses: ./.github/actions/extract_branch_and_service_name
- name: Set environment variables
run: |
echo "SERVICE_NAME=${{ steps.extract.outputs.SERVICE_NAME }}" >> $GITHUB_ENV
echo "FULL_BRANCH_NAME=${{ steps.extract.outputs.FULL_BRANCH_NAME }}" >> $GITHUB_ENV
- name: Run Release Drafter
uses: release-drafter/release-drafter@v6
with:
config-name: release-drafter.yml
commitish: ${{ env.FULL_BRANCH_NAME }}
disable-autolabeler: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ポイントはcommitish: ${{ env.FULL_BRANCH_NAME }}です。releaseブランチ名(例: release/serviceName/1.2.0)を動的に渡すことで、該当releaseブランチに含まれる変更のみをリリースノートに反映します。
release-drafter.yml設定の変更
共通設定ファイルからcommitishを削除します。ワークフローから動的に渡すため、設定ファイルに固定する必要はありません。
# .github/release-drafter.yml(修正後)
version-resolver:
minor:
labels:
- 'minor'
patch:
labels:
- 'patch'
default: minor
# commitish: main ← 削除
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&'
template: |
## Changes
$CHANGES
Composite Actionの修正: pushイベント対応
既存のブランチ名抽出Composite Actionはpull_requestイベントのみ対応していました。releaseブランチへのpushイベントでも動作するよう修正が必要です。
Composite Actionの使い方については以下のリンクをご参照ください。
# .github/actions/extract_branch_and_service_name/action.yml
runs:
using: composite
steps:
- id: extract_branch_and_service_name
shell: bash
run: |
# 修正前
# FULL_BRANCH_NAME=${{ github.event.pull_request.head.ref }}
# 修正後: PRイベントとpushイベントの両方に対応
if [ -n "${{ github.event.pull_request.head.ref }}" ]; then
FULL_BRANCH_NAME=${{ github.event.pull_request.head.ref }}
else
FULL_BRANCH_NAME=${GITHUB_REF#refs/heads/}
fi
pull_requestイベント:github.event.pull_request.head.refからブランチ名を取得します。pushイベント:GITHUB_REF環境変数からrefs/heads/プレフィックスを除去してブランチ名を抽出します。
Release Drafterの主要Action Inputs
ワークフロー分離に使用したRelease Drafterの主要Action Inputsをまとめます。
| Input | デフォルト値 | 説明 |
|---|---|---|
config-name | release-drafter.yml | 使用する設定ファイルパス(.github/基準) |
commitish | ワークフロー実行ブランチ | リリース対象ブランチまたはコミット。このブランチのHEADまでの変更をリリースノートに含める |
disable-releaser | false | trueにするとリリースノート生成を無効化し、autolabel機能のみ実行 |
disable-autolabeler | false | trueにするとautolabelを無効化し、リリースノート生成のみ実行 |
tag-prefix | '' | リリースタグのプレフィックス。前回リリース検索時にこのプレフィックスでフィルタリング |
filter-by-commitish | false | trueにすると前回リリース検索時にcommitishと一致するリリースのみを対象とする |
注意事項
モノレポでのサービス別設定ファイル分離
モノレポで複数サービスを管理する場合、サービスごとにrelease-drafter-for-{serviceName}.yml設定ファイルを分離し、tag-prefixをサービスごとに異なる値に設定してリリースを区別します。
# .github/release-drafter-for-serviceName.yml
tag-prefix: serviceName-v
これにより、serviceName-v1.2.0のようなタグから前回リリースを検索し、その後の変更のみをリリースノートに含めます。
releaseブランチのネーミング規約
release/**パターンとComposite Actionでサービス名を抽出するロジックが一致する必要があります。例えば、release/serviceName/1.2.0からserviceNameをサービス名として抽出するルールがある場合、ブランチ作成時にこの規約を必ず守る必要があります。
GitHub Actionsでブランチ名を検査する方法については以下のリンクをご参照ください。
filter-by-commitishの活用
複数のreleaseブランチが同時に存在する場合、filter-by-commitish: trueを設定すると、前回リリース検索時に該当releaseブランチで作成されたリリースのみを対象とします。異なるreleaseブランチのリリースが混在するのを防ぐことができます。
まとめ
Release Drafterのcommitishをmainに固定すると、releaseブランチとmainブランチの差異によりリリースノートが不正確になる問題が発生します。ワークフローをautolabel専用とリリースノート生成専用に分離し、commitishをreleaseブランチに動的設定することで、正確なリリースノートを生成できます。
私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!
アプリ広報
Dekuが開発したアプリを使ってみてください。Dekuが開発したアプリはFlutterで開発されています。興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。