fix(ci): pass NODE_OPTIONS=--use-system-ca to clear grpc-tools tls install #199

Merged
julien merged 1 commits from fix/ci-grpc-tools-node-system-ca into main 2026-05-20 10:23:39 +02:00
Owner

Summary

The CI runner fails pnpm install --frozen-lockfile since the AI-relay chantier added grpc-tools to the dep tree. The package's postinstall downloads a precompiled protoc archive from node-precompiled-binaries.grpc.io, and Node 24's bundled CA set cannot verify the TLS chain on the runner network path.

The fix follows the Node team's own remediation, surfaced verbatim in the error message:

unable to verify the first certificate; if the root CA is installed locally, try running Node.js with --use-system-ca

Setting NODE_OPTIONS=--use-system-ca at the workflow env: block makes Node consult the OS CA store in addition to its bundled set. The runner image (catthehacker/ubuntu:act-22.04 per ADR-0015) carries the standard Ubuntu ca-certificates bundle, which validates the chain.

What lands

.gitea/workflows/ci.yml:

env:
  NODE_OPTIONS: --use-system-ca

.gitea/workflows/docs-site.yml: same one-line block.

Both placed at workflow scope so every Node process (pnpm itself + every postinstall it spawns) inherits the option without per-step duplication.

No package.json change. No code change. No runner-image change.

Notes for the reviewer

  • Why not skip the grpc-tools postinstall in CI instead. The protoc binary downloaded here is never invoked in CI — the generated TypeScript stubs in apps/portal-bff/src/grpc/gen/ are committed (per ADR-0024 §"Sub-decision 3 — vendored protos"), so CI only needs to type-check them. Removing grpc-tools from pnpm.onlyBuiltDependencies would also clear the failure and is arguably more minimal in CI. The trade-off: developers who update protos would have to opt back into the postinstall (pnpm approve-builds grpc-tools && pnpm rebuild grpc-tools) before running pnpm grpc:codegen. --use-system-ca keeps the developer workflow identical and fixes the underlying TLS-chain issue for any future native dep that hits the same wall (a real risk as the dep tree grows). The cost is a single workflow env var.
  • Why workflow-scope env: rather than per-step env:. Five separate pnpm install steps run across ci.yml; setting it five times would invite drift. The env: block at workflow scope applies to every step in every job — clean, single source of truth.
  • Node 24 compatibility. --use-system-ca is documented since Node 22; Node 24 (the workspace LTS per .nvmrc) carries it. No .nvmrc change required.
  • Local-dev impact. None. Local developers' Node already validates the chain (the issue is specific to the runner's network path); the env var is a no-op locally.
  • Forward compatibility. If a future native dep fetches binaries from a different CDN with a similar chain issue, this fix covers it without further changes.

Test plan

This PR cannot be locally validated in a way that reproduces the failure — the CI runner's network path is the only environment where node-precompiled-binaries.grpc.io cannot be reached with Node's bundled CA. The validation is the next CI run.

  • CI green on this PR's first run — pnpm install --frozen-lockfile completes; pnpm ci:check runs to completion.
  • If CI still fails: the runner's Ubuntu CA bundle does not contain the missing intermediate either. Fallback path: drop grpc-tools from pnpm.onlyBuiltDependencies so the postinstall is skipped entirely in CI (and document the dev-side pnpm approve-builds step). Trivial follow-up if needed.

What's next

If --use-system-ca fixes the CI install and no other Node TLS issues surface, no further action is required. The env var stays as a forward-looking guard.

