-
Notifications
You must be signed in to change notification settings - Fork 1k
feat(cli): add template rebuild --refresh-envd
#1818
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
Closed
AdaAibaby
wants to merge
1
commit into
e2b-dev:main
from
AdaAibaby:feat/cli-template-rebuild-refresh-envd
Closed
Changes from all commits
Commits
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| '@e2b/cli': minor | ||
| --- | ||
|
|
||
| Add `e2b template rebuild <template> --refresh-envd`: rebuild an existing template with the host's current envd while keeping its specs and alias. Old templates bake an old envd into their snapshot, which blocks features gated on a newer envd (e.g. volume mounts need envd >= 0.5.14); this rebuilds in place FROM the template's own latest ready build so only the envd binary is swapped. Streams build logs until the new build is ready. Requires the companion `POST /v2/templates/{templateID}/refresh-envd` endpoint (e2b-dev/infra#3624). |
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,101 @@ | ||
| import * as commander from 'commander' | ||
| import { defaultBuildLogger, Template } from 'e2b' | ||
|
|
||
| import { client, ensureAPIKey } from 'src/api' | ||
| import { handleE2BRequestError } from '../../utils/errors' | ||
| import { | ||
| asBold, | ||
| asFormattedError, | ||
| asLocal, | ||
| asPrimary, | ||
| } from '../../utils/format' | ||
|
|
||
| const buildStatusPollFrequencyMs = 2_000 | ||
|
|
||
| /** | ||
| * Rebuild a template with the host's current envd. This calls the server-side | ||
| * refresh-envd endpoint, which derives a new build FROM the template's own | ||
| * latest ready build (base layer cached, only the envd binary swapped) and | ||
| * inherits the source build's specs and alias in place. Then it streams build | ||
| * logs until the new build is ready. | ||
| */ | ||
| async function refreshEnvd(templateID: string) { | ||
| ensureAPIKey() | ||
|
|
||
| const res = await client.api.POST('/v2/templates/{templateID}/refresh-envd', { | ||
| params: { path: { templateID } }, | ||
| }) | ||
| handleE2BRequestError(res, 'Error requesting envd refresh') | ||
|
|
||
| const { buildID, fromEnvdVersion, aliases } = res.data | ||
| const name = aliases && aliases.length > 0 ? aliases[0] : templateID | ||
|
|
||
| console.log( | ||
| `\nRefreshing envd for ${asBold(name)} (from v${fromEnvdVersion}); rebuilding...\n` | ||
| ) | ||
|
|
||
| const onLog = defaultBuildLogger() | ||
| let logsOffset = 0 | ||
| // Poll the existing build status endpoint until the derived build settles. | ||
| // The status endpoint returns at most 100 log entries per call, so keep | ||
| // draining after a terminal status before deciding the outcome. | ||
| for (;;) { | ||
| const status = await Template.getBuildStatus( | ||
| { templateId: templateID, buildId: buildID }, | ||
| { logsOffset } | ||
| ) | ||
| logsOffset += status.logEntries.length | ||
| status.logEntries.forEach(onLog) | ||
|
|
||
| if (status.status === 'ready') { | ||
| if (status.logEntries.length > 0) continue | ||
| break | ||
| } | ||
| if (status.status === 'error') { | ||
| if (status.logEntries.length > 0) continue | ||
| console.error( | ||
| asFormattedError(status.reason?.message ?? 'Template build failed') | ||
| ) | ||
| process.exit(1) | ||
| } | ||
|
|
||
| await new Promise((r) => setTimeout(r, buildStatusPollFrequencyMs)) | ||
| } | ||
|
|
||
| console.log( | ||
| `\n✅ ${asBold(name)} rebuilt with the current envd.\n\n Confirm the binary changed: start a sandbox from ${asLocal( | ||
| name | ||
| )}, then run ${asPrimary('/usr/bin/envd -version')}.` | ||
| ) | ||
| } | ||
|
|
||
| export const rebuildCommand = new commander.Command('rebuild') | ||
| .description( | ||
| 'rebuild a template with the current envd, keeping its specs and alias. Useful for old templates whose baked-in envd is too old for newer features (e.g. volume mounts need envd >= 0.5.14).' | ||
| ) | ||
| .argument( | ||
| '<template>', | ||
| 'template id or alias to rebuild. Its specs and alias are inherited from the latest ready build.' | ||
| ) | ||
| .option( | ||
| '--refresh-envd', | ||
| "swap in the host's current envd binary (the only rebuild mode today; required)." | ||
| ) | ||
| .alias('rb') | ||
| .action(async (template: string, opts: { refreshEnvd?: boolean }) => { | ||
| if (!opts.refreshEnvd) { | ||
| console.error( | ||
| `Nothing to rebuild. Pass ${asBold( | ||
| '--refresh-envd' | ||
| )} to rebuild the template with the current envd.` | ||
| ) | ||
| process.exit(1) | ||
| } | ||
|
|
||
| try { | ||
| await refreshEnvd(template) | ||
| } catch (err: any) { | ||
| console.error(asFormattedError(err.message)) | ||
| process.exit(1) | ||
| } | ||
| }) | ||
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,36 @@ | ||
| import * as path from 'path' | ||
| import { execSync } from 'child_process' | ||
| import { describe, expect, test } from 'vitest' | ||
|
|
||
| // Black-box CLI tests (same idiom as publish.test.ts): run the built binary and | ||
| // assert on output up to the network boundary. The --refresh-envd guard and the | ||
| // command registration are deterministic and need no API key or network. | ||
| describe('template rebuild', () => { | ||
| const cliPath = path.join(process.cwd(), 'dist', 'index.js') | ||
|
|
||
| function run(args: string): string { | ||
| try { | ||
| return execSync(`node "${cliPath}" ${args} 2>&1`, { | ||
| encoding: 'utf-8', | ||
| stdio: 'pipe', | ||
| timeout: 10_000, | ||
| }) | ||
| } catch (err: any) { | ||
| return (err?.stdout ?? '') + (err?.stderr ?? '') | ||
| } | ||
| } | ||
|
|
||
| test('without --refresh-envd it refuses and points at the flag', () => { | ||
| const output = run('template rebuild some-template') | ||
| expect(output).toContain('--refresh-envd') | ||
| expect(output).not.toContain('Refreshing envd') | ||
| }) | ||
|
|
||
| test('is registered and documented under template help', () => { | ||
| const output = run('template rebuild --help') | ||
| expect(output).toContain('rebuild') | ||
| expect(output).toContain('--refresh-envd') | ||
| // The description explains the old-envd motivation. | ||
| expect(output).toContain('envd') | ||
| }) | ||
| }) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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.