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

handlertoolchain

package
v0.0.0-...-2fd5d2c Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package handlertoolchain resolves and drives the build tooling for an OS-only runtime.

An OS-only runtime identifier (os-only.debian13) names a base operating system rather than a language, so unlike "nodejs24.x" it does not give the language away and the toolchain has to be resolved from the project instead. Two implementations ship, one driving the Celerity Go SDK's celerity-go tool and a declarative one driven by a handlerBuild block in the application's deploy config, which is how a community SDK for another compiled language is supported without CLI code of its own.

This package is deliberately a leaf. internal/deployconfig already imports internal/build and internal/handlerresolve, so a toolchain importing deployconfig back would close a cycle. The handlerBuild schema therefore lives here and deploy config embeds it.

Index

Constants

View Source
const (
	EnvBuildOS           = "CELERITY_BUILD_OS"
	EnvBuildArch         = "CELERITY_BUILD_ARCH"
	EnvBuildOutput       = "CELERITY_BUILD_OUTPUT"
	EnvBuildDeployTarget = "CELERITY_BUILD_DEPLOY_TARGET"
	EnvBuildMode         = "CELERITY_BUILD_MODE"
)

Environment variables the CLI injects into every handlerBuild command, so a build script can key off what it is being asked for rather than hard-coding one platform and one deploy target.

View Source
const (
	// GoToolBinary is the Celerity Go SDK's build-time tool.
	GoToolBinary = "celerity-go"

	// GoToolModule is the module that tool is in. Its own module rather than
	// the SDK's, so an application links no part of the build tooling.
	GoToolModule = GoSDKModule + "/cmd/" + GoToolBinary

	// GoToolEnvVar overrides where that tool is found, for a checkout that
	// has not installed it on PATH.
	GoToolEnvVar = "CELERITY_GO_TOOL"
)
View Source
const (
	ModeDev    = "dev"
	ModeDeploy = "deploy"
)

Build modes. A dev session reads its own local config store and talks to local emulators, so it links different packages from a deployed artefact.

View Source
const GoSDKModule = "github.com/newstack-cloud/celerity-go-sdk"

GoSDKModule is the Celerity Go SDK's module path. A go.mod requiring it is what identifies a Go Celerity application.

View Source
const TelemetryOTel = "otel"

TelemetryOTel is what PrepareParams.Telemetry carries to link an OpenTelemetry exporter. Its own setting rather than one derived from the deploy target, since an application deployed anywhere may export anywhere.

Variables

This section is empty.

Functions

func CheckArchitecture

func CheckArchitecture(path, goarch string) error

CheckArchitecture reports whether the executable at path is built for the given GOARCH.

Worth a check of its own because the failure it catches is otherwise invisible. An executable of the wrong architecture is a valid file the kernel refuses to exec, which surfaces as "exit status 126" with no indication of why, long after the build that caused it.

A non-ELF file is not an error. A Lambda or container target is always Linux, so anything else is a build for somewhere the check does not apply rather than a mistake.

func IsOSOnly

func IsOSOnly(runtime string) bool

IsOSOnly reports whether a runtime identifier names an OS-only runtime.

func WithToolOutput

func WithToolOutput(ctx context.Context, w io.Writer) context.Context

WithToolOutput returns a context carrying where a toolchain's command output should be streamed.

On the context because the sink is a property of how the CLI is being run, a log file when a TUI owns the terminal and stdout when it does not, rather than of the build being asked for. Threading it through every params struct would put it in the signature of calls that never produce any output.

Types

type BinaryParams

type BinaryParams struct {
	AppDir string
	// OS and Arch are the platform the executable has to run on rather than
	// the one building it. A dev session targets the Docker daemon's
	// architecture, and a Lambda build targets the architecture the function
	// is declared with.
	OS   string
	Arch string
	// OutputPath is where the executable must end up.
	OutputPath string
	// DeployTarget and Mode mirror PrepareParams.
	DeployTarget string
	Mode         string
}

