Fix sg docker re-exec restarting setup from scratch
When maybeReexecUnderSg() re-launches setup:auto under `sg docker`, the new process had no memory of completed steps — it re-prompted the welcome menu, re-ran environment and container checks, and then failed on onecli because the earlier run's state was lost. Pass NANOCLAW_SKIP with completedStepNames() so the re-exec'd process skips already-finished steps, suppress the welcome menu and existing-env prompts on re-exec since the user already answered them. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -85,7 +85,10 @@ async function main(): Promise<void> {
|
|||||||
|
|
||||||
// Welcome menu — default path or open advanced overrides before any setup
|
// Welcome menu — default path or open advanced overrides before any setup
|
||||||
// work begins. Default lands on standard so Enter is the happy path.
|
// work begins. Default lands on standard so Enter is the happy path.
|
||||||
const startChoice = ensureAnswer(
|
// On sg re-exec, the user already chose — skip straight to standard.
|
||||||
|
let startChoice: 'default' | 'advanced' = 'default';
|
||||||
|
if (process.env.NANOCLAW_REEXEC_SG !== '1') {
|
||||||
|
startChoice = ensureAnswer(
|
||||||
await brightSelect<'default' | 'advanced'>({
|
await brightSelect<'default' | 'advanced'>({
|
||||||
message: 'How would you like to begin?',
|
message: 'How would you like to begin?',
|
||||||
options: [
|
options: [
|
||||||
@@ -96,6 +99,7 @@ async function main(): Promise<void> {
|
|||||||
}),
|
}),
|
||||||
) as 'default' | 'advanced';
|
) as 'default' | 'advanced';
|
||||||
setupLog.userInput('start_choice', startChoice);
|
setupLog.userInput('start_choice', startChoice);
|
||||||
|
}
|
||||||
if (startChoice === 'advanced') {
|
if (startChoice === 'advanced') {
|
||||||
configValues = await runAdvancedScreen(configValues);
|
configValues = await runAdvancedScreen(configValues);
|
||||||
applyToEnv(configValues);
|
applyToEnv(configValues);
|
||||||
@@ -126,12 +130,17 @@ async function main(): Promise<void> {
|
|||||||
// paste credentials again on a re-run.
|
// paste credentials again on a re-run.
|
||||||
const existingEnv = detectExistingEnv();
|
const existingEnv = detectExistingEnv();
|
||||||
if (existingEnv) {
|
if (existingEnv) {
|
||||||
|
// On sg re-exec, auto-reuse — the user already decided in the first run.
|
||||||
|
const isReexec = process.env.NANOCLAW_REEXEC_SG === '1';
|
||||||
|
let reuseChoice: 'reuse' | 'fresh' = 'reuse';
|
||||||
|
|
||||||
|
if (!isReexec) {
|
||||||
const lines = Object.values(existingEnv.groups).map(
|
const lines = Object.values(existingEnv.groups).map(
|
||||||
(g) => ` ${k.green('✓')} ${g.label}`,
|
(g) => ` ${k.green('✓')} ${g.label}`,
|
||||||
);
|
);
|
||||||
note(lines.join('\n'), 'Found existing configuration');
|
note(lines.join('\n'), 'Found existing configuration');
|
||||||
|
|
||||||
const reuseChoice = ensureAnswer(
|
reuseChoice = ensureAnswer(
|
||||||
await brightSelect({
|
await brightSelect({
|
||||||
message: 'Use this existing environment?',
|
message: 'Use this existing environment?',
|
||||||
options: [
|
options: [
|
||||||
@@ -142,6 +151,7 @@ async function main(): Promise<void> {
|
|||||||
}),
|
}),
|
||||||
) as 'reuse' | 'fresh';
|
) as 'reuse' | 'fresh';
|
||||||
setupLog.userInput('existing_env_choice', reuseChoice);
|
setupLog.userInput('existing_env_choice', reuseChoice);
|
||||||
|
}
|
||||||
|
|
||||||
if (reuseChoice === 'reuse') {
|
if (reuseChoice === 'reuse') {
|
||||||
for (const [key, value] of Object.entries(existingEnv.raw)) {
|
for (const [key, value] of Object.entries(existingEnv.raw)) {
|
||||||
@@ -1178,9 +1188,11 @@ function maybeReexecUnderSg(): void {
|
|||||||
if (spawnSync('which', ['sg'], { stdio: 'ignore' }).status !== 0) return;
|
if (spawnSync('which', ['sg'], { stdio: 'ignore' }).status !== 0) return;
|
||||||
|
|
||||||
p.log.warn('Docker socket not accessible in current group. Re-executing under `sg docker`.');
|
p.log.warn('Docker socket not accessible in current group. Re-executing under `sg docker`.');
|
||||||
|
const existingSkip = (process.env.NANOCLAW_SKIP ?? '').split(',').map((s) => s.trim()).filter(Boolean);
|
||||||
|
const skipList = [...new Set([...existingSkip, ...setupLog.completedStepNames()])].join(',');
|
||||||
const res = spawnSync('sg', ['docker', '-c', 'pnpm run setup:auto'], {
|
const res = spawnSync('sg', ['docker', '-c', 'pnpm run setup:auto'], {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
env: { ...process.env, NANOCLAW_REEXEC_SG: '1' },
|
env: { ...process.env, NANOCLAW_REEXEC_SG: '1', ...(skipList ? { NANOCLAW_SKIP: skipList } : {}) },
|
||||||
});
|
});
|
||||||
process.exit(res.status ?? 1);
|
process.exit(res.status ?? 1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user