diff --git a/lib/pregate/checks/lanes.ts b/lib/pregate/checks/lanes.ts index f3368b936..58458d39a 100644 --- a/lib/pregate/checks/lanes.ts +++ b/lib/pregate/checks/lanes.ts @@ -353,7 +353,8 @@ function unfinished(ctx: PregateContext, r: Awaited> type NoLaneMode = 'no-policy' | 'warned' | 'strict'; function describe(ctx: PregateContext, sel: Selection, mode: NoLaneMode): string[] { - const lines = mode === 'warned' ? sel.noLane.map(f => `WARN lanes — ${f} has no test lane (warn: ["lanes"] in ${ctx.configLabel}; the selected tests are still judged)`) + const lines = !sel.noLane.length ? [] + : mode === 'warned' ? sel.noLane.map(f => `WARN lanes — ${f} has no test lane (warn: ["lanes"] in ${ctx.configLabel}; the selected tests are still judged)`) : mode === 'strict' ? sel.noLane.map(f => `FAIL lanes — ${f} has no test lane`) : ctx.configKind === 'none' ? [`no policy: ${sel.noLane.join(' ')} have no test lane (a warning under no policy; the starter below maps them)`] : [`no lane policy: ${sel.noLane.join(' ')} have no test lane (a warning while ${ctx.configLabel} declares no dependencies, empty_lanes, selection or local; the starter below maps them)`]; diff --git a/lib/pregate/context.ts b/lib/pregate/context.ts index 162db7a7e..b745cb5fc 100644 --- a/lib/pregate/context.ts +++ b/lib/pregate/context.ts @@ -247,7 +247,7 @@ export function buildContext(o: BuildContextOptions): ContextLoad { return { ctx: { repoRoot: o.repoRoot, base, baseRef, baseSha: baseSha.out, mergeBase, head, wtree, touched: touchedFiles(o.repoRoot, mergeBase), - config, configLabel: configLoad.label, configKind: configLoad.kind, policyDeclaresLanes: configLoad.declaresLanes === true, scratch, configFile: configLoad.kind === 'user' && o.userConfigPath ? o.userConfigPath : PREGATE_CONFIG_PATH, ...(configLoad.digest ? { configDigest: configLoad.digest } : {}), ...(absentUserPolicy ? { absentUserPolicy } : {}), registry: registryLoad.registry as Registry, registryLabel: registryLoad.source.label, + config, configLabel: configLoad.label, configKind: configLoad.kind, policyDeclaresLanes: configLoad.declaresLanes !== false, scratch, configFile: configLoad.kind === 'user' && o.userConfigPath ? o.userConfigPath : PREGATE_CONFIG_PATH, ...(configLoad.digest ? { configDigest: configLoad.digest } : {}), ...(absentUserPolicy ? { absentUserPolicy } : {}), registry: registryLoad.registry as Registry, registryLabel: registryLoad.source.label, lanes, platform, allowRepoCommands: o.allowRepoCommands, timeoutMs: o.timeoutMs ?? (config.timeout_s ?? 600) * 1000, timeoutSource: o.timeoutMs !== undefined ? '--timeout' : config.timeout_s ? `timeout_s from ${configLoad.label}` : 'the 600 s default', stallTimeoutMs: o.stallTimeoutMs ?? (config.stall_timeout_s ?? DEFAULT_STALL_TIMEOUT_S) * 1000, progress: o.progress ?? (line => process.stderr.write(`${line}\n`)), diff --git a/lib/pregate/lane-selection.ts b/lib/pregate/lane-selection.ts index 3e0f9bafe..ffa5347d4 100644 --- a/lib/pregate/lane-selection.ts +++ b/lib/pregate/lane-selection.ts @@ -230,6 +230,7 @@ export function selectLanes(ctx: PregateContext): Selection { if (m.declaredNone) { const r = gone.includes(file) ? removedPath(ctx, graph, goneSet, file) : null; if (r && 'removed' in r) { waive(file, r); continue; } + if (r) provenance.push(`${file}: ${r.refused}; cleared by its [] declaration`); if (isDocsEmptyLane(file, ctx.config.empty_lanes ?? [])) emptyLane.push(file); continue; } diff --git a/test/pregate-policy-lane-verdicts.test.ts b/test/pregate-policy-lane-verdicts.test.ts index 97407bcaf..c00848c46 100644 --- a/test/pregate-policy-lane-verdicts.test.ts +++ b/test/pregate-policy-lane-verdicts.test.ts @@ -65,6 +65,16 @@ describe('a policy that declares no lanes keeps the no-policy lane verdicts (GST expect(r.ran).toContain('test/util.test.js'); }); + // Value: protects=a fully mapped change prints no empty "have no test lane" line under no policy or a lane-less one; fails_when=the + // no-lane line is rendered for an empty list; why_new=the mode switch is new; seam=none; no_claim=none + test.each([['no policy', null], ['timeout-only', { $schema: SCHEMA, timeout_s: 1800 }]])('%s: a fully mapped change passes with no no-lane line', (_name, policy) => { + const repo = fixture({ pregate: policy, baseFiles: NO_PLATFORM_LANE }); + commit(repo, { 'lib/util.js': 'exports.add = (a, b) => b + a;\n' }); + const r = lanes(repo); + expect([r.status, r.row.status]).toEqual([EXIT.ok, 'pass']); + expect(r.lines.some(l => l.includes('have no test lane'))).toBe(false); + }); + // Value: protects=the starter names the policy that exists instead of claiming there is none; fails_when=the starter header says // "no .gstack/pregate.json" while one is on the base; why_new=new wording; seam=none; no_claim=none test('the starter says the active policy declares no lanes, not that there is no policy', () => {