fakegithub

package
v0.19.6 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package fakegithub is an in-process stand-in for the GitHub REST/GraphQL surface internal/host talks to, backed by REAL local git repositories.

It exists because the exec'd `a2a` binary could not be driven against a host at all: cmd/a2a wired a hardcoded API root, so every host-facing verb — submit, every lifecycle verb, every contract sub-verb, feedback submit — was unreachable from a script, and the wiring closures that assemble them (cmd/a2a/wire.go's runSubmit/runContract/runLifecycle/ runFeedback, resolveCredential, resolveTargetSpaceRef) were executed by no test at all. Point A2A_GITHUB_API at Server.URL and the whole chain runs for real: real config load, real credential resolution, real mirror clone, real `git push`, real PR open — with nothing leaving the machine.

It is a TEST DOUBLE, not a GitHub emulator: it implements exactly the calls internal/host makes. Merges are REAL git merges into a work clone, not ref moves — the funnel branches from the mirror's own possibly-stale HEAD, so a PR is routinely not a descendant of the current base, and a fast-forward stand-in would rewind the space instead of merging it.

Index

Constants

View Source
const ForkLogin = "consumer"

ForkLogin is the account EnsureFork forks as.

Variables

This section is empty.

Functions

This section is empty.

Types

type PR

type PR struct {
	Number int
	Head   string // "<branch>" for a same-repo PR, "<owner>:<branch>" from a fork
	Base   string
	Title  string
	Body   string
	State  string // "open" | "merged"
	Merged bool
	// MergeCommitSHA is recorded ONCE, at merge time, from the base branch's
	// tip immediately after this PR's own merge lands. It must not be
	// re-resolved later: the base moves on with every subsequent merge onto
	// it, and re-resolving at read time would hand a caller a LATER PR's
	// merge commit under this PR's number.
	MergeCommitSHA string
	// HeadSHA is captured ONCE, at merge time, before any prune — the same
	// discipline MergeCommitSHA already uses, for the same reason: real
	// GitHub keeps reporting a merged PR's head commit forever, even after
	// its branch is deleted (host.CheckStatus/prHeadSHA and
	// internal/livee2e's WaitForRequiredCheck both read a MERGED PR's
	// head.sha this way), so a fake that only resolved the live ref would
	// invent an absence DeleteBranchOnMerge's own pruning would otherwise
	// cause. pullPayload uses this as a fallback when the live ref no
	// longer resolves; an OPEN PR is never frozen this way — its head
	// genuinely moves as the branch is pushed to.
	HeadSHA string
	// AutoMergeArmed tracks whether enablePullRequestAutoMerge actually
	// armed THIS PR — set inside handleGraphQL, on both the arming path and
	// the AutoMergeAlreadyClean refusal path (which must leave it false: a
	// refusal is "not armed", and getting that backwards would make the
	// refusal untestable through host.ListOpenPRs' own AutoMergeArmed
	// field). It drives the `auto_merge` field in pullPayload — GitHub
	// reports that field as an object when armed and null otherwise, and
	// internal/host.ListOpenPRs' AutoMergeArmed is exactly `auto_merge !=
	// nil`, so an omitted/always-null field here would make every open PR
	// look like auto-merge was never armed, regardless of the truth.
	AutoMergeArmed bool
}

PR is one pull request the fake has seen.

type Server