## Summary The CI runner fails `pnpm install --frozen-lockfile` since the AI-relay chantier added `grpc-tools` to the dep tree. The package's postinstall downloads a precompiled `protoc` archive from `node-precompiled-binaries.grpc.io`, and Node 24's bundled CA set cannot verify the TLS chain on the runner network path. The fix follows the Node team's own remediation, surfaced verbatim in the error message: > unable to verify the first certificate; if the root CA is installed locally, try running Node.js with `--use-system-ca` Setting `NODE_OPTIONS=--use-system-ca` at the workflow `env:` block makes Node consult the OS CA store in addition to its bundled set. The runner image (`catthehacker/ubuntu:act-22.04` per [ADR-0015](docs/decisions/0015-cicd-gitea-actions.md)) carries the standard Ubuntu `ca-certificates` bundle, which validates the chain. ## What lands `.gitea/workflows/ci.yml`: ```yaml env: NODE_OPTIONS: --use-system-ca ``` `.gitea/workflows/docs-site.yml`: same one-line block. Both placed at workflow scope so every Node process (pnpm itself + every postinstall it spawns) inherits the option without per-step duplication. No package.json change. No code change. No runner-image change. ## Notes for the reviewer - **Why not skip the grpc-tools postinstall in CI instead.** The protoc binary downloaded here is never invoked in CI — the generated TypeScript stubs in `apps/portal-bff/src/grpc/gen/` are committed (per ADR-0024 §"Sub-decision 3 — vendored protos"), so CI only needs to type-check them. Removing `grpc-tools` from `pnpm.onlyBuiltDependencies` would also clear the failure and is arguably more minimal in CI. The trade-off: developers who update protos would have to opt back into the postinstall (`pnpm approve-builds grpc-tools && pnpm rebuild grpc-tools`) before running `pnpm grpc:codegen`. `--use-system-ca` keeps the developer workflow identical and fixes the underlying TLS-chain issue for any future native dep that hits the same wall (a real risk as the dep tree grows). The cost is a single workflow env var. - **Why workflow-scope `env:` rather than per-step `env:`.** Five separate `pnpm install` steps run across `ci.yml`; setting it five times would invite drift. The `env:` block at workflow scope applies to every step in every job — clean, single source of truth. - **Node 24 compatibility.** `--use-system-ca` is documented since Node 22; Node 24 (the workspace LTS per `.nvmrc`) carries it. No `.nvmrc` change required. - **Local-dev impact.** None. Local developers' Node already validates the chain (the issue is specific to the runner's network path); the env var is a no-op locally. - **Forward compatibility.** If a future native dep fetches binaries from a different CDN with a similar chain issue, this fix covers it without further changes. ## Test plan This PR cannot be locally validated in a way that reproduces the failure — the CI runner's network path is the only environment where `node-precompiled-binaries.grpc.io` cannot be reached with Node's bundled CA. The validation is the next CI run. - [ ] **CI green** on this PR's first run — `pnpm install --frozen-lockfile` completes; `pnpm ci:check` runs to completion. - [ ] If CI still fails: the runner's Ubuntu CA bundle does not contain the missing intermediate either. Fallback path: drop `grpc-tools` from `pnpm.onlyBuiltDependencies` so the postinstall is skipped entirely in CI (and document the dev-side `pnpm approve-builds` step). Trivial follow-up if needed. ## What's next If `--use-system-ca` fixes the CI install and no other Node TLS issues surface, no further action is required. The env var stays as a forward-looking guard.
julien added 1 commit 2026-05-20 10:22:41 +02:00
fix(ci): pass NODE_OPTIONS=--use-system-ca to clear grpc-tools tls install
CI / scan (pull_request) Failing after 1m22s
CI / check (pull_request) Failing after 1m27s
CI / commits (pull_request) Failing after 1m31s
CI / perf (pull_request) Failing after 14s
CI / a11y (pull_request) Failing after 1m36s
Docs site / build (pull_request) Failing after 1m41s
c419a73bf5
The CI runner (catthehacker/ubuntu:act-22.04) fails `pnpm install
--frozen-lockfile` because grpc-tools' postinstall downloads a
precompiled protoc archive from node-precompiled-binaries.grpc.io
and Node 24's bundled CA set cannot verify the chain there.

Node 24 itself surfaces the fix in the error message: pass
`--use-system-ca` so Node consults the OS CA store in addition to
its bundled set. The runner image carries the standard Ubuntu
`ca-certificates` bundle, which validates the impacted chains.

Applied at workflow scope (env: block) on both ci.yml and
docs-site.yml so every Node child (pnpm itself plus every
postinstall it spawns) inherits the option. Future native deps
that hit the same TLS rejection will benefit automatically.
julien merged commit 219b7a2143 into main 2026-05-20 10:23:39 +02:00
julien deleted branch fix/ci-grpc-tools-node-system-ca 2026-05-20 10:23:40 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: julien/apf_portal#199