Skip to content

feat: environment variable substitution in INI config#532

Merged
CybotTM merged 4 commits into
mainfrom
feat/env-substitution
Mar 20, 2026
Merged

feat: environment variable substitution in INI config#532
CybotTM merged 4 commits into
mainfrom
feat/env-substitution

Conversation

@CybotTM

@CybotTM CybotTM commented Mar 20, 2026

Copy link
Copy Markdown
Member

Summary

Closes #362 — Support ${VAR} and ${VAR:-default} environment variable substitution in INI config files.

Use case

Users want to keep secrets (SMTP passwords, API keys) out of version-controlled config files, referencing them via environment variables instead.

[global]
smtp-host = ${SMTP_HOST:-mail.example.com}
smtp-password = ${SMTP_PASS}

[job-run "backup"]
schedule = @daily
image = ${BACKUP_IMAGE:-postgres:15}
command = pg_dump ${DB_NAME:-mydb}

Behavior

Syntax Behavior
${VAR} Replaced if defined and non-empty; kept literal if undefined (typos visible)
${VAR:-default} Replaced if defined and non-empty; uses default if undefined or empty
$VAR (no braces) Not substituted — cron expressions and shell commands stay safe

Changes

  • cli/envsubst.goexpandEnvVars() using regex, os.LookupEnv
  • cli/config.go — wired into BuildFromFile (per-file, before INI parse) and BuildFromString
  • cli/envsubst_test.go — 24 unit tests covering all edge cases
  • cli/envsubst_integration_test.go — 5 integration tests (BuildFromString + BuildFromFile)
  • docs/CONFIGURATION.md — new "Environment Variable Substitution" section with Docker Compose tip
  • .github/workflows/ci.yml — bump trivy-action 0.28.0 → v0.35.0 (upstream [email protected] yanked)
  • CHANGELOG updated

Test plan

  • 24 unit tests (happy path, edge cases, safety)
  • 5 integration tests (full config parse with env vars)
  • All existing tests pass
  • CI passes

Support ${VAR} and ${VAR:-default} syntax in INI config files.
Variables are resolved before INI parsing, both in BuildFromFile
and BuildFromString paths.

- ${VAR}: replaced if defined and non-empty, kept literal if undefined
- ${VAR:-default}: uses default when undefined or empty
- $VAR without braces is NOT substituted (cron/shell safe)

Closes #362.

Signed-off-by: Sebastian Mendel <[email protected]>
Copilot AI review requested due to automatic review settings March 20, 2026 07:50
@github-actions

github-actions Bot commented Mar 20, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
actions/aquasecurity/trivy-action 57a97c7e7821a5776cebc9bb87c984fa69cba8f1 🟢 6.7
Details
CheckScoreReason
Code-Review🟢 9Found 15/16 approved changesets -- score normalized to 9
Maintained🟢 1014 commit(s) and 2 issue activity found in the last 90 days -- score normalized to 10
Binary-Artifacts🟢 10no binaries found in the repo
Packaging⚠️ -1packaging workflow not detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Token-Permissions🟢 7detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies🟢 8dependency not pinned by hash detected -- score normalized to 8
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Branch-Protection⚠️ -1internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
Security-Policy⚠️ 0security policy file not detected
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0

Scanned Files

  • .github/workflows/ci.yml

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the flexibility and security of INI configuration by implementing environment variable substitution. Users can now leverage environment variables to inject dynamic values or sensitive data into their configurations, with support for default values. This change allows for more robust and adaptable deployments, ensuring that configuration can be managed externally without compromising existing syntax or readability.

Highlights

  • Environment Variable Substitution: Introduced support for ${VAR} and ${VAR:-default} syntax in INI configuration files, allowing dynamic values to be sourced from environment variables.
  • Secure Configuration: Enables users to keep sensitive information like passwords and API keys out of version-controlled config files by referencing them via environment variables.
  • Syntax Safety: The $VAR syntax (without braces) is explicitly not substituted, ensuring that existing cron expressions and shell commands within the configuration remain unaffected.
  • Improved Debugging: Undefined variables without a specified default value will remain as their literal ${VAR} string, making typos and missing environment variables easily visible.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

