From a5076a2d98aa6c53d98c4e2a7acbb50c70452f80 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Mon, 22 Jun 2026 17:21:05 -0700 Subject: [PATCH] Reincorporate template publish-dispatch guards and JSON casing fix (#759) Re-sync the upstream ProjectTemplate fixes (ptr727/ProjectTemplate#184/#185, Fixes #181/#182/#183) that resolved the publish-dispatch mis-versioning defect surfaced while re-syncing this downstream. - publish-release.yml: fail fast when a publish is dispatched on a non-default ref; the matrix builds both branches, so a non-default dispatch mis-versions the main leg and publishes a malformed non-prerelease "Latest". - build-release-task.yml: refuse to create a main release whose SemVer2 carries a prerelease suffix (root-cause-agnostic safety net). - .editorconfig: correct JSON/JSONC casing in the section comment. Co-authored-by: Claude Opus 4.8 (1M context) --- .editorconfig | 2 +- .github/workflows/build-release-task.yml | 15 +++++++++++++++ .github/workflows/publish-release.yml | 9 +++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index cc5416c4..d66b1947 100644 --- a/.editorconfig +++ b/.editorconfig @@ -36,7 +36,7 @@ indent_size = 2 end_of_line = crlf indent_size = 2 -# Json and JsonC files +# JSON and JSONC files [*.{json,jsonc}] end_of_line = crlf diff --git a/.github/workflows/build-release-task.yml b/.github/workflows/build-release-task.yml index a7c6b876..84a5e87b 100644 --- a/.github/workflows/build-release-task.yml +++ b/.github/workflows/build-release-task.yml @@ -103,6 +103,21 @@ jobs: with: ref: ${{ needs.get-version.outputs.GitCommitId }} + # Safety net: a public (main) release must never carry a prerelease identifier - any '-' in SemVer2 (e.g. the + # observed '-g' git-height suffix). Guards against NBGV mis-detecting the public ref (e.g. a dispatch on a + # non-default ref) from publishing a malformed non-prerelease release that GitHub would then mark "Latest". + # Root-cause-agnostic backstop to the dispatch-ref guard in publish-release.yml. + - name: Verify public release version step + if: ${{ inputs.branch == 'main' }} + env: + SEMVER2: ${{ needs.get-version.outputs.SemVer2 }} + run: | + set -euo pipefail + if [[ "$SEMVER2" == *-* ]]; then + echo "::error::Public (main) release version '$SEMVER2' carries a prerelease suffix; refusing to publish." + exit 1 + fi + # Collect every release-asset--* artifact by pattern, so the # release job never names a build job and stays reusable as targets change. - name: Download release asset artifacts step diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 3a0e70e3..d2b7ea02 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -43,6 +43,15 @@ jobs: PUBLISH_ON_MERGE: ${{ vars.PUBLISH_ON_MERGE }} run: | set -euo pipefail + # A schedule or dispatch builds BOTH branches in the matrix regardless of the triggering ref (a push builds + # only the pushed branch). Dispatching on a non-default ref makes the main leg mis-version (NBGV can't resolve + # the public main ref), publishing a malformed non-prerelease release that GitHub marks "Latest". Fail fast: + # dispatch only from the default branch. + if [[ "${{ github.event_name }}" == "workflow_dispatch" \ + && "${{ github.ref_name }}" != "${{ github.event.repository.default_branch }}" ]]; then + echo "::error::Dispatch publish-release from the default branch (${{ github.event.repository.default_branch }}); the matrix builds both branches. Re-dispatch on the default branch." + exit 1 + fi case "${{ github.event_name }}" in push) branches='["${{ github.ref_name }}"]'