Dagger
Search

z5labs

and release pipelines for Go projects. Construct via the GoApp or GoLib
factories on Z5labs; call the terminal Ci method to run the pipeline.

Installation

dagger install github.com/z5labs/devex/daggerverse/z5labs@40748316f5487a0b9755b5c5f46e3d15403153fd

Types

Z5Labs 🔗

Z5labs is the root module type. Construct project archetypes via GoApp / GoLib.

goApp() 🔗

GoApp wires up an opinionated CI/release pipeline for a package main Go application. Call Ci to run checks + multi-arch buildpublish, or Builder to produce the same image single-arch locally.

Every binary GoApp builds is stamped at link time with the version and the commit it was built from, so an application can answer “which build am I running” without a second build definition beside this one. Declare these two package-level vars in your main package and they are filled in:

var (
	version = "dev"
	commit  = "none"
)

The names are fixed by the module — main.version and main.commit — and the values are taken from HEAD, never from a parameter. A tag pointing at HEAD gives version the stripped tag name; anything else gives “-”, the same rule the published image tag follows, so the two agree by construction. commit is the short HEAD SHA. Because both are functions of the commit alone, two builds of one commit are byte-identical; there is no caller-supplied value that could break that. Source without git metadata at HEAD is an error.

publishOn is a regex evaluated against source repo’s HEAD refs (after normalizing refs/remotes/origin/Xrefs/heads/X); matches trigger publish. When registry is set, auth is required.

platforms defaults to [“linux/amd64”,“linux/arm64”].

registryService, when non-nil, is a Dagger-hosted registry reached over the session network instead of over the public network — used by tests against a local registry service and by callers whose private registry is itself a Dagger service. Its endpoint is assigned by the engine, so it replaces registry as the address published to; registry is still what decides that a publish happens at all.

insecure means plain HTTP and no TLS verification, and it is off unless the caller asks for it. It is deliberately not inferred from registryService being set: that inference made a caller who supplied a service for their own reasons silently publish over an unverified connection. It is spelled insecure rather than tlsVerify because a bool defaulting to true cannot be turned off from the CLI.

Return Type
GoApp !
Arguments
NameTypeDefault ValueDescription
sourceDirectory !-No description provided
pkgString "."No description provided
binaryNameString -No description provided
publishOnString "^refs/heads/main$"No description provided
registryString -No description provided
authUsernameString "ci"No description provided
authSecret -No description provided
lintConfigFile -No description provided
platforms[String ! ] -No description provided
registryServiceService -No description provided
insecureBoolean -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/z5labs@40748316f5487a0b9755b5c5f46e3d15403153fd call \
 go-app --source DIR_PATH
func (m *MyModule) Example(source *dagger.Directory) *dagger.Z5LabsGoApp  {
	return dag.
			Z5labs().
			Goapp(source)
}
@function
def example(source: dagger.Directory) -> dagger.Z5LabsGoApp:
	return (
		dag.z5labs()
		.goapp(source)
	)
@func()
example(source: Directory): Z5LabsGoApp {
	return dag
		.z5labs()
		.goApp(source)
}

goLib() 🔗

GoLib wires up the checks-only pipeline for a Go library. v1 has no publish equivalent for libraries.

Return Type
GoLib !
Arguments
NameTypeDefault ValueDescription
sourceDirectory !-No description provided
lintConfigFile -No description provided
Example
dagger -m github.com/z5labs/devex/daggerverse/z5labs@40748316f5487a0b9755b5c5f46e3d15403153fd call \
 go-lib --source DIR_PATH
func (m *MyModule) Example(source *dagger.Directory) *dagger.Z5LabsGoLib  {
	return dag.
			Z5labs().
			Golib(source)
}
@function
def example(source: dagger.Directory) -> dagger.Z5LabsGoLib:
	return (
		dag.z5labs()
		.golib(source)
	)
@func()
example(source: Directory): Z5LabsGoLib {
	return dag
		.z5labs()
		.goLib(source)
}

GoApp 🔗

GoApp is the application archetype. Construct via Z5labs.GoApp.

builder() 🔗

Builder returns the local-dev sibling that produces the same image CI would publish, single-arch (host platform).

Return Type
Builder !
Example
dagger -m github.com/z5labs/devex/daggerverse/z5labs@40748316f5487a0b9755b5c5f46e3d15403153fd call \
 go-app --source DIR_PATH \
 builder
