@@ -52,38 +52,58 @@ jobs:
5252 const path = require('path');
5353 const run = context.payload.workflow_run;
5454 const root = 'strict-outcomes';
55- // One directory per artifact, i.e. per expected-failures matrix
56- // entry. Each contains a strict-outcome.json written by ci_tests.yml
57- // with the schema {"name": "<matrix name>",
58- // "state": "success" | "failure" | "error"}.
59- let dirs = [];
55+ // One artifact per expected-failures matrix entry, each holding a
56+ // strict-outcome.json written by ci_tests.yml with the schema
57+ // {"name": "<matrix name>", "state": "success"|"failure"|"error"}.
58+ // download-artifact extracts each artifact into its own
59+ // strict-job-outcome-* subdirectory when the pattern matches
60+ // several artifacts, but flattens a single match directly into the
61+ // root -- scan for the JSON files so both layouts work.
62+ let entries = [];
6063 try {
61- dirs = fs.readdirSync(root).filter((d) => d.startsWith('strict-job-outcome-') );
64+ entries = fs.readdirSync(root, { withFileTypes: true } );
6265 } catch (err) {
6366 core.info(`No outcome artifacts downloaded (${err.message}); nothing to report.`);
6467 return;
6568 }
66- if (dirs.length === 0) {
67- core.info('No strict-job-outcome-* artifacts found; nothing to report.');
69+ const outcomes = [];
70+ if (entries.some((e) => e.isFile() && e.name === 'strict-outcome.json')) {
71+ outcomes.push({
72+ jsonPath: path.join(root, 'strict-outcome.json'),
73+ // The flat layout loses the artifact name; the JSON inside
74+ // normally supplies the real one.
75+ fallbackName: 'strict-job',
76+ });
77+ }
78+ for (const entry of entries) {
79+ if (entry.isDirectory() && entry.name.startsWith('strict-job-outcome-')) {
80+ outcomes.push({
81+ jsonPath: path.join(root, entry.name, 'strict-outcome.json'),
82+ fallbackName: entry.name.replace('strict-job-outcome-', ''),
83+ });
84+ }
85+ }
86+ if (outcomes.length === 0) {
87+ core.info('No strict-outcome.json files found in downloaded artifacts; nothing to report.');
6888 return;
6989 }
70- for (const dir of dirs ) {
90+ for (const { jsonPath, fallbackName } of outcomes ) {
7191 // Fall back to the artifact name and an error state if the JSON
7292 // is missing or malformed, so a broken upload still surfaces.
73- let name = dir.replace('strict-job-outcome-', '') ;
93+ let name = fallbackName ;
7494 let state = 'error';
7595 try {
76- const data = JSON.parse(fs.readFileSync(path.join(root, dir, 'strict-outcome.json') , 'utf8'));
96+ const data = JSON.parse(fs.readFileSync(jsonPath , 'utf8'));
7797 if (typeof data.name === 'string' && data.name) {
7898 name = data.name;
7999 }
80100 if (['success', 'failure', 'error'].includes(data.state)) {
81101 state = data.state;
82102 } else {
83- core.warning(`Unrecognized state ${JSON.stringify(data.state)} in ${dir }; reporting an error state.`);
103+ core.warning(`Unrecognized state ${JSON.stringify(data.state)} in ${jsonPath }; reporting an error state.`);
84104 }
85105 } catch (err) {
86- core.warning(`Could not read outcome JSON in ${dir } (${err.message}); reporting an error state.`);
106+ core.warning(`Could not read outcome JSON at ${jsonPath } (${err.message}); reporting an error state.`);
87107 }
88108 let conclusion;
89109 let title;
0 commit comments