Conversation
When the --config flag is not set, poutine now searches for a config
file in two locations in priority order:
1. .poutine.{yml,yaml,json,toml} at the repository root (existing
behaviour)
2. .github/poutine.{yml,yaml,json,toml}
This lets users group CI configuration under .github/ alongside
existing GitHub config files (dependabot.yml, CODEOWNERS, etc.). The
--config flag still overrides both, and a root-level .poutine.yml
still takes precedence over one under .github/, so existing projects
are unaffected.
Closes boostsecurityio#422
There was a problem hiding this comment.
Pull request overview
Adds config auto-discovery support for a secondary config location under .github/, allowing CI-related configuration to live alongside other GitHub tooling files while preserving existing root precedence.
Changes:
- Extend default config discovery to check
.github/poutine.{yml,yaml,json,toml}after.poutine.{yml,yaml,json,toml}. - Add unit tests for discovery precedence and directory-entries-as-config edge case.
- Update CLI help text and README to document the new fallback path and precedence.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| cmd/root.go | Introduces discoverConfigFile() and wires it into initConfig() to prefer root config, then .github/ fallback. |
| cmd/discover_config_test.go | Adds tests covering discovery behavior, precedence, and ignoring directory “configs”. |
| README.md | Documents the new fallback path and precedence in usage/configuration sections. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| for _, ext := range extensions { | ||
| p := base + "." + ext | ||
| if fi, err := os.Stat(p); err == nil && !fi.IsDir() { | ||
| return p | ||
| } | ||
| } |
There was a problem hiding this comment.
discoverConfigFile() currently ignores any os.Stat error (other than nil) and just keeps searching. This can misclassify an existing config file as “not found” when Stat fails due to permission/IO errors, causing initConfig() to silently proceed with defaults instead of surfacing a read error. Consider treating non-IsNotExist errors as a hard failure (or returning the candidate path / an error) so permission issues don’t get swallowed.
| poutine analyze_local . --config my-config.yml | ||
| ``` | ||
|
|
||
| If a `.poutine.yml` file is not present at the repository root, poutine also looks for `.github/poutine.yml` so CI-related configuration can be grouped alongside other GitHub configuration files. A file at the repository root takes precedence over one under `.github/`, and the `--config` flag overrides both. |
There was a problem hiding this comment.
The text says “repository root”, but config discovery here is relative to the current working directory (matching the earlier paragraph that says “current working directory”). To avoid misleading users who run poutine from a subdirectory, reword this to “current directory/working directory” (and keep the precedence explanation).
| If a `.poutine.yml` file is not present at the repository root, poutine also looks for `.github/poutine.yml` so CI-related configuration can be grouped alongside other GitHub configuration files. A file at the repository root takes precedence over one under `.github/`, and the `--config` flag overrides both. | |
| If a `.poutine.yml` file is not present in the current working directory, poutine also looks for `.github/poutine.yml` under the current working directory so CI-related configuration can be grouped alongside other GitHub configuration files. A `.poutine.yml` file in the current working directory takes precedence over one under `.github/`, and the `--config` flag overrides both. |
|
Hey @mvanhorn, thanks for jumping in on this. Closing this one as a duplicate of #424, which @graelo opened a few hours earlier. They also filed the original issue (#422) and had already offered to implement it, so we'd like to let them run with it. One thing for next time: before starting work on an issue, have a look at the thread and open PRs to see if someone is already on it. Avoids duplicated effort on both sides. Also, if you used AI assistance on the PR, please flag that in the description so reviewers know what to look for. Thanks again for wanting to help out. |
|
Sorry about that! |
Closes #422
Summary
When
--configis not provided, poutine now checks two locations for its configuration file, in priority order:.poutine.{yml,yaml,json,toml}at the repository root (existing behaviour)..github/poutine.{yml,yaml,json,toml}.This lets users keep CI-related configuration under
.github/alongsidedependabot.yml,CODEOWNERS, etc. — the pattern mentioned in the issue and used by tools like zizmor. Root-level.poutine.ymlstill wins if both exist, so existing repositories are unaffected.Implementation
cmd/root.go— added a smalldiscoverConfigFile()helper that walks the two candidate paths and returns the first existing file. When that helper returns a non-empty path,initConfigcallsviper.SetConfigFile()on it; when it returns"", the existing viper search (AddConfigPath(".") + SetConfigName(".poutine")) still runs, so theConfigFileNotFoundErrorpath is unchanged.Using
SetConfigFileon the resolved path is cleaner than jugglingviper.AddConfigPath/SetConfigNamefor two differently-named files, and it keeps the error-handling branch identical for both discovery and the "no config" case.Tests
cmd/discover_config_test.gocovers:.poutine.ymlat root takes precedence over.github/poutine.yml.github/poutine.ymlused when root is absent.poutine.ymlare ignored (defence against straymkdir)Also smoke-tested the built binary in three temp directories (root config,
.githubconfig, and no config) — all succeed and use the expected file.Docs
Updated the
--configflag help text and the README "Configuration" section to mention the new fallback path and note the precedence order. The CLI flag string now readsconfig file (default searches .poutine.yml in the current directory, then .github/poutine.yml).