github-actions[bot]
github-actions Bot previously approved these changes Mar 20, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval for solo maintainer project

All CI checks passed. See SECURITY.md for compensating controls.

@github-actions

Copy link
Copy Markdown

✅ Mutation Testing Results

Mutation Score: 100.00% (threshold: 60%)

✨ Good job! Mutation score meets the threshold.

What is mutation testing?

Mutation testing measures test quality by introducing small changes (mutations) to the code and checking if tests detect them. A higher score means better test effectiveness.

  • Killed mutants: Tests caught the mutation (good!)
  • Survived mutants: Tests missed the mutation (needs improvement)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds environment-variable substitution support to Ofelia’s INI configuration loading, enabling secrets/defaults to be referenced via ${VAR} and ${VAR:-default} prior to INI parsing.

Changes:

  • Introduces ${VAR} / ${VAR:-default} substitution via a new expandEnvVars() helper.
  • Wires substitution into BuildFromFile and BuildFromString so configs are expanded before INI parsing.
  • Adds unit + integration test coverage and updates documentation + changelog.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
cli/envsubst.go Implements ${...} substitution logic using regex + os.LookupEnv.
cli/config.go Applies env substitution when building config from file/string (pre-INI parse).
cli/envsubst_test.go Unit tests for substitution edge cases and safety behavior.
cli/envsubst_integration_test.go Integration tests validating end-to-end config parsing with substitution.
docs/CONFIGURATION.md Documents the new substitution feature and recommended usage.
CHANGELOG.md Notes the feature addition under Unreleased.

Comment thread docs/CONFIGURATION.md
Comment thread docs/CONFIGURATION.md
Comment thread cli/envsubst_integration_test.go
Comment thread cli/envsubst_integration_test.go

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a well-implemented feature for environment variable substitution in INI configuration files, which is great for managing secrets. The changes are accompanied by a comprehensive set of unit and integration tests, and the documentation is clear. My feedback includes a couple of suggestions to document a minor limitation in the substitution logic to improve clarity for users and maintainers.

Comment thread cli/envsubst.go
Comment thread docs/CONFIGURATION.md Outdated
- Add #nosec G304 for os.ReadFile (file path from user config flag)
- Fix gofumpt struct field alignment in test
- Use unique env var names in integration tests to prevent flakiness
- Clarify docs: ${VAR} in commands is substituted, use $VAR for shell;
  defaults cannot contain closing braces

Signed-off-by: Sebastian Mendel <[email protected]>
github-actions[bot]
github-actions Bot previously approved these changes Mar 20, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval for solo maintainer project

All CI checks passed. See SECURITY.md for compensating controls.

The aquasecurity/[email protected] tag was removed upstream, breaking
the trivy scan job. Bump trivy-action from 0.28.0 to v0.35.0 which uses
the current setup-trivy version.

Signed-off-by: Sebastian Mendel <[email protected]>
github-actions[bot]
github-actions Bot previously approved these changes Mar 20, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval for solo maintainer project

All CI checks passed. See SECURITY.md for compensating controls.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated approval for solo maintainer project

All CI checks passed. See SECURITY.md for compensating controls.

@CybotTM CybotTM added this pull request to the merge queue Mar 20, 2026
Merged via the queue into main with commit d06b58a Mar 20, 2026
29 checks passed
@CybotTM CybotTM deleted the feat/env-substitution branch March 20, 2026 09:21
Copilot AI mentioned this pull request Mar 20, 2026
1 task
@github-actions github-actions Bot added the released:v0.22.0 Included in v0.22.0 release label Mar 20, 2026
@github-actions

Copy link
Copy Markdown

🚀 Released in v0.22.0

Thank you for your contribution! 🙏

This is now available in the latest release. Please test and verify everything works as expected in your environment.

If you encounter any issues, please open a new issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released:v0.22.0 Included in v0.22.0 release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Upstream PR#328] Substitute env variables in config

2 participants