config

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Index

Constants

View Source
const (
	PresetBranchProtection       = "branch-protection"
	PresetStrictBranchProtection = "strict-branch-protection"
	PresetTagProtection          = "tag-protection"
	PresetNoForcePush            = "no-force-push"
	PresetRequireSignedCommits   = "require-signed-commits"
	PresetRequireDCO             = "require-dco"
	PresetNoCommittedKeys        = "no-committed-keys"
)

Built-in preset names. These are the guard rails gomgr ships with, so a config can ask for "the usual protection" without restating a dozen rules.

View Source
const (
	RulesetTargetBranch = "branch"
	RulesetTargetTag    = "tag"
	RulesetTargetPush   = "push"
)

Ruleset targets. A ruleset protects refs (branch/tag) or the push itself.

View Source
const (
	RulesetEnforcementActive   = "active"
	RulesetEnforcementEvaluate = "evaluate"
	RulesetEnforcementDisabled = "disabled"
)

Ruleset enforcement levels. "evaluate" reports what would have been blocked without blocking it — the safe way to roll a new guardrail out.

View Source
const (
	BypassActorTypeIntegration       = "Integration"
	BypassActorTypeOrganizationAdmin = "OrganizationAdmin"
	BypassActorTypeEnterpriseOwner   = "EnterpriseOwner"
	BypassActorTypeRepositoryRole    = "RepositoryRole"
	BypassActorTypeTeam              = "Team"
	BypassActorTypeDeployKey         = "DeployKey"
)

Bypass actor types accepted in YAML. These mirror the GitHub API values and are case-sensitive there, so they are matched case-insensitively here and normalized on the way out.

View Source
const (
	BypassModeAlways      = "always"
	BypassModePullRequest = "pull_request"
)

Bypass modes. "pull_request" lets the actor bypass only via a pull request.

Variables

This section is empty.

Functions

func BootstrapTeamYAML

func BootstrapTeamYAML(path string, name string) error

func BypassActorTypeNames added in v0.3.0

func BypassActorTypeNames() string

BypassActorTypeNames returns the recognized actor types, for error messages.

func FindTeamFileForRepo added in v0.4.0

func FindTeamFileForRepo(dir, repo string) (string, error)

FindTeamFileForRepo returns the team file under <dir>/teams that declares repo, or "" when no file does. When several declare it the first by filename wins, which keeps the choice stable across runs.

func InsertOrgRulesets added in v0.4.0

func InsertOrgRulesets(path string, rulesets []RulesetConfig) error

InsertOrgRulesets adds ruleset entries to the top-level `rulesets:` block of an org.yaml, creating the block when the file has none.

The file is edited as text rather than re-encoded from a parsed tree. yaml.v3 can round-trip a document, but it normalizes as it goes — blank lines between entries disappear, quoting style shifts, long values re-wrap — and a config repository's diff is something people have to read. Parsing is used only to find the line to splice at, which is exactly what a parser is good for and a regex is not.

func InsertRepoRulesets added in v0.4.0

func InsertRepoRulesets(path, repo string, rulesets []RulesetConfig) error

InsertRepoRulesets adds ruleset entries to a repository's entry in a team file, handling the three shapes a repository entry can take: one that already has a `rulesets:` block, one that is a settings map without it, and one that is the bare permission string (`infra: push`), which has to grow into a map first.

func PresetNames added in v0.3.0

func PresetNames() []string

PresetNames returns the built-in preset names in sorted order, for error messages and documentation.

func RulesetPresets added in v0.3.0

func RulesetPresets() map[string]RulesetConfig

RulesetPresets returns the built-in guard rails, freshly constructed on each call. Presets hand out pointers into RulesetRules and callers merge those pointers into their own config, so sharing one package-level map between rulesets would let them alias each other's rule structs.

A preset supplies target, conditions and rules; a RulesetConfig naming one overrides any of those it sets itself. Presets deliberately do not set bypass actors — who may bypass a guard rail is a decision for the org, not a default.

func ValidateCodeOwner added in v0.2.5

func ValidateCodeOwner(co string) error

