Compress with zopfli in a worker pool
compress-app gzips every build artifact with zopfli, but @gfx/zopfli is
synchronous WASM: it ran on the main thread, pinned a single core and blocked
the event loop for the whole step, so it dominated the production build.
Replace gulp-zopfli-green with an equivalent gulp transform that runs the same
compressor in a pool of worker_threads sized to availableParallelism(). The
compressed output is byte-identical, and @gfx/zopfli is no longer loaded on the
main thread of every gulp invocation.
On a 12-core machine compress-app drops from 6.98 min to 1.27 min, and the full
production build from 8.87 min to 3.32 min.
* Recover from a stale index.html at boot
A cached, stale index.html imports the previous build's content-hashed
entry bundles (core.<hash>.js / app.<hash>.js). After an upgrade those
files 404, app.js never runs, <home-assistant> is never defined, and the
launch screen never clears. No bundled JS can recover this, because the
bundle itself failed to load.
Add a tiny, prod-only inline guard in index.html that catches the failed
entry load (capture-phase resource error + unhandledrejection) and does a
single, loop-guarded cache-busting reload, dropping the service worker and
caches on https first. core.ts strips the cache-bust param after a
successful boot.
Part of home-assistant/epics#113.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Share stale-build recovery patterns via a single JSON source
Move the boot guard's chunk-detection regexes into
stale-build-patterns.json and inject them into the inline guard at build
time (entry-html.js), so they stay in sync with the bundled recovery util
(util/recover-stale-build.ts, in the follow-up post-boot recovery) which
reads the same file — no more manually kept-in-sync copies.
Part of home-assistant/epics#113.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Shared build and runner for all build,dev,test flows
* Harden managed process lifecycle
* Make build workflows deterministic
* Test build management contracts
* Queue shared generated output work
* Isolate generated inputs for dev servers
* Preserve dev server child failures
* Make generated lock test deterministic
* Keep test navigator configurable
* Block concurrent frontend workflows
* Simplify workflow lock ownership
* Focus workflow locking on managed commands
* Trim workflow lock unit tests
* Consolidate dev server lifecycle handlers
* Add managed modern production builds
* Harden managed build process controls
* Update managed process testing guidance
* Harden managed process file operations
* Share generated output process ownership
* Clean stale build state on status
* Address managed build review feedback
Co-authored-by: timmo001 <28114703+timmo001@users.noreply.github.com>
* Use single compress task
* 1
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
* Forward SIGHUP to foreground processes
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
* Fall back to English when nightly translations cannot be fetched
Local builds no longer fail when the nightly translations fetch errors
(offline or invalid GitHub credentials); they warn and continue with
English only, like the existing no-token path. CI still fails so
releases cannot silently ship without translations.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3oj5uaCRRaoXRd5iEffhi
* Record fetched artifact only after successful extraction
A failure mid-fetch previously left a fresh artifact.json next to wiped
translations, so builds within the next 24 hours skipped the fetch and
silently built English only. Writing the artifact file last means a
failed fetch is retried by the next build.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3oj5uaCRRaoXRd5iEffhi
* Update build-scripts/gulp/fetch-nightly-translations.js
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
* Dont open demo
* Scripts to run script/develop*
* Scripts for dev demo and gallery
* Background wrapper for agents with `--background`
* Background `yarn dev` and `dev:serve` for agents
* Dedupe lifecycle functions
* Apply suggestions from code review
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Update babel monorepo
* Migrate Core-JS polyfilling for Babel 8
Babel 8.0.1 removed preset-env's `useBuiltIns`/`corejs` options. Replace
them with the babel-plugin-polyfill-corejs3 provider directly
(`usage-global`), and pin transform-runtime's `moduleName` to
`@babel/runtime` so the provider doesn't redirect helpers to the
uninstalled `@babel/runtime-corejs3`.
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
* Update babel monorepo to v8
* Bugfixes option has been removed and is enabled by default
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
* Dedicated gallery AGENTS.md
* Dont auto open the dev server for gallery
* Refactor and theme gallery
* Add icons
* Better positioning of icons
* Reorganise sidebar
* Remove extra title
* Remove header/toolbar height override
* Add some global spacing for content
* Show flipped theme mode for comparisions
* Remove unnesassary headings
* Fix eslint webpack resolution path for gallery vscode import errors
* Scroll item into view
* Fix theme variables
* Fix theme when system theme is dark and set to light
* Review
* Review
* Review
* Review
* Add mock
* Fix buttons
* Generate third party license file during production build
* Add license check CI step
* Address review comments: use license-checker-rseidelsohn, add version validation for LICENSE_OVERRIDES
* Fix license-checker-rseidelsohn import (CJS module, use require)
* Update dependency @rspack/dev-server to v2
* Upgrade @rspack/core to 2.0.0
Pairs with the @rspack/dev-server 2.0.0 bump in #51666 — dev-server v2
declares @rspack/core ^2.0.0-0 as a peer, so the two must move together.
Patches webpackbar to defend against non-string info in Rspack 2's
ProgressPlugin handler (otherwise `parseRequest` throws `split is not a
function` during compilation).
Verified locally: yarn lint:types, yarn test, yarn lint, script/build_frontend,
and all three rspack-dev-server-{demo,cast,gallery} tasks.
* Wrap webpackbar instead of patching it
Replace the yarn patch with a small SafeWebpackBar subclass that sanitizes
the progress `details` array before the upstream parseRequest sees it.
Keeps the fix local to the Rspack config where it belongs.
* Pass moduleIdentifier to webpackbar progress
Rspack 2's progress info is `{ builtModules, moduleIdentifier? }`.
moduleIdentifier is what v1 passed as a plain string, so extract it to
keep the "active module" line in the progress bar instead of blanking it.
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
* Update eslint to v10.1.0
Migrate from eslint-plugin-import to eslint-plugin-import-x since the
original plugin uses removed ESLint 10 APIs (context.parserOptions,
context.parserPath). Airbnb-base non-import rules preserved via
FlatCompat with import rules stripped and replaced by import-x.
- eslint 9.39.4 → 10.1.0
- Add eslint-plugin-import-x 4.16.2
- Add @eslint/eslintrc and @eslint/js as explicit deps
- Remove --flag v10_config_lookup_from_file (now default)
- Replace /* eslint-env */ comment with config-based globals
- Update all import/ rule references to import-x/
* Remove unnecessary eslint-disable for generated gallery imports
The import-pages file is generated as .ts, so import-x/extensions
doesn't require an extension (ts: "never" in config).
The @rspack/dev-server overlay catches ResizeObserver loop errors as
runtime crashes, showing a full-screen error overlay that blocks
development. These errors are benign — they originate from
lit-virtualizer (used by ha-data-table) and simply mean not all
resize observations could be delivered in a single animation frame.
Add a client.overlay.runtimeErrors filter to the dev server config
that suppresses ResizeObserver loop messages while still surfacing
all real runtime errors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Separate entity, device and area name in more info dialog header
* Use has_entity_name
* Separate entity, device and area name in entity picker
* Fix entity name with has entity name
* Fix compute entity name
* Add full name
* Add floor
* Improve code quality
* Use compute entity name in device entities card
* Use context functions
* Remove floor
* Use state name provided by backend
* Use breadcrumb for more info
* Revert entity picker changes
* Use new logic in device page
* Use breadcrumb
* Use join directive
* Add comments
* Use secondary text color
* Update compute_entity_name.ts
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
* Remove html join
* Improve computeDeviceNameDisplay
* Fallback to original name
* Simplify more info logic
* Include breadcrumb for child view (voice assistant)
---------
Co-authored-by: Bram Kragten <mail@bramkragten.nl>