From 352b95c14114cffd45d7647243bb9fce89456d43 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Thu, 16 Apr 2026 10:10:46 -0700 Subject: [PATCH] Refactor Dagger go_build() helper and standardize Alpine 3.23 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) --- containers/forgejo-runner/container.py | 35 ++++++------------- containers/miniflux/container.py | 27 ++++---------- .../+dagger-go-build-refactor.infra.md | 1 + src/blumeops/containers.py | 30 ++++++++-------- 4 files changed, 33 insertions(+), 60 deletions(-) create mode 100644 docs/changelog.d/+dagger-go-build-refactor.infra.md diff --git a/containers/forgejo-runner/container.py b/containers/forgejo-runner/container.py index 16f6986..ffaca88 100644 --- a/containers/forgejo-runner/container.py +++ b/containers/forgejo-runner/container.py @@ -5,11 +5,11 @@ Source cloned from forge mirror. """ import dagger -from dagger import dag from blumeops.containers import ( alpine_runtime, clone_from_forge, + go_build, oci_labels, ) @@ -20,29 +20,16 @@ async def build(src: dagger.Directory) -> dagger.Container: source = clone_from_forge("forgejo-runner", f"v{VERSION}") # Stage 1: Build Go binary (static, CGO enabled for SQLite) - ldflags = ( - '-extldflags "-static" -s -w' - f' -X "code.forgejo.org/forgejo/runner/v12/internal/pkg/ver.version=v{VERSION}"' - ) - backend = ( - 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_env_variable("CGO_CFLAGS", "-DSQLITE_MAX_VARIABLE_NUMBER=32766") - .with_exec( - [ - "go", - "build", - "-tags=netgo osusergo", - f"-ldflags={ldflags}", - "-o", - "/forgejo-runner", - ".", - ] - ) + backend = go_build( + source, + "/forgejo-runner", + tags="netgo osusergo", + ldflags=( + '-extldflags "-static" -s -w' + f' -X "code.forgejo.org/forgejo/runner/v12/internal/pkg/ver.version=v{VERSION}"' + ), + cgo_enabled=True, + extra_env={"CGO_CFLAGS": "-DSQLITE_MAX_VARIABLE_NUMBER=32766"}, ) # Stage 2: Runtime diff --git a/containers/miniflux/container.py b/containers/miniflux/container.py index ef2050a..e25485c 100644 --- a/containers/miniflux/container.py +++ b/containers/miniflux/container.py @@ -5,11 +5,11 @@ Source cloned from forge mirror. """ import dagger -from dagger import dag from blumeops.containers import ( alpine_runtime, clone_from_forge, + go_build, oci_labels, ) @@ -20,25 +20,12 @@ async def build(src: dagger.Directory) -> dagger.Container: source = clone_from_forge("miniflux", VERSION) # Stage 1: Build Go backend (PIE mode, matching upstream Makefile) - ldflags = f"-s -w -X 'miniflux.app/v2/internal/version.Version={VERSION}'" - backend = ( - 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", - ".", - ] - ) + backend = go_build( + source, + "/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) diff --git a/docs/changelog.d/+dagger-go-build-refactor.infra.md b/docs/changelog.d/+dagger-go-build-refactor.infra.md new file mode 100644 index 0000000..af09d7f --- /dev/null +++ b/docs/changelog.d/+dagger-go-build-refactor.infra.md @@ -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. diff --git a/src/blumeops/containers.py b/src/blumeops/containers.py index 4805c5c..d63c127 100644 --- a/src/blumeops/containers.py +++ b/src/blumeops/containers.py @@ -70,33 +70,31 @@ def go_build( cmd_path: str = ".", tags: str = "netgo", ldflags: str = "-w -s", + buildmode: str | None = None, cgo_enabled: bool = False, extra_apk: list[str] | None = None, + extra_env: dict[str, str] | None = None, ) -> 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`. """ apk_packages = ["build-base", "git"] + (extra_apk or []) - return ( + ctr = ( dag.container() - .from_("golang:alpine3.22") + .from_("golang:alpine3.23") .with_exec(["apk", "add", "--no-cache", *apk_packages]) .with_directory("/app", source) .with_workdir("/app") .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( @@ -133,7 +131,7 @@ def alpine_runtime( username: str = "app", create_user: bool = True, ) -> 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 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"adduser -u {uid} -G {username} -D {username}") - ctr = dag.container().from_("alpine:3.22") + ctr = dag.container().from_("alpine:3.23") if setup_cmds: ctr = ctr.with_exec(["sh", "-c", " && ".join(setup_cmds)]) return ctr