Statamic + Laravel Consulting

Automatic Releases & Changelogs


For one of my clients, Transform Studios, I built what is essentially a Statamic Starter Kit, but as an addon. This allows us to update sites easily via composer update.

One of our current challenges is that we want to be more transparent with our customer with regards to updates and enhancements; to do that we want a dashboard page that shows the latest changes to their site.

However, creating a changelog manually is error prone and takes a while, so I wanted to automate as much as possible.

My end goal was a changelog that conformed to the Keep a Changelog format, as well as a release with the same information, driven by Github Actions, all from the usual PRs and tags.

For this to happen:

  1. PRs need to be categorized as features or bugs, so they can be separated in the release note
  2. Release note needs to include every PR since the last release
  3. Changelog should mirror the release note

To label the PRs, I found Timon van Spronsen's PR Labeler Action. You can configure it, but used the defaults, and set it to run whenever a PR was opened:

name: PR Labeler
on:
  pull_request:
    types: [opened]
jobs:
  pr-labeler:
    runs-on: ubuntu-latest
    steps:
      - uses: TimonVS/pr-labeler-action@v3
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Next up is creating a draft release, because I wanted to be able to see what the notes looked like before the release was published. For that I found the amazing Release Drafter. This action takes the categorized PRs and creates sections (Changed/Fixed, etc) with the PR titles, author(s) and PR link. This action has many config options, but again, I kept it simple:

name: Release Drafter
on:
  pull_request:
    types: [closed]
permissions:
  contents: read
jobs:
  update-draft-release:
    if: github.event.pull_request.merged == true
    permissions:
      contents: write  # for release-drafter/release-drafter to create a github release
    runs-on: ubuntu-latest
    steps:
      - uses: release-drafter/release-drafter@v5
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Note that there is no merged Github event so you have to run it on closed but check to see if the PR was merged vs closed.

Lastly, when I push a (versioned) tag, like v3.4.5, the release should be published and the changelog updated. This one was the most complicated because it's gotta do a few things:

  1. Get the draft release
  2. Update the release title and attach it to the pushed tag
  3. Update the changelog from the release note
  4. Commit the updated changelog.

I started with Cardinalby's Get Release action, to get the release id. Then I use Github's script action to update the release (I couldn't find an existing action that let me attach the release to a tag).

After that I found a pair of Stefan Zweifel's actions, stefanzweifel/changelog-updater-action and stefanzweifel/git-auto-commit-action that update the changelog based on the release note and commit it:

name: Release
on:
  push:
    tags: ['v*']
jobs:
  update-changelog:
    runs-on: ubuntu-latest
    steps:
      - name: Get Draft Release
        uses: cardinalby/git-get-release-action@v1
        id: latest_draft_release
        env:
          GITHUB_TOKEN: ${{ github.token }}
        with:
          draft: true
          latest: true
      - name: Update Title and Publish Release
        id: publish_release
        uses: actions/github-script@v6
        with:
          script: |
            github.rest.repos.updateRelease({
              draft: false,
              name: '${{ github.ref_name }}',
              owner: context.repo.owner,
              repo: context.repo.repo,
              release_id: ${{ steps.latest_draft_release.outputs.id }},
              tag_name: '${{ github.ref_name }}'
            })
      - name: Checkout code
        uses: actions/checkout@v3
      - name: Update Changelog
        id: update_changelog
        uses: stefanzweifel/changelog-updater-action@v1
        with:
          latest-version: ${{ github.ref_name }}
          release-notes: ${{ steps.latest_draft_release.outputs.body }}
      - name: Commit updated Changelog
        uses: stefanzweifel/git-auto-commit-action@v4
        with:
          branch: main
          commit_message: Update CHANGELOG
          file_pattern: CHANGELOG.md

You can see the release note it produces and the changelog. It was my test repo so yours will look nicer I'm sure.

© 2024 Silent Z Consulting