Repository navigation
Conversation
Docs preview (local build)Handbook preview: https://docs-v3-preview.elastic.dev/elastic/docs-builder/pull/4205/ |
There was a problem hiding this comment.
Requesting changes.
What is this? | From workflow: PR Review
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
|
@reakaleek this is basically #3884 reworked, I instructed claude to update yours but it chose not too 😸 |
474718c to
aea1856
Compare
aea1856 to
24957ca
Compare
There was a problem hiding this comment.
Requesting changes based on the inline findings.
What is this? | From workflow: PR Review
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
| <Target Name="EnsureSkipNpmBuildArtifacts" | ||
| BeforeTargets="NpmInstall;NpmRunBuild" | ||
| Condition="'$(SkipNpmBuild)' == 'true'"> | ||
| <Error Condition="!Exists('_static/main.js') Or !Exists('_static/styles.css')" |
There was a problem hiding this comment.
[MEDIUM] SkipNpmBuild validation misses build-type CSS artifacts
EnsureSkipNpmBuildArtifacts only checks _static/main.js and _static/styles.css, but _Head.cshtml also requires one of assembler.css, isolated.css, or codex.css based on BuildType. With SkipNpmBuild=true, a partial _static/ can pass this check and later serve pages with missing stylesheet URLs (404), producing broken styling at runtime.
Please validate the required build-type stylesheet(s) in this target as well, not just main.js and styles.css.
| - uses: actions/cache@v6 | ||
| with: | ||
| path: src/Elastic.Documentation.Site/node_modules | ||
| key: node-modules-${{ runner.os }}-${{ hashFiles('src/Elastic.Documentation.Site/package-lock.json') }} |
There was a problem hiding this comment.
[LOW] node_modules cache key should include Node runtime version
This cache key is based on OS + lockfile hash only. If .nvmrc changes while package-lock.json does not, this key still restores an older node_modules tree built against a different Node version, which can cause native-module ABI mismatches and flaky CI behavior.
Consider adding the Node version (for example via .nvmrc hash) to the key so runtime upgrades invalidate this cache.
388c2ec to
4bb76be
Compare
There was a problem hiding this comment.
Requesting changes due to a verified incremental-build regression in the frontend MSBuild target wiring.
What is this? | From workflow: PR Review
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
| <OldHashedBundles Include="_static/*.????????*.css" /> | ||
| </ItemGroup> | ||
| <Delete Files="@(OldHashedFiles)" ContinueOnError="true" /> | ||
| <Delete Files="@(GeneratedStaticFiles);@(ViteGeneratedFiles);@(OldHashedBundles)" ContinueOnError="true" /> |
There was a problem hiding this comment.
[MEDIUM] Cleaning build outputs before NpmRunBuild defeats incremental builds
NpmRunBuild declares incremental outputs (_static/.build-stamp;_static/main.js;_static/styles.css), but CleanGeneratedStaticAssets runs BeforeTargets="NpmRunBuild" and deletes those generated files first. That makes the target out-of-date on every invocation, so npm run build runs every time even when inputs are unchanged.
I reproduced this by running dotnet msbuild ... -t:NpmRunBuild twice in a row with no source changes; both runs executed Vite.
Please avoid deleting declared outputs in the pre-target cleanup path (for example, clean only stale hashed/chunked artifacts), so no-op builds can skip the frontend rebuild as intended.
4bb76be to
6d364ff
Compare
There was a problem hiding this comment.
Requesting changes based on the inline finding.
What is this? | From workflow: PR Review
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
| <Target Name="EnsureSkipNpmBuildArtifacts" | ||
| BeforeTargets="NpmInstall;NpmRunBuild" | ||
| Condition="'$(SkipNpmBuild)' == 'true'"> | ||
| <Error Condition="!Exists('_static/main.js') Or !Exists('_static/styles.css') Or !Exists('_static/assembler.css') Or !Exists('_static/isolated.css') Or !Exists('_static/codex.css')" |
There was a problem hiding this comment.
[MEDIUM] SkipNpmBuild check still allows incomplete Vite output
EnsureSkipNpmBuildArtifacts verifies only five top-level files, but Vite runtime also needs generated chunk-*/asset-* files referenced by main.js. In SkipNpmBuild=true builds, a partially-populated _static/ directory can pass this check and produce runtime 404s when the browser requests missing chunks/assets.
Please also validate bundle completeness for the skip path (for example by checking for required generated chunk/asset outputs or validating a manifest from the last full build).
6d364ff to
48f8d80
Compare
The `Docs preview (local)` workflow takes ~6m32s; two steps dominate. #### Fix NUGET_PACKAGES so the cache is actually used The bootstrap action caches `.nuget/packages` but never sets the `NUGET_PACKAGES` env var, so `dotnet` ignores the cache and does a full restore from nuget.org on every run. Adding the var to `bootstrap/action.yml` fixes this for every consumer at once: `docs-preview-local.yml`, `assembler-preview.yml`, and external repos that pin to this action. #### Separate build from validation Five consecutive `dotnet run` calls each pay ~8 s of MSBuild evaluation, with the first also absorbing restore and build. An explicit `dotnet build -c release src/tooling/docs-builder` step runs once before any `dotnet run` call. All `dotnet run` calls become `dotnet run --no-build -c release` so subsequent steps share the build artifact instead of re-evaluating. The release config also drops the Debug-only `Elastic.Documentation.Api` project reference and skips the `curb` MSBuild rewrite that runs across ~25 projects in Debug mode. #### Upload pre-compressed objects to preview S3 `aws s3 sync` ships raw bytes; the 4,029 API operation pages average ~420 KB each, driving the output tree to ~2 GiB. CloudFront compresses on delivery, but the upload cost is paid in full on every run. The upload step now gzips the entire output tree in parallel before syncing, then passes `--content-encoding gzip` so every object carries the header. CloudFront forwards pre-compressed objects untouched, preserving brotli negotiation for clients that ask for it — the flag only disables CloudFront's own compression pass. Expected upload: ~120 MB instead of ~2 GiB. One pass with `--content-encoding gzip` is intentional: the flag applies sync-wide, so splitting into text vs binary would need two passes and would break `--delete` (each pass deletes keys the other pass owns). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The in-place gzip pass compressed redirects.json alongside all other output files. The subsequent Deploy redirects step read it as plain JSON and got gzip bytes instead, breaking the redirects update. Copy redirects.json to /tmp before compression and point the deploy step at the uncompressed copy. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…index upload Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
48f8d80 to
cc855c2
Compare
There was a problem hiding this comment.
Requesting changes due to a verified incremental-build regression in frontend asset cleanup.
What is this? | From workflow: PR Review
Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
| causing duplicated JS/CSS with different hashes in the final _static folder. --> | ||
| <Target Name="CleanOldHashedAssets" BeforeTargets="NpmRunBuild" Condition="'$(IsPublishing)' == 'true'"> | ||
| <Target Name="CleanGeneratedStaticAssets" | ||
| BeforeTargets="NpmRunBuild" |
There was a problem hiding this comment.
[HIGH] Cleanup runs even when frontend build is skipped, leaving broken chunk references
CleanGeneratedStaticAssets runs BeforeTargets="NpmRunBuild" and deletes chunk-*/asset-* files regardless of whether NpmRunBuild actually executes. Because NpmRunBuild can be skipped by incremental checks, this can leave _static/main.js referencing chunk files that were just deleted.
I reproduced this on the current branch by invoking NpmRunBuild via MSBuild and then checking _static/main.js: it contains 45 ./chunk-* imports, and all 45 referenced files were missing on disk after the target graph ran.
Please make cleanup conditional on the build actually running (for example, move cleanup into NpmRunBuild before the Exec), so no-op builds don't invalidate an otherwise consistent _static output set.
Vite eliminates the Windows TEMP workaround Parcel required and cuts cold npm ci cost by caching node_modules in the bootstrap action. SkipNpmBuild and DesignTimeBuild MSBuild hooks prevent redundant npm runs in IDE and --no-build scenarios. IgnoreStandardErrorWarningFormat on the npm run build exec prevents MSBuild from misclassifying Vite chunk names (EuiIconWarning, EuiIconError) as build diagnostics. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…in SkipNpmBuild guard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes main.js, styles.css, assembler.css, isolated.css, codex.css and their map files from the pre-build clean target. Deleting declared NpmRunBuild outputs before the incremental output check defeats MSBuild's up-to-date detection, so npm run build ran on every dotnet build even when no source files changed. The clean target now only removes content-hashed chunk-* and asset-* files from prior Vite runs, which do need cleaning to avoid accumulation across builds. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cc855c2 to
520f233
Compare
|
Closed to retarget as a standalone PR stacked on #4206. Content preserved in new PR. |
The frontend toolchain moves from Parcel to Vite. This eliminates the Windows TEMP workaround Parcel required, adds `node_modules` caching to the bootstrap action, and fixes a class of MSBuild false-positive errors caused by Vite chunk names that contain `Error` and `Warning` (EUI icon names).
Affects: Site UI, Automation
Prompt summary: #3884 replaced Parcel with Vite but went stale. The ask was to rebase it, regenerate `package-lock.json`, and add the `SkipNpmBuild`/`DesignTimeBuild` MSBuild hooks that prevent npm from running in IDE or `--no-build` contexts.
Why
Parcel required a Windows-specific workaround (redirecting `TEMP` to the same drive) and had no incremental-build hooks, so every `dotnet build` paid a full `npm ci` + `npm run build`. The MSBuild `Exec` task scanned Vite output for error/warning patterns and misclassified chunk filenames like `chunk-EuiIconWarning-xxx.js` and `chunk-EuiIconError-xxx.js` as build diagnostics, failing the build even when the exit code was 0.
What
Vite build pipeline
`vite.config.ts` replaces `.parcelrc` and `.postcssrc`. It configures `@tailwindcss/vite`, `@vitejs/plugin-react`, and `vite-plugin-svgr`, and produces the same five output artefacts (`main.js`, `styles.css`, `assembler.css`, `isolated.css`, `codex.css`) under `_static/`. The `watch` and `build` npm scripts call `vite` instead of `parcel`.
MSBuild integration
`SkipNpmBuild` and `DesignTimeBuild` conditions on `NpmInstall` and `NpmRunBuild` prevent npm from running in IDE design-time evaluations or when building with `--no-build`. A new `EnsureSkipNpmBuildArtifacts` target errors early when `SkipNpmBuild=true` but any of the five `_static/` artefacts are absent. `IgnoreStandardErrorWarningFormat="true"` on the `npm run build` exec stops MSBuild from misclassifying Vite chunk names as build errors. `EmbedGeneratedAssets` uses a recursive `_static/**/*.js` glob to pick up Vite's `assets/` subdirectory.
Incremental builds
`CleanGeneratedStaticAssets` runs before `NpmRunBuild` to remove stale `chunk-` and `asset-` files from previous Vite runs. It deliberately does not delete the stable named outputs (`main.js`, `styles.css`, etc.) — doing so would delete the files that MSBuild checks against the declared `Outputs` for incremental up-to-date detection, forcing a full `npm run build` on every `dotnet build` even when no source files changed.
CI and bootstrap
`node_modules` is cached in `bootstrap/action.yml` keyed on both `package-lock.json` and `.nvmrc` so a Node version bump invalidates the cache. The Windows TEMP workaround steps are removed from `ci.yml` and `release.yml`. The `<script defer>` tag becomes `<script type="module">` in `_Head.cshtml` to match Vite's ES module output.
Live reload
`ParcelWatchService` is renamed to `FrontendWatchService` and `DocumentationWebHost` is updated to use it. The `npm run watch` command now runs `vite` in watch mode.
Verify
```bash
cd src/Elastic.Documentation.Site
npm ci && npm run build && npm run test && npm run compile:check
dotnet build src/tooling/docs-builder -c release
Run twice; the second build should skip NpmRunBuild (up-to-date).
dotnet build src/tooling/docs-builder -c release
```
Stack: 4 of 5, on top of #4208. #4210 follows.
🤖 Generated with Claude Code