Skip to content

ci: tag each crates.io release as v<version> (port consensus Create git tag) - #2

Merged
secsovereign merged 2 commits into
mainfrom
ci/tag-releases
Oct 22, 2026
Merged

secsovereign merged 2 commits into
mainfrom
ci/tag-releases

Conversation

@secsovereign

@secsovereign secsovereign commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

The publish job runs cargo publish but has never created a tag; this repo has 0 tags and 0 releases. This PR adds blvm-consensus's Create git tag step to that job.

Change

A new last step in publish, Create git tag. It's the consensus step with the following differences:

  • Gate: it runs only when steps.gate.outputs.do_release == 'true' && steps.publish.outputs.published == 'true', so nothing is tagged after a skipped or failed publish.
  • Tag name and commit: VERSION_TAG="v${{ steps.version.outputs.version }}", because this job has no version_tag output. The tag goes on HEAD, which is the rebased Bump version commit that Commit version bump pushes before publishing, i.e. the exact tree that was published.
  • Error hints: the Workflows-permission hint prints the manual tag command at that HEAD sha, not github.sha. The generic push-failure message prints the same command.

Unchanged from consensus: it skips if the tag already exists on origin, errors if REPO_ACCESS_TOKEN is missing, unsets the extraheader/includeIf credentials, and pushes with x-access-token.

REPO_ACCESS_TOKEN is available to this repo as an org secret. With that token, node's Release pushed v0.1.73 at 8f4aba5, a commit that itself changed ci.yml, so a workflow-touching range wasn't rejected there.

No GitHub Release step. Consensus builds one from a release-notes generator plus attestation steps in the same job (~250 lines); that isn't cheap enough for this PR.

What changes once tags exist

All of this was run in a scratch clone against live crates.io data, using the job's own Determine version and breaking-change scripts pulled from this YAML.

  • Next version: USED_VERSIONS = tags ∪ crates.io. Tags are only created after a successful publish, so tags ⊆ crates.io and the next version doesn't change. It computed 0.1.44 with no tags, with only the backfilled v0.1.43, and with every historical version tagged.
  • No refuse or skip on the first run: the first post-merge run publishes 0.1.44 and tags v0.1.44. Nothing skips because of a tag: the version loop only steps past versions that already exist, and the new tag step only skips when that exact tag is already on origin.
  • crates.io API down: today, with no tags and the API unreachable, USED_VERSIONS=$(… | grep -v '^$') has no matches, so grep exits 1 and the default bash -e fails Determine version. This is an existing failure mode, and it fails safe. Once tags exist, the step instead picks max(tag)+1, which was 0.1.44 in the simulation. The one risk: if a publish succeeded but its tag push failed, an API outage could make it pick an already-published number. Publish would then hit "already exists", which this job treats as published=false / exit 0, and the bump commit would already be on main. This is unlikely, and it isn't worse than the current API-down behaviour; I left that logic alone.
  • Breaking-change scan (advisory only): git describe --tags --abbrev=0 now returns the last tag, so the range becomes <last tag>..HEAD instead of the HEAD~20..HEAD fallback. That's just the commits since the last release.
  • actions/checkout with fetch-depth: 0 fetches tags, so both lookups see them.

Post-merge: backfill (not pushed by this PR)

Evidence: run 39172698415 (job 117809350791), 2026-10-18 6:35 PM ET (22:35Z).

  • Log line 627: 8005213..902444b HEAD -> main (the bump commit pushed).
  • Log line 974: Published blvm-spec-lock v0.1.43.
  • Cargo.toml at 902444b has version = "0.1.43", and crates.io's max_version is 0.1.43.

Run as a human, ideally before the first post-merge release:

git fetch origin
git tag -a v0.1.43 902444bd061df74c601654d749c63d0dfad6a6f2 -m 'Release v0.1.43'
git push origin v0.1.43
Optional: full history. Each crates.io version mapped to its "Bump version to X" commit on main (subject plus Cargo.toml at that commit; only v0.1.43 is also confirmed by a run log)
# skip v0.1.1 (38c4cfa25659c347c1c904d7a90e4656098a634e): bump commit exists but 0.1.1 is not on crates.io
git tag -a v0.1.2 046d46381f783074ef2e05046bafd44405bbb679 -m 'Release v0.1.2'
git tag -a v0.1.3 d8a38e1fadfae81cbecf51a2dc50951268b4c192 -m 'Release v0.1.3'
git tag -a v0.1.4 7650d0ace339a7b2d71215abdaf4fc4bf153d15b -m 'Release v0.1.4'
git tag -a v0.1.5 5d8ffc2adbba35f05815719972a0f0f0a0399082 -m 'Release v0.1.5'
git tag -a v0.1.6 9c5f83fd418cc0faa88b83e982d34e2cd813fc2c -m 'Release v0.1.6'
git tag -a v0.1.7 f10d9653d8b5c829038a6a02344d5e4f6a076333 -m 'Release v0.1.7'
git tag -a v0.1.8 47ff5981ad7019958192a2cea51d789f16a01d95 -m 'Release v0.1.8'
git tag -a v0.1.10 d28be2a8aff8c525aad56d241d1f8e057ac437ba -m 'Release v0.1.10'
git tag -a v0.1.11 c24555a1123696584679a8b009fd3bf6436fc666 -m 'Release v0.1.11'
# skip v0.1.13 (ef9ab69f07e6f444ded6466d480049674e439127): bump commit exists but 0.1.13 is not on crates.io
git tag -a v0.1.14 102908d8e53fef1ca1afdb2bbdf5de5df0d1d016 -m 'Release v0.1.14'
git tag -a v0.1.15 9bd23936d4d6860df4f6b2232d6ac80d4e7190dd -m 'Release v0.1.15'
git tag -a v0.1.17 95a694b03d7d8bc80eafe9d7bce4a95b3518569e -m 'Release v0.1.17'
git tag -a v0.1.18 3ab89ba3fc2fc64299f6b2d7d309da8957a7ded9 -m 'Release v0.1.18'
git tag -a v0.1.19 c7ab07bf3c4547d0c936b734a6dc5dfc43c7fa40 -m 'Release v0.1.19'
git tag -a v0.1.20 7c43defcb11f3497a0f351c86ae607902710e7ce -m 'Release v0.1.20'
git tag -a v0.1.21 b55dd9e9a371556a0a4229e3bd17eab5b0fadda1 -m 'Release v0.1.21'
git tag -a v0.1.22 44122cc64e44a2247567e025b3b6b4a82776c417 -m 'Release v0.1.22'
git tag -a v0.1.23 7148dd0c59f625a518f9e81349d38e9bdce1607f -m 'Release v0.1.23'
git tag -a v0.1.24 e7146980a5cdbac3d9c80b1a676d0063f75c396a -m 'Release v0.1.24'
git tag -a v0.1.25 595833af6a0949e2a4980c0a9f70aca21a489bfd -m 'Release v0.1.25'
git tag -a v0.1.27 85fdcbe33878e0e48d11bc0ab57bc4c016fe8089 -m 'Release v0.1.27'
git tag -a v0.1.28 a37980a40b3696a1c5b884a3da2d7f1f0f7ff82c -m 'Release v0.1.28'
git tag -a v0.1.29 9c23542b72da674d1f22bc20a2b725edaf2bc898 -m 'Release v0.1.29'
git tag -a v0.1.30 232bf5cf0cc86b38c299ff336787fef7adfc706d -m 'Release v0.1.30'
git tag -a v0.1.31 d68ac873192d408a46c00fd5df8d2bbfbe0ae3f2 -m 'Release v0.1.31'
git tag -a v0.1.32 e2f0290eeae53171804088f1c2f60576418bd0e6 -m 'Release v0.1.32'
git tag -a v0.1.33 a37e36c1201d70335d455719fec4db235aec75cc -m 'Release v0.1.33'
git tag -a v0.1.34 4d8657d1c40404be283eb32a25c2d8b336f9f5a4 -m 'Release v0.1.34'
git tag -a v0.1.35 91f17f9f9663a73505d9065d2e45f77054a0de7a -m 'Release v0.1.35'
git tag -a v0.1.36 71661d951b2785e09f94217183aa0e6b30037278 -m 'Release v0.1.36'
git tag -a v0.1.37 affbe226d0fed505cc90790aa5402ccc749d3854 -m 'Release v0.1.37'
git tag -a v0.1.38 37d0412002439f8dafe688c250263799ca435543 -m 'Release v0.1.38'
git tag -a v0.1.39 426d66ef60db5b4a35336f27a2287061102202e6 -m 'Release v0.1.39'
git tag -a v0.1.40 8fd77ab64cd486da59214146515d98c835fa1225 -m 'Release v0.1.40'
git tag -a v0.1.41 340b63b0abacea519e1948e273af26c027941c96 -m 'Release v0.1.41'
git tag -a v0.1.42 aacb0eecdf176fd23279e2cca0097b7331c46abd -m 'Release v0.1.42'
git tag -a v0.1.43 902444bd061df74c601654d749c63d0dfad6a6f2 -m 'Release v0.1.43'

Push with git push origin --tags, after checking that no stray local tags exist.

The list above skips 0.1.1 and 0.1.13. Those bump commits exist, but neither version is on crates.io.

Does pushing a tag trigger anything? No. ci.yml runs on push: branches: [ main, develop ] with no tags: filter, and a branch-only filter doesn't match tag pushes.

fuzz-build-weekly.yml is workflow_dispatch only.

Checks run

  • actionlint: no new findings compared with main (shellcheck isn't installed on the box).
  • The YAML parses, and the step is last in publish.
  • The step's script was run against a local bare remote, with set-url stubbed out:
    • it creates an annotated tag at HEAD;
    • a rerun skips because the tag already exists;
    • a push failure exits 1 and prints the manual command with the HEAD sha;
    • a missing token exits 1.
  • Merging this PR starts a release: merging is a normal push to main, so it publishes 0.1.44 and creates the first automatic tag.

Docs commit d62adb1 (wording only, no code change): src/translator/z3_verifier.rs:15 said a Z3 pass means "the implementation is mathematically locked to the spec". It now says the function is annotated and Z3-checked against its contracts, which is not formal verification. README.md:14 changed from "provides formal verification for Bitcoin consensus code" to "annotates ... and Z3-checks their contracts". Both now link blvm-consensus docs/VERIFICATION.md, where 3 of 182 anchors are mutation-validated (ed2fac0).

Port the blvm-consensus 'Create git tag' step to the publish job: after a
successful publish, create an annotated v<version> tag at HEAD (the pushed
'Bump version' commit, i.e. the published tree) and push it with
REPO_ACCESS_TOKEN. Skips if the tag already exists on origin. The
Workflows-permission hint and the generic failure message print the manual
tag command at that commit.

Until now this repo published without tagging, so the describe-based
breaking-change scan always fell back to HEAD~20 and the version step
relied on crates.io alone. No GitHub Release step (consensus builds notes
and attestations for that; out of scope here).
Match blvm-consensus docs/VERIFICATION.md (ed2fac0): 3 of 182 anchors are mutation-validated. A Z3 pass means annotated and Z3-checked against the translated contracts. Comment and README only.
@secsovereign
secsovereign merged commit 6f2794c into main Oct 22, 2026
2 checks passed
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.

1 participant