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

build

package
v0.5.5 Latest Latest
Warning

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

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

Documentation

Overview

Package build produces the container image of a DAG project and reports what it pushed.

A Builder is one way of producing that image. ADR 0073 decides the order builders are tried in (ResolutionOrder): skip the build when the dependency image already exists, append a code layer, pack a daemonless dependency layer, use a remote builder, and only then fall back to a local container daemon. These exist today: Existing, the skip path in its first form (the whole image for this content label is already in the registry, see Select); CodeLayer, which appends the DAG code to a dependency image the registry holds, or first builds that dependency image, from wheels without a daemon (DependencyLayer, ADR 0078), with the remote builder or with the daemon (ADR 0077); CloudBuild and InCluster, the remote builder on Google Cloud Build (ADR 0083) or on the in-cluster BuildKit daemon the Helm chart runs (Remote, #1883); and LocalDaemon. Every builder returns a Result that carries the digest of the image it pushed, so the caller pins dag.json to exactly those bytes (ADR 0003, ADR 0041).

Builders run out of process or through a registry API; none links the Docker SDK (ADR 0015).

Index

Constants

View Source
const (
	ProviderGoogle = "Google Cloud"
	ProviderAWS    = "AWS"
	ProviderAzure  = "Azure"
)

The cloud providers a registry host can belong to.

View Source
const PlatformPattern = `^[A-Za-z0-9]+/[A-Za-z0-9_]+(/[A-Za-z0-9]+)?$`

PlatformPattern is the os/arch[/variant] form a platform takes, as a regular expression. Case is not checked: docker matches platforms without regard to it. domain.DeployDefaults validates cluster platforms with the same expression.

View Source
const SourceDockerConfig = "the docker config"

SourceDockerConfig is the Source of a credential the docker config or one of its credential helpers holds.

View Source
const Workdir = "/home/leoflow"

Workdir is where the DAG code lands in the image, the working directory of the runtime base and the destination of every COPY of the generated Dockerfile.

Variables

View Source
var ErrMultiPlatform = errors.New("the multi-platform build failed")

ErrMultiPlatform marks the failure of a build for several platforms; the error wraps the builder's own failure and says how to build one platform.

View Source
var ErrPinRead = errors.New("the image was pushed, but its digest could not be read")

ErrPinRead marks a build whose push succeeded and whose read of the pushed image's digest, asked for by Request.Pin, failed (#1703). The builder then returns the Result of the push, Pushed and without Ref, with the error, so a caller that may register a tag (compile) keeps it, and one that must register a digest (deploy) stops. A read that verifies a multi-platform push is not a pin read: its failure leaves the push unverified.

View Source
var ErrPushDenied = errors.New("the registry refused a push")

ErrPushDenied is the registry refusing a push to the repository (401 or 403): the credential is missing, or may not push there.

Functions

func CheckReference

func CheckReference(image string) error

CheckReference refuses an image that is not a reference Resolve can read, so a reference given on the command line is refused before anything is read or sent.

func CheckRegistryHost added in v0.5.5

func CheckRegistryHost(host string) error

CheckRegistryHost reports whether host names a registry the way a login takes it: a host with an optional port and nothing else, no scheme, path or user, and not empty, which the registry client would read as Docker Hub. The error quotes host escaped, never as given.

func CloudBuildSourceBucket

func CloudBuildSourceBucket(project string) string

CloudBuildSourceBucket is the bucket where gcloud builds submit stages the source archive of a build in project, as gcloud names it: the project id with ':' and '.' replaced by '_' and "google" by "elgoog", which bucket names may not contain.

func LoginCommand

func LoginCommand(host, tool string) string

LoginCommand is the command that signs tool (docker when empty) in to the registry at host once, so its pushes and the registry client's find a credential: for docker, the cloud CLI's own docker login; for another tool, the cloud's token piped to `<tool> login`. For a registry no cloud owns, `dexaflow registry login <host>` when the tool is docker: it needs no docker and stores the credential in the docker config, which docker and the registry client both read (StoreLogin); `<tool> login <host>` for another tool, which keeps credentials of its own.

func NormalizeDistName

func NormalizeDistName(n string) string

NormalizeDistName is a distribution name as PyPI compares names (PEP 503): lower case, with runs of -, _ and . as one -.

func ParsePlatforms

func ParsePlatforms(values []string) ([]string, error)

ParsePlatforms validates platform values as given on a command line, each either one platform or a comma-separated list, and returns them in order with duplicates removed. An empty or malformed value is an error: the value reaches a build tool's argv and a registry manifest, so only the os/arch form is accepted.

func PinnedRef

func PinnedRef(image, digest string) string

PinnedRef replaces the tag or digest of image with digest and keeps the rest as written, so a docker.io image reads as the user wrote it.

func StoreLogin added in v0.5.5

func StoreLogin(ctx context.Context, host, user, secret string) (string, error)

StoreLogin writes user and secret for the registry host to the docker config (DOCKER_CONFIG, else ~/.docker/config.json), where the registry client's keychain reads it and docker, podman and nerdctl find it too. A credHelpers entry for the host, else a credsStore, keeps the secret in that helper (the system keychain) through the credential helper protocol, as `docker login` does, and the file records only the host; otherwise the secret goes in the file's auths, base64 as docker writes it. Every other field of the file is kept, and the file stays readable by its owner only. Docker Hub is filed under its legacy key, whichever of its names host is. It returns the path of the config file. ctx bounds the helper's run.

func VerifyLogin added in v0.5.5

func VerifyLogin(ctx context.Context, host, user, secret string) error

VerifyLogin checks that the registry host accepts user and secret: it speaks the registry API's handshake as a push would (a Basic challenge, or the token exchange of a Bearer one, as GHCR and Docker Hub answer) and asks /v2/ with what it got. The secret never appears in the error.

Types

type AuthMethod

type AuthMethod string

AuthMethod is where the registry client reads a registry credential, the registry.auth_method of dexaflow.yaml.

const (
	// AuthAuto reads the docker config and its credential helpers, then,
	// when they hold nothing for the registry, the session of the cloud CLI
	// that owns its host. It is the default.
	AuthAuto AuthMethod = "auto"
	// AuthDockerConfig reads the docker config and its credential helpers
	// only, as every release before auto did.
	AuthDockerConfig AuthMethod = "docker_config"
	// AuthCloud reads the cloud CLI session only for a host a cloud owns, so
	// a stale entry in the docker config (an ECR token is good for 12 hours)
	// is never sent there; a host no cloud owns (ghcr.io, Harbor) has no
	// cloud session and reads the docker config.
	AuthCloud AuthMethod = "cloud"
)

The values of registry.auth_method.

func ParseAuthMethod

func ParseAuthMethod(v string) (method AuthMethod, note string, err error)

ParseAuthMethod reads a registry.auth_method value. Empty is AuthAuto. The two values the schema accepted before any was implemented, env and iam, still parse, with a note to print, and read as auto, which keeps the docker config they were read with.

type BaseImage

type BaseImage struct {
	// Format is the layout of a cached listing (baseCacheFormat).
	Format int `json:"format"`
	// Digest is the digest of the platform image, sha256:<hex>.
	Digest string `json:"digest"`
	// Python is PYTHON_VERSION of the image config, X.Y.Z; empty when the
	// config sets none, which no Dexaflow runtime base does.
	Python string `json:"python"`
	// Glibc is the version of the libc6 package dpkg installed, X.Y; empty
	// when the image records none (a musl or distroless image).
	Glibc string `json:"glibc"`
	// SitePackages reports that the image has the site-packages directory
	// of Python, usr/local/lib/pythonX.Y/site-packages.
	SitePackages bool `json:"site_packages"`
	// Dists are the distributions installed in that site-packages, as
	// name==version with the name normalized, sorted.
	Dists []string `json:"dists"`
	// PipConfig names what in the image tells pip where or what to install,
	// sorted: PIP_* (and XDG_CONFIG_*) variables of the config, and pip
	// configuration files (/etc/pip.conf, ...). The daemon's pip honors
	// them; the dependency layer cannot, so it declines such a base.
	PipConfig []string `json:"pip_config"`
}

BaseImage is what the daemonless dependency layer (ADR 0078) needs to know about one platform image of the runtime base.

func (BaseImage) MinorPython

func (b BaseImage) MinorPython() string

MinorPython is the X.Y of Python, or "" when the image has none.

func (BaseImage) SitePackagesDir

func (b BaseImage) SitePackagesDir() string

SitePackagesDir is the site-packages directory of the image, without a leading slash.

type Builder

type Builder interface {
	// Path is the resolution step this builder implements.
	Path() Path
	// Describe names the builder for the command output.
	Describe() string
	// Build produces the image described by req.
	Build(ctx context.Context, req Request) (Result, error)
}

Builder produces a DAG image.

func Select

func Select(ctx context.Context, o Options, image string, platforms []string) (b Builder, reason string)

Select resolves the builder for a build of image for platforms in ResolutionOrder, and says why it was chosen. The skip path applies when reuse is allowed and the registry already holds image for every platform (ADR 0076). Then a split build (ADR 0077) appends the DAG code to the dependency image when the registry holds it for every platform, or first builds that dependency image, from wheels (Split.Wheels, ADR 0078), with the remote builder or with the local daemon. Otherwise the remote builder builds the whole image when one is configured and applies (Options.Remote, ADR 0083), and the local daemon when not.

type CloudBuild

type CloudBuild struct {
	// Project is the Google Cloud project the build runs in.
	Project string
	// Region is the Cloud Build region; gcloud's builds/region, else global,
	// when empty.
	Region string
	// WorkerPool is a private pool, projects/<p>/locations/<r>/workerPools/<n>;
	// the default pool when empty.
	WorkerPool string
	// ServiceAccount is the service account the build runs as,
	// projects/<p>/serviceAccounts/<email>; Cloud Build's default when empty.
	ServiceAccount string
	// Tool is the gcloud executable, "gcloud" from PATH when empty.
	Tool string
	// Registry reads the pushed digest; the registry client when nil.
	Registry Resolver
	// Poll is how often a build whose log cannot be streamed is described
	// until it ends, and the first wait before a failed describe is tried
	// again; cloudBuildPoll when zero.
	Poll time.Duration
	// MaxContext is the largest compressed build context uploaded, in
	// bytes; defaultMaxContext (2 GiB) when zero.
	MaxContext int64
}

CloudBuild builds on Google Cloud Build through the gcloud CLI.

func (CloudBuild) Build

func (b CloudBuild) Build(ctx context.Context, req Request) (Result, error)

Build packs the listed context with the Dockerfile, submits it to Cloud Build, follows the build until it ends (it pushes the image), and, when a pin is asked for, reads the pushed image's digest from the registry and checks it is the one the build reports.

func (CloudBuild) Decline

func (CloudBuild) Decline(platforms []string) string

Decline says why platforms are not built here: anything but one linux/amd64 image.

func (CloudBuild) Describe

func (b CloudBuild) Describe() string

Describe names the path, the backend and where it builds, such as "remote (cloud-build, project acme-ci, region us-central1)".

func (CloudBuild) Path

func (CloudBuild) Path() Path

Path is PathRemote.

func (CloudBuild) Ready

func (b CloudBuild) Ready(_ context.Context) error

Ready reports whether gcloud is on PATH.

type CloudCLI

type CloudCLI struct {
	// contains filtered or unexported fields
}

CloudCLI is the CloudKeychain of the cloud CLIs on PATH: gcloud, aws and az. It runs the one that owns the registry host and keeps its token for cloudTokenTTL, and a failure for cloudFailureTTL.

func NewCloudCLI

func NewCloudCLI(run CommandRunner) *CloudCLI

NewCloudCLI returns a CloudCLI that runs the cloud CLIs through run.

func (*CloudCLI) Credential

func (c *CloudCLI) Credential(ctx context.Context, host string) (Credential, error)

Credential runs the cloud CLI that owns host, or nothing when no cloud does.

func (*CloudCLI) Owns

func (c *CloudCLI) Owns(host string) bool

Owns reports whether DetectCloudRegistry knows host.

type CloudKeychain

type CloudKeychain interface {
	// Owns reports whether a cloud owns the registry host, so that its
	// session is the place to read a credential for it.
	Owns(host string) bool
	// Credential returns the credential the cloud session holds for the
	// registry host, an empty Credential when no cloud owns host, or an
	// error saying why the session gave none.
	Credential(ctx context.Context, host string) (Credential, error)
}

CloudKeychain reads a registry credential from a cloud session.

type CloudRegistry

type CloudRegistry struct {
	// Provider is ProviderGoogle, ProviderAWS or ProviderAzure.
	Provider string
	// Host is the registry host, as `docker login` takes it.
	Host string
	// Region is the AWS region of an ECR host.
	Region string
	// Name is the registry name of an ACR host.
	Name string
}

CloudRegistry is a registry host a cloud CLI signs in to.

func DetectCloudRegistry

func DetectCloudRegistry(host string) (CloudRegistry, bool)

DetectCloudRegistry reports whether host is a registry a cloud CLI signs in to, and which: gcr.io and its regional hosts and Artifact Registry (<location>-docker.pkg.dev) for Google Cloud, a private ECR registry for AWS, an ACR registry for Azure.

func (CloudRegistry) PushRole

func (c CloudRegistry) PushRole() string

PushRole is the permission the signed-in account needs to push to the registry.

func (CloudRegistry) SessionCommand

func (c CloudRegistry) SessionCommand() string

SessionCommand is the command that signs this machine in to the cloud whose session the registry client reads.

type CodeLayer

type CodeLayer struct {
	// Split names the dependency image and its Dockerfile.
	Split Split
	// Deps is the dependency image found in the registry, or nil when it is
	// built first.
	Deps *Pinned
	// Daemon builds the dependency image when Deps is nil and neither the
	// wheels nor Remote do.
	Daemon LocalDaemon
	// Remote builds the dependency image in the daemon's place when it is
	// set (path 4): when the wheels do not apply, or fail.
	Remote Remote
	// Registry reads digests and pushes the image.
	Registry codeRegistry
}

CodeLayer builds the DAG image as Split says. With Deps set, the dependency image is already in the registry and no daemon runs (the code-layer path); without it, the dependency layer (Split.Wheels), the remote builder or the local daemon builds and pushes the dependency image first.

func (CodeLayer) Build

func (c CodeLayer) Build(ctx context.Context, req Request) (Result, error)

Build pushes the DAG image: the dependency image, built first when Deps is nil, with req.Code appended. The result is pinned to the digest the registry returns for the pushed image (ADR 0075).

func (CodeLayer) Describe

func (c CodeLayer) Describe() string

Describe names the path, and what builds the dependency image when it is built.

func (CodeLayer) Path

func (c CodeLayer) Path() Path

Path is PathCodeLayer when the dependency image is reused, PathDependencyLayer when it is built from wheels, PathRemote when the remote builder builds it, PathLocalDaemon when the daemon does.

type CommandRunner

type CommandRunner func(ctx context.Context, argv []string) ([]byte, error)

CommandRunner runs argv and returns what it printed on stdout.

type Credential

type Credential struct {
	// Username and Password are what the registry is sent.
	Username, Password string
	// Source names where the credential came from, for the command output,
	// such as "the gcloud session".
	Source string
}

Credential is a registry credential and where it came from.

type DependencyLayer

type DependencyLayer struct {
	// Base is the runtime base, pinned by digest: an index or one image.
	Base Pinned
	// Python is the X.Y of the base's Python.
	Python string
	// Env are the KEY=VALUE variables the image sets on top of the base's.
	Env []string
	// User is the user the image runs as; empty keeps the base's.
	User string
	// Installer installs the dependencies of each platform.
	Installer Installer
	// Registry is the registry client that reads the base and pushes the
	// image, with its credentials (registry.auth_method).
	Registry Registry
}

DependencyLayer builds the dependency image without a daemon (path 3, ADR 0078): for each platform, the Installer installs the wheels into a directory, the directory is packed as one deterministic layer under /usr/local, and the layer is appended to the runtime base through the registry API, with the image configuration of the generated Dockerfile.

func (DependencyLayer) Push

func (d DependencyLayer) Push(ctx context.Context, image string, platforms []string) error

Push builds the dependency image for platforms and pushes it under image: an index when the base is one (its attestation manifests dropped, its other platforms left out), one image otherwise.

type Existing

type Existing struct {
	// Pinned is what the registry holds under the image tag.
	Pinned Pinned
}

Existing is the skip path: the registry already holds the image for this build's content, so nothing is built or pushed and the image is pinned to the digest the registry returned when Select looked it up.

func (Existing) Build

func (e Existing) Build(_ context.Context, req Request) (Result, error)

Build returns the image already in the registry, pinned.

func (Existing) Describe

func (Existing) Describe() string

Describe names the path.

func (Existing) Path

func (Existing) Path() Path

Path is PathSkip.

type InCluster added in v0.5.5

type InCluster struct {
	// Namespace is the namespace of the builder.
	Namespace string
	// PodSelector is the label selector of the builder pod; the chart's
	// (domain.DefaultBuildKitPodSelector) when empty.
	PodSelector string
	// Context is the kubeconfig context; kubectl's current one when empty.
	Context string
	// Registry reads the pushed digest when BuildKit reports none; the
	// registry client when nil.
	Registry Resolver
}

InCluster builds on the in-cluster BuildKit daemon, through buildctl over kubectl exec.

func (InCluster) Build added in v0.5.5

func (b InCluster) Build(ctx context.Context, req Request) (Result, error)

Build finds the ready builder pod, builds req on it with buildctl, which pushes the image, and pins the digest BuildKit reports for the push, or, when it reports none, the digest the registry holds.

func (InCluster) Decline added in v0.5.5

func (InCluster) Decline(platforms []string) string

Decline says why platforms are not built here: the rootless builder sets up no emulation, so it builds one platform, its node's.

func (InCluster) Describe added in v0.5.5

func (b InCluster) Describe() string

Describe names the path, the backend and where it builds, such as "remote (buildkit, namespace dexaflow-builder)".

func (InCluster) Path added in v0.5.5

func (InCluster) Path() Path

Path is PathRemote.

func (InCluster) Ready added in v0.5.5

func (b InCluster) Ready(ctx context.Context) error

Ready reports whether buildctl and kubectl are on PATH and whether the person deploying may exec into pods of the builder namespace, which is what the chart's Role grants to builder.subjects. A builder this person may not use is passed over for the local daemon when its tool is on PATH.

type Installer

type Installer interface {
	// Describe names the installer and its version, "uv 0.11.32".
	Describe() string
	// Install installs the dependencies of platform into dir.
	Install(ctx context.Context, platform, dir string) error
}

Installer installs the resolved Python dependencies of one platform into a directory, as `pip install --target` lays them out (ADR 0078).

type LayerFile

type LayerFile struct {
	// Path is the slash-separated path under the root of the layer: Workdir
	// for the code layer.
	Path string
	// Source is the file on disk whose bytes the entry carries; empty for a
	// directory or a symlink.
	Source string
	// Dir marks a directory entry.
	Dir bool
	// Link is the target of a symlink entry, kept as written.
	Link string
	// Exec marks a regular file with an execute bit, which keeps it
	// executable in the image.
	Exec bool
}

LayerFile is one entry of a layer the CLI packs: the code layer, or the dependency layer of path 3.

type LocalDaemon

type LocalDaemon struct {
	// Tool is the executable to run, "docker" when empty.
	Tool string
	// Registry reads the pushed digest; the registry client when nil.
	Registry Resolver
}

LocalDaemon builds with a local container tool, docker, podman or nerdctl, by shelling out to it: `<tool> build` and `<tool> push`, or one `docker buildx build --push` when docker has buildx. The digest of what it pushed is taken from the tool's report of the push (the buildx metadata file, podman's --digestfile, the last line of docker push), never from the tool's image store; when the tool reports none it is read from the registry (ADR 0075, ADR 0087). It is the last step of the resolution order, the fallback for when no daemonless or remote builder applies.

