From 209f3a3d78c33a7cd10adbfa93916231c2a85196 Mon Sep 17 00:00:00 2001 From: Durable Workflow Date: Wed, 23 Sep 2026 12:07:54 +0000 Subject: [PATCH] Verify CLI releases against current stable release authority --- scripts/ci/test-cli-release-channel.js | 46 ++++++++++-------------- scripts/ci/verify-cli-release-channel.js | 27 +++++--------- 2 files changed, 26 insertions(+), 47 deletions(-) diff --git a/scripts/ci/test-cli-release-channel.js b/scripts/ci/test-cli-release-channel.js index 1a149bb..0b0c284 100644 --- a/scripts/ci/test-cli-release-channel.js +++ b/scripts/ci/test-cli-release-channel.js @@ -47,46 +47,37 @@ test('a prerelease tag exposed as a stable GitHub Release fails closed', () => { ); }); -test('channel classification supports prerelease and stable transition records', () => { +test('channel classification reads the public stable release authority', () => { assert.deepEqual( validateChannel({ schema: AUTHORITY_SCHEMA, - schema_version: 2, - outcome: 'pass', - qualified_artifact_versions: {cli: '2.0.0-rc.31'}, + schema_version: 1, + artifacts: {cli: '2.0.0'}, }), { schema: AUTHORITY_SCHEMA, - channel: 'prerelease', - version: '2.0.0-rc.31', + channel: 'stable', + version: '2.0.0', }, ); - assert.equal(validateChannel({ - schema: AUTHORITY_SCHEMA, - schema_version: 2, - outcome: 'pass', - qualified_artifact_versions: {cli: '2.0.0'}, - }).version, '2.0.0'); assert.throws( () => validateChannel({ schema: AUTHORITY_SCHEMA, - schema_version: 2, - outcome: 'pass', - qualified_artifact_versions: {cli: '2.0.0-preview.1'}, + schema_version: 1, + artifacts: {cli: '2.0.0-rc.1'}, }), - /must be an alpha, beta, or rc/, + /must be exact MAJOR.MINOR.PATCH/, ); }); -test('the supported prerelease must remain publicly discoverable with complete assets', async () => { +test('the current stable channel remains publicly discoverable with complete assets', async () => { const releaseTag = '2.0.0-rc.32'; - const supportedTag = '2.0.0-rc.12'; + const supportedTag = '2.0.0'; const channel = { schema: AUTHORITY_SCHEMA, - schema_version: 2, - outcome: 'pass', - qualified_artifact_versions: {cli: supportedTag}, + schema_version: 1, + artifacts: {cli: supportedTag}, }; const fetchImpl = async url => { if (url === 'https://example.test/channel.json') { @@ -96,7 +87,7 @@ test('the supported prerelease must remain publicly discoverable with complete a return jsonResponse(release(releaseTag, true)); } if (url.endsWith(`/releases/tags/${supportedTag}`)) { - return jsonResponse(release(supportedTag, true)); + return jsonResponse(release(supportedTag, false)); } return jsonResponse({}, 404); }; @@ -109,7 +100,7 @@ test('the supported prerelease must remain publicly discoverable with complete a releaseTag, }), { - channel: 'prerelease', + channel: 'stable', channel_version: supportedTag, release_prerelease: true, release_tag: releaseTag, @@ -123,7 +114,7 @@ test('the supported prerelease must remain publicly discoverable with complete a if (url.endsWith(`/releases/tags/${releaseTag}`)) { return jsonResponse(release(releaseTag, true)); } - const incompleteSupportedRelease = release(supportedTag, true); + const incompleteSupportedRelease = release(supportedTag, false); incompleteSupportedRelease.assets = incompleteSupportedRelease.assets.filter( asset => asset.name !== 'SHA256SUMS', ); @@ -155,7 +146,7 @@ test('the supported prerelease must remain publicly discoverable with complete a fetchImpl: unavailableFetch, releaseTag, }), - /HTTP 404 fetching .*2\.0\.0-rc\.12/, + /HTTP 404 fetching .*2\.0\.0/, ); }); @@ -164,9 +155,8 @@ test('stable transition resolution requires stable public metadata', async () => if (url === 'https://example.test/channel.json') { return jsonResponse({ schema: AUTHORITY_SCHEMA, - schema_version: 2, - outcome: 'pass', - qualified_artifact_versions: {cli: '2.0.0'}, + schema_version: 1, + artifacts: {cli: '2.0.0'}, }); } return jsonResponse(release('2.0.0', false)); diff --git a/scripts/ci/verify-cli-release-channel.js b/scripts/ci/verify-cli-release-channel.js index 3f35f98..0e4f4ba 100644 --- a/scripts/ci/verify-cli-release-channel.js +++ b/scripts/ci/verify-cli-release-channel.js @@ -2,9 +2,9 @@ const {parseReleaseVersion} = require('./release-version'); -const AUTHORITY_SCHEMA = 'durable-workflow.docs.public-artifact-compatibility-evidence'; +const AUTHORITY_SCHEMA = 'durable-workflow.docs.stable-releases'; const DEFAULT_CHANNEL_URL = - 'https://durable-workflow.com/public-artifact-compatibility-evidence.json'; + 'https://durable-workflow.com/stable-releases.json'; const DEFAULT_API_BASE = 'https://api.github.com/repos/durable-workflow/cli'; const REQUIRED_ASSETS = Object.freeze([ 'SHA256SUMS', @@ -32,29 +32,18 @@ function validateChannel(value) { if (!value || typeof value !== 'object' || Array.isArray(value)) { throw new Error('CLI release authority must be a JSON object'); } - if (value.schema !== AUTHORITY_SCHEMA || value.schema_version !== 2 || value.outcome !== 'pass') { - throw new Error('CLI release authority must be a passing schema-v2 document'); + if (value.schema !== AUTHORITY_SCHEMA || value.schema_version !== 1) { + throw new Error('CLI release authority must use the stable-releases schema v1'); } - const version = value.qualified_artifact_versions?.cli; + const version = value.artifacts?.cli; const parsed = parseReleaseVersion(version); - if (parsed === null) { - throw new Error(`qualified CLI version is not valid SemVer: ${String(version)}`); - } - - const channel = parsed.prerelease === null ? 'stable' : 'prerelease'; - if (channel === 'prerelease') { - const [label, sequence, ...rest] = parsed.prerelease; - if (!['alpha', 'beta', 'rc'].includes(label)) { - throw new Error('qualified CLI prerelease must be an alpha, beta, or rc version'); - } - if (rest.length > 0 || sequence === undefined || !/^(0|[1-9][0-9]*)$/.test(sequence)) { - throw new Error('qualified CLI prerelease must use a numeric sequence'); - } + if (parsed === null || parsed.prerelease !== null || parsed.build !== null) { + throw new Error(`stable CLI version must be exact MAJOR.MINOR.PATCH: ${String(version)}`); } return Object.freeze({ - channel, + channel: 'stable', schema: value.schema, version, });