You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The release automation (auto-tag.yml + publish.yml) has three compounding defects that together mean tagged releases are not being published, and if they ever are, they will publish the wrong (lower) version number. This is distinct from every open issue/PR — those all touch src/ logic; this is purely about the CI/release machinery, which only auto-tag.yml / publish.yml cover and no in-flight work modifies.
Evidence (current state)
$ git ls-remote --tags origin
... refs/tags/v0.0.2 ... refs/tags/v0.0.10 # newest tag = v0.0.10 on HEAD of main
$ node -p "require('./package.json').version"
1.0.1
So the repo simultaneously claims 1.0.1 in package.json (and the README npm-version badge advertises the 1.x line) while the auto-tagger keeps emitting v0.0.x tags. The two never reconcile.
Three concrete defects
1. Automated publishing never fires — GITHUB_TOKEN tag pushes can't trigger publish.yml
.github/workflows/auto-tag.yml creates and pushes the version tag using the default GITHUB_TOKEN:
.github/workflows/publish.yml is meant to fire on that tag:
on:
push:
tags:
- 'v*'
But per GitHub's documented behavior, events triggered by GITHUB_TOKEN (other than workflow_dispatch/repository_dispatch) do not start new workflow runs — this is the recursion guard. So a tag pushed by auto-tag.yml will not trigger publish.yml. Result: tags v0.0.2–v0.0.10 exist, but none of them were auto-published to npm. The only way publish.yml runs today is a manual workflow_dispatch.
Ref: GitHub Actions docs, "Triggering a workflow from a workflow" — "events triggered by the GITHUB_TOKEN … will not create a new workflow run."
2. Version source-of-truth split — package.json 1.0.1 is permanently ignored
auto-tag.yml computes the next version solely from the highest existing git tag, only falling back to package.json when no tags exist:
LATEST=$(git tag -l 'v*' --sort=-version:refname | head -1)# -> v0.0.10if [ -z"$LATEST" ];then
LATEST="v$(node -p "require('./package.json').version")"# only when NO tags existfi
CURRENT="${LATEST#v}"# 0.0.10
IFS='.'read -r MAJOR MINOR PATCH <<<"$CURRENT"
NEW_VERSION="$MAJOR.$MINOR.$((PATCH +1))"# 0.0.11
Because a v0.0.x tag already exists, the manual chore: bump to v1.0.1 (commit 8e4ee6e) is silently ignored and the next tag will be v0.0.11, not something in the 1.x line. The declared package version and the auto-tag stream have permanently diverged.
3. If publish does run, it ships a version below what users already have
publish.yml overwrites the package version from the tag before publishing:
TAG_VERSION="${GITHUB_REF#refs/tags/v}"# 0.0.11
npm version "$TAG_VERSION" --no-git-tag-version # package.json -> 0.0.11
npm publish --provenance --access public
If 1.0.1 is the version currently on npm (as the badge implies), a manual dispatch of publish.yml on v0.0.11 would publish 0.0.11 and move npm's latest dist-tag backward, so npm install @hailbytes/sbom-diff would start resolving to a lower version than 1.0.1. For a security tool that's a real supply-chain footgun, not just cosmetics.
Bonus: publish.yml has no quality gate
publish.yml runs npm run build then npm publish with no typecheck, test, or lint step. The auto-tag.yml test gate doesn't protect the workflow_dispatch publish path, so a manual publish can ship code that doesn't even compile-check or pass tests.
Proposed fixes
These involve a couple of policy decisions, so flagging as an issue rather than a unilateral PR. Recommended direction:
Make package.json the single source of truth for the version. Drop the "derive next version from highest git tag" logic. Either:
tag directly from package.json (v$(node -p "require('./package.json').version")) and let a human own the bump (e.g. via npm version), or
if you want auto-increment, increment from package.json (npm version patch) and commit the bump back, so the file and the tags never diverge.
This immediately resolves the 0.0.x vs 1.0.1 split and prevents the downgrade in defect fix: add engines field, remove placeholder workflow #3.
Fix the publish trigger. Pick one:
(simplest) Move the build+publish steps into the auto-tag.yml job itself, right after the tag is created — no cross-workflow trigger needed.
Push the tag with a PAT / fine-grained token (or a GitHub App token) instead of GITHUB_TOKEN, so the push: tags event actually fires publish.yml.
Have auto-tag.yml explicitly invoke publish via workflow_dispatch / repository_dispatch (those are allowed from GITHUB_TOKEN).
Add a quality gate to publish.yml before npm publish:
- run: npm ci
- run: npm run typecheck
- run: npm test
- run: npm run build
So no path to npm skips type-check + tests.
Reconcile the existing tags once a direction is chosen (e.g. cut a proper v1.0.x/v1.1.0 tag so the tag stream lines up with the published 1.x line, and stop emitting 0.0.x).
Why this is high-leverage
It's the difference between "releases publish correctly" and "releases silently don't publish, or publish a downgrade." For a package whose whole pitch is supply-chain integrity, a release pipeline that ships the wrong version (or nothing) undermines trust in the artifact itself.
It's orthogonal to all open PRs/issues (which touch diff.ts / parser.ts / reporter.ts / cli.ts), so it won't conflict with anything in flight.
The changes are confined to the two workflow files plus a one-time tag cleanup.
Happy to open a focused PR implementing whichever of the option (1)/(2) directions you prefer.
Summary
The release automation (
auto-tag.yml+publish.yml) has three compounding defects that together mean tagged releases are not being published, and if they ever are, they will publish the wrong (lower) version number. This is distinct from every open issue/PR — those all touchsrc/logic; this is purely about the CI/release machinery, which onlyauto-tag.yml/publish.ymlcover and no in-flight work modifies.Evidence (current state)
So the repo simultaneously claims
1.0.1inpackage.json(and the README npm-version badge advertises the1.xline) while the auto-tagger keeps emittingv0.0.xtags. The two never reconcile.Three concrete defects
1. Automated publishing never fires —
GITHUB_TOKENtag pushes can't triggerpublish.yml.github/workflows/auto-tag.ymlcreates and pushes the version tag using the defaultGITHUB_TOKEN:.github/workflows/publish.ymlis meant to fire on that tag:But per GitHub's documented behavior, events triggered by
GITHUB_TOKEN(other thanworkflow_dispatch/repository_dispatch) do not start new workflow runs — this is the recursion guard. So a tag pushed byauto-tag.ymlwill not triggerpublish.yml. Result: tagsv0.0.2–v0.0.10exist, but none of them were auto-published to npm. The only waypublish.ymlruns today is a manualworkflow_dispatch.2. Version source-of-truth split —
package.json1.0.1 is permanently ignoredauto-tag.ymlcomputes the next version solely from the highest existing git tag, only falling back topackage.jsonwhen no tags exist:Because a
v0.0.xtag already exists, the manualchore: bump to v1.0.1(commit8e4ee6e) is silently ignored and the next tag will bev0.0.11, not something in the1.xline. The declared package version and the auto-tag stream have permanently diverged.3. If publish does run, it ships a version below what users already have
publish.ymloverwrites the package version from the tag before publishing:If
1.0.1is the version currently on npm (as the badge implies), a manual dispatch ofpublish.ymlonv0.0.11would publish0.0.11and move npm'slatestdist-tag backward, sonpm install @hailbytes/sbom-diffwould start resolving to a lower version than1.0.1. For a security tool that's a real supply-chain footgun, not just cosmetics.Bonus:
publish.ymlhas no quality gatepublish.ymlrunsnpm run buildthennpm publishwith notypecheck,test, orlintstep. Theauto-tag.ymltest gate doesn't protect theworkflow_dispatchpublish path, so a manual publish can ship code that doesn't even compile-check or pass tests.Proposed fixes
These involve a couple of policy decisions, so flagging as an issue rather than a unilateral PR. Recommended direction:
Make
package.jsonthe single source of truth for the version. Drop the "derive next version from highest git tag" logic. Either:package.json(v$(node -p "require('./package.json').version")) and let a human own the bump (e.g. vianpm version), orpackage.json(npm version patch) and commit the bump back, so the file and the tags never diverge.This immediately resolves the
0.0.xvs1.0.1split and prevents the downgrade in defect fix: add engines field, remove placeholder workflow #3.Fix the publish trigger. Pick one:
auto-tag.ymljob itself, right after the tag is created — no cross-workflow trigger needed.GITHUB_TOKEN, so thepush: tagsevent actually firespublish.yml.auto-tag.ymlexplicitly invoke publish viaworkflow_dispatch/repository_dispatch(those are allowed fromGITHUB_TOKEN).Add a quality gate to
publish.ymlbeforenpm publish:So no path to npm skips type-check + tests.
Reconcile the existing tags once a direction is chosen (e.g. cut a proper
v1.0.x/v1.1.0tag so the tag stream lines up with the published1.xline, and stop emitting0.0.x).Why this is high-leverage
diff.ts/parser.ts/reporter.ts/cli.ts), so it won't conflict with anything in flight.Happy to open a focused PR implementing whichever of the option (1)/(2) directions you prefer.