Skip to content

Commit e151bd4

Browse files
DePasqualeOrgfelixweinberger
authored andcommitted
feat: add --spec-version option to tier-check
Allows filtering conformance scenarios by target spec version, so SDKs are only scored against scenarios applicable to the version they target. This prevents legacy backward-compatibility scenarios from counting against SDKs that don't claim legacy support.
1 parent fe16e38 commit e151bd4

File tree

4 files changed

+72
-39
lines changed

4 files changed

+72
-39
lines changed

src/index.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
listScenariosForSpec,
2525
listClientScenariosForSpec,
2626
getScenarioSpecVersions,
27-
ALL_SPEC_VERSIONS
27+
resolveSpecVersion
2828
} from './scenarios';
2929
import type { SpecVersion } from './scenarios';
3030
import { ConformanceCheck } from './types';
@@ -37,15 +37,6 @@ import {
3737
import { createTierCheckCommand } from './tier-check';
3838
import packageJson from '../package.json';
3939

40-
function resolveSpecVersion(value: string): SpecVersion {
41-
if (ALL_SPEC_VERSIONS.includes(value as SpecVersion)) {
42-
return value as SpecVersion;
43-
}
44-
console.error(`Unknown spec version: ${value}`);
45-
console.error(`Valid versions: ${ALL_SPEC_VERSIONS.join(', ')}`);
46-
process.exit(1);
47-
}
48-
4940
// Note on naming: `command` refers to which CLI command is calling this.
5041
// The `client` command tests Scenario objects (which test clients),
5142
// and the `server` command tests ClientScenario objects (which test servers).

src/scenarios/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,15 @@ export const ALL_SPEC_VERSIONS: SpecVersion[] = [
227227
'extension'
228228
];
229229

230+
export function resolveSpecVersion(value: string): SpecVersion {
231+
if (ALL_SPEC_VERSIONS.includes(value as SpecVersion)) {
232+
return value as SpecVersion;
233+
}
234+
console.error(`Unknown spec version: ${value}`);
235+
console.error(`Valid versions: ${ALL_SPEC_VERSIONS.join(', ')}`);
236+
process.exit(1);
237+
}
238+
230239
export function listScenariosForSpec(version: SpecVersion): string[] {
231240
return scenariosList
232241
.filter((s) => s.specVersions.includes(version))

src/tier-check/checks/test-conformance-results.ts

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { ConformanceResult } from '../types';
66
import {
77
listScenarios,
88
listActiveClientScenarios,
9+
listScenariosForSpec,
10+
listClientScenariosForSpec,
911
getScenarioSpecVersions
1012
} from '../../scenarios';
1113
import { ConformanceCheck, SpecVersion } from '../../types';
@@ -166,6 +168,7 @@ function reconcileWithExpected(
166168
export async function checkConformance(options: {
167169
serverUrl?: string;
168170
skip?: boolean;
171+
specVersion?: SpecVersion;
169172
}): Promise<ConformanceResult> {
170173
if (options.skip || !options.serverUrl) {
171174
return {
@@ -179,23 +182,37 @@ export async function checkConformance(options: {
179182
}
180183

181184
const outputDir = mkdtempSync(join(tmpdir(), 'tier-check-server-'));
185+
const args = [
186+
process.argv[1],
187+
'server',
188+
'--url',
189+
options.serverUrl,
190+
'-o',
191+
outputDir
192+
];
193+
if (options.specVersion) {
194+
args.push('--spec-version', options.specVersion);
195+
}
182196

183197
try {
184-
execFileSync(
185-
process.execPath,
186-
[process.argv[1], 'server', '--url', options.serverUrl, '-o', outputDir],
187-
{
188-
stdio: ['pipe', 'pipe', 'pipe'],
189-
timeout: 120_000
190-
}
191-
);
198+
execFileSync(process.execPath, args, {
199+
stdio: ['pipe', 'pipe', 'pipe'],
200+
timeout: 120_000
201+
});
192202
} catch {
193203
// Non-zero exit is expected when tests fail — results are still in outputDir
194204
}
195205

206+
const activeScenarios = new Set(listActiveClientScenarios());
207+
const expectedScenarios = options.specVersion
208+
? listClientScenariosForSpec(options.specVersion).filter((s) =>
209+
activeScenarios.has(s)
210+
)
211+
: [...activeScenarios];
212+
196213
return reconcileWithExpected(
197214
parseOutputDir(outputDir),
198-
listActiveClientScenarios(),
215+
expectedScenarios,
199216
'server'
200217
);
201218
}
@@ -206,6 +223,7 @@ export async function checkConformance(options: {
206223
export async function checkClientConformance(options: {
207224
clientCmd?: string;
208225
skip?: boolean;
226+
specVersion?: SpecVersion;
209227
}): Promise<ConformanceResult> {
210228
if (options.skip || !options.clientCmd) {
211229
return {
@@ -219,28 +237,32 @@ export async function checkClientConformance(options: {
219237
}
220238

221239
const outputDir = mkdtempSync(join(tmpdir(), 'tier-check-client-'));
240+
const args = [
241+
process.argv[1],
242+
'client',
243+
'--command',
244+
options.clientCmd,
245+
'--suite',
246+
'all',
247+
'-o',
248+
outputDir
249+
];
250+
if (options.specVersion) {
251+
args.push('--spec-version', options.specVersion);
252+
}
222253

223254
try {
224-
execFileSync(
225-
process.execPath,
226-
[
227-
process.argv[1],
228-
'client',
229-
'--command',
230-
options.clientCmd,
231-
'--suite',
232-
'all',
233-
'-o',
234-
outputDir
235-
],
236-
{
237-
stdio: ['pipe', 'pipe', 'pipe'],
238-
timeout: 120_000
239-
}
240-
);
255+
execFileSync(process.execPath, args, {
256+
stdio: ['pipe', 'pipe', 'pipe'],
257+
timeout: 120_000
258+
});
241259
} catch {
242260
// Non-zero exit is expected when tests fail — results are still in outputDir
243261
}
244262

245-
return reconcileWithExpected(parseOutputDir(outputDir), listScenarios());
263+
const expectedScenarios = options.specVersion
264+
? listScenariosForSpec(options.specVersion)
265+
: listScenarios();
266+
267+
return reconcileWithExpected(parseOutputDir(outputDir), expectedScenarios);
246268
}

src/tier-check/index.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { checkSpecTracking } from './checks/spec-tracking';
1313
import { computeTier } from './tier-logic';
1414
import { formatJson, formatMarkdown, formatTerminal } from './output';
1515
import { TierScorecard } from './types';
16+
import { resolveSpecVersion } from '../scenarios';
1617

1718
function parseRepo(repo: string): { owner: string; repo: string } {
1819
const parts = repo.split('/');
@@ -48,10 +49,18 @@ export function createTierCheckCommand(): Command {
4849
'--token <token>',
4950
'GitHub token (defaults to GITHUB_TOKEN env var)'
5051
)
52+
.option(
53+
'--spec-version <version>',
54+
'Only run conformance scenarios for this spec version'
55+
)
5156
.action(async (options) => {
5257
const { owner, repo } = parseRepo(options.repo);
5358
let token = options.token || process.env.GITHUB_TOKEN;
5459

60+
const specVersion = options.specVersion
61+
? resolveSpecVersion(options.specVersion)
62+
: undefined;
63+
5564
if (!token) {
5665
// Try to get token from GitHub CLI
5766
try {
@@ -90,14 +99,16 @@ export function createTierCheckCommand(): Command {
9099
] = await Promise.all([
91100
checkConformance({
92101
serverUrl: options.conformanceServerUrl,
93-
skip: options.skipConformance
102+
skip: options.skipConformance,
103+
specVersion
94104
}).then((r) => {
95105
console.error(' ✓ Server Conformance');
96106
return r;
97107
}),
98108
checkClientConformance({
99109
clientCmd: options.clientCmd,
100-
skip: options.skipConformance || !options.clientCmd
110+
skip: options.skipConformance || !options.clientCmd,
111+
specVersion
101112
}).then((r) => {
102113
console.error(' ✓ Client Conformance');
103114
return r;

0 commit comments

Comments
 (0)