Moves project-owned JavaScript onto stable Bun 1.4.3 in development, tests, CI and the container, following ADR 0009 and the decisions recorded during the #289 verification.
Closes#289 Closes#291 Closes#292
Refs #290: native bun lint/bun fmt are canary-only, so ESLint and Prettier stay, run by Bun, until a stable release ships them.
Refs #293: the final gate is completed by this PR's live checks; the migration stays open with #290.
Version. Stable Bun 1.4.3 everywhere (packageManager, CI installer with pinned SHA-256s, digest-pinned oven/bun:1.4.3-alpine).
Server. Angular's server build relies on Node module.register loader hooks that Bun ignores. Every route is client-rendered, so Angular now builds client-only and a small Bun.serve server replaces Express and @angular/ssr.
Coverage.bun test collects line coverage only. HTML and Cobertura are generated from lcov, and branch and function coverage are shown as "not collected" rather than 100%.
Benchmark memory. JavaScriptCore has no heap flag, so the benchmark job uses a --memory=3g container limit.
scripts/install-bun.sh installs the checksum-verified release, with no npm.
Project steps run in a job shell without Node on PATH. Node stays only for the checkout and upload-artifact JS actions.
Policy, publication and the required aggregation are unchanged.
Verification
Local, with Node unavailable:
frozen install;
typecheck, lint and format check;
750/750 functional tests, plus the coverage run and its reports;
the policy and image regression scripts;
the production build and server probes;
the benchmark: 6/6 within budget;
a Docker build that reaches healthy.
Real Gitea runner engine (gitea-runner exec 5.1.0), locally: the validate, build, test and benchmark jobs pass with the custom shell; node is absent from project steps, and the JavaScript actions still work.
Review: an independent Opus review checked the server traversal handling, the installer checksums for all four platforms, and the spec diffs (no weakened assertions). Its findings are fixed in dfe6d28 and 282d9c6.
Still needed: live CI on this PR, covering the custom shell on the instance runner, the per-job Bun download, the images job with credentials, and the benchmark margin.
Known limits
The images job keeps Alpine's nodejs on PATH for the checkout action. The project command runs Bun by absolute path.
src/test-setup.ts deep-imports Analog's internal jitTransform. It is marked as a shortcut.
Moves project-owned JavaScript onto stable **Bun 1.4.3** in development, tests, CI and the container, following ADR 0009 and the decisions recorded during the #289 verification.
Closes #289
Closes #291
Closes #292
Refs #290: native `bun lint`/`bun fmt` are canary-only, so ESLint and Prettier stay, run by Bun, until a stable release ships them.
Refs #293: the final gate is completed by this PR's live checks; the migration stays open with #290.
## Decisions taken during #289
- **Version.** Stable Bun 1.4.3 everywhere (`packageManager`, CI installer with pinned SHA-256s, digest-pinned `oven/bun:1.4.3-alpine`).
- **Server.** Angular's server build relies on Node `module.register` loader hooks that Bun ignores. Every route is client-rendered, so Angular now builds client-only and a small `Bun.serve` server replaces Express and `@angular/ssr`.
- **Coverage.** `bun test` collects line coverage only. HTML and Cobertura are generated from lcov, and branch and function coverage are shown as "not collected" rather than 100%.
- **Benchmark memory.** JavaScriptCore has no heap flag, so the benchmark job uses a `--memory=3g` container limit.
## Changes
- **Tests (#291)**
- `bun test` replaces Vitest, Jest, Nx and Vite.
- A preload compiles components through Angular's JIT transform with inlined templates. It also sets up jsdom, TestBed and zoneless change detection.
- `src/testing/vitest-compat.ts` covers the Vitest APIs that `bun:test` lacks.
- Test files run isolated, and the real-worker specs spawn the running Bun.
- The checkpoint-cancellation test is now deterministic.
- **Server and container (#292)**
- `src/server.ts`:
- serves hashed assets with a one-year cache;
- revalidates `index.html`;
- falls back to `index.html` for client routes;
- answers 404 for missing assets;
- answers 400 for traversal or malformed paths and 405 for other methods.
- It has 33 HTTP tests, including raw-path traversal.
- The Docker image contains no Node, and its health checks honor `PORT`.
- **Development and checks (#290)**
- `bunfig.toml` sets `[run] bun = true`, so `ng`, ESLint and Prettier never fall back to an installed Node.
- `bun run typecheck` uses `bun check` for the app and spec projects. TypeScript 6 stays for Angular.
- **CI (#293)**
- `scripts/install-bun.sh` installs the checksum-verified release, with no npm.
- Project steps run in a job shell without Node on `PATH`. Node stays only for the checkout and upload-artifact JS actions.
- Policy, publication and the required aggregation are unchanged.
## Verification
- **Local, with Node unavailable:**
- frozen install;
- `typecheck`, lint and format check;
- 750/750 functional tests, plus the coverage run and its reports;
- the policy and image regression scripts;
- the production build and server probes;
- the benchmark: 6/6 within budget;
- a Docker build that reaches healthy.
- **Real Gitea runner engine (`gitea-runner exec` 5.1.0), locally:** the validate, build, test and benchmark jobs pass with the custom shell; `node` is absent from project steps, and the JavaScript actions still work.
- **Review:** an independent Opus review checked the server traversal handling, the installer checksums for all four platforms, and the spec diffs (no weakened assertions). Its findings are fixed in `dfe6d28` and `282d9c6`.
- **Still needed:** live CI on this PR, covering the custom shell on the instance runner, the per-job Bun download, the `images` job with credentials, and the benchmark margin.
## Known limits
- The `images` job keeps Alpine's `nodejs` on `PATH` for the checkout action. The project command runs Bun by absolute path.
- `src/test-setup.ts` deep-imports Analog's internal `jitTransform`. It is marked as a shortcut.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Record the proposed decision to run project-owned JavaScript under Bun
with its native test runner, linter, formatter, type checker and HTTP
server, keeping Angular's standard build pipeline, plus the development
spec for the migration tickets.
Refs #289
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stable Bun 1.4.3 runs installs, the development server, standalone type
checks, the native test runner and a Bun.serve static server. Native
lint/fmt are canary-only, and Angular's server build needs Node loader
hooks Bun does not apply, so the spec now keeps ESLint/Prettier until a
stable release, builds Angular client-only behind a Bun static server,
converts line coverage from lcov, and replaces the heap cap with a
container memory limit.
Refs #289
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace Vitest with bun test across the whole suite. A preload compiles
components through Angular's JIT transform with inlined templates, sets
up jsdom, TestBed and zoneless change detection, and a small shim covers
the Vitest APIs bun:test lacks. Files run isolated, real-worker specs
spawn the running Bun, and line coverage from lcov is converted to the
existing HTML and Cobertura reports. The CI benchmark replaces its heap
cap with a container memory limit. Vitest, Jest, Nx and their Vite
configuration are removed.
Refs #291
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Angular's server build needs Node loader hooks that Bun does not apply,
and every route is client-rendered, so Angular now builds a client-only
bundle and a small Bun.serve server delivers it: hashed assets with the
one-year cache, index.html revalidated, extension-less routes falling
back to index.html, missing assets 404, traversal and malformed paths
rejected, and other methods 405. Express, @angular/ssr and the unused
hydration provider are removed. Both Docker stages use the pinned
oven/bun:1.4.3-alpine image without Node, and the health checks use
Bun's fetch.
Refs #292
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pin Bun 1.4.3 with packageManager, and force every bun run script onto
the Bun runtime through bunfig so ng, ESLint and Prettier never fall
back to an installed Node. Type checking uses bun check for the
application and test projects, next to the Angular build.
CI jobs install the pinned release from a checksum-verified download
instead of npm and run project steps in a shell without Node on PATH,
which stays available only for the checkout and upload actions. The
image test's fake docker runs on Bun.
Refs #290, #293
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cancelled stage takes about a millisecond, so under load the worker
could finish it before the cancel message arrived and report it as
completed. The real-worker harness now holds the worker after reporting
that stage until the cancel is delivered, keeping every assertion.
Refs #291
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The generated HTML and Cobertura reports no longer show unmeasured
branch and function coverage as 100%. Poll and waitFor deadlines use
performance.now so frozen dates cannot make them loop forever, the
malformed-configuration test covers undefined again next to the empty
array, compose health checks honor PORT, and the migration spec lists
only what is still open.
Refs #291, #292, #293
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nessar
merged commit 85fc4561fd into develop2026-10-17 18:28:43 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Moves project-owned JavaScript onto stable Bun 1.4.3 in development, tests, CI and the container, following ADR 0009 and the decisions recorded during the #289 verification.
Closes #289
Closes #291
Closes #292
Refs #290: native
bun lint/bun fmtare canary-only, so ESLint and Prettier stay, run by Bun, until a stable release ships them.Refs #293: the final gate is completed by this PR's live checks; the migration stays open with #290.
Decisions taken during #289
packageManager, CI installer with pinned SHA-256s, digest-pinnedoven/bun:1.4.3-alpine).module.registerloader hooks that Bun ignores. Every route is client-rendered, so Angular now builds client-only and a smallBun.serveserver replaces Express and@angular/ssr.bun testcollects line coverage only. HTML and Cobertura are generated from lcov, and branch and function coverage are shown as "not collected" rather than 100%.--memory=3gcontainer limit.Changes
bun testreplaces Vitest, Jest, Nx and Vite.src/testing/vitest-compat.tscovers the Vitest APIs thatbun:testlacks.src/server.ts:index.html;index.htmlfor client routes;PORT.bunfig.tomlsets[run] bun = true, song, ESLint and Prettier never fall back to an installed Node.bun run typecheckusesbun checkfor the app and spec projects. TypeScript 6 stays for Angular.scripts/install-bun.shinstalls the checksum-verified release, with no npm.PATH. Node stays only for the checkout and upload-artifact JS actions.Verification
typecheck, lint and format check;gitea-runner exec5.1.0), locally: the validate, build, test and benchmark jobs pass with the custom shell;nodeis absent from project steps, and the JavaScript actions still work.dfe6d28and282d9c6.imagesjob with credentials, and the benchmark margin.Known limits
imagesjob keeps Alpine'snodejsonPATHfor the checkout action. The project command runs Bun by absolute path.src/test-setup.tsdeep-imports Analog's internaljitTransform. It is marked as a shortcut.🤖 Generated with Claude Code