Documentation
¶
Overview ¶
Package catalogue is GitHub Apps declared as data: what each App is called, which organisation owns it, what it may do, and — for a later exchange that mints installation tokens — which groups may ask for how much of it.
The deployment declares a catalogue; an operator creates and installs each App from the console in two clicks, and the service keeps its key. The roster's own Apps (an organisation's controller App, the link App, a runner App) are expressed in the same shape, so one manifest builder serves them all.
A catalogue is read once, at start, and a malformed one stops the service: an App declared wrongly and created anyway is an App with the wrong permissions that nobody can change from here — GitHub has no API for that.
Index ¶
Constants ¶
const ( // InstallationAll is every repository in the organisation, now and // later. InstallationAll = "all" // InstallationSelected is the repositories the installer picks. InstallationSelected = "selected" )
The two installation scopes an App can be declared with. Informational: GitHub's install page is where the installer chooses, and this says which choice the deployment expects.
const ( LevelRead = "read" LevelWrite = "write" LevelAdmin = "admin" )
The permission levels GitHub grants, in order: each includes the ones before it.
const NameLimit = 34
NameLimit is GitHub's length limit on an App's name.
const RunnerPrefix = "runner-"
RunnerPrefix begins the name of a runner App's secret at external/github/runner-<tier>-<org> (ADR 0041), so a catalogue App's id may not begin with it.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type App ¶
type App struct {
// ID names the App here: it is the storage key and never changes for
// the life of the App.
ID string `yaml:"id"`
// Org is the organisation the App is created under.
Org string `yaml:"org"`
// Name is the App's name on GitHub. Empty is "<org>-<id>", cut to
// GitHub's limit.
Name string `yaml:"name,omitempty"`
Description string `yaml:"description,omitempty"`
// Public lets any account install the App. A private App installs only
// on the organisation that owns it.
Public bool `yaml:"public,omitempty"`
// Permissions are GitHub permission names to read, write or admin.
Permissions map[string]string `yaml:"permissions"`
// Events are the webhook events the App subscribes to. The webhook is
// active only when Webhook says where it goes; without it the App
// subscribes to events nothing receives.
Events []string `yaml:"events,omitempty"`
// Webhook is where GitHub delivers the events: one URL, or a Kargo
// receiver. Unset leaves the webhook inactive.
Webhook *Webhook `yaml:"webhook,omitempty"`
// Installation is all or selected; empty is selected.
Installation string `yaml:"installation,omitempty"`
// Export places an installed App's key at external/github/<id> for a
// consumer to read (layout v4, ADR 0041). Unset keeps the key internal.
// A runner App is always exported, and is not in the catalogue.
Export bool `yaml:"export,omitempty"`
// Grants say which groups may ask for tokens of this App, for which
// repositories and with at most which permissions.
Grants []Grant `yaml:"grants,omitempty"`
}
App is one declared App.
func (*App) DisplayName ¶
DisplayName is the App's name on GitHub: the declared one, or "<org>-<id>" cut to GitHub's limit.
func (*App) InstallationScope ¶
InstallationScope is the declared scope, defaulted.
type Catalogue ¶
type Catalogue struct {
Apps []App `yaml:"apps"`
}
Catalogue is every declared App, in declaration order.
func Parse ¶
Parse reads a catalogue strictly — an unknown key is an error, because a misspelt permission block would otherwise create an App with none — and validates it.
func (*Catalogue) Exported ¶ added in v1.74.0
Exported reports whether the App with the id is declared `export: true`.
func (*Catalogue) GrantGroups ¶
GrantGroups are every group named by some App's grant, deduplicated, in no particular order. It is [UndeclaredGroups]'s mirror image: that one reads the policy to find a grant naming a group the policy never declared; this one hands the policy the groups its own grants name, so the root policy package's Unconsumed lint (its catalogueGroups parameter — see policy.Policy.Unconsumed's doc comment) can stop reporting a group that exists ONLY to let some identity mint an App's installation token — the catalogue is the one place that actually consumes it, and the policy package cannot read this file for itself.
func (*Catalogue) UndeclaredGroups ¶
UndeclaredGroups are the grants' groups for which declared says false: the policy's groups, checked at start by the caller that has the policy.
type Grant ¶
type Grant struct {
// Group is a group the policy declares.
Group string `yaml:"group"`
// Repositories are names or path.Match globs within the App's
// organisation; "*" is every one.
Repositories []string `yaml:"repositories"`
// Permissions are the most a token may carry, each within the App's
// own.
Permissions map[string]string `yaml:"permissions"`
}
Grant is what one group may ask of an App.
type Kargo ¶ added in v1.74.0
type Kargo struct {
// Base is where Kargo's receivers are served, e.g.
// `https://kargo-webhooks.example`; the path below it is derived.
Base string `yaml:"base"`
// Receiver is the receiver's name in the Kargo project.
Receiver string `yaml:"receiver"`
// Project is the Kargo project, empty for a cluster-scoped receiver.
Project string `yaml:"project,omitempty"`
}
Kargo names a Kargo GitHub receiver.
type Webhook ¶ added in v1.74.0
type Webhook struct {
// URL is the endpoint every delivery is POSTed to, e.g. Argo CD's
// `https://argocd.example/api/webhook`.
URL string `yaml:"url,omitempty"`
// Kargo is a Kargo receiver. Kargo derives a receiver's path from its
// secret, so the URL moves whenever the secret does.
Kargo *Kargo `yaml:"kargo,omitempty"`
}
Webhook is where an App's events are delivered. Exactly one of URL and Kargo is set. The secret GitHub signs deliveries with is generated by this service, never declared (ADR 0041).
func (*Webhook) Placeholder ¶ added in v1.74.0
Placeholder is the URL the App is created with: the real one for a plain URL, a stand-in under the base for Kargo, replaced right after creation.