Refactor Dagger go_build() helper and standardize Alpine 3.23
All checks were successful
Build Container / detect (push) Successful in 3s
Build Container / build-dagger (miniflux) (push) Successful in 10m2s
Build Container / build-dagger (forgejo-runner) (push) Successful in 10m2s

Extend go_build() with buildmode and extra_env params, migrate miniflux
and forgejo-runner to use it, and bump all Alpine bases from 3.22 to 3.23.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erich Blume 2026-04-16 10:10:46 -07:00
commit 352b95c141
4 changed files with 33 additions and 60 deletions

View file

@ -5,11 +5,11 @@ Source cloned from forge mirror.
""" """
import dagger import dagger
from dagger import dag
from blumeops.containers import ( from blumeops.containers import (
alpine_runtime, alpine_runtime,
clone_from_forge, clone_from_forge,
go_build,
oci_labels, oci_labels,
) )
@ -20,29 +20,16 @@ async def build(src: dagger.Directory) -> dagger.Container:
source = clone_from_forge("forgejo-runner", f"v{VERSION}") source = clone_from_forge("forgejo-runner", f"v{VERSION}")
# Stage 1: Build Go binary (static, CGO enabled for SQLite) # Stage 1: Build Go binary (static, CGO enabled for SQLite)
backend = go_build(
source,
"/forgejo-runner",
tags="netgo osusergo",
ldflags=( ldflags=(
'-extldflags "-static" -s -w' '-extldflags "-static" -s -w'
f' -X "code.forgejo.org/forgejo/runner/v12/internal/pkg/ver.version=v{VERSION}"' f' -X "code.forgejo.org/forgejo/runner/v12/internal/pkg/ver.version=v{VERSION}"'
) ),
backend = ( cgo_enabled=True,
dag.container() extra_env={"CGO_CFLAGS": "-DSQLITE_MAX_VARIABLE_NUMBER=32766"},
.from_("golang:alpine3.22")
.with_exec(["apk", "add", "--no-cache", "build-base", "git"])
.with_directory("/app", source)
.with_workdir("/app")
.with_env_variable("CGO_ENABLED", "1")
.with_env_variable("CGO_CFLAGS", "-DSQLITE_MAX_VARIABLE_NUMBER=32766")
.with_exec(
[
"go",
"build",
"-tags=netgo osusergo",
f"-ldflags={ldflags}",
"-o",
"/forgejo-runner",
".",
]
)
) )
# Stage 2: Runtime # Stage 2: Runtime

View file

@ -5,11 +5,11 @@ Source cloned from forge mirror.
""" """
import dagger import dagger
from dagger import dag
from blumeops.containers import ( from blumeops.containers import (
alpine_runtime, alpine_runtime,
clone_from_forge, clone_from_forge,
go_build,
oci_labels, oci_labels,
) )
@ -20,25 +20,12 @@ async def build(src: dagger.Directory) -> dagger.Container:
source = clone_from_forge("miniflux", VERSION) source = clone_from_forge("miniflux", VERSION)
# Stage 1: Build Go backend (PIE mode, matching upstream Makefile) # Stage 1: Build Go backend (PIE mode, matching upstream Makefile)
ldflags = f"-s -w -X 'miniflux.app/v2/internal/version.Version={VERSION}'" backend = go_build(
backend = ( source,
dag.container()
.from_("golang:alpine3.22")
.with_exec(["apk", "add", "--no-cache", "build-base", "git"])
.with_directory("/app", source)
.with_workdir("/app")
.with_env_variable("CGO_ENABLED", "1")
.with_exec(
[
"go",
"build",
"-buildmode=pie",
f"-ldflags={ldflags}",
"-o",
"/miniflux", "/miniflux",
".", buildmode="pie",
] ldflags=f"-s -w -X 'miniflux.app/v2/internal/version.Version={VERSION}'",
) cgo_enabled=True,
) )
# Stage 2: Runtime (uses Alpine's built-in nobody:65534) # Stage 2: Runtime (uses Alpine's built-in nobody:65534)

View file

@ -0,0 +1 @@
Refactored Dagger container pipelines: extended `go_build()` helper with `buildmode` and `extra_env` params, migrated miniflux and forgejo-runner to use it, and standardized all Alpine bases from 3.22 to 3.23.

View file

@ -70,33 +70,31 @@ def go_build(
cmd_path: str = ".", cmd_path: str = ".",
tags: str = "netgo", tags: str = "netgo",
ldflags: str = "-w -s", ldflags: str = "-w -s",
buildmode: str | None = None,
cgo_enabled: bool = False, cgo_enabled: bool = False,
extra_apk: list[str] | None = None, extra_apk: list[str] | None = None,
extra_env: dict[str, str] | None = None,
) -> dagger.Container: ) -> dagger.Container:
"""Go build stage on golang:alpine3.22. """Go build stage on golang:alpine3.23.
Returns a container with the built binary at `output`. Returns a container with the built binary at `output`.
""" """
apk_packages = ["build-base", "git"] + (extra_apk or []) apk_packages = ["build-base", "git"] + (extra_apk or [])
return ( ctr = (
dag.container() dag.container()
.from_("golang:alpine3.22") .from_("golang:alpine3.23")
.with_exec(["apk", "add", "--no-cache", *apk_packages]) .with_exec(["apk", "add", "--no-cache", *apk_packages])
.with_directory("/app", source) .with_directory("/app", source)
.with_workdir("/app") .with_workdir("/app")
.with_env_variable("CGO_ENABLED", "1" if cgo_enabled else "0") .with_env_variable("CGO_ENABLED", "1" if cgo_enabled else "0")
.with_exec(
[
"go",
"build",
f"-tags={tags}",
f"-ldflags={ldflags}",
"-o",
output,
cmd_path,
]
)
) )
for key, val in (extra_env or {}).items():
ctr = ctr.with_env_variable(key, val)
build_cmd = ["go", "build"]
if buildmode:
build_cmd.append(f"-buildmode={buildmode}")
build_cmd += [f"-tags={tags}", f"-ldflags={ldflags}", "-o", output, cmd_path]
return ctr.with_exec(build_cmd)
def node_build( def node_build(
@ -133,7 +131,7 @@ def alpine_runtime(
username: str = "app", username: str = "app",
create_user: bool = True, create_user: bool = True,
) -> dagger.Container: ) -> dagger.Container:
"""Standard Alpine 3.22 runtime base. """Standard Alpine 3.23 runtime base.
When create_user is True (default), creates a non-root user with the given When create_user is True (default), creates a non-root user with the given
uid/gid/username. Set create_user=False to use an existing user (e.g. uid/gid/username. Set create_user=False to use an existing user (e.g.
@ -147,7 +145,7 @@ def alpine_runtime(
setup_cmds.append(f"addgroup -g {gid} {username}") setup_cmds.append(f"addgroup -g {gid} {username}")
setup_cmds.append(f"adduser -u {uid} -G {username} -D {username}") setup_cmds.append(f"adduser -u {uid} -G {username} -D {username}")
ctr = dag.container().from_("alpine:3.22") ctr = dag.container().from_("alpine:3.23")
if setup_cmds: if setup_cmds:
ctr = ctr.with_exec(["sh", "-c", " && ".join(setup_cmds)]) ctr = ctr.with_exec(["sh", "-c", " && ".join(setup_cmds)])
return ctr return ctr