Skip to content

ci(release): refuse a non-empty milestone and close it after the release (#124) - #125

Merged
rubentalstra merged 2 commits into
mainfrom
ci/release-closes-milestone
Oct 19, 2026
Merged

rubentalstra merged 2 commits into
mainfrom
ci/release-closes-milestone

Conversation

@rubentalstra

Copy link
Copy Markdown
Contributor

What changed and why

FerroSMART v0.1.0 was tagged and published on 2026-10-19 while its milestone stayed open. The release workflow now holds both ends of the "Milestones = releases" rule itself:

  • plan runs scripts/release/milestone.sh check <tag> before anything is created. It fails when no milestone is titled exactly as the tag, or when that milestone still holds an open issue or pull request, and the log names each one.
  • A final milestone job runs close <tag> after every leg, the approval-gated crates.io leg included. It runs under always() so a failed or refused leg is named in its log and the milestone stays open; re-running the failed jobs closes it. An already-closed milestone counts as done. The job holds contents: read (to check out the script) and issues: write; the workflow-level permissions: {} is unchanged.
  • A pre-release tag (-rc.N) finishes no milestone, so both steps accept it and change nothing.
  • milestone.sh --self-test drives both modes against a stub gh and runs in the CI shellcheck job.
  • The release.yml bullet of .claude/rules/ci-cd.md, the release-tag memory, the release section of .claude/rules/issue-workflow.md and a new memory file record the rule.

No specification governs this: our own design. actionlint, zizmor and shellcheck are clean. The same change lands in every FerroHEALTH product repository.

Closes #124

Licensing of contributions

  • I accept the terms in CONTRIBUTING.md § Licensing of contributions: I have the right to submit this work, I license it under the project licence of the version it lands in, and I grant the Licensor the relicensing right stated there.

Checklist

  • Shell and workflow files are clean: shellcheck --severity=style, actionlint, zizmor --min-severity=low .github/.
  • The committed guards pass, and the --self-test of the new script.
  • CI only: the no-changelog label.
  • Docs are updated.
  • Every commit is signed.
  • No AI or assistant attribution anywhere in the commits or this PR.

…ase (#124)

FerroSMART v0.1.0 was published while its milestone stayed open. The plan
job now refuses a tag whose milestone, titled exactly as the tag, is missing
or still holds an open item, and a final job closes that milestone once
every leg, crates.io included, has succeeded. Both call
scripts/release/milestone.sh, whose self-test runs in CI.
@rubentalstra rubentalstra added the no-changelog PR escape hatch: the change has no effect a console sees. label Oct 19, 2026
@sonarqubecloud

Copy link
Copy Markdown

@rubentalstra
rubentalstra added this pull request to the merge queue Oct 19, 2026
Merged via the queue into main with commit dfbf84a Oct 19, 2026
26 checks passed
@rubentalstra
rubentalstra deleted the ci/release-closes-milestone branch October 19, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-changelog PR escape hatch: the change has no effect a console sees.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The release workflow refuses a non-empty milestone and closes it after the release

1 participant