Skip to content

Support setting env vars at deploy time (miren deploy -e/-s)#521

Merged
phinze merged 1 commit intomainfrom
phinze/mir-606-support-setting-env-vars-at-deploy-time-miren-deploy-e-s
Jan 7, 2026
Merged

Support setting env vars at deploy time (miren deploy -e/-s)#521
phinze merged 1 commit intomainfrom
phinze/mir-606-support-setting-env-vars-at-deploy-time-miren-deploy-e-s

Conversation

@phinze
Copy link
Contributor

@phinze phinze commented Jan 7, 2026

Summary

Add -e and -s flags to miren deploy for setting environment variables atomically with the deploy. This ensures env vars are available to the very first sandbox, solving ordering issues where apps need env vars present at initial startup.

Example use case: Grafana's GF_SECURITY_ADMIN_PASSWORD must be set before the first DB creation - setting it after deploy is too late.

Syntax

miren deploy -e KEY=VALUE        # Regular env var
miren deploy -s SECRET=value     # Sensitive (masked in output)
miren deploy -e KEY=@file        # Read value from file
miren deploy -e KEY              # Prompt interactively

# Multiple vars
miren deploy -e FOO=bar -e BAZ=qux -s API_KEY=secret

Implementation

  • Extends buildFromTar RPC to accept envVars parameter
  • Adds mergeCliEnvVars() helper that applies CLI vars with source="manual"
  • CLI vars merged last in buildVersionConfig() (highest precedence)
  • Creates single atomic AppVersion with merged config (no intermediate versions)

Merge order:

  1. Existing config from previous version
  2. app.toml vars (source="config")
  3. CLI vars (source="manual") - always wins

Test plan

  • Unit tests for ParseEnvVarSpecs() (KEY=VALUE, KEY=@file, errors)
  • Unit tests for mergeCliEnvVars() (override, merge, sensitive flag)
  • Manual test: miren deploy -e FOO=bar sets env var on first sandbox
  • Manual test: miren deploy -s SECRET=x masks value in output
  • Manual test: env vars persist across redeploys

Summary by CodeRabbit

  • New Features

    • Environment variables can now be passed during deployments.
    • Sensitive environment variables are supported for secure handling.
    • CLI-provided environment variables override existing configuration settings.
  • Tests

    • Added tests for environment variable parsing and merging.

✏️ Tip: You can customize this high-level summary in your review settings.