BinaryParams describes one handlers executable to produce.

type Config

type Config struct {
	// Command builds the handlers executable. Run through the shell, from the
	// application directory.
	Command string `json:"command"`
	// Binary is where Command leaves the executable, relative to the
	// application directory. The CLI copies it to wherever it is needed.
	Binary string `json:"binary"`
	// Env is added to Command's environment, on top of the CELERITY_BUILD_*
	// variables the CLI injects.
	Env map[string]string `json:"env,omitempty"`
	// Tidy, where set, is run after Command to reconcile the project's
	// dependency manifest.
	Tidy string `json:"tidy,omitempty"`
	// Extract reports the handlers the executable serves. Optional, and
	// without it the blueprint's hand-authored handler resources are used as
	// they are.
	Extract *ExtractConfig `json:"extract,omitempty"`
	// Test maps a suite name (unit, integration, api) to its command.
	Test map[string]string `json:"test,omitempty"`
	// WatchRoots are the directories a dev session watches, relative to the
	// application directory. Defaults to the application directory itself.
	WatchRoots []string `json:"watchRoots,omitempty"`
	// WatchExtensions are the file extensions a dev session rebuilds for.
	WatchExtensions []string `json:"watchExtensions,omitempty"`
	// WatchSkipDirs are directory names the watcher does not descend into.
	WatchSkipDirs []string `json:"watchSkipDirs,omitempty"`
	// Targets overrides any of the above per deploy target. A cross-compiled
	// binary usually lands somewhere different for each.
	Targets map[string]*Config `json:"targets,omitempty"`
}

Config is the handlerBuild block of an application's deploy config.

It is what makes a community SDK for a compiled language usable without any CLI code. The author states how to produce a handlers executable and, where their SDK can, how to report what it serves, and everything the CLI does with the result is language-neutral.

It lives on the deploy config rather than in celerity.config.toml because that provider carries only scalars, and because a build command legitimately differs per deploy target.

func (*Config) Validate

func (c *Config) Validate() error

Validate reports whether the block is usable.

type ExecRunner

type ExecRunner struct{}

ExecRunner is the Runner backed by os/exec.

func (ExecRunner) Output

func (ExecRunner) Output(
	ctx context.Context,
	dir string,
	env map[string]string,
	toolOutput io.Writer,
	name string,
	args ...string,
) ([]byte, error)

func (ExecRunner) Run

func (ExecRunner) Run(
	ctx context.Context,
	dir string,
	env map[string]string,
	toolOutput io.Writer,
	name string,
	args ...string,
) error

type ExtractConfig

type ExtractConfig struct {
	// Command produces a handler manifest. Run through the shell, from the
	// application directory.
	Command string `json:"command"`
	// ManifestFile is where Command writes the manifest, relative to the
	// application directory. When empty the manifest is read from the
	// command's standard output.
	ManifestFile string `json:"manifestFile,omitempty"`
}

ExtractConfig describes a command that reports an application's handlers.

type ExtractParams

type ExtractParams struct {
	AppDir string
}

ExtractParams describes a handler extraction run.

type Options

type Options struct {
	// Runtime is the blueprint's runtime identifier.
	Runtime string
	// AppDir is the application directory.
	AppDir string
	// Config is the handlerBuild block, or nil when the app declares none.
	Config *Config
	// Runner runs external commands. Defaults to ExecRunner.
	Runner Runner
}

Options configures toolchain resolution.

type PrepareParams

