hub.yml¶
The settings of a hub, at the root of the hub repository. Only id is required; every
other key has a default. touchmark schema hub prints the JSON Schema, for editors.
version: 1
id: acme-eng # required; 3–40 characters, lowercase words joined by hyphens
# branch: touchmark/acme-eng # default: touchmark/<id>
branch_aliases: [chore/sync-engineering-assets] # former branch names: their pull requests stay the hub's
previous_fingerprints: [] # the hub's fingerprints before a move, like gitlab.example.com/1234
opt_in_file: .engineering-assets.yml
commit:
message: "chore: sync engineering assets"
pr:
title: "chore: sync engineering assets"
labels: [engineering-assets]
draft: false
intro_file: .touchmark/pr-intro.md
link_hub: auto # auto: no links to a private hub in public targets
limits:
max_new_prs_per_run: 100
max_close_fraction: 0.1 # a run that would close more than max(5, 10%) closes none
memory:
auto_close_cooldown: 30d # a bot's close: proposed again after 30d, then 60d; the third counts
security:
write_isolation: platform # platform | external | none
# reason: "..." # required with none, and with platform on Bitbucket and Azure Pipelines
private_targets_in_public_hub: skip # skip | deliver
providers:
- id: gh # TOUCHMARK_GH_* variables; gh:owner/name in targets.yml
type: github # github | gitlab | gitea | forgejo
url: https://github.com
writer: acme-assets-write[bot]
sign: auto # auto | always
- id: corp
type: gitlab
url: https://gitlab.example.com
ca_file: certs/corp-ca.pem
writer: touchmark-writer
known_authors: [group_42_bot_8f3c]
automation_accounts: [stale-bot]
limits: { writes_per_minute: 120 }
sensitive_paths:
- deploy/**
packs:
claude:
description: Claude Code skills, a reviewer agent and settings
requires: [agents]
python-library:
formerly: [python-lib]
Rules check adds¶
The schema cannot say everything. touchmark check also requires:
idis not the template's placeholderchange-me;- the single-provider shorthand (
writer,sign,platform,base_url) andprovidersare not both used; provider ids are unique;giteaandforgejoproviders have aurl; - every pack in
requiresexists,requireshas no cycle, and aformerlyname is neither a current pack nor claimed by two packs; commit.messageandpr.titleare not blank and do not start withDraft:orWIP:(setpr.draftinstead);commit.messageholds no git scissors line;security.reasonis set whenwrite_isolationisnone(anddistributeanddoctoron Bitbucket Pipelines and Azure Pipelines need it underplatformtoo: see A hub on Bitbucket Cloud and A hub on Azure DevOps);- no line of the file looks like a token (
ghp_,github_pat_,ghs_,glpat-,-----BEGIN).
In a hub pull request, providers and ca_file are read from the default branch, and
sensitive_paths is the union of the default branch's and the pull request's.
Keys¶
| Key | Type | Description |
|---|---|---|
version |
1 |
Format version. Only 1 exists; when absent, 1 is assumed with a warning. |
id |
string, 3 to 40 characters, required | Short slug naming this hub, used in the sync branch name and in pull request markers. The template's placeholder "change-me" fails touchmark check. |
branch |
string | Sync branch in every target. Default: touchmark/<id>. |
branch_aliases |
list of strings | Former sync branch names. Open pull requests on them are still recognised as this hub's own. |
previous_fingerprints |
list of strings | Former fingerprints of this hub (host/repository-id: a numeric id, a Bitbucket repository UUID with or without braces, or an Azure Repos repository id), after the hub moved. |
opt_in_file |
string | Path of the opt-in file in targets. Default: .engineering-assets.yml. |
commit |
object | Commit settings. The commit author is always the provider's writer account. |
commit.message |
string | Commit message. Default: "chore: sync engineering assets". Must not start with Draft: or WIP:, which turns a GitLab merge request into a draft. |
commit.author |
object | Deprecated. Ignored with a warning: commits are always authored by the writer account. |
commit.author.name |
string | — |
commit.author.email |
string | — |
pr |
object | Pull request settings. After creation, the title, draft state and labels belong to people. |
pr.title |
string | Title of new pull requests. Default: "chore: sync engineering assets". Must not start with Draft: or WIP:, which makes a GitLab or Gitea pull request a draft: set draft instead. |
pr.labels |
list of strings, each up to 50 characters | Labels of new pull requests. Default: [engineering-assets]; [] for none. |
pr.draft |
boolean | Open new pull requests as drafts. Default: false. |
pr.intro_file |
string | Hub file whose text opens every pull request body. |
pr.link_hub |
one of auto, always, never |
Whether the body links to the hub. auto leaves the links out when the hub is private and the target public. Default: auto. |
limits |
object | Guards against mass actions. |
limits.max_new_prs_per_run |
integer ≥ 0 | New pull requests per run; the rest are deferred to the next run. Default: 100. |
limits.max_close_fraction |
number > 0, ≤ 1 | If a run would close more than max(5, this fraction of the hub's open pull requests), it closes none. Default: 0.1. |
memory |
object | Memory of pull requests closed without merging. |
memory.auto_close_cooldown |
string | How long content closed by a bot waits before it is proposed again, in days or hours. Default: 30d. |
security |
object | — |
security.write_isolation |
one of platform, external, none |
Where the write key lives. platform: in the hub's CI platform, checked by a probe (on Bitbucket Pipelines and Azure Pipelines only with a reason); external: issued by an external vault over OIDC; none: risk accepted, needs a reason. Default: platform. |
security.reason |
string | Why the write key cannot be isolated. Required with write_isolation: none, and with platform on Bitbucket Pipelines, where it states the deployment permissions (Premium) that keep the write key on the default branch, and on Azure Pipelines, where it states the Branch control check of the variable group that holds it: touchmark cannot read either. |
security.private_targets_in_public_hub |
one of skip, deliver |
What a public hub does with non-public targets: skip them, or deliver and let their names reach public CI logs. Default: skip. |
security.writer_on_hub |
one of refuse, guard |
What a writer that reaches the hub means. refuse: doctor fails it, and setup gitlab refuses a hub inside the group of targets. guard (GitLab): the writer may be a Developer of the hub; doctor verifies that it cannot get content onto the default branch, and plan refuses a hub merge request the writer opened or pushed to. Default: refuse. |
providers |
list of objects | Platforms this hub delivers to. Targets refer to them by id. |
providers[].id |
string, required | Name targets.yml uses for this provider, and the <ID> of its TOUCHMARK_<ID>_* variables. |
providers[].type |
one of github, gitlab, gitea, forgejo, bitbucket, azure-devops, bitbucket-datacenter, required |
github: github.com, GHE.com or GitHub Enterprise Server; gitlab; gitea; forgejo; bitbucket: Bitbucket Cloud; azure-devops: one organization of Azure DevOps Services; bitbucket-datacenter: a Bitbucket Data Center instance (bitbucket, azure-devops and bitbucket-datacenter: plan, distribute and doctor; setup does not set up a hub on them yet). |
providers[].url |
string | Web URL of the instance. Default for github: https://github.com; for gitlab: https://gitlab.com; for bitbucket: https://bitbucket.org, the only url it takes without api_url. Required for gitea and forgejo, for bitbucket-datacenter (the base URL, with its context path, like https://bitbucket.example.com/bitbucket), and for azure-devops: https://dev.azure.com/<organization>, one provider per organization. A target targets.yml names by web URL belongs to the provider whose url it lies under. |
providers[].api_url |
string | API URL, when it cannot be derived from url. |
providers[].ca_file |
string | Hub file with extra CA certificates for this instance. |
providers[].writer |
string, up to 255 characters | The account that writes to targets, as the platform names it: on GitHub the App's bot, <slug>[bot]; on GitLab, Gitea and Forgejo the username of the service account or bot user; on Bitbucket the bot account's UUID in braces, {…}; on Azure DevOps the user's id, a GUID; on Bitbucket Data Center the user's slug. |
providers[].known_authors |
list of strings, each up to 255 characters | Former writer accounts whose pull requests still count as this hub's own. |
providers[].automation_accounts |
list of strings, each up to 255 characters | Accounts whose closing of a pull request is automatic, not a team's decision. |
providers[].sign |
one of auto, always |
auto: sign where it costs nothing and where target rules require it; always: sign every commit. Default: auto. |
providers[].limits |
object | Overrides of the platform's rate defaults; 0 keeps the default. |
providers[].limits.writes_per_minute |
integer ≥ 0 | Writes in any minute (HTTP writes and pushes). |
providers[].limits.writes_per_hour |
integer ≥ 0 | Writes in any hour. |
providers[].limits.reads |
integer ≥ 0 | Targets inspected at once. |
providers[].limits.git_reads |
integer ≥ 0 | Git fetches at once. |
providers[].limits.reads_per_minute |
integer ≥ 0 | API reads in any minute. |
providers[].limits.comments_per_minute |
integer ≥ 0 | Comments in any minute. |
providers[].limits.min_interval |
string | Least time between two writes, in milliseconds or seconds, e.g. 250ms or 1s. |
sensitive_paths |
list of strings | Patterns added to the built-in list of paths highlighted in pull requests. |
packs |
map of pack to object | Optional metadata of packs, by pack name. |
packs.<pack>.description |
string | — |
packs.<pack>.requires |
list of strings, each up to 64 characters | Packs that must come before this one. They are added to every target that gets this pack. |
packs.<pack>.formerly |
list of strings, each up to 64 characters | Former names of this pack. Their history counts as this pack's own. |
writer |
string, up to 255 characters | Single-provider shorthand: the writer account, as the platform names it (on GitHub the App's bot, <slug>[bot]). Without platform, the provider's type and URL come from the CI environment, or locally from the hub's origin remote. Not allowed with providers. |
sign |
one of auto, always |
Single-provider shorthand: commit signing. Not allowed with providers. |
platform |
one of github, gitlab, gitea, forgejo, bitbucket, azure-devops, bitbucket-datacenter |
Single-provider shorthand: the provider type, which is also its id. Not allowed with providers. |
base_url |
string | Single-provider shorthand: the provider URL, for self-managed instances. Needs platform; not allowed with providers. |
See Deliver to several platforms for providers, and
Security model for security.