diff --git a/.github/workflows/sdk-cli-release.yml b/.github/workflows/sdk-cli-release.yml index 5b49161e..5a2aa547 100644 --- a/.github/workflows/sdk-cli-release.yml +++ b/.github/workflows/sdk-cli-release.yml @@ -91,6 +91,9 @@ jobs: tag_name: ${{ steps.gate.outputs.tag_name }} version: ${{ steps.gate.outputs.version }} steps: + - name: Checkout + uses: actions/checkout@v7 + - name: Resolve release intent id: gate env: @@ -113,6 +116,57 @@ jobs: echo "No release requested for $GITHUB_REF — validation only." fi + # THE TAG AND THE PACKAGE MUST AGREE, AND UNTIL NOW NOTHING ASKED. + # + # This pipeline reads the version from two places and never compared them. + # `publish-npm` reads `package.json` — correctly — and since #569 it asks the + # registry first, so a version already published is skipped as a non-failure. + # `smoke-test-functional` then installs `@beyondnet/evolith-cli@${tag#v}`. + # + # When the two disagree, publish "succeeds" by skipping and the smoke test dies + # on `npm error code ETARGET / No matching version found`. That is not a flake and + # no re-run fixes it: the tag names a version that was never built. + # + # It happened on five consecutive tags, and each one filed an issue: + # v1.3.3 -> cli 1.3.1 (#599) + # v1.3.4 -> cli 1.3.1 (#603) + # v1.3.5 -> cli 1.3.1 (#606) + # v1.3.6 -> cli 1.3.2 + # v1.3.7 -> cli 1.3.2 (#627) + # + # Every one was doomed the moment the tag was pushed, and the pipeline spent a full + # build, three binary packagings and three platform smoke tests finding that out. + # The question belongs here, in the gate, before anything is built or published. + - name: Tag must name the version the package carries + if: steps.gate.outputs.release_created == 'true' + env: + TAG_NAME: ${{ steps.gate.outputs.tag_name }} + EXPECTED: ${{ steps.gate.outputs.version }} + run: | + set -euo pipefail + ACTUAL=$(node -p "require('./${CLI_DIR}/package.json').version") + if [ "$ACTUAL" != "$EXPECTED" ]; then + echo "::error::Tag $TAG_NAME asks to release $EXPECTED, but ${CLI_DIR}/package.json carries $ACTUAL." + { + echo "### Release refused: the tag and the package disagree" + echo "" + echo "| | |" + echo "|---|---|" + echo "| Tag | \`$TAG_NAME\` (asks for \`$EXPECTED\`) |" + echo "| \`${CLI_DIR}/package.json\` | \`$ACTUAL\` |" + echo "" + echo "Nothing was published. Publishing reads the package version and would have" + echo "shipped \`$ACTUAL\`, or skipped it as already-published; the smoke test then" + echo "installs \`@beyondnet/evolith-cli@$EXPECTED\`, which does not exist, and fails" + echo "with \`ETARGET\`." + echo "" + echo "Fix one of the two: bump the package to \`$EXPECTED\`, or delete this tag and" + echo "push \`v$ACTUAL\`." + } >> "$GITHUB_STEP_SUMMARY" + exit 1 + fi + echo "Tag $TAG_NAME and ${CLI_DIR}/package.json agree on $ACTUAL." + # ============================================ # GATE 2: Build and Test # ============================================