Repository navigation
epic-129 S1: release path to ADR-9 (--ci, --preview, release on merge, tests gate the publish, ARM CI) - #3
Conversation
- release.sh: --ci (no prompts, refuses a dirty tree), --preview
({next}-preview.{N}, any branch), --dry-run; current version ignores
-preview tags; --major keeps build+1 (1.13.0.71 -> 2.0.0.72); a release
runs on master only; writes version/tag/previous to $GITHUB_OUTPUT;
parameterised by PACKAGE and INITIAL_VERSION so matrix copies it unchanged.
- release.test.sh: plain-bash tests in a throw-away repo.
- release.yml: on push master, bump from the merged PR's release:* label
(default minor, release:none skips), runs release.sh --<bump> --ci, then
calls publish-nuget.yml in the same run.
- publish-nuget.yml: workflow_call trigger with a version input; tests gate
the push (no more || true); preview suffix stripped for Assembly/FileVersion.
- ci.yml: ubuntu-24.04-arm job, release-script job, paths cover the release
files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rafalmaciag
left a comment
There was a problem hiding this comment.
Review of aff4e77 (concrete defects only; release.test.sh passes locally 22/22, CI green on x64 + arm64).
1. release.yml:67-83: when the PR lookup finds nothing, the job publishes a minor.
If repos/$REPO/commits/$SHA/pulls returns [] (the endpoint can lag right after a merge, or the push to master was a local git merge and push with no PR), LABELS is empty, COUNT=0, and BUMP=minor. A merge labelled release:none, this PR included, then tags and pushes 1.14.0.72 to nuget.org. That cannot be undone (nuget.org can only unlist). The fallback should apply only when a PR was found and has no label. "No PR found" should retry, then fail or skip.
2. release.yml:30-32: the concurrency group can cancel a merge's release without anyone noticing.
With cancel-in-progress: false, GitHub still keeps only one pending run per group. A third run queued while one is running cancels the pending one. Example: merge A is publishing, merge B (release:major, the ADR-11 merge) is pending, merge C (no label) arrives. B is cancelled, and C releases --minor as 1.14.0.72, so the breaking change ships under 1.x.
3. release.yml:94-126: the tag and the GitHub Release are created before any test runs.
release.sh pushes the tag and ncipollo/release-action publishes the GitHub Release in the tag job. Tests run later, in publish. With a red suite, NuGet gets nothing (correct), but the public GitHub Release "v1.14.0.72" and its tag exist. The next merge then bumps past it, so a released version has no package. The GitHub Release should be created after publish succeeds. release.yml also does not wait for ci.yml, so a failure only on arm64 or 9.0.x does not stop the publish.
4. release.yml:101-102 + release.sh:110-112,155: custom with an empty custom_version makes a silent patch release.
./release.sh --version "" --ci sets custom_version="". The -n check skips it, so the default patch bump runs. Verified: --version '' produces …/1.0.1.1 with exit 0.
5. release.ps1 (unchanged, still in the tree) is a second release path that skips fixes 3 and master-only.
It takes the highest tag including -preview tags, so the first preview breaks its arithmetic. It has no branch check, edits the csproj, and runs git push origin HEAD followed by the tag push, which triggers publish-nuget.yml. It should be deleted, so that release.sh is the only implementation.
6. release.sh:42-81: tags are never fetched before the version is computed.
On a laptop with stale local tags, --preview computes {next} from an old release. Example: local tags stop at 1.12.0.70 while origin has 1.13.0.71, so the preview is 1.13.0.71-preview.1, a preview of an already-released version. Two leads can also both compute -preview.N: the second push is rejected and leaves a local tag behind, so every retry fails with "Tag already exists". A git fetch --tags --force origin before get_current_version fixes this. CI is unaffected (fetch-depth: 0).
7. publish-nuget.yml:14-19: workflow_dispatch publishes any version from any branch to nuget.org.
This path existed before, but the PR keeps it beside the new workflow_call. Feature-branch code can ship as a release version, for example 1.14.0.72 with no tag, which is what ADR-9's "master pins releases only" forbids. Restrict it to master or remove it.
Minor:
release.sh:138-139:git diff-indexignores untracked files, so--ciaccepts a tree with untracked files.release.sh:181-191: an interactive (non---ci, non-preview) release from a laptop on master is still allowed. Its tag push triggers publish-nuget.yml on the tag, which bypasses the label flow and races release.yml for the same version number.
- release.yml: no merged PR for the pushed commit -> retry 3 times (10 s), then fail; minor is the default only for a found PR without a label. - release.yml: concurrency group removed (it can cancel a pending release); the reasoning is in the header comment. - release.yml: the suite (restore, build, test Release) runs before release.sh, in a separate worktree because the tests rewrite tracked SVG galleries; the GitHub Release moves to a github-release job after publish. - release.yml: custom bump with an empty custom_version fails. - publish-nuget.yml: workflow_dispatch only re-publishes an existing release tag and builds that tag's commit. - release.sh: empty or malformed --version exits 1; tags are fetched from origin first (a failed fetch is a warning under --dry-run alone, exit 1 otherwise); untracked files make the tree dirty; a failed tag push removes the local tag. - release.test.sh: cases for the above; every invocation reads /dev/null. - release.ps1 deleted: a second release path with the old defects. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BezierFitTests, CorrectionTests and DensifyTests wrote their galleries into the tracked bezier-fit-svg/, correction-svg/ and densify-svg/ folders, so a test run left a dirty tree (CRLF -> LF on Linux, and platform-dependent numbers). They now write to <temp>/ModelingEvolution.Drawing.Tests/<gallery>; the committed galleries stay as a one-time snapshot. release.yml: the tag job runs the suite in its own checkout again (the worktree workaround is removed); release.sh --ci finds a clean tree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Re-check of 33f9756 + 2283cf7.
New: without serialisation, an older commit can be released after a newer one.
A fix that covers both 2 and this:
Minor: the SVG fix moved three galleries to the temp folder. The other writers are fine: |
…mmit - release.yml: concurrency group release-master restored. The bump is the highest release:* label (major > minor > patch > none) over every PR merged in first-parent lastReleaseTag..HEAD, so a cancelled pending run loses nothing. An unlabelled PR counts as minor, all release:none skips, no PR for any commit fails. HEAD's lookup is retried (API lag after a merge). Recovery text: re-run only while the commit is master's tip. - release.sh: refuses to tag (previews included) when the newest release tag is not an ancestor of HEAD; skipped when there is no release tag yet. Fetch-failure message names both causes. - release.test.sh: ancestor cases (refused off-history, accepted after merge). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both build-and-test jobs (x64 matrix and arm64) check git status --porcelain after the Test step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Final pass on 3ea6523 + e7a3d40.
New, should-fix: when HEAD's PR is not found, its label is ignored. |
…he range never decides HEAD's bump Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Brings Drawing's release path to ADR-9. Spec:
docs/epics/epic-129-matrix/alignment-review.md §3(the eight-row table).Nothing is published by this PR. It carries the label
release:none, so the newrelease.ymlskips on merge: no tag, no package.release.sh --ci: no prompts; refuses a dirty tree (exit 1)release.sh --preview: tagsModelingEvolution.Drawing/{next}-preview.{N}, from any branch; the existing tag trigger ofpublish-nuget.ymlpublishes itget_current_versionexcludes-previewtagsrelease.ymlruns onpush: master(keepsworkflow_dispatch, with its explicit bump). The bump is the highestrelease:major|minor|patch|nonelabel over every PR merged in first-parentlastReleaseTag..HEAD(an unlabelled PR counts asminor; allnone= skip; no merged PR for any of those commits = the job fails). It runs the suite, then./release.sh --<bump> --cipublish-nuget.ymlgetson: workflow_call(inputversion);release.ymlcalls it in the same run withsecrets: inherit. Version order: call input → dispatch input → tag. Tag trigger kept. A manual dispatch only re-publishes an existing release tag and builds that tag's commit. The GitHub Release is created after the publishpublish-nuget.yml: `--majorkeepsbuild+1: from 1.13.0.71,--majorgives 2.0.0.72ci.yml:ubuntu-24.04-armjob (10.0.x);pathsincluderelease.sh,release.test.shand all three workflow filesAlso:
release.shis parameterised (PACKAGE,INITIAL_VERSIONat the top) so the matrix repo copies it unchanged. Flags:--patch(default) |--minor|--major|--version X.Y.Z.B, plus--preview,--ci,--dry-run. A non-preview release runs on master only. Inside Actions it writesversion,tag,previousto$GITHUB_OUTPUT.release.test.sh(plain bash) runs as therelease-scriptjob inci.yml: 32 assertions, including a real tag+push into a throw-away bare origin.AssemblyVersion/FileVersionget the numeric part (2.0.0.72),Version/PackageVersionthe full2.0.0.72-preview.1.workflow_dispatchpath ofrelease.ymlkeeps its bump choice (patch/minor/major/custom) and goes throughrelease.shas well; the duplicate version arithmetic in the workflow is gone.release.ps1is deleted: it was a second release path with the old defects (it counted-previewtags, had no branch check, and pushed HEAD).release.shfetches tags from origin before computing the version, counts untracked files as dirty, rejects an empty--version, refuses to tag (previews included) when the newest release tag is not an ancestor of HEAD, and removes the local tag when its push fails.release.ymlruns one at a time (concurrency: release-master, no cancel-in-progress). GitHub may replace a pending run with a newer one, but the newer run's bump covers the whole range since the last release, so nothing is lost.release.shrefuses to tag a commit whose history lacks the newest release, so an older merge can never get a higher version. Recovery: re-run a failed run only while its commit is still master's tip; otherwise the next merge carries the bump.BezierFitTests,CorrectionTestsandDensifyTestsnow write their SVG galleries to<temp>/ModelingEvolution.Drawing.Tests/<gallery>instead of the trackedbezier-fit-svg/,correction-svg/anddensify-svg/folders (the committed galleries stay as a one-time snapshot). A test run used to rewrite 35 tracked files, sorelease.yml's tag job, which runs the suite beforerelease.sh --ci, would have found a dirty tree on every release.Verification (local,
mcr.microsoft.com/dotnet/sdk:10.0):Sourcestest suite, master before this change: 1633 passed, 0 failed, 0 skipped.Sourcestest suite, this branch, with the publish workflow's version injection for2.0.0.72-preview.1: 1633 passed, and again in a fresh clone as release.yml's tag job runs it: 1633 passed, 0 failed, 0 skipped;dotnet packproducedModelingEvolution.Drawing.2.0.0.72-preview.1.nupkg.git status --porcelainprinted nothing (0 lines)../release.test.sh: 32 passed, 0 failed.bash -nand shellcheck clean; actionlint clean onrelease.yml.🤖 Generated with Claude Code