Help us shape the future of Go! Take the 2026 Go Developer Survey

forgedelegate

package
v1.0.14 Latest Latest
Warning

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

Go to latest
Published: Nov 2, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package forgedelegate finds, and if need be builds, the forge a project pins, so a forge of another version can hand a command to it.

WHY. forge's templates, KCL schemas and analyzers ship inside the binary, so a command run by the wrong forge rewrites a project with the wrong output or fails with errors that blame the project. The forge on PATH is routinely not the project's: a Reliant workspace bundles one at image-build time, and every project pins its own. Refusing and printing a `go run …@<pin>` line made the version skew a wall that every agent climbed by hand. Delegating removes it: the project says which forge it is, and that forge runs.

WHERE THE PINNED FORGE COMES FROM, cheapest first:

  1. the project's own .tools/bin/forge, when it reports the pinned version (`task tools` / scripts/install-tools.sh installs it there);
  2. the content-addressed cache, <user cache>/forge/pinned/<version>/… A pseudo-version names one commit, so an entry never goes stale;
  3. a build: `go install github.com/reliant-labs/forge/cmd/forge@<version>` into a temp dir that is renamed into the cache, so a build that dies never leaves a half-written binary where step 2 would trust it.

A project whose go.mod or go.work points forge at a local checkout (the dev link) is a different case: the forge it runs is that checkout, built where it stands (Bridge).

This package only resolves and executes. Whether to delegate is the caller's decision (internal/cli/forge_pin_delegate.go).

Index

Constants

View Source
const CacheDirEnv = "FORGE_PINNED_CACHE"

CacheDirEnv relocates the builds the resolver keeps (default <user cache dir>/forge/pinned), for read-only home directories and test isolation.

View Source
const MarkerEnv = "FORGE_VERSION_DELEGATED"

MarkerEnv is set in the environment of a forge that was delegated to. It ends the hand-off: the parent has already decided this is the right forge, and a child that second-guessed it (its own version string can differ in spelling from the pin) would delegate again, forever.

The marker is good for ONE process: the forge the hand-off exec'd. It used to be a bare `=1` that every descendant inherited, so a `reliant forge` run anywhere under a delegated `forge env up` (its services, a daemon, an agent shell that daemon spawned) skipped the pin check for good and ran whatever forge it embedded. Now:

  • its value names the process it is for, `<pid>:<target>` (markerOwner: the pid exec(2) keeps on Unix, the relaying parent on Windows), so a copy that reaches any other process is not believed;
  • it is consumed when this package initialises — before main, so before anything can spawn — and removed from this process's environment, so no child inherits it at all.

Variables

This section is empty.

Functions

func Delegated

func Delegated() bool

Delegated reports whether this process is the forge a hand-off started.

func Env

func Env(target string) []string

Env is the environment to give the delegated forge: ours, plus the marker. target names the forge it is handed to, for whoever reads the environment; the pid is what makes the marker good for that forge alone. Any marker already in the environment is replaced, never doubled.

func Exec

func Exec(path string, args, env []string) error

Exec replaces this process with the forge at path, running args (the forge arguments, no program name). The process keeps its pid, its stdio and its signals, so nothing between the caller and the delegated forge can swallow an interrupt or an exit status. It returns only on failure.

func MarkerEntry added in v1.0.7

func MarkerEntry(pid int, target string) string

MarkerEntry is the MarkerEnv=… entry a process with pid writes for the forge it hands target to.

func RunVersion

func RunVersion(ctx context.Context, path string) (string, error)

RunVersion is Resolver.Version's default: `<path> version`, first line, the token after "version".

Types

type Resolver

type Resolver struct {
	// Log receives the notice that a build is starting (a minute of silence
	// reads as a hang).
	Log io.Writer

	// Version runs a forge binary and returns the version it reports.
	Version func(ctx context.Context, path string) (string, error)
	// Same reports whether version got is the forge want names.
	Same func(want, got string) bool
	// Install runs `go install pkg` with GOBIN=gobin.
	Install func(ctx context.Context, pkg, gobin string) error
	// Build runs `go build` of cmd/forge in checkout dir, writing out.
	Build func(ctx context.Context, dir, out string) error
}

Resolver finds or builds forge binaries. The zero value is usable; the func fields are seams for tests and default to the real thing.

func (*Resolver) Bridge

func (r *Resolver) Bridge(ctx context.Context, dir, stamp string) (Result, error)

Bridge returns a forge built from the checkout at dir, the forge a project bridged to it (go.work `use`, or a directory `replace`) compiles against. stamp must change whenever the checkout's contents do (HEAD plus its uncommitted edits), so an unchanged checkout is built once. The build's own settings join the key (buildSettingsKey): two callers whose GOFLAGS differ (one with -trimpath, one without) build different bytes from the same checkout, and must not share — or replace — one cached binary.

func (*Resolver) LocalPinned

func (r *Resolver) LocalPinned(ctx context.Context, projectRoot, pin string) (string, bool)

LocalPinned reports the project's own .tools/bin/forge when it exists and reports the pinned version. It runs the binary (`forge version`), never builds anything.

func (*Resolver) Pinned

func (r *Resolver) Pinned(ctx context.Context, projectRoot, pin string) (Result, error)

Pinned returns the forge named by pin (forge.yaml's forge_version), for the project at projectRoot.

type Result

type Result struct {
	// Path is the executable.
	Path string
	// Source says where it came from, for the one-line notice.
	Source string
}

Result is a forge ready to exec.

Jump to

Keyboard shortcuts

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