commit

package
v0.11.1 Latest Latest
Warning

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

Go to latest
Published: Oct 7, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package commit lands rendered files in GitOps repositories as the person: a branch, one commit per repository, the pull request carrying the caller's text, and the merge once the caller says approved and the checks are green.

The module holds no token. A Remote is built from the token the caller supplies (for the managers: the person's user token of the manager's App), and a token GitHub refuses surfaces as ErrAuth carrying the HTTP status; the callers turn it into their sign-in answer. Nothing is retried with another token, nothing is logged, and no error carries file content.

Index

Constants

View Source
const (
	ReviewNone             ReviewState = "none"
	ReviewApproved         ReviewState = "approved"
	ReviewChangesRequested ReviewState = "changes_requested"

	// ChecksNone: the head carries no statuses and no check runs; nothing to wait for.
	ChecksNone    CheckState = "none"
	ChecksPending CheckState = "pending"
	ChecksSuccess CheckState = "success"
	ChecksFailure CheckState = "failure"
)
View Source
const (
	OpCreateBranch    = "create branch"
	OpCommit          = "commit"
	OpOpenPullRequest = "open pull request"
	OpStatus          = "pull request status"
	OpMerge           = "merge"
	OpApprove         = "approve pull request"
	OpFindPullRequest = "find pull request"
	OpEnableAutoMerge = "enable auto-merge"
	OpClose           = "close pull request"
	OpRevert          = "revert pull request"
	OpReadFile        = "read file"
	OpListFiles       = "list files"
)

Operation names of the remote calls, carried by AuthError and by Fake.Fail.

Variables

View Source
var (
	// ErrAuth: the remote refused the caller's token (401 or 403). The callers
	// answer with their sign-in flow; the module neither retries nor substitutes.
	ErrAuth = errors.New("token refused")
	// ErrInvalidRequest: the request lacks a branch or a title.
	ErrInvalidRequest = errors.New("request needs a branch and a title")
	// ErrNoFiles: a change carries no files.
	ErrNoFiles = errors.New("no files to commit")
	// ErrConflictingBase: two changes for one repository name different branches.
	ErrConflictingBase = errors.New("one repository, two base branches")
	// ErrDuplicatePath: two changes for one repository write the same path.
	ErrDuplicatePath = errors.New("one path in two changes")
	// ErrStaleBranch: the existing branch is behind its base and base does not
	// merge into it; nothing is committed onto a head that lacks the base.
	ErrStaleBranch = errors.New("branch behind its base and the base does not merge into it")
	// ErrNotApproved: the caller has not said approved.
	ErrNotApproved = errors.New("merge refused: not approved")
	// ErrChecksPending: a status or check run on the head has not finished.
	ErrChecksPending = errors.New("merge refused: checks pending")
	// ErrChecksFailed: a status or check run on the head failed.
	ErrChecksFailed = errors.New("merge refused: checks failed")
	// ErrHeadMoved: the head is no longer the commit the caller saw.
	ErrHeadMoved = errors.New("merge refused: the head moved since the pull request was seen")
	// ErrNotMerged: only a merged pull request can be reverted.
	ErrNotMerged = errors.New("revert refused: the pull request is not merged")
	// ErrNothingToRevert: the merged pull request changed no files.
	ErrNothingToRevert = errors.New("revert refused: the pull request changed no files")
	// ErrFileNotFound: the branch carries no file at the path.
	ErrFileNotFound = errors.New("no such file")
)

Functions

func Merge

func Merge(ctx context.Context, remote Remote, pr PullRequest, approved bool) error

Merge merges the pull request as the person. It is refused before the caller says approved (ErrNotApproved, no remote call), before every check on the head is green (ErrChecksPending, ErrChecksFailed; a head without checks has nothing to wait for) and when the head is not the commit the caller saw (ErrHeadMoved). A merged pull request is left as it is. GitHub's own rules — the approving review that satisfies enforce_admins and rulesets — apply at the merge call; no administrative path exists.

