Skip to content

fix: next-runtime-env not working in next 16; allow theme change for runtime#2322

Open
knudtty wants to merge 3 commits into
mainfrom
aaron/runtime-theme-env-var
Open

fix: next-runtime-env not working in next 16; allow theme change for runtime#2322
knudtty wants to merge 3 commits into
mainfrom
aaron/runtime-theme-env-var

Conversation

@knudtty
Copy link
Copy Markdown
Contributor

@knudtty knudtty commented May 20, 2026

Summary

next-runtime-env doesn't work for Next.js 16, or even 15 and seems to have been abandoned expatfile/next-runtime-env#178. I added some node script to make up for it for docker images.
Also fixed a theme change flash when first loading if using the clickstack theme.

References

  • Linear Issue: Closes HDX-4296

@vercel
Copy link
Copy Markdown

vercel Bot commented May 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview, Comment May 20, 2026 11:46pm

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 20, 2026

🦋 Changeset detected

Latest commit: d10d3a9

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/app Patch
@hyperdx/api Patch
@hyperdx/otel-collector Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added the review/tier-4 Critical — deep review + domain expert sign-off label May 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

🔴 Tier 4 — Critical

Touches auth, data models, config, tasks, OTel pipeline, ClickHouse, or CI/CD.

Why this tier:

  • Critical-path files (4):
    • docker/hyperdx/Dockerfile
    • docker/hyperdx/entry.local.base.sh
    • docker/hyperdx/entry.prod.sh
    • docker/hyperdx/refresh-env.js

Review process: Deep review from a domain expert. Synchronous walkthrough may be required.
SLA: Schedule synchronous review within 2 business days.

Stats
  • Production files changed: 6
  • Production lines changed: 74
  • Branch: aaron/runtime-theme-env-var
  • Author: knudtty

To override this classification, remove the review/tier-4 label and apply a different review/tier-* label. Manual overrides are preserved on subsequent pushes.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 20, 2026

E2E Test Results

All tests passed • 180 passed • 3 skipped • 1210s

Status Count
✅ Passed 180
❌ Failed 0
⚠️ Flaky 2
⏭️ Skipped 3

Tests ran across 4 shards in parallel.

View full report →

@github-actions
Copy link
Copy Markdown
Contributor

Knip - Unused Code Analysis

🔴 1 issue found

Unused files (1)

  • docker/hyperdx/refresh-env.js

Knip finds unused files, dependencies, and exports in your codebase.
Run yarn knip locally to see full details.

@github-actions
Copy link
Copy Markdown
Contributor

Deep Review

✅ No critical issues found.

🟡 P2 -- recommended

  • docker/hyperdx/refresh-env.js:12 -- The empty catch {} swallows JSON parse errors as well as missing-file errors, so if the on-disk __ENV.js is present but does not match the window.__ENV = {...}; shape (future next-runtime-env output drift, partial write, etc.), existing resets to {} and every build-time default silently disappears, contradicting the file's own comment.
    • Fix: Distinguish ENOENT from parse failures and log a warning when an existing __ENV.js cannot be parsed instead of silently dropping its contents.
  • docker/hyperdx/refresh-env.js:6 -- The path is resolved relative to process.cwd() (./packages/app/packages/app/public/__ENV.js), so the script only works when launched with cwd /app; any future entrypoint refactor or invocation from a different directory will silently fail the read and then crash or write to the wrong location.
    • Fix: Use an absolute path (e.g. /app/packages/app/packages/app/public/__ENV.js) or accept an env-var override.
  • docker/hyperdx/entry.prod.sh:15, docker/hyperdx/entry.local.base.sh:69 -- node /etc/local/refresh-env.js runs without status checking and neither script uses set -e, so a failure (read-only volume, missing public dir, etc.) lets the entry script continue and start the app with the stale __ENV.js -- masking the exact bug this PR is trying to fix.
    • Fix: Either guard the call (node /etc/local/refresh-env.js || echo "WARN: runtime env injection failed") or wrap the script in its own try/catch and emit a clearly tagged warning so operators can diagnose the regression.
  • Testing gap -- new behavior is uncovered. No tests exercise the runtime-env merge in refresh-env.js, the new getEnvTheme() path in packages/app/src/theme/index.ts:177, or the SSR + inline-script theme swap in packages/app/pages/_document.tsx. These three pieces are the entire fix and ship without regression coverage.
    • Fix: Add a unit test for refresh-env.js covering (a) missing file, (b) valid existing file, (c) malformed existing file; and a Document/theme test that asserts the inline init script only swaps to known themes and leaves the SSR class alone for unknown values.
🔵 P3 nitpicks (2)
  • packages/app/pages/_document.tsx:14 -- THEME_INIT_SCRIPT re-serializes the theme name list at module load and inlines it into every SSR response even though the values are statically known at build time; the SSR'd <html> class is also hard-coded theme-hyperdx, so a runtime clickstack deployment always pays an unnecessary class swap.
    • Fix: Either resolve the initial class server-side via env('NEXT_PUBLIC_THEME') (the same source the rest of the app now uses) and keep the inline script only as a defensive client fallback, or leave a comment explaining why SSR intentionally diverges from the runtime config.
  • docker/hyperdx/refresh-env.js:18 -- JSON.stringify(merged) does not escape U+2028/U+2029 line separators; while NEXT_PUBLIC_* values are operator-controlled and the file is loaded as an external script (so </script> injection is moot), a value containing those code points could still produce an invalid JS file in older runtimes.
    • Fix: Post-process the stringified output to escape / , or add a comment acknowledging the constraint on accepted env-var values.

Reviewers (6): correctness, maintainability, testing, project-standards, reliability, kieran-typescript.

Testing gaps:

  • No unit tests for refresh-env.js merge / parse-failure paths.
  • No test verifies that the inline theme-init script in _document.tsx keeps the SSR class when window.__ENV.NEXT_PUBLIC_THEME is missing or invalid.
  • No test exercises getEnvTheme() against a mocked next-runtime-env env() so future regressions in runtime resolution surface in CI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review/tier-4 Critical — deep review + domain expert sign-off

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant