@biffo/cli 0.250.3 → 0.251.0
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.
|
@@ -9,6 +9,7 @@ overrides:
|
|
|
9
9
|
sharp@<0.35.0: '>=0.35.0'
|
|
10
10
|
brace-expansion@<5.0.9: '>=5.0.9'
|
|
11
11
|
undici@<7.29.0: '>=7.29.0'
|
|
12
|
+
js-yaml@<4.3.1: '>=4.3.1 <5'
|
|
12
13
|
|
|
13
14
|
importers:
|
|
14
15
|
|
|
@@ -1871,8 +1872,8 @@ packages:
|
|
|
1871
1872
|
js-tokens@4.0.0:
|
|
1872
1873
|
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
|
1873
1874
|
|
|
1874
|
-
js-yaml@4.3.
|
|
1875
|
-
resolution: {integrity: sha512-
|
|
1875
|
+
js-yaml@4.3.1:
|
|
1876
|
+
resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==}
|
|
1876
1877
|
hasBin: true
|
|
1877
1878
|
|
|
1878
1879
|
jsdom@30.0.1:
|
|
@@ -2937,7 +2938,7 @@ snapshots:
|
|
|
2937
2938
|
globals: 14.0.0
|
|
2938
2939
|
ignore: 5.3.2
|
|
2939
2940
|
import-fresh: 3.3.1
|
|
2940
|
-
js-yaml: 4.3.
|
|
2941
|
+
js-yaml: 4.3.1
|
|
2941
2942
|
minimatch: 3.1.5
|
|
2942
2943
|
strip-json-comments: 3.1.1
|
|
2943
2944
|
transitivePeerDependencies:
|
|
@@ -3974,8 +3975,8 @@ snapshots:
|
|
|
3974
3975
|
'@typescript-eslint/parser': 8.62.1(eslint@9.39.4)(typescript@5.9.3)
|
|
3975
3976
|
eslint: 9.39.4
|
|
3976
3977
|
eslint-import-resolver-node: 0.3.10
|
|
3977
|
-
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0
|
|
3978
|
-
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1
|
|
3978
|
+
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4)
|
|
3979
|
+
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4)
|
|
3979
3980
|
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.4)
|
|
3980
3981
|
eslint-plugin-react: 7.37.5(eslint@9.39.4)
|
|
3981
3982
|
eslint-plugin-react-hooks: 5.2.0(eslint@9.39.4)
|
|
@@ -3994,7 +3995,7 @@ snapshots:
|
|
|
3994
3995
|
transitivePeerDependencies:
|
|
3995
3996
|
- supports-color
|
|
3996
3997
|
|
|
3997
|
-
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0
|
|
3998
|
+
eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4):
|
|
3998
3999
|
dependencies:
|
|
3999
4000
|
'@nolyfill/is-core-module': 1.0.39
|
|
4000
4001
|
debug: 4.4.3
|
|
@@ -4005,22 +4006,22 @@ snapshots:
|
|
|
4005
4006
|
tinyglobby: 0.2.17
|
|
4006
4007
|
unrs-resolver: 1.12.2
|
|
4007
4008
|
optionalDependencies:
|
|
4008
|
-
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1
|
|
4009
|
+
eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4)
|
|
4009
4010
|
transitivePeerDependencies:
|
|
4010
4011
|
- supports-color
|
|
4011
4012
|
|
|
4012
|
-
eslint-module-utils@2.14.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1
|
|
4013
|
+
eslint-module-utils@2.14.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4):
|
|
4013
4014
|
dependencies:
|
|
4014
4015
|
debug: 3.2.7
|
|
4015
4016
|
optionalDependencies:
|
|
4016
4017
|
'@typescript-eslint/parser': 8.62.1(eslint@9.39.4)(typescript@5.9.3)
|
|
4017
4018
|
eslint: 9.39.4
|
|
4018
4019
|
eslint-import-resolver-node: 0.3.10
|
|
4019
|
-
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0
|
|
4020
|
+
eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4)
|
|
4020
4021
|
transitivePeerDependencies:
|
|
4021
4022
|
- supports-color
|
|
4022
4023
|
|
|
4023
|
-
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1
|
|
4024
|
+
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4):
|
|
4024
4025
|
dependencies:
|
|
4025
4026
|
'@rtsao/scc': 1.1.0
|
|
4026
4027
|
array-includes: 3.1.9
|
|
@@ -4031,7 +4032,7 @@ snapshots:
|
|
|
4031
4032
|
doctrine: 2.1.0
|
|
4032
4033
|
eslint: 9.39.4
|
|
4033
4034
|
eslint-import-resolver-node: 0.3.10
|
|
4034
|
-
eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1
|
|
4035
|
+
eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.62.1(eslint@9.39.4)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4)
|
|
4035
4036
|
hasown: 2.0.4
|
|
4036
4037
|
is-core-module: 2.16.2
|
|
4037
4038
|
is-glob: 4.0.3
|
|
@@ -4480,7 +4481,7 @@ snapshots:
|
|
|
4480
4481
|
|
|
4481
4482
|
js-tokens@4.0.0: {}
|
|
4482
4483
|
|
|
4483
|
-
js-yaml@4.3.
|
|
4484
|
+
js-yaml@4.3.1:
|
|
4484
4485
|
dependencies:
|
|
4485
4486
|
argparse: 2.0.1
|
|
4486
4487
|
|
package/package.json
CHANGED
|
@@ -102,6 +102,60 @@ export const VERDICT = {
|
|
|
102
102
|
FLEET_FAULT_UNEXPLAINED: 'fleet-fault-unexplained',
|
|
103
103
|
/** Ran on a GitHub-hosted runner, so there is no fleet to correlate against. */
|
|
104
104
|
NOT_SELF_HOSTED: 'not-self-hosted',
|
|
105
|
+
/**
|
|
106
|
+
* The job never ran. Not a gate rejecting the change, not a runner dying
|
|
107
|
+
* mid-job — GitHub's own control plane failed before the work began, or no
|
|
108
|
+
* runner was ever assigned. Re-run it; there is nothing in the repo to fix.
|
|
109
|
+
*/
|
|
110
|
+
NEVER_RAN: 'never-ran',
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* A job that GitHub could not start, as distinct from one that ran and failed.
|
|
115
|
+
*
|
|
116
|
+
* Two shapes, both observed on 2026-08-06/07 during a critical GitHub Actions
|
|
117
|
+
* incident, and both previously adjudicated `real-failure` because
|
|
118
|
+
* `isRunnerKill` answers "did a runner die MID-job?" and neither of these got
|
|
119
|
+
* that far:
|
|
120
|
+
*
|
|
121
|
+
* 1. **Died in setup.** The only step is `Set up job` and it failed —
|
|
122
|
+
* `Failed to resolve action download info. Error: Service Unavailable`.
|
|
123
|
+
* A gate that genuinely rejects a change has run checkout and install
|
|
124
|
+
* first, so it always carries more steps than this.
|
|
125
|
+
* 2. **Never scheduled.** `conclusion: 'cancelled'` with **no steps at all**
|
|
126
|
+
* and no `runner_name`: the job sat in the queue until GitHub gave up.
|
|
127
|
+
* Observed at 28m51s against an empty fleet during the same incident.
|
|
128
|
+
*
|
|
129
|
+
* Why this is worth its own verdict rather than folding into `real-failure`:
|
|
130
|
+
* the whole point of this tool is that "red" and "your code is broken" are
|
|
131
|
+
* different claims. It cost three separate diagnoses in one session — a hunt
|
|
132
|
+
* for a secret in a file that had none, a hunt for a closing-keyword problem
|
|
133
|
+
* in a PR body that had none, and a hunt for a bug in a `*_pg.py` test that
|
|
134
|
+
* had never executed. The signature is one API call away in every case.
|
|
135
|
+
*
|
|
136
|
+
* Deliberately narrow. A job whose FIRST step failed but which has later steps
|
|
137
|
+
* is a normal failure — only a job that never got past setup counts, so a gate
|
|
138
|
+
* that legitimately fails fast is not laundered into an infrastructure excuse.
|
|
139
|
+
*
|
|
140
|
+
* @param {Array<{ conclusion?: string, steps?: Array<{ name?: string, conclusion?: string }>, runner_name?: string | null }> | null | undefined} jobs
|
|
141
|
+
* @returns {boolean}
|
|
142
|
+
*/
|
|
143
|
+
export function neverRan(jobs) {
|
|
144
|
+
const stalled = (jobs ?? []).filter(
|
|
145
|
+
(job) => job.conclusion === 'failure' || job.conclusion === 'cancelled'
|
|
146
|
+
)
|
|
147
|
+
if (stalled.length === 0) return false
|
|
148
|
+
return stalled.every((job) => {
|
|
149
|
+
const steps = job.steps ?? []
|
|
150
|
+
// Never scheduled: cancelled with nothing to show for it.
|
|
151
|
+
if (steps.length === 0) return job.conclusion === 'cancelled'
|
|
152
|
+
// Died in setup: `Set up job` is the only step, and it failed.
|
|
153
|
+
return (
|
|
154
|
+
steps.length === 1 &&
|
|
155
|
+
steps[0]?.name === 'Set up job' &&
|
|
156
|
+
steps[0]?.conclusion === 'failure'
|
|
157
|
+
)
|
|
158
|
+
})
|
|
105
159
|
}
|
|
106
160
|
|
|
107
161
|
/**
|
|
@@ -187,6 +241,10 @@ export function evictionKilledJob(job, evictedAt) {
|
|
|
187
241
|
* @returns {{ verdict: string, jobs: Array<{ name: string, instance: string | null, verdict: string, evictedAt: string | null }> }}
|
|
188
242
|
*/
|
|
189
243
|
export function adjudicateRun(jobs, evictions) {
|
|
244
|
+
// Asked BEFORE `isRunnerKill`, which answers "did a runner die mid-job?" — a
|
|
245
|
+
// job that never started cannot have, so it would otherwise fall straight
|
|
246
|
+
// through to `real-failure` and send someone to read code that never ran.
|
|
247
|
+
if (neverRan(jobs)) return { verdict: VERDICT.NEVER_RAN, jobs: [] }
|
|
190
248
|
if (!isRunnerKill(jobs)) return { verdict: VERDICT.REAL_FAILURE, jobs: [] }
|
|
191
249
|
|
|
192
250
|
const lost = (jobs ?? []).filter((job) => job.conclusion === 'failure')
|
|
@@ -334,6 +392,10 @@ function main() {
|
|
|
334
392
|
// because **2 is never a pass** here as everywhere else. "The runner died for
|
|
335
393
|
// reasons unknown" must not read as "safe to re-run and move on"; that is the
|
|
336
394
|
// fail-open this whole tool exists to close.
|
|
395
|
+
if (result.verdict === VERDICT.NEVER_RAN) {
|
|
396
|
+
console.log(' the job never started — GitHub could not schedule or set it up. Re-run it.')
|
|
397
|
+
process.exit(0)
|
|
398
|
+
}
|
|
337
399
|
if (result.verdict === VERDICT.REAL_FAILURE) process.exit(1)
|
|
338
400
|
if (result.verdict === VERDICT.SPOT_RECLAIMED) process.exit(0)
|
|
339
401
|
process.exit(2)
|