Skip to content

feat(gotenberg): add Gotenberg HTML→PDF sidecar across compose and Helm#13

Merged
mariomeyer merged 3 commits into
1.xfrom
feat/gotenberg-pdf-service
Jun 17, 2026
Merged

feat(gotenberg): add Gotenberg HTML→PDF sidecar across compose and Helm#13
mariomeyer merged 3 commits into
1.xfrom
feat/gotenberg-pdf-service

Conversation

@mariomeyer

Copy link
Copy Markdown
Member

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

  • New stubs/gotenberg.stubgotenberg/gotenberg:8, on the sail network, /health healthcheck, stateless (no volume).
  • gotenberg registered as an opt-in service in InteractsWithDockerComposeServices::$services (parallel to redis/typesense/etc.). It's added via sail:add gotenberg or sail:install --with=…,gotenberg. depends_on on the laravel service is wired automatically by the existing generic mechanism, and it's correctly excluded from the volume-creation allowlist.
  • replaceEnvVariables() appends GOTENBERG_URL=http://gotenberg:3000 to the local .env (docker-compose service name), consistent with REDIS_HOST=redis, MEILISEARCH_HOST=…, etc.

Helm

  • New stubs/helm/templates/gotenberg.stub — Deployment + Service, gated on .Values.gotenberg.enabled, internal-only (no PVC, no ingress). Uses the chart's real sail.name/sail.labels helpers.
  • GOTENBERG_URL=http://{name}-gotenberg:3000 is injected into the web, worker, and scheduler pods through the shared sail.laravelEnv helper (same mechanism as DB_HOST/REDIS_HOST), so it overrides the app-shipped value in-cluster. gotenberg threaded into the $main context dict on the web/worker deployment stubs.
  • values.stub gains a gotenberg block (enabled: true, image, replicas, apiTimeout).

Tests

  • HelmTemplateTest: renders Deployment+Service when enabled, omits when disabled, GOTENBERG_URL wired into all 3 tiers when enabled, absent when disabled.
  • BuildCommandTest: validates the compose stub (image, sail network, /health check, 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 next sail:build.

Reviewer notes

  • Runtime image untouched — no Chromium/puppeteer added to runtimes/8.x (the entire point of the change).
  • gotenberg.enabled: true by default in values.stub (per the brief) differs from typesense.enabled: false. Since values.stub only merges new keys into a consumer's values.yaml, redeployed apps gain a gotenberg pod. Flip to false if opt-in parity with typesense is preferred.
  • Local vs cluster URL are intentionally different: local .env uses the compose service name gotenberg; Helm injects the in-cluster Service name {name}-gotenberg (short, same-namespace — matching how typesense is referenced in this chart).
  • A separate follow-up covers the optional nginx client_max_body_size footgun 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 template renders valid Gotenberg Deployment + Service and wires GOTENBERG_URL into web/worker/scheduler.

🤖 Generated with Claude Code

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread stubs/helm/templates/gotenberg.stub Outdated
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.
@mariomeyer mariomeyer merged commit 33e1455 into 1.x Jun 17, 2026
3 checks passed
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