Skip to content

feat(cmd/duckgres-controlplane): add a CP-only binary that does not link libduckdb#498

Merged
fuziontech merged 1 commit intomainfrom
feature/cmd-controlplane-binary
May 1, 2026
Merged

feat(cmd/duckgres-controlplane): add a CP-only binary that does not link libduckdb#498
fuziontech merged 1 commit intomainfrom
feature/cmd-controlplane-binary

Conversation

@fuziontech
Copy link
Copy Markdown
Member

Summary

After the long sequence of subpackage extractions (PRs #477-#497), the controlplane import graph is fully free of github.com/duckdb/duckdb-go:

go list -deps ./controlplane                                | grep duckdb-go   # empty
go list -tags kubernetes -deps ./controlplane               | grep duckdb-go   # empty
go list -deps ./cmd/duckgres-controlplane                   | grep duckdb-go   # empty
go list -tags kubernetes -deps ./cmd/duckgres-controlplane  | grep duckdb-go   # empty

This PR adds the corresponding entry-point binary at cmd/duckgres-controlplane. The binary builds and links without libduckdb, but the actual config-loading + RunControlPlane wiring is still a stub that errors out at runtime — duckgres' YAML / CLI / env config resolution lives in the package main file at the repo root alongside the all-in-one binary, and lifting that into a shared config-resolution package is its own focused PR.

What this PR locks in

The point of this PR is the import-graph win: a CP-only build is now possible. Future PRs will:

  • Move resolveEffectiveConfig + the YAML/env/CLI plumbing out of main.go (repo root) into a shared package both binaries can import (still duckdb-free, since it's pure config wrangling).
  • Wire that into cmd/duckgres-controlplane/main.go and remove the stub error.
  • Add a CI step that runs the deps check above and fails the build if duckdb-go ever creeps back in.
  • Introduce cmd/duckgres-worker for the duckdb-service path so the matrix-build CI in the binary-split plan can target it.

Test plan

  • go build ./cmd/duckgres-controlplane/... clean
  • go build -tags kubernetes ./cmd/duckgres-controlplane/... clean
  • go list -deps ./cmd/duckgres-controlplane | grep duckdb-go returns empty
  • same with -tags kubernetes
  • The all-in-one duckgres binary at the repo root continues to build and run unchanged (it imports duckdbservice, which still pulls duckdb-go — that's expected for the worker / standalone modes)

🤖 Generated with Claude Code

…ink libduckdb

After the long sequence of subpackage extractions (PRs #477-#497) the
controlplane import graph is fully free of github.com/duckdb/duckdb-go:

  go list -deps ./controlplane                       | grep duckdb-go   # empty
  go list -tags kubernetes -deps ./controlplane      | grep duckdb-go   # empty
  go list -deps ./cmd/duckgres-controlplane          | grep duckdb-go   # empty
  go list -tags kubernetes -deps ./cmd/duckgres-controlplane | grep duckdb-go   # empty

This PR adds the corresponding entry-point binary at
cmd/duckgres-controlplane. The binary builds and links without
libduckdb, but the actual config-loading + RunControlPlane wiring is
still a stub that errors out at runtime — duckgres' YAML / CLI / env
config resolution lives in the package main file at the repo root
alongside the all-in-one binary, and lifting that into a shared
config-resolution package is its own focused PR.

The point of this PR is to lock in the import-graph win: a CP-only
build is now possible. Future PRs will:

  - Move resolveEffectiveConfig + the YAML/env/CLI plumbing out of
    main.go (repo root) into a shared package both binaries can
    import (still duckdb-free, since it's pure config wrangling).
  - Wire that into cmd/duckgres-controlplane/main.go and remove the
    stub error.
  - Add a CI step that runs the deps check above and fails the build
    if duckdb-go ever creeps back in.
  - Introduce cmd/duckgres-worker for the duckdb-service path so the
    matrix-build CI in the binary-split plan can target it.

Verified:
  - go build ./cmd/duckgres-controlplane/... clean
  - go build -tags kubernetes ./cmd/duckgres-controlplane/... clean
  - go list -deps ./cmd/duckgres-controlplane | grep duckdb-go is empty
  - same with -tags kubernetes
  - The all-in-one duckgres binary at the repo root continues to build
    and run unchanged (it imports duckdbservice, which still pulls
    duckdb-go — that's expected for the worker / standalone modes).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@fuziontech fuziontech enabled auto-merge (squash) May 1, 2026 18:08
@fuziontech fuziontech merged commit 4d52ae0 into main May 1, 2026
20 of 21 checks passed
@fuziontech fuziontech deleted the feature/cmd-controlplane-binary branch May 1, 2026 18:11
fuziontech added a commit that referenced this pull request May 1, 2026
Adds a controlplane-no-libduckdb job that builds cmd/duckgres-controlplane
(both default tags and -tags kubernetes) and then runs

  go list -deps ./cmd/duckgres-controlplane | grep duckdb-go
  go list -deps ./controlplane              | grep duckdb-go

If anything matches, the job fails the build.

This locks in the binary-split achievement from PRs #477-#498. Without
this guard, someone could land a server/* extraction that grows a new
duckdb-go transitive import and silently re-link libduckdb into the CP
build — which would defeat the matrix-build per-DuckDB-version goal.

The error message points at the right diagnostic command and suggests
the right fix (subpackage extraction / registration hook / interface
boundary) rather than encouraging anyone to suppress the check.

Verified locally:
  - go list -deps ./cmd/duckgres-controlplane | grep duckdb-go is empty
  - go list -deps ./controlplane              | grep duckdb-go is empty
  - same with -tags kubernetes

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fuziontech added a commit that referenced this pull request May 1, 2026
…ibduckdb (#500)

Counterpart to cmd/duckgres-controlplane (PR #498). This binary:

  - Links libduckdb (verified: go list -deps shows duckdb-go-bindings,
    duckdb-go/v2 in the import graph).
  - Imports duckdbservice but not controlplane — no PG wire surface, no
    config-store / k8s pool wiring. It's the runtime that the control
    plane spawns into worker pods over Unix sockets / TCP.
  - Is the target of the planned per-DuckDB-version matrix build in CI.
    A worker pod ships exactly one DuckDB version, pinned via go.mod +
    the Dockerfile DUCKDB_EXTENSION_VERSION build arg.

Like cmd/duckgres-controlplane, this is a stub that errors out at
runtime — duckgres' YAML / CLI / env config resolution still lives in
the package main file at the repo root alongside the all-in-one binary.
The follow-up PR lifts that into a shared package both new binaries
can import. The point of this PR is locking in the binary's existence
and the import-graph contract.

Together with PR #498 (CP-only, no libduckdb) and PR #499 (CI guard),
the binary split is now structurally complete:

  cmd/duckgres-controlplane   no libduckdb (CP-only, all DuckDB versions
                              run on remote workers)
  cmd/duckgres-worker         links libduckdb (worker-only, pinned to
                              one DuckDB version per build)
  duckgres                    all-in-one (links libduckdb, all modes)

Verified:
  - go build ./cmd/duckgres-worker/... clean
  - go list -deps ./cmd/duckgres-worker | grep duckdb-go shows the
    expected DuckDB driver imports
  - go list -deps ./cmd/duckgres-controlplane | grep duckdb-go is still
    empty (the CP-only contract held)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fuziontech added a commit that referenced this pull request May 1, 2026
* feat: add Dockerfile.controlplane for the duckdb-free CP image

Builds cmd/duckgres-controlplane (PR #498). The image is the control-
plane Pod's runtime; all SQL execution is routed to remote
duckgres-worker images (Dockerfile.worker), so this image:

  - Does NOT link libduckdb (the controlplane-no-libduckdb CI guard
    from PR #499 enforces it)
  - Does NOT bundle the DuckDB extension downloads — without a DuckDB
    driver they'd be dead weight
  - Is meaningfully smaller than the all-in-one image

CGO is still enabled because the transpiler uses pg_query_go which
links libpg_query. That's a pure Postgres parser, nothing to do with
DuckDB.

Together with Dockerfile.worker (per-DuckDB-version, PR #501) and the
existing all-in-one Dockerfile (unchanged), the image set now mirrors
the binary set:

  duckgres                    (existing) — all-in-one, links libduckdb
  duckgres-worker             (new)      — worker-only, per-DuckDB-version
  duckgres-controlplane       (this PR)  — CP-only, no libduckdb

A CD workflow that publishes the controlplane image (single build per
sha, no DuckDB matrix needed since this binary is version-agnostic) is
the next PR.

Verified locally:
  - go build -o /tmp/duckgres-controlplane ./cmd/duckgres-controlplane
    builds clean (~40MB binary)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ci: add CD pipeline for cmd/duckgres-controlplane image (#504)

Adds .github/workflows/container-image-controlplane-cd.yml — publishes
duckgres-controlplane:<sha> + duckgres-controlplane:latest as a multi-
arch manifest (arm64 + amd64) on every push to main.

Single build per sha — the CP is version-agnostic by design (one
image fits all worker fleets), so no DuckDB-version matrix here.
Contrast with container-image-worker-cd.yml (PR #502) which produces
one duckgres-worker image per (DuckDB version × arch).

Together with the existing all-in-one CD (container-image-cd.yml,
unchanged) and the worker matrix CD, the image pipeline now mirrors
the binary set:

  duckgres                container-image-cd.yml             (existing)
  duckgres-worker         container-image-worker-cd.yml      (PR #502)
  duckgres-controlplane   container-image-controlplane-cd.yml (this PR)

Stacked on PR #503 which adds Dockerfile.controlplane.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant