Skip to content

Version each publish leg against its own branch; validate at entry - #215

Merged
ptr727 merged 1 commit into
developfrom
feature/version-leg-prerelease-213
Jun 26, 2026
Merged

Version each publish leg against its own branch; validate at entry#215
ptr727 merged 1 commit into
developfrom
feature/version-leg-prerelease-213

Conversation

@ptr727

@ptr727 ptr727 commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Problem

Closes #213. publish-release.yml dispatched from main builds a matrix of both main and develop. NBGV derives PublicRelease from the runner's GITHUB_REF, which is refs/heads/main for every leg regardless of the ref each leg checks out. So the develop leg is classified public, NBGV strips its -g<sha> prerelease suffix, and the develop NuGet package is published as a stable version (isPrerelease=false) — consumers can resolve a develop build as if stable. The GitHub release object stays prerelease:true, masking the bug.

Fix

  • get-version-task.yml: optional branch input pins the GITHUB_REF/GITHUB_REF_NAME NBGV reads to the leg being versioned (fallback to github.ref when empty). The mislabel originates in build-nugetlibrary-task's own get-version call, so branch is threaded from all five callers (build-release-task + the four build-*-task files).
  • Validate at entry: the late, one-directional "Verify public release version" step (main-only, mid-flow in github-release) is replaced by a single validate-release job that the build jobs needs:. It checks branch↔version consistency both directions — main must carry no prerelease -; every other branch must carry one (the Publish matrix mislabels the develop leg as a public release: NBGV drops the prerelease tag, NuGet package published as stable #213 regression guard) — and fails fast before the expensive builds.
  • Pattern: codified "validate input/state consistency at entry, fail fast" in AGENTS.md "Workflow YAML Conventions", generalizing the existing publish-docker-readme-task.yml "Validate inputs step".

Verification

  • actionlint (Docker) clean on all six changed workflows; markdownlint clean on AGENTS.md; CRLF preserved.
  • Live proof (post-merge): dispatch publish-release from main, confirm the develop leg's SemVer2 regains -g<sha> and the NuGet package is isPrerelease=true; validate-release fails a clean-X.Y.Z develop version.

🤖 Generated with Claude Code

Fixes #213. On a publish dispatched from the default branch, NBGV derives
PublicRelease from the runner's GITHUB_REF (= refs/heads/main for every matrix
leg), so the develop leg loses its -g<sha> prerelease suffix and its NuGet
package is published as a stable version (isPrerelease=false).

- get-version-task.yml gains an optional `branch` input that pins the
  GITHUB_REF/GITHUB_REF_NAME NBGV reads to the leg being versioned, with a
  github.ref fallback when empty. Threaded from all five callers
  (build-release-task + the four build-*-task files).
- Replace the late, main-only "Verify public release version" step with a
  single `validate-release` entry job that the build jobs needs:, checking
  branch<->version consistency both directions (main must have no prerelease
  suffix; every other branch must have one) and failing fast before builds.
- Codify the validate-input/state-consistency-at-entry pattern in AGENTS.md
  "Workflow YAML Conventions".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 26, 2026 17:46

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.

Pull request overview

Fixes a release-pipeline versioning bug where publish-release.yml runs from main but builds a main+develop matrix, causing NBGV to classify the develop leg as a public release and publish stable NuGet versions.

Changes:

  • Add an optional branch input to get-version-task.yml and pin GITHUB_REF/GITHUB_REF_NAME for the NBGV step to the leg being versioned.
  • Thread branch through all reusable-workflow callers of get-version-task.yml so every target versions against its intended branch.
  • Replace the late, one-directional main-only version check with an early validate-release job that enforces branch<->prerelease consistency for both main and non-main legs.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
AGENTS.md Documents the “validate invariants at entry, fail fast” workflow convention with concrete examples.
.github/workflows/get-version-task.yml Adds branch input and pins env so NBGV classifies the correct leg branch during matrix publishes.
.github/workflows/build-release-task.yml Threads branch into versioning and adds an entry validate-release job gating downstream build/release jobs.
.github/workflows/build-pypilibrary-task.yml Passes inputs.branch to the shared get-version workflow.
.github/workflows/build-nugetlibrary-task.yml Passes inputs.branch to the shared get-version workflow (fixing the mislabel root cause for NuGet).
.github/workflows/build-executable-task.yml Passes inputs.branch to the shared get-version workflow.
.github/workflows/build-docker-task.yml Passes inputs.branch to the shared get-version workflow.

@ptr727
ptr727 merged commit 5adbcb9 into develop Jun 26, 2026
10 checks passed
@ptr727
ptr727 deleted the feature/version-leg-prerelease-213 branch June 26, 2026 18:05
ptr727 added a commit that referenced this pull request Jun 27, 2026
## Problem

Closes #219. The `validate-release` entry gate (added in #213/#215) runs
**unconditionally**, including in PR **smoke** builds. A smoke build
checks out the PR head in detached HEAD, so NBGV always computes a
prerelease version (`X.Y.Z-g<sha>`). On a **main-base** PR — a `develop
→ main` promotion carrying a build target — the gate's `branch ==
'main'` arm fails:

```
::error::Public (main) release version 'X.Y.Z-g<sha>' carries a prerelease suffix; refusing to publish.
```

`validate-release` fails → `build` is skipped → the required `Check pull
request workflow status` fails. **Every clean `develop → main` promotion
PR that includes a build-target change is blocked by its own smoke
build** (masked only when merged via admin bypass).

## Fix

Skip the gate for smoke builds — they never publish — keeping the job in
the graph as a **success** so `build-*`'s `needs: [get-version,
validate-release]` stays satisfied:

```yaml
          SMOKE: ${{ inputs.smoke }}
          ...
          if [[ "$SMOKE" == "true" ]]; then
            echo "Smoke build; skipping release version validation."
            exit 0
          fi
```

Real publishes (`smoke: false`) still get both-direction validation.

## Verification

- `actionlint` (Docker, shellcheck-bundled) clean; CRLF preserved.
- Per the issue's push-probe: a `smoke: true` invocation passes for both
`branch: main` (Release) and `branch: develop` (Debug) with
`github-release` skipped; real publishes unaffected.

Found via end-to-end CI flow validation during the #213/#214 downstream
re-sync.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ptr727 added a commit that referenced this pull request Jun 27, 2026
…ride (#222)

## Problem

Closes #221; supersedes the mechanism from #215. The #213 fix (PR #215)
restored the develop leg's prerelease tag by overriding `GITHUB_REF` in
the nbgv step `env:`. **It doesn't work.** `GITHUB_REF` is
GitHub-reserved — a step-level `env:` can't reliably override it (the
runner re-injects the dispatch ref). NBGV's GitHub Actions cloud-build
provider reads `GITHUB_REF` for `BuildingRef`, so on a publish
dispatched from `main` the develop leg was still classified public and
would publish a **clean (stable)** version.

CI evidence from the first real publish after #215:

```
GITHUB_REF: refs/heads/develop      # the step-env override (as configured)
"BuildingRef": "refs/heads/main"    # NBGV still saw the dispatch ref
"PublicRelease": true
"SemVer2": "1.4.2"                   # clean, no -g suffix
```

(The `validate-release` gate correctly blocked the bad publish, so
nothing shipped — but the develop prerelease leg never publishes.)

## Fix

NBGV versions from the **checked-out branch** unless its cloud provider
overrides with `GITHUB_REF`. Each matrix leg already checks out its own
branch, so set NBGV's own `IGNORE_GITHUB_REF=true` to make it ignore the
CI ref:

```yaml
      - name: Run Nerdbank.GitVersioning tool step
        id: nbgv
        uses: dotnet/nbgv@master
        env:
          IGNORE_GITHUB_REF: true
```

- Removed the ineffective `GITHUB_REF`/`GITHUB_REF_NAME` override.
- Dropped the now-useless `branch` input from `get-version-task.yml` and
its threading from all five callers (`build-release-task` + the four
`build-*-task`).
- `validate-release` entry gate (from #213/#215, smoke-skip from #219)
**stays** as the backstop.

NBGV source confirms the knob: `BuildingRef => IgnoreGitHubRef ? null :
env GITHUB_REF`.

## Verification

- `actionlint` (Docker) clean on all six changed workflows; CRLF
preserved.
- Per the issue's CI probe (real `dotnet/nbgv`): `develop` checkout +
`IGNORE_GITHUB_REF=true` → `PublicRelease=False`, `1.4.2-g…`; `main` →
`True`, `1.4.3`; `main` without the flag reproduces the bug.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ptr727 added a commit that referenced this pull request Jul 4, 2026
Promote the accumulated `develop` work to `main`. Twelve changes since
the last promotion:

- Add `WORKFLOW.md`: workflow style, architecture, behavioral contract,
test methodology (#223)
- Use NBGV `IGNORE_GITHUB_REF` instead of the ineffective `GITHUB_REF`
override (#222)
- Skip validate-release on smoke builds (#220)
- Gate asset delete on the release create/refresh condition (#218)
- Ship branch rulesets as versioned JSON in the re-sync / drift loop
(#212)
- Clean up transfer artifacts surgically at consumption, not
blanket-delete (#216)
- Version each publish leg against its own branch; validate at entry
(#215)
- Consolidate workspace configurations into a unified ProjectTemplate
workspace (#210)
- Template convergence barrier: absorb pins, generic release +
docker-readme, carry-whole-file (#207)
- Key merge-bot concurrency on PR number, not `github.ref` (#206)
- Codify orchestrated re-sync personas and full-replacement rule (#205)
- Lead action pins; affirm pattern-based artifact handoff (#204)

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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