Types

type AuthError

type AuthError struct {
	Op     string
	Status int
}

AuthError is ErrAuth with the status the remote answered and the operation it refused. errors.Is(err, ErrAuth) matches it.

func (*AuthError) Error

func (e *AuthError) Error() string

func (*AuthError) Unwrap

func (e *AuthError) Unwrap() error

Unwrap makes errors.Is(err, ErrAuth) true.

type Change

type Change struct {
	Location provenance.Location
	Files    map[string][]byte
}

Change is the set of files for one location: the repository, the base branch and the repository-relative paths the files land at (the keys of what sopsenc.Encrypt returns). Changes for one repository become one commit. A path whose content is nil is removed from the repository.

type CheckState

type CheckState string

CheckState is the rollup of the commit statuses and check runs on the head.

type Fake

type Fake struct {
	// Fail maps an operation name (OpCreateBranch, OpCommit, ...) to the error
	// that operation returns instead of acting.
	Fail map[string]error
	// contains filtered or unexported fields
}

Fake is an in-process Remote for tests — the module's own and its callers': branches with commits, pull requests with review and check state, and a way to make any operation fail. It never touches the network.

func NewFake

func NewFake() *Fake

NewFake returns an empty Fake; seed base branches with AddBranch.

func (*Fake) AddBranch

func (f *Fake) AddBranch(repo Repository, branch string, files map[string][]byte)

AddBranch seeds branch in repo with one commit holding files (nil for an empty tree).

func (*Fake) Approve added in v0.5.0

func (f *Fake) Approve(_ context.Context, pr PullRequest, body string) error

Approve implements Remote: the approval is recorded on the pull request and the review rollup becomes approved unless changes are requested. An unknown or closed pull request is an error.

func (*Fake) Close added in v0.4.0

func (f *Fake) Close(_ context.Context, pr PullRequest, deleteBranch bool) error

Close implements Remote.

func (*Fake) Commit

func (f *Fake) Commit(_ context.Context, repo Repository, branch, message string, files map[string][]byte) error

Commit implements Remote.

func (*Fake) Commits

func (f *Fake) Commits(repo Repository, branch string) []FakeCommit

Commits returns the commits made on branch after its seed, oldest first.

func (*Fake) CreateBranch

func (f *Fake) CreateBranch(_ context.Context, repo Repository, branch, base string) error

CreateBranch implements Remote: a new branch starts at base's head; an existing one that lacks base's head takes a merge commit with base's changes since their common ancestor, or ErrStaleBranch when a path changed on both sides differently.

func (*Fake) EnableAutoMerge added in v0.4.0

func (f *Fake) EnableAutoMerge(_ context.Context, pr PullRequest) error

EnableAutoMerge implements Remote: the pull request is marked, nothing merges by itself.

func (*Fake) Files

func (f *Fake) Files(repo Repository, branch string) map[string][]byte

Files returns the tree at the head of branch.

func (*Fake) FindPullRequest added in v0.4.0

func (f *Fake) FindPullRequest(_ context.Context, repo Repository, head string) (PullRequest, bool, error)

FindPullRequest implements Remote.

func (*Fake) ListFiles added in v0.11.0

func (f *Fake) ListFiles(_ context.Context, repo Repository, branch, dir string) ([]string, error)

ListFiles implements Lister.

func (*Fake) Merge

func (f *Fake) Merge(_ context.Context, pr PullRequest) error

Merge implements Remote: the base fast-forwards to the head.

func (*Fake) OpenDraftPullRequest added in v0.4.0

func (f *Fake) OpenDraftPullRequest(_ context.Context, repo Repository, head, base, title, body string) (PullRequest, error)

OpenDraftPullRequest implements Remote.

func (*Fake) OpenPullRequest

func (f *Fake) OpenPullRequest(_ context.Context, repo Repository, head, base, title, body string) (PullRequest, error)

OpenPullRequest implements Remote.

func (*Fake) PullRequests

func (f *Fake) PullRequests() []FakePullRequest