type Server struct {
	// URL is the API root to hand the binary via A2A_GITHUB_API.
	URL string
	// OriginDir is the bare repository PRs merge into.
	OriginDir string

	// AutoMerge, when true (the default), fast-forwards the base branch to
	// the PR's head as soon as auto-merge is enabled — the space's own CI
	// gate is not modelled here, so "auto-merge armed" means "merged".
	// Set false to leave PRs open (the pending-merge path).
	AutoMerge bool
	// CheckState/CheckConclusion are what CheckStatus reports.
	CheckState      string
	CheckConclusion string
	// CheckName is the check run's NAME — the field internal/host selects
	// on. It defaults to the post-P33 COMPOUND context a migrated space
	// really emits (`<caller-job> / <reusable-job>`), so the default rig
	// exercises the shape the fleet is moving to; set it to the flat
	// `a2a-validate` to stand in for an un-migrated space.
	CheckName string
	// ReviewApprovals are the logins whose latest review is an approval.
	ReviewApprovals []string
	// AllowAutoMerge is what GET /repos/{owner}/{name} reports as the repo's
	// `allow_auto_merge` setting (host.GitHubHost.AutoMergeAllowed). Defaults
	// to true — a correctly-configured space — so no existing test's
	// behaviour changes; set false to drive the WAVE M2 doctor FAIL path.
	AllowAutoMerge bool
	// AllowMergeCommit/AllowSquashMerge/AllowRebaseMerge are what GET
	// /repos/{owner}/{name} reports for the same three merge-method flags
	// host.GitHubHost.MergePR reads to pick an explicit merge_method
	// (WAVE M4). All default true — a freshly created repository's own
	// default — so MergePR's default preference (merge commit) is what a
	// test sees unless it narrows one of these.
	AllowMergeCommit bool
	AllowSquashMerge bool
	AllowRebaseMerge bool
	// AutoMergeAlreadyClean, when true, makes the enable-auto-merge mutation
	// answer GitHub's REAL "clean status" refusal (WAVE M4) instead of
	// arming/merging: `errors: [{"message": "... is in clean status"}]`,
	// the exact wording internal/host's autoMergeRefusal/IsAutoMergeAlreadyClean
	// match against. Reaching a merge from here therefore requires the
	// caller to land the PR itself via the merge endpoint below — this flag
	// is what makes that scenario reproducible over a real HTTP path rather
	// than only inside internal/host's own httptest-server unit tests.
	// False (default) preserves every existing test's behaviour.
	AutoMergeAlreadyClean bool
	// MergeableState is what a PR's list/get payload reports as
	// `mergeable_state`. Defaults to "clean" (GitHub's steady-state value for
	// a PR with no conflicts); set it to drive a different value in a test
	// that exercises a caller's handling of, e.g., "dirty" or "blocked".
	MergeableState string
	// DeleteBranchOnMerge models GET /repos/{owner}/{name}'s own
	// `delete_branch_on_merge` setting AND the pruning it causes. Defaults to
	// true — the same reasoning ProtectionBody's own doc gives for mirroring
	// production rather than being maximally strict (spec 36 §T6-a):
	// internal/livee2e's RepoSettingsBody turns this on for every space this
	// project operates, so a rig that modelled it off would model a
	// configuration no space we run actually uses, and every scenario after
	// a first merge would fail for a reason production does not have (a
	// stale head branch defeating ProbeContractPublicationHeads' plan-digest
	// check being the exact case that surfaced this). Set false when a test
	// wants the un-pruned shape.
	//
	// When true, mergeByNumber deletes a SAME-REPO PR's head branch from
	// OriginDir the instant its own merge lands — never a cross-fork PR's
	// head (it lives in the fork; real GitHub does not touch a fork's own
	// branch) and never the refs/fork/<branch> copy mergeByNumber keeps for
	// SHA resolution.
	//
	// This models WHETHER a space prunes, never HOW LONG pruning takes. Real
	// GitHub prunes ASYNCHRONOUSLY — a branch listing can differ between two
	// reads that straddle the deletion, a timing fact spec 09 §3 names and
	// that broke a live row once. This fake's deletion is synchronous (gone
	// the instant the merge call returns); a scenario asserting on that async
	// window is a provider fact and belongs in the live tier, not here.
	DeleteBranchOnMerge bool
	// contains filtered or unexported fields
}

Server is the fake host. Construct with New, point A2A_GITHUB_API at URL, and inspect the recorded calls afterwards.

func New

func New(t testing.TB, originDir string) *Server

New starts a fake host in front of originDir (a bare repository, e.g. spacefixture's own origin) and stops it when the test ends.

func (*Server) DenyPushes

func (s *Server) DenyPushes(login string)

DenyPushes makes the origin refuse every push the way GitHub refuses a non-collaborator: a pre-receive hook that fails with GitHub's own wording, relayed by git as `remote: Permission to … denied to <login>`. This drives the REAL stderr classifier in internal/host, not a hand-written string.

func (*Server) ForkDir

func (s *Server) ForkDir(login string) string

ForkDir returns the bare repo standing in for login's fork ("" if none was created).

func (*Server) PRs

func (s *Server) PRs() []PR

PRs returns the pull requests opened so far.

func (*Server) Requests

func (s *Server) Requests() []string

Requests returns every API path the binary called, in order.

Jump to

Keyboard shortcuts

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