ValidateCodeOwner checks that a CODEOWNERS entry is well-formed. Accepts bare usernames (octocat), explicit user refs (@octocat), and team refs (@org/team-slug). Emails are not yet supported.

func ValidateRulesets added in v0.3.0

func ValidateRulesets(scope RulesetScope, where string, rulesets []RulesetConfig) error

ValidateRulesets checks a ruleset list for the mistakes GitHub would only report as an opaque 422 at apply time: unknown presets, invalid enumerations, duplicate names, and conditions used at the wrong scope.

where labels the source ("org.yaml" or "team X, repo Y") in error messages.

func WriteTeamFile added in v0.4.0

func WriteTeamFile(dir string, team TeamConfig) (string, error)

WriteTeamFile writes an imported team to <dir>/teams/<slug>.yaml and returns the path it wrote.

Unlike the ruleset import, which has to splice into files somebody else wrote, every team file here is new — so this is a plain encode, and the only thing worth guarding is not landing on top of a file that already exists.

Types

type AppConfig

type AppConfig struct {
	AppID      int64  `yaml:"app_id,omitempty"`
	PrivateKey string `yaml:"private_key,omitempty"`
	Org        string `yaml:"org"`

	DryWarnings struct {
		WarnUnmanagedTeams        bool `yaml:"warn_unmanaged_teams"`
		WarnMembersWithoutAnyTeam bool `yaml:"warn_members_without_any_team"`
		WarnUnmanagedRepos        bool `yaml:"warn_unmanaged_repos"`
		WarnUnmanagedCustomRoles  bool `yaml:"warn_unmanaged_custom_roles"`
		WarnUnmanagedRulesets     bool `yaml:"warn_unmanaged_rulesets"`
	} `yaml:"dry_warnings"`
	RemoveMembersWithoutTeam   bool `yaml:"remove_members_without_team"`
	DeleteUnconfiguredTeams    bool `yaml:"delete_unconfigured_teams"`
	DeleteUnmanagedRepos       bool `yaml:"delete_unmanaged_repos"`
	DeleteUnmanagedCustomRoles bool `yaml:"delete_unmanaged_custom_roles"`
	DeleteUnmanagedRulesets    bool `yaml:"delete_unmanaged_rulesets"`
	DeleteStaleCodeowners      bool `yaml:"delete_stale_codeowners"`
	CreateRepo                 bool `yaml:"create_repo"`

	// SignOff is the identity used for the Signed-off-by trailer appended to
	// every commit gomgr writes, in "Name <email>" form. Set it when the org
	// enforces DCO — a ruleset with a commit_message_pattern rule requiring
	// "Signed-off-by:" rejects gomgr's file-sync pushes otherwise, because
	// those commits go straight to the default branch and never pass through
	// a pull request where a DCO check could run.
	//
	// Empty (the default) appends nothing, preserving prior behavior for orgs
	// that do not require sign-off.
	SignOff string `yaml:"sign_off,omitempty"`

	// Files declares templated files that should exist in every managed
	// repository. Each entry's Content is rendered through text/template with
	// {Org, Repo} context. Only (optional) limits which repos an entry applies
	// to via path.Match-style globs.
	Files []FileSpec `yaml:"files,omitempty"`

	// Legacy convenience flags. These are still honored but are materialized
	// into Files entries at load time. Prefer Files for new configurations.
	AddRenovateConfig bool   `yaml:"add_renovate_config,omitempty"`
	RenovateConfig    string `yaml:"renovate_config,omitempty"`
	AddDefaultReadme  bool   `yaml:"add_default_readme,omitempty"`
}

func (AppConfig) ResolvedAppID added in v0.3.0

func (a AppConfig) ResolvedAppID() int64

ResolvedAppID returns the GitHub App ID in effect, falling back to GITHUB_APP_ID when app.yaml does not set one. It is 0 under PAT auth, where there is no app.

type BypassActorConfig added in v0.3.0

type BypassActorConfig struct {
	Type    string `yaml:"type"`
	Team    string `yaml:"team,omitempty"`
	App     string `yaml:"app,omitempty"`
	ActorID int64  `yaml:"actor_id,omitempty"`
	Mode    string `yaml:"mode,omitempty"` // always|pull_request (default always)
}

