Multi-Environment Management Quick Start

1. Installation and Setup

The which_env library provides intelligent environment detection for multi-environment deployment strategies. Let’s start by importing the necessary components.

[1]:
import os
from which_runtime.api import runtime
from which_env.api import (
    BaseEnvNameEnum,
    CommonEnvNameEnum,
    detect_current_env,
    validate_env_name,
    EnvNameValidationError,
    USER_ENV_NAME,
    ENV_NAME
)

2. Understanding Environment Validation

Environment names must follow specific naming conventions for consistency and safety. Let’s explore the validation rules.

[3]:
valid_names = [
    # valid names
    "dev", "prod", "staging", "test1", "sbx123",
    # invalid names
    "Dev", "prod-1", "1test", "test_env", "dev.staging",
]

print("Testing valid environment names:")
for name in valid_names:
    try:
        validate_env_name(name)
        print(f"✅ '{name}' - Valid")
    except EnvNameValidationError as e:
        print(f"❌ '{name}' - {e}")
Testing valid environment names:
✅ 'dev' - Valid
✅ 'prod' - Valid
✅ 'staging' - Valid
✅ 'test1' - Valid
✅ 'sbx123' - Valid
❌ 'Dev' - 'Dev' is an invalid env name, first letter of env_name has to be a-z!
❌ 'prod-1' - 'prod-1' is an invalid env name, env_name can only has a-z, 0-9
❌ '1test' - '1test' is an invalid env name, first letter of env_name has to be a-z!
❌ 'test_env' - 'test_env' is an invalid env name, env_name can only has a-z, 0-9
❌ 'dev.staging' - 'dev.staging' is an invalid env name, env_name can only has a-z, 0-9

3. Working with Common Environment Names

The library provides predefined common environment names with emoji representations for better visualization.

[7]:
# Explore all common environment names
print("Common Environment Names:")
print("=" * 40)

for env in CommonEnvNameEnum:
    print(f"{env.value}")
Common Environment Names:
========================================
devops
sbx
dev
tst
stg
qa
preprd
prd

4. Creating Custom Environment Enumerations

Create your own environment enumeration by inheriting from BaseEnvNameEnum. Every custom enumeration must include at least ‘devops’, ‘dev’, and ‘prd’ environments.

[11]:
class MyProjectEnv(BaseEnvNameEnum):
    """Custom environment enumeration for MyProject."""
    devops = "devops"  # Required: CI/CD environment
    sbx = "sbx"        # Optional: Sandbox environment that can be destroy or recreat
    dev = "dev"        # Required: Development environment
    tst = "tst"        # Optional: Testing environment
    stg = "stg"        # Optional: Staging environment
    prd = "prd"        # Required: Production environment
[12]:
MyProjectEnv.validate()
print("✅ MyProjectEnv validation passed!")
✅ MyProjectEnv validation passed!
[13]:
print("\nMyProject Environments:")
for env in MyProjectEnv:
    print(f"{env.emoji} {env.value} ({env.name.upper()})")

MyProject Environments:
🛠 devops (DEVOPS)
🧰 sbx (SBX)
💻 dev (DEV)
🧪 tst (TST)
🎸 stg (STG)
🏭 prd (PRD)

5. Environment Detection in Different Runtime Contexts

The detect_current_env function intelligently detects the current environment based on runtime context and environment variables.

[14]:
# Clean up any existing environment variables for demo
if USER_ENV_NAME in os.environ:
    del os.environ[USER_ENV_NAME]
if ENV_NAME in os.environ:
    del os.environ[ENV_NAME]
[15]:
# Scenario 1: Default behavior (typically returns 'dev' for local development)
print("Scenario 1: Default environment detection")
current_env = detect_current_env(runtime, MyProjectEnv)
print(f"Detected environment: {current_env}")
print(f"Environment emoji: {getattr(MyProjectEnv, current_env).emoji}")

print("\n" + "="*50)
Scenario 1: Default environment detection
Detected environment: dev
Environment emoji: 💻

==================================================
[16]:
# Scenario 2: Using USER_ENV_NAME override
print("Scenario 2: User environment override")
os.environ[USER_ENV_NAME] = "tst"
current_env = detect_current_env(runtime, MyProjectEnv)
print(f"USER_ENV_NAME set to: {os.environ[USER_ENV_NAME]}")
print(f"Detected environment: {current_env}")
print(f"Environment emoji: {getattr(MyProjectEnv, current_env).emoji}")

# Clean up
del os.environ[USER_ENV_NAME]
Scenario 2: User environment override
USER_ENV_NAME set to: tst
Detected environment: tst
Environment emoji: 🧪
[ ]: