fix: pin CNPG postgres to 18.4 (PG 18.6 segfaults the 0.113.0 DocumentDB extension; unblock E2E) + govulncheck - #445
Conversation
The DocumentDB CRD defaulted spec.image.postgres to the floating tag ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie. On 2026-08-13 that tag rolled from PostgreSQL 18.4 (18.4-202608030910) to 18.6 (18.6-202608131513). The 18.6 build broke the gateway's SCRAM-SHA-256 handshake, which the gateway surfaces to Mongo clients as a generic (InternalError). This turned the E2E data suite deterministically red starting with the first run after the tag rolled, while every baked DocumentDB/gateway/operator artifact stayed byte-identical. Pin the default to the immutable, digest-addressed last-known-good build (18.4-202608030910, the image the last green run on 2026-08-11 used) so CI is reproducible and no longer at the mercy of upstream tag rolls. Co-authored-by: Copilot <[email protected]> Copilot-Session: d53b8fec-0585-4888-89da-d9a6847597a5 Signed-off-by: Wenting Wu <[email protected]>
|
🤖 Auto-triaged by documentdb-triage-tool. Applied: Reasoningcomponent from path globs (api, manifests); effort from diff stats (24+3 LOC, 3 files); LLM: Pins a floating upstream image tag to a known-good digest to unblock a deterministically failing E2E pipeline on main; touches API types, manifests, and CRDs but the change itself is minimal. If a label is wrong, remove it manually and ping |
govulncheck flagged 4 called standard-library vulnerabilities (GO-2026-6218, GO-2026-6090, GO-2026-5972, GO-2026-5026), all fixed in go1.26.6. Bump the go directive in every scanned module and the pinned GO_VERSION in the unit-test workflows from 1.26.5 to 1.26.6 so CI builds and scans against the patched standard library. Verified locally: govulncheck reports 'No vulnerabilities found' for both documentdb-kubectl-plugin and operator/src under go1.26.6. Co-authored-by: Copilot <[email protected]> Copilot-Session: d53b8fec-0585-4888-89da-d9a6847597a5 Signed-off-by: Wenting Wu <[email protected]>
The Lint Long-Haul Workflows job runs actionlint (with embedded
shellcheck) over any workflow file touched by a PR. Bumping GO_VERSION in
these two files surfaced pre-existing SC2046/SC2086 findings that
exceeded reviewdog's annotation limit and failed the lint gate.
Fix the underlying issues so the files are lint-clean:
- quote $GITHUB_STEP_SUMMARY redirections (SC2086)
- collect 'go list' output via mapfile and expand "${pkgs[@]}" instead
of unquoted command substitution (SC2046)
- quote $(go env GOPATH) before the /bin path (SC2046)
Behavior is unchanged; verified with actionlint (exit 0) locally.
Co-authored-by: Copilot <[email protected]>
Copilot-Session: d53b8fec-0585-4888-89da-d9a6847597a5
Signed-off-by: Wenting Wu <[email protected]>
The kubebuilder default comment (and the CRDs generated from it) still attributed the E2E breakage to a broken gateway SCRAM-SHA-256 handshake. That was wrong: the real cause is the shipped DocumentDB 0.113.0 extension segfaulting (signal 11 in documentdb_api.insert) on PostgreSQL 18.6, an extension-vs-PG-18.6 ABI incompatibility reproduced on both CNPG and vanilla-Debian 18.6. Rewrite the comment accordingly and regenerate CRDs. Co-authored-by: Copilot <[email protected]> Copilot-Session: d53b8fec-0585-4888-89da-d9a6847597a5 Signed-off-by: Wenting Wu <[email protected]>
Condense the field comment to a concise note; same root cause, less prose. Co-authored-by: Copilot <[email protected]> Copilot-Session: d53b8fec-0585-4888-89da-d9a6847597a5 Signed-off-by: Wenting Wu <[email protected]>
The 18.6 crash is a product bug: PG 18.6's executor-pruning rework added an unguarded list_nth on fdwPrivLists in ExecInitModifyTable, and the extension's hand-built local-shard insert plan left that list NIL, so the second insert segfaults. Fixed upstream in documentdb/documentdb 3555c7d. Drop the inaccurate ABI framing from the field comment and regenerate CRDs. Co-authored-by: Copilot <[email protected]> Copilot-Session: d53b8fec-0585-4888-89da-d9a6847597a5 Signed-off-by: Wenting Wu <[email protected]>
There was a problem hiding this comment.
Pull request overview
Pins the DocumentDB CRD default PostgreSQL image to a last-known-good CNPG Postgres 18.4 digest to make CI (and new clusters) reproducible and to avoid the PG 18.6 regression that triggers segfaults in the currently released DocumentDB extension; additionally bumps Go patch version to address govulncheck failures and updates the unit-test workflows accordingly.
Changes:
- Pin
spec.image.postgresdefault from floating18-minimal-trixieto an immutable18.4-...@sha256:...digest in the API marker and regenerated CRDs. - Bump
godirectives across modules from1.26.5→1.26.6. - Update unit-test / unit-coverage GitHub Actions workflows to use Go
1.26.6and improve shell robustness (avoid SC2046/SC2086 via arrays + quoting).
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
operator/src/api/preview/documentdb_types.go |
Updates the kubebuilder default marker and documents the rationale for digest pinning. |
operator/src/config/crd/bases/documentdb.io_dbs.yaml |
Regenerated CRD schema reflecting the pinned Postgres image default and expanded description. |
operator/documentdb-helm-chart/crds/documentdb.io_dbs.yaml |
Regenerated Helm-packaged CRD mirroring the pinned default for chart installs. |
operator/src/go.mod |
Bumps operator module Go directive to 1.26.6 for vulnfixes. |
documentdb-kubectl-plugin/go.mod |
Bumps kubectl plugin module Go directive to 1.26.6. |
operator/cnpg-plugins/sidecar-injector/go.mod |
Bumps sidecar-injector module Go directive to 1.26.6. |
test/e2e/go.mod |
Bumps E2E test module Go directive to 1.26.6. |
test/longhaul/go.mod |
Bumps longhaul test module Go directive to 1.26.6. |
test/shared/go.mod |
Bumps shared test utilities module Go directive to 1.26.6. |
.github/workflows/test-unit.yml |
Updates CI Go version and makes package list handling safer via mapfile + arrays. |
.github/workflows/test-unit-coverage.yml |
Updates CI Go version and improves shell safety/quoting for coverage and diff coverage steps. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
The immutable digest is appropriate for reproducible CI, but I do not think it should be the CRD default for user deployments. CNPG rebuilds its images with Debian/PGDG security updates; pinning this digest permanently freezes the default on the August 3 image and will miss future security fixes unless this PR is manually refreshed. Could the default use the version-constrained rolling tag instead? That keeps PostgreSQL at 18.4 to avoid the known 18.6 regression while allowing CNPG to publish refreshed 18.4 images with security updates. The immutable digest can remain in a dedicated E2E/reproducibility fixture if needed. |
|
new version 117 should fix the issue, see this commit: |
| // "18-minimal-trixie" tag, which rolled 18.4 -> 18.6 on 2026-08-13 and | ||
| // crashed the DocumentDB 0.113.0 extension on insert. Holds PG at 18.4 | ||
| // until a DocumentDB release carrying the PG 18.6 fix ships; revert then. | ||
| // +kubebuilder:default="ghcr.io/cloudnative-pg/postgresql:18.4-202608030910-minimal-trixie@sha256:229ab83c0639d294042ca747745fb214db690ade64d5d59131a135825b994391" |
There was a problem hiding this comment.
The digest pin makes this the production default indefinitely, so CNPG Debian/PGDG security rebuilds will not reach new deployments unless we manually update this CRD. Could we use the version-constrained rolling tag ghcr.io/cloudnative-pg/postgresql:18.4-minimal-trixie here instead? It keeps PG 18.4 while allowing refreshed 18.4 images; reserve the immutable digest for the E2E fixture if reproducibility is required.
Per review feedback (xgerman): the CRD default ships to every user deployment, so pinning an immutable digest freezes new deployments on the Aug-3 image and misses future CNPG/PGDG security rebuilds. Use the version-constrained rolling tag 18.4-minimal-trixie instead: it stays on PG 18.4 (avoiding the 18.6 insert segfault) while still receiving refreshed 18.4 images. Revert to floating 18-minimal-trixie once a DocumentDB release carrying the PG 18.6 fix ships. Co-authored-by: Copilot <[email protected]> Copilot-Session: d53b8fec-0585-4888-89da-d9a6847597a5 Signed-off-by: Wenting Wu <[email protected]>
|
Good call — thanks. Switched the CRD default to the version-constrained rolling tag: This keeps PostgreSQL on the 18.4 minor (avoiding the 18.6 insert segfault) while still letting CNPG publish refreshed 18.4 images with Debian/PGDG security updates, so the user-facing default isn't frozen on a single dated image. I kept it simple and didn't add a separate immutable-digest E2E fixture for now — the E2E suite runs against the CRD default, and 18.4 is the safe minor. We can add a pinned-digest fixture later if we want byte-for-byte reproducible CI. This is still a stopgap: once a DocumentDB release carrying the PG 18.6 fix ( |
Problem
The TEST - E2E workflow started failing deterministically on 2026-08-13 and stayed red on
mainafterwards. TheE2E datajob failed specs ($inc,deleteMany,$or) with a generic Mongo(InternalError), while every baked DocumentDB / gateway / operator artifact was byte-identical across the last green (Aug 11) and first red (Aug 13) runs.Root cause
The DocumentDB CRD defaults
spec.image.postgresto the floating tagghcr.io/cloudnative-pg/postgresql:18-minimal-trixie. Each E2E job spins up a fresh kind cluster and pulls whatever that tag currently points to. CloudNative-PG rolled the tag on 2026-08-13:18.4-202608030910-minimal-trixie18.4-202608130737-minimal-trixie18.6-202608131513-minimal-trixieThe 18.4 → 18.6 jump is the regression. The PostgreSQL backend segfaults inside the DocumentDB extension on 18.6. The postgres logs show the crashing query is a DocumentDB
insertand, becauserestart_after_crashis off, the crash takes the whole instance down:That crash is the real, common failure across all red runs. Clients only see the downstream symptom — usually a generic Mongo
(InternalError)when their backend dies mid-request, and in one run aSCRAM-SHA-256"sasl conversation error" from a connection whose backend was gone. The earlier SCRAM hypothesis was wrong: SCRAM was an occasional symptom, not the cause.Isolating the culprit (repro matrix)
The
0.113.0extension.debwas held constant while the PostgreSQL image was swapped:0.113.0deb0.113.0deb0.113.0debThe only variable that flips pass → fail is the PostgreSQL minor (18.4 → 18.6); image vendor and userland drop out. This rules out a bad CNPG image build and the operator's own extension-image packaging (
Dockerfile_extension/ ImageVolume lib-bundling) — the raw deb crashes on 18.6 regardless of vendor.The fault is a product bug in the extension exposed by a PG 18.6 planner change (fixed upstream in
3555c7d): PG 18.6's executor-pruning rework added an unguardedlist_nthonfdwPrivListsinExecInitModifyTable(18.4 only read it behind anri_FdwRoutine != NULLguard). The extension's hand-built local-shard insert plan (CreateLocalShardInsertPlan) left that listNIL, so the second insert into a collection dereferences NULL and segfaults. It's a source logic bug — not an ABI/recompile issue.Fix
Pin the CRD default to the version-constrained 18.4 tag:
Staying on the 18.4 minor avoids the 18.6 insert segfault, while the rolling tag still receives CNPG's Debian/PGDG security rebuilds — so the user-facing default isn't frozen on a single dated image (see review discussion). This is a stopgap, not the destination — it holds PostgreSQL at 18.4 until a DocumentDB release carrying the 18.6 fix ships, at which point the default reverts to the floating
18-minimal-trixietag.Changes
operator/src/api/preview/documentdb_types.go— updated+kubebuilder:defaultmarker (source of truth) + explanatory comment.make manifests generate):operator/src/config/crd/bases/documentdb.io_dbs.yamlandoperator/documentdb-helm-chart/crds/documentdb.io_dbs.yaml.Validation
go test ./internal/cnpg/...passes.Follow-ups (out of scope)
documentdb/documentdbcuts a release (v0.115-0+) containing the fix now onmain: bumpdocumentDbVersion, verify the new deb on the latest PG 18.6 (canary/local repro across the 18.x range), then revert this pin back to floating18-minimal-trixie. Tracked separately so the bridge doesn't become permanent.18-minimal-trixie(the postgres pod, the extension-image build base, and the deb's compile-time minor); they drifted apart, which is how this reached users. Long term, bump them as a matched set (or validate the postgres major at admission via the existing webhook).18-minimal-trixieso the next upstream minor roll is caught before it reaches production, while the 18.4 tag protects the default path.fail-faston the E2E matrix so one job failure doesn't cancel the whole workflow.Also in this PR: govulncheck fix
The
govulncheckworkflow was failing on 4 called standard-library vulnerabilities, all fixed in go1.26.6:GO-2026-6218— quadratic complexity innet/urlresolvePathGO-2026-6090— unbounded post-handshake messages incrypto/tlsGO-2026-5972— recursion depth inencoding/asn1GO-2026-5026— punycode label handling viagolang.org/x/net/idnaBumped the
godirective from1.26.5→1.26.6in every scanned module (operator/src,documentdb-kubectl-plugin,operator/cnpg-plugins/sidecar-injector,test/e2e,test/longhaul,test/shared) and the pinnedGO_VERSIONintest-unit.yml/test-unit-coverage.yml. Also made those two workflows shellcheck-clean (SC2046/SC2086) since the actionlint gate lints any workflow a PR touches. Verified locally:govulncheckreports No vulnerabilities found fordocumentdb-kubectl-pluginandoperator/srcunder go1.26.6.