type PrepareParams struct {
	AppDir string
	// DeployTarget is the app's deploy target (e.g. "aws-serverless"), which
	// decides the platform packages linked into the executable.
	DeployTarget string
	// Mode is ModeDev or ModeDeploy.
	Mode string
	// ResourceKinds are the Celerity resource kinds the blueprint declares
	// (bucket, queue, topic, cache, datastore, sqlDatabase), so the toolchain
	// links an implementation for each.
	ResourceKinds []string
	// SQLEngines are the engines of the blueprint's SQL databases
	// (e.g. "postgres"), so a driver is linked for each.
	SQLEngines []string
	// Telemetry names what traces are exported with, or is empty for none.
	Telemetry string
	// TestPackages links the platform packages into the project's integration
	// suites as well as into the application, so a test that reaches a real
	// resource reaches it through the same provider the deployed binary would.
	// Set for a dev session and not for a deploy, where there are no tests to
	// generate for.
	TestPackages bool
}

PrepareParams describes the code generation a toolchain does before either building or extracting.

type Runner

type Runner interface {
	// Run executes name with args in dir, with env added to the process
	// environment, streaming output to toolOutput.
	Run(ctx context.Context, dir string, env map[string]string, toolOutput io.Writer, name string, args ...string) error
	// Output executes the command and returns its standard output, streaming
	// only standard error to toolOutput.
	Output(ctx context.Context, dir string, env map[string]string, toolOutput io.Writer, name string, args ...string) ([]byte, error)
}

Runner runs the external commands a toolchain drives.

Declared here rather than reused from internal/build so this package stays a leaf. The two are the same shape by coincidence of both shelling out rather than because they share a contract.

type Toolchain

type Toolchain interface {
	// Name identifies the toolchain in output and errors (e.g. "go").
	Name() string

	// Validate reports whether the project is actually set up for this
	// toolchain, so a missing SDK dependency fails before a build does.
	Validate(appDir string) error

	// Prepare runs whatever code generation has to happen before the
	// application will compile for this target. It is safe to call more than
	// once and regenerates rather than reusing what is on disk, because a dev
	// session's generated file is the wrong one for a deploy and vice versa.
	Prepare(ctx context.Context, p PrepareParams) error

	// Extract reports the handlers the executable serves. Returning a nil
	// manifest means this toolchain cannot extract, and the blueprint's
	// hand-authored handler resources are used as they are.
	//
	// Callers run Prepare first: extraction compiles the application, so it
	// fails on a project whose generated platform imports are absent or stale.
	Extract(ctx context.Context, p ExtractParams) (*preprocess.HandlerManifest, error)

	// BuildBinary compiles the handlers executable to p.OutputPath.
	BuildBinary(ctx context.Context, p BinaryParams) error

	// WatchPaths describes what a dev session should watch.
	WatchPaths() WatchPaths

	// TestCommand returns the command for a named test suite, and whether one
	// is configured.
	TestCommand(suite string) ([]string, bool)
}

Toolchain turns an application's source into a handlers executable for an OS-only runtime, and reports what that executable serves.

func Resolve

func Resolve(opts Options) (Toolchain, error)

Resolve returns the toolchain for an application, or (nil, nil) where the runtime is not an OS-only one.

Returning nil rather than an error for Node.js and Python keeps every call site uniform. A caller threads whatever comes back, and the nil case means the runtime hosts the language itself and there is nothing to build.

An explicit handlerBuild block wins over an inferred Go project, because a Go application that declares one has asked to drive its own build.

type WatchPaths

type WatchPaths struct {
	// Roots are directories relative to the application directory.
	Roots []string
	// Extensions are the file extensions a change is relevant for.
	Extensions []string
	// SkipDirs are directory names not to descend into.
	SkipDirs []string
	// SkipFiles are base names a change is never relevant for, whatever their
	// extension.
	//
	// A toolchain's own generated file has to be listed here or a session
	// cannot settle, because Prepare rewrites that file and reacting to the
	// rewrite runs Prepare again.
	SkipFiles []string
}

WatchPaths describes what a dev session's file watcher should follow.

Returned by the toolchain rather than read from the runtime conventions because all three are properties of the language. A Go module keeps its handlers at the module root while a Node project keeps them under src/, and a Rust project needs the .toml files no other language does.

Jump to

Keyboard shortcuts

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