fix(cli): run Windows post-processing on cached bundles + add docs preview smoke test#14765
fix(cli): run Windows post-processing on cached bundles + add docs preview smoke test#14765thesandlord wants to merge 21 commits intomainfrom
Conversation
Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Build the CLI locally and test it against the production docs bundle. This is the sibling/inverse of fern-platform's docs-bundle-smoke-test which builds the bundle locally and tests with the prod CLI. Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
…age.json Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
…otocol error Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
….json Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
packages/cli/cli/build-utils.mjs
Outdated
| } catch { | ||
| return {}; | ||
| } |
There was a problem hiding this comment.
🟡 Empty catch block silently swallows errors in loadPnpmCatalog
The catch {} block at packages/cli/cli/build-utils.mjs:42 silently discards any error from readFileSync or the YAML parsing logic — no error variable is bound, nothing is logged, and no comment explains why. If the pnpm-workspace.yaml file exists but is unreadable (permissions) or malformed, the function silently returns {}. This causes a confusing downstream error in getDependencyVersion (line 58) that says the dependency "was not found in pnpm-workspace.yaml catalog" — masking the real root cause. This violates the REVIEW.md / CLAUDE.md rule: "Never swallow errors with empty catch blocks — at minimum log the error. If you truly want to ignore it, add a comment explaining why."
| } catch { | |
| return {}; | |
| } | |
| } catch (error) { | |
| // Gracefully degrade if workspace file is missing (e.g. running outside the monorepo). | |
| // Catalog references will still fail explicitly in getDependencyVersion(). | |
| console.warn(`Warning: could not load pnpm catalog from pnpm-workspace.yaml: ${error.message}`); | |
| return {}; | |
| } |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Good catch — fixed in 8b2687c. The catch block now logs a warning with the error message before returning the empty fallback.
…mCatalog Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
…nstall Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
…xtraction The tar bundle contains 1290+ Unix symlinks that are filtered out during extraction on Windows. pnpm install recreates pnpm-managed symlinks, but Next.js file-traced symlinks in .next/node_modules/ are NOT recreated, causing HTTP 500 errors on all pages. This fix: 1. Collects symlink metadata (path + linkname) during tar extraction 2. Saves metadata to .symlinks-metadata.json in the bundle directory 3. After pnpm install, recreates missing symlinks as directory junctions (no admin required on Windows) or file copies Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
| - name: Re-enable Windows Defender real-time monitoring | ||
| if: runner.os == 'Windows' | ||
| shell: powershell | ||
| run: Set-MpPreference -DisableRealtimeMonitoring $false |
There was a problem hiding this comment.
Windows Defender is re-enabled too early, before the main test runs. The workflow disables Defender at line 68-71 to speed up tool installation, but then re-enables it at line 196-199 BEFORE the "Start fern docs dev server" step (line 201-250). The fern docs dev server performs a slow pnpm install on Windows (as noted in the comment on line 215: "Windows bundle installation (download + pnpm install) can take 3-5 minutes"), which will be significantly slower with Defender enabled.
Move the re-enable step to after all tests complete:
- name: Stop fern docs dev server
if: always() && steps.node-check.outputs.available == 'true'
shell: bash
run: |
if [ -n "$FERN_PID" ]; then
kill $FERN_PID 2>/dev/null || true
fi
- name: Re-enable Windows Defender real-time monitoring
if: always() && runner.os == 'Windows'
shell: powershell
run: Set-MpPreference -DisableRealtimeMonitoring $falseSpotted by Graphite
Is this helpful? React 👍 or 👎 to let us know.
…nk metadata Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
…uning Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
pnpm i esbuild wipes node_modules/ including copies made before it. New approach: backup traced packages to .traced-packages-backup/ before pnpm operations, then restore them after all pnpm ops complete in postProcessWindowsBundle. Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
…urce instead Co-Authored-By: Sandeep Dinesh <sandeep@buildwithfern.com>
Description
Refs: fern-api/fern-platform#9546, fern-api/fern-platform#9569
Two related changes:
Windows cached-bundle fix: On Windows,
fern docs devskips bundle post-processing when the etag matches (cached bundle). This means bundles that were pre-extracted externally (e.g. by CI, or by a previous non-Windows-aware CLI version) never get the symlink-replacementpnpm install, causing the standalone server to fail.Docs preview smoke test: Adds a sibling smoke test to the one in fern-platform. While fern-platform's test builds the docs bundle locally and tests with the prod CLI, this test builds the CLI locally and tests with the prod docs bundle from S3. Runs on ubuntu-latest, macos-latest, and windows-latest × Node 20/22/24/26.
The root cause of Windows failures (symlinks in the bundle tar) is being fixed at the source in fern-platform#9569, which dereferences symlinks during tar creation so the bundle is Windows-compatible. This PR's CLI-side changes handle the remaining post-processing (
pnpm install,.npmrc, etc.) and add the smoke test to verify it all works.Changes Made
Windows cached-bundle fix (
downloadLocalDocsBundle.ts)postProcessWindowsBundle()function.windows-post-processedmarker file to avoid re-running the expensivepnpm installon every subsequentfern docs devinvocation — the marker lives inside thestandalone/directory and is automatically cleaned up when a new bundle replaces the old oneBuild utils fix (
build-utils.mjs)loadPnpmCatalog()to parsepnpm-workspace.yamland resolvecatalog:references inpackage.jsondependenciesnpm installin the extracted CLI artifact fails because npm doesn't understand pnpm'scatalog:protocolDocs preview smoke test (new)
.github/workflows/docs-preview-smoke-test.ymlthat:pnpm turbo run dist:cli:prod)cli.cjsas an artifactubuntu-latest×macos-latest×windows-latest× Node 20/22/24/26fern docs dev(CLI downloads prod bundle from S3 automatically)pnpm installtakes 3-5 min)smoke-test/fern/(minimal docs project with markdown pages + REST API OpenAPI spec)smoke-test/playwright/packages/cli/docs-preview/**,packages/cli/cli/**,smoke-test/**, or the workflow itselfCurrent Windows smoke test status
Human Review Checklist
Windows fix
app-previewfolder is renamed+deleted (line ~316–323), which removes the marker. Confirm fresh downloads always re-run post-processing.postProcessWindowsBundleis called without a try/catch at line 232 (cached-bundle path). If it throws, the entiredownloadBundlecall fails — is that the desired behavior, or should it fall through gracefully?PLATFORM_IS_WINDOWS && app, matching the existingif (app) { ... if (PLATFORM_IS_WINDOWS)nesting in the fresh-download path..next/node_modules/) at bundle build time.Build utils
loadPnpmCatalog()is a simple regex-based YAML parser. Verify it handles quoted keys, inline comments, and multi-catalog configs correctly for this repo'spnpm-workspace.yaml.Smoke test
FERN_TOKENsecret: The workflow referencessecrets.FERN_TOKEN— verify this secret exists in the fern repo.pages.ts: The test assumes page slugs/welcomeand/getting-started. Confirm these match what the CLI generates from the fixture'sdocs.yml.Testing
Link to Devin session: https://app.devin.ai/sessions/762b6ec9085f4ec0849edcca9e133472
Requested by: @thesandlord