Skip to main content

Environment-specific items

Environment-specific items allow you to have different versions of resources and variables per environment/branch (dev/staging/prod). The CLI automatically transforms file paths so that each environment gets its own namespaced files locally while maintaining clean base paths in the Windmill workspace.

How it works

When a file matches a pattern in your wmill.yaml configuration, the CLI inserts the environment name into the local file path:

  • Local files: database.dev.resource.yaml, database.prod.resource.yaml
  • Windmill workspace: database.resource.yaml (clean base path)

This lets each environment have its own configuration for the same logical resource. In practice, multiple environment files usually end up coexisting in the repository (e.g. database.dev.resource.yaml and database.prod.resource.yaml side by side) — by design in single-branch setups, or as a result of merging branches in multi-branch setups. The CLI only reads the files matching the current environment and ignores the others.

Two workflows are supported to define environments:

  • Multi-branch — each git branch is an environment, detected automatically. Use the gitBranches key in wmill.yaml.
  • Single-branch — one git branch, environments are defined explicitly. Use the environments key in wmill.yaml and the --env CLI flag.

Both use the same path-transformation logic — only the configuration key differs.

Multi-branch setup

Each git branch maps to an environment (e.g. main → production, dev → development). The CLI detects the current branch automatically.

Configuration

gitBranches:
main:
specificItems:
resources:
- "u/alex/config/**"
variables:
- "u/alex/env_*"
triggers:
- "u/alex/kafka_*"
folders:
- "f/env_*"
settings: true
overrides:
skipSecrets: false

dev:
specificItems:
resources:
- "u/alex/config/**"
variables:
- "u/alex/env_*"
triggers:
- "u/alex/kafka_*"
folders:
- "f/env_*"
settings: true
overrides:
skipSecrets: true

Usage

The CLI automatically detects the current git branch and applies the matching configuration.

git checkout main
wmill sync pull
# Creates: u/alex/config/database.main.resource.yaml

git checkout dev
wmill sync pull
# Creates: u/alex/config/database.dev.resource.yaml

You can override the detected branch with --branch (e.g. wmill sync pull --branch main).

Single-branch setup

All environments are managed from a single git branch. You select the target environment with --env.

Configuration

Use the environments key in wmill.yaml:

environments:
dev:
specificItems:
resources:
- "u/alex/config/**"
variables:
- "u/alex/env_*"
triggers:
- "u/alex/kafka_*"
folders:
- "f/env_*"
settings: true
overrides:
skipSecrets: true

staging:
specificItems:
resources:
- "u/alex/config/**"
variables:
- "u/alex/env_*"
folders:
- "f/env_*"
settings: true

prod:
specificItems:
resources:
- "u/alex/config/**"
variables:
- "u/alex/env_*"
folders:
- "f/env_*"
settings: true
overrides:
skipSecrets: false

Usage

wmill sync pull --env dev
# Creates: u/alex/config/database.dev.resource.yaml

wmill sync pull --env prod
# Creates: u/alex/config/database.prod.resource.yaml

wmill sync push --env staging

No git checkout is needed — all environment-specific files coexist on the same branch.

File path transformation

Transform logic

Pull (Windmill workspace → local):

  • u/alex/database.resource.yamlu/alex/database.prod.resource.yaml
  • u/alex/orders.kafka_trigger.yamlu/alex/orders.prod.kafka_trigger.yaml
  • f/env_staging/folder.meta.yamlf/env_staging/folder.prod.meta.yaml
  • settings.yamlsettings.prod.yaml

Push (local → Windmill workspace):

  • u/alex/database.dev.resource.yamlu/alex/database.resource.yaml
  • u/alex/orders.dev.kafka_trigger.yamlu/alex/orders.kafka_trigger.yaml
  • f/env_staging/folder.dev.meta.yamlf/env_staging/folder.meta.yaml
  • settings.dev.yamlsettings.yaml

Resource files

Resources can include associated files (certificates, config files, etc.) alongside their YAML definitions. These follow the same transformation:

  • Base file: u/alex/certificate.resource.file.pem
  • Environment-specific: u/alex/certificate.dev.resource.file.pem

