Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c90099ea9 |
@@ -0,0 +1,67 @@
|
||||
# Row 238: the sso-config hint names the instance (row 200 follow-up N1)
|
||||
|
||||
Launchpad, 2026-10-21. Author Launchpad, reviewer Webby, gate owner Sage. Issue #1744. Brief "Brief: row 200
|
||||
follow-up N1, the sso-config hint names the instance" in `docs/plans/2026-10-20_stack-release-sso.md` (76134dfde),
|
||||
from Webby's row 200 round 3 note N1 (comment 29772), assigned in sage-1597.
|
||||
|
||||
Round 4 base c515273db, row 240's landing (`base.txt`). Branch `launchpad/row238-r4`, one commit.
|
||||
|
||||
- Round 1 was `launchpad/row238` bec7e499e on 011d41ba6, approved by Webby (webby-0049). It was built on
|
||||
76134dfde and rebased before its first push, after row 199 (cb5fdb064) added 6 lines to `docs/TOOLS.md`.
|
||||
- Rows 232 (e65a3ab4d) and 233 (57f59e0c3) then landed on all 3 paths (sage-1710, sage-1755). Round 2 was a
|
||||
local rebase onto 57f59e0c3 (ca3d30e5c, never pushed). The merge was clean. `sso_checks` moved from about
|
||||
:838 to :920 with its body unchanged except for this row's hunk. 233 moved the shared test helpers into
|
||||
`stack-release-fixture.mjs`, and the new subtest is still under T57.
|
||||
- Row 234 (c771a36f4) then added two lines to T46's `untimed` map (`host_grants`, `hosts`, now :919-920).
|
||||
Round 3 is the same patch on c771a36f4 with those lines kept. The code diff on the 3 paths has the same
|
||||
`git patch-id --stable` on both bases (b9d0bb0ee3c7). Pushed as `launchpad/row238-r3` a33597c33 and
|
||||
approved by Webby in round 2 (webby-0059, rev 2707).
|
||||
- Row 240 (c515273db) then changed `docs/TOOLS.md` at :837 and :854, away from this row's hunk at :599
|
||||
(sage-1803). Round 4 is the same patch on c515273db: `docs/TOOLS.md` is the landed blob plus the one
|
||||
hunk, and `scripts/stack-release.sh` (100755) and `stack-release.test.mjs` keep round 3's blobs. The
|
||||
patch-id is still b9d0bb0ee3c7. No test run for this doc-only merge; Sage's landing gate covers it.
|
||||
Row 240 also changed `stack-upgrade.test.mjs`, so the round 2 result for that file is from the older blob.
|
||||
`candidate-manifest.sha256` lists the 3 changed paths; the packet files are not in it.
|
||||
|
||||
No test touches `~/.mosaic-dev`, `~/.config/mosaic-dev`, `~/.mosaic`, a live unit or a live slot. The new
|
||||
subtest runs on row 190's `named()` scratch instance under the test's temp HOME.
|
||||
|
||||
## Files
|
||||
|
||||
| Path | Change |
|
||||
| --- | --- |
|
||||
| `scripts/stack-release.sh` | `sso_checks`: the N4 first step puts `${INSTANCE_FLAGS[*]}` after `activate $TO` in both commands. |
|
||||
| `packages/cli/tests/stack-release.test.mjs` | T57 subtest "row 238 (#1744)": the sso-config refusal and the `--plan` line on instance `alpha`. |
|
||||
| `docs/TOOLS.md` | The `sso-config` paragraph says both commands carry `--instance NAME` on a named instance. |
|
||||
|
||||
## What it does
|
||||
|
||||
On a named instance the hint now reads `activate ID --instance NAME without --sso first, then write
|
||||
console.sso, then run activate ID --instance NAME --sso`. `INSTANCE_FLAGS` is empty for the default instance,
|
||||
so `inst` is empty and the default text is unchanged byte for byte. T57's item 2 subtest still asserts the
|
||||
default text exactly. The flag goes right after `ID`, the same place the other entry points take it from
|
||||
`INSTANCE_FLAGS`. BUSINESS is not in the hint before or after this row.
|
||||
|
||||
## Tests run (this tree)
|
||||
|
||||
Logs are in `/mnt/storage/scratch/launchpad-r238/`.
|
||||
|
||||
- Round 1: `stack-release.test.mjs` whole, 193/193 on 76134dfde (`sr-whole.log`) and on 011d41ba6
|
||||
(`sr-whole-2.log`). `stack-instances.test.mjs` whole, 23/23 (`si.log`).
|
||||
- Round 2, on ca3d30e5c (57f59e0c3), each file singly on Sage's slot (sage-1761): `stack-release.test.mjs`
|
||||
196/196, `stack-release-external.test.mjs` 25/25, `stack-upgrade.test.mjs` 20/20 (`r2-*.log`, 241/0 by
|
||||
awk). Sage counts these as pre-merge (sage-1769).
|
||||
- Round 3, on this blob singly on Sage's slot (sage-1794): `stack-release.test.mjs` 196/196, 06:34:22Z to
|
||||
06:42:57Z (`r3-stack-release.log`). The other two files and
|
||||
`stack-release-fixture.mjs` are the same on 57f59e0c3 and c771a36f4, so their round 2 results stand.
|
||||
- A grep of `packages/*/tests/*` and `scripts/test-*.sh` finds the hint text only in `stack-release.test.mjs`
|
||||
(`:1538` default, `:1689` and `:1691` named) and no 64-hex pin on the 3 paths.
|
||||
- The cli suite, every `scripts/test-*.sh` and the mutant go to Sage's slot.
|
||||
|
||||
## Mutants (`mutants.py`, run as `python3 mutants.py <tree> [N ...]`, against T57)
|
||||
|
||||
| # | Mutant | Result |
|
||||
| --- | --- | --- |
|
||||
| 1 | the first step drops `--instance NAME` (`inst=""`) | not run, Sage's slot |
|
||||
|
||||
The pattern matches once on this tree.
|
||||
@@ -0,0 +1 @@
|
||||
c515273db7b364736527493ed170d0f088eb506e
|
||||
@@ -0,0 +1,3 @@
|
||||
abdd641ea5a411347e3644286821c6485a6220e2a3de0f5ee95dcc37ba2c75ca docs/TOOLS.md
|
||||
4eeae9f672aecccdf853c377fb10847ce2656dbc566720bddfece435c1755d3b packages/cli/tests/stack-release.test.mjs
|
||||
1896d6518a502d340dfe30d402102b8c5cd5d8520757387b018b636755eb5d36 scripts/stack-release.sh
|
||||
@@ -0,0 +1,37 @@
|
||||
# Row 238 (#1744) mutant: `python3 mutants.py <tree> [N ...]`. Each applies to the tree's scripts/stack-release.sh,
|
||||
# runs T57 in packages/cli/tests/stack-release.test.mjs and restores the file from a saved copy, checked by sha256.
|
||||
# Killed = test exit != 0.
|
||||
import hashlib, os, subprocess, sys, signal
|
||||
R = os.path.abspath(sys.argv[1])
|
||||
S = os.path.join(R, 'scripts', 'stack-release.sh')
|
||||
if not os.path.isfile(S): sys.exit(f'ABORT no scripts/stack-release.sh under {sys.argv[1]}')
|
||||
T, PAT = 'tests/stack-release.test.mjs', '^T57'
|
||||
M = [
|
||||
('the sso-config first step drops --instance NAME (row 238)', [(' local first="" inst="${INSTANCE_FLAGS[*]:+ ${INSTANCE_FLAGS[*]}}"', ' local first="" inst=""')]),
|
||||
]
|
||||
sha = lambda b: hashlib.sha256(b).hexdigest()
|
||||
only = sys.argv[2:]
|
||||
os.chdir(os.path.join(R, 'packages', 'cli'))
|
||||
survived = []
|
||||
for i, (name, pairs) in enumerate(M, 1):
|
||||
if only and str(i) not in only: continue
|
||||
orig = open(S, 'rb').read(); h = sha(orig)
|
||||
src = orig.decode()
|
||||
for a, b in pairs:
|
||||
if src.count(a) != 1: sys.exit(f'ABORT {i} {name}: pattern found {src.count(a)} times')
|
||||
src = src.replace(a, b)
|
||||
try:
|
||||
open(S, 'w').write(src); os.chmod(S, 0o755)
|
||||
p = subprocess.Popen(['node', '--test', f'--test-name-pattern={PAT}', T], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, start_new_session=True)
|
||||
try: out, _ = p.communicate(timeout=300)
|
||||
except subprocess.TimeoutExpired:
|
||||
os.killpg(p.pid, signal.SIGKILL); out, _ = p.communicate(); out += b'\nTIMEOUT'
|
||||
text = out.decode(errors='replace')
|
||||
ran = [l for l in text.splitlines() if l.startswith('ℹ fail ')]
|
||||
verdict = 'KILLED' if p.returncode != 0 else 'SURVIVED'
|
||||
if verdict == 'SURVIVED': survived.append(name)
|
||||
print(f'{i:2} {verdict} {name} [{ran[0] if ran else "no count"}]', flush=True)
|
||||
finally:
|
||||
open(S, 'wb').write(orig); os.chmod(S, 0o755)
|
||||
if sha(open(S, 'rb').read()) != h: sys.exit(f'ABORT restore failed for {S}')
|
||||
print('survived:', survived or 'none')
|
||||
+2
-1
@@ -599,7 +599,8 @@ error. Before anything stops, a run whose Console flags hold `--sso` refuses
|
||||
`sso-target` for a target Console without it, `sso-config` when the target's own
|
||||
`checkConsole` refuses the config's `console` key (or there is none, in which
|
||||
case, from another copy, it names the first step: activate the target without
|
||||
`--sso`, then write `console.sso`), and `sso-slot` for each provider's slot file
|
||||
`--sso`, then write `console.sso`; on a named instance both commands carry
|
||||
`--instance NAME`), and `sso-slot` for each provider's slot file
|
||||
that is missing, a symlink, not a regular file, not owned by this uid, has group
|
||||
or other bits, resolves inside the repository or the copies, or is empty. It
|
||||
uses `lstat`, `stat` and `realpath` on the slot and never reads it. `--plan`
|
||||
|
||||
@@ -1683,6 +1683,14 @@ test('T57 row 200: activate --sso, its refusals before any stop, and the rollbac
|
||||
assert.ok(stepText(a).includes(`Z drop --sso; ${B}'s Console does not support it, so the Console flags come from ${set}/${show}\n`));
|
||||
await noLeak(a);
|
||||
});
|
||||
await t.test('row 238 (#1744): on a named instance the sso-config first step names --instance NAME in both commands',async(t)=>{
|
||||
const e=await mk(t),a=await named(e,'alpha');await seed(a);
|
||||
assert.equal(JSON.parse(readFileSync(a.cfg,'utf8')).console,undefined);
|
||||
await refused(a,['activate',C1,'acme','--sso'],'sso-config',`${C1}'s Console would refuse its --sso start: there is no console.sso in the system config; activate ${C1} --instance alpha without --sso first, then write console.sso, then run activate ${C1} --instance alpha --sso`);
|
||||
const out=await planOnly(a,3,'activate',C1,'acme','--sso');
|
||||
assert.ok(out.includes(`refuses sso-config: ${C1}'s Console would refuse its --sso start: there is no console.sso in the system config; activate ${C1} --instance alpha without --sso first, then write console.sso, then run activate ${C1} --instance alpha --sso`),out.join('\n'));
|
||||
await noLeak(a);
|
||||
});
|
||||
});
|
||||
|
||||
// --- rehearse (D2, row 163; the brief's "Stack rehearsal on a scratch root") ---
|
||||
|
||||
@@ -929,12 +929,13 @@ sso_checks() {
|
||||
sso_supported || { check_refuse sso-target "$TO's Console does not support --sso"; return 0; }
|
||||
local cfg="${MOSAIC_CONFIG:-$HOME/.config/mosaic-dev/config.json}" out id slot path why
|
||||
# N4 (webby-0019, sage-1403): a pre-phase-1 loader refuses a console key, so with the key not yet
|
||||
# written and the stack on another copy, the first step is the re-pin without --sso.
|
||||
local first=""
|
||||
# written and the stack on another copy, the first step is the re-pin without --sso. On a named
|
||||
# instance both commands carry --instance NAME (row 238).
|
||||
local first="" inst="${INSTANCE_FLAGS[*]:+ ${INSTANCE_FLAGS[*]}}"
|
||||
if ! out="$(node -e "$SSO_JS" -- "$COPIES/$TO" "$cfg" 2>&1)"; then
|
||||
out="${out%%$'\n'*}"
|
||||
[ "$out" != "there is no console.sso in the system config" ] || [ "$P_COPY" = "$TO" ] ||
|
||||
first="; activate $TO without --sso first, then write console.sso, then run activate $TO --sso"
|
||||
first="; activate $TO$inst without --sso first, then write console.sso, then run activate $TO$inst --sso"
|
||||
check_refuse sso-config "$TO's Console would refuse its --sso start: $out$first"
|
||||
return 0
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user