githubappbootstrap

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 23, 2026 License: AGPL-3.0 Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// ActionsReadPermission is required by authoritative lifecycle
	// reconciliation. The scale-set message stream identifies a run and job,
	// but deciding whether an old row is still queued requires the workflow-run
	// jobs endpoint. Read is sufficient; the fleet never dispatches, cancels or
	// modifies a workflow run through this credential.
	ActionsReadPermission = "actions"
	// OrganizationRunnersPermission is what POST /orgs/{org}/actions/runners/
	// registration-token requires. Repository `administration` does not cover
	// it: an organization entity without this permission creates its GARM
	// entity and then fails on the first scale set, which is the shape this
	// deployment hit.
	OrganizationRunnersPermission = "organization_self_hosted_runners"
	OwnerTypeOrganization         = "organization"
	OwnerTypeUser                 = "user"
)

The account that owns a GitHub App decides which registration form can create it. An organization-owned App is not reachable through the personal form at all, so picking the wrong one is the difference between a bootstrap that can recreate the deployed credential and one that cannot.

Variables

This section is empty.

Functions

func IsTimeout

func IsTimeout(err error) bool

func NormalizeAppName

func NormalizeAppName(value string) string

Types

type Options

type Options struct {
	Registry tenant.Registry
	// Tenant names which registered account this App will serve. Empty means
	// the default tenant, so an existing invocation keeps working unchanged.
	Tenant string
	// OrganizationRunners requests the organization runner permission. Set it
	// when the App will back an organization entity; leave it off for a
	// repository entity, which does not need it.
	OrganizationRunners bool
	ListenAddress       string
	Repository          string
	// OwnerType is the kind of account that owns the App and receives its
	// installation. Both are the repository owner: the fleet credential is
	// owned by, installed on, and scoped to one account. A mixed arrangement
	// is not a supported deployment and fails closed.
	OwnerType       string
	AppName         string
	HomepageURL     string
	OutputDirectory string
	OpenBrowser     bool
}

type Runner

type Runner struct {
	HTTPClient *http.Client
	APIBaseURL string
	OpenURL    func(string) error
	Random     io.Reader
}

func (Runner) Run

func (r Runner) Run(ctx context.Context, options Options, stdout io.Writer) (VerifiedInstallation, error)

func (Runner) Verify

func (r Runner) Verify(ctx context.Context, options VerifyOptions) (VerifiedInstallation, error)

Verify re-reads a live installation and writes a current bundle for it.

Every check `bootstrap-github-app` applies after the manifest is approved applies here too, because it is the same function: the installation must belong to the tenant's account, its repository selection must be one this deployment accepts, and its permissions must be exactly the least-privilege set the tenant asked for. What this skips is only the part that creates an App, which is the part that must not happen.

type VerifiedInstallation

type VerifiedInstallation struct {
	SchemaVersion       int               `json:"schema_version"`
	AppID               int64             `json:"app_id"`
	AppSlug             string            `json:"app_slug"`
	InstallationID      int64             `json:"installation_id"`
	AccountLogin        string            `json:"account_login"`
	OwnerType           string            `json:"owner_type"`
	Repository          string            `json:"repository"`
	RepositorySelection string            `json:"repository_selection"`
	Permissions         map[string]string `json:"permissions"`
	PrivateKeyPath      string            `json:"private_key_path"`
	VerifiedAt          time.Time         `json:"verified_at"`
}

func RedactedResult

func RedactedResult(verified VerifiedInstallation) VerifiedInstallation

type VerifyOptions

type VerifyOptions struct {
	Registry tenant.Registry
	// Tenant names the registered account. Identity comes from the registry.
	Tenant string
	// Repository, OwnerType and OrganizationRunners are held to the same values
	// `bootstrap-github-app` would have used, so a bundle written here is
	// indistinguishable from one written there.
	Repository          string
	OwnerType           string
	OrganizationRunners bool
	// AppID and InstallationID name the App being re-verified. Both are
	// non-secret and both appear in the credential anchor.
	AppID          int64
	InstallationID int64
	// PrivateKeyPath is the existing App key. It is read, used to sign one JWT
	// and copied into the new bundle; it is never logged.
	PrivateKeyPath string
	// OutputDirectory must not exist. A bundle is written whole or not at all.
	OutputDirectory string
}

VerifyOptions re-verifies an App that already exists.

`bootstrap-github-app` is the only writer of a credential bundle, and it always creates a new App, because the manifest flow has no other shape. That is the wrong tool for the case this exists for: an App whose *permissions* changed after its bundle was written.

The bundle records the permissions it was written with, and `garmbootstrap.Reconcile` reads them from that file rather than from GitHub — deliberately, since the file is what a reviewer approved. So approving a new permission on a live installation leaves a bundle that is now wrong about it, and an organization entity built from that bundle fails closed. Before this command the only remedy was to create a second App and retire the first, which churns an installation, an anchor and a registry row to fix a stale JSON file.

Jump to

Keyboard shortcuts

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