Support environment variable placeholders in configuration files
- Dominant language
- C#
- Stars
- 832
- Forks
- 89
- Avg merge
- 12h 1m
- Merged PRs (30d)
- 23
Description
## Summary
Dev Proxy config files (devproxyrc.json and plugin config files like CrudApiPlugin API files) don't support environment variable placeholders. This means values that vary per environment — like Entra app client IDs or tenant IDs — must be hardcoded in config files, or users need to write scripts to patch them before running Dev Proxy.
## Example: the workaround today
In the [da-ristorante-api-devproxy-entra](https://github.com/pnp/copilot-pro-dev-samples/tree/main/samples/da-ristorante-api-devproxy-entra) sample, we need to inject `ENTRA_APP_CLIENT_ID` and `ENTRA_APP_TENANT_ID` into the CrudApiPlugin API files. Because Dev Proxy doesn't support this, the sample includes a [Node.js script](https://github.com/pnp/copilot-pro-dev-samples/blob/main/samples/da-ristorante-api-devproxy-entra/scripts/update-devproxy-config.js) that reads `.env.local` and rewrites the JSON config files before each run.
The config file looks like this:
```json
{
"entraAuthConfig": {
"audience": "",
"issuer": "https://login.microsoftonline.com//v2.0"
}
}
```
And the script manually replaces those placeholders with values from env files. This works but adds friction — extra tooling, an extra build step, and mutated config files that can accidentally get committed.
## What I'd like to see
Support for environment variable references in config files, for example:
```json
{
"entraAuthConfig": {
"audience": "${ENTRA_APP_CLIENT_ID}",
"issuer": "https://login.microsoftonline.com/${ENTRA_APP_TENANT_ID}/v2.0"
}
}
```
When Dev Proxy loads a config file, it would resolve `${VAR_NAME}` placeholders against environment variables (or the `env` config section).
## Why this seems feasible
Dev Proxy already has closely related infrastructure:
- **Path tokens**: `~appFolder` and `~dataFolder` are resolved via `ProxyUtils.ReplacePathTokens` when loading config/plugin paths
- **`@dynamic` tokens**: used in mock responses and rate limiting headers, resolved at runtime
- **`ProxyUtils.ReplaceVariables`**: a general-purpose string replacement utility that replaces variable references in a string given a dictionary of values
- **`IProxyConfiguration.Env`**: the proxy configuration already exposes a `Dictionary Env` property
- **`MinimalPermissionsPlugin`** already uses `ProxyUtils.ReplaceVariables(fileContents, ProxyConfiguration.Env, v => $"{{{v}}}")` to resolve `{VAR}` placeholders in OpenAPI spec files
The pattern is already proven in plugins — it just needs to be applied when loading configuration files too.
## Benefits
- No more wrapper scripts to inject environment-specific values
- Config files stay clean and committable (no secrets, no environment-specific values)
- Consistent with how other tools handle this (Docker Compose, Azure Pipelines, GitHub Actions, etc.)
- Works naturally with `.env` files and CI/CD environments
Contributor guide
Assessment
This issue has not been assessed yet.