Documentation
¶
Overview ¶
Package registry loads and validates the GitHub plane registry — one YAML file (github.yaml at the root of the fs.FS handed to Load) describing every org the structure engine owns: org settings, teams, repos (a settings profile plus per-repo overrides with reasons), the GitHub Apps the org depends on, and the Actions runner groups ARC registers scale sets against.
The registry is DESIRED STATE for everything Pulumi can apply and INVENTORY for everything it cannot (App creation, App installation and App permission edits have no API — see docs/operations/github-apps-day1.md). Rows marked external are third-party Apps: drift detection only.
Company-agnosticism is the design constraint. Profiles are top-level and shared, so a second org (INF-473, the TP migration) is a new `orgs:` key referencing the same `public`/`private` profiles — never new code.
Index ¶
- Constants
- func InstallationIDField(org, primaryOrg string) string
- type ActionsSettings
- type App
- type AppCredentials
- type BranchRuleset
- type Config
- type Org
- type OrgActions
- type OrgSettings
- type OrgVariable
- type ProtectionSettings
- type Repo
- type RepoSettings
- type Resolved
- type ResolvedActions
- type ResolvedProtection
- type RunnerGroup
- type SecurityConfiguration
- type TagRuleset
- type Team
Constants ¶
const ( PermPull = "pull" PermTriage = "triage" PermPush = "push" PermMaintain = "maintain" PermAdmin = "admin" )
Team permission levels, in ascending order of power. These are the values GitHub accepts for a team's permission on a repository.
const ( VisibilityPublic = "public" VisibilityPrivate = "private" )
Repository visibility values.
const ( PrivacyClosed = "closed" PrivacySecret = "secret" )
Team privacy values. GitHub calls a visible team "closed" and a hidden one "secret"; nested teams must be closed.
const ( NotificationsEnabled = "enabled" NotificationsDisabled = "disabled" )
Team notification settings.
const ( ActionsAll = "all" ActionsLocalOnly = "local_only" ActionsSelected = "selected" WorkflowPermissionRead = "read" WorkflowPermissionWrit = "write" )
Actions allowed-actions policy values.
const ( InstallAll = "all" InstallSelected = "selected" )
App installation scope values.
const ( RunnerVisibilityAll = "all" RunnerVisibilitySelected = "selected" RunnerVisibilityPrivate = "private" )
Runner-group visibility values.
const ( FieldAppID = "github-app-id" FieldInstallationID = "github-installation-id" FieldPrivateKey = "github-private-key" FieldClientID = "github-client-id" FieldClientSecret = "github-client-secret" FieldWebhookSecret = "github-webhook-secret" )
The credential field-name convention for App credentials. Every App's secret-store item uses exactly these names, so a consumer (or an AI agent session) can find credentials knowing only the App name.
Variables ¶
This section is empty.
Functions ¶
func InstallationIDField ¶
InstallationIDField returns the field holding an App's installation ID for the given organization. The App's PRIMARY org uses the bare `github-installation-id`; any additional installation of the same App — the roster's sandbox org being the one sanctioned case — is suffixed with the org, so a test installation can never be mistaken for, or overwrite, the production one.
Types ¶
type ActionsSettings ¶
type ActionsSettings struct {
AllowedActions *string `yaml:"allowed_actions,omitempty"`
DefaultWorkflowPermissions *string `yaml:"default_workflow_permissions,omitempty"`
CanApprovePullRequests *bool `yaml:"can_approve_pull_request_reviews,omitempty"`
}
ActionsSettings is the repo's GitHub Actions policy.
type App ¶
type App struct {
// External marks a vendor App: inventory + drift detection only.
// We never create, install or edit those.
External bool `yaml:"external,omitempty"`
// Adopted marks an App we author that predates this registry and
// whose 1Password item has not been normalized to the field
// convention yet. Such a row is inventory + drift only until the
// item is normalized and credentials are filled in — at which
// point the flag goes away. It is deliberately narrow: a row can
// be credential-less only by admitting it in writing.
Adopted bool `yaml:"adopted,omitempty"`
// Description is the App blurb (ours: rendered into the manifest).
Description string `yaml:"description,omitempty"`
// URL is the App's homepage (ours: required by the manifest flow).
URL string `yaml:"url,omitempty"`
// AppID and InstallationID are recorded once known. Optional —
// drift detection keys on the App slug, so a freshly registered
// row works before its first creation.
AppID int64 `yaml:"app_id,omitempty"`
InstallationID int64 `yaml:"installation_id,omitempty"`
// Install is the installation's repository scope.
Install string `yaml:"install"`
// Repos scopes a `selected` installation. Empty means "not read
// yet" — there is no REST endpoint to read another App's scope
// with a user token (snapshot §4.3).
Repos []string `yaml:"repos,omitempty"`
// Permissions is the App's permission set, keyed exactly as
// GET /orgs/{org}/installations reports it.
Permissions map[string]string `yaml:"permissions"`
// Events are the webhook events the App subscribes to.
Events []string `yaml:"events,omitempty"`
// WebhookURL is where GitHub delivers events. Empty means the App
// is API-only and the manifest omits the webhook block entirely —
// GitHub rejects a hook_attributes object that has no url.
WebhookURL string `yaml:"webhook_url,omitempty"`
// Credentials locate the App's secrets. Required for ours,
// forbidden for external rows (we never hold vendor keys).
Credentials *AppCredentials `yaml:"credentials,omitempty"`
// Note carries context a future reader needs (why it exists, what
// replaced it, which ticket retires it).
Note string `yaml:"note,omitempty"`
}
App is one GitHub App the org depends on.
type AppCredentials ¶
type AppCredentials struct {
// OpItem names the item in the estate's credential store (for
// truvity, a 1Password item in the breakglass vault). Always
// required: every App the engine authors has a source of truth.
OpItem string `yaml:"op_item"`
// SSMPrefix is where the estate mirrors the item for machine
// consumers (for truvity, cfg/secrets.yaml → SSM).
//
// Optional, because mirroring is a CONSUMER's need, not a
// property of the App. An App consumed only from GitHub itself
// (Renovate on public repos, whose key is copied by hand into a
// scoped org secret — INF-491) has a 1Password item and no SSM
// path at all.
SSMPrefix string `yaml:"ssm_prefix,omitempty"`
}
AppCredentials is the one credential doctrine: 1Password is the source of truth, SSM is the mirror. The field names inside the 1Password item are fixed by convention (see FieldAppID and friends).
type BranchRuleset ¶
type BranchRuleset struct {
// Name is the ruleset's display name, unique within the repo.
Name string `yaml:"name"`
// Pattern is the ref pattern (e.g. ~DEFAULT_BRANCH).
Pattern string `yaml:"pattern"`
// RequiredApprovals is the PR review count the ruleset enforces.
RequiredApprovals int `yaml:"required_approvals"`
// BypassApps are GitHub App DATABASE ids (not node ids) allowed
// to bypass — how renovate automerges its green PRs.
BypassApps []int `yaml:"bypass_apps"`
// BypassOrgAdmins lets organization admins merge without the
// review. Rulesets, unlike classic protection, do NOT exempt
// admins implicitly: moving bar's approval gate into a ruleset
// (D11) silently removed the admin bypass the repo had relied
// on, blocking its own maintainers' PRs. Set this to keep the
// pre-ruleset behavior explicit rather than accidental.
BypassOrgAdmins bool `yaml:"bypass_org_admins,omitempty"`
}
BranchRuleset is one branch-target ruleset row: a PR approval gate with App bypass (see the field comment on Repo).
type Config ¶
type Config struct {
// Profiles are the shared repo settings vocabulary. Every repo row
// names exactly one; per-repo overrides layer on top.
Profiles map[string]*RepoSettings `yaml:"profiles"`
// Orgs maps a GitHub org login to its desired structure.
Orgs map[string]*Org `yaml:"orgs"`
}
Config is the whole registry.
func (*Config) AppPrefixFor ¶
AppPrefixFor returns the App name prefix for the named org.
func (*Config) Resolve ¶
Resolve layers a repo's overrides over its profile. Callers must have validated the config first (Load does); an unknown profile resolves to the zero value rather than panicking.
func (*Config) ResolveRepo ¶
ResolveRepo is the by-name form of Resolve.
func (*Config) SortedOrgs ¶
SortedOrgs returns org logins in deterministic order.
type Org ¶
type Org struct {
// Company links this org to a cfg/companies.yaml row. Truvity is
// the incumbent and has no code there; other orgs must name one.
Company string `yaml:"company,omitempty"`
// AppPrefix is the mandatory name prefix for Apps we author in
// this org — App display names are globally unique on GitHub.
// Defaults to "{org}-".
AppPrefix string `yaml:"app_prefix,omitempty"`
// CredentialsSSMPrefix is where the structure engine's own App
// credentials live in the estate's secret store — the caller
// reads them from there and hands engine.Credentials to Deploy.
CredentialsSSMPrefix string `yaml:"credentials_ssm_prefix"`
// Settings are the org-level toggles.
Settings *OrgSettings `yaml:"settings"`
// Owners are the organization's owners (GitHub's `admin` org
// role), by login. This is the half of a contract the roster
// service already keeps its side of: it renders owners from
// CURRENT state and never computes them, because "owners are
// registry-pinned and change by reviewed infrastructure
// commit". This registry is that pin.
//
// ASSERTED, NOT RECONCILED. Each login gets its own resource,
// so the engine can promote a listed login but can never
// demote one you forgot to list — a full-set model here would
// make "omitted the block" mean "remove every owner", which is
// the accident neither service may have. Divergence between
// live and declared is reported by `githubctl drift`, where a
// human decides, exactly as org variables work.
//
// Removing a login from this list DEMOTES them to member; it
// does not evict them from the org (DowngradeOnDestroy).
Owners []string `yaml:"owners,omitempty"`
// Teams are the org's teams, keyed by slug. Membership is NOT
// modeled here — that is the roster service's territory
// (INF-484/INF-487); this engine owns structure only.
Teams map[string]*Team `yaml:"teams"`
// Repos are the in-scope repositories, keyed by name.
Repos map[string]*Repo `yaml:"repos"`
// Apps are the GitHub Apps the org depends on.
Apps map[string]*App `yaml:"apps"`
// RunnerGroups are the Actions runner groups ARC targets.
RunnerGroups map[string]*RunnerGroup `yaml:"runner_groups,omitempty"`
// SecurityConfigurations is INVENTORY, never desired state: the
// provider has no resource for code security configurations, and
// an enforced one makes GitHub reject per-repository writes to
// the settings it covers. Recorded so the registry still answers
// "who owns Dependabot alerts" — the same role the `external`
// App rows play. See
// docs/operations/github-security-configurations.md.
SecurityConfigurations map[string]*SecurityConfiguration `yaml:"security_configurations,omitempty"`
}
Org is one GitHub organization.
func (*Org) ChecksWaived ¶
ChecksWaived lists the repos currently running without their profile's required checks, with the reason for each. Enumerable on purpose: an exception nobody can list is an exception nobody revisits.
func (*Org) SortedApps ¶
SortedApps returns App names in deterministic order.
func (*Org) SortedRepos ¶
SortedRepos returns repo names in deterministic order.
func (*Org) SortedRunnerGroups ¶
SortedRunnerGroups returns runner-group names in deterministic order.
func (*Org) SortedTeams ¶
SortedTeams returns team slugs in deterministic order.
type OrgActions ¶
type OrgActions struct {
AllowedActions string `yaml:"allowed_actions"`
EnabledRepositories string `yaml:"enabled_repositories"`
ShaPinningRequired bool `yaml:"sha_pinning_required"`
DefaultWorkflowPermissions string `yaml:"default_workflow_permissions"`
CanApprovePullRequests bool `yaml:"can_approve_pull_request_reviews"`
// Variables are org-level Actions variables: the particulars a
// PUBLIC shared workflow must never contain (runner labels, bucket
// names, in-cluster URLs). The workflow reads them from the
// caller's context, so the same public code serves both orgs
// without either one's estate appearing in it.
Variables map[string]*OrgVariable `yaml:"variables,omitempty"`
}
OrgActions is the organization's GitHub Actions policy.
type OrgSettings ¶
type OrgSettings struct {
// DisplayName is the organization's profile name — the "Name"
// field in the UI, NOT the URL slug (that is the immutable
// `login`). Empty means unmanaged, which is what D9 asked for
// while it was null.
//
// Setting it is also what stops Pulumi auto-naming the resource
// and pushing a generated string like "org-truvity-1fd213c" onto
// the organization.
DisplayName string `yaml:"display_name,omitempty"`
// Billing is deliberately NOT here (decided 2026-07-31): it is
// the IT team's, managed in the GitHub UI. The provider's
// settings resource requires the field, so the engine passes the
// org's live value through and never diffs it.
DefaultRepositoryPermission string `yaml:"default_repository_permission"`
MembersCanCreateRepositories bool `yaml:"members_can_create_repositories"`
MembersCanCreatePublicRepositories bool `yaml:"members_can_create_public_repositories"`
MembersCanCreatePrivateRepositories bool `yaml:"members_can_create_private_repositories"`
MembersCanCreateInternalRepositories bool `yaml:"members_can_create_internal_repositories"`
MembersCanCreatePages bool `yaml:"members_can_create_pages"`
MembersCanCreatePublicPages bool `yaml:"members_can_create_public_pages"`
MembersCanCreatePrivatePages bool `yaml:"members_can_create_private_pages"`
MembersCanForkPrivateRepositories bool `yaml:"members_can_fork_private_repositories"`
WebCommitSignoffRequired bool `yaml:"web_commit_signoff_required"`
HasOrganizationProjects bool `yaml:"has_organization_projects"`
HasRepositoryProjects bool `yaml:"has_repository_projects"`
DependabotAlertsEnabledForNewRepos bool `yaml:"dependabot_alerts_enabled_for_new_repositories"`
DependabotSecurityUpdatesForNewRepos bool `yaml:"dependabot_security_updates_enabled_for_new_repositories"`
DependencyGraphEnabledForNewRepos bool `yaml:"dependency_graph_enabled_for_new_repositories"`
AdvancedSecurityEnabledForNewRepos bool `yaml:"advanced_security_enabled_for_new_repositories"`
SecretScanningForNewRepos bool `yaml:"secret_scanning_enabled_for_new_repositories"`
SecretScanningPushProtForNewRepos bool `yaml:"secret_scanning_push_protection_enabled_for_new_repositories"`
// Actions is the ORG-level Actions policy — the ceiling every
// repository's own policy sits under (INF-410's "Actions org
// permissions"). Readable only through the App: a human token
// with read:org gets 403.
Actions *OrgActions `yaml:"actions"`
}
OrgSettings are the org-level toggles the engine owns.
The remaining cosmetic fields (description, blog, location) stay absent: they are null today and managing null invites diff noise (D9). DisplayName is the exception — see its comment.
type OrgVariable ¶
type OrgVariable struct {
Value string `yaml:"value"`
// Visibility is private | selected | all, defaulting to PRIVATE —
// the safe end. A variable naming internal infrastructure that
// drifts to `all` becomes readable by any public repository's
// workflow, which is exactly the leak the public shared workflow
// exists to avoid. `selected` additionally carries a repository
// list that is NOT modeled here; the drift check reports the
// visibility, not the membership.
Visibility string `yaml:"visibility,omitempty"`
}
OrgVariable is one org-level Actions variable.
type ProtectionSettings ¶
type ProtectionSettings struct {
Enabled *bool `yaml:"enabled,omitempty"`
// RequiredChecks are status-check contexts. A context declared
// here that no workflow produces blocks every PR forever — see
// the snapshot's D1.
RequiredChecks *[]string `yaml:"required_checks,omitempty"`
// Strict is GitHub's "branch must be up to date before merging".
// False fleet-wide: the public-repo CI lesson.
Strict *bool `yaml:"strict,omitempty"`
// EnforceAdmins applies the rule to admins too.
EnforceAdmins *bool `yaml:"enforce_admins,omitempty"`
// RequiredApprovals of 0 means NO review requirement block at all.
RequiredApprovals *int `yaml:"required_approvals,omitempty"`
// PullRequestBypassers are actors whose PRs skip the REVIEW
// requirement (checks stay required). Format: usernames,
// org/team slugs, or /<app-slug> (the provider's leading-slash
// convention for Apps — app/<slug> fails to resolve). This is how automation
// (renovate) automerges its green non-major PRs on a repo
// whose humans still need review — policy-as-code instead of
// a bot rubber-stamping approvals. Requires
// required_approvals > 0 (bypassing a review nobody requires
// is a config smell the validator rejects).
PullRequestBypassers *[]string `yaml:"pull_request_bypassers,omitempty"`
DismissStaleReviews *bool `yaml:"dismiss_stale_reviews,omitempty"`
RequireCodeOwnerReviews *bool `yaml:"require_code_owner_reviews,omitempty"`
RequireConvResolution *bool `yaml:"require_conversation_resolution,omitempty"`
RequireLinearHistory *bool `yaml:"require_linear_history,omitempty"`
RequireSignatures *bool `yaml:"require_signatures,omitempty"`
AllowForcePushes *bool `yaml:"allow_force_pushes,omitempty"`
AllowDeletions *bool `yaml:"allow_deletions,omitempty"`
}
ProtectionSettings is the default branch's protection rule. Enabled:false means "no protection rule at all" (GitHub 404s), not "an empty rule" — the two are different states.
type Repo ¶
type Repo struct {
// Profile names a key in Config.Profiles.
Profile string `yaml:"profile"`
// Description is the repo blurb; empty means unmanaged.
Description string `yaml:"description,omitempty"`
// Teams are grants ADDED to the profile's team map (or upgrades
// of a profile grant). Removing a profile grant is not expressible
// on purpose — that is a profile change, not a repo exception.
Teams map[string]string `yaml:"teams,omitempty"`
// TagRulesets are repository rulesets targeting tags: each
// restricts creation, update and deletion of refs matching its
// pattern to the listed bypass teams. This is how a release act
// (a {project}/v* tag) gets an owner: push access to the repo no
// longer implies the right to cut a release.
//
// Per-repo and raw (not part of the profile/override merge):
// which tag namespaces exist is a property of the repo's release
// contract, not of its settings tier.
TagRulesets []*TagRuleset `yaml:"tag_rulesets,omitempty"`
// BranchRulesets are repository rulesets targeting branches —
// today expressing exactly one shape: a pull-request approval
// requirement that named GitHub Apps may bypass. This exists
// because classic protection cannot carry an App bypass under
// the engine's App auth at all: referencing an App actor fails
// with "Resource not accessible by integration" on write AND
// wedges refresh once set via REST (observed 2026-08-15, D11).
// Rulesets take Integration bypass actors by database ID over
// REST — the same machinery the tag rulesets already use.
BranchRulesets []*BranchRuleset `yaml:"branch_rulesets,omitempty"`
// ChecksWaived suspends the profile's required status checks for
// this repo, and its value is the reason.
//
// This exists because the failure mode is silent and total:
// requiring a check context that no workflow produces blocks
// EVERY pull request, forever. A repo whose CI has not landed
// yet therefore needs an explicit, per-repo escape — while the
// profile keeps stating the intent, so the exception is visible
// as an exception rather than as a profile that asks for
// nothing (INF-410).
//
// Lifting it is deleting one line. Waiving checks a profile does
// not require is rejected, so a waiver cannot outlive its cause.
ChecksWaived string `yaml:"checks_waived,omitempty"`
// Overrides are per-repo settings deviations. Every override is a
// documented decision (see the snapshot's D-table); Reason says
// which, so a future reader knows whether it is permanent.
Overrides *RepoSettings `yaml:"overrides,omitempty"`
// Reason explains the overrides. Required when Overrides is set.
Reason string `yaml:"reason,omitempty"`
// Archived retires the repository: read-only on GitHub, and here
// reduced to a single owned attribute.
//
// GitHub rejects settings writes on an archived repository, so
// the engine declares NOTHING else for one — no Actions
// permissions, no workflow permissions, no branch protection —
// and ignores every settings input on the repository itself.
// Only `archived` is owned; the rest is frozen at whatever it
// held on the way in.
//
// This is what keeps a retirement expressible. Before it existed
// the only options were to leave a live row that 403s on every
// run — the trap that wedged the engine during the INF-512
// sdk-python adoption — or to drop the row and hand-archive,
// which puts the repo outside the registry and leaves a
// protected orphan in state. See
// docs/operations/github-repo-archival.md.
//
// Reversible: clear the flag and the row resumes full
// management, because unarchiving is itself a settings write the
// provider makes before any other.
Archived bool `yaml:"archived,omitempty"`
}
Repo is one repository row: a profile reference plus the deviations that survived the keep-or-fix review.
type RepoSettings ¶
type RepoSettings struct {
Visibility *string `yaml:"visibility,omitempty"`
HasIssues *bool `yaml:"has_issues,omitempty"`
HasWiki *bool `yaml:"has_wiki,omitempty"`
HasProjects *bool `yaml:"has_projects,omitempty"`
AllowAutoMerge *bool `yaml:"allow_auto_merge,omitempty"`
AllowSquashMerge *bool `yaml:"allow_squash_merge,omitempty"`
AllowMergeCommit *bool `yaml:"allow_merge_commit,omitempty"`
AllowRebaseMerge *bool `yaml:"allow_rebase_merge,omitempty"`
DeleteBranchOnMerge *bool `yaml:"delete_branch_on_merge,omitempty"`
AllowUpdateBranch *bool `yaml:"allow_update_branch,omitempty"`
AllowForking *bool `yaml:"allow_forking,omitempty"`
HasDownloads *bool `yaml:"has_downloads,omitempty"`
DefaultBranch *string `yaml:"default_branch,omitempty"`
Actions *ActionsSettings `yaml:"actions,omitempty"`
Protection *ProtectionSettings `yaml:"protection,omitempty"`
// Teams is the profile's baseline team grant map. On an override
// it is ignored — repo-level grants live in Repo.Teams.
Teams map[string]string `yaml:"teams,omitempty"`
}
RepoSettings is both a profile (all fields set) and an override (any subset). Pointers distinguish "not specified" from "false" — the whole reason overrides can be partial.
type Resolved ¶
type Resolved struct {
Visibility string
HasIssues bool
HasWiki bool
HasProjects bool
AllowAutoMerge bool
AllowSquashMerge bool
AllowMergeCommit bool
AllowRebaseMerge bool
DeleteBranchOnMerge bool
AllowUpdateBranch bool
AllowForking bool
HasDownloads bool
DefaultBranch string
Description string
// Archived is the repo row's own flag, never a profile's: a
// retirement is a fact about one repository, not a class of
// them. When set, every field above is inert — the engine
// ignores them rather than planning writes GitHub will reject.
Archived bool
Actions ResolvedActions
Protection ResolvedProtection
// Teams is the profile's grants merged with the repo's own. A
// repo grant wins over the profile's for the same team.
Teams map[string]string
}
Resolved is a repo's fully-determined settings: the profile with the repo's overrides layered on top. Every field is concrete — the Pulumi program never sees a pointer and never has to guess a default.
type ResolvedActions ¶
type ResolvedActions struct {
AllowedActions string
DefaultWorkflowPermissions string
CanApprovePullRequests bool
}
ResolvedActions is a repo's concrete Actions policy.
type ResolvedProtection ¶
type ResolvedProtection struct {
Enabled bool
RequiredChecks []string
Strict bool
EnforceAdmins bool
RequiredApprovals int
PullRequestBypassers []string
DismissStaleReviews bool
RequireCodeOwnerReviews bool
RequireConvResolution bool
RequireLinearHistory bool
RequireSignatures bool
AllowForcePushes bool
AllowDeletions bool
}
ResolvedProtection is a repo's concrete branch-protection rule. Enabled:false means no rule exists at all.
type RunnerGroup ¶
type RunnerGroup struct {
Visibility string `yaml:"visibility"`
Repos []string `yaml:"repos,omitempty"`
AllowsPublicRepositories bool `yaml:"allows_public_repositories,omitempty"`
RestrictedToWorkflows bool `yaml:"restricted_to_workflows,omitempty"`
SelectedWorkflows []string `yaml:"selected_workflows,omitempty"`
}
RunnerGroup is an Actions runner group — the GitHub-side half of the ARC scale-set model (which repos may target which runners).
type SecurityConfiguration ¶
type SecurityConfiguration struct {
Enforcement string `yaml:"enforcement"`
DependabotAlerts string `yaml:"dependabot_alerts"`
DependabotSecurityUpdates string `yaml:"dependabot_security_updates"`
AppliesTo string `yaml:"applies_to"`
}
SecurityConfiguration is one org-level code security configuration, recorded for humans. Nothing reads these fields.
type TagRuleset ¶
type TagRuleset struct {
// Name is the ruleset's display name, unique within the repo.
Name string `yaml:"name"`
// Pattern is the fnmatch ref pattern the ruleset covers; it must
// start with refs/tags/ (this type expresses tag rulesets only).
Pattern string `yaml:"pattern"`
// BypassTeams are the org team slugs allowed to create, update
// and delete matching tags. At least one is required: a ruleset
// nobody can bypass makes the tag namespace permanently
// unwritable, which is a bricked release path, not protection.
BypassTeams []string `yaml:"bypass_teams"`
}
TagRuleset is one tag-protection ruleset row on a repository.
type Team ¶
type Team struct {
Name string `yaml:"name,omitempty"`
Description string `yaml:"description,omitempty"`
Privacy string `yaml:"privacy,omitempty"`
Parent string `yaml:"parent,omitempty"`
Notifications string `yaml:"notifications,omitempty"`
}
Team is one org team. Nesting is expressed by Parent (a team slug).