func (LocalDaemon) Build

func (b LocalDaemon) Build(ctx context.Context, req Request) (Result, error)

Build runs the build, then the push when asked, and takes the digest of what it pushed from the tool's own report of the push (pushImage). The registry is read only to check that a push of several platforms holds every one of them (verifyPlatforms), at that digest, or, when the tool reported no digest, at the tag, as ADR 0075 decided (ADR 0087).

func (LocalDaemon) Describe

func (b LocalDaemon) Describe() string

Describe names the path and the tool, such as "local-daemon (docker)".

func (LocalDaemon) Path

func (b LocalDaemon) Path() Path

Path is PathLocalDaemon.

type Options

type Options struct {
	// Tool is the local container tool for the fallback path (--builder).
	Tool string
	// Reuse allows the skip path: the image tag names the build's content
	// (the default version label with tag_strategy version), so an image the
	// registry already holds under it was built from the same inputs. The
	// caller leaves it off for any other tag and for --rebuild.
	Reuse bool
	// Split is how this build divides into a dependency image and a code
	// layer (ADR 0077), or nil when it cannot: then NoSplit says why.
	Split *Split
	// NoSplit says why the build is not split, for the builder line; empty
	// when there is nothing to say (a build that is not pushed).
	NoSplit string
	// Rebuild builds the dependency image again even when the registry holds
	// one for its key (--rebuild).
	Rebuild bool
	// Registry reads what the registry holds; the registry client when nil.
	// A split build also needs it to push (codeRegistry).
	Registry Resolver
	// Remote is the remote builder the project or its target configured
	// (path 4), or nil when none is.
	Remote Remote
	// RemoteSource names where Remote was configured, for the builder line,
	// such as the project's dexaflow.yaml.
	RemoteSource string
	// Push says the build is pushed. The remote builder pushes what it
	// builds, so it applies only to a pushed build.
	Push bool
	// LocalOnly says why the build must run on this machine (its build
	// secrets or package index come from this machine's environment), or ""
	// when the remote builder may take it.
	LocalOnly string
}

