Environment Variables
Set environment variables directly in your invkfile. These are available to your scripts during execution.
Basic Usage
{
name: "build"
env: {
vars: {
NODE_ENV: "production"
API_URL: "https://api.example.com"
DEBUG: "false"
}
}
implementations: [{
script: """
echo "Building for $NODE_ENV"
echo "API: $API_URL"
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
Variable Syntax
Variables are key-value string pairs:
vars: {
// Simple values
NAME: "value"
// Numbers (still strings in shell)
PORT: "3000"
TIMEOUT: "30"
// Boolean-like (strings "true"/"false")
DEBUG: "true"
VERBOSE: "false"
// Paths
CONFIG_PATH: "/etc/myapp/config.yaml"
OUTPUT_DIR: "./dist"
// URLs
API_URL: "https://api.example.com"
}
All values are strings. The shell interprets them as needed.
Referencing Other Variables
Reference system environment variables:
vars: {
// Use system variable
HOME_CONFIG: "${HOME}/.config/myapp"
// With default value
LOG_LEVEL: "${LOG_LEVEL:-info}"
// Combine variables
FULL_PATH: "${HOME}/projects/${PROJECT_NAME}"
}
Note: References are expanded at runtime, not definition time.
Scope Levels
Root Level
Available to all commands:
env: {
vars: {
PROJECT_NAME: "myproject"
VERSION: "1.0.0"
}
}
cmds: [
{
name: "build"
// Gets PROJECT_NAME and VERSION
implementations: [...]
},
{
name: "deploy"
// Also gets PROJECT_NAME and VERSION
implementations: [...]
}
]
Command Level
Available to specific command:
{
name: "build"
env: {
vars: {
BUILD_MODE: "release"
}
}
implementations: [...]
}
Implementation Level
Available to specific implementation:
{
name: "build"
implementations: [
{
script: "npm run build"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
env: {
vars: {
NODE_ENV: "production"
}
}
},
{
script: "go build ./..."
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
env: {
vars: {
CGO_ENABLED: "0"
}
}
}
]
}
Platform Level
Per-platform variables:
// Platform-specific env requires separate implementations
implementations: [
{
script: "echo $PLATFORM_CONFIG"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}]
env: {
vars: {
PLATFORM_CONFIG: "/etc/myapp"
PLATFORM_NAME: "Linux"
}
}
},
{
script: "echo $PLATFORM_CONFIG"
runtimes: [{name: "native"}]
platforms: [{name: "macos"}]
env: {
vars: {
PLATFORM_CONFIG: "/usr/local/etc/myapp"
PLATFORM_NAME: "macOS"
}
}
},
{
script: "echo %PLATFORM_CONFIG%"
runtimes: [{name: "native"}]
platforms: [{name: "windows"}]
env: {
vars: {
PLATFORM_CONFIG: "%APPDATA%\\myapp"
PLATFORM_NAME: "Windows"
}
}
}
]
Combined with Files
Variables override values from env files:
env: {
files: [".env"] // Loaded first
vars: {
// These override .env values
OVERRIDE: "from-invkfile"
}
}
CLI Override
Override at runtime:
# Single variable
invowk cmd build --invk-env-var NODE_ENV=development
# Multiple variables
invowk cmd build --invk-env-var NODE_ENV=dev --invk-env-var DEBUG=true --invk-env-var PORT=8080
CLI variables have the highest priority.
Real-World Examples
Build Configuration
{
name: "build"
env: {
vars: {
NODE_ENV: "production"
BUILD_TARGET: "es2020"
SOURCEMAP: "false"
}
}
implementations: [{
script: "npm run build"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}
API Configuration
{
name: "start"
env: {
vars: {
API_HOST: "0.0.0.0"
API_PORT: "3000"
API_PREFIX: "/api/v1"
CORS_ORIGIN: "*"
}
}
implementations: [{
script: "go run ./cmd/server"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}, {name: "windows"}]
}]
}
Dynamic Values
{
name: "release"
env: {
vars: {
// Git-based version
GIT_SHA: "$(git rev-parse --short HEAD)"
GIT_BRANCH: "$(git branch --show-current)"
// Timestamp
BUILD_TIME: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
// Combine values
BUILD_ID: "${GIT_BRANCH}-${GIT_SHA}"
}
}
implementations: [{
script: """
echo "Building $BUILD_ID at $BUILD_TIME"
go build -ldflags="-X main.version=$BUILD_ID" ./...
"""
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
Database Configuration
{
name: "db migrate"
env: {
vars: {
DB_HOST: "${DB_HOST:-localhost}"
DB_PORT: "${DB_PORT:-5432}"
DB_NAME: "${DB_NAME:-myapp}"
DB_USER: "${DB_USER:-postgres}"
// Construct URL from parts
DATABASE_URL: "postgres://${DB_USER}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
}
}
implementations: [{
script: "migrate -database $DATABASE_URL up"
runtimes: [{name: "native"}]
platforms: [{name: "linux"}, {name: "macos"}]
}]
}
Container Environment
Variables are passed into containers:
{
name: "build"
env: {
vars: {
GOOS: "linux"
GOARCH: "amd64"
CGO_ENABLED: "0"
}
}
implementations: [{
script: "go build -o /workspace/bin/app ./..."
runtimes: [{name: "container", image: "golang:1.21"}]
platforms: [{name: "linux"}]
}]
}
Best Practices
- Use defaults:
${VAR:-default}for optional config - Keep secrets out: Don't hardcode secrets; use env files or external secrets
- Document variables: Add comments explaining each variable
- Use consistent naming:
UPPER_SNAKE_CASEconvention - Scope appropriately: Root for shared, command for specific
Next Steps
- Env Files - Load from .env files
- Precedence - Understand override order