pusher

package
v0.1.0-dev6 Latest Latest
Warning

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

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

README

Pusher

Pluggable abstraction for landing a list of entity.Change values onto a target branch and pushing the result to a source-control remote.

Interface

Pusher exposes a single Push method that accepts a list of changes. Implementations are bound to a specific (checkout, remote, target) tuple at construction time, so the interface itself stays vendor- and configuration-agnostic.

The interface enforces an all-or-nothing atomicity contract: when Push returns an error, no change has reached the remote — neither partially nor fully. Callers can treat a non-nil error as "the remote is exactly as it was before the call". The ErrConflict sentinel marks user-caused failures so callers can route them to a non-retry path.

A successful Push returns one ChangeOutcome per input change in input order. Each outcome reports either:

  • OutcomeStatusCommitted with the list of CommitSHAs produced on the target branch (one change can land as multiple commits, e.g. a stack of PRs); or
  • OutcomeStatusAlreadyExisted with no commits, when the change is already present on the target branch (previously landed via another path, or subsumed by an earlier change in the same push). Git surfaces this as "rebased out" during a cherry-pick.

Implementations

  • git/ — applies changes against a local checkout via git cherry-pick, then git push. Construction takes the path to the checkout, the remote name, and the target branch; the implementation owns that working tree and serializes concurrent invocations.

Adding a new backend

  1. Create extension/pusher/{backend}/ with a Pusher implementation.
  2. Bind the implementation to its checkout/remote/target at construction.
  3. Map each entity.Change to the backend's commit/push primitives.
  4. Honour the atomicity contract: never publish partial state. Return ErrConflict (wrapped) for user-caused apply failures and a plain error for transient infra failures.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrConflict = errors.New("change conflict")

ErrConflict is returned by a Pusher when one of the changes fails to apply cleanly on top of the current tip of the target branch. Callers should treat conflicts as user-caused and non-retryable.

Functions

This section is empty.

Types

type ChangeOutcome

type ChangeOutcome struct {
	// Change is the input change this outcome corresponds to.
	Change entity.Change
	// Status describes whether the change produced commits or was already
	// present on the target branch.
	Status OutcomeStatus
	// CommitSHAs lists the commits this change produced on the target
	// branch, in apply order. A single Change may produce multiple commits
	// (e.g. a stack of PRs). Empty when Status is OutcomeStatusAlreadyExisted.
	CommitSHAs []string
}

ChangeOutcome describes what happened to a single Change inside a Push.

type OutcomeStatus

type OutcomeStatus string

OutcomeStatus describes what happened to a single Change during a Push.

const (
	// OutcomeStatusUnknown is the unreachable zero value, set by default
	// when the structure is initialized. It should never be seen in the system.
	OutcomeStatusUnknown OutcomeStatus = ""
	// OutcomeStatusCommitted means the change produced one or more commits
	// on the target branch. CommitSHAs lists those commits in apply order.
	OutcomeStatusCommitted OutcomeStatus = "committed"
	// OutcomeStatusAlreadyExisted means the change produced no commits
	// because every part of it is already present in the target branch
	// (e.g. it previously landed via another path, or a prior change in
	// the same push subsumed it). CommitSHAs is empty for this status.
	// In git terms this is what a `cherry-pick` surfaces as "rebased out".
	OutcomeStatusAlreadyExisted OutcomeStatus = "already_existed"
)

type Pusher

type Pusher interface {
	// Push applies changes onto the target branch and pushes the resulting
	// commits. See the type-level docs for the atomicity contract.
	Push(ctx context.Context, changes []entity.Change) (Result, error)
}

Pusher applies a list of Changes on top of a target branch and pushes the result to the source-control remote. Each implementation is bound to a specific (checkout, remote, target) at construction time.

Atomicity contract: when Push returns a non-nil error, NO change has been pushed to the remote — neither partially nor fully. Implementations must either roll back any local state or arrange for the push to never happen when any change fails to apply. Callers can treat a non-nil error as "the remote is exactly as it was before the call".

On success, len(Result.Outcomes) == len(changes) and Outcomes[i] describes what happened to changes[i]. A change can produce multiple commits (OutcomeStatusCommitted, CommitSHAs populated in apply order) or none at all (OutcomeStatusAlreadyExisted, CommitSHAs empty) — the latter happens when the change's content is already present on the target branch.

type Result

type Result struct {
	// Outcomes is one entry per input change, in the same order as the
	// changes passed to Push. The slice length equals the input length.
	Outcomes []ChangeOutcome
}

Result is the outcome of a successful Push call.

Directories

Path Synopsis
Package git is a simple Pusher implementation backed by a local git checkout.
Package git is a simple Pusher implementation backed by a local git checkout.
Package mock is a generated GoMock package.
Package mock is a generated GoMock package.

Jump to

Keyboard shortcuts

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