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
- Variables
- func Merge(ctx context.Context, remote Remote, pr PullRequest, approved bool) error
- type AuthError
- type Change
- type CheckState
- type Fake
- func (f *Fake) AddBranch(repo Repository, branch string, files map[string][]byte)
- func (f *Fake) Approve(_ context.Context, pr PullRequest, body string) error
- func (f *Fake) Close(_ context.Context, pr PullRequest, deleteBranch bool) error
- func (f *Fake) Commit(_ context.Context, repo Repository, branch, message string, ...) error
- func (f *Fake) Commits(repo Repository, branch string) []FakeCommit
- func (f *Fake) CreateBranch(_ context.Context, repo Repository, branch, base string) error
- func (f *Fake) EnableAutoMerge(_ context.Context, pr PullRequest) error
- func (f *Fake) Files(repo Repository, branch string) map[string][]byte
- func (f *Fake) FindPullRequest(_ context.Context, repo Repository, head string) (PullRequest, bool, error)
- func (f *Fake) ListFiles(_ context.Context, repo Repository, branch, dir string) ([]string, error)
- func (f *Fake) Merge(_ context.Context, pr PullRequest) error
- func (f *Fake) OpenDraftPullRequest(_ context.Context, repo Repository, head, base, title, body string) (PullRequest, error)
- func (f *Fake) OpenPullRequest(_ context.Context, repo Repository, head, base, title, body string) (PullRequest, error)
- func (f *Fake) PullRequests() []FakePullRequest
- func (f *Fake) ReadFile(_ context.Context, repo Repository, branch, path string) ([]byte, error)
- func (f *Fake) Revert(_ context.Context, pr PullRequest, body string, overrides map[string][]byte) (PullRequest, error)
- func (f *Fake) SetChecks(pr PullRequest, state CheckState)
- func (f *Fake) SetReview(pr PullRequest, state ReviewState)
- func (f *Fake) Status(_ context.Context, pr PullRequest) (Status, error)
- type FakeCommit
- type FakePullRequest
- type GitHub
- func (g *GitHub) Approve(ctx context.Context, pr PullRequest, body string) error
- func (g *GitHub) Close(ctx context.Context, pr PullRequest, deleteBranch bool) error
- func (g *GitHub) Commit(ctx context.Context, repo Repository, branch, message string, ...) error
- func (g *GitHub) CreateBranch(ctx context.Context, repo Repository, branch, base string) error
- func (g *GitHub) EnableAutoMerge(ctx context.Context, pr PullRequest) error
- func (g *GitHub) FindPullRequest(ctx context.Context, repo Repository, head string) (PullRequest, bool, error)
- func (g *GitHub) ListFiles(ctx context.Context, repo Repository, branch, dir string) ([]string, error)
- func (g *GitHub) Merge(ctx context.Context, pr PullRequest) error
- func (g *GitHub) OpenDraftPullRequest(ctx context.Context, repo Repository, head, base, title, body string) (PullRequest, error)
- func (g *GitHub) OpenPullRequest(ctx context.Context, repo Repository, head, base, title, body string) (PullRequest, error)
- func (g *GitHub) ReadFile(ctx context.Context, repo Repository, branch, path string) ([]byte, error)
- func (g *GitHub) Revert(ctx context.Context, pr PullRequest, body string, overrides map[string][]byte) (PullRequest, error)
- func (g *GitHub) Status(ctx context.Context, pr PullRequest) (Status, error)
- type GitHubOption
- type Lister
- type PullRequest
- type Reader
- type Remote
- type Repository
- type Request
- type ReviewState
- type Status
Constants ¶
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" )
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 ¶
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 ¶
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 ¶
AuthError is ErrAuth with the status the remote answered and the operation it refused. errors.Is(err, ErrAuth) matches it.
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
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) 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 ¶
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) 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) 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 base's tip.
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.
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
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
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 ¶
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 the tip of the repository's default branch, on branch revert-<number>-<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 ¶
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 on the current tip of the base — added
// files removed, changed and removed files restored — except the paths in
// overrides, which take the given content. 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 ¶
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.