Taskfile, VS Code & CI¶
Practical integration patterns for projects that want dotenv-fusion to own environment resolution.
Taskfile¶
Use Taskfile as the project orchestrator and delegate environment work to dotenv-fusion. Keep imports, conditions, defaults and validation in .env-fuse; Taskfile should only call dotenv-fusion.
project/
├── .env-fuse
├── .env # generated only when another tool needs it
├── configs/
│ ├── database-dev.env
│ └── database-prod.env
└── Taskfile.yml
ENV=${ENV:-dev}
APP_NAME=myapp
#@import configs/database-${ENV}.env
API_URL=http://localhost:8000/api
Task Dependencies¶
Define one task that generates .env, then make project tasks depend on it. The app, framework, Docker command or editor integration can read .env in its usual way.
version: '3'
tasks:
env:generate:
desc: Generate .env
cmds:
- dotenv-fusion fuse -f .env-fuse {{if .ENV}}--var ENV={{.ENV}}{{end}} -o .env
dev:
desc: Run the app
deps:
- env:generate
cmds:
- uv run python app.py
test:
desc: Run tests
deps:
- env:generate
cmds:
- uv run pytest
Leave ENV unset to use the default defined in .env-fuse. Set ENV only when a task should override it. The {{if .ENV}}...{{end}} guard avoids passing an empty --var ENV=.
dotenv-fusion fuse is already the validation point: if .env-fuse is invalid, the dependency fails and the dependent task does not run.
Prefer explicit deps on tasks that consume .env. If every task in a small Taskfile needs .env, a shared wrapper can work; mixed Taskfiles are easier to read with explicit dependencies.
If the project does not install dotenv-fusion as a dev dependency, keep the same shape and replace dotenv-fusion with uvx dotenv-fusion in the task commands.
Watch¶
dotenv-fusion does not have a native --watch mode. Keep watch orchestration outside the CLI for now.
With Taskfile, watch the artifact task:
tasks:
env:generate:
desc: Generate .env
sources:
- .env-fuse
- configs/**/*.env
cmds:
- dotenv-fusion fuse -f .env-fuse {{if .ENV}}--var ENV={{.ENV}}{{end}} -o .env
Task watches the files declared in sources and reruns dotenv-fusion fuse when they change. A native dotenv-fusion --watch would be a separate CLI feature, because it would need to track source files, imports, dynamic --var values and output writes itself.
VS Code¶
VS Code reads a plain .env file. Use dotenv-fusion to generate that file directly; Taskfile is not required for this workflow.
project/
├── .env-fuse
├── .env # generated, ignored by Git
├── configs/
└── .vscode/
├── settings.json
├── tasks.json
└── launch.json
Tell VS Code and extensions to read the generated .env.
Regenerate .env before debugging with a VS Code task that calls dotenv-fusion directly.
{
"version": "2.0.0",
"tasks": [
{
"label": "dotenv-fusion: generate .env",
"type": "shell",
"command": "dotenv-fusion fuse -f .env-fuse -o .env",
"problemMatcher": []
}
]
}
{
"version": "0.2.0",
"configurations": [
{
"name": "App",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/app.py",
"envFile": "${workspaceFolder}/.env",
"preLaunchTask": "dotenv-fusion: generate .env"
}
]
}
For normal shell sessions, skip .env and load the source directly:
CI¶
Use CI variables as inputs and keep the environment logic in .env-fuse. The CI job should only validate, load, or generate the resolved environment.
Validate and Build¶
Use this when the build command can run in a shell with exported variables.
build:
variables:
ENV: production
script:
- dotenv-fusion check -f .env-fuse
- eval "$(dotenv-fusion load -f .env-fuse)"
- npm run build
jobs:
build:
runs-on: ubuntu-latest
env:
ENV: production
steps:
- uses: actions/checkout@v4
- run: dotenv-fusion check -f .env-fuse
- run: |
eval "$(dotenv-fusion load -f .env-fuse)"
npm run build
Generate .env for Tools¶
For encrypted secrets, see Docker & Compose to inject values at startup with exec or provide Compose secret files.
Use this when a CI tool needs a plain dotenv file. Docker Compose accepts the default quoted dialect:
compose:build:
variables:
ENV: production
script:
- dotenv-fusion fuse -f .env-fuse -o .env
- docker compose --env-file .env build
jobs:
compose:
runs-on: ubuntu-latest
env:
ENV: production
steps:
- uses: actions/checkout@v4
- run: dotenv-fusion fuse -f .env-fuse -o .env
- run: docker compose --env-file .env build
docker run --env-file does not remove quotes or process escapes. Generate a separate raw artifact for that command:
dotenv-fusion fuse -f .env-fuse --dialect docker -o .env.docker
docker run --env-file .env.docker my-image
The Docker dialect rejects newline characters and NUL bytes because this line-oriented format cannot represent them.
Drift Check¶
Use --diff only when .env is a committed or reviewed artifact. If .env is ignored, generate it in the job instead.
env:diff:
variables:
ENV: production
script:
- dotenv-fusion fuse -f .env-fuse -o .env --diff
jobs:
env-diff:
runs-on: ubuntu-latest
env:
ENV: production
steps:
- uses: actions/checkout@v4
- run: dotenv-fusion fuse -f .env-fuse -o .env --diff
For branch-dependent configuration, see the branch-aware example.