PullRequests returns every pull request the Fake holds, oldest first.

func (*Fake) ReadFile added in v0.9.0

func (f *Fake) ReadFile(_ context.Context, repo Repository, branch, path string) ([]byte, error)

ReadFile implements Reader.

func (*Fake) Revert added in v0.4.0

func (f *Fake) Revert(_ context.Context, pr PullRequest, body string, overrides map[string][]byte) (PullRequest, error)

Revert implements Remote: the merged pull request's files, inverted against the base as it was at the merge, in one commit on the head of the revert branch, created at the base's tip or brought up to date with it as CreateBranch does.

func (*Fake) SetChecks

func (f *Fake) SetChecks(pr PullRequest, state CheckState)

SetChecks sets the check rollup the Fake reports for pr.

func (*Fake) SetReview

func (f *Fake) SetReview(pr PullRequest, state ReviewState)

SetReview sets the review rollup the Fake reports for pr.

func (*Fake) Status

func (f *Fake) Status(_ context.Context, pr PullRequest) (Status, error)

Status implements Remote.

type FakeCommit

type FakeCommit struct {
	Repository  Repository
	Branch      string
	Message     string
	Parent      string
	MergeParent string
	SHA         string
	Files       map[string][]byte
}

FakeCommit is one commit the Fake holds; Files is the full tree at that commit. MergeParent is set on the merge commit CreateBranch makes when it brings an existing branch up to date: the base's head it merged in.

type FakePullRequest

type FakePullRequest struct {
	PullRequest
	Title     string
	Body      string
	Draft     bool
	Merged    bool
	Closed    bool // closed without a merge
	AutoMerge bool
	Review    ReviewState
	// Approvals are the bodies of the approving reviews Approve submitted, in order.
	Approvals []string
	Checks    CheckState
	// contains filtered or unexported fields
}

FakePullRequest is a pull request the Fake holds, with what the remote knows about it.

type GitHub

type GitHub struct {
	// contains filtered or unexported fields
}

GitHub is the Remote for github.com (or a GitHub Enterprise Server) acting with the token the caller supplies. It talks REST through google/go-github, never a git or sops binary.

func NewGitHub

func NewGitHub(token string, opts ...GitHubOption) (*GitHub, error)

NewGitHub builds the Remote from the caller's token. The token is the person's; the module keeps none of its own.

func NewGitHubWithClient added in v0.4.0

func NewGitHubWithClient(hc *http.Client, opts ...GitHubOption) (*GitHub, error)

NewGitHubWithClient builds the Remote on an HTTP client that already carries the caller's identity — a GitHub App installation transport, a rotated token file — so no token string changes hands. The module adds no credential of its own to it.

func (*GitHub) Approve added in v0.5.0

func (g *GitHub) Approve(ctx context.Context, pr PullRequest, body string) error

Approve submits an approving review on the pull request as the person, pinned to pr.HeadSHA when the caller names it. GitHub applies its own rules to the call: the author of a pull request cannot approve it.

func (*GitHub) Close added in v0.4.0

func (g *GitHub) Close(ctx context.Context, pr PullRequest, deleteBranch bool) error

Close closes the pull request and, when asked, deletes its head branch. A pull request that is closed already (merged or not) is left as it is.

func (*GitHub) Commit

func (g *GitHub) Commit(ctx context.Context, repo Repository, branch, message string, files map[string][]byte) error

Commit writes one commit with files on top of branch: blobs, a tree on the head's tree, the commit, and a fast-forward of the branch. A nil content removes the path from the tree.

func (*GitHub) CreateBranch

func (g *GitHub) CreateBranch(ctx context.Context, repo Repository, branch, base string) error

CreateBranch creates branch at base's head. An existing branch (GitHub answers 422 to the create) is brought up to date with base instead.

func (*GitHub) EnableAutoMerge added in v0.4.0

func (g *GitHub) EnableAutoMerge(ctx context.Context, pr PullRequest) error

