ADR 011: Repository guard pattern for optional workflows¶
Status¶
Accepted
Context¶
This is a template repository. When someone creates a new project from this template (or forks it), all GitHub Actions workflows are copied over. Many workflows require additional setup (secrets, tokens, external services) that new users haven't configured yet.
Problems without a guard:
- Workflows fail immediately on forks/clones with confusing error messages
- Users waste Actions minutes on workflows they haven't set up
- Some workflows (e.g., PyPI publish, Codecov) may expose configuration issues publicly
Options considered:
- Disable all optional workflows by default — Rename files with
_prefix or put in adisabled/folder. Users must manually enable each one. - Use
workflow_dispatchonly — No automatic triggers; users must manually run each workflow. Loses the automation benefit. - Repository guard
if:condition — Workflows exist and have proper triggers but skip execution unless the repo matches a known slug or opt-in variable is set.
Decision¶
Use a repository guard pattern in all optional workflows. Each workflow job includes an if: condition that checks one of three opt-in methods:
if: >-
${{
github.repository == 'YOURNAME/YOURREPO'
|| vars.ENABLE_WORKFLOWS == 'true'
|| vars.ENABLE_<WORKFLOW_NAME> == 'true'
}}
Three ways to opt in¶
| Method | How | Best for |
|---|---|---|
| Option A | Replace YOURNAME/YOURREPO with your repo slug in the YAML (or run scripts/customize.py) |
Simple, permanent |
| Option B | Set vars.ENABLE_WORKFLOWS = 'true' repository variable |
Enable all workflows at once with no YAML edits |
| Option C | Set vars.ENABLE_<WORKFLOW> = 'true' repository variable |
Granular control over individual workflows |
Options B and C can be combined — ENABLE_WORKFLOWS activates everything,
then individual ENABLE_<WORKFLOW> variables can be used if only some
workflows are desired (without the global variable).
Consequences¶
Positive¶
- Workflows are visible and well-documented from day one — users can read them to understand what's available
- No file renaming or directory juggling needed to enable/disable
- Guards are self-documenting with TODO comments explaining both options
- Repository variables (Option B) allow enabling/disabling without code changes
- Workflows don't fail on forks — they silently skip
Negative¶
- Every optional workflow needs the boilerplate guard condition
- Template users must remember to opt in (guards block execution by default)
- The
YOURNAME/YOURREPOplaceholder can be confusing if not updated
Neutral¶
- Core workflows (test, lint) don't need guards — they should always run
- The pattern is consistent across all optional workflows in this template