Skip to content

feat(ci): scope release version bumps to the deployable payload - #132

Merged
GingerGraham merged 2 commits into
mainfrom
feat/scope-release-analysis-to-payload
Sep 22, 2026
Merged

GingerGraham merged 2 commits into
mainfrom
feat/scope-release-analysis-to-payload

Conversation

@GingerGraham

Copy link
Copy Markdown
Owner

Summary

Follow-up to #130/#131. v2.6.0 was cut as a minor release when #130 merged, even though
that PR only touched .github/workflows/release.yml, docs/releases.md, CONTRIBUTING.md, and
a skill file — nothing in the deployable payload. This happens because semantic-release's
default commit analysis considers the type of every commit since the last tag regardless of what
it touched, and #130's path filter only gated whether to run semantic-release at all
(workbench.yml had sat unreleased as a chore: commit since 2.5.6, which was enough to satisfy
that gate) — not which commits' types count toward the version.

Per the maintainer's decision, v2.6.0 itself is left as-is (immutable releases are enabled).
This PR only changes behaviour going forward: a commit's type now only counts toward the version
if that same commit's own diff touches logging.sh or workbench.yml.

Change

  • Adds scripts/analyze-release-commits.sh: given a last-release tag, filters git log by
    pathspec (logging.sh, workbench.yml) and reports the highest bump type
    (major/minor/patch) among only the commits that touched one of those paths.
  • .releaserc.json: replaces @semantic-release/commit-analyzer with
    analyzeCommitsCmd on the existing @semantic-release/exec plugin, pointing at the new
    script — this is the officially supported way to fully customize semantic-release's version
    decision (analyzeCommitsCmd docs: stdout is the release type only, or nothing for no release).
  • .github/workflows/release.yml: both the auto-push "should we even run semantic-release" gate
    and the manual workflow_dispatch pending-bump safety check now call the same script, instead
    of each having their own (previously slightly different, now identical) inline regex logic.
  • docs/releases.md: documents the new analyzeCommitsCmd wiring and the payload-scoping
    rationale.

The workflow_dispatch exception

Manual dispatch creates a synthetic --allow-empty commit specifically to force a chosen bump
level regardless of what changed — that's the entire point of #130's bump input. Path-filtering
that commit would make it invisible to the analyzer (an empty commit touches no files), silently
breaking manual releases entirely. The script detects this via GITHUB_EVENT_NAME (set
automatically by GitHub Actions) and skips path-filtering only for workflow_dispatch — it falls
back to the previous unfiltered behaviour there, preserving #130's "Day-1 workbench.yml release"
scenario.

Testing

Verified against real repository history using git worktree (this sandbox has no PAT_TOKEN,
so a true end-to-end semantic-release dry run against GitHub wasn't possible — the script and
the workflow's bash wiring were tested directly instead):

  • Push event, range = last tag → feat(ci): add manual bump control and workbench.yml release detection #130's actual merge commit (975307e, feat(ci):, touches no
    payload file): now correctly produces no release (was: minor → v2.6.0)
  • Push event, range = last tag → a real historical logging.sh fix (19ba794,
    fix(#120): ...): correctly produces patch
  • workflow_dispatch event, same feat(ci): add manual bump control and workbench.yml release detection #130 range: correctly still produces minor (unfiltered, so
    the pending-bump warning still fires exactly as before)
  • workflow_dispatch event with a synthetic empty fix: ... commit appended: correctly still
    produces patch — manual dispatch is unaffected
  • .releaserc.json and release.yml both parse (json.load/yaml.safe_load)
  • pre-commit run shellcheck on the new script and the workflow file — passed
  • pre-commit run markdownlint on docs/releases.md — passed

Related issues

Follow-up to #130 (build spec) and #131 (bug fix) — addresses the maintainer's follow-up request
after observing the unwanted v2.6.0 minor bump.


🤖 Generated with Claude Code

https://claude.ai/code/session_017KFf4oXoAAheW8AdAQ2q7G


Generated by Claude Code

The automatic push-triggered release path only gated whether to run
semantic-release at all on logging.sh/workbench.yml having changed since
the last tag; the actual version bump was still decided by scanning every
commit since that tag regardless of what it touched. Merging PR #130 (a
feat(ci): commit that changed only .github/workflows/release.yml, docs,
and a skill file) demonstrated the problem directly: it cut v2.6.0 as a
minor release even though nothing in the deployable payload changed,
because workbench.yml had separately sat unreleased since 2.5.6.

