feat(gotenberg): add Gotenberg HTML→PDF sidecar across compose and Helm#13
Merged
Conversation
Makes Gotenberg a first-class, optional service in both the local
docker-compose stack and the production Helm chart, so consuming apps can
render HTML→PDF without baking headless Chromium into the app image.
- compose: add gotenberg.stub (gotenberg/gotenberg:8, sail network,
/health check, stateless) and register `gotenberg` as an opt-in service;
depends_on is wired by the existing generic mechanism. replaceEnvVariables
appends GOTENBERG_URL=http://gotenberg:3000 for local dev.
- helm: add gotenberg.stub Deployment+Service gated on
.Values.gotenberg.enabled; wire GOTENBERG_URL=http://{name}-gotenberg:3000
into web/worker/scheduler via the shared sail.laravelEnv helper; add the
gotenberg block to values.stub.
- tests: helm render coverage (enabled/disabled + GOTENBERG_URL wiring) and
a compose-stub validity check.
The runtime image (runtimes/8.x) is intentionally untouched — no Chromium.
pozil/auto-assign-issue@v1 only understands issue context, so the pull_request: opened trigger crashed every PR with "Couldn't find issue info in current context". Drop the PR trigger (and its pull-requests: write permission) so the workflow only assigns new issues, and remove the invalid numOfAssignee input that emitted an "unexpected input" warning.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: db81e8d154
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A consumer override setting `gotenberg: null` (the same nullable-map
pattern the chart already guards for `app`) caused helm template to fail
with "nil pointer evaluating interface {}.enabled", breaking the entire
chart render. Bind `.Values.gotenberg | default dict` once and test that
map's flags, matching the existing app/typesense guarding. Add a
regression test mirroring test_defaults_secret_renders_when_app_values_is_null.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Makes Gotenberg a first-class, optional part of the sail-generated stack — local Docker Compose and production Helm/k8s — so consuming apps can render HTML→PDF without baking headless Chromium into the app image.
Docker Compose
stubs/gotenberg.stub—gotenberg/gotenberg:8, on thesailnetwork,/healthhealthcheck, stateless (no volume).gotenbergregistered as an opt-in service inInteractsWithDockerComposeServices::$services(parallel to redis/typesense/etc.). It's added viasail:add gotenbergorsail:install --with=…,gotenberg.depends_onon thelaravelservice is wired automatically by the existing generic mechanism, and it's correctly excluded from the volume-creation allowlist.replaceEnvVariables()appendsGOTENBERG_URL=http://gotenberg:3000to the local.env(docker-compose service name), consistent withREDIS_HOST=redis,MEILISEARCH_HOST=…, etc.Helm
stubs/helm/templates/gotenberg.stub— Deployment + Service, gated on.Values.gotenberg.enabled, internal-only (no PVC, no ingress). Uses the chart's realsail.name/sail.labelshelpers.GOTENBERG_URL=http://{name}-gotenberg:3000is injected into the web, worker, and scheduler pods through the sharedsail.laravelEnvhelper (same mechanism asDB_HOST/REDIS_HOST), so it overrides the app-shipped value in-cluster.gotenbergthreaded into the$maincontext dict on the web/worker deployment stubs.values.stubgains agotenbergblock (enabled: true, image, replicas, apiTimeout).Tests
HelmTemplateTest: renders Deployment+Service when enabled, omits when disabled,GOTENBERG_URLwired into all 3 tiers when enabled, absent when disabled.BuildCommandTest: validates the compose stub (image,sailnetwork,/healthcheck, stateless).Why
The ReyemTech Laravel app generates PDFs and was using
spatie/laravel-pdf(browsershot + bundled Chromium), which fails on the Alpine/arm64 runtime and would bloat the app image ~770 MB. The app now renders Blade→HTML and POSTs to${GOTENBERG_URL}/forms/chromium/convert/html. This change makes the required Gotenberg service exist in every environment without it being lost on the nextsail:build.Reviewer notes
runtimes/8.x(the entire point of the change).gotenberg.enabled: trueby default invalues.stub(per the brief) differs fromtypesense.enabled: false. Sincevalues.stubonly merges new keys into a consumer'svalues.yaml, redeployed apps gain a gotenberg pod. Flip tofalseif opt-in parity with typesense is preferred..envuses the compose service namegotenberg; Helm injects the in-cluster Service name{name}-gotenberg(short, same-namespace — matching how typesense is referenced in this chart).client_max_body_sizefootgun from the brief's appendix (kept out of this PR to stay focused).Verification
vendor/bin/phpunit→ 50 passing (3 Docker-dependent integration tests skipped), 5 new.vendor/bin/phpstan analyse src→ no errors.helm templaterenders valid Gotenberg Deployment + Service and wiresGOTENBERG_URLinto web/worker/scheduler.🤖 Generated with Claude Code