Skip to content

Release Notes Generator #25

Release Notes Generator

Release Notes Generator #25

name: Release Notes Generator
run-name: Release Notes Generator
on:
workflow_dispatch:
inputs:
new-release-tag:
description: 'Tag name of the *new* release'
required: true
type: string
default: 'e.g., v1.1 or v2.0'
previous-release-reference:
description: 'Tag name of the *previous* release or the commit SHA right *before* the first commit in the new release'
required: true
type: string
default: 'e.g., v1.0 or 2f4a6b2'
release-notes-source:
description: 'Release Notes Source'
required: true
type: choice
options:
- Commit Messages
- Pull Requests
default: 'Pull Requests'
pr-release-notes-mode:
description: 'Release Notes Mode (only affects release notes if you chose source as Pull Requests)'
required: false
type: choice
options:
- Short
- Full
default: 'Full'
jobs:
run-script-to-generate-release-notes:
name: Generate Release Notes
runs-on: ubuntu-latest
env:
NEW_RELEASE_TAG: ${{ inputs.new-release-tag }}
PREVIOUS_RELEASE_REFERENCE: ${{ inputs.previous-release-reference }}
RELEASE_NOTES_SOURCE: ${{ inputs.release-notes-source }}
RELEASE_NOTES_MODE: ${{ inputs.pr-release-notes-mode }}
# secrets.GITHUB_TOKEN is automatically generated by GitHub for each workflow run
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Copy this repository to the Linux runner
uses: actions/checkout@v4
with:
# By default actions/checkout fetches the .git folder with only a small part of the git history
# usually the latest commit only, and my release notes script needs all the git history
# so I need to add this "fetch-depth: 0", which makes it fetch ALL the git history/commit messages
fetch-depth: 0
- name: Install libcurl
run: sudo apt install libcurl4-openssl-dev
- name: Download nlohmann json.hpp header file
run: wget https://raw.githubusercontent.com/nlohmann/json/develop/single_include/nlohmann/json.hpp
- name: Build the script
run: g++ -o release_notes_generator Main.cpp Config.cpp Utils.cpp Format.cpp -lcurl -I.
# I am doing this extra step to make the workflow work with draft releases
# since a draft release's tag hasn't yet been created in the git history
# I can't use its tag in the release notes script as a reference to the last commit in the release
- name: Get the git reference (commit SHA/branch name) that the new release tag is on
id: get-new-release-git-reference
# I check if the tag exists in the git history, >/dev/null is used to not show the output generated from the command
# if the tag exists then I get the commit SHA it's on, if not, then the release being created is a draft release
# with a new tag, so I get the commit SHA of the location the new tag will be added to, using the GitHub API
run: |
if git rev-parse --quiet --verify "$NEW_RELEASE_TAG" > /dev/null; then
NEW_RELEASE_REFERENCE=$(git rev-parse "$NEW_RELEASE_TAG")
else
NEW_RELEASE_REFERENCE=$(gh release view "$NEW_RELEASE_TAG" --json targetCommitish --jq .targetCommitish)
fi
echo "NEW_RELEASE_REFERENCE=$NEW_RELEASE_REFERENCE" >> "$GITHUB_OUTPUT"
- name: Validate the given previous release reference
run: |
if ! git rev-parse --quiet --verify "$PREVIOUS_RELEASE_REFERENCE" > /dev/null; then
echo "Input error: Given previous reference '$PREVIOUS_RELEASE_REFERENCE' does not exist"
echo "Please make sure that the previous reference you input exists in this repository's git history"
exit 1
fi
# I am using checkout here so that it also works if the new release reference is a commit
# In the second checkout, I checkout back to the original branch that triggered the GitHub workflow
- name: If the new release reference is a branch (e.g. v1.4.x) ensure that I have a local branch tracking the remote branch
env:
NEW_RELEASE_REFERENCE: ${{ steps.get-new-release-git-reference.outputs.NEW_RELEASE_REFERENCE }}
run: |
git checkout "$NEW_RELEASE_REFERENCE" > /dev/null 2>&1
git checkout ${{ github.ref_name }} > /dev/null 2>&1
- name: Run the release notes script with the needed parameters
env:
NEW_RELEASE_REFERENCE: ${{ steps.get-new-release-git-reference.outputs.NEW_RELEASE_REFERENCE }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: ./release_notes_generator "$RELEASE_NOTES_SOURCE" "$PREVIOUS_RELEASE_REFERENCE" "$NEW_RELEASE_REFERENCE" "$GH_TOKEN" "$RELEASE_NOTES_MODE" "$GITHUB_REPOSITORY"
# GitHub's cli tool "gh" automatically uses the GH_TOKEN environment variable
- name: Update the new GitHub release description with the generated markdown release notes
run: gh release edit "$NEW_RELEASE_TAG" --notes-file release_notes.md
- name: Upload to the new GitHub release assets the generated HTML release notes
# If HTML release notes are already added as an asset to the release, then uploading release_notes.html will give an error
# this means that the workflow is used to update release notes for an already existing release
# I check if the upload failed, and if yes, I delete the existing HTML file and upload the newly generated one
# I use "set +e" to disable the GitHub workflow to exit if any command fails, then I reenable it with "set -e"
run: |
set +e
gh release upload "$NEW_RELEASE_TAG" release_notes.html > /dev/null 2>&1
html_upload_status=$?
set -e
if [ $html_upload_status -ne 0 ]; then
gh release delete-asset "$NEW_RELEASE_TAG" release_notes.html
gh release upload "$NEW_RELEASE_TAG" release_notes.html
fi