Options are the inputs to builder selection.

type Path

type Path string

Path names one step of the builder resolution order.

const (
	// PathSkip reuses the whole image of the content label already in the
	// registry (ADR 0076). A cached dependency image is reused by
	// PathCodeLayer (ADR 0077).
	PathSkip Path = "skip"
	// PathCodeLayer appends the DAG code as a layer to a cached dependency
	// image through the registry API.
	PathCodeLayer Path = "code-layer"
	// PathDependencyLayer installs wheels for the target platform without a
	// daemon and packs them as a layer on the runtime base.
	PathDependencyLayer Path = "dependency-layer"
	// PathRemote builds in a remote builder: an in-cluster build pod or a
	// cloud builder.
	PathRemote Path = "remote"
	// PathLocalDaemon shells out to a local container tool (docker, podman,
	// nerdctl). It is the fallback, never the default.
	PathLocalDaemon Path = "local-daemon"
)

The builder resolution order of ADR 0073, first to last.

func ResolutionOrder

func ResolutionOrder() []Path

ResolutionOrder returns the builder paths in the order the CLI tries them.

type Pinned

type Pinned struct {
	// Ref is the image as written with its tag replaced by the digest,
	// <repo>@sha256:<hex>.
	Ref string
	// Manifest is the raw manifest or index the digest names.
	Manifest []byte
	// Platform is os/arch[/variant] from the config of a single image, filled
	// by the skip path only (Registry.Platform); empty for an index.
	Platform string
}

