Documentation
¶
Overview ¶
Package repocfg models and applies a repository's GitHub configuration — general settings, security, CodeQL, Pages and the per-repo rulesets — from editable YAML templates under templates/.
The desired state for a repo is composed from three inputs:
- a CLASS preset (classes/<class>.yaml) — the per-kind toggles,
- an ORG profile (orgs/<org>.yaml) — bypass actors and signing,
- semantically DISCOVERED checks (checks.yaml + the detect package),
then overridden by CLI flags / the interactive form. The templates are plain YAML so they can be edited without touching Go; an on-disk copy (under the stack checkout, or $REPO_CONFIG_DIR) wins over the embedded copy so edits don't need a rebuild.
Index ¶
- Variables
- func CODEOWNERS() (string, error)
- func ReadTemplate(rel string) ([]byte, error)
- func RenderCodeQL(langs []string, querySuite, defaultBranch string) (string, error)
- func SecurityBlock(c *ClassPreset) map[string]any
- func SettingsBody(c *ClassPreset) map[string]any
- type APIBypassActor
- type APIRule
- type APIRuleset
- type CheckDef
- type CheckRef
- type ChecksConfig
- type Class
- type ClassPreset
- type ClassRulesets
- type CodeQLLangRule
- type CodeQLPreset
- type CodeQLRule
- type CodeQualityParams
- type CodecovMode
- type CodecovRule
- type Discovered
- type ExcludeRules
- type Features
- type LabelDef
- type LabelsConfig
- type Merge
- type Op
- type OrgProfile
- type Plan
- type RSCParams
- type RepoTarget
- type RulesetConditions
- type RulesetRules
- type RulesetSpec
- type SecurityToggles
Constants ¶
This section is empty.
Variables ¶
var AllClasses = []Class{ClassService, ClassLibrary, ClassWorkflows, ClassMeta}
AllClasses is the ordered set of known classes (for the UI picker and flag validation).
Functions ¶
func CODEOWNERS ¶ added in v1.3.3
CODEOWNERS returns the uniform CODEOWNERS file provisioned to every repo. It is static today — a single owner (`* @kushuh`) — so there is nothing to render; lift it to an org/class config field if/when teams appear.
func ReadTemplate ¶
ReadTemplate returns the bytes of templates/<rel>, preferring an on-disk copy so edits don't need a rebuild, falling back to the embedded copy. On-disk precedence: $REPO_CONFIG_DIR, else <stack>/cli/internal/repocfg/templates.
func RenderCodeQL ¶
RenderCodeQL fills the CodeQL advanced-setup workflow template.
func SecurityBlock ¶
func SecurityBlock(c *ClassPreset) map[string]any
SecurityBlock is the security_and_analysis sub-object.
func SettingsBody ¶
func SettingsBody(c *ClassPreset) map[string]any
SettingsBody is the PATCH /repos body for general + merge + security.
Types ¶
type APIBypassActor ¶
type APIBypassActor struct {
ActorID *int64 `json:"actor_id"`
ActorType string `json:"actor_type"`
BypassMode string `json:"bypass_mode"`
}
APIBypassActor is one bypass-actor entry in the GitHub rulesets API request body.
type APIRule ¶
type APIRule struct {
Type string `json:"type"`
Parameters map[string]any `json:"parameters,omitempty"`
}
APIRule is one rule entry in the GitHub rulesets API request body.
type APIRuleset ¶
type APIRuleset struct {
Name string `json:"name"`
Target string `json:"target"`
Enforcement string `json:"enforcement"`
Conditions map[string]any `json:"conditions"`
BypassActors []APIBypassActor `json:"bypass_actors"`
Rules []APIRule `json:"rules"`
}
APIRuleset is the GitHub rulesets API request body.
func BuildRuleset ¶
func BuildRuleset(spec *RulesetSpec, org *OrgProfile, checks []CheckRef) (*APIRuleset, error)
BuildRuleset turns a ruleset template + org + discovered checks into the API body, resolving generic bypass entries and injecting the checks.
type CheckDef ¶
CheckDef is one required status check (its integration key resolves to an app id via ChecksConfig.Integrations).
type ChecksConfig ¶
type ChecksConfig struct {
Integrations map[string]int64 `yaml:"integrations"`
Always []CheckDef `yaml:"always"`
Exclude ExcludeRules `yaml:"exclude"`
CodeQL CodeQLRule `yaml:"codeql"`
Codecov CodecovRule `yaml:"codecov"`
}
ChecksConfig is checks.yaml. Required checks are the jobs declared in a repo's .github/workflows/main.yaml (minus Exclude), plus the Always set — there is no per-class or per-file derivation. CodeQL languages (for the codeql.yml workflow) and the Codecov ruleset's checks are the only other pieces here.
func (*ChecksConfig) ResolveBotIntegrations ¶ added in v1.3.5
func (c *ChecksConfig) ResolveBotIntegrations(org *OrgProfile)
ResolveBotIntegrations fills the integration ids that belong to a per-org bot rather than a global app. checks.yaml can't hardcode these: each org runs its own [Agent] App with a distinct id (a-novel and a-novel-kit differ), and the same checks.yaml is loaded for both. Call this with the target repo's org profile before discovery so a check posted by the [Agent] App — the merge-gate — is required against that org's App and can actually be satisfied.
type Class ¶
type Class string
Class is a repository kind; each maps to one classes/<class>.yaml preset.
func DetectClass ¶ added in v1.2.0
DetectClass infers a repo's class from its name, used when neither a repos/<org>_<repo>.yaml override nor the --class flag is given. The strong-semantic classes match exact names (workflows, .github); the service-* family is the service class; everything else falls to the freeform library default. platform-* frontends are not modelled yet — they fall to library or need an explicit override until platform conventions exist.
type ClassPreset ¶
type ClassPreset struct {
Class Class `yaml:"class"`
Features Features `yaml:"features"`
Merge Merge `yaml:"merge"`
Security SecurityToggles `yaml:"security"`
CodeQL CodeQLPreset `yaml:"codeql"`
Pages bool `yaml:"pages"`
Codecov CodecovMode `yaml:"codecov"`
CodeQuality bool `yaml:"code_quality"`
Rulesets ClassRulesets `yaml:"rulesets"`
}
ClassPreset is one classes/<class>.yaml file.
func LoadClass ¶
func LoadClass(c Class) (*ClassPreset, error)
LoadClass reads and parses classes/<class>.yaml.
func LoadRepoOverride ¶
func LoadRepoOverride(org, repo string) (*ClassPreset, bool, error)
LoadRepoOverride reads repos/<org>_<repo>.yaml if it exists. The bool is false (nil error) when the repo has no override and should use its class.
type ClassRulesets ¶
type ClassRulesets struct {
Master bool `yaml:"master"`
RequireApproval bool `yaml:"require_approval"`
Tags bool `yaml:"tags"`
}
ClassRulesets says which named rulesets the class applies. codecov is driven separately by ClassPreset.Codecov.
type CodeQLLangRule ¶ added in v1.3.2
CodeQLLangRule maps a detection signal to a CodeQL language.
type CodeQLPreset ¶
CodeQLPreset configures CodeQL advanced setup. Languages are discovered, not declared here.
type CodeQLRule ¶ added in v1.3.2
type CodeQLRule struct {
Always []string `yaml:"always"`
Languages []CodeQLLangRule `yaml:"languages"`
}
CodeQLRule is the only file-based detection left: the CodeQL workflow's languages. Always-on languages need no signal (e.g. actions); the rest are detected by a canonical file (go.mod → go, package.json → javascript).
type CodeQualityParams ¶
type CodeQualityParams struct {
Severity string `yaml:"severity"`
}
CodeQualityParams is the code_quality rule's parameters.
type CodecovMode ¶
type CodecovMode string
CodecovMode selects whether a repo enforces the Codecov coverage ruleset. It is a string rather than a bool to sidestep YAML's off/on boolean coercion.
const ( // CodecovAuto enforces the ruleset only where the repo has tests (Codecov // actually reports), so the gate never blocks a repo that uploads no coverage. CodecovAuto CodecovMode = "auto" // CodecovEnabled always enforces the ruleset. CodecovEnabled CodecovMode = "enabled" // CodecovDisabled never enforces the ruleset. CodecovDisabled CodecovMode = "disabled" )
type CodecovRule ¶
type CodecovRule struct {
EnableWhenTests bool `yaml:"enable_when_tests"`
Checks []CheckDef `yaml:"checks"`
}
CodecovRule controls the codecov ruleset's auto-enable + its checks. Codecov posts its own statuses (codecov/patch, codecov/project), so they are not main.yaml jobs — they live in this separate, bot-bypassing ruleset.
type Discovered ¶
Discovered is what probing a repo tells us: the required checks (for the master ruleset) and the CodeQL languages (for the codeql.yml workflow).
func Discover ¶
func Discover(repoPath string, cc *ChecksConfig) (*Discovered, error)
Discover computes a repo's required checks and CodeQL languages.
Required checks are the `always` set plus every job declared in the repo's .github/workflows/main.yaml, minus cc.Exclude — the job id is the check context, so there is no class- or file-based derivation to drift. A missing main.yaml (e.g. a docs/meta repo) simply contributes no jobs.
CodeQL languages are the one remaining file-based signal, used only to render the codeql.yml workflow.
type ExcludeRules ¶ added in v1.3.2
type ExcludeRules struct {
Prefixes []string `yaml:"prefixes"`
IfContains []string `yaml:"if_contains"`
}
ExcludeRules narrows the main.yaml jobs that become required checks. A job is excluded when its id starts with any Prefix (reporting / post-merge jobs) or its `if:` contains any IfContains string (e.g. master-only jobs, which never run on a PR and so cannot gate one).
type Features ¶
type Features struct {
Issues bool `yaml:"issues"`
Wiki bool `yaml:"wiki"`
Projects bool `yaml:"projects"`
Discussions bool `yaml:"discussions"`
}
Features mirrors the repo "Features" toggles.
type LabelDef ¶ added in v1.3.4
type LabelDef struct {
Name string `yaml:"name"`
Color string `yaml:"color"`
Description string `yaml:"description"`
}
LabelDef is one entry in the canonical label set — name, hex colour (no leading '#', lower-case, as GitHub stores it) and description.
type LabelsConfig ¶ added in v1.3.4
LabelsConfig is governance/labels.yaml: the uniform label vocabulary every repo carries, provisioned like CODEOWNERS. Ensure labels are upserted (created when absent, recoloured / re-described when they drift); Retire labels are deleted. A label in neither list is left untouched — apply never removes a label it was not told about.
func LoadLabels ¶ added in v1.3.4
func LoadLabels() (*LabelsConfig, error)
LoadLabels reads and parses governance/labels.yaml.
type Merge ¶
type Merge struct {
Squash bool `yaml:"squash"`
MergeCommit bool `yaml:"merge_commit"`
Rebase bool `yaml:"rebase"`
AutoMerge bool `yaml:"auto_merge"`
DeleteBranchOnMerge bool `yaml:"delete_branch_on_merge"`
AllowUpdateBranch bool `yaml:"allow_update_branch"`
SignoffRequired bool `yaml:"signoff_required"`
}
Merge mirrors the merge-button + PR settings.
type Op ¶
type Op struct {
Method string `json:"method,omitempty"`
Path string `json:"path,omitempty"`
Body any `json:"body,omitempty"`
Content string `json:"content,omitempty"`
RulesetName string `json:"ruleset,omitempty"`
}
Op is one API operation the plan performs — a small tagged union. Most ops carry a Method, Path, and Body (or Content, for a file write). A ruleset op instead sets RulesetName and is reconciled by name at apply time: POST when the ruleset is absent, PUT .../{id} when it already exists.
type OrgProfile ¶
type OrgProfile struct {
Org string `yaml:"org"`
SigningRequired bool `yaml:"signing_required"`
Bots map[string]int64 `yaml:"bots"`
}
OrgProfile is orgs/<org>.yaml — per-org bot ids and signing policy. A ruleset's generic bot name (bots key) resolves to the app id here.
func LoadOrg ¶
func LoadOrg(org string) (*OrgProfile, error)
LoadOrg reads and parses orgs/<org>.yaml.
type Plan ¶
type Plan struct {
Ops []Op
}
Plan is the ordered set of operations to bring a repo to desired state.
func BuildPlan ¶
func BuildPlan(t *RepoTarget) (*Plan, error)
BuildPlan assembles the desired-state operations for a repo.
type RSCParams ¶
type RSCParams struct {
Strict bool `yaml:"strict"`
DoNotEnforceOnCreate bool `yaml:"do_not_enforce_on_create"`
}
RSCParams is the static part of a required_status_checks rule; the checks list is injected from discovery.
type RepoTarget ¶
type RepoTarget struct {
Org, Repo, DefaultBranch string
Class *ClassPreset
OrgProfile *OrgProfile
Checks *ChecksConfig
Discovered *Discovered
// CodecovReports is whether Codecov posts a status on this repo. It
// gates `codecov: auto` — a coverage ruleset is only enforced where
// Codecov actually reports, so it never blocks PRs on a repo that has
// no coverage upload.
CodecovReports bool
}
RepoTarget is everything needed to compute a repo's desired config.
type RulesetConditions ¶
type RulesetConditions struct {
RefName struct {
Include []string `yaml:"include"`
Exclude []string `yaml:"exclude"`
} `yaml:"ref_name"`
}
RulesetConditions is the ref-name match for a branch ruleset.
type RulesetRules ¶
type RulesetRules struct {
Creation bool `yaml:"creation"`
Update bool `yaml:"update"`
Deletion bool `yaml:"deletion"`
NonFastForward bool `yaml:"non_fast_forward"`
RequiredSignatures bool `yaml:"required_signatures"`
RequiredStatusChecks *RSCParams `yaml:"required_status_checks"`
MergeQueue map[string]any `yaml:"merge_queue"`
CodeQuality *CodeQualityParams `yaml:"code_quality"`
PullRequest map[string]any `yaml:"pull_request"`
}
RulesetRules holds every rule a template may set; absent ones stay nil/ false. Param blobs that pass straight through to the API (merge_queue, pull_request) are kept as maps so the template owns their shape.
type RulesetSpec ¶
type RulesetSpec struct {
Name string `yaml:"name"`
Target string `yaml:"target"`
Enforcement string `yaml:"enforcement"`
Conditions RulesetConditions `yaml:"conditions"`
Bypass []string `yaml:"bypass"`
Rules RulesetRules `yaml:"rules"`
}
RulesetSpec is one rulesets/<name>.yaml base. The required-status-checks list and concrete bypass actors are injected by the builder, not stored here.
func LoadRuleset ¶
func LoadRuleset(name string) (*RulesetSpec, error)
LoadRuleset reads rulesets/<name>.yaml.
type SecurityToggles ¶
type SecurityToggles struct {
SecretScanning bool `yaml:"secret_scanning"`
PushProtection bool `yaml:"push_protection"`
Dependabot bool `yaml:"dependabot"`
}
SecurityToggles mirrors the security_and_analysis block we manage.