-
Notifications
You must be signed in to change notification settings - Fork 3
feat: add sf migrate command and Rust CLI migration banner
#266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
sigmachirality
wants to merge
4
commits into
main
Choose a base branch
from
indent-2026-05-21-migrate-banner
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
d0b679a
feat: add sf migrate command and Rust CLI migration banner
sigmachirality 8f91f5f
fix: address review feedback on migrate banner + command
sigmachirality a9e78ed
copy: rewrite migrate banner around reselling value prop
sigmachirality dd58923
copy: "back to the market" -> "back on our orderbook"
sigmachirality File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| import { spawn } from "node:child_process"; | ||
| import * as console from "node:console"; | ||
| import process from "node:process"; | ||
| import type { Command } from "@commander-js/extra-typings"; | ||
| import boxen from "boxen"; | ||
| import chalk from "chalk"; | ||
| import ora from "ora"; | ||
|
|
||
| const NEW_CLI_INSTALL_URL = "https://cli.sfcompute.com"; | ||
| const MIGRATION_GUIDE_URL = | ||
| "https://docs.sfcompute.com/preview/guides/migrating-from-nodes"; | ||
|
|
||
| export function showMigrateBanner() { | ||
| const message = `We've rewritten sf in Rust — faster, with new commands | ||
| like 'sf availability', 'sf capacities', and 'sf orders'. | ||
|
|
||
| Migrating also opts you into our public preview, which | ||
| lets you resell unused compute back on our orderbook | ||
| and earn credits. | ||
|
|
||
| Run 'sf migrate' to install it. Your current sf will | ||
| be moved to 'sf-old' so you can keep using it. | ||
|
|
||
| Docs: ${MIGRATION_GUIDE_URL} | ||
| Hide: SF_CLI_DISABLE_MIGRATE_BANNER=1`; | ||
|
|
||
| console.log( | ||
| boxen(chalk.cyan(message), { | ||
| padding: 1, | ||
| borderColor: "cyan", | ||
| borderStyle: "round", | ||
| }), | ||
| ); | ||
| } | ||
|
|
||
| async function fetchInstallScript(): Promise<string | null> { | ||
| const spinner = ora("Downloading install script").start(); | ||
| try { | ||
| const response = await fetch(NEW_CLI_INSTALL_URL); | ||
| if (!response.ok) { | ||
| spinner.fail("Failed to download install script."); | ||
| return null; | ||
| } | ||
| const script = await response.text(); | ||
| spinner.succeed(); | ||
| return script; | ||
| } catch (err) { | ||
| spinner.fail("Failed to download install script."); | ||
| console.error(err); | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| async function runInstallScript(script: string): Promise<boolean> { | ||
| const bashProcess = spawn("bash", [], { | ||
|
indent[bot] marked this conversation as resolved.
|
||
| stdio: ["pipe", "inherit", "inherit"], | ||
| env: process.env, | ||
| }); | ||
|
|
||
| // Without an error listener, spawn failures (ENOENT/EACCES on bash) emit | ||
| // an unhandled 'error' event and crash the CLI instead of returning false. | ||
| const spawnError = new Promise<Error>((resolve) => { | ||
| bashProcess.once("error", resolve); | ||
| }); | ||
|
|
||
| try { | ||
| bashProcess.stdin.write(script); | ||
| bashProcess.stdin.end(); | ||
| } catch { | ||
| // If stdin is already torn down (e.g. spawn failed synchronously), the | ||
| // 'error' event handler below will surface the real reason. | ||
| } | ||
|
|
||
| const result = await Promise.race([ | ||
| new Promise<{ kind: "close"; code: number | null }>((resolve) => { | ||
| bashProcess.once("close", (code) => resolve({ kind: "close", code })); | ||
| }), | ||
| spawnError.then((err) => ({ kind: "error" as const, err })), | ||
| ]); | ||
|
|
||
| if (result.kind === "error") { | ||
| console.error(chalk.red(`Failed to run bash: ${result.err.message}`)); | ||
| return false; | ||
| } | ||
|
|
||
| return result.code === 0; | ||
| } | ||
|
|
||
| export async function handleMigrate(): Promise<boolean> { | ||
| const script = await fetchInstallScript(); | ||
| if (!script) return false; | ||
|
|
||
| console.log(chalk.cyan("\nInstalling the new Rust sf CLI...\n")); | ||
| const ok = await runInstallScript(script); | ||
| if (!ok) { | ||
| console.error(chalk.red("\nMigration failed.")); | ||
| return false; | ||
| } | ||
|
|
||
| console.log( | ||
| boxen( | ||
| chalk.cyan( | ||
| `You're on the new sf. | ||
|
|
||
| Your previous CLI is still available as 'sf-old'. | ||
|
|
||
| Next steps: | ||
| sf login | ||
| sf availability | ||
|
|
||
| Migration guide: ${MIGRATION_GUIDE_URL}`, | ||
| ), | ||
| { | ||
| padding: 1, | ||
| borderColor: "cyan", | ||
| borderStyle: "round", | ||
| }, | ||
| ), | ||
| ); | ||
| return true; | ||
| } | ||
|
|
||
| export function registerMigrate(program: Command) { | ||
| return program | ||
| .command("migrate") | ||
| .description("Install the new Rust-based sf CLI") | ||
| .action(async () => { | ||
| const success = await handleMigrate(); | ||
| process.exit(success ? 0 : 1); | ||
| }); | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is the first time some one is seeing this:
- sf capacities etc doesn't mean anything to them.
- rewritten in rust also doesn't entice them to migrate.
Suggested copy below. Tried to highlight better compute utilization/planning and reselling. If that piques their curiosity then can look at our docs.
A new sf is here.
Intuitive tools to plan, buy, and utilize compute.
Resell unused compute back on our orderbook and earn credits.
Opt in to get early access.
Run 'sf migrate'...
Docs: <link to preview docs>
Alternative Resell line:
Save upto 20% by reselling compute back on our orderbook and earn credits. Source: https://sfcompute.slack.com/archives/C09UJ3K6T4P/p1779323745810779