EnableAutoMerge arms GitHub's auto-merge on the pull request with the repository's merge method. Auto-merge is GraphQL-only; the mutation goes through the same client and identity as every other call.

func (*GitHub) FindPullRequest added in v0.4.0

func (g *GitHub) FindPullRequest(ctx context.Context, repo Repository, head string) (PullRequest, bool, error)

FindPullRequest returns the open pull request of head, if there is one.

func (*GitHub) ListFiles added in v0.11.0

func (g *GitHub) ListFiles(ctx context.Context, repo Repository, branch, dir string) ([]string, error)

ListFiles returns the files under dir at the head of branch, from the branch's recursive Git tree. A tree GitHub truncates is an error, never a partial answer.

func (*GitHub) Merge

func (g *GitHub) Merge(ctx context.Context, pr PullRequest) error

Merge merges the pull request with the repository's merge method (squash where allowed, else merge commit, else rebase), only if the head is still pr.HeadSHA. GitHub applies its own protection rules to the call.

func (*GitHub) OpenDraftPullRequest added in v0.4.0

func (g *GitHub) OpenDraftPullRequest(ctx context.Context, repo Repository, head, base, title, body string) (PullRequest, error)

OpenDraftPullRequest is OpenPullRequest as a draft.

func (*GitHub) OpenPullRequest

func (g *GitHub) OpenPullRequest(ctx context.Context, repo Repository, head, base, title, body string) (PullRequest, error)

OpenPullRequest opens head against base with the caller's title and body. When head already has an open pull request, that one is returned.

func (*GitHub) ReadFile added in v0.9.0

func (g *GitHub) ReadFile(ctx context.Context, repo Repository, branch, path string) ([]byte, error)

ReadFile returns the content of path at the head of branch, through the Git blob so a file past the contents API's 1 MB inline limit reads whole.

func (*GitHub) Revert added in v0.4.0

func (g *GitHub) Revert(ctx context.Context, pr PullRequest, body string, overrides map[string][]byte) (PullRequest, error)

Revert opens a pull request undoing the merged pr: the merge commit's diff against its first parent, inverted into one commit on branch revert-<number>-<head>. The branch is brought into existence or up to date with the pull request's base the way CreateBranch does — ErrStaleBranch when the base does not merge into it — and the commit lands on its head, so a second revert adds a commit to the open revert pull request.

func (*GitHub) Status

func (g *GitHub) Status(ctx context.Context, pr PullRequest) (Status, error)

Status reads the pull request, its reviews, and the statuses and check runs of its head.

type GitHubOption

type GitHubOption = github.ClientOptionsFunc

GitHubOption configures NewGitHub.

func WithBaseURL

func WithBaseURL(baseURL string) GitHubOption

WithBaseURL points the client at another API root: a GitHub Enterprise Server, or a test server.

func WithHTTPClient

func WithHTTPClient(c *http.Client) GitHubOption

WithHTTPClient sets the HTTP client the requests go through.

type Lister added in v0.11.0

type Lister interface {
	// ListFiles returns the repository-relative paths of every file under
	// dir at the head of branch, recursively and sorted; none when the
	// branch carries no such directory.
	ListFiles(ctx context.Context, repo Repository, branch, dir string) ([]string, error)
}