BypassActorConfig grants an actor the right to bypass the ruleset.

Exactly one identifier applies per Type:

  • Team: Team names a team slug, resolved to its ID against the org.
  • Integration: App is either "self" (gomgr's own app_id, so its file-sync pushes survive a pull-request rule) or a numeric GitHub App ID.
  • RepositoryRole: ActorID is the role ID, which the roles API reports.
  • OrganizationAdmin, DeployKey: no identifier; GitHub fixes the ID.

func (BypassActorConfig) BypassMode added in v0.3.0

func (b BypassActorConfig) BypassMode() string

BypassMode returns the actor's bypass mode, defaulting to "always".

func (BypassActorConfig) IdentifiedByTypeAlone added in v0.3.0

func (b BypassActorConfig) IdentifiedByTypeAlone() bool

IdentifiedByTypeAlone reports whether GitHub recognizes this actor from its type without an ID. Such actors must be sent without one.

func (BypassActorConfig) NormalizedType added in v0.3.0

func (b BypassActorConfig) NormalizedType() string

NormalizedType returns the canonical, correctly-cased actor type for the GitHub API, or "" if the configured type is not recognized.

type CodeScanningRule added in v0.3.0

type CodeScanningRule struct {
	Tools []CodeScanningTool `yaml:"tools"`
}

CodeScanningRule blocks merges when a scanning tool reports alerts at or above the configured thresholds.

type CodeScanningTool added in v0.3.0

type CodeScanningTool struct {
	Tool                    string `yaml:"tool"`
	AlertsThreshold         string `yaml:"alerts_threshold,omitempty"`          // none|errors|errors_and_warnings|all
	SecurityAlertsThreshold string `yaml:"security_alerts_threshold,omitempty"` // none|critical|high_or_higher|medium_or_higher|all
}

CodeScanningTool sets the thresholds for one scanning tool, e.g. CodeQL.

type CustomRoleConfig added in v0.2.1

type CustomRoleConfig struct {
	Name        string   `yaml:"name"`
	Description string   `yaml:"description,omitempty"`
	BaseRole    string   `yaml:"base_role"` // read, triage, write, maintain, admin
	Permissions []string `yaml:"permissions,omitempty"`
}

CustomRoleConfig defines a custom repository role for the organization Requires GitHub Enterprise Cloud

type FileExtensionRestrictionRule added in v0.3.0

type FileExtensionRestrictionRule struct {
	RestrictedFileExtensions []string `yaml:"restricted_file_extensions"`
}

FileExtensionRestrictionRule blocks pushes touching the listed extensions.

type FilePathRestrictionRule added in v0.3.0

type FilePathRestrictionRule struct {
	RestrictedFilePaths []string `yaml:"restricted_file_paths"`
}

FilePathRestrictionRule blocks pushes touching the listed paths.

type FileSpec added in v0.2.5

type FileSpec struct {
	Path      string   `yaml:"path"`
	Content   string   `yaml:"content"`
	Message   string   `yaml:"message,omitempty"`
	Branch    string   `yaml:"branch,omitempty"`
	Only      []string `yaml:"only,omitempty"`
	Reconcile bool     `yaml:"reconcile,omitempty"`
}

FileSpec declares a file that gomgr should ensure exists in managed repos. Content is a Go text/template; Path, Message and Branch are literal strings. Only restricts which repositories the file applies to (path.Match globs against the repo name). An empty Only matches every managed repo.

Reconcile controls drift handling for files that already exist. When false (the default) gomgr only writes the file when it is missing, leaving any hand-edited content alone. When true gomgr compares the rendered content to what is on the default branch and pushes an update commit if they differ — useful for config-derived files like CODEOWNERS that should track the YAML.

type MergeQueueRule added in v0.3.0

type MergeQueueRule struct {
	MergeMethod                  string `yaml:"merge_method,omitempty"`      // merge|squash|rebase
	GroupingStrategy             string `yaml:"grouping_strategy,omitempty"` // allgreen|headgreen
	CheckResponseTimeoutMinutes  int    `yaml:"check_response_timeout_minutes,omitempty"`
	MaxEntriesToBuild            int    `yaml:"max_entries_to_build,omitempty"`
	MaxEntriesToMerge            int    `yaml:"max_entries_to_merge,omitempty"`
	MinEntriesToMerge            int    `yaml:"min_entries_to_merge,omitempty"`
	MinEntriesToMergeWaitMinutes int    `yaml:"min_entries_to_merge_wait_minutes,omitempty"`
}

MergeQueueRule routes merges through GitHub's merge queue.

type OrgConfig

type OrgConfig struct {
	Owners      []string           `yaml:"owners"`
	CustomRoles []CustomRoleConfig `yaml:"custom_roles,omitempty"`

	// Rulesets declares organization-wide rulesets — the guard rails that
	// apply across repositories, narrowed by their repository_name conditions.
	// Repository-specific rulesets live on the repository entry in teams/*.yaml
	// and stack on top of these; GitHub evaluates every ruleset that matches and
	// enforces the strictest outcome.
	Rulesets []RulesetConfig `yaml:"rulesets,omitempty"`
}

type PatternRule added in v0.3.0

type PatternRule struct {
	Name     string `yaml:"name,omitempty"`
	Operator string `yaml:"operator"` // starts_with|ends_with|contains|regex
	Pattern  string `yaml:"pattern"`
	Negate   *bool  `yaml:"negate,omitempty"`
}

PatternRule matches a commit message, email, branch name or tag name. Negate inverts the match, so the rule fails when the pattern *does* match.

type PullRequestRule added in v0.3.0

type PullRequestRule struct {
	RequiredApprovingReviewCount   int      `yaml:"required_approving_review_count,omitempty"`
	DismissStaleReviewsOnPush      bool     `yaml:"dismiss_stale_reviews_on_push,omitempty"`
	RequireCodeOwnerReview         bool     `yaml:"require_code_owner_review,omitempty"`
	RequireLastPushApproval        bool     `yaml:"require_last_push_approval,omitempty"`
	RequiredReviewThreadResolution bool     `yaml:"required_review_thread_resolution,omitempty"`
	AllowedMergeMethods            []string `yaml:"allowed_merge_methods,omitempty"` // merge|squash|rebase
}

PullRequestRule requires changes to arrive through a pull request.

type RefNameCondition added in v0.3.0

type RefNameCondition struct {
	Include []string `yaml:"include,omitempty"`
	Exclude []string `yaml:"exclude,omitempty"`
}

RefNameCondition selects refs by fnmatch pattern. GitHub also accepts the magic values "~ALL" and "~DEFAULT_BRANCH".

type RepoConfig added in v0.1.13

type RepoConfig struct {
	Permission string          `yaml:"permission,omitempty"` // pull|triage|push|maintain|admin
	Topics     []string        `yaml:"topics,omitempty"`
	Pinned     bool            `yaml:"pinned,omitempty"`
	Rulesets   []RulesetConfig `yaml:"rulesets,omitempty"`
}

type RepositoryNameCondition added in v0.3.0

type RepositoryNameCondition struct {
	Include   []string `yaml:"include,omitempty"`
	Exclude   []string `yaml:"exclude,omitempty"`
	Protected *bool    `yaml:"protected,omitempty"`
}

RepositoryNameCondition selects repositories by fnmatch pattern, or "~ALL". Protected, when set, additionally restricts to repositories GitHub considers protected.

type RequiredDeploymentsRule added in v0.3.0

type RequiredDeploymentsRule struct {
	Environments []string `yaml:"environments"`
}

RequiredDeploymentsRule requires deployments to the named environments to succeed before merge.

type RequiredStatusChecksRule added in v0.3.0

type RequiredStatusChecksRule struct {
	Checks               []StatusCheck `yaml:"checks"`
	Strict               bool          `yaml:"strict,omitempty"`
	DoNotEnforceOnCreate *bool         `yaml:"do_not_enforce_on_create,omitempty"`
}

RequiredStatusChecksRule requires named checks to pass before merge. Strict additionally requires the branch to be up to date with its base.

type Root

type Root struct {
	App  AppConfig    `yaml:"app"`
	Org  OrgConfig    `yaml:"org"`
	Team []TeamConfig `yaml:"teams"`
}

func Load

func Load(dir string) (*Root, error)

func (*Root) Validate added in v0.2.3

func (r *Root) Validate() error

Validate checks that the loaded configuration is semantically correct.

type RuleWorkflow added in v0.3.0

type RuleWorkflow struct {
	Path         string `yaml:"path"`
	Repository   string `yaml:"repository,omitempty"` // repo name in this org; resolved to an ID
	RepositoryID *int64 `yaml:"repository_id,omitempty"`
	Ref          string `yaml:"ref,omitempty"`
	SHA          string `yaml:"sha,omitempty"`
}

RuleWorkflow points at a workflow file, optionally pinned to a ref or SHA in a specific repository.

type RulesetConditions added in v0.3.0

type RulesetConditions struct {
	RefName        *RefNameCondition        `yaml:"ref_name,omitempty"`
	RepositoryName *RepositoryNameCondition `yaml:"repository_name,omitempty"`
}

RulesetConditions narrows which refs and repositories a ruleset applies to. RepositoryName is only meaningful for organization-level rulesets; a repository-level ruleset already knows its repository.

type RulesetConfig added in v0.3.0

type RulesetConfig struct {
	Name         string              `yaml:"name"`
	Preset       string              `yaml:"preset,omitempty"`
	Target       string              `yaml:"target,omitempty"`      // branch|tag|push (default branch)
	Enforcement  string              `yaml:"enforcement,omitempty"` // active|evaluate|disabled (default active)
	Conditions   *RulesetConditions  `yaml:"conditions,omitempty"`
	BypassActors []BypassActorConfig `yaml:"bypass_actors,omitempty"`
	Rules        RulesetRules        `yaml:"rules,omitempty"`
}

RulesetConfig declares a GitHub ruleset — the successor to branch protection, and the mechanism behind org-wide guard rails.

The same shape is used at both scopes:

  • org.yaml `rulesets:` applies across the organization, narrowed by Conditions.RepositoryName.
  • a repository entry in teams/*.yaml may carry its own `rulesets:`, which apply to that repository alone and stack on top of the org's.

Preset names a built-in guard rail (see RulesetPresets) that supplies the target, conditions and rules. Anything set explicitly alongside it wins, at whole-rule granularity: naming a rule key replaces the preset's version of that rule outright rather than merging field by field.

func ParseRulesets added in v0.3.0

func ParseRulesets(v any) ([]RulesetConfig, error)

ParseRulesets decodes a `rulesets:` value that arrived as an untyped YAML node — the shape repository entries in teams/*.yaml are held in. Round-tripping through YAML keeps RulesetConfig the single definition of the schema instead of duplicating the field walk here.

func (RulesetConfig) Resolve added in v0.3.0

func (r RulesetConfig) Resolve() (RulesetConfig, error)

Resolve expands the ruleset's preset and fills in defaults, returning a configuration with Target and Enforcement always set. The receiver is not modified.

type RulesetRules added in v0.3.0

type RulesetRules struct {
	// Branch and tag rules.
	Creation                 *bool                     `yaml:"creation,omitempty"`
	Update                   *UpdateRule               `yaml:"update,omitempty"`
	Deletion                 *bool                     `yaml:"deletion,omitempty"`
	RequiredLinearHistory    *bool                     `yaml:"required_linear_history,omitempty"`
	RequiredSignatures       *bool                     `yaml:"required_signatures,omitempty"`
	NonFastForward           *bool                     `yaml:"non_fast_forward,omitempty"`
	PullRequest              *PullRequestRule          `yaml:"pull_request,omitempty"`
	RequiredStatusChecks     *RequiredStatusChecksRule `yaml:"required_status_checks,omitempty"`
	RequiredDeployments      *RequiredDeploymentsRule  `yaml:"required_deployments,omitempty"`
	MergeQueue               *MergeQueueRule           `yaml:"merge_queue,omitempty"`
	CommitMessagePattern     *PatternRule              `yaml:"commit_message_pattern,omitempty"`
	CommitAuthorEmailPattern *PatternRule              `yaml:"commit_author_email_pattern,omitempty"`
	CommitterEmailPattern    *PatternRule              `yaml:"committer_email_pattern,omitempty"`
	BranchNamePattern        *PatternRule              `yaml:"branch_name_pattern,omitempty"`
	TagNamePattern           *PatternRule              `yaml:"tag_name_pattern,omitempty"`
	Workflows                *WorkflowsRule            `yaml:"workflows,omitempty"`
	CodeScanning             *CodeScanningRule         `yaml:"code_scanning,omitempty"`

	// Push rules. These require GitHub Enterprise Cloud on private repositories.
	FileExtensionRestriction *FileExtensionRestrictionRule `yaml:"file_extension_restriction,omitempty"`
	FilePathRestriction      *FilePathRestrictionRule      `yaml:"file_path_restriction,omitempty"`
	MaxFilePathLength        *int                          `yaml:"max_file_path_length,omitempty"`
	MaxFileSize              *int64                        `yaml:"max_file_size,omitempty"`
}

RulesetRules is the YAML face of GitHub's rule list. Every field is a pointer so that "unset" is distinguishable from "explicitly off" — a preset can turn a rule on and the config can turn it back off with `deletion: false`.

Field order here is also the merge order used by mergeRules; adding a field requires no change there as long as it stays nil-able.

func (RulesetRules) IsEmpty added in v0.3.0

func (rr RulesetRules) IsEmpty() bool

IsEmpty reports whether no rule at all is enabled. A ruleset with no rules is accepted by GitHub but enforces nothing, so it is worth catching in validation.

type RulesetScope added in v0.3.0

type RulesetScope string

RulesetScope distinguishes the two places a ruleset can be declared, because a few rules are only legal at one of them.

const (
	// ScopeOrg is org.yaml `rulesets:` — applies across the organization.
	ScopeOrg RulesetScope = "org"
	// ScopeRepo is a `rulesets:` block on a repository in teams/*.yaml.
	ScopeRepo RulesetScope = "repo"
)

type StatusCheck added in v0.3.0

type StatusCheck struct {
	Context       string `yaml:"context"`
	IntegrationID *int64 `yaml:"integration_id,omitempty"`
}

StatusCheck names a required check. IntegrationID pins the check to a specific GitHub App, so an unrelated app cannot report the same context.

type TeamConfig

type TeamConfig struct {
	Name        string   `yaml:"name"`
	Slug        string   `yaml:"slug,omitempty"`
	Description string   `yaml:"description,omitempty"`
	Privacy     string   `yaml:"privacy,omitempty"` // closed, secret
	Parents     []string `yaml:"parents,omitempty"`

	Maintainers []string `yaml:"maintainers,omitempty"`
	Members     []string `yaml:"members,omitempty"`

	// repo => permission (pull|triage|push|maintain|admin) or RepoConfig for advanced settings
	// For backward compatibility, supports both:
	//   repositories:
	//     infra: maintain               # simple string permission
	//     api:                          # or advanced RepoConfig
	//       permission: push
	//       topics: [backend, api]
	//       pinned: true
	Repositories map[string]any `yaml:"repositories,omitempty"`
}

func (TeamConfig) ResolvedSlug added in v0.2.3

func (t TeamConfig) ResolvedSlug() string

ResolvedSlug returns the team's slug, deriving it from the name if not explicitly set.

type UpdateRule added in v0.3.0

type UpdateRule struct {
	AllowsFetchAndMerge bool `yaml:"allows_fetch_and_merge,omitempty"`
}

UpdateRule restricts updates to a matching ref.

type WorkflowsRule added in v0.3.0

type WorkflowsRule struct {
	Workflows            []RuleWorkflow `yaml:"workflows"`
	DoNotEnforceOnCreate *bool          `yaml:"do_not_enforce_on_create,omitempty"`
}

WorkflowsRule requires the named workflows to have run.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL