Skip to content

Publish matrix mislabels the develop leg as a public release: NBGV drops the prerelease tag, NuGet package published as stable #213

Description

@ptr727

Summary

When publish-release.yml runs from the default branch (main) — via schedule or workflow_dispatch — the matrix builds both the main and develop legs. The develop leg's NBGV SemVer2 is computed without its prerelease (-g<sha>) suffix, so:

  • the NuGet package is pushed as a stable / non-prerelease version (isPrerelease=false), and
  • the GitHub release tag is a clean X.Y.Z.

The GitHub release object is still correctly flagged prerelease: true (via build-release-task.ymlprerelease: ${{ inputs.branch != 'main' }}), which masks the problem: the release looks like a prerelease while the NuGet package and version string are not.

Impact

Every non-default-branch (develop) publish since the "dispatch-from-main, matrix builds both branches" model was adopted pushes a non-prerelease NuGet package. Consumers running dotnet add package <id> without --prerelease can resolve a develop build as if it were stable.

Observed in a derived repo: develop builds 1.3.8, 1.3.10, 1.4.1 were all published to NuGet with clean version strings and isPrerelease=false, despite being develop prereleases (and correctly flagged prerelease on the GitHub release).

Root cause

get-version-task.yml checks out inputs.ref (the leg's branch) and runs dotnet/nbgv@master. NBGV computes PublicRelease by matching version.json's publicReleaseRefSpec (^refs/heads/main$) against the branch reported by its GitHub Actions cloud-build provider, which reads GITHUB_REF.

On a publish triggered from main, GITHUB_REF=refs/heads/main for the entire run regardless of which ref each matrix leg checks out. So the develop leg is classified PublicRelease=true, and NBGV strips the -g<sha> prerelease suffix → clean X.Y.Z.

This is specific to the matrix publisher: a direct push-to-develop build runs with GITHUB_REF=refs/heads/develop and versions correctly. The regression appeared when publishing moved to the dispatch-from-main matrix.

Proposed fix

  1. Make NBGV version against the leg's branch. In get-version-task.yml, add a branch input (the publisher already threads a logical branch through build-release-task.yml) and pin the ref NBGV reads for that step:

    - name: Run Nerdbank.GitVersioning tool step
      id: nbgv
      uses: dotnet/nbgv@master
      env:
        # NBGV derives PublicRelease from the CI branch (GITHUB_REF). On a publish dispatched from the default
        # branch, every leg would otherwise be versioned as the public ref and lose its prerelease tag. Pin the
        # branch NBGV sees to the leg actually being versioned.
        GITHUB_REF: refs/heads/${{ inputs.branch }}
        GITHUB_REF_NAME: ${{ inputs.branch }}

    and have build-release-task.yml pass branch: ${{ inputs.branch }} to get-version-task.yml.

  2. Add the inverse backstop. build-release-task.yml already fails a branch == 'main' build whose SemVer2 carries a prerelease - ("Verify public release version" step). Add the symmetric guard: a branch != 'main' build whose SemVer2 has no prerelease suffix should fail loudly, so a future "develop published as stable" regression can't slip through silently.

Repro

Dispatch publish-release.yml from main; inspect the develop leg's get-version SemVer2 (clean X.Y.Z, missing -g<sha>) and the resulting NuGet package (isPrerelease=false).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions