branchprotection

package
v0.3.0-rc.18 Latest Latest
Warning

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

Go to latest
Published: Jun 22, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package branchprotection emits the JSON body an operator applies to GitHub's branch-protection API for a cascade-managed trunk. cascade EMITS the file; the operator APPLIES it. cascade never calls the GitHub API.

The emitted artifact is a small wrapper with two top-level keys:

{
  "protection":    { ... },  // the EXACT body to PUT to the branches API
  "operator_todo": { ... }   // companion guidance, NOT part of the PUT body
}

An operator applies it with, for example:

cascade branch-protection | jq .protection | \
  gh api -X PUT repos/OWNER/REPO/branches/main/protection --input -

The safety invariant is that the ".protection" object, applied verbatim, never creates a required status check that can never report. Only the two cascade controlled steps jobs (Setup and Finalize) are required, because cascade knows their exact check-run names and both run unconditionally on every run. The reusable-workflow caller jobs (validate, build, deploy) are deliberately left out of the required contexts: cascade knows their display-name prefix but not the inner job name that GitHub appends to form the real context, so requiring a bare prefix would block every pull request. Those prefixes are surfaced under operator_todo.complete_these_contexts as "<DisplayName> / <inner-job>" placeholders for the operator to complete once they know their reusable workflow's inner job names.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Marshal

func Marshal(p Payload) ([]byte, error)

Marshal renders the payload as indented JSON with exactly one trailing newline. The same manifest always produces byte-identical output.

func NewCommand

func NewCommand() *cobra.Command

NewCommand creates the branch-protection command. It emits the JSON body an operator applies to GitHub's branch-protection API for a cascade-managed trunk. cascade emits the file; the operator applies it. cascade never calls the GitHub API.

func Run

func Run(o Options, stdout io.Writer) error

Run resolves the manifest, builds the payload, and writes it. When Options.Output is empty or "-", it writes to stdout (w); otherwise it writes to that file path.

Types

type OperatorTodo

type OperatorTodo struct {
	Note                  string   `json:"note"`
	CompleteTheseContexts []string `json:"complete_these_contexts"`
}

OperatorTodo is companion guidance emitted alongside the PUT body. It is NOT part of the body GitHub accepts, so it is carried as a sibling key the operator strips off (jq .protection) before applying.

type Options

type Options struct {
	// ConfigPath is the manifest path; empty means auto-detect.
	ConfigPath string
	// ManifestKey is the key in the manifest file holding the CI config.
	ManifestKey string
	// Branch labels the protection target. It affects only the operator_todo
	// note; the PUT body itself is branch-agnostic. The required contexts (Setup
	// and Finalize) are the orchestrate-workflow steps jobs, identical across
	// branches and environments, so the branch never changes them.
	Branch string
	// Output is the destination path. Empty or "-" writes to stdout.
	Output string
}

Options configures a branch-protection emit run.

type Payload

type Payload struct {
	Protection   Protection   `json:"protection"`
	OperatorTodo OperatorTodo `json:"operator_todo"`
}

Payload is the full emitted artifact. The "protection" object is the exact PUT body; "operator_todo" is sibling guidance that must never be sent to GitHub.

func Build

func Build(cfg *config.TrunkConfig, branch string) Payload

Build assembles the Payload from a resolved manifest. The required contexts are exactly the cascade-controlled steps jobs (Setup and Finalize), referenced from generate.SetupJobName and generate.FinalizeJobName so a rename in the generator updates both the workflow and these contexts together. Every reusable-workflow caller job (validate, build, deploy) is surfaced under operator_todo as a "<DisplayName> / <inner-job>" placeholder rather than required directly, because requiring a context cascade cannot fully name would block every pull request.

type Protection

type Protection struct {
	RequiredStatusChecks           RequiredStatusChecks       `json:"required_status_checks"`
	EnforceAdmins                  bool                       `json:"enforce_admins"`
	RequiredPullRequestReviews     RequiredPullRequestReviews `json:"required_pull_request_reviews"`
	Restrictions                   *Restrictions              `json:"restrictions"`
	RequiredLinearHistory          bool                       `json:"required_linear_history"`
	AllowForcePushes               bool                       `json:"allow_force_pushes"`
	AllowDeletions                 bool                       `json:"allow_deletions"`
	RequiredConversationResolution bool                       `json:"required_conversation_resolution"`
}

Protection is the body an operator PUTs to /repos/{owner}/{repo}/branches/{branch}/protection. Every field is explicit so the marshaled output is byte-stable for a given manifest.

type RequiredPullRequestReviews

type RequiredPullRequestReviews struct {
	RequiredApprovingReviewCount int  `json:"required_approving_review_count"`
	DismissStaleReviews          bool `json:"dismiss_stale_reviews"`
	RequireCodeOwnerReviews      bool `json:"require_code_owner_reviews"`
}

RequiredPullRequestReviews mirrors the GitHub API review-protection block.

type RequiredStatusChecks

type RequiredStatusChecks struct {
	Strict   bool     `json:"strict"`
	Contexts []string `json:"contexts"`
}

RequiredStatusChecks lists the checks GitHub requires before merge. contexts holds ONLY cascade-controlled steps-job names whose check-run context cascade knows exactly, kept sorted for deterministic output.

type Restrictions

type Restrictions struct {
	Users []string `json:"users"`
	Teams []string `json:"teams"`
	Apps  []string `json:"apps"`
}

Restrictions models the push-restriction block. GitHub requires the key to be present; a nil *Restrictions marshals to null, meaning no push restriction.

Jump to

Keyboard shortcuts

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