Add scripts/analyze-release-commits.sh and wire it in as
.releaserc.json's analyzeCommitsCmd (replacing @semantic-release/commit-
analyzer), so a commit's type only counts toward the release if that same
commit's own diff touches logging.sh or workbench.yml. The manual
workflow_dispatch pending-bump check in release.yml now calls the same
script, so what it warns about always matches what the real release run
will decide.

workflow_dispatch's own synthetic --allow-empty commit is deliberately
exempt from this path restriction (detected via GITHUB_EVENT_NAME) since
its whole purpose is to force a chosen bump level regardless of what
changed — path-filtering it would make manual dispatch unable to ever
trigger a release.

v2.6.0 itself is not reverted (immutable releases; the maintainer decided
to leave it as-is) — this only changes behaviour going forward.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017KFf4oXoAAheW8AdAQ2q7G
Copilot AI balanced review requested due to automatic review settings September 22, 2026 15:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It rewires the release/versioning mechanism (removing commit-analyzer for a custom analyzeCommitsCmd) that could not be end-to-end verified in this environment, so it warrants human sign-off.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
What changed in this PR

This PR refines the release automation so that a version bump only happens when a commit's own diff touches the deployable payload (logging.sh or workbench.yml). It fixes the root cause behind the unwanted v2.6.0 minor bump (a feat(ci): commit that touched no payload file), replacing @semantic-release/commit-analyzer's releaseRules with a custom analyzeCommitsCmd script that both the workflow gate and semantic-release itself now share, keeping the auto-push and manual paths consistent. workflow_dispatch is intentionally exempted (via GITHUB_EVENT_NAME) so synthetic empty commits still force a bump.

Changes:

  • Adds scripts/analyze-release-commits.sh that path-filters git log (except for workflow_dispatch) and prints the highest release type among in-scope commits.
  • Wires the script into .releaserc.json (analyzeCommitsCmd) and both release.yml decision points, removing the duplicated inline regex logic.
  • Documents the new payload-scoping behavior and the manual-dispatch exception in docs/releases.md.
File Description
scripts/​analyze-release-commits.sh New shared analyzer: filters commits by payload path and reports major/minor/patch (or nothing); exempts workflow_dispatch.
.releaserc.json Removes commit-analyzer/releaseRules; adds analyzeCommitsCmd pointing at the new script on the existing @semantic-release/exec plugin.
.github/​workflows/​release.yml Auto-push gate and manual pending-bump check now both call the shared script instead of inline regex.
docs/​releases.md Documents the analyzeCommitsCmd wiring and payload-scoping rationale, including the workflow_dispatch exception.

The logic is coherent: the grep-based bump mapping matches the removed releaseRules (including #131's anchored BREAKING CHANGE fix), the script is executable (mode 100755), always exits 0 (the terminating if/elif/fi with no match yields status 0, so it won't spuriously fail set -e), and the workflow_dispatch exemption correctly preserves manual empty-commit releases. The only in-diff finding is a minor Bash-convention nit ([ ] vs [[ ]]).


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/analyze-release-commits.sh Outdated
This script is Bash-targeted (it uses a Bash array), so per CLAUDE.md's
shell compatibility guidelines it should use [[ ]] rather than the
POSIX-portable [ ], matching the convention already used elsewhere in
scripts/ (e.g. validate-commit-msg.sh, package-release.sh).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017KFf4oXoAAheW8AdAQ2q7G
@GingerGraham
GingerGraham requested a balanced review from Copilot September 22, 2026 15:16
@GingerGraham
GingerGraham merged commit ce43f06 into main Sep 22, 2026
6 checks passed
@GingerGraham
GingerGraham deleted the feat/scope-release-analysis-to-payload branch September 22, 2026 15:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It alters the release-versioning pipeline, whose end-to-end behavior (semantic-release + analyzeCommitsCmd integration) cannot be verified in this sandbox and carries operational risk if wrong.

Review effort: Balanced
Findings: None

Resolved since last review (1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants