Repository Overrides
Repository overrides let you change behavior for one repository without changing the default behavior for every repo the server manages.
This project has two per-repository configuration layers:
config.yamlon the server, underrepositories.<repo>.github-webhook-server.yamlin the root of the repository itself
For runtime settings that the webhook reads from the repository, precedence is:
.github-webhook-server.yaml- The matching repository entry in
config.yaml - Top-level defaults in
config.yaml
Note: The server looks for
.github-webhook-server.yamlin the repository root. If that file is missing, the repository falls back to itsconfig.yamlentry, then to global defaults.Tip: Keep repo-owned workflow behavior in
.github-webhook-server.yaml, and keep server-owned settings such as credentials, webhook events, and protected branch setup inconfig.yaml.
| Area | .github-webhook-server.yaml |
config.yaml repositories.<repo> |
Notes |
|---|---|---|---|
labels.enabled-labels, labels.colors |
Yes | Yes | Repo-local values win. |
pr-size-thresholds |
No | Yes | Current runtime reads PR size buckets from config.yaml. |
tox, tox-python-version, pre-commit, verified-job, conventional-title, custom-check-runs, set-auto-merge-prs, can-be-merged-required-labels, minimum-lgtm |
Yes | Yes | Repo-local values win. |
pypi, container |
Yes | Yes | Repo-local values win. |
github-tokens |
No | Yes | Needed before the repo-local file can be read. |
protected-branches and branch protection sync |
No | Yes | Applied by the server when it configures repositories. |
branch-protection.required_conversation_resolution |
Yes | Yes | Also affects the runtime can-be-merged gate. |
events, test-oracle, allow-commands-on-draft-prs |
No | Yes | Current code reads these from config.yaml. |
Labels
Per-repo label overrides are useful when one repository wants fewer automation labels, different colors, or different PR size buckets than the global defaults.
The repo-specific label shape in config.yaml looks like this:
labels:
enabled-labels:
- verified
- hold
- size
colors:
hold: purple
pr-size-thresholds:
Express:
threshold: 25 # PRs with 0-24 lines changed
color: lightblue
Standard:
threshold: 100 # PRs with 25-99 lines changed
color: green
Premium:
threshold: 500 # PRs with 100-499 lines changed
color: orange # PRs with 500+ lines changed get this category
labels.enabled-labels is a whitelist.
- Leave it unset to keep all configurable label categories enabled.
- Set it to
[]to disable configurable label categories for that repo. - Review labels such as
approved-*,lgtm-*,changes-requested-*, andcommented-*still stay enabled. - The exact
lgtmandapprovelabels also stay enabled.
labels.colors overrides only the keys you provide, so you can inherit global colors and replace just a few. The code also supports dynamic prefixes such as approved- and branch-, not just exact label names.
Note:
pr-size-thresholdsis per-repository, but in the current code it belongs inconfig.yaml, not.github-webhook-server.yaml.
Checks And Merge Rules
This is the area where repo-local overrides are most useful. You can change what checks run, how strict the merge gate is, and whether auto-merge is enabled for selected branches.
The repo-local example shows branch-specific tox, an optional Python version for tox, and pre-commit:
verified-job: true # Enable/disable verified job functionality
# ... other repo-local settings ...
tox:
main: "tests,linting" # Commands for main branch
develop: "tests" # Commands for develop branch
feature/*: ["tests", "quick-lint"] # Array format also supported
tox-python-version: "3.11"
pre-commit: true
The same repo-local file also shows merge-gate controls:
set-auto-merge-prs:
- main
- develop
can-be-merged-required-labels:
- "approved"
- "tests-passed"
- "security-reviewed"
conventional-title: "feat,fix,build,chore,ci,docs,style,refactor,perf,test,revert"
minimum-lgtm: 2
create-issue-for-new-pr: true # Create tracking issues for new PRs
These keys change behavior in practical ways:
verified-jobenables theverifiedcheck flow for that repository.toxmaps base branches to thetoxenvs that should run.tox-python-versionchooses the Python version passed totox.pre-commitenables thepre-commitcheck.conventional-titlevalidates PR titles against the configured Conventional Commit types.can-be-merged-required-labelsadds extra labels that must be present beforecan-be-mergedpasses.minimum-lgtmraises the LGTM threshold before a PR is considered approved.set-auto-merge-prsenables GitHub auto-merge automatically when the PR targets one of those base branches.create-issue-for-new-prcontrols automatic tracking issue creation per repository.
Custom checks are configured as custom-check-runs:
custom-check-runs:
# Examples from the schema:
- name: lint
command: uv tool run --from ruff ruff check
mandatory: true
- name: security-scan
command: TOKEN=xyz DEBUG=true uv tool run --from bandit bandit -r .
mandatory: false
- name: complex-check
command: |
uv run python -c "
import sys
print('Running complex check')
sys.exit(0)
"
custom-check-runs behave like built-in checks, with two especially useful details:
- The check name is used exactly as configured.
mandatory: falsemeans the check still runs, but it does not blockcan-be-merged.
Note: Custom checks run in the repository worktree and support shell syntax, including environment variable prefixes.
Warning: Custom checks are validated when they are loaded. The check name cannot collide with built-in checks such as
tox,pre-commit,build-container,python-module-install,conventional-title, orcan-be-merged, and the executable incommandmust already exist on the server. Invalid checks are skipped.
One more merge-related setting is worth calling out: branch-protection.required_conversation_resolution. The runtime merge gate reads that flag and, when enabled, unresolved review threads will cause can-be-merged to fail.
Other supported repo-local workflow overrides include auto-verified-and-merged-users, auto-verify-cherry-picked-prs, cherry-pick-assign-to-pr-author, slack-webhook-url, and ai-features.
Tokens And Protected Branches
Some settings are still per-repository, but they remain server-side because the server needs them before it can read .github-webhook-server.yaml.
The repo-specific server config supports branch protection setup, per-repo tokens, and branch protection policy:
protected-branches:
dev: []
main: # set [] in order to set all defaults run included
include-runs:
- "pre-commit.ci - pr"
- "WIP"
exclude-runs:
- "SonarCloud Code Analysis"
# ... other repo-specific settings ...
github-tokens: # override GitHub tokens per repository
- <GITHUB TOKEN1>
- <GITHUB TOKEN2>
# ... other repo-specific settings ...
branch-protection:
strict: True
require_code_owner_reviews: True
dismiss_stale_reviews: False
required_approving_review_count: 1
required_linear_history: True
required_conversation_resolution: True
Use github-tokens when one repository needs its own API budget or a different permission set than the global default. The server will build GitHub clients from that repo's token list and select the token with the highest remaining rate limit.
Warning: Put
github-tokensinconfig.yaml, not in.github-webhook-server.yaml. Token selection happens before the server reads the repo-local file.
protected-branches controls which branches get protection and what required checks are applied.
[]means "protect this branch with the computed default required checks".include-runsgives an explicit required-check list for that branch.exclude-runsremoves checks from the computed default list.
Note: If
include-runsis present, the server uses that explicit list. If it is not present, the server builds the list fromdefault-status-checks, enabled repo features such astoxandpre-commit, andcan-be-merged, then removes anything listed inexclude-runs.
branch-protection controls the actual GitHub branch protection settings for that repository. Per-repo values override global values field by field, so you can change only strict, only required_approving_review_count, or only required_conversation_resolution without redefining everything.
Release Settings
Release behavior is also override-friendly. A repository can decide whether tag pushes should publish packages, push container images, or both.
The repo-local example shows both pypi and container:
pypi:
token: pypi-your-token-here
# ... other repo-local settings ...
container:
username: your-registry-username
password: your-registry-password # pragma: allowlist secret
repository: quay.io/your-org/your-repo
tag: latest
release: true # Push on new releases
build-args:
- "BUILD_ARG=value"
args:
- "--platform=linux/amd64"
These keys affect release flow like this:
- If
pypiis configured, a tag push triggers a build and upload to PyPI. - If
containeris configured, the repo gets container build behavior. - If
container.releaseistrue, tag pushes also push the built image to the configured registry. container.build-argsandcontainer.argsare passed through to the container build command.
Tip: On tag pushes, the published container image uses the Git tag name. For PR builds, the image tag is
pr-<number>. For merged builds tomainormaster, the server usescontainer.tag.
Recommended Split
A good working pattern is:
- Keep
github-tokens,protected-branches,branch-protection,events,pr-size-thresholds,test-oracle, andallow-commands-on-draft-prsinconfig.yaml. - Keep
labels,tox,pre-commit,custom-check-runs,conventional-title,set-auto-merge-prs,can-be-merged-required-labels,minimum-lgtm,pypi,container, and other PR workflow behavior in.github-webhook-server.yaml.
That gives you the best of both worlds: the server keeps control over secrets and GitHub setup, while each repository can own its day-to-day workflow behavior in version control.