@bongos/core 1.21.104 → 1.21.105
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/.bongos-core.json +14 -14
- package/docs/module-api-changelog.md +2 -0
- package/modules/lifecycle/check-rollup.js +11 -1
- package/modules/lifecycle/github-push.js +3 -7
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +6 -0
- package/scripts/gds/ship-land.js +2 -2
- package/src/module-api.js +1 -1
- package/tests/github_push_merge_driver.mjs +46 -0
package/.bongos-core.json
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.21.
|
|
6
|
-
"core_contract": "1.21.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.21.105",
|
|
6
|
+
"core_contract": "1.21.105",
|
|
7
|
+
"source_commit": "12969410e588a86536f6426de5dcd95390b3be6b",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-10-
|
|
9
|
+
"built_at": "2026-10-09T14:04:06.264Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 592,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
19
|
"file_count": 3642,
|
|
20
|
-
"tree_sha256": "
|
|
20
|
+
"tree_sha256": "10dd1c422b8f42c90e7521862acb305b14d72053ddbe6c75511033ab149b694b",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -2872,7 +2872,7 @@
|
|
|
2872
2872
|
{
|
|
2873
2873
|
"path": "docs/module-api-changelog.md",
|
|
2874
2874
|
"mode": "0000644",
|
|
2875
|
-
"sha256": "
|
|
2875
|
+
"sha256": "9e09c3f6c9d01b93d3a0857d2115578a4e2268491278f11656efcf499c20b766"
|
|
2876
2876
|
},
|
|
2877
2877
|
{
|
|
2878
2878
|
"path": "docs/modules-contract.md",
|
|
@@ -6832,7 +6832,7 @@
|
|
|
6832
6832
|
{
|
|
6833
6833
|
"path": "modules/lifecycle/check-rollup.js",
|
|
6834
6834
|
"mode": "0000644",
|
|
6835
|
-
"sha256": "
|
|
6835
|
+
"sha256": "9109d29e5fc6739419c6584d4be2990516c2736c398ed8e3b916bb8b4627e0bb"
|
|
6836
6836
|
},
|
|
6837
6837
|
{
|
|
6838
6838
|
"path": "modules/lifecycle/claim-eligibility.js",
|
|
@@ -6992,7 +6992,7 @@
|
|
|
6992
6992
|
{
|
|
6993
6993
|
"path": "modules/lifecycle/github-push.js",
|
|
6994
6994
|
"mode": "0000644",
|
|
6995
|
-
"sha256": "
|
|
6995
|
+
"sha256": "65386fff8736c1b55c1f105c595758161e718352077603d1ba9aa7dd05d6d1d6"
|
|
6996
6996
|
},
|
|
6997
6997
|
{
|
|
6998
6998
|
"path": "modules/lifecycle/goal-advisory.js",
|
|
@@ -10137,12 +10137,12 @@
|
|
|
10137
10137
|
{
|
|
10138
10138
|
"path": "package-lock.json",
|
|
10139
10139
|
"mode": "0000644",
|
|
10140
|
-
"sha256": "
|
|
10140
|
+
"sha256": "967618b349cf51650bbb10bb29c9304205ce8b84b0a61b0f26a84ff6b65751e8"
|
|
10141
10141
|
},
|
|
10142
10142
|
{
|
|
10143
10143
|
"path": "package.json",
|
|
10144
10144
|
"mode": "0000644",
|
|
10145
|
-
"sha256": "
|
|
10145
|
+
"sha256": "6312c6a7441ab5c39cb567c6272d4a753edf0e2896a53b6cbb83e8c0713866d9"
|
|
10146
10146
|
},
|
|
10147
10147
|
{
|
|
10148
10148
|
"path": "public-docs/index.html",
|
|
@@ -10162,7 +10162,7 @@
|
|
|
10162
10162
|
{
|
|
10163
10163
|
"path": "release-notes.json",
|
|
10164
10164
|
"mode": "0000644",
|
|
10165
|
-
"sha256": "
|
|
10165
|
+
"sha256": "7a99e0dae60fe796637cc0190ef51e49b0ff707b1a193bdab8b7f9444b953134"
|
|
10166
10166
|
},
|
|
10167
10167
|
{
|
|
10168
10168
|
"path": "scripts/cron/style_guide_audit.sh",
|
|
@@ -11672,7 +11672,7 @@
|
|
|
11672
11672
|
{
|
|
11673
11673
|
"path": "scripts/gds/ship-land.js",
|
|
11674
11674
|
"mode": "0000644",
|
|
11675
|
-
"sha256": "
|
|
11675
|
+
"sha256": "0b60f062ccf052a0eecb71fff3e0abf3c75cb2399786a286ab54df4091fff787"
|
|
11676
11676
|
},
|
|
11677
11677
|
{
|
|
11678
11678
|
"path": "scripts/gds/ship-memory-sync.js",
|
|
@@ -12437,7 +12437,7 @@
|
|
|
12437
12437
|
{
|
|
12438
12438
|
"path": "src/module-api.js",
|
|
12439
12439
|
"mode": "0000644",
|
|
12440
|
-
"sha256": "
|
|
12440
|
+
"sha256": "9f15b0adaa8dea1358b3c6d154c7ff2b378ce4bb7c8ba23c21f611861836aa11"
|
|
12441
12441
|
},
|
|
12442
12442
|
{
|
|
12443
12443
|
"path": "src/module-loader/catalog.js",
|
|
@@ -14092,7 +14092,7 @@
|
|
|
14092
14092
|
{
|
|
14093
14093
|
"path": "tests/github_push_merge_driver.mjs",
|
|
14094
14094
|
"mode": "0000644",
|
|
14095
|
-
"sha256": "
|
|
14095
|
+
"sha256": "5bf4d9ab391f0e457ec11b47197dd812487098d120f8fbba87dbddf7e23e92b9"
|
|
14096
14096
|
},
|
|
14097
14097
|
{
|
|
14098
14098
|
"path": "tests/github_push_stderr_truncation.mjs",
|
|
@@ -3045,5 +3045,7 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
3045
3045
|
landed since 1.21.102 with no explicit bump. run 37936846665. (task 1002620)
|
|
3046
3046
|
1.21.104 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3047
3047
|
landed since 1.21.103 with no explicit bump. run 37939497390. (task 1002620)
|
|
3048
|
+
1.21.105 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
3049
|
+
landed since 1.21.104 with no explicit bump. run 37941330141. (task 1002620)
|
|
3048
3050
|
---------------------------------------------------------------------------
|
|
3049
3051
|
```
|
|
@@ -39,4 +39,14 @@ function readCheckRollup(rollup) {
|
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
// The conclusions that mean a check really FAILED (task 1004666). One set for both
|
|
43
|
+
// readers: the laptop's ship-land.js (task 1003764) and the server's mergeBlockReason.
|
|
44
|
+
// readCheckRollup maps a status context's state into `conclusion`, so PENDING and
|
|
45
|
+
// EXPECTED (posted but unfinished, or required but not yet reported) land there too —
|
|
46
|
+
// those are waiting, not red. The server reader used to count anything outside
|
|
47
|
+
// SUCCESS/NEUTRAL/SKIPPED as failing, which named a still-running check as the reason
|
|
48
|
+
// a PR was red and sent the publish reconciler after a regen-heal it did not need.
|
|
49
|
+
const RED_CONCLUSIONS = new Set(['FAILURE', 'ERROR', 'TIMED_OUT', 'CANCELLED', 'ACTION_REQUIRED', 'STARTUP_FAILURE']);
|
|
50
|
+
const isRedCheck = (c) => !!c && RED_CONCLUSIONS.has(String(c.conclusion || '').toUpperCase());
|
|
51
|
+
|
|
52
|
+
module.exports = { readCheckRollup, UNIT_REPORT_CONTEXT, RED_CONCLUSIONS, isRedCheck };
|
|
@@ -40,7 +40,7 @@ const os = require('node:os');
|
|
|
40
40
|
const path = require('node:path');
|
|
41
41
|
const { promisify } = require('node:util');
|
|
42
42
|
const { repoInfo, userAgent } = require('../../src/module-api');
|
|
43
|
-
const { readCheckRollup, UNIT_REPORT_CONTEXT } = require('./check-rollup');
|
|
43
|
+
const { readCheckRollup, UNIT_REPORT_CONTEXT, isRedCheck } = require('./check-rollup'); // isRedCheck: only a FAILED check is red, never a pending one (task 1004666)
|
|
44
44
|
const { loadRepoInfo } = repoInfo;
|
|
45
45
|
|
|
46
46
|
const execFileP = promisify(execFile);
|
|
@@ -951,10 +951,6 @@ async function getMergeState({ branch }, deps = {}) {
|
|
|
951
951
|
};
|
|
952
952
|
}
|
|
953
953
|
|
|
954
|
-
// A non-passing check conclusion (everything that isn't a clean success/skip).
|
|
955
|
-
const _BAD_CHECK = (c) =>
|
|
956
|
-
c.conclusion && !['SUCCESS', 'NEUTRAL', 'SKIPPED'].includes(String(c.conclusion).toUpperCase());
|
|
957
|
-
|
|
958
954
|
// Human-readable reason a not-yet-merged PR isn't mergeable, surfaced to a
|
|
959
955
|
// credential-less session so it reports the truth instead of guessing.
|
|
960
956
|
function mergeBlockReason(s) {
|
|
@@ -967,7 +963,7 @@ function mergeBlockReason(s) {
|
|
|
967
963
|
if (s.review_decision === 'CHANGES_REQUESTED') return 'changes_requested';
|
|
968
964
|
if (s.review_decision === 'REVIEW_REQUIRED') return 'review_required';
|
|
969
965
|
if (s.merge_state === 'BLOCKED') {
|
|
970
|
-
const bad = s.checks.filter(
|
|
966
|
+
const bad = s.checks.filter(isRedCheck);
|
|
971
967
|
if (bad.length) return `failing_check:${bad[0].name}`;
|
|
972
968
|
// Red, and the failing check is one of the nulled nodes: say the list is blind
|
|
973
969
|
// rather than guess "review or pending", which sent a ship retrying (task 1003988).
|
|
@@ -975,7 +971,7 @@ function mergeBlockReason(s) {
|
|
|
975
971
|
return 'blocked_required_review_or_pending_check';
|
|
976
972
|
}
|
|
977
973
|
if (s.merge_state === 'UNSTABLE') {
|
|
978
|
-
const bad = s.checks.filter(
|
|
974
|
+
const bad = s.checks.filter(isRedCheck);
|
|
979
975
|
return bad.length ? `non_required_check_failing:${bad[0].name}` : 'non_required_check_pending';
|
|
980
976
|
}
|
|
981
977
|
if (s.mergeable === 'UNKNOWN' || s.merge_state === 'UNKNOWN' || s.merge_state == null) {
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.105",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.21.
|
|
9
|
+
"version": "1.21.105",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.105",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
package/release-notes.json
CHANGED
|
@@ -9470,5 +9470,11 @@
|
|
|
9470
9470
|
"id": "1004665",
|
|
9471
9471
|
"text": "When a builder re-runs a review and attaches a screenshot, the screenshot now actually gets attached to the task. Before, it was quietly thrown away, so reviewers asking for a picture never saw one unless someone added it by h"
|
|
9472
9472
|
}
|
|
9473
|
+
],
|
|
9474
|
+
"1.21.105": [
|
|
9475
|
+
{
|
|
9476
|
+
"id": "1004666",
|
|
9477
|
+
"text": "A check that is still running is no longer reported as a failed one. Before, a project whose test service posts a \"still working\" status would see its change called broken and trigger a pointless repair attempt; now it is corr"
|
|
9478
|
+
}
|
|
9473
9479
|
]
|
|
9474
9480
|
}
|
package/scripts/gds/ship-land.js
CHANGED
|
@@ -18,7 +18,7 @@ const { normalizeApiError } = require('./ship-io.js');
|
|
|
18
18
|
const { plainCardLines } = require('./plain-cards.js');
|
|
19
19
|
// The server's own reader of a PR's check rollup (task 1003988), reused so the laptop
|
|
20
20
|
// poll names a red PR exactly the way publish-status does (task 1003764). Dependency-free.
|
|
21
|
-
const { readCheckRollup, UNIT_REPORT_CONTEXT } = require('../../modules/lifecycle/check-rollup.js');
|
|
21
|
+
const { readCheckRollup, UNIT_REPORT_CONTEXT, RED_CONCLUSIONS } = require('../../modules/lifecycle/check-rollup.js');
|
|
22
22
|
const { prMergeSentence } = require('../../modules/lifecycle/page-tweak-hold.js');
|
|
23
23
|
|
|
24
24
|
// ---------- the land outcome (task 1002541, part 1) ----------
|
|
@@ -474,7 +474,7 @@ function redBlocksMerge(md) {
|
|
|
474
474
|
// A check conclusion (CheckRun) or state (status context) that means FAILED. Pending and
|
|
475
475
|
// expected are waiting, not red — reporting them as failures would be the mirror image of
|
|
476
476
|
// the bug this names (a failure dressed as waiting).
|
|
477
|
-
|
|
477
|
+
// The set itself lives in check-rollup.js, shared with the server's mergeBlockReason (task 1004666).
|
|
478
478
|
|
|
479
479
|
// localMergeDriver — task 1003764. The laptop path watches its PR with the builder's own
|
|
480
480
|
// gh, and read only state + mergeCommit, so a red required check was invisible for the
|
package/src/module-api.js
CHANGED
|
@@ -75,7 +75,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
|
|
|
75
75
|
// MAJOR (see allowBoxScope below): passes the request through untouched.
|
|
76
76
|
function deprecatedNoopMiddleware(_req, _res, next) { next(); }
|
|
77
77
|
|
|
78
|
-
const CORE_VERSION = '1.21.
|
|
78
|
+
const CORE_VERSION = '1.21.105'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
79
79
|
|
|
80
80
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
81
81
|
// Usage: const log = api.logger('discord'); log.info('mounted');
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import { strict as assert } from 'node:assert';
|
|
14
14
|
import { createRequire } from 'node:module';
|
|
15
|
+
import fs from 'node:fs';
|
|
15
16
|
|
|
16
17
|
const require = createRequire(import.meta.url);
|
|
17
18
|
const gh = require('../modules/lifecycle/github-push.js');
|
|
@@ -169,6 +170,51 @@ test('mergeBlockReason maps the common blocker states', () => {
|
|
|
169
170
|
assert.equal(gh.mergeBlockReason({ ...open, merged: true }), null);
|
|
170
171
|
});
|
|
171
172
|
|
|
173
|
+
// --- task 1004666: a check still running is waiting, not red --------------
|
|
174
|
+
//
|
|
175
|
+
// check-rollup maps a status context's state into `conclusion`, so PENDING and
|
|
176
|
+
// EXPECTED (posted but unfinished, or required but not yet reported) reached
|
|
177
|
+
// mergeBlockReason as conclusions. It counted anything outside SUCCESS/NEUTRAL/
|
|
178
|
+
// SKIPPED as failing, so a BLOCKED PR waiting on a third-party status read
|
|
179
|
+
// "failing_check:<context>" and the reconciler tried a regen-heal on it.
|
|
180
|
+
|
|
181
|
+
const ctx = (context, state) => ({ __typename: 'StatusContext', context, state, description: null });
|
|
182
|
+
|
|
183
|
+
test('1004666 a PENDING or EXPECTED status context on a BLOCKED PR reads as waiting', async () => {
|
|
184
|
+
for (const state of ['PENDING', 'EXPECTED']) {
|
|
185
|
+
const { fetchImpl } = mkFetch({ node: prNode({ mergeStateStatus: 'BLOCKED', rollup: 'PENDING', checks: [TRUST, ctx('ci/external', state)] }) });
|
|
186
|
+
const r = await gh.mergeIfGreen({ branch: 'claude/wt' }, DEPS(fetchImpl));
|
|
187
|
+
assert.equal(r.reason, 'blocked_required_review_or_pending_check', `${state} is not a failure`);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('1004666 on an UNSTABLE PR a pending optional check is pending, not failing', () => {
|
|
192
|
+
const open = { pr_state: 'open', merged: false };
|
|
193
|
+
assert.equal(gh.mergeBlockReason({ ...open, merge_state: 'UNSTABLE', checks: [{ name: 'e2e', conclusion: 'PENDING' }] }), 'non_required_check_pending');
|
|
194
|
+
assert.equal(gh.mergeBlockReason({ ...open, merge_state: 'UNSTABLE', checks: [{ name: 'e2e', conclusion: 'TIMED_OUT' }] }), 'non_required_check_failing:e2e');
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test('1004666 every red conclusion still names its check, past a pending one', () => {
|
|
198
|
+
for (const state of ['FAILURE', 'ERROR', 'TIMED_OUT', 'CANCELLED', 'ACTION_REQUIRED', 'STARTUP_FAILURE']) {
|
|
199
|
+
const open = { pr_state: 'open', merged: false, merge_state: 'BLOCKED' };
|
|
200
|
+
assert.equal(gh.mergeBlockReason({ ...open, checks: [{ name: 'ci/external', conclusion: 'PENDING' }, { name: 'unit', conclusion: state }] }), 'failing_check:unit', state);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test('1004666 the server and the laptop read red from ONE set', () => {
|
|
205
|
+
const rollup = require('../modules/lifecycle/check-rollup.js');
|
|
206
|
+
const land = fs.readFileSync(new URL('../scripts/gds/ship-land.js', import.meta.url), 'utf8');
|
|
207
|
+
const push = fs.readFileSync(new URL('../modules/lifecycle/github-push.js', import.meta.url), 'utf8');
|
|
208
|
+
assert.ok(land.includes("RED_CONCLUSIONS } = require('../../modules/lifecycle/check-rollup.js')"), 'ship-land imports the shared set');
|
|
209
|
+
assert.doesNotMatch(land, /const RED_CONCLUSIONS\s*=/, 'and no longer declares its own');
|
|
210
|
+
assert.doesNotMatch(push, /_BAD_CHECK|'SUCCESS', 'NEUTRAL', 'SKIPPED'/, 'the old allow-list reading is gone');
|
|
211
|
+
for (const c of ['PENDING', 'EXPECTED', 'SUCCESS', 'NEUTRAL', 'SKIPPED', 'STALE', null, undefined]) {
|
|
212
|
+
assert.equal(rollup.isRedCheck({ conclusion: c }), false, String(c));
|
|
213
|
+
}
|
|
214
|
+
assert.equal(rollup.isRedCheck({ conclusion: 'failure' }), true, 'case-insensitive like the old reader');
|
|
215
|
+
assert.equal(rollup.isRedCheck(null), false);
|
|
216
|
+
});
|
|
217
|
+
|
|
172
218
|
// --- task 1003988: a red PR names what failed, or says it cannot see -------
|
|
173
219
|
//
|
|
174
220
|
// Without Checks:read GitHub nulls every CheckRun node and keeps the rollup state,
|