Skip to content

Commit b83702e

Browse files
gustavoliraclaude
andcommitted
fix: address review (@rostalan) — surface skips, always write results.json
- Warn when backend plugins are filtered by KNOWN_FAILURES, and when nothing at all was validated (avoids a silent pass on a known-failure-only workspace); include the skipped list in results.json. [native-smoke.ts] - Move the CLI version check + temp-dir setup inside the try, so a failure there still writes a results.json (status: error) instead of exiting with no report. - Validate the --dynamic-plugins file exists (not just that the arg was passed). - Warn instead of silently skipping a plugin dir with a malformed package.json. [loader.ts] - Clarify that plugin-config KNOWN_FAILURES/configOverrides are for multi-plugin/ workspace runs and kept in TS (type-checked, in sync with the RHDH port) rather than package.json. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 588b296 commit b83702e

3 files changed

Lines changed: 57 additions & 12 deletions

File tree

smoke-tests-native/src/loader.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ export function discoverPlugins(root: string): PluginManifest {
5959
try {
6060
pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
6161
} catch {
62-
// A malformed package.json in one dir shouldn't abort discovery of the rest.
62+
// A malformed package.json shouldn't abort discovery of the rest, but it's a real
63+
// problem — warn loudly so it isn't skipped silently.
64+
console.warn(
65+
`⚠ skipping '${entry.name}': malformed package.json (${pkgPath})`,
66+
);
6367
continue;
6468
}
6569
const role: string = pkg.backstage?.role ?? "";

smoke-tests-native/src/native-smoke.ts

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
*/
2828

2929
import { execFileSync } from "node:child_process";
30+
import { existsSync } from "node:fs";
3031
import { mkdtemp, rm, mkdir, writeFile, copyFile } from "node:fs/promises";
3132
import { join, dirname } from "node:path";
3233
import { fileURLToPath } from "node:url";
@@ -74,7 +75,12 @@ const coreFeatures = [scaffolderPlugin];
7475
type Status = "pass" | "fail-load" | "fail-start" | "fail-bundle" | "error";
7576
type Report = {
7677
cliVersion: string;
77-
backend: { total: number; loaded: number; errors: PluginError[] };
78+
backend: {
79+
total: number;
80+
loaded: number;
81+
skipped: string[];
82+
errors: PluginError[];
83+
};
7884
backendStart: { ok: boolean; skipped?: boolean; error?: string };
7985
frontend: { total: number; valid: number; errors: PluginError[] };
8086
status: Status;
@@ -169,15 +175,25 @@ async function main(): Promise<number> {
169175
console.error("Provide --dynamic-plugins <dynamic-plugins.yaml>.");
170176
return 2;
171177
}
178+
if (!existsSync(dynamicPlugins)) {
179+
console.error(`dynamic-plugins file not found: ${dynamicPlugins}`);
180+
return 2;
181+
}
172182

173-
const cliVersion = run(process.execPath, [CLI_BIN, "--version"]);
174-
console.log(`▶ install CLI: ${CLI}@${cliVersion}`);
175-
176-
const tempDir = await mkdtemp(join(tmpdir(), "native-smoke-"));
177-
const root = join(tempDir, "dynamic-plugins-root");
178-
await mkdir(root, { recursive: true });
183+
// Declared outside the try so the catch/finally can see them even if setup fails.
184+
let cliVersion = "unknown";
185+
let tempDir: string | undefined;
179186

180187
try {
188+
// Everything fallible lives in the try, so any failure still writes a results.json
189+
// (status: error) instead of exiting with no report.
190+
cliVersion = run(process.execPath, [CLI_BIN, "--version"]);
191+
console.log(`▶ install CLI: ${CLI}@${cliVersion}`);
192+
193+
tempDir = await mkdtemp(join(tmpdir(), "native-smoke-"));
194+
const root = join(tempDir, "dynamic-plugins-root");
195+
await mkdir(root, { recursive: true });
196+
181197
await extractPlugins(root, dynamicPlugins);
182198

183199
const manifest = discoverPlugins(root);
@@ -187,18 +203,38 @@ async function main(): Promise<number> {
187203

188204
// Let extracted plugins (under a temp dir) resolve their @backstage/* peers here.
189205
patchModuleResolution(HARNESS_NODE_MODULES);
206+
207+
const skipped = manifest.backend
208+
.filter((p) => KNOWN_FAILURES.has(p.dirName))
209+
.map((p) => p.dirName);
210+
if (skipped.length > 0) {
211+
console.warn(
212+
`⚠ skipped ${skipped.length} known-failure backend plugin(s): ${skipped.join(", ")}`,
213+
);
214+
}
215+
190216
const backendPlugins = manifest.backend.filter(
191217
(p) => !KNOWN_FAILURES.has(p.dirName),
192218
);
193219
const { loaded, errors: loadErrors } = loadBackendPlugins(backendPlugins);
194220
const start = await startBackend(loaded);
195221
const frontend = validateFrontends(manifest.frontend);
196222

223+
// A workspace whose only backend plugin is a known failure would otherwise pass
224+
// silently having validated nothing — make that visible.
225+
if (loaded.length === 0 && manifest.frontend.length === 0) {
226+
console.warn(
227+
`⚠ nothing validated: 0 plugins loaded ` +
228+
`(${manifest.backend.length} backend found, ${skipped.length} skipped)`,
229+
);
230+
}
231+
197232
const report: Report = {
198233
cliVersion,
199234
backend: {
200235
total: manifest.backend.length,
201236
loaded: loaded.length,
237+
skipped,
202238
errors: loadErrors,
203239
},
204240
backendStart: start,
@@ -216,8 +252,9 @@ async function main(): Promise<number> {
216252
: String(start.ok);
217253
console.log(`▶ report → ${out} (status: ${report.status})`);
218254
console.log(
219-
` backend loaded ${report.backend.loaded}/${report.backend.total}, ` +
220-
`start=${startLabel}, frontend ${frontend.valid}/${manifest.frontend.length}`,
255+
` backend loaded ${report.backend.loaded}/${report.backend.total}` +
256+
(skipped.length ? ` (${skipped.length} skipped)` : "") +
257+
`, start=${startLabel}, frontend ${frontend.valid}/${manifest.frontend.length}`,
221258
);
222259
return report.status === "pass" ? 0 : 1;
223260
} catch (err) {
@@ -226,7 +263,7 @@ async function main(): Promise<number> {
226263
const message = err instanceof Error ? err.message : String(err);
227264
const report: Report = {
228265
cliVersion,
229-
backend: { total: 0, loaded: 0, errors: [] },
266+
backend: { total: 0, loaded: 0, skipped: [], errors: [] },
230267
backendStart: { ok: false, error: message },
231268
frontend: { total: 0, valid: 0, errors: [] },
232269
status: "error",
@@ -235,7 +272,7 @@ async function main(): Promise<number> {
235272
console.error(`▶ report → ${out} (status: error)\n${message}`);
236273
return 1;
237274
} finally {
238-
await rm(tempDir, { recursive: true, force: true });
275+
if (tempDir) await rm(tempDir, { recursive: true, force: true });
239276
}
240277
}
241278

smoke-tests-native/src/plugin-config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
* e2e-tests/playwright/utils/plugin-config.ts). Some backend plugins/modules
1010
* validate config at boot, so startTestBackend needs a root config with (dummy)
1111
* values for them; others can't load in a test env and are skipped.
12+
*
13+
* These lists mostly matter for multi-plugin / whole-workspace runs (they don't fire
14+
* for a single scaffolder-module run). Kept in TS — rather than package.json — to stay
15+
* type-checked and in sync with the RHDH source they're ported from.
1216
*/
1317

1418
import type { JsonObject } from "@backstage/types";

0 commit comments

Comments
 (0)