Add -e and -s flags to `miren deploy` for setting environment variables
atomically with the deploy. This ensures env vars are available to the
very first sandbox, solving ordering issues where apps need env vars
present at initial startup (e.g., Grafana's GF_SECURITY_ADMIN_PASSWORD).

Syntax:
  miren deploy -e KEY=VALUE        # Regular env var
  miren deploy -s SECRET=value     # Sensitive (masked in output)
  miren deploy -e KEY=@file        # Read value from file
  miren deploy -e KEY              # Prompt interactively

Implementation:
- Add EnvironmentVariable type and envVars param to buildFromTar RPC
- Add mergeCliEnvVars() that applies CLI vars with source="manual"
- CLI vars are merged last in buildVersionConfig() (highest precedence)
- Single atomic AppVersion created with merged config

The merge order ensures CLI vars always win:
1. Start with existing config from previous version
2. Layer in app.toml vars (source="config")
3. Layer in CLI vars (source="manual")

Closes MIR-606
@coderabbitai
Copy link

coderabbitai bot commented Jan 7, 2026

📝 Walkthrough

Walkthrough

This change introduces environment variable support across the deployment pipeline. New types define environment variables in the RPC layer, CLI parsing logic converts flag inputs to structured types, and server-side code merges CLI-provided variables with highest precedence over existing configuration variables.

Changes

Cohort / File(s) Summary
RPC API & Type Definitions
api/build/build_v1alpha/rpc.gen.go, api/build/rpc.yml
New EnvironmentVariable type with Key, Value, and Sensitive fields; CBOR/JSON serialization methods. BuildFromTar API signature updated to accept envVars []*EnvironmentVariable parameter; corresponding accessor methods on BuilderBuildFromTarArgs.
CLI Parsing & Command Integration
cli/commands/env.go, cli/commands/deploy.go
New EnvVarSpec type and ParseEnvVarSpecs() function to parse -e and -s flag inputs; supports KEY=VALUE and KEY=@file formats with validation. Deploy command struct gains Env and Sensitive fields; all BuildFromTar call sites (explainer, interactive, non-interactive) updated to pass parsed environment variables.
CLI Test Coverage
cli/commands/env_test.go
New TestParseEnvVarSpecs with subtests covering KEY=VALUE pairs, sensitive variable marking, file-backed values (@file), error cases (missing files, empty keys), and edge cases (equals signs in values, empty values).
Server-Side Environment Variable Merging
servers/build/build.go, servers/build/build_test.go
New mergeCliEnvVars() function to merge CLI-provided variables with highest precedence, marking them as source=manual. ConfigInputs struct gains CliEnvVars field; buildVersionConfig and BuildFromTar updated to apply CLI vars after config vars. Test helper makeEnvVar() and TestMergeCliEnvVars validate merging logic, precedence handling, and sensitive flag preservation.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI as CLI<br/>(deploy.go)
    participant Parser as CLI<br/>(env.go)
    participant RPC as RPC Client
    participant Server as Build Server<br/>(build.go)
    participant Config as Config Merge

    User->>CLI: deploy with -e KEY=VALUE -s SENSITIVE=val
    CLI->>Parser: ParseEnvVarSpecs(envSpecs, sensitiveSpecs)
    Parser-->>CLI: []EnvVarSpec (parsed & validated)
    note over Parser: Handles KEY=VALUE, KEY=@file<br/>file reads, validation
    
    CLI->>RPC: BuildFromTar(..., envVars []*EnvironmentVariable)
    note over CLI: Convert EnvVarSpec → EnvironmentVariable
    
    RPC->>Server: Receive envVars parameter
    Server->>Server: args.EnvVars() retrieves CLI vars
    Server->>Config: mergeCliEnvVars(existingVars, cliVars)
    note over Config: CLI vars get highest precedence<br/>marked source="manual"
    
    Config-->>Server: merged variables
    Server->>Server: buildVersionConfig applies merged vars
    note over Server: Final config includes CLI vars
    Server-->>RPC: BuildFromTarResults
    RPC-->>CLI: Success with applied env vars
    CLI-->>User: Deploy complete
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @api/build/build_v1alpha/rpc.gen.go:
- Around line 758-764: BuilderBuildFromTarArgs.EnvVars() currently dereferences
v.data.EnvVars and can panic when nil; change the accessor to match other slice
accessors by returning the pointer (i.e., return v.data.EnvVars) or otherwise
guard the dereference (check v.data.EnvVars != nil and return nil or empty
slice). Update the code generator or the RPC schema (api/build/rpc.yml) so
generated code for EnvVars uses the same pointer-return pattern as
Services()/Hostnames(), and regenerate the file so HasEnvVars() remains the
nil-check while EnvVars() does not dereference the pointer.
🧹 Nitpick comments (1)
cli/commands/env.go (1)

18-20: Consider renaming FromFile_ to a more descriptive name.

The trailing underscore in FromFile_ is unconventional for Go. Consider renaming to SourceFile or SourceFilename for clarity and to better distinguish it from the boolean FromFile field.

♻️ Suggested rename
 type EnvVarSpec struct {
 	Key       string
 	Value     string
 	Sensitive bool
-	FromFile  bool   // true if value was read from a file
-	FromFile_ string // original filename if FromFile is true
+	FromFile       bool   // true if value was read from a file
+	SourceFilename string // original filename if FromFile is true
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 91909be and 02fdbaa.

📒 Files selected for processing (7)
  • api/build/build_v1alpha/rpc.gen.go
  • api/build/rpc.yml
  • cli/commands/deploy.go
  • cli/commands/env.go
  • cli/commands/env_test.go
  • servers/build/build.go
  • servers/build/build_test.go
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.go: Follow standard Go formatting conventions
Only add comments when they provide valuable context or explain 'why' something is done - avoid redundant comments that restate what the code does
Good comments should explain complex logic, document assumptions, or clarify non-obvious behavior rather than restating the code
Function/method comments should explain the purpose and any important side effects, not just restate the function name

Files:

  • cli/commands/env_test.go
  • servers/build/build_test.go
  • servers/build/build.go
  • cli/commands/env.go
  • api/build/build_v1alpha/rpc.gen.go
  • cli/commands/deploy.go
**/*.gen.go

📄 CodeRabbit inference engine (CLAUDE.md)

Code generation outputs for entity schemas and RPC interfaces should have .gen.go suffix

Files:

  • api/build/build_v1alpha/rpc.gen.go
🧠 Learnings (1)
📚 Learning: 2025-12-15T17:54:35.854Z
Learnt from: phinze
Repo: mirendev/runtime PR: 478
File: cli/commands/debug_netdb.go:155-156
Timestamp: 2025-12-15T17:54:35.854Z
Learning: In reviews of Go CLI commands under cli/commands (mirendev/runtime), prefer validating inputs on the server side and skip duplicating client-side validation when the CLI is the only client. This avoids code duplication and keeps validation centralized. If local validation is absolutely necessary for UX, keep it slim and clearly justified, and ensure it does not duplicate server logic. Document the rationale and ensure server API validation remains the source of truth.

Applied to files:

  • cli/commands/env_test.go
  • cli/commands/env.go
  • cli/commands/deploy.go
🧬 Code graph analysis (4)
cli/commands/env_test.go (1)
cli/commands/env.go (1)
  • ParseEnvVarSpecs (25-47)
servers/build/build_test.go (3)
api/build/build_v1alpha/rpc.gen.go (1)
  • EnvironmentVariable (483-485)
api/core/core_v1alpha/schema.gen.go (1)
  • Variable (705-710)
api/compute/compute_v1alpha/schema.gen.go (1)
  • Key (1936-1939)
servers/build/build.go (2)
api/build/build_v1alpha/rpc.gen.go (1)
  • EnvironmentVariable (483-485)
api/core/core_v1alpha/schema.gen.go (1)
  • Variable (705-710)
cli/commands/deploy.go (3)
api/core/core_v1alpha/schema.gen.go (1)
  • Env (571-576)
api/build/build_v1alpha/rpc.gen.go (1)
  • EnvironmentVariable (483-485)
cli/commands/env.go (1)
  • ParseEnvVarSpecs (25-47)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-binaries (darwin, amd64, macos-latest)
  • GitHub Check: lint
  • GitHub Check: build-binaries (darwin, arm64, macos-latest)
  • GitHub Check: test-e2e
  • GitHub Check: test
🔇 Additional comments (6)
cli/commands/env_test.go (1)

9-119: Test coverage looks good.

The test function comprehensively covers various parsing scenarios including edge cases and error conditions. The use of t.TempDir() for temporary file handling is clean and appropriate.

cli/commands/env.go (3)

23-47: LGTM!

The parsing logic correctly processes both regular and sensitive env var specs, with proper error propagation.


49-101: LGTM!

The parsing handles all three formats (KEY, KEY=VALUE, KEY=@file) correctly. Error handling for file operations and empty keys is appropriate.


103-148: LGTM!

The refactored EnvSet cleanly delegates parsing to ParseEnvVarSpecs and handles all cases appropriately, including sensitive variable masking in logs.

api/build/build_v1alpha/rpc.gen.go (2)

477-546: LGTM!

The EnvironmentVariable type follows the established patterns in this generated file with proper accessors and serialization methods.


1013-1037: LGTM!

The BuildFromTar client method correctly includes the new envVars parameter and wires it to the RPC arguments.

@phinze phinze marked this pull request as ready for review January 7, 2026 23:03
@phinze phinze requested a review from a team as a code owner January 7, 2026 23:03
@phinze phinze merged commit 7c74b2c into main Jan 7, 2026
9 checks passed
@phinze phinze deleted the phinze/mir-606-support-setting-env-vars-at-deploy-time-miren-deploy-e-s branch January 7, 2026 23:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants