From b830d20bf2bf901d1c1911726e2d30cb251e097e Mon Sep 17 00:00:00 2001 From: Phil Leggetter Date: Fri, 29 May 2026 17:44:10 +0100 Subject: [PATCH 1/2] ci(spec-sdk-tests-vs-release): pin spec-sdk-tests/ alongside SDK on sdk_version override MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this, dispatching with sdk_version=v1.3.0 pinned the SDK to its release tag but left main's newer tests in place, causing TS compile errors when the tests referenced fields the pinned SDK didn't have ('type does not exist in type DestinationUpdate'). Verified empirically on the prior dispatch run. Now when sdk_version is set, we checkout both sdks/outpost-typescript/ AND spec-sdk-tests/ from the same SDK release tag. The tag is namespaced but points at a full repo commit, so spec-sdk-tests/ at that commit is the test suite as it shipped with that SDK release — guaranteed aligned. Bot regen PR case (the workflow's primary purpose) is unchanged: sdk_version stays empty, working tree's SDK + tests are both used, they're already aligned by the bot's regen. --- .../workflows/spec-sdk-tests-vs-release.yml | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/.github/workflows/spec-sdk-tests-vs-release.yml b/.github/workflows/spec-sdk-tests-vs-release.yml index 75f13d78..e071e374 100644 --- a/.github/workflows/spec-sdk-tests-vs-release.yml +++ b/.github/workflows/spec-sdk-tests-vs-release.yml @@ -23,7 +23,9 @@ # # workflow_dispatch inputs (UI overrides, ignored on PR runs): # sdk_version — pin SDK to a specific TS release (e.g. "1.3.0" or "v1.3.0"). -# Empty = use the dispatch branch's current SDK contents. +# When set, ALSO pins spec-sdk-tests/ to the same release +# point so tests + SDK shape stay aligned. Empty = use the +# dispatch branch's current SDK + test contents. # outpost_version — pin Outpost server to a specific release (e.g. "1.0.3" or "v1.0.3"). # Empty = latest non-prerelease Outpost release. name: Spec SDK tests vs released Outpost @@ -32,7 +34,7 @@ on: workflow_dispatch: inputs: sdk_version: - description: 'TS SDK version to test (e.g. "1.3.0" or "v1.3.0"). Empty = use this branch''s SDK contents.' + description: 'TS SDK version to test (e.g. "1.3.0" or "v1.3.0"). When set, also pins spec-sdk-tests/ to the same release point. Empty = use this branch''s SDK + test contents.' required: false type: string outpost_version: @@ -202,23 +204,29 @@ jobs: docker logs outpost || true exit 1 - - name: Override SDK with sdk_version (workflow_dispatch only) + - name: Override SDK + tests with sdk_version (workflow_dispatch only) # Guard event_name first so the inputs.* reference is short-circuited # away on pull_request runs (where inputs.* isn't populated). if: github.event_name == 'workflow_dispatch' && inputs.sdk_version != '' - # Replace the working tree's sdks/outpost-typescript with the contents - # at the SDK release tag. SDK tags are namespaced as - # sdks/outpost-typescript/v. Accept either "1.3.0" or "v1.3.0" by - # stripping any leading "v" and re-adding it. + # Replace BOTH sdks/outpost-typescript/ AND spec-sdk-tests/ with the + # contents at the SDK release tag. The SDK tag is namespaced + # (sdks/outpost-typescript/v) but points at a full repo commit, + # so checking out that tag for spec-sdk-tests/ gives us the tests as + # they were at SDK release time — guaranteed aligned with the pinned + # SDK shape. Without this, main's newer tests would reference SDK + # fields the pinned SDK doesn't have, causing TS compile errors. + # Accept either "1.3.0" or "v1.3.0" by stripping any leading "v". env: SDK_VERSION_INPUT: ${{ inputs.sdk_version }} run: | ver="${SDK_VERSION_INPUT#v}" full_tag="sdks/outpost-typescript/v${ver}" - echo "Pinning SDK to $full_tag" + echo "Pinning SDK + tests to $full_tag" git fetch --depth=1 origin "refs/tags/$full_tag:refs/tags/$full_tag" rm -rf sdks/outpost-typescript git checkout "$full_tag" -- sdks/outpost-typescript + rm -rf spec-sdk-tests + git checkout "$full_tag" -- spec-sdk-tests - name: Build TypeScript SDK working-directory: sdks/outpost-typescript From c642a5fe6eb145242c4563bd846fc0029282d810 Mon Sep 17 00:00:00 2001 From: Phil Leggetter Date: Fri, 29 May 2026 18:13:31 +0100 Subject: [PATCH 2/2] ci(spec-sdk-tests-vs-release): validate version inputs against strict X.Y.Z Spotted by Copilot review on #929. Typos in sdk_version or outpost_version otherwise produced cryptic git errors (fatal: couldn't find remote ref). Reject anything that isn't a strict semver triple before constructing the git refspec, with a clear ::error:: message naming the offending input. --- .github/workflows/spec-sdk-tests-vs-release.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/spec-sdk-tests-vs-release.yml b/.github/workflows/spec-sdk-tests-vs-release.yml index e071e374..e22df103 100644 --- a/.github/workflows/spec-sdk-tests-vs-release.yml +++ b/.github/workflows/spec-sdk-tests-vs-release.yml @@ -121,7 +121,12 @@ jobs: # `gh release view` returns the wrong thing. run: | if [ -n "$OVERRIDE" ]; then - tag="v${OVERRIDE#v}" + ver="${OVERRIDE#v}" + if ! [[ "$ver" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "::error::outpost_version must be a strict X.Y.Z version (got: '$OVERRIDE')" + exit 1 + fi + tag="v${ver}" echo "Using outpost_version override: $tag" else tag=$(gh api repos/${{ github.repository }}/releases \ @@ -220,6 +225,10 @@ jobs: SDK_VERSION_INPUT: ${{ inputs.sdk_version }} run: | ver="${SDK_VERSION_INPUT#v}" + if ! [[ "$ver" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "::error::sdk_version must be a strict X.Y.Z version (got: '$SDK_VERSION_INPUT')" + exit 1 + fi full_tag="sdks/outpost-typescript/v${ver}" echo "Pinning SDK + tests to $full_tag" git fetch --depth=1 origin "refs/tags/$full_tag:refs/tags/$full_tag"