Release Drafter commitish Issue — Generating Release Notes Based on the Release Branch

2026-03-19 hit count image

Analyzing the release note mismatch issue when Release Drafter's commitish is fixed to main, and introducing how to split workflows into autolabel and release note generation to produce accurate release notes based on the release branch.

github_actions

The Problem

Release Drafter is a GitHub Action that automatically generates release note drafts based on PR labels. We had been using separate Release Drafter configurations per service in a monorepo, but ran into an issue where PRs that should be included were missing, or PRs that shouldn’t be included were appearing in the release notes.

For details on automating Release notes with Release Drafter and validating labels, please refer to the following blog posts.

How Release Drafter Works

Release Drafter generates release notes in the following order:

  1. Find the latest tag (previous release) using tag-prefix
  2. Retrieve the commit history from the previous release tag to the HEAD of the commitish (target branch)
  3. Find PRs linked to those commits and classify them by PR labels into categories
  4. Generate a release note draft according to the template

The key here is commitish. The range of PRs included in the release notes depends on which branch this value points to.

The Problem with commitish: main

In the existing configuration, commitish was fixed to main in release-drafter.yml.

# .github/release-drafter.yml (before)
commitish: main

This leads to the following problems:

1. Changes only in the release branch are missing

Changes applied directly to the release branch via hotfixes or cherry-picks don’t exist on the main branch, so they are excluded from the release notes.

         hotfix ──────┐

release: ──A──B──C─┼──H──    ← H(hotfix) is not on main, so it's missing from release notes

main: ──A──B──C──D──E──F──

2. Changes merged to main after the release branch was created are included

PRs merged to main after the release branch was created are also included in the release notes. These are changes not actually part of the current release.

main: ──A──B──C──D──E──F──    ← E, F are for the next release but included in release notes

release: ──A──B──C─┘

Solution

Core Idea: Splitting the Workflow

Release Drafter provides two main features:

FeatureDescriptionWhen to Run
AutolabelerAutomatically assigns labels to PRsWhen a PR is created or updated
Release note generationCreates release note drafts based on labelsWhen there are changes to the release branch

Previously, both features were executed in a single workflow, but since their execution timing and target branches differ, splitting them is the rational approach.

  • Autolabel: Runs on PR events → targets the main branch
  • Release note generation: Runs on push to release branches → targets the release branch

Workflow 1: PR Label Checker (autolabel only)

A workflow that only assigns labels automatically when a PR is created or updated. Release note generation is disabled with 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 }}

Setting disable-releaser: true prevents Release Drafter from generating release note drafts, running only the autolabel feature.

Workflow 2: Release Drafter (release notes only)

A workflow that generates release notes when a push occurs to a release branch. Label assignment is disabled with disable-autolabeler: true, and commitish is dynamically set to the release branch.

# .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 }}

The key is commitish: ${{ env.FULL_BRANCH_NAME }}. By dynamically passing the release branch name (e.g., release/serviceName/1.2.0), only changes included in that release branch are reflected in the release notes.

Updating release-drafter.yml

Remove commitish from the shared configuration file. Since it’s now passed dynamically from the workflow, there’s no need to hardcode it in the configuration file.

# .github/release-drafter.yml (after)
version-resolver:
  minor:
    labels:
      - 'minor'
  patch:
    labels:
      - 'patch'
  default: minor
# commitish: main  ← removed
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
change-title-escapes: '\<*_&'
template: |
  ## Changes
  $CHANGES

Updating the Composite Action: Supporting Push Events

The existing branch name extraction Composite Action only supported pull_request events. It needs to be updated to also work with push events to release branches.

For details on how to use Composite Actions, please refer to the following link.

# .github/actions/extract_branch_and_service_name/action.yml
runs:
  using: composite
  steps:
    - id: extract_branch_and_service_name
      shell: bash
      run: |
        # Before
        # FULL_BRANCH_NAME=${{ github.event.pull_request.head.ref }}

        # After: Support both PR events and push events
        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 event: Gets the branch name from github.event.pull_request.head.ref.
  • push event: Extracts the branch name by removing the refs/heads/ prefix from the GITHUB_REF environment variable.

Key Release Drafter Action Inputs

Here’s a summary of the key Release Drafter Action Inputs used in the workflow split.

InputDefaultDescription
config-namerelease-drafter.ymlPath to the configuration file (relative to .github/)
commitishWorkflow execution branchRelease target branch or commit. Changes up to this branch’s HEAD are included in notes
disable-releaserfalseWhen true, disables release note generation and runs only the autolabel feature
disable-autolabelerfalseWhen true, disables autolabel and runs only release note generation
tag-prefix''Release tag prefix. Filters by this prefix when searching for previous releases
filter-by-commitishfalseWhen true, only considers releases matching the commitish when searching for previous releases

Considerations

Separating configuration files per service in a monorepo

When managing multiple services in a monorepo, separate release-drafter-for-{serviceName}.yml configuration files per service with different tag-prefix values to distinguish releases.

# .github/release-drafter-for-serviceName.yml
tag-prefix: serviceName-v

This searches for previous releases from tags like serviceName-v1.2.0 and includes only subsequent changes in the release notes.

Release branch naming conventions

The release/** pattern and the logic for extracting service names in the Composite Action must be consistent. For example, if there’s a rule to extract serviceName as the service name from release/serviceName/1.2.0, this convention must be followed when creating branches.

For details on how to validate branch names with GitHub Actions, please refer to the following link.

Using filter-by-commitish

When multiple release branches exist simultaneously, setting filter-by-commitish: true ensures that only releases created from the relevant release branch are considered when searching for previous releases. This prevents releases from different release branches from being mixed.

Conclusion

Fixing Release Drafter’s commitish to main causes inaccurate release notes due to differences between the release branch and the main branch. By splitting the workflow into autolabel only and release note generation only, and dynamically setting commitish to the release branch, you can generate accurate release notes.

Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!

App promotion

You can use the applications that are created by this blog writer Deku.
Deku created the applications with Flutter.

If you have interested, please try to download them for free.



SHARE
Twitter Facebook RSS