Lister lists a directory of a repository at a branch: what a caller removes as a whole (a workload cluster's directory) or checks is there before it writes into it. GitHub and Fake implement it.

type PullRequest

type PullRequest struct {
	Repository Repository
	Number     int
	URL        string
	Head       string
	Base       string
	HeadSHA    string
}

PullRequest identifies a pull request the module opened or found open. HeadSHA is the commit the caller saw; Merge refuses when the head has moved.

func Open

func Open(ctx context.Context, remote Remote, req Request, changes []Change) ([]PullRequest, error)

Open lands the changes: for every repository one branch from its base, one commit with all of that repository's files, one pull request with the caller's title and body. A branch an earlier run left behind is brought up to date with its base first, so files composed from the base's current content never land on a head that lacks it (ErrStaleBranch when the base does not merge in). Repositories are handled in name order; on an error the pull requests opened so far are returned with it.

type Reader added in v0.9.0

type Reader interface {
	// ReadFile returns the content of path at the head of branch, or
	// ErrFileNotFound.
	ReadFile(ctx context.Context, repo Repository, branch, path string) ([]byte, error)
}

Reader reads a repository's files at a branch: what a caller renders against before it lands a change — the kustomization.yaml it extends, the .sops.yaml it encrypts for, whether a file it would remove exists. GitHub and Fake implement it.

type Remote

type Remote interface {
	// CreateBranch creates branch from base. A branch that exists is brought
	// up to date: base is merged into it when it is behind (a merge commit,
	// history never rewritten), or ErrStaleBranch names the branch and its
	// open pull request when base does not merge into it. The branch's head
	// contains base when CreateBranch returns nil.
	CreateBranch(ctx context.Context, repo Repository, branch, base string) error
	// Commit adds one commit with files to branch; a path whose content is
	// nil is removed.
	Commit(ctx context.Context, repo Repository, branch, message string, files map[string][]byte) error
	// OpenPullRequest opens head against base, or returns the open pull request head already has.
	OpenPullRequest(ctx context.Context, repo Repository, head, base, title, body string) (PullRequest, error)
	// Status reads the pull request's head, merged flag, review and check state.
	Status(ctx context.Context, pr PullRequest) (Status, error)
	// Approve submits an approving review on the pull request as the person —
	// the identity the remote was built with. GitHub refuses a review by the
	// pull request's own author; callers check the author before the call.
	Approve(ctx context.Context, pr PullRequest, body string) error
	// Merge merges the pull request as the person, refusing when the head is not pr.HeadSHA.
	Merge(ctx context.Context, pr PullRequest) error
	// FindPullRequest returns the open pull request whose head is head, and whether there is one.
	FindPullRequest(ctx context.Context, repo Repository, head string) (PullRequest, bool, error)
	// OpenDraftPullRequest is OpenPullRequest with the pull request opened as a draft.
	OpenDraftPullRequest(ctx context.Context, repo Repository, head, base, title, body string) (PullRequest, error)
	// EnableAutoMerge arms the remote's auto-merge on the pull request with the
	// repository's merge method, so it lands once its reviews and checks pass.
	// The caller's choice, never the module's default.
	EnableAutoMerge(ctx context.Context, pr PullRequest) error
	// Close closes the pull request without merging and, when asked, deletes
	// its head branch; a closed pull request is left as it is.
	Close(ctx context.Context, pr PullRequest, deleteBranch bool) error
	// Revert opens a pull request undoing a merged one: the merged change's
	// files are inverted in one commit — added files removed, changed and
	// removed files restored — except the paths in overrides, which take the
	// given content. The commit lands on the head of the revert branch, which
	// is created at the base's tip or brought up to date with it as
	// CreateBranch does (ErrStaleBranch naming the branch and its pull request
	// when the base does not merge in); a second revert adds a commit to the
	// open revert pull request. History is never rewritten.
	Revert(ctx context.Context, pr PullRequest, body string, overrides map[string][]byte) (PullRequest, error)
}

Remote is the git hosting the package talks to: GitHub in production, Fake in tests. Every operation acts with the token the Remote was built from.

type Repository

type Repository = provenance.Repository

Repository is the GitHub repository a change lands in.

type Request

type Request struct {
	Branch string
	Title  string
	Body   string
}

Request names one run: its head branch, its commit message and pull request title, and the pull request body — the caller's text, carried verbatim.

type ReviewState

type ReviewState string

ReviewState is the pull request's review rollup: the latest stance of every reviewer, approved when at least one approves and none requests changes.

type Status

type Status struct {
	HeadSHA string
	Merged  bool
	Review  ReviewState
	Checks  CheckState
}

Status is the pull request's state as the remote reports it.

Jump to

Keyboard shortcuts

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