diff --git a/docs.json b/docs.json index 386dcdd..b7e7a8d 100644 --- a/docs.json +++ b/docs.json @@ -104,7 +104,8 @@ "docs/template/defining-template", "docs/template/start-ready-command", "docs/template/build", - "docs/template/aliases", + "docs/template/names", + "docs/template/versioning", "docs/template/logging", "docs/template/error-handling", { @@ -270,6 +271,11 @@ } }, "redirects": [ + { + "source": "/docs/template/aliases", + "destination": "/docs/template/names", + "permanent": true + }, { "source": "/docs/sandbox-templates/overview", "destination": "/docs/sandbox-template", diff --git a/docs/mcp/custom-templates.mdx b/docs/mcp/custom-templates.mdx index 05344a8..ab7a6a5 100644 --- a/docs/mcp/custom-templates.mdx +++ b/docs/mcp/custom-templates.mdx @@ -28,8 +28,7 @@ export const template = Template() .fromTemplate("mcp-gateway") .addMcpServer(["browserbase", "exa"]); -await Template.build(template, { - alias: "my-mcp-gateway", +await Template.build(template, 'my-mcp-gateway', { cpuCount: 8, memoryMB: 8192, onBuildLogs: defaultBuildLogger(), @@ -50,7 +49,7 @@ template = ( Template.build( template, - alias="my-mcp-gateway", + 'my-mcp-gateway', cpu_count=8, memory_mb=8192, on_build_logs=default_build_logger(), @@ -61,7 +60,7 @@ Template.build( ## Using the template -Once built, create sandboxes from your template alias. You still need to provide the configuration for each MCP server. +Once built, create sandboxes from your template. You still need to provide the configuration for each MCP server. diff --git a/docs/quickstart/install-custom-packages.mdx b/docs/quickstart/install-custom-packages.mdx index 4d75305..4f6310b 100644 --- a/docs/quickstart/install-custom-packages.mdx +++ b/docs/quickstart/install-custom-packages.mdx @@ -71,8 +71,7 @@ import { Template, defaultBuildLogger } from 'e2b'; import { template } from './template'; async function main() { - await Template.build(template, { - alias: "custom-packages", + await Template.build(template, 'custom-packages', { cpuCount: 2, memoryMB: 2048, onBuildLogs: defaultBuildLogger(), @@ -93,7 +92,7 @@ load_dotenv() if __name__ == '__main__': Template.build( template, - alias="custom-packages", + 'custom-packages', cpu_count=2, memory_mb=2048, on_build_logs=default_build_logger(), diff --git a/docs/template/build.mdx b/docs/template/build.mdx index 588f95a..b05795c 100644 --- a/docs/template/build.mdx +++ b/docs/template/build.mdx @@ -10,8 +10,7 @@ The `build` method builds the template and waits for the build to complete. It r ```typescript JavaScript & TypeScript wrap -const buildInfo = await Template.build(template, { - alias: 'my-template', // Template alias (required) +const buildInfo = await Template.build(template, 'my-template', { cpuCount: 2, // CPU cores memoryMB: 2048, // Memory in MB skipCache: false, // Configure cache skip (except for files) @@ -20,13 +19,13 @@ const buildInfo = await Template.build(template, { domain: 'your-domain', // Override domain }) -// buildInfo contains: { alias, templateId, buildId } +// buildInfo contains: { name, templateId, buildId } ``` ```python Python wrap build_info = Template.build( template, - alias="my-template", # Template alias (required) + 'my-template', cpu_count=2, # CPU cores memory_mb=2048, # Memory in MB skip_cache=False, # Configure cache skip (except for files) @@ -35,7 +34,7 @@ build_info = Template.build( domain="your-domain", # Override domain ) -# build_info contains: BuildInfo(alias, template_id, build_id) +# build_info contains: BuildInfo(name, template_id, build_id) ``` @@ -47,24 +46,23 @@ The `buildInBackground` method starts the build process and returns immediately ```typescript JavaScript & TypeScript wrap -const buildInfo = await Template.buildInBackground(template, { - alias: 'my-template', +const buildInfo = await Template.buildInBackground(template, 'my-template', { cpuCount: 2, memoryMB: 2048, }) -// Returns immediately with: { alias, templateId, buildId } +// Returns immediately with: { name, templateId, buildId } ``` ```python Python wrap build_info = Template.build_in_background( template, - alias="my-template", + 'my-template', cpu_count=2, memory_mb=2048, ) -# Returns immediately with: BuildInfo(alias, template_id, build_id) +# Returns immediately with: BuildInfo(name, template_id, build_id) ``` @@ -100,8 +98,7 @@ status = Template.get_build_status( ```typescript JavaScript & TypeScript wrap // Start build in background -const buildInfo = await Template.buildInBackground(template, { - alias: 'my-template', +const buildInfo = await Template.buildInBackground(template, 'my-template', { cpuCount: 2, memoryMB: 2048, }) @@ -137,7 +134,7 @@ if (status === 'ready') { # Start build in background build_info = Template.build_in_background( template, - alias="my-template", + 'my-template', cpu_count=2, memory_mb=2048, ) diff --git a/docs/template/caching.mdx b/docs/template/caching.mdx index ef0eab8..585adec 100644 --- a/docs/template/caching.mdx +++ b/docs/template/caching.mdx @@ -43,9 +43,8 @@ To force rebuild the whole template, you can use also `skipCache`/`skip_cache` p -```typescript JavaScript & TypeScript wrap highlight={3} -Template.build(template, { - alias: 'my-template', +```typescript JavaScript & TypeScript wrap highlight={2} +Template.build(template, 'my-template', { skipCache: true, // Configure cache skip (except for files) }) ``` @@ -53,7 +52,7 @@ Template.build(template, { ```python Python wrap highlight={4} Template.build( template, - alias="my-template", + 'my-template', skip_cache=True, # Configure cache skip (except for files) ) ``` @@ -91,7 +90,7 @@ template = ( ## Use Case for Caching You can leverage caching to create templates with multiple variants (e.g., different RAM or CPU) while reusing the common layers. -When building the template, just change the template alias to a specific RAM/CPU configuration (e.g., `my-template-2cpu-2gb`, `my-template-1cpu-4gb`), keep the rest of the template definition the same, and the build process will reuse the cached layers. +When building the template, just change the template name to a specific RAM/CPU configuration (e.g., `my-template-2cpu-2gb`, `my-template-1cpu-4gb`), keep the rest of the template definition the same, and the build process will reuse the cached layers. ## Optimize Build Times To optimize build times, place frequently changing commands (e.g., copying source code) towards the end of your template definition. This way, earlier layers can be cached and reused more often. diff --git a/docs/template/error-handling.mdx b/docs/template/error-handling.mdx index 926c9d1..38f3033 100644 --- a/docs/template/error-handling.mdx +++ b/docs/template/error-handling.mdx @@ -11,9 +11,7 @@ The SDK provides specific error types: import { AuthError, BuildError, FileUploadError } from 'e2b'; try { - await Template.build(template, { - alias: "my-template", - }); + await Template.build(template, 'my-template'); } catch (error) { if (error instanceof AuthError) { console.error("Authentication failed:", error.message); @@ -29,7 +27,7 @@ try { from e2b import AuthError, BuildError, FileUploadError try: - Template.build(template, alias="my-template") + Template.build(template, 'my-template') except AuthError as error: print(f"Authentication failed: {error}") except FileUploadError as error: diff --git a/docs/template/examples/claude-code.mdx b/docs/template/examples/claude-code.mdx index fc8c02f..efb97ff 100644 --- a/docs/template/examples/claude-code.mdx +++ b/docs/template/examples/claude-code.mdx @@ -41,8 +41,7 @@ template = ( import { Template, defaultBuildLogger } from 'e2b' import { template as claudeCodeTemplate } from './template' -Template.build(claudeCodeTemplate, { - alias: 'claude-code', +Template.build(claudeCodeTemplate, 'claude-code', { cpuCount: 1, memoryMB: 1024, onBuildLogs: defaultBuildLogger(), @@ -54,8 +53,7 @@ Template.build(claudeCodeTemplate, { from e2b import Template, default_build_logger from .template import template as claudeCodeTemplate -Template.build(claudeCodeTemplate, - alias="claude-code", +Template.build(claudeCodeTemplate, 'claude-code', cpu_count=1, memory_mb=1024, on_build_logs=default_build_logger(), diff --git a/docs/template/examples/desktop.mdx b/docs/template/examples/desktop.mdx index 185a88a..2be2e91 100644 --- a/docs/template/examples/desktop.mdx +++ b/docs/template/examples/desktop.mdx @@ -164,8 +164,7 @@ sleep 2 import { Template, defaultBuildLogger } from 'e2b' import { template as desktopTemplate } from './template' -await Template.build(desktopTemplate, { - alias: 'desktop', +await Template.build(desktopTemplate, 'desktop', { cpuCount: 8, memoryMB: 8192, onBuildLogs: defaultBuildLogger(), @@ -177,8 +176,7 @@ await Template.build(desktopTemplate, { from e2b import Template, default_build_logger from .template import template as desktopTemplate -Template.build(desktopTemplate, - alias="desktop", +Template.build(desktopTemplate, 'desktop', cpu_count=8, memory_mb=8192, on_build_logs=default_build_logger(), diff --git a/docs/template/examples/expo.mdx b/docs/template/examples/expo.mdx index 258b4a3..c60b631 100644 --- a/docs/template/examples/expo.mdx +++ b/docs/template/examples/expo.mdx @@ -45,8 +45,7 @@ template = ( import { Template, defaultBuildLogger } from 'e2b' import { template as expoTemplate } from './template' -Template.build(expoTemplate, { - alias: 'expo-app', +Template.build(expoTemplate, 'expo-app', { cpuCount: 4, memoryMB: 8192, onBuildLogs: defaultBuildLogger(), @@ -58,8 +57,7 @@ Template.build(expoTemplate, { from e2b import Template, default_build_logger from .template import template as expoTemplate -Template.build(expoTemplate, - alias="expo-app", +Template.build(expoTemplate, 'expo-app', cpu_count=4, memory_mb=8192, on_build_logs=default_build_logger(), diff --git a/docs/template/examples/nextjs-bun.mdx b/docs/template/examples/nextjs-bun.mdx index 921a693..36ea65a 100644 --- a/docs/template/examples/nextjs-bun.mdx +++ b/docs/template/examples/nextjs-bun.mdx @@ -53,8 +53,7 @@ template = ( import { Template, defaultBuildLogger } from 'e2b' import { template as nextJSTemplate } from './template' -Template.build(nextJSTemplate, { - alias: 'nextjs-app-bun', +Template.build(nextJSTemplate, 'nextjs-app-bun', { cpuCount: 4, memoryMB: 4096, onBuildLogs: defaultBuildLogger(), @@ -66,8 +65,7 @@ Template.build(nextJSTemplate, { from e2b import Template, default_build_logger from .template import template as nextjsTemplate -Template.build(nextjsTemplate, - alias="nextjs-app-bun", +Template.build(nextjsTemplate, 'nextjs-app-bun', cpu_count=4, memory_mb=4096, on_build_logs=default_build_logger(), diff --git a/docs/template/examples/nextjs.mdx b/docs/template/examples/nextjs.mdx index 0cb350a..eb175bb 100644 --- a/docs/template/examples/nextjs.mdx +++ b/docs/template/examples/nextjs.mdx @@ -55,8 +55,7 @@ template = ( import { Template, defaultBuildLogger } from 'e2b' import { template as nextJSTemplate } from './template' -Template.build(nextJSTemplate, { - alias: 'nextjs-app', +Template.build(nextJSTemplate, 'nextjs-app', { cpuCount: 4, memoryMB: 4096, onBuildLogs: defaultBuildLogger(), @@ -68,8 +67,7 @@ Template.build(nextJSTemplate, { from e2b import Template, default_build_logger from .template import template as nextjsTemplate -Template.build(nextjsTemplate, - alias="nextjs-app", +Template.build(nextjsTemplate, 'nextjs-app', cpu_count=4, memory_mb=4096, on_build_logs=default_build_logger(), diff --git a/docs/template/logging.mdx b/docs/template/logging.mdx index aed0139..fd97c32 100644 --- a/docs/template/logging.mdx +++ b/docs/template/logging.mdx @@ -12,8 +12,7 @@ We provide a default logger that you can use to filter logs by level: ```typescript JavaScript & TypeScript import { Template, defaultBuildLogger } from 'e2b'; -await Template.build(template, { - alias: "my-template", +await Template.build(template, 'my-template', { onBuildLogs: defaultBuildLogger({ minLevel: "info", // Minimum log level to show }), @@ -25,7 +24,7 @@ from e2b import Template, default_build_logger Template.build( template, - alias="my-template", + 'my-template', on_build_logs=default_build_logger( min_level="info", # Minimum log level to show ) @@ -68,14 +67,14 @@ def custom_logger(log_entry): time = log_entry.timestamp.isoformat() print(f"[{time}] {log_entry.level.upper()}: {log_entry.message}") -Template.build(template, alias="my-template", on_build_logs=custom_logger) +Template.build(template, 'my-template', on_build_logs=custom_logger) # Filter by log level def error_logger(log_entry): if log_entry.level in ["error", "warn"]: print(f"ERROR/WARNING: {log_entry}", file=sys.stderr) -Template.build(template, alias="my-template", on_build_logs=error_logger) +Template.build(template, 'my-template', on_build_logs=error_logger) ``` diff --git a/docs/template/aliases.mdx b/docs/template/names.mdx similarity index 51% rename from docs/template/aliases.mdx rename to docs/template/names.mdx index cb13c8b..966af7a 100644 --- a/docs/template/aliases.mdx +++ b/docs/template/names.mdx @@ -1,39 +1,38 @@ --- -title: "Template Aliases" -sidebarTitle: "Aliases" -description: "Understanding and managing template aliases" +title: "Template Names" +sidebarTitle: "Names" +description: "Understanding and managing template names" --- -Template aliases are unique identifiers used to reference and create sandboxes from your templates. They serve as human-readable names that make it easy to identify and use your templates across your applications. +Template names are unique identifiers used to reference and create sandboxes from your templates. They serve as human-readable names that make it easy to identify and use your templates across your applications. -## What is a Template Alias? +## What is a Template Name? -An alias is a string identifier that you assign to a template when building it. Once a template is built with an alias, you can use that alias to create sandboxes from the template. +A name is a string identifier that you assign to a template when building it. Once a template is built with a name, you can use that name to create sandboxes from the template. ```typescript JavaScript & TypeScript -// Build a template with an alias -await Template.build(template, { - alias: 'my-python-env', +// Build a template with a name +await Template.build(template, 'my-python-env', { cpuCount: 2, memoryMB: 2048, }) -// Create a sandbox using the alias +// Create a sandbox using the name const sandbox = await Sandbox.create('my-python-env') ``` ```python Python -# Build a template with an alias +# Build a template with a name Template.build( template, - alias='my-python-env', + 'my-python-env', cpu_count=2, memory_mb=2048, ) -# Create a sandbox using the alias +# Create a sandbox using the name sandbox = Sandbox(template='my-python-env') ``` @@ -42,10 +41,10 @@ sandbox = Sandbox(template='my-python-env') ## Uniqueness Requirement -Template aliases must be **globally unique across the entire E2B platform**, not just within your team or account. This means if another user has already claimed an alias, you cannot use it for your template. +Template names must be **globally unique across the entire E2B platform**, not just within your team or account. This means if another user has already claimed a name, you cannot use it for your template. -When choosing an alias, consider using: +When choosing a name, consider using: - Your company or project name as a prefix (e.g., `acme-api-server`) - Version numbers or environment indicators (e.g., `myapp-v2`, `myapp-staging`) - Descriptive names that indicate the template's purpose (e.g., `data-analysis-python`) @@ -54,21 +53,19 @@ When choosing an alias, consider using: ### Development and Production Environments -Use different aliases for different environments: +Use different names for different environments: ```typescript JavaScript & TypeScript // Development template -await Template.build(template, { - alias: 'myapp-dev', +await Template.build(template, 'myapp-dev', { cpuCount: 1, memoryMB: 1024, }) // Production template -await Template.build(template, { - alias: 'myapp-prod', +await Template.build(template, 'myapp-prod', { cpuCount: 4, memoryMB: 4096, }) @@ -78,7 +75,7 @@ await Template.build(template, { # Development template Template.build( template, - alias='myapp-dev', + 'myapp-dev', cpu_count=1, memory_mb=1024, ) @@ -86,7 +83,7 @@ Template.build( # Production template Template.build( template, - alias='myapp-prod', + 'myapp-prod', cpu_count=4, memory_mb=4096, ) @@ -102,15 +99,13 @@ Create different variants of the same template with different configurations: ```typescript JavaScript & TypeScript // Small instance -await Template.build(template, { - alias: 'myapp-small', +await Template.build(template, 'myapp-small', { cpuCount: 1, memoryMB: 512, }) // Large instance -await Template.build(template, { - alias: 'myapp-large', +await Template.build(template, 'myapp-large', { cpuCount: 8, memoryMB: 16384, }) @@ -120,7 +115,7 @@ await Template.build(template, { # Small instance Template.build( template, - alias='myapp-small', + 'myapp-small', cpu_count=1, memory_mb=512, ) @@ -128,7 +123,7 @@ Template.build( # Large instance Template.build( template, - alias='myapp-large', + 'myapp-large', cpu_count=8, memory_mb=16384, ) @@ -140,9 +135,9 @@ Template.build( When building variants with the same template definition but different CPU/RAM configurations, E2B's caching system will reuse common layers, making subsequent builds much faster. -## Checking Alias Availability +## Checking Name Availability -You can check if an alias is already in use with the `aliasExists` method. +You can check if a name is already in use with the `aliasExists` method. @@ -150,28 +145,21 @@ You can check if an alias is already in use with the `aliasExists` method. import { Template } from 'e2b' const exists = await Template.aliasExists('my-template') -console.log(`Alias ${exists ? 'is taken' : 'is available'}`) +console.log(`Name ${exists ? 'is taken' : 'is available'}`) ``` ```python Python from e2b import Template exists = Template.alias_exists('my-template') -print(f"Alias {'is taken' if exists else 'is available'}") -``` - -```python Python (Async) -from e2b import AsyncTemplate - -exists = await AsyncTemplate.alias_exists('my-template') -print(f"Alias {'is taken' if exists else 'is available'}") +print(f"Name {'is taken' if exists else 'is available'}") ``` ## Best Practices -1. **Use descriptive names**: Choose aliases that clearly indicate the template's purpose or configuration -2. **Include versioning**: Consider adding version numbers to your aliases for better version management (e.g., `myapp-v1`, `myapp-v2`) +1. **Use descriptive names**: Choose names that clearly indicate the template's purpose or configuration +2. **Include versioning**: Consider adding version numbers to your names for better version management (e.g., `myapp-v1`, `myapp-v2`) 3. **Use consistent naming**: Establish a naming convention for your team and stick to it -4. **Document your aliases**: Keep a record of which aliases are used for which purposes in your team +4. **Document your names**: Keep a record of which names are used for which purposes in your team diff --git a/docs/template/quickstart.mdx b/docs/template/quickstart.mdx index 6397d32..e6c6061 100644 --- a/docs/template/quickstart.mdx +++ b/docs/template/quickstart.mdx @@ -104,8 +104,7 @@ import { Template, defaultBuildLogger } from 'e2b'; import { template } from './template'; async function main() { - await Template.build(template, { - alias: "template-tag-dev", + await Template.build(template, 'template-tag-dev', { cpuCount: 1, memoryMB: 1024, onBuildLogs: defaultBuildLogger(), @@ -126,7 +125,7 @@ load_dotenv() if __name__ == '__main__': Template.build( template, - alias="template-tag-dev", + 'template-tag-dev', cpu_count=1, memory_mb=1024, on_build_logs=default_build_logger(), @@ -146,8 +145,7 @@ import { Template, defaultBuildLogger } from 'e2b'; import { template } from './template'; async function main() { - await Template.build(template, { - alias: "template-tag", + await Template.build(template, 'template-tag', { cpuCount: 1, memoryMB: 1024, onBuildLogs: defaultBuildLogger(), @@ -168,7 +166,7 @@ load_dotenv() if __name__ == '__main__': Template.build( template, - alias="template-tag", + 'template-tag', cpu_count=1, memory_mb=1024, on_build_logs=default_build_logger(), @@ -238,5 +236,5 @@ sbx = Sandbox(template="template-tag") -The template alias is the identifier that can be used to create a new Sandbox. +The template name is the identifier that can be used to create a new Sandbox. diff --git a/docs/template/user-and-workdir.mdx b/docs/template/user-and-workdir.mdx index 1222ddf..19ce632 100644 --- a/docs/template/user-and-workdir.mdx +++ b/docs/template/user-and-workdir.mdx @@ -45,8 +45,7 @@ const template = Template() // build_dev.ts -await Template.build(template, { - alias: "custom-user-template", +await Template.build(template, 'custom-user-template', { onBuildLogs: defaultBuildLogger() }) @@ -71,8 +70,7 @@ template = ( # build_dev.py -Template.build(template, - alias="custom-user-template", +Template.build(template, 'custom-user-template', on_build_logs=default_build_logger() ) diff --git a/docs/template/versioning.mdx b/docs/template/versioning.mdx new file mode 100644 index 0000000..3a37920 --- /dev/null +++ b/docs/template/versioning.mdx @@ -0,0 +1,247 @@ +--- +title: "Template Versioning" +sidebarTitle: "Versioning" +description: "Version your templates using tags for environment-based deployments" +--- + +Template versioning allows you to maintain multiple versions of the same template using tags. This enables workflows like semantic versioning, environment-based deployments, and gradual rollouts. + +## Tag Format + +Tags follow the `name:tag` format, where `name` is your template's unique identifier and `tag` is the version label. + +``` +my-template:v1.0.0 +my-template:production +my-template:latest +``` + +## The Default Tag + +When you build or reference a template without specifying a tag, E2B uses the `default` tag automatically. This means: + +- `my-template` is equivalent to `my-template:default` +- Existing templates without tags continue to work seamlessly + + + +```typescript JavaScript & TypeScript +// These are equivalent +const sandbox1 = await Sandbox.create('my-template') +const sandbox2 = await Sandbox.create('my-template:default') +``` + +```python Python +# These are equivalent +sandbox1 = Sandbox('my-template') +sandbox2 = Sandbox('my-template:default') +``` + + + +## Building with Tags + +You can build templates with one or more tags to create versioned builds. + +### Single Tag + + + +```typescript JavaScript & TypeScript +import { Template } from 'e2b' + +// Build with a specific version tag +await Template.build(template, 'my-template:v1.0.0') +``` + +```python Python +from e2b import Template + +# Build with a specific version tag +Template.build(template, 'my-template:v1.0.0') +``` + + + +### Multiple Tags + +Build with multiple tags to assign several version labels to the same build artifact. + + + +```typescript JavaScript & TypeScript +import { Template } from 'e2b' + +// Build with multiple tags pointing to the same artifact +await Template.build(template, 'my-template', { tags: ['v1.2.0', 'latest'] }) +``` + +```python Python +from e2b import Template + +# Build with multiple tags pointing to the same artifact +Template.build(template, 'my-template', tags=['v1.2.0', 'latest']) +``` + + + + +## Managing Tags + +You can manage tags on existing template builds without rebuilding. + +### Assign Tags + +Use `assignTags` to add new tag(s) to an existing build. This is useful for promoting a tested version to production or marking a version as stable. + + + +```typescript JavaScript & TypeScript +import { Template } from 'e2b' + +// Assign a single tag +await Template.assignTags('my-template:v1.2.0', 'production') + +// Assign multiple tags at once +await Template.assignTags('my-template:v1.2.0', ['production', 'stable']) +``` + +```python Python +from e2b import Template + +# Assign a single tag +Template.assign_tags('my-template:v1.2.0', 'production') + +# Assign multiple tags at once +Template.assign_tags('my-template:v1.2.0', tags=['production', 'stable']) +``` + + + +### Remove Tags + +Use `removeTags` to remove a tag from a template. The underlying build artifact remains accessible via other tags. + + + +```typescript JavaScript & TypeScript +import { Template } from 'e2b' + +// Remove a tag +await Template.removeTags('my-template', 'staging') +``` + +```python Python +from e2b import Template + +# Remove a tag +Template.remove_tags('my-template', 'staging') +``` + + + + +Removing a tag does not delete the build artifact. Other tags pointing to the same build will continue to work. + + +## Use Cases + +### Semantic Versioning + +Use semantic version tags to track releases and enable rollbacks. + + + +```typescript JavaScript & TypeScript +// Release versions +await Template.build(template, 'api-server:v1.0.0') +await Template.build(template, 'api-server:v1.1.0') +await Template.build(template, 'api-server:v2.0.0') + +// Create sandbox from specific version +const sandbox = await Sandbox.create('api-server:v1.1.0') +``` + +```python Python +# Release versions +Template.build(template, 'api-server:v1.0.0') +Template.build(template, 'api-server:v1.1.0') +Template.build(template, 'api-server:v2.0.0') + +# Create sandbox from specific version +sandbox = Sandbox('api-server:v1.1.0') +``` + + + +### Environment Tags + +Use environment tags for deployment pipelines. + + + +```typescript JavaScript & TypeScript +// Build new version +await Template.build(template, 'my-app:v1.5.0') + +// Promote through environments +await Template.assignTags('my-app:v1.5.0', 'staging') + +// After testing, promote to production +await Template.assignTags('my-app:v1.5.0', 'production') + +// Use in your application +const env = process.env.NODE_ENV +const sandbox = await Sandbox.create(`my-app:${env}`) +``` + +```python Python +import os + +# Build new version +Template.build(template, 'my-app:v1.5.0') + +# Promote through environments +Template.assign_tags('my-app:v1.5.0', 'staging') + +# After testing, promote to production +Template.assign_tags('my-app:v1.5.0', 'production') + +# Use in your application +env = os.environ.get('ENV', 'staging') +sandbox = Sandbox(f'my-app:{env}') +``` + + + +### Latest and Stable Tags + +Maintain rolling tags that always point to specific versions. + + + +```typescript JavaScript & TypeScript +// Build with version and latest tag +await Template.build(template, 'my-tool', { tags: ['v3.0.0', 'latest'] }) + +// Mark a tested version as stable +await Template.assignTags('my-tool:v2.9.0', 'stable') + +// You can choose your risk tolerance +const latestSandbox = await Sandbox.create('my-tool:latest') // Newest +const stableSandbox = await Sandbox.create('my-tool:stable') // Tested +``` + +```python Python +# Build with version and latest tag +Template.build(template, 'my-tool', tags=['v3.0.0', 'latest']) + +# Mark a tested version as stable +Template.assign_tags('my-tool:v2.9.0', 'stable') + +# You can choose your risk tolerance +latest_sandbox = Sandbox('my-tool:latest') # Newest +stable_sandbox = Sandbox('my-tool:stable') # Tested +``` + +