gitwriteback

package
v0.0.5 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package gitwriteback turns the files a harness changed into something the hub can merge.

Why this is its own package

It is gitprovision's mirror image, and it exists for the same reason. Two callers have to do exactly the same thing at the other end of a run:

  • the remote agent (pkg/executor/agent), which recovers the work product from an edge device after the harness there exits;
  • `cloop workspace writeback` (cmd), which the Kubernetes driver runs inside the Pod, because a Pod's /workspace is an emptyDir that stops existing the moment the Pod does.

Two implementations would be two chances to reintroduce the failure this subsystem exists to remove — a run that streams a plausible transcript and delivers nothing — and the drifted copy would be silent, because a write-back that produced no commit looks exactly like a task that changed no files. So there is one engine, here, and both callers are thin.

The package depends on nothing but the standard library and pkg/executor, so the CLI does not import the agent's transport machinery to make a commit and the agent does not import the CLI.

What it produces

Always a branch at a commit, never a diff. The hub already has a merge story for parallel work — a per-task branch merged back through pkg/mergequeue, with AI conflict resolution — and remote work has to arrive in a shape that story accepts. A patch would have to be turned back into a branch on the hub, with a new SHA, and the "hub verifies the branch is at the SHA the sandbox reported" check would have nothing left to verify.

The credential

Push mode reuses the grant that cloned the tree, delivered exactly the way gitprovision delivers it: in the environment of the single git child that contacts the remote, as a URL-scoped http.extraHeader. It is never written to disk, never placed in an argv, and never added to the harness's environment. Everything this package emits or returns goes through executor.RedactSecrets first, because git quotes headers back in error messages.

Ordering

Nothing is committed until the harness has exited. The engine runs after the workload, against a tree nobody is writing to, so a commit can never capture a half-written file — and a failed task writes back nothing at all, which is the caller's decision to make and this package's to enforce (see Request.OnlyOnSuccess).

Index

Constants

View Source
const DefaultTimeout = 5 * time.Minute

DefaultTimeout bounds the whole write-back when a Request names none.

A write-back runs after the harness has already produced its result, so a hang here loses work that exists rather than work that does not — which makes a ceiling more important than a generous one, not less. Five minutes covers a push of a large tree over a slow link.

Variables

This section is empty.

Functions

func SHA256

func SHA256(b []byte) string

SHA256 digests a byte slice the same way fileSHA256 digests a file, so the hub can compare what it received against what the sandbox reported.

Types

type Request

type Request struct {
	// Dir is the absolute path of the provisioned tree. It must be a git
	// repository — gitprovision left one there — and the caller is responsible
	// for having confined it.
	Dir string
	// Workspace is the workspace the tree was provisioned from. It supplies
	// the push remote: a push goes to Workspace.Repo and nowhere else.
	Workspace executor.Workspace
	// WriteBack says which mode to run and what to name the branch.
	WriteBack executor.WriteBack
	// Credential authenticates the push. The zero value means an
	// unauthenticated push, which only works for a repository that accepts
	// anonymous writes — that is, essentially never, so a push mode request
	// without one fails with a legible error rather than a git prompt.
	Credential executor.GitCredential
	// BaseSHA is the commit the workspace was provisioned at. Empty means
	// "read it from the repository", which is right for the ordinary case;
	// a caller that recorded it before the harness ran should pass it, because
	// a harness that moved HEAD itself would otherwise shrink the range and
	// silently drop its own earlier commits.
	BaseSHA string
	// BundlePath is where a bundle-mode write-back writes its file. Empty
	// means a temporary file this package creates and the caller must remove;
	// Result.BundlePath always names the file that exists.
	BundlePath string
	// ExitCode is the harness's exit status, and OnlyOnSuccess decides whether
	// it gates the write-back. See OnlyOnSuccess.
	ExitCode int
	// OnlyOnSuccess refuses to write back the work of a failed task.
	//
	// It defaults to off in the zero Request because a caller has to opt into
	// a policy this consequential, and every caller in the tree opts in. The
	// reasoning: a harness that exited non-zero left the tree in whatever state
	// it was in when it died — a half-applied refactor, a partially generated
	// file — and merging that is worse than losing it, because the loss is
	// visible and the half-change is not.
	OnlyOnSuccess bool
	// Emit receives progress as it completes, already redacted. May be nil.
	Emit func(string)
	// Host is how the machine names itself in a diagnostic. Empty falls back
	// to gitprovision.HostLabel("machine").
	Host string
	// Timeout bounds the whole write-back. 0 means DefaultTimeout.
	Timeout time.Duration
	// GitCA is the hub's own CA, trusted for the URLs it names and nothing
	// else, for a push through a git proxy serving a certificate the hub
	// issued (Task 20409). See gitprovision.Request.GitCA.
	GitCA *executor.GitCA
}

Request is one write-back.

type Result

type Result struct {
	executor.WriteBackResult
	// BundlePath names the bundle file on disk, for mode bundle. The caller
	// owns the file and is responsible for removing it.
	BundlePath string
}

Result is what the write-back produced. It is the same shape the driver reports upward, so a caller does not have to translate.

func Produce

func Produce(ctx context.Context, r Request) (Result, error)

Produce commits the harness's changes to a per-task branch and delivers them.

Every error it returns wraps executor.ErrWriteBackUnavailable and has already been through executor.RedactSecrets, so a caller may log it, ship it across the remote boundary, or print it to a terminal without further filtering.

A clean tree is not an error. It returns a Result with Skipped set, because "the agent changed nothing" is a real outcome that an operator needs to be able to tell apart from "the write-back broke".

Jump to

Keyboard shortcuts

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