@mmnto/cli 2.2.0 → 2.3.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.
- package/dist/commands/config-drift.test.js +4 -1
- package/dist/commands/config-drift.test.js.map +1 -1
- package/dist/commands/gate-install.d.ts +35 -0
- package/dist/commands/gate-install.d.ts.map +1 -1
- package/dist/commands/gate-install.js +48 -0
- package/dist/commands/gate-install.js.map +1 -1
- package/dist/commands/gate-install.test.js +638 -9
- package/dist/commands/gate-install.test.js.map +1 -1
- package/dist/commands/gate.d.ts +9 -0
- package/dist/commands/gate.d.ts.map +1 -1
- package/dist/commands/gate.js +37 -2
- package/dist/commands/gate.js.map +1 -1
- package/dist/commands/gate.test.js +42 -1
- package/dist/commands/gate.test.js.map +1 -1
- package/dist/commands/init-templates.d.ts +8 -8
- package/dist/commands/init-templates.d.ts.map +1 -1
- package/dist/commands/init-templates.js +866 -94
- package/dist/commands/init-templates.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +22 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/init.test.js +132 -0
- package/dist/commands/init.test.js.map +1 -1
- package/dist/commands/mail-cli-wiring.test.js +58 -2
- package/dist/commands/mail-cli-wiring.test.js.map +1 -1
- package/dist/commands/mail-derive-seat.test.d.ts +28 -0
- package/dist/commands/mail-derive-seat.test.d.ts.map +1 -0
- package/dist/commands/mail-derive-seat.test.js +557 -0
- package/dist/commands/mail-derive-seat.test.js.map +1 -0
- package/dist/commands/mail.d.ts +112 -0
- package/dist/commands/mail.d.ts.map +1 -1
- package/dist/commands/mail.js +189 -0
- package/dist/commands/mail.js.map +1 -1
- package/dist/commands/resolve-threads-cli-wiring.test.d.ts +19 -0
- package/dist/commands/resolve-threads-cli-wiring.test.d.ts.map +1 -0
- package/dist/commands/resolve-threads-cli-wiring.test.js +103 -0
- package/dist/commands/resolve-threads-cli-wiring.test.js.map +1 -0
- package/dist/commands/resolve-threads.d.ts +468 -0
- package/dist/commands/resolve-threads.d.ts.map +1 -0
- package/dist/commands/resolve-threads.js +794 -0
- package/dist/commands/resolve-threads.js.map +1 -0
- package/dist/commands/resolve-threads.test.d.ts +2 -0
- package/dist/commands/resolve-threads.test.d.ts.map +1 -0
- package/dist/commands/resolve-threads.test.js +1121 -0
- package/dist/commands/resolve-threads.test.js.map +1 -0
- package/dist/commands/session-context-journal-select.test.d.ts +2 -0
- package/dist/commands/session-context-journal-select.test.d.ts.map +1 -0
- package/dist/commands/session-context-journal-select.test.js +95 -0
- package/dist/commands/session-context-journal-select.test.js.map +1 -0
- package/dist/commands/sync-labels-forms.test.d.ts +36 -0
- package/dist/commands/sync-labels-forms.test.d.ts.map +1 -0
- package/dist/commands/sync-labels-forms.test.js +573 -0
- package/dist/commands/sync-labels-forms.test.js.map +1 -0
- package/dist/index.js +74 -5
- package/dist/index.js.map +1 -1
- package/dist/parsers/bot-identity-parity.test.d.ts +2 -0
- package/dist/parsers/bot-identity-parity.test.d.ts.map +1 -0
- package/dist/parsers/bot-identity-parity.test.js +175 -0
- package/dist/parsers/bot-identity-parity.test.js.map +1 -0
- package/dist/parsers/bot-review-parser.d.ts +8 -5
- package/dist/parsers/bot-review-parser.d.ts.map +1 -1
- package/dist/parsers/bot-review-parser.js +12 -34
- package/dist/parsers/bot-review-parser.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The issue-form ↔ label-canon coupling, and the `-WhatIf` dry run of
|
|
3
|
+
* `scripts/sync-labels.ps1` (mmnto-ai/totem#2792).
|
|
4
|
+
*
|
|
5
|
+
* Two contracts are locked here, both DERIVED from the real script rather than
|
|
6
|
+
* mirrored (Tenet 20 — the same discipline `parity-label-canon.test.ts` applies
|
|
7
|
+
* to the canon itself):
|
|
8
|
+
*
|
|
9
|
+
* 1. Every `.github/ISSUE_TEMPLATE/*.yml` form parses and applies exactly its
|
|
10
|
+
* own `type: <basename>` label, a name the script defines. A space-less
|
|
11
|
+
* `type:bug` would leave the canon's type label missing on every issue the
|
|
12
|
+
* form creates (whether GitHub drops the unknown label or mints a stray
|
|
13
|
+
* one); here it fails the suite instead.
|
|
14
|
+
* 2. Every form's `Tier` and `Scope` dropdowns offer exactly the canon's
|
|
15
|
+
* `tier-*` names and its `scope: ` names with the namespace stripped. Both
|
|
16
|
+
* option sets are computed from the parsed script — never hand-listed — so
|
|
17
|
+
* a new scope in the script is a failing test until the forms carry it.
|
|
18
|
+
* The scope derivation reads ONLY names starting with `scope: `, so the
|
|
19
|
+
* `disposition: ` namespace can never leak into the dropdown.
|
|
20
|
+
*
|
|
21
|
+
* The remaining cases spawn `pwsh` against the real script. The first proves the
|
|
22
|
+
* `-WhatIf` shadow prints every `gh` call and executes none (a stub `gh` sits on
|
|
23
|
+
* PATH and must stay untouched); the second proves the shadow does NOT leak into
|
|
24
|
+
* a normal run — the same stub, no `-WhatIf`, must receive the whole canon; the
|
|
25
|
+
* rest drive the stub's failure modes (a refused `label edit`, a refused
|
|
26
|
+
* `issue edit`, a failed `issue list`) to pin the mutation tally and the gated
|
|
27
|
+
* delete in `Merge-Label` (mmnto-ai/totem#2837). Every one runs against
|
|
28
|
+
* `-Repo example/stub`; none can reach GitHub, because `gh` on the child's PATH
|
|
29
|
+
* is a log-appending stub.
|
|
30
|
+
*
|
|
31
|
+
* Every case skips when the repo-root files are absent (a packaged install
|
|
32
|
+
* carries neither the script nor `.github/`), and the spawning ones skip when
|
|
33
|
+
* `pwsh` is not on PATH.
|
|
34
|
+
*/
|
|
35
|
+
import { spawnSync } from 'node:child_process';
|
|
36
|
+
import * as fs from 'node:fs';
|
|
37
|
+
import * as os from 'node:os';
|
|
38
|
+
import * as path from 'node:path';
|
|
39
|
+
import { fileURLToPath } from 'node:url';
|
|
40
|
+
import { describe, expect, it } from 'vitest';
|
|
41
|
+
import { parse as parseYaml } from 'yaml';
|
|
42
|
+
import { normalizeLabelColor, parseLabelCanon } from '@mmnto/totem';
|
|
43
|
+
/** packages/cli/src/commands → the repo root. */
|
|
44
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', '..');
|
|
45
|
+
const SCRIPT_PATH = path.join(ROOT, 'scripts', 'sync-labels.ps1');
|
|
46
|
+
const TEMPLATE_DIR = path.join(ROOT, '.github', 'ISSUE_TEMPLATE');
|
|
47
|
+
const CONFIG_PATH = path.join(TEMPLATE_DIR, 'config.yml');
|
|
48
|
+
const ONBOARDING_PATH = path.join(TEMPLATE_DIR, 'onboarding.md');
|
|
49
|
+
const REPO_FILES_PRESENT = fs.existsSync(SCRIPT_PATH) && fs.existsSync(TEMPLATE_DIR);
|
|
50
|
+
/** `pwsh` on PATH and runnable — absent on a minimal container, present on every GitHub runner. */
|
|
51
|
+
function pwshRunnable() {
|
|
52
|
+
const probe = spawnSync('pwsh', ['-NoProfile', '-Command', 'exit 0'], { encoding: 'utf8' });
|
|
53
|
+
return probe.error === undefined && probe.status === 0;
|
|
54
|
+
}
|
|
55
|
+
const PWSH_PRESENT = REPO_FILES_PRESENT && pwshRunnable();
|
|
56
|
+
/** The form files, `config.yml` excluded (it is not a form). */
|
|
57
|
+
function formFiles() {
|
|
58
|
+
return fs
|
|
59
|
+
.readdirSync(TEMPLATE_DIR)
|
|
60
|
+
.filter((file) => file.endsWith('.yml') && file !== 'config.yml')
|
|
61
|
+
.sort();
|
|
62
|
+
}
|
|
63
|
+
function readForm(file) {
|
|
64
|
+
return parseYaml(fs.readFileSync(path.join(TEMPLATE_DIR, file), 'utf8'));
|
|
65
|
+
}
|
|
66
|
+
/** The canon of record, parsed from the real script exactly as the sensor parses it. */
|
|
67
|
+
function realCanon() {
|
|
68
|
+
return parseLabelCanon(fs.readFileSync(SCRIPT_PATH, 'utf8'));
|
|
69
|
+
}
|
|
70
|
+
/** The `tier-*` canonical names — the Tier dropdown's option set, derived. */
|
|
71
|
+
function tierOptionsFromCanon(names) {
|
|
72
|
+
return names.filter((name) => name.startsWith('tier-')).sort();
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The `scope: ` canonical names with the namespace stripped — the Scope
|
|
76
|
+
* dropdown's option set, derived. The `scope: ` prefix is the ONLY source, so a
|
|
77
|
+
* `disposition: ` (or any other namespace) entry can never enter this set.
|
|
78
|
+
*/
|
|
79
|
+
function scopeOptionsFromCanon(names) {
|
|
80
|
+
const prefix = 'scope: ';
|
|
81
|
+
return names
|
|
82
|
+
.filter((name) => name.startsWith(prefix))
|
|
83
|
+
.map((name) => name.slice(prefix.length))
|
|
84
|
+
.sort();
|
|
85
|
+
}
|
|
86
|
+
/** The one dropdown in `form.body` whose rendered label is `label`. */
|
|
87
|
+
function dropdownByLabel(form, label) {
|
|
88
|
+
return (form.body ?? []).find((field) => field.type === 'dropdown' && field.attributes?.label === label);
|
|
89
|
+
}
|
|
90
|
+
// ─── Forms ↔ canon ───────────────────────────────────────
|
|
91
|
+
describe.skipIf(!REPO_FILES_PRESENT)('issue forms', () => {
|
|
92
|
+
it('ships one form per canonical type, each parsing as YAML with a name and a description', () => {
|
|
93
|
+
const files = formFiles();
|
|
94
|
+
expect(files).toEqual([
|
|
95
|
+
'bug.yml',
|
|
96
|
+
'chore.yml',
|
|
97
|
+
'docs.yml',
|
|
98
|
+
'epic.yml',
|
|
99
|
+
'feature.yml',
|
|
100
|
+
'security.yml',
|
|
101
|
+
]);
|
|
102
|
+
for (const file of files) {
|
|
103
|
+
const form = readForm(file);
|
|
104
|
+
expect(typeof form.name, file).toBe('string');
|
|
105
|
+
expect(typeof form.description, file).toBe('string');
|
|
106
|
+
expect(Array.isArray(form.body), file).toBe(true);
|
|
107
|
+
// Titles stay free-form — no `title:` prefix is imposed on the author.
|
|
108
|
+
expect(Object.keys(form), file).not.toContain('title');
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
it('applies exactly its own type: label, one the script defines (the space in `type: bug` is load-bearing)', () => {
|
|
112
|
+
const canonNames = new Set(realCanon().labels.map((label) => label.name));
|
|
113
|
+
// The canon must be non-empty, or this assertion would pass vacuously the
|
|
114
|
+
// moment the script's grammar changed (the readers' own empty-canon refusal).
|
|
115
|
+
expect(canonNames.size).toBeGreaterThan(0);
|
|
116
|
+
for (const file of formFiles()) {
|
|
117
|
+
const form = readForm(file);
|
|
118
|
+
// Charter § 4c(ii): one template per `type:` value, applying THAT label —
|
|
119
|
+
// derived from the filename, so `docs.yml` cannot ship `type: bug`, an
|
|
120
|
+
// empty list, or two type labels and still pass.
|
|
121
|
+
const expected = `type: ${file.replace(/\.yml$/, '')}`;
|
|
122
|
+
expect(form.labels, file).toEqual([expected]);
|
|
123
|
+
expect(canonNames.has(expected), `${file} applies ${expected}`).toBe(true);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
it("carries a required Tier dropdown whose options are the canon's tier-* names", () => {
|
|
127
|
+
const expected = tierOptionsFromCanon(realCanon().labels.map((label) => label.name));
|
|
128
|
+
expect(expected.length).toBeGreaterThan(0);
|
|
129
|
+
for (const file of formFiles()) {
|
|
130
|
+
const form = readForm(file);
|
|
131
|
+
const tier = dropdownByLabel(form, 'Tier');
|
|
132
|
+
expect(tier, `${file} has a Tier dropdown`).toBeDefined();
|
|
133
|
+
// The id and the label are BOTH a contract with the rung-1 body sensor.
|
|
134
|
+
expect(tier?.id, file).toBe('tier');
|
|
135
|
+
expect(tier?.validations?.required, file).toBe(true);
|
|
136
|
+
expect([...(tier?.attributes?.options ?? [])].sort(), file).toEqual(expected);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
it("carries a required multi-select Scope dropdown whose options are the canon's scope: names, namespace stripped", () => {
|
|
140
|
+
const expected = scopeOptionsFromCanon(realCanon().labels.map((label) => label.name));
|
|
141
|
+
expect(expected.length).toBeGreaterThan(0);
|
|
142
|
+
// Derived from `scope: ` alone — never "every label that is not a tier".
|
|
143
|
+
expect(expected.some((option) => option.includes('disposition'))).toBe(false);
|
|
144
|
+
for (const file of formFiles()) {
|
|
145
|
+
const form = readForm(file);
|
|
146
|
+
const scope = dropdownByLabel(form, 'Scope');
|
|
147
|
+
expect(scope, `${file} has a Scope dropdown`).toBeDefined();
|
|
148
|
+
expect(scope?.id, file).toBe('scope');
|
|
149
|
+
expect(scope?.attributes?.multiple, file).toBe(true);
|
|
150
|
+
expect(scope?.validations?.required, file).toBe(true);
|
|
151
|
+
expect([...(scope?.attributes?.options ?? [])].sort(), file).toEqual(expected);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
it('renders every field under a distinct heading (the body sensor keys on heading text, never on ids)', () => {
|
|
155
|
+
// The epic form once carried a `Scope` textarea beside the `Scope` dropdown:
|
|
156
|
+
// two `### Scope` headings in one rendered body, and a heading-keyed parser
|
|
157
|
+
// cannot tell them apart. Labels are the contract; ids never render.
|
|
158
|
+
for (const file of formFiles()) {
|
|
159
|
+
const form = readForm(file);
|
|
160
|
+
const labels = (form.body ?? [])
|
|
161
|
+
.map((field) => field.attributes?.label)
|
|
162
|
+
.filter((label) => typeof label === 'string');
|
|
163
|
+
expect(new Set(labels).size, `${file} field labels: ${labels.join(' | ')}`).toBe(labels.length);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
it('routes an exploitable vulnerability out of the public security form', () => {
|
|
167
|
+
const form = readForm('security.yml');
|
|
168
|
+
const first = (form.body ?? [])[0];
|
|
169
|
+
expect(first?.type).toBe('markdown');
|
|
170
|
+
expect(first?.attributes?.value ?? '').toMatch(/advisor/i);
|
|
171
|
+
});
|
|
172
|
+
it('disables blank issues and leaves the onboarding template in place', () => {
|
|
173
|
+
const config = parseYaml(fs.readFileSync(CONFIG_PATH, 'utf8'));
|
|
174
|
+
expect(config.blank_issues_enabled).toBe(false);
|
|
175
|
+
expect(fs.existsSync(ONBOARDING_PATH)).toBe(true);
|
|
176
|
+
// Untouched by mmnto-ai/totem#2792: still the front-matter markdown template it was.
|
|
177
|
+
expect(fs.readFileSync(ONBOARDING_PATH, 'utf8').startsWith('---')).toBe(true);
|
|
178
|
+
});
|
|
179
|
+
it("every canonical's create line carries exactly the colour and description of its edit twin", () => {
|
|
180
|
+
// The canon readers regex only the `edit` lines; the `create` twin is
|
|
181
|
+
// invisible to them, so a later change to one line of a pair would leave a
|
|
182
|
+
// fresh repository initialised with metadata the canon does not carry
|
|
183
|
+
// (Greptile P2 on mmnto-ai/totem#2839). Read from the script TEXT, not the
|
|
184
|
+
// rendered dry run, so a console code page cannot transliterate the compare.
|
|
185
|
+
const script = fs.readFileSync(SCRIPT_PATH, 'utf8');
|
|
186
|
+
const createRe = /gh label create "([^"]+)" --color "([^"]+)" --description "([^"]*)"/g;
|
|
187
|
+
const creates = new Map();
|
|
188
|
+
for (const match of script.matchAll(createRe)) {
|
|
189
|
+
creates.set(match[1], { color: normalizeLabelColor(match[2]), description: match[3] });
|
|
190
|
+
}
|
|
191
|
+
const canon = realCanon();
|
|
192
|
+
expect(canon.labels.length).toBeGreaterThan(0);
|
|
193
|
+
expect(creates.size).toBe(canon.labels.length);
|
|
194
|
+
for (const label of canon.labels) {
|
|
195
|
+
expect(creates.get(label.name), `create twin for ${label.name}`).toEqual({
|
|
196
|
+
color: normalizeLabelColor(label.color),
|
|
197
|
+
description: label.description,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
// ─── The pwsh dry run ────────────────────────────────────
|
|
203
|
+
/**
|
|
204
|
+
* A temp dir holding a `gh` stub that appends its whole argument line to a log
|
|
205
|
+
* and exits 0. Prepended to the child's PATH, it satisfies the script's `gh`
|
|
206
|
+
* presence check and its `gh auth status` preflight while making a real GitHub
|
|
207
|
+
* call impossible.
|
|
208
|
+
*/
|
|
209
|
+
function makeGhStub() {
|
|
210
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-gh-stub-'));
|
|
211
|
+
const logPath = path.join(dir, 'gh-calls.log');
|
|
212
|
+
// The stub logs every call and exits 0, with opt-in modes read from the
|
|
213
|
+
// child's environment. The script's two `issue list` reads differ only by
|
|
214
|
+
// their cap — `--limit 1000` migrates, `--limit 1 --json` rechecks — and the
|
|
215
|
+
// stub keys on that token so each read can be answered on its own:
|
|
216
|
+
// TOTEM_GH_STUB_ISSUES — the migration read answers with one
|
|
217
|
+
// issue, #7, so the merge phase relabels
|
|
218
|
+
// TOTEM_GH_STUB_ISSUES_REMAIN — the recheck read still answers #7 (an
|
|
219
|
+
// issue past the cap; Greptile P1 on
|
|
220
|
+
// mmnto-ai/totem#2839)
|
|
221
|
+
// TOTEM_GH_STUB_FAIL_ISSUE_LIST — `issue list` exits 1 (a failed READ)
|
|
222
|
+
// TOTEM_GH_STUB_FAIL_ISSUE_EDIT — `issue edit` exits 1 (a failed relabel —
|
|
223
|
+
// the totem-status incident, mmnto-ai/totem#2837)
|
|
224
|
+
// TOTEM_GH_STUB_FAIL_LABEL_DELETE — `label delete` exits 1
|
|
225
|
+
// TOTEM_GH_STUB_LABEL_PRESENT — `label list` answers non-empty (the
|
|
226
|
+
// deleted label is still there)
|
|
227
|
+
// TOTEM_GH_STUB_FAIL — `label edit` exits 1 — the failure path of
|
|
228
|
+
// the mutation tally (Greptile P1 on mmnto-ai/totem#2827)
|
|
229
|
+
if (process.platform === 'win32') {
|
|
230
|
+
fs.writeFileSync(path.join(dir, 'gh.cmd'), [
|
|
231
|
+
'@echo off',
|
|
232
|
+
`>>"${logPath}" echo %*`,
|
|
233
|
+
'if "%TOTEM_GH_STUB_ISSUES%"=="" goto :after_issues',
|
|
234
|
+
'echo %* | findstr /C:"--limit 1000" >nul',
|
|
235
|
+
'if %errorlevel%==0 echo 7',
|
|
236
|
+
':after_issues',
|
|
237
|
+
'if "%TOTEM_GH_STUB_ISSUES_REMAIN%"=="" goto :after_remain',
|
|
238
|
+
'echo %* | findstr /C:"--limit 1 --json" >nul',
|
|
239
|
+
'if %errorlevel%==0 echo 7',
|
|
240
|
+
':after_remain',
|
|
241
|
+
'if "%TOTEM_GH_STUB_LABEL_PRESENT%"=="" goto :after_present',
|
|
242
|
+
'echo %* | findstr /C:"label list" >nul',
|
|
243
|
+
'if %errorlevel%==0 echo present',
|
|
244
|
+
':after_present',
|
|
245
|
+
'if "%TOTEM_GH_STUB_FAIL_ISSUE_LIST%"=="" goto :after_list_fail',
|
|
246
|
+
'echo %* | findstr /C:"issue list" >nul',
|
|
247
|
+
'if %errorlevel%==0 exit /b 1',
|
|
248
|
+
':after_list_fail',
|
|
249
|
+
'if "%TOTEM_GH_STUB_FAIL_ISSUE_EDIT%"=="" goto :after_edit_fail',
|
|
250
|
+
'echo %* | findstr /C:"issue edit" >nul',
|
|
251
|
+
'if %errorlevel%==0 exit /b 1',
|
|
252
|
+
':after_edit_fail',
|
|
253
|
+
'if "%TOTEM_GH_STUB_FAIL_LABEL_DELETE%"=="" goto :after_delete_fail',
|
|
254
|
+
'echo %* | findstr /C:"label delete" >nul',
|
|
255
|
+
'if %errorlevel%==0 exit /b 1',
|
|
256
|
+
':after_delete_fail',
|
|
257
|
+
'if "%TOTEM_GH_STUB_FAIL%"=="" exit /b 0',
|
|
258
|
+
'echo %* | findstr /C:"label edit" >nul',
|
|
259
|
+
'if %errorlevel%==0 exit /b 1',
|
|
260
|
+
'exit /b 0',
|
|
261
|
+
'',
|
|
262
|
+
].join('\r\n'), 'utf8');
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
const stub = path.join(dir, 'gh');
|
|
266
|
+
fs.writeFileSync(stub, [
|
|
267
|
+
'#!/bin/sh',
|
|
268
|
+
`printf '%s\\n' "$*" >> "${logPath}"`,
|
|
269
|
+
'if [ -n "$TOTEM_GH_STUB_ISSUES" ]; then',
|
|
270
|
+
' case "$*" in *"--limit 1000"*) echo 7 ;; esac',
|
|
271
|
+
'fi',
|
|
272
|
+
'if [ -n "$TOTEM_GH_STUB_ISSUES_REMAIN" ]; then',
|
|
273
|
+
' case "$*" in *"--limit 1 --json"*) echo 7 ;; esac',
|
|
274
|
+
'fi',
|
|
275
|
+
'if [ -n "$TOTEM_GH_STUB_LABEL_PRESENT" ]; then',
|
|
276
|
+
' case "$*" in *"label list"*) echo present ;; esac',
|
|
277
|
+
'fi',
|
|
278
|
+
'if [ -n "$TOTEM_GH_STUB_FAIL_ISSUE_LIST" ]; then',
|
|
279
|
+
' case "$*" in *"issue list"*) exit 1 ;; esac',
|
|
280
|
+
'fi',
|
|
281
|
+
'if [ -n "$TOTEM_GH_STUB_FAIL_ISSUE_EDIT" ]; then',
|
|
282
|
+
' case "$*" in *"issue edit"*) exit 1 ;; esac',
|
|
283
|
+
'fi',
|
|
284
|
+
'if [ -n "$TOTEM_GH_STUB_FAIL_LABEL_DELETE" ]; then',
|
|
285
|
+
' case "$*" in *"label delete"*) exit 1 ;; esac',
|
|
286
|
+
'fi',
|
|
287
|
+
'if [ -n "$TOTEM_GH_STUB_FAIL" ]; then',
|
|
288
|
+
' case "$*" in *"label edit"*) exit 1 ;; esac',
|
|
289
|
+
'fi',
|
|
290
|
+
'exit 0',
|
|
291
|
+
'',
|
|
292
|
+
].join('\n'), { encoding: 'utf8', mode: 0o755 });
|
|
293
|
+
fs.chmodSync(stub, 0o755);
|
|
294
|
+
}
|
|
295
|
+
return { dir, logPath };
|
|
296
|
+
}
|
|
297
|
+
/** `process.env` with `dir` prepended to PATH, whatever case the platform spells it. */
|
|
298
|
+
function envWithPathPrefix(dir) {
|
|
299
|
+
const env = {};
|
|
300
|
+
let currentPath = '';
|
|
301
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
302
|
+
if (key.toUpperCase() === 'PATH') {
|
|
303
|
+
currentPath = value ?? '';
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
env[key] = value;
|
|
307
|
+
}
|
|
308
|
+
env.PATH = dir + path.delimiter + currentPath;
|
|
309
|
+
return env;
|
|
310
|
+
}
|
|
311
|
+
function runScript(args, stubDir, extraEnv = {}) {
|
|
312
|
+
return spawnSync('pwsh', ['-NoProfile', '-File', SCRIPT_PATH, ...args], {
|
|
313
|
+
cwd: ROOT,
|
|
314
|
+
encoding: 'utf8',
|
|
315
|
+
env: { ...envWithPathPrefix(stubDir), ...extraEnv },
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
describe.skipIf(!PWSH_PRESENT)('scripts/sync-labels.ps1 dry run', () => {
|
|
319
|
+
it('-WhatIf prints every gh call and executes none', () => {
|
|
320
|
+
const stub = makeGhStub();
|
|
321
|
+
try {
|
|
322
|
+
const run = runScript(['-WhatIf', '-Repo', 'example/stub'], stub.dir);
|
|
323
|
+
expect(run.error).toBeUndefined();
|
|
324
|
+
expect(run.status, run.stderr).toBe(0);
|
|
325
|
+
const stdout = run.stdout;
|
|
326
|
+
expect(stdout).toContain('[WhatIf] gh label edit "disposition: done"');
|
|
327
|
+
const labelLines = stdout
|
|
328
|
+
.split(/\r?\n/)
|
|
329
|
+
.filter((line) => line.startsWith('[WhatIf] gh label'));
|
|
330
|
+
// One line per would-be call, derived from the canon rather than pinned:
|
|
331
|
+
// a `create` AND an `edit` per canonical label (mmnto-ai/totem#2837 — an
|
|
332
|
+
// `edit`-only canonical exits the run on a repo that never carried it),
|
|
333
|
+
// and a `delete` per Merge-Label retirement.
|
|
334
|
+
const canon = realCanon();
|
|
335
|
+
const creates = canon.labels.length;
|
|
336
|
+
expect(labelLines.length).toBe(canon.labels.length + creates + canon.merges.length);
|
|
337
|
+
// Every canonical's `create` line immediately precedes its `edit` line.
|
|
338
|
+
// Keyed on the name alone: the shadow re-quotes only an argument carrying
|
|
339
|
+
// whitespace, and a description's em-dash is transliterated by the child
|
|
340
|
+
// console's code page, so the colour and description are the count's
|
|
341
|
+
// business (above), not this adjacency's.
|
|
342
|
+
const q = (text) => (/\s/.test(text) ? `"${text}"` : text);
|
|
343
|
+
for (const label of canon.labels) {
|
|
344
|
+
const createAt = labelLines.findIndex((line) => line.startsWith(`[WhatIf] gh label create ${q(label.name)} --color `));
|
|
345
|
+
expect(createAt, `create line for ${label.name}`).toBeGreaterThanOrEqual(0);
|
|
346
|
+
expect(labelLines[createAt + 1], `edit line follows create for ${label.name}`).toMatch(new RegExp(`^\\[WhatIf\\] gh label edit ${q(label.name).replace(/[.*+?^${}()|[\]\\]/g, '\\$&')} --color `));
|
|
347
|
+
}
|
|
348
|
+
// The shadow replaces the executable, so the stub on PATH never ran: no
|
|
349
|
+
// log file at all. This is the "-WhatIf touches nothing" invariant.
|
|
350
|
+
expect(fs.existsSync(stub.logPath)).toBe(false);
|
|
351
|
+
}
|
|
352
|
+
finally {
|
|
353
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
it('a normal run reaches gh for the whole canon — the -WhatIf shadow never leaks', () => {
|
|
357
|
+
const stub = makeGhStub();
|
|
358
|
+
try {
|
|
359
|
+
const run = runScript(['-Repo', 'example/stub'], stub.dir);
|
|
360
|
+
expect(run.error).toBeUndefined();
|
|
361
|
+
expect(run.status, run.stderr).toBe(0);
|
|
362
|
+
expect(run.stdout).not.toContain('[WhatIf]');
|
|
363
|
+
expect(fs.existsSync(stub.logPath), 'the stub gh was invoked').toBe(true);
|
|
364
|
+
const calls = fs
|
|
365
|
+
.readFileSync(stub.logPath, 'utf8')
|
|
366
|
+
.split(/\r?\n/)
|
|
367
|
+
.map((line) => line.trim())
|
|
368
|
+
.filter((line) => line.length > 0);
|
|
369
|
+
// The preflight ran (the unauthenticated silent no-op is now a hard stop).
|
|
370
|
+
expect(calls.some((call) => call.startsWith('auth status'))).toBe(true);
|
|
371
|
+
// Every canonical label was edited, by name, exactly once — the set and
|
|
372
|
+
// the count both derive from the real script (CodeRabbit on mmnto-ai/totem#2827).
|
|
373
|
+
const edited = calls
|
|
374
|
+
.map((call) => /^label edit "?(.+?)"? --color /.exec(call)?.[1])
|
|
375
|
+
.filter((name) => name !== undefined)
|
|
376
|
+
.sort();
|
|
377
|
+
const expectedEdited = realCanon()
|
|
378
|
+
.labels.map((label) => label.name)
|
|
379
|
+
.sort();
|
|
380
|
+
expect(edited).toEqual(expectedEdited);
|
|
381
|
+
// ...and created, by name, exactly once — every namespace, not only the
|
|
382
|
+
// dispositions (mmnto-ai/totem#2837).
|
|
383
|
+
const created = calls
|
|
384
|
+
.map((call) => /^label create "?(.+?)"? --color /.exec(call)?.[1])
|
|
385
|
+
.filter((name) => name !== undefined)
|
|
386
|
+
.sort();
|
|
387
|
+
expect(created).toEqual(expectedEdited);
|
|
388
|
+
}
|
|
389
|
+
finally {
|
|
390
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
it('a failed label edit fails the run — mutation errors never reach "sync complete"', () => {
|
|
394
|
+
// Authenticated but without write access, or an API failure: the literal
|
|
395
|
+
// lines suppress stderr by design, so only the exit CODE can carry the
|
|
396
|
+
// failure. The stub exits 1 on every `label edit`; the tally must name each
|
|
397
|
+
// canonical label and the script must exit non-zero (Greptile P1).
|
|
398
|
+
const stub = makeGhStub();
|
|
399
|
+
try {
|
|
400
|
+
const run = runScript(['-Repo', 'example/stub'], stub.dir, { TOTEM_GH_STUB_FAIL: '1' });
|
|
401
|
+
expect(run.error).toBeUndefined();
|
|
402
|
+
expect(run.status, run.stdout).toBe(1);
|
|
403
|
+
expect(run.stdout).toContain('label mutation(s) failed');
|
|
404
|
+
expect(run.stdout).not.toContain('sync complete');
|
|
405
|
+
const tallied = run.stdout
|
|
406
|
+
.split(/\r?\n/)
|
|
407
|
+
.filter((line) => line.includes('[Error] gh label edit')).length;
|
|
408
|
+
expect(tallied).toBe(realCanon().labels.length);
|
|
409
|
+
}
|
|
410
|
+
finally {
|
|
411
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
/** The stub's call log, one trimmed line per `gh` invocation. */
|
|
415
|
+
function loggedCalls(logPath) {
|
|
416
|
+
return fs
|
|
417
|
+
.readFileSync(logPath, 'utf8')
|
|
418
|
+
.split(/\r?\n/)
|
|
419
|
+
.map((line) => line.trim())
|
|
420
|
+
.filter((line) => line.length > 0);
|
|
421
|
+
}
|
|
422
|
+
it('a converged relabel retires the old label — every merge deletes once the issue carries the new name', () => {
|
|
423
|
+
// The positive control for the gate below: the stub lists issue #7 under
|
|
424
|
+
// every legacy label and accepts every `issue edit`, so every `Merge-Label`
|
|
425
|
+
// relabels #7 and then deletes the legacy name.
|
|
426
|
+
const stub = makeGhStub();
|
|
427
|
+
try {
|
|
428
|
+
const run = runScript(['-Repo', 'example/stub'], stub.dir, { TOTEM_GH_STUB_ISSUES: '1' });
|
|
429
|
+
expect(run.error).toBeUndefined();
|
|
430
|
+
expect(run.status, run.stdout).toBe(0);
|
|
431
|
+
expect(run.stdout).toContain('sync complete');
|
|
432
|
+
const calls = loggedCalls(stub.logPath);
|
|
433
|
+
const merges = realCanon().merges.length;
|
|
434
|
+
expect(merges).toBeGreaterThan(0);
|
|
435
|
+
expect(calls.filter((call) => /^issue edit 7 --add-label /.test(call))).toHaveLength(merges);
|
|
436
|
+
expect(calls.filter((call) => call.startsWith('label delete '))).toHaveLength(merges);
|
|
437
|
+
}
|
|
438
|
+
finally {
|
|
439
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
it('a failed relabel keeps the old label — the delete is gated on every issue carrying the new name', () => {
|
|
443
|
+
// The totem-status incident (2026-09-08, mmnto-ai/totem#2837): every
|
|
444
|
+
// `issue edit --add-label "type: bug"` had failed and the delete still ran,
|
|
445
|
+
// so `bug` left its issues with no replacement. The stub lists issue #7
|
|
446
|
+
// under every legacy label and refuses every `issue edit`: the script must
|
|
447
|
+
// name each kept label, delete nothing, and exit non-zero.
|
|
448
|
+
const stub = makeGhStub();
|
|
449
|
+
try {
|
|
450
|
+
const run = runScript(['-Repo', 'example/stub'], stub.dir, {
|
|
451
|
+
TOTEM_GH_STUB_ISSUES: '1',
|
|
452
|
+
TOTEM_GH_STUB_FAIL_ISSUE_EDIT: '1',
|
|
453
|
+
});
|
|
454
|
+
expect(run.error).toBeUndefined();
|
|
455
|
+
expect(run.status, run.stdout).toBe(1);
|
|
456
|
+
expect(run.stdout).not.toContain('sync complete');
|
|
457
|
+
const merges = realCanon().merges.length;
|
|
458
|
+
const kept = run.stdout
|
|
459
|
+
.split(/\r?\n/)
|
|
460
|
+
.filter((line) => line.includes("[Error] keeping '")).length;
|
|
461
|
+
expect(kept).toBe(merges);
|
|
462
|
+
const calls = loggedCalls(stub.logPath);
|
|
463
|
+
expect(calls.filter((call) => /^issue edit 7 --add-label /.test(call))).toHaveLength(merges);
|
|
464
|
+
expect(calls.filter((call) => call.startsWith('label delete '))).toHaveLength(0);
|
|
465
|
+
}
|
|
466
|
+
finally {
|
|
467
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
it('a failed issue list keeps the old label — a read failure is not an empty list', () => {
|
|
471
|
+
// `gh issue list` exits 1 (auth, rate limit, network): the script must not
|
|
472
|
+
// read that as "no issue carries the label" and delete it. Nothing is
|
|
473
|
+
// relabelled, nothing is deleted, the read failure counts against
|
|
474
|
+
// convergence, and the run exits non-zero.
|
|
475
|
+
const stub = makeGhStub();
|
|
476
|
+
try {
|
|
477
|
+
const run = runScript(['-Repo', 'example/stub'], stub.dir, {
|
|
478
|
+
TOTEM_GH_STUB_FAIL_ISSUE_LIST: '1',
|
|
479
|
+
});
|
|
480
|
+
expect(run.error).toBeUndefined();
|
|
481
|
+
expect(run.status, run.stdout).toBe(1);
|
|
482
|
+
expect(run.stdout).not.toContain('sync complete');
|
|
483
|
+
const merges = realCanon().merges.length;
|
|
484
|
+
const kept = run.stdout
|
|
485
|
+
.split(/\r?\n/)
|
|
486
|
+
.filter((line) => /\[Error\] gh issue list '.+' failed \(exit 1\) -- keeping '/.test(line)).length;
|
|
487
|
+
expect(kept).toBe(merges);
|
|
488
|
+
const calls = loggedCalls(stub.logPath);
|
|
489
|
+
expect(calls.filter((call) => call.startsWith('issue edit '))).toHaveLength(0);
|
|
490
|
+
expect(calls.filter((call) => call.startsWith('label delete '))).toHaveLength(0);
|
|
491
|
+
}
|
|
492
|
+
finally {
|
|
493
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
it('an issue past the read cap keeps the old label — the delete waits until no issue carries it', () => {
|
|
497
|
+
// The migration read is `--limit 1000`; a label on more issues than that
|
|
498
|
+
// lists a subset (Greptile P1 on mmnto-ai/totem#2839). The stub relabels
|
|
499
|
+
// #7 and then answers the limit-1 recheck with #7 again: the script must
|
|
500
|
+
// keep every legacy label, delete nothing, name the cap, and exit non-zero.
|
|
501
|
+
const stub = makeGhStub();
|
|
502
|
+
try {
|
|
503
|
+
const run = runScript(['-Repo', 'example/stub'], stub.dir, {
|
|
504
|
+
TOTEM_GH_STUB_ISSUES: '1',
|
|
505
|
+
TOTEM_GH_STUB_ISSUES_REMAIN: '1',
|
|
506
|
+
});
|
|
507
|
+
expect(run.error).toBeUndefined();
|
|
508
|
+
expect(run.status, run.stdout).toBe(1);
|
|
509
|
+
expect(run.stdout).not.toContain('sync complete');
|
|
510
|
+
const merges = realCanon().merges.length;
|
|
511
|
+
const kept = run.stdout
|
|
512
|
+
.split(/\r?\n/)
|
|
513
|
+
.filter((line) => line.includes('issues still carry it after the relabel pass')).length;
|
|
514
|
+
expect(kept).toBe(merges);
|
|
515
|
+
const calls = loggedCalls(stub.logPath);
|
|
516
|
+
expect(calls.filter((call) => /^issue edit 7 --add-label /.test(call))).toHaveLength(merges);
|
|
517
|
+
expect(calls.filter((call) => /^issue list .* --limit 1 --json/.test(call))).toHaveLength(merges);
|
|
518
|
+
expect(calls.filter((call) => call.startsWith('label delete '))).toHaveLength(0);
|
|
519
|
+
}
|
|
520
|
+
finally {
|
|
521
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
it('a failed delete of an already-absent label is a no-op — the run still converges', () => {
|
|
525
|
+
// `label delete` exits 1 on a name that was retired on an earlier run; the
|
|
526
|
+
// read-back finds nothing, so the failure is benign and the run completes.
|
|
527
|
+
const stub = makeGhStub();
|
|
528
|
+
try {
|
|
529
|
+
const run = runScript(['-Repo', 'example/stub'], stub.dir, {
|
|
530
|
+
TOTEM_GH_STUB_ISSUES: '1',
|
|
531
|
+
TOTEM_GH_STUB_FAIL_LABEL_DELETE: '1',
|
|
532
|
+
});
|
|
533
|
+
expect(run.error).toBeUndefined();
|
|
534
|
+
expect(run.status, run.stdout).toBe(0);
|
|
535
|
+
expect(run.stdout).toContain('sync complete');
|
|
536
|
+
const merges = realCanon().merges.length;
|
|
537
|
+
const calls = loggedCalls(stub.logPath);
|
|
538
|
+
expect(calls.filter((call) => call.startsWith('label delete '))).toHaveLength(merges);
|
|
539
|
+
expect(calls.filter((call) => call.startsWith('label list '))).toHaveLength(merges);
|
|
540
|
+
}
|
|
541
|
+
finally {
|
|
542
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
it('a failed delete of a label that remains fails the run — convergence is never reported over a leftover', () => {
|
|
546
|
+
// `label delete` exits 1 and the read-back still finds the name (CodeRabbit
|
|
547
|
+
// on mmnto-ai/totem#2839): the failure is tallied, the run exits non-zero
|
|
548
|
+
// and never prints "sync complete".
|
|
549
|
+
const stub = makeGhStub();
|
|
550
|
+
try {
|
|
551
|
+
const run = runScript(['-Repo', 'example/stub'], stub.dir, {
|
|
552
|
+
TOTEM_GH_STUB_ISSUES: '1',
|
|
553
|
+
TOTEM_GH_STUB_FAIL_LABEL_DELETE: '1',
|
|
554
|
+
TOTEM_GH_STUB_LABEL_PRESENT: '1',
|
|
555
|
+
});
|
|
556
|
+
expect(run.error).toBeUndefined();
|
|
557
|
+
expect(run.status, run.stdout).toBe(1);
|
|
558
|
+
expect(run.stdout).not.toContain('sync complete');
|
|
559
|
+
const merges = realCanon().merges.length;
|
|
560
|
+
const still = run.stdout
|
|
561
|
+
.split(/\r?\n/)
|
|
562
|
+
.filter((line) => /\[Error\] gh label delete '.+' failed and the label is still present/.test(line)).length;
|
|
563
|
+
expect(still).toBe(merges);
|
|
564
|
+
const calls = loggedCalls(stub.logPath);
|
|
565
|
+
expect(calls.filter((call) => call.startsWith('label delete '))).toHaveLength(merges);
|
|
566
|
+
expect(calls.filter((call) => call.startsWith('label list '))).toHaveLength(merges);
|
|
567
|
+
}
|
|
568
|
+
finally {
|
|
569
|
+
fs.rmSync(stub.dir, { recursive: true, force: true });
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
});
|
|
573
|
+
//# sourceMappingURL=sync-labels-forms.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-labels-forms.test.js","sourceRoot":"","sources":["../../src/commands/sync-labels-forms.test.ts"],"names":[],"mappings":"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"}
|