Skip to content

Commit 1eb0f22

Browse files
committed
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 a2855b0 commit 1eb0f22

2 files changed

Lines changed: 45 additions & 6 deletions

File tree

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

Lines changed: 25 additions & 4 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,10 +182,13 @@ export async function checkConformance(options: {
179182
}
180183

181184
const outputDir = mkdtempSync(join(tmpdir(), 'tier-check-server-'));
185+
const specVersionArg = options.specVersion
186+
? `--spec-version ${options.specVersion}`
187+
: '';
182188

183189
try {
184190
execSync(
185-
`node dist/index.js server --url ${options.serverUrl} -o ${outputDir}`,
191+
`node dist/index.js server --url ${options.serverUrl} -o ${outputDir} ${specVersionArg}`,
186192
{
187193
cwd: process.cwd(),
188194
stdio: ['pipe', 'pipe', 'pipe'],
@@ -193,9 +199,16 @@ export async function checkConformance(options: {
193199
// Non-zero exit is expected when tests fail — results are still in outputDir
194200
}
195201

202+
const activeScenarios = new Set(listActiveClientScenarios());
203+
const expectedScenarios = options.specVersion
204+
? listClientScenariosForSpec(options.specVersion).filter((s) =>
205+
activeScenarios.has(s)
206+
)
207+
: [...activeScenarios];
208+
196209
return reconcileWithExpected(
197210
parseOutputDir(outputDir),
198-
listActiveClientScenarios(),
211+
expectedScenarios,
199212
'server'
200213
);
201214
}
@@ -206,6 +219,7 @@ export async function checkConformance(options: {
206219
export async function checkClientConformance(options: {
207220
clientCmd?: string;
208221
skip?: boolean;
222+
specVersion?: SpecVersion;
209223
}): Promise<ConformanceResult> {
210224
if (options.skip || !options.clientCmd) {
211225
return {
@@ -219,10 +233,13 @@ export async function checkClientConformance(options: {
219233
}
220234

221235
const outputDir = mkdtempSync(join(tmpdir(), 'tier-check-client-'));
236+
const specVersionArg = options.specVersion
237+
? `--spec-version ${options.specVersion}`
238+
: '';
222239

223240
try {
224241
execSync(
225-
`node dist/index.js client --command '${options.clientCmd}' --suite all -o ${outputDir}`,
242+
`node dist/index.js client --command '${options.clientCmd}' --suite all -o ${outputDir} ${specVersionArg}`,
226243
{
227244
cwd: process.cwd(),
228245
stdio: ['pipe', 'pipe', 'pipe'],
@@ -233,5 +250,9 @@ export async function checkClientConformance(options: {
233250
// Non-zero exit is expected when tests fail — results are still in outputDir
234251
}
235252

236-
return reconcileWithExpected(parseOutputDir(outputDir), listScenarios());
253+
const expectedScenarios = options.specVersion
254+
? listScenariosForSpec(options.specVersion)
255+
: listScenarios();
256+
257+
return reconcileWithExpected(parseOutputDir(outputDir), expectedScenarios);
237258
}

src/tier-check/index.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ 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 { ALL_SPEC_VERSIONS } from '../scenarios';
17+
import { SpecVersion } from '../types';
1618

1719
function parseRepo(repo: string): { owner: string; repo: string } {
1820
const parts = repo.split('/');
@@ -48,10 +50,24 @@ export function createTierCheckCommand(): Command {
4850
'--token <token>',
4951
'GitHub token (defaults to GITHUB_TOKEN env var)'
5052
)
53+
.option(
54+
'--spec-version <version>',
55+
'Only run conformance scenarios for this spec version'
56+
)
5157
.action(async (options) => {
5258
const { owner, repo } = parseRepo(options.repo);
5359
let token = options.token || process.env.GITHUB_TOKEN;
5460

61+
let specVersion: SpecVersion | undefined;
62+
if (options.specVersion) {
63+
if (!ALL_SPEC_VERSIONS.includes(options.specVersion as SpecVersion)) {
64+
console.error(`Unknown spec version: ${options.specVersion}`);
65+
console.error(`Valid versions: ${ALL_SPEC_VERSIONS.join(', ')}`);
66+
process.exit(1);
67+
}
68+
specVersion = options.specVersion as SpecVersion;
69+
}
70+
5571
if (!token) {
5672
// Try to get token from GitHub CLI
5773
try {
@@ -90,14 +106,16 @@ export function createTierCheckCommand(): Command {
90106
] = await Promise.all([
91107
checkConformance({
92108
serverUrl: options.conformanceServerUrl,
93-
skip: options.skipConformance
109+
skip: options.skipConformance,
110+
specVersion
94111
}).then((r) => {
95112
console.error(' ✓ Server Conformance');
96113
return r;
97114
}),
98115
checkClientConformance({
99116
clientCmd: options.clientCmd,
100-
skip: options.skipConformance || !options.clientCmd
117+
skip: options.skipConformance || !options.clientCmd,
118+
specVersion
101119
}).then((r) => {
102120
console.error(' ✓ Client Conformance');
103121
return r;

0 commit comments

Comments
 (0)