Skip to content

Release v3.8.9 — final sync (static-asset fix + contributor credits) - #3135

Merged
diegosouzapw merged 3 commits into
mainfrom
release/v3.8.9
Jun 4, 2026
Merged

diegosouzapw merged 3 commits into
mainfrom
release/v3.8.9

Conversation

@diegosouzapw

Copy link
Copy Markdown
Owner

Finalizes the v3.8.9 release for tagging. Brings the two commits that landed on `release/v3.8.9` after the initial release merge (#3092):

Included

Validation

  • Static fix verified on the VM: built standalone serves chunks → HTTP 200, login UI renders.
  • Deployed + validated on the local VPS (192.168.0.15) by the maintainer.

After merge → tag `v3.8.9` → npm/docker/electron publishes.

…teral .next

CRITICAL white-screen bug from the build-output-isolation refactor: the standalone
server.js bakes distDir ("./.build/next") into its config and serves /_next/static
from <root>/.build/next/static — but assembleStandalone hard-coded the destination
to <outDir>/.next/static (+ sanitised/patched <outDir>/.next/{required-server-files,
server}). Result: the server's static dir was EMPTY → every JS/CSS chunk 404'd →
blank login page (health stayed 200, so it slipped past the health-only dry-run).

Mirror the distDir path (relative to projectRoot) for static, required-server-files
sanitization (was a silent no-op → 0 paths sanitised, now 11), and the Turbopack
chunk patch. Verified: booting the assembled bundle serves the webpack chunk 200.
Affects every consumer (npm/Docker/Electron/VPS).
…ic-asset build fix

- #3131 Kiro Opus 4.8 catalog (thanks @artickc)
- #3132 Kimi thinking-mode reasoning_content fix (thanks @bypanghu)
- #3130 connectionId fallback + kilo call logging (thanks @androw)
- build: standalone static-asset path fix (white login screen after build-output reorg)
- contributors hall: +@artickc +@bypanghu +@androw (15 total)

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request updates the standalone build assembly process to support custom build output directories (distDir) instead of assuming a hardcoded ".next" directory. It ensures static assets, required server files, and Turbopack chunks are correctly placed and referenced. The review feedback identifies edge cases where path resolution could fail if distDir is absolute or if the project root differs from the current working directory, offering robust code suggestions to normalize these paths.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +286 to 293
export function assemblePathSanitize(projectRoot, outDir, distDir = ".next") {
const buildRoot = projectRoot.replace(/\\/g, "/"); // normalise for regex safety
const sanitizeTargets = [
path.join(outDir, "server.js"),
path.join(outDir, ".next", "required-server-files.json"),
// required-server-files.json lives under the distDir (e.g. .build/next), not
// a literal .next — the standalone preserves the configured distDir path.
path.join(outDir, distDir, "required-server-files.json"),
];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

If distDir is passed as an absolute path, path.join(outDir, distDir, ...) will produce an incorrect path (e.g., outDir/absolute/path/...), causing fsSync.existsSync to fail and silently skipping the sanitization of required-server-files.json.

Since assemblePathSanitize has access to projectRoot, we can defensively normalize distDir to be relative to projectRoot if it is absolute.

Suggested change
export function assemblePathSanitize(projectRoot, outDir, distDir = ".next") {
const buildRoot = projectRoot.replace(/\\/g, "/"); // normalise for regex safety
const sanitizeTargets = [
path.join(outDir, "server.js"),
path.join(outDir, ".next", "required-server-files.json"),
// required-server-files.json lives under the distDir (e.g. .build/next), not
// a literal .next — the standalone preserves the configured distDir path.
path.join(outDir, distDir, "required-server-files.json"),
];
export function assemblePathSanitize(projectRoot, outDir, distDir = ".next") {
const buildRoot = projectRoot.replace(/\\/g, "/"); // normalise for regex safety
const relDistDir = path.isAbsolute(distDir) ? path.relative(projectRoot, distDir) : distDir;
const sanitizeTargets = [
path.join(outDir, "server.js"),
// required-server-files.json lives under the distDir (e.g. .build/next), not
// a literal .next — the standalone preserves the configured distDir path.
path.join(outDir, relDistDir, "required-server-files.json"),
];

Comment on lines +397 to 403
// The standalone bundle preserves the distDir path RELATIVE to projectRoot
// (the server's baked config uses e.g. "./.build/next"), so output dest paths
// for static / required-server-files / server chunks must use the relative
// distDir appended to outDir — never the absolute build-machine distDir.
const relDistDir = path.isAbsolute(distDir) ? path.relative(projectRoot, distDir) : distDir;

const standaloneDir = path.resolve(path.join(distDir, "standalone"));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

If distDir is relative and projectRoot is different from process.cwd(), path.resolve(path.join(distDir, "standalone")) will resolve against process.cwd() instead of projectRoot. This can lead to incorrect path resolution in monorepos or custom build environments.

We should resolve distDir against projectRoot first if it is relative, and then derive relDistDir and standaloneDir from it.

Suggested change
// The standalone bundle preserves the distDir path RELATIVE to projectRoot
// (the server's baked config uses e.g. "./.build/next"), so output dest paths
// for static / required-server-files / server chunks must use the relative
// distDir appended to outDir — never the absolute build-machine distDir.
const relDistDir = path.isAbsolute(distDir) ? path.relative(projectRoot, distDir) : distDir;
const standaloneDir = path.resolve(path.join(distDir, "standalone"));
// The standalone bundle preserves the distDir path RELATIVE to projectRoot
// (the server's baked config uses e.g. "./.build/next"), so output dest paths
// for static / required-server-files / server chunks must use the relative
// distDir appended to outDir — never the absolute build-machine distDir.
const resolvedDistDir = path.isAbsolute(distDir) ? distDir : path.resolve(projectRoot, distDir);
const relDistDir = path.relative(projectRoot, resolvedDistDir);
const standaloneDir = path.join(resolvedDistDir, "standalone");

Comment thread scripts/build/assembleStandalone.mjs Outdated
Comment on lines +441 to +442
const staticSrc = path.join(distDir, "static");
const staticDest = path.join(resolvedOutDir, ".next", "static");
const staticDest = path.join(resolvedOutDir, relDistDir, "static");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

To ensure correct path resolution when projectRoot is different from process.cwd() and distDir is relative, staticSrc should be resolved using resolvedDistDir instead of distDir.

Suggested change
const staticSrc = path.join(distDir, "static");
const staticDest = path.join(resolvedOutDir, ".next", "static");
const staticDest = path.join(resolvedOutDir, relDistDir, "static");
const staticSrc = path.join(resolvedDistDir, "static");
const staticDest = path.join(resolvedOutDir, relDistDir, "static");

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

CI Coverage Report

  • Coverage job: success
  • PR test policy: success

Coverage artifact was not available for this run.

…rCloud gate)

Extract patchStandalonePackageJson / copyStaticAndPublic / copyNativeAssetsAndExtraModules
helpers so assembleStandalone drops from cognitive complexity 29 → ~12 (≤15 gate).
Also: replaceAll over replace, String.raw for the regex-escape replacement (2 minor smells).
Pure refactor — assemble-standalone.test.ts still green; no behavior change.
@sonarqubecloud

sonarqubecloud Bot commented Jun 4, 2026

Copy link
Copy Markdown

@kilo-code-bot

kilo-code-bot Bot commented Jun 4, 2026 •

Copy link
Copy Markdown

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • CHANGELOG.md
  • scripts/build/assembleStandalone.mjs
  • tests/unit/build/assemble-standalone.test.ts

Reviewed by nemotron-3-super-120b-a12b-20230311:free · 1,845,266 tokens

@diegosouzapw
diegosouzapw merged commit 5057454 into main Jun 4, 2026
91 checks passed
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
Release v3.8.9 — final sync (static-asset fix + contributor credits)
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
Release v3.8.9 — final sync (static-asset fix + contributor credits)
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
Release v3.8.9 — final sync (static-asset fix + contributor credits)
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