Automatic versioning for GitHub Actions authors

Published: (February 7, 2026 at 05:34 AM EST)
7 min read
Source: Dev.to

Source: Dev.to

Overview

As a maintainer of three GitHub Actions, I’ve always struggled a bit with versioning. GitHub’s documentation gives guidance, but there’s no easy way to verify that everything is correct. A quick scan of the Marketplace shows I’m not alone—some of GitHub’s own actions have inconsistencies, too.

That’s why I cobbled together v1 of the Actions Semver Checker a couple of years ago. It served me well, but the initial implementation had a few bugs, was hard to maintain, and any change felt risky because I couldn’t easily test whether I’d broken something.

From v1 to v2

I asked Copilot Agent to use the v1 code as a blueprint and refactor it with the following constraints:

ConstraintDescription
Side‑by‑sideKeep the old and new implementations callable together for easy comparison.
Modular validationExtract validation rules into separate scripts for easier maintenance and testing.
Manual remediationProvide manual remediation options wherever possible.
AutofixImplement an autofix that attempts the manual remediation steps automatically.
Unit testsAdd unit tests for everything.
Integration testsAdd integration tests for everything.
Backwards compatibilityPreserve v1 input signatures as much as possible.

I fed Copilot links to the relevant GitHub docs and blogs (CLI release commands, Releases REST API, Tags REST API, GraphQL API, immutable releases, Actions versioning). Claude Opus helped generate a detailed plan, which I tweaked before letting Copilot spend ~45 minutes coding.

The result was a first‑vibe‑coded GitHub Action that mostly did what was needed, surfacing a few gaps in the plan and creating some interesting interweaving between the two implementations.

After building a test suite of 90+ tests, I felt confident tweaking the behavior. Following several back‑and‑forth sessions with Copilot and hands‑on work in VS Code, I’m proud to release v2 of the GitHub Actions Semver Checker.

What the Action Does

The action is intended to be installed inside the repository that hosts a GitHub Action (e.g., actions/checkout or jessehouwing/actions-semver-checker). It analyzes all branches, tags, and releases and validates them against a set of rules.

Core validation rules (v1)

RuleDescription
vX tag/branchA configurable vX tag or branch must point to the latest vX.y.z tag.
vX.Y tag/branchA configurable vX.Y tag or branch must point to the latest vX.Y.z tag.
vx.y.z tagMust exist.
vx.y.z branchMust not exist.

New validation rules (v2)

RuleDescription
Release for every vx.y.z tagThere should be a release for each vx.y.z tag.
Immutable releasesReleases must be immutable.
Latest releaseThe release for the highest vx.y.z should be marked as “latest”.
No releases for vX / vX.YReleases must not exist for the vX and vX.Y tags/branches.
Marketplace publishingThe action must be published to the Marketplace.
action.yml metadataaction.yml must contain the correct metadata elements.
Immutable‑release settingImmutable releases must be turned on.

For almost all of these validations, an autofix option automatically corrects any issues found. If the action cannot fix a problem, it logs manual remediation steps to the workflow’s summary page.

Autofix Capabilities

CapabilityWhat it does
BranchesDelete / update / create branches.
TagsDelete / update / create tags.
ConvertConvert a branch to a tag or a tag to a branch.
ReleasesDelete / update / create / publish releases.
Latest versionAutomatically set the latest version.
Immutable releasesRepublish releases to make them immutable.

Additional Improvements

  • Configurable rule suites – Choose which groups of rules to run.
  • No full checkout needed – The action no longer requires checking out the entire repository.
  • Retry & rate‑limit handling – Built‑in retry logic for API rate limits.
  • PowerShell Gallery module – Available as a module on the PowerShell Gallery.

Breaking change (v1 → v2)

You must now pass the secret ${{ secrets.GITHUB_TOKEN }} to the token: input of the action.

Permission neededReason
contents: writeRequired for some validations (e.g., reading draft releases).
contents: write (autofix)Required for autofix functionality.
Additional permissions (e.g., workflows: write)Some fixes need permissions that cannot be granted to GitHub Actions. Use a GitHub App or a fine‑grained Personal Access Token instead.

Getting Started

  1. Install the action in your action repository with the default settings. It will analyze the repo and report any rule violations.

  2. Adjust settings to match your desired behavior:

InputOptionsDescription
floating-versions-usetags | branchesChoose how to manage vx and vx.y versions.
check-minor-versionnone | warning | errorValidate the existence of vx.y versions.
check-releasesnone | warning | errorValidate the existence of releases for vx.y.z tags.
check-release-immutabilitynone | warning | errorValidate whether releases are immutable.
ignore-preview-releasestrue | falseExclude preview releases when checking floating versions (vx and vx.y).
ignore-versionscomma‑separated listExclude specific versions from validation (e.g., very old versions or ones that were accidentally made immutable).

Example Workflow

name: Check SemVer

on:
  push:
    branches: ['main']
    tags:
      - '*'
  workflow_dispatch:

permissions: {}

jobs:
  check-semver:
    permissions:
      contents: write   # needed for validations & autofix
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
      cancel-in-progress: true
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository (shallow)
        uses: actions/checkout@v4
        with:
          fetch-depth: 1   # no need for full history

      - name: Run SemVer Checker (v2)
        uses: jessehouwing/actions-semver-checker@v2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          floating-versions-use: tags
          check-minor-version: warning
          check-releases: error
          check-release-immutability: warning
          ignore-preview-releases: true
          ignore-versions: |
            0.0.1
            1.0.0-beta

Summary

  • v2 adds many new validation rules and a robust autofix system.
  • The action is fully configurable, doesn’t require a full checkout, and includes retry & rate‑limit handling.
  • It’s available as a PowerShell Gallery module and can run side‑by‑side with v1 for easy comparison.

Feel free to try it out, tweak the inputs to suit your workflow, and let the action keep your GitHub Action releases clean, consistent, and immutable!

GitHub Workflow Example

# Example job fragment
{{ github.workflow }}:
  cancel-in-progress: true

  runs-on: ubuntu-latest

  steps:
    - uses: jessehouwing/actions-semver-checker@v2
      with:
        token: ${{ secrets.GITHUB_TOKEN }}
        check-release-immutability: none

⚠️ Important:
Be extra careful with the check-release-immutability setting prior to turning on autofix. Most automatic fixes can be easily undone using the Git command line, but once a release is made immutable, there is no way back.

1️⃣ Clean up existing tags

Once your existing tags have been cleaned up and you understand the implications, enable release‑immutability checks:

steps:
  - uses: jessehouwing/actions-semver-checker@v2
    with:
      token: ${{ secrets.GITHUB_TOKEN }}
      check-release-immutability: error

2️⃣ Run in read‑only mode

Use the action in read‑only mode for a while, manually performing the suggested remediation steps.

3️⃣ Enable autofix (optional)

When you’re confident the action does what you want, consider turning on autofix:

steps:
  - uses: jessehouwing/actions-semver-checker@v2
    with:
      token: ${{ secrets.GITHUB_TOKEN }}
      autofix: true

How it works with autofix

With autofix turned on, the only thing you need to do to release a new version and update all tags and releases is to push a new tag (e.g., vX.Y.Z). This will trigger the action to:

  1. Create a new release with the correct name.
  2. Update all relevant tags automatically.

That’s it—no further manual steps required!

0 views
Back to Blog

Related posts

Read more »