Background
As the Consumer Product Squad grows and more repositories become part of our ecosystem, keeping release notes consistent and useful across all of them is important.
The goal is to have a unified, automated release notes process across all key CPS repositories so that every release tells a clear, consistent state of the actual work that went into it.
The Generate Release Notes picks up release note entries written directly in PR descriptions, groups them by label into chapters, and produces a clean Markdown block ready to drop into a release draft.
We strongly recommend improving the current solution into the newest one. Please see the described updated solution below.
Feature
Set up the Generate Release Notes action with two workflows that together cover the full release notes lifecycle:
- A release draft workflow that auto-generates notes at release time.
- A PR check workflow that makes sure every PR includes release note content before it gets merged.
If this is already set up in your project, great — please check that you're on the latest version and that your configuration matches the current recommended setup below.
Business Value
- Every release gets structured, readable notes without anyone having to write them from scratch.
- Developers are nudged to describe their changes in PR descriptions, which is good practice regardless of release notes.
- Releases across all CPS repositories start to look and feel consistent to everyone reading them.
Solution Example
A project that has the full setup in place is common-abstraction-layer project. You can use it as a working reference:
Proposed Solution
There are two mandatory parts of the Release Notes Generator solution. In the following step-by-step is described current newest version. Walk through every step, the optional one is easy to implement and well worth adding.
For the security best practice, there is need to change a version tags for full SHA of the corresponding release commit in all described workflow files.
1. Release Draft Workflow
This workflow is the primary piece that generates the release draft based on contained Release Notes from PRs. The whole logic is set inside the .github/workflows/release_draft.yml file. This workflow is triggered manually. You give it a target tag name, it generates the release notes from everything merged since the previous tag, creates the tag, and opens a draft release. You review and publish from there.
name: Draft Release
on:
workflow_dispatch:
inputs:
tag-name:
description: 'Name of git tag to be created, and then draft release created. Syntax: "v[0-9]+.[0-9]+.[0-9]+".'
required: true
from-tag-name:
description: 'Name of the git tag from which to detect changes from. Default value: latest tag. Syntax: "v[0-9]+.[0-9]+.[0-9]+".'
required: false
jobs:
release-draft:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6 # replace with SHA
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-python@v6 # replace with SHA
with:
python-version: '3.14'
- name: Check Format of Received Tag
id: check-version-tag
uses: AbsaOSS/version-tag-check@v1 # replace with SHA
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
github-repository: ${{ github.repository }}
version-tag: ${{ github.event.inputs.tag-name }}
- name: Check Format of Received From Tag
if: ${{ github.event.inputs.from-tag-name }}
id: check-version-from-tag
uses: AbsaOSS/version-tag-check@v1 # replace with SHA
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
github-repository: ${{ github.repository }}
version-tag: ${{ github.event.inputs.from-tag-name }}
should-exist: true
- name: Generate Release Notes
id: generate_release_notes
uses: AbsaOSS/generate-release-notes@v1.3.0 # replace with SHA
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
release-notes-title: "## [Rr]elease [Nn]otes"
tag-name: ${{ github.event.inputs.tag-name }}
from-tag-name: ${{ github.event.inputs.from-tag-name }}
chapters: |
- {"title": "Breaking Changes 💥", "label": "breaking-change"}
- {"title": "New Features 🎉", "label": "enhancement"}
- {"title": "Bugfixes 🛠", "label": "bug"}
- {"title": "Infrastructure ⚙️", "label": "infrastructure"}
- {"title": "Documentation 📜", "label": "documentation"}
- {"title": "Entries to skip 🚫", "label": "no RN", "hidden": true}
duplicity-scope: 'none'
warnings: true
skip-release-notes-labels: "no RN,duplicate,invalid,wontfix"
print-empty-chapters: false
row-format-issue: '_{title}_ {developers} in {number}'
row-format-pr: '_{title}_ {developers} in {number}'
row-format-link-pr: true
- name: Create and Push Tag
uses: actions/github-script@v9 # replace with SHA
env:
TAG_NAME: ${{ github.event.inputs.tag-name }}
with:
script: |
const tag = process.env.TAG_NAME;
const ref = `refs/tags/${tag}`;
const sha = context.sha;
await github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: ref,
sha: sha
});
console.log(`Tag created: ${tag}`);
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Create Draft Release
uses: softprops/action-gh-release@v3 # replace with SHA
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
name: ${{ github.event.inputs.tag-name }}
body: ${{ steps.generate_release_notes.outputs.release-notes }}
tag_name: ${{ github.event.inputs.tag-name }}
draft: true
prerelease: false
The chapters configuration above is a suggested starting point, that reflects the newest adapted solution. Feel free to adapt the titles and labels to whatever makes sense for your project. That said, every label you reference in chapters must actually exist in your repository's label settings, otherwise that chapter simply won't match anything. The full list of available configuration options can be found in the configuration reference.
2. Check PR Release Notes Workflow
This workflow is checking, that every PR is containing Release Notes info. For implementing the newest solution create .github/workflows/check_pr_release_notes.yml file. It runs automatically on every PR against master and fails if the PR description doesn't contain a proper Release Notes section. The configuration inputs' description can be found at GitHub Action inputs description.
name: Check PR Release Notes
on:
pull_request:
types: [opened, synchronize, reopened, edited, labeled, unlabeled]
branches: [ master ]
jobs:
check-release-notes:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v6 # replace with SHA
with:
python-version: '3.14'
- name: Check presence of release notes in PR description
uses: AbsaOSS/release-notes-presence-check@v0.4.0 # replace with SHA
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
github-repository: ${{ github.repository }}
pr-number: ${{ github.event.number }}
title: "## [Rr]elease [Nn]otes"
skip-labels: 'no RN'
skip-placeholders: 'TBD'
If a PR genuinely doesn't need release notes (CI tweak, a dependency bump) just add the no RN label and this check will skip it automatically.
3. PR Template (optional but recommended)
We highly recommend to create a PR template. It can be done by adding .github/pull_request_template.md file. This pre-fills every new PR with template containing a ## Release Notes section that automates the flow of writing the key points of every PR. In the CPS projects we usually use the following one:
<!-- What problem does it solve or what feature does it add? -->
## Overview
<!-- Summarize the key changes for release notes. -->
## Release Notes
- TBD: 1st item of release notes
- TBD: 2nd item of release notes
<!-- Add attached issue that this PR solves. -->
## Related
Closes #issue_number
Release Notes check workflow treats the TBD placeholders as "not filled in yet" and will fail until the author writes something real.
4. Add the no RN label to the repo
We commonly use a no RN label in the repositories. Labeling solves following two cases:
- PRs with this label skip the release notes presence check (Part 2).
- PRs and issues with this label are excluded from the generated release notes entirely (Part 1).
It's the way how eliminate anything that genuinely shouldn't show up in a release (CI changes, renovate bumps...).
One thing worth understanding.
The title value in the Release Notes checker workflow and the release-notes-title value in the Release Draft workflow are both set to "## [Rr]elease [Nn]otes" in this case. That regex is what both tools use to locate the release notes section in a PR description. If you decide not to use the PR template or your team uses a different heading format, make sure you update both of those values to match. They need to be consistent with each other and with whatever heading actually appears in your PR bodies. The default behavior for Release Notes Presence Check title is '[Rr]elease [Nn]otes:'.
Background
As the Consumer Product Squad grows and more repositories become part of our ecosystem, keeping release notes consistent and useful across all of them is important.
The goal is to have a unified, automated release notes process across all key CPS repositories so that every release tells a clear, consistent state of the actual work that went into it.
The Generate Release Notes picks up release note entries written directly in PR descriptions, groups them by label into chapters, and produces a clean Markdown block ready to drop into a release draft.
Feature
Set up the Generate Release Notes action with two workflows that together cover the full release notes lifecycle:
If this is already set up in your project, great — please check that you're on the latest version and that your configuration matches the current recommended setup below.
Business Value
Solution Example
A project that has the full setup in place is common-abstraction-layer project. You can use it as a working reference:
no RNlabel present in the repository (label used to skip release notes when genuinely not needed)Proposed Solution
There are two mandatory parts of the Release Notes Generator solution. In the following step-by-step is described current newest version. Walk through every step, the optional one is easy to implement and well worth adding.
1. Release Draft Workflow
This workflow is the primary piece that generates the release draft based on contained Release Notes from PRs. The whole logic is set inside the
.github/workflows/release_draft.ymlfile. This workflow is triggered manually. You give it a target tag name, it generates the release notes from everything merged since the previous tag, creates the tag, and opens a draft release. You review and publish from there.The
chaptersconfiguration above is a suggested starting point, that reflects the newest adapted solution. Feel free to adapt the titles and labels to whatever makes sense for your project. That said, every label you reference inchaptersmust actually exist in your repository's label settings, otherwise that chapter simply won't match anything. The full list of available configuration options can be found in the configuration reference.2. Check PR Release Notes Workflow
This workflow is checking, that every PR is containing Release Notes info. For implementing the newest solution create
.github/workflows/check_pr_release_notes.ymlfile. It runs automatically on every PR againstmasterand fails if the PR description doesn't contain a proper Release Notes section. The configuration inputs' description can be found at GitHub Action inputs description.If a PR genuinely doesn't need release notes (CI tweak, a dependency bump) just add the
no RNlabel and this check will skip it automatically.3. PR Template (optional but recommended)
We highly recommend to create a PR template. It can be done by adding
.github/pull_request_template.mdfile. This pre-fills every new PR with template containing a## Release Notessection that automates the flow of writing the key points of every PR. In the CPS projects we usually use the following one:Release Notes check workflow treats the
TBDplaceholders as "not filled in yet" and will fail until the author writes something real.4. Add the
no RNlabel to the repoWe commonly use a
no RNlabel in the repositories. Labeling solves following two cases:It's the way how eliminate anything that genuinely shouldn't show up in a release (CI changes, renovate bumps...).