Skip to content

Commit ca4b5d6

Browse files
chore: rewrite migrate banner copy and update guide URL
Banner now leads with the Rust rewrite and frames the orderbook value prop as recouping up to 20% of spend. Migration guide URL switches from the docs preview path to sfcompute.com/migrate. Inlines the install-script helpers back into the command action. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 7f85986 commit ca4b5d6

1 file changed

Lines changed: 78 additions & 95 deletions

File tree

src/lib/migrate.ts

Lines changed: 78 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,16 @@ import chalk from "chalk";
77
import ora from "ora";
88

99
const NEW_CLI_INSTALL_URL = "https://cli.sfcompute.com";
10-
const MIGRATION_GUIDE_URL =
11-
"https://docs.sfcompute.com/preview/guides/migrating-from-nodes";
10+
const MIGRATION_GUIDE_URL = "https://sfcompute.com/migrate";
1211

1312
export function showMigrateBanner() {
14-
const message = `We've rewritten sf in Rust — faster, with new commands
15-
like 'sf availability', 'sf capacities', and 'sf orders'.
13+
const message = `We've rewritten the sf CLI in Rust.
1614
17-
Migrating also opts you into our public preview, which
18-
lets you resell unused compute back on our orderbook
19-
and earn credits.
15+
List idle capacity on the orderbook to
16+
recoup up to 20% of your spend.
2017
21-
Run 'sf migrate' to install it. Your current sf will
22-
be moved to 'sf-old' so you can keep using it.
18+
Run 'sf migrate' to switch. Your current
19+
CLI stays as 'sf-old'.
2320
2421
Docs: ${MIGRATION_GUIDE_URL}
2522
Hide: SF_CLI_DISABLE_MIGRATE_BANNER=1`;
@@ -33,74 +30,69 @@ Hide: SF_CLI_DISABLE_MIGRATE_BANNER=1`;
3330
);
3431
}
3532

36-
async function fetchInstallScript(): Promise<string | null> {
37-
const spinner = ora("Downloading install script").start();
38-
try {
39-
const response = await fetch(NEW_CLI_INSTALL_URL);
40-
if (!response.ok) {
41-
spinner.fail("Failed to download install script.");
42-
return null;
43-
}
44-
const script = await response.text();
45-
spinner.succeed();
46-
return script;
47-
} catch (err) {
48-
spinner.fail("Failed to download install script.");
49-
console.error(err);
50-
return null;
51-
}
52-
}
53-
54-
async function runInstallScript(script: string): Promise<boolean> {
55-
const bashProcess = spawn("bash", [], {
56-
stdio: ["pipe", "inherit", "inherit"],
57-
env: process.env,
58-
});
59-
60-
// Without an error listener, spawn failures (ENOENT/EACCES on bash) emit
61-
// an unhandled 'error' event and crash the CLI instead of returning false.
62-
const spawnError = new Promise<Error>((resolve) => {
63-
bashProcess.once("error", resolve);
64-
});
65-
66-
try {
67-
bashProcess.stdin.write(script);
68-
bashProcess.stdin.end();
69-
} catch {
70-
// If stdin is already torn down (e.g. spawn failed synchronously), the
71-
// 'error' event handler below will surface the real reason.
72-
}
73-
74-
const result = await Promise.race([
75-
new Promise<{ kind: "close"; code: number | null }>((resolve) => {
76-
bashProcess.once("close", (code) => resolve({ kind: "close", code }));
77-
}),
78-
spawnError.then((err) => ({ kind: "error" as const, err })),
79-
]);
80-
81-
if (result.kind === "error") {
82-
console.error(chalk.red(`Failed to run bash: ${result.err.message}`));
83-
return false;
84-
}
85-
86-
return result.code === 0;
87-
}
88-
89-
export async function handleMigrate(): Promise<boolean> {
90-
const script = await fetchInstallScript();
91-
if (!script) return false;
92-
93-
console.log(chalk.cyan("\nInstalling the new Rust sf CLI...\n"));
94-
const ok = await runInstallScript(script);
95-
if (!ok) {
96-
console.error(chalk.red("\nMigration failed."));
97-
return false;
98-
}
99-
100-
console.log(
101-
boxen(
102-
chalk.cyan(
103-
`You're on the new sf.
33+
export function registerMigrate(program: Command) {
34+
return program
35+
.command("migrate")
36+
.description("Install the new Rust-based sf CLI")
37+
.action(async () => {
38+
const spinner = ora("Downloading install script").start();
39+
let script: string;
40+
try {
41+
const response = await fetch(NEW_CLI_INSTALL_URL);
42+
if (!response.ok) {
43+
spinner.fail("Failed to download install script.");
44+
process.exit(1);
45+
}
46+
script = await response.text();
47+
spinner.succeed();
48+
} catch (err) {
49+
spinner.fail("Failed to download install script.");
50+
console.error(err);
51+
process.exit(1);
52+
}
53+
54+
console.log(chalk.cyan("\nInstalling the new Rust sf CLI...\n"));
55+
56+
const bashProcess = spawn("bash", [], {
57+
stdio: ["pipe", "inherit", "inherit"],
58+
env: process.env,
59+
});
60+
61+
// Without an error listener, spawn failures (ENOENT/EACCES on bash) emit
62+
// an unhandled 'error' event and crash the CLI instead of exiting cleanly.
63+
const spawnError = new Promise<Error>((resolve) => {
64+
bashProcess.once("error", resolve);
65+
});
66+
67+
try {
68+
bashProcess.stdin.write(script);
69+
bashProcess.stdin.end();
70+
} catch {
71+
// If stdin is already torn down (e.g. spawn failed synchronously), the
72+
// 'error' event handler below will surface the real reason.
73+
}
74+
75+
const result = await Promise.race([
76+
new Promise<{ kind: "close"; code: number | null }>((resolve) => {
77+
bashProcess.once("close", (code) => resolve({ kind: "close", code }));
78+
}),
79+
spawnError.then((err) => ({ kind: "error" as const, err })),
80+
]);
81+
82+
if (result.kind === "error") {
83+
console.error(chalk.red(`Failed to run bash: ${result.err.message}`));
84+
process.exit(1);
85+
}
86+
87+
if (result.code !== 0) {
88+
console.error(chalk.red("\nMigration failed."));
89+
process.exit(1);
90+
}
91+
92+
console.log(
93+
boxen(
94+
chalk.cyan(
95+
`You're on the new sf.
10496
10597
Your previous CLI is still available as 'sf-old'.
10698
@@ -109,23 +101,14 @@ Next steps:
109101
sf availability
110102
111103
Migration guide: ${MIGRATION_GUIDE_URL}`,
112-
),
113-
{
114-
padding: 1,
115-
borderColor: "cyan",
116-
borderStyle: "round",
117-
},
118-
),
119-
);
120-
return true;
121-
}
122-
123-
export function registerMigrate(program: Command) {
124-
return program
125-
.command("migrate")
126-
.description("Install the new Rust-based sf CLI")
127-
.action(async () => {
128-
const success = await handleMigrate();
129-
process.exit(success ? 0 : 1);
104+
),
105+
{
106+
padding: 1,
107+
borderColor: "cyan",
108+
borderStyle: "round",
109+
},
110+
),
111+
);
112+
process.exit(0);
130113
});
131114
}

0 commit comments

Comments
 (0)