Pinned is what a registry says a reference names.

type PushAccess

type PushAccess struct {
	// Registry is the registry host, as a `docker login` takes it.
	Registry string
	// Repository is the repository a push goes to, <registry>/<path>.
	Repository string
	// Anonymous is true when no credential was found for the registry, in
	// the docker config, its credential helpers or the cloud session, as
	// the auth method reads them.
	Anonymous bool
	// Source names where the credential came from (SourceDockerConfig, or
	// the cloud CLI's session); empty when Anonymous.
	Source string
	// CloudError says why the cloud session gave no credential, when it was
	// asked and could not (the CLI is not installed or not signed in). It
	// carries the command and the last line of its stderr, capped; the token
	// is on stdout and never in it.
	CloudError error
}

PushAccess is what a push check found out about a repository.

type Registry

type Registry struct {
	// Auth is registry.auth_method; empty is AuthAuto.
	Auth AuthMethod
	// Cloud reads the cloud session; the cloud CLIs on PATH when nil.
	Cloud CloudKeychain
}

Registry is the CLI's registry client (ADR 0073, section 3). It speaks the registry API in process, never through a local image store, so an image any tool pushed can be pinned (ADR 0075). Its credentials are those `dexaflow registry login` (StoreLogin), `docker login` and its credential helpers wrote (authn.DefaultKeychain) and, for a registry a cloud owns, that cloud CLI's session, as Auth says (ADR 0080). The zero value reads both, the default of registry.auth_method.