When a resource YAML file is marked as environment-specific, all associated resource files are automatically treated the same way.

Supported file types

  • Variables: *.variable.yaml
  • Resources: *.resource.yaml and resource files (*.resource.file.*)
  • Triggers: *.kafka_trigger.yaml, *.http_trigger.yaml, *.websocket_trigger.yaml, *.nats_trigger.yaml, *.postgres_trigger.yaml, *.mqtt_trigger.yaml, *.sqs_trigger.yaml, *.gcp_trigger.yaml
  • Folders: folder.meta.yaml files within folder directories
  • Settings: settings.yaml (workspace settings file)

Pattern matching

Patterns support standard glob syntax:

  • * matches any characters within a path segment
  • ** matches any characters across path segments
  • u/alex/database_* matches u/alex/database_config, u/alex/database_url, etc.
  • f/environments/** matches all files under f/environments/ recursively

Common specific items

Items that should be environment-specific across all environments can be defined with commonSpecificItems:

# Inside gitBranches or environments
commonSpecificItems:
variables:
- "u/alex/database_*"
- "f/config/**"
resources:
- "u/alex/api_keys/**"
- "f/environments/**"
triggers:
- "u/alex/kafka_*"
- "f/streaming/**"
folders:
- "f/env_*"
settings: true

Per-environment specific items

If some resources only exist in certain environments, you can define different patterns per environment instead of using commonSpecificItems:

# Inside gitBranches or environments
prod:
specificItems:
variables:
- "u/alex/prod_*"
resources:
- "u/alex/production/**"
triggers:
- "u/alex/prod_kafka_*"
folders:
- "f/prod_config"
settings: true

dev:
specificItems:
variables:
- "u/alex/dev_*"
resources:
- "u/alex/development/**"
triggers:
- "u/alex/dev_kafka_*"
folders:
- "f/dev_config"
settings: true

Here, prod_kafka_* triggers only get the environment suffix on prod — they don't exist in dev, so there's no need to mark them there. Most setups use commonSpecificItems since the same resources typically exist across all environments.

Name safety

Environment and branch names containing certain characters are automatically sanitized for filesystem safety:

  • Unsafe characters: / \ : * ? " < > | .
  • Replacement: All unsafe characters are replaced with _
  • Warning: The CLI shows a clear warning when sanitization occurs
Warning: Branch name "feature/api-v2.1" contains filesystem-unsafe characters (/ \ : * ? " < > | .)
and was sanitized to "feature_api-v2_1". This may cause collisions with other similarly named branches.

Best practices

  • Start broad: Use commonSpecificItems for widely-used resources
  • Be specific: Target exact paths rather than overly broad patterns
  • Group logically: Organize patterns by team, environment, or function
  • Define patterns early: Establish patterns before team members start using them
  • Test locally: Verify environment-specific behavior works correctly before CI/CD integration

Troubleshooting

Files not being detected as environment-specific

  1. Check patterns: Ensure your glob patterns match the file paths exactly
  2. Verify file types: Only variables, resources, resource files, and trigger files are supported
  3. Pattern testing: Use tools like globster.xyz to test your patterns

Files syncing to the wrong workspace

  1. Check config: Ensure your environment configuration is correct
  2. Verify current context: Make sure you're on the expected git branch or using the right --env flag
  3. Configuration precedence: CLI flags override configuration file settings

Git sync integration

When Git sync is configured, environment-specific items work seamlessly with your Git repository setup. Git sync will automatically push changes to the correct environment-specific files based on the repository configuration.

Multi-branch: each workspace's git_repository resource points to a different branch. Git sync detects the branch and applies the matching gitBranches configuration automatically.

  • Production workspace: git_repository pointing to repoX on prod branch
    • Changes to database.resource.yaml → pushes to database.prod.resource.yaml
  • Development workspace: git_repository pointing to repoX on dev branch
    • Changes to database.resource.yaml → pushes to database.dev.resource.yaml

Single-branch: all workspaces point to the same branch. Set the environment name in the Git sync advanced settings so that Git sync applies the matching environments configuration.