willfire 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/predict.js +28 -15
- package/package.json +2 -2
package/dist/predict.js
CHANGED
|
@@ -77,33 +77,40 @@ function getPrTrigger(wf) {
|
|
|
77
77
|
}
|
|
78
78
|
return MISSING;
|
|
79
79
|
}
|
|
80
|
+
// A predicate: does this workflow produce a run for the PR? Every workflow-level
|
|
81
|
+
// verdict is decidable, so there is no third answer to express. Only job
|
|
82
|
+
// expansion can be genuinely undecidable (dynamic matrix, non-local reusable
|
|
83
|
+
// workflow, unresolvable `if`), and that is a per-entry status.
|
|
80
84
|
function workflowDispatches(wf, ctx) {
|
|
81
85
|
const trig = getPrTrigger(wf);
|
|
82
86
|
if (trig === MISSING)
|
|
83
|
-
return [
|
|
87
|
+
return [false, "no pull_request trigger"];
|
|
84
88
|
const types = trig["types"] ?? DEFAULT_TYPES;
|
|
85
89
|
if (!types.includes(ctx.action)) {
|
|
86
|
-
return [
|
|
90
|
+
return [false, `action '${ctx.action}' not in types [${types}]`];
|
|
87
91
|
}
|
|
92
|
+
// Setting a filter and its -ignore twin on one trigger is invalid config.
|
|
93
|
+
// GitHub does not fall back to "no filter" or skip the workflow: it creates
|
|
94
|
+
// the run and concludes `startup_failure`. The run exists, so it dispatches.
|
|
88
95
|
if ("branches" in trig && "branches-ignore" in trig) {
|
|
89
|
-
return [
|
|
96
|
+
return [true, "both branches and branches-ignore set: startup failure"];
|
|
90
97
|
}
|
|
91
98
|
if ("branches" in trig && !matchFilters(ctx.baseRef, trig["branches"])) {
|
|
92
|
-
return [
|
|
99
|
+
return [false, `base branch '${ctx.baseRef}' not in branches`];
|
|
93
100
|
}
|
|
94
101
|
if ("branches-ignore" in trig && matchFilters(ctx.baseRef, trig["branches-ignore"])) {
|
|
95
|
-
return [
|
|
102
|
+
return [false, "base branch in branches-ignore"];
|
|
96
103
|
}
|
|
97
104
|
if ("paths" in trig && "paths-ignore" in trig) {
|
|
98
|
-
return [
|
|
105
|
+
return [true, "both paths and paths-ignore set: startup failure"];
|
|
99
106
|
}
|
|
100
107
|
if ("paths" in trig && !ctx.files.some((f) => matchFilters(f, trig["paths"]))) {
|
|
101
|
-
return [
|
|
108
|
+
return [false, "no changed file matches paths"];
|
|
102
109
|
}
|
|
103
110
|
if ("paths-ignore" in trig && ctx.files.every((f) => matchFilters(f, trig["paths-ignore"]))) {
|
|
104
|
-
return [
|
|
111
|
+
return [false, "all changed files match paths-ignore"];
|
|
105
112
|
}
|
|
106
|
-
return [
|
|
113
|
+
return [true, "trigger matched"];
|
|
107
114
|
}
|
|
108
115
|
/** Return list of matrix combination dicts, or null if dynamic. */
|
|
109
116
|
export function expandMatrix(strategy) {
|
|
@@ -308,11 +315,14 @@ export async function predict(octokit, repo, prNumber) {
|
|
|
308
315
|
}
|
|
309
316
|
const content = await fetchFile(path);
|
|
310
317
|
if (content == null) {
|
|
318
|
+
// The Actions API keeps listing a workflow as `active` after its file is
|
|
319
|
+
// deleted. There is no file at head, so there is nothing to dispatch —
|
|
320
|
+
// the same verdict as the disabled case above, reached a different way.
|
|
311
321
|
entries.push({
|
|
312
322
|
workflow: path,
|
|
313
323
|
job: "*",
|
|
314
|
-
status: "
|
|
315
|
-
reason: "
|
|
324
|
+
status: "no-dispatch",
|
|
325
|
+
reason: "no workflow file at head",
|
|
316
326
|
});
|
|
317
327
|
continue;
|
|
318
328
|
}
|
|
@@ -321,17 +331,20 @@ export async function predict(octokit, repo, prNumber) {
|
|
|
321
331
|
wf = parseYaml(content);
|
|
322
332
|
}
|
|
323
333
|
catch (e) {
|
|
334
|
+
// GitHub creates a run for an unparseable workflow file and concludes it
|
|
335
|
+
// `startup_failure`. The run exists but has no jobs, so this is a
|
|
336
|
+
// workflow-level "it dispatches" with nothing to expand.
|
|
324
337
|
entries.push({
|
|
325
338
|
workflow: path,
|
|
326
339
|
job: "*",
|
|
327
|
-
status: "
|
|
340
|
+
status: "run",
|
|
328
341
|
reason: `YAML parse error: ${e}`,
|
|
329
342
|
});
|
|
330
343
|
continue;
|
|
331
344
|
}
|
|
332
|
-
const [
|
|
333
|
-
if (
|
|
334
|
-
entries.push({ workflow: path, job: "*", status:
|
|
345
|
+
const [dispatches, reason] = workflowDispatches(wf, ctx);
|
|
346
|
+
if (!dispatches) {
|
|
347
|
+
entries.push({ workflow: path, job: "*", status: "no-dispatch", reason });
|
|
335
348
|
continue;
|
|
336
349
|
}
|
|
337
350
|
for (const [jobName, status, jreason] of await expandJobs(wf, ctx, fetchFile)) {
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "willfire",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Predict the set of CI check entries GitHub Actions will create for a pull request",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Kevin Scott <me@thekevinscott.com>",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/thekevinscott/
|
|
9
|
+
"url": "git+https://github.com/thekevinscott/willfire.git"
|
|
10
10
|
},
|
|
11
11
|
"keywords": [
|
|
12
12
|
"github-actions",
|