func (m *MyModule) Example(source *dagger.Directory) *dagger.Z5LabsBuilder  {
	return dag.
			Z5labs().
			Goapp(source).
			Builder()
}
@function
def example(source: dagger.Directory) -> dagger.Z5LabsBuilder:
	return (
		dag.z5labs()
		.goapp(source)
		.builder()
	)
@func()
example(source: Directory): Z5LabsBuilder {
	return dag
		.z5labs()
		.goApp(source)
		.builder()
}

ci() 🔗

Ci runs the standardized GoApp pipeline: verify .git exists, run the shared check stages (fmt+vet+lint+test -race) once, build a scratch image per platform, then conditionally publish per the publishOn filter.

It returns the digest of what was published — the manifest list naming every platform variant, or the single image manifest when only one platform was built. Every matching ref publishes the same bytes under its own tag, so one digest describes them all. A run that publishes nothing — no ref matched, or no registry was configured — returns the empty string rather than an error.

Returning the digest rather than only an error is what lets a caller reference what was published: an attestation, a deployment manifest or a release note has to name an immutable artifact, and a tag is not one.

Publish is a side-effecting operation against an external registry, so the whole pipeline is uncached — re-runs (e.g. after a retry, or after a new ref appears within the same engine session) must actually push.

Return Type
String !
Example
dagger -m github.com/z5labs/devex/daggerverse/z5labs@40748316f5487a0b9755b5c5f46e3d15403153fd call \
 go-app --source DIR_PATH \
 ci
func (m *MyModule) Example(ctx context.Context, source *dagger.Directory) string  {
	return dag.
			Z5labs().
			Goapp(source).
			Ci(ctx)
}
@function
async def example(source: dagger.Directory) -> str:
	return await (
		dag.z5labs()
		.goapp(source)
		.ci()
	)
@func()
async example(source: Directory): Promise<string> {
	return dag
		.z5labs()
		.goApp(source)
		.ci()
}

GoLib 🔗

GoLib is the library archetype. Construct via Z5labs.GoLib.

ci() 🔗

Ci runs the standardized check stages (fmt, vet, lint, test -race) against the supplied library source.

Return Type
Void !
Example
dagger -m github.com/z5labs/devex/daggerverse/z5labs@40748316f5487a0b9755b5c5f46e3d15403153fd call \
 go-lib --source DIR_PATH \
 ci
func (m *MyModule) Example(ctx context.Context, source *dagger.Directory)   {
	return dag.
			Z5labs().
			Golib(source).
			Ci(ctx)
}
@function
async def example(source: dagger.Directory) -> None:
	return await (
		dag.z5labs()
		.golib(source)
		.ci()
	)
@func()
async example(source: Directory): Promise<void> {
	return dag
		.z5labs()
		.goLib(source)
		.ci()
}

Builder 🔗

Builder produces the same image GoApp.Ci would publish, single-arch (host platform). Used for local development to verify the artifact before pushing. Both of its functions route through the same per-platform build Ci uses, so the binary carries the same version and commit stamp and a local build is the same artifact.

binary() 🔗

Binary returns the host-platform compiled binary as a *dagger.File.

Return Type
File !
Example
dagger -m github.com/z5labs/devex/daggerverse/z5labs@40748316f5487a0b9755b5c5f46e3d15403153fd call \
 go-app --source DIR_PATH \
 builder \
 binary
func (m *MyModule) Example(source *dagger.Directory) *dagger.File  {
	return dag.
			Z5labs().
			Goapp(source).
			Builder().
			Binary()
}
@function
def example(source: dagger.Directory) -> dagger.File:
	return (
		dag.z5labs()
		.goapp(source)
		.builder()
		.binary()
	)
@func()
example(source: Directory): File {
	return dag
		.z5labs()
		.goApp(source)
		.builder()
		.binary()
}

container() 🔗

Container returns the host-platform scratch image containing the compiled binary at /app/ with that path as entrypoint.

Return Type
Container !
Example
dagger -m github.com/z5labs/devex/daggerverse/z5labs@40748316f5487a0b9755b5c5f46e3d15403153fd call \
 go-app --source DIR_PATH \
 builder \
 container
func (m *MyModule) Example(source *dagger.Directory) *dagger.Container  {
	return dag.
			Z5labs().
			Goapp(source).
			Builder().
			Container()
}
@function
def example(source: dagger.Directory) -> dagger.Container:
	return (
		dag.z5labs()
		.goapp(source)
		.builder()
		.container()
	)
@func()
example(source: Directory): Container {
	return dag
		.z5labs()
		.goApp(source)
		.builder()
		.container()
}