func (Registry) AppendCode

func (r Registry) AppendCode(ctx context.Context, base Pinned, files []LayerFile, image string) error

AppendCode pushes image: the dependency image base with files appended as one code layer, to every platform image of base when it is an index. Attestation manifests of an index are dropped, since they describe the images without the layer. The layers of base are not uploaded again: the registry already holds them in the repository base and image share.

func (Registry) Base

func (r Registry) Base(ctx context.Context, base Pinned, platform string) (BaseImage, error)

Base reads what the platform image of base (an index or a single image, pinned by digest) holds for the daemonless dependency layer: the Python version of its config and, for a runtime base, the glibc version and the distributions of its site-packages, from the layer tar headers (and the dpkg status file). The listing is cached by the platform image digest under the user cache directory, so a redeploy reads no layer again.

func (Registry) CheckPush

func (r Registry) CheckPush(ctx context.Context, image string) (PushAccess, error)

CheckPush asks the registry of image whether a push to its repository is allowed, with the credentials a push would use (resolveAuth), before anything is built (#1705). It starts a blob upload, which a registry authorizes like a push, and cancels it, best effort (cancelUpload): a registry that refuses the DELETE (ECR and Harbor may) keeps an empty upload until it expires it, and no blob or manifest is written. A 401 or 403 is ErrPushDenied; any other failure says nothing about the right to push and is returned as it is. Plain HTTP is spoken only to the loopback, as for Resolve.

func (Registry) Copy

func (r Registry) Copy(ctx context.Context, src, dstRepo, tag string) (string, error)

Copy copies the image src names, pinned by digest, into the repository dstRepo of another registry (or the same one), with every layer and, for an index, every platform's image, and returns dstRepo@digest. The manifest is copied byte for byte, so the copy has the source's digest: `dexaflow promote` registers the same bytes on another control plane (#1708). With a tag the copy is pushed under it too, so a registry that collects untagged images keeps it, and a tag that already names another digest is refused, never moved; without one it is pushed by digest. The copy is checked afterwards with a HEAD of dstRepo@digest. Credentials and transport are those of Resolve, read per registry.

func (Registry) Platform

func (r Registry) Platform(ctx context.Context, ref string) (string, error)

Platform reads os/arch[/variant] from the config of the single image ref names (a pinned reference), or "" when the config names no platform. It is a second request, made only by the skip path, which must know what a single image was built for.

func (Registry) Resolve

func (r Registry) Resolve(ctx context.Context, image string) (Pinned, error)

Resolve reads the digest and the manifest that image names. Only a registry on localhost, a *.localhost name or a loopback address may answer over plain HTTP (plainHTTPOnLoopback); every other one is spoken to over verified TLS. Only an OCI or Docker v2 manifest or index is accepted, so the digest is always the one computed from the manifest returned.

type Remote

type Remote interface {
	Builder
	// Ready says why the builder cannot run on this machine (its CLI is not
	// on PATH, or the person deploying may not use it), or nil when it can.
	Ready(ctx context.Context) error
	// Decline says why the builder does not build for platforms, or "" when
	// it does.
	Decline(platforms []string) string
}

Remote is a builder of the remote path: it builds a whole image from a Dockerfile and a listed context somewhere else and pushes it. Select asks it whether it can before it picks it.

type Request

type Request struct {
	// Image is the tag reference to build, <registry>/<name>:<tag>.
	Image string
	// Dockerfile is the path of the Dockerfile the build reads.
	Dockerfile string
	// ContextDir is the build context, the DAG project directory.
	ContextDir string
	// Platforms are the os/arch targets; empty means the builder's default.
	Platforms []string
	// Push pushes the image to its registry after the build.
	Push bool
	// Pin asks for the digest of the pushed image in Result.Ref. It needs
	// Push: an image that is not pushed has no registry digest.
	Pin bool
	// Code is the DAG project files of the code layer, for a split build
	// (Split); other builders read ContextDir.
	Code []LayerFile
	// ContextFiles is the build context as the build would read it, the
	// files of ContextDir that the .dockerignore keeps, for a builder that
	// sends the context to another machine (the remote path). nil means not
	// listed: such a builder refuses to run rather than send the whole
	// directory; an empty list is an empty context.
	ContextFiles []LayerFile
	// BuildArgs are the build arguments a Dockerfile build passes with
	// --build-arg, in name order. Plain values, never secrets.
	BuildArgs map[string]string
	// Secrets are the build secrets a Dockerfile build passes with
	// --secret id=<ID>,env=<Env>; the tool reads each value from its own
	// environment, so none reaches its argv.
	Secrets []Secret
	// Env are KEY=VALUE variables added to the environment of the tool, for
	// a secret whose value the caller composed (the package index URL).
	Env []string
	// Stdout and Stderr receive the builder's own output.
	Stdout io.Writer
	Stderr io.Writer
}

Request is one image to produce.

type Resolver

type Resolver interface {
	// Resolve returns what image (a tag reference) names in its registry.
	Resolve(ctx context.Context, image string) (Pinned, error)
}

Resolver reads a pushed image's digest and manifest from its registry.

type Result

type Result struct {
	// Path is the resolution step that produced the image.
	Path Path
	// Image is the tag reference that was built.
	Image string
	// Platforms are the platforms the image was built for.
	Platforms []string
	// Pushed reports that the image is in its registry.
	Pushed bool
	// Ref is the digest-pinned reference, <repo>@sha256:<hex>, when the
	// request asked for a pin; empty otherwise.
	Ref string
}

Result is what a builder produced.

func (Result) Digest

func (r Result) Digest() string

Digest returns the sha256:<hex> part of Ref, or "" when the result is not pinned.

type Secret added in v0.5.5

type Secret struct {
	// ID is the id of --mount=type=secret,id=<ID>.
	ID string
	// Env is the environment variable holding the value.
	Env string
}

Secret is one build secret: the id a RUN line mounts it under, and the environment variable of the tool that holds its value.

type Split

type Split struct {
	// DepsImage is the dependency image, <repo>:deps-<key> in the DAG's own
	// repository.
	DepsImage string
	// Dockerfile is the content of the dependency image's Dockerfile. It
	// copies nothing, so it builds from an empty context.
	Dockerfile string
	// Wheels builds the dependency image without a daemon (ADR 0078), or is
	// nil when the daemon builds it from Dockerfile; then NoWheels says why.
	Wheels *DependencyLayer
	// DaemonDepsImage is the dependency image the daemon builds, under the
	// key of its own builds (ADR 0077), when Wheels fails before anything is
	// pushed; empty when the daemon's key cannot cover the dependencies
	// (they are not pinned), and then the failure stands.
	DaemonDepsImage string
	// NoWheels says why the dependency layer does not apply, for the
	// builder line; empty when Wheels is set.
	NoWheels string
	// Note is said on the builder line after the reason, such as how long
	// the resolution of the dependencies took; empty when there is nothing
	// to say.
	Note string
}

Split describes a build of the DAG image as a dependency image plus a code layer (ADR 0073 section 4, ADR 0077): the dependency image holds the base, the system packages and the Python dependencies, and is reused for as long as its Dockerfile and platforms are unchanged; the code layer holds the DAG project files and is appended to it through the registry API.

Jump to

Keyboard shortcuts

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