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
gitBrancheskey inwmill.yaml. - Single-branch — one git branch, environments are defined explicitly. Use the
environmentskey inwmill.yamland the--envCLI 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.yaml→u/alex/database.prod.resource.yamlu/alex/orders.kafka_trigger.yaml→u/alex/orders.prod.kafka_trigger.yamlf/env_staging/folder.meta.yaml→f/env_staging/folder.prod.meta.yamlsettings.yaml→settings.prod.yaml
Push (local → Windmill workspace):
u/alex/database.dev.resource.yaml→u/alex/database.resource.yamlu/alex/orders.dev.kafka_trigger.yaml→u/alex/orders.kafka_trigger.yamlf/env_staging/folder.dev.meta.yaml→f/env_staging/folder.meta.yamlsettings.dev.yaml→settings.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.yamland 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.yamlfiles 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 segmentsu/alex/database_*matchesu/alex/database_config,u/alex/database_url, etc.f/environments/**matches all files underf/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
commonSpecificItemsfor 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
- Check patterns: Ensure your glob patterns match the file paths exactly
- Verify file types: Only variables, resources, resource files, and trigger files are supported
- Pattern testing: Use tools like globster.xyz to test your patterns
Files syncing to the wrong workspace
- Check config: Ensure your environment configuration is correct
- Verify current context: Make sure you're on the expected git branch or using the right
--envflag - 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_repositorypointing torepoXonprodbranch- Changes to
database.resource.yaml→ pushes todatabase.prod.resource.yaml
- Changes to
- Development workspace:
git_repositorypointing torepoXondevbranch- Changes to
database.resource.yaml→ pushes todatabase.dev.resource.yaml
- Changes to
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.
Related documentation
- CLI sync - Main sync operations and configuration
- Git sync settings - Managing sync configuration
- Git sync - Backend Git integration