Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c6c2ed272 | ||
|
|
1cc4e4625e | ||
|
|
6b3840b6ac |
6 changed files with 178 additions and 124 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
// esbuild build for @hive/agent. Output layout (`dist/`):
|
// esbuild build for @hive/agent. Output layout (`dist/`):
|
||||||
//
|
//
|
||||||
// dist/index.html served at GET / (the Preact rewrite,
|
// dist/index.html served at GET / (the Preact rewrite —
|
||||||
// hyperhive#3685 — app.js is deleted)
|
// the old vanilla-JS app.js is deleted)
|
||||||
// dist/stats.html served at GET /stats
|
// dist/stats.html served at GET /stats
|
||||||
// dist/screen.html served at GET /screen
|
// dist/screen.html served at GET /screen
|
||||||
// dist/static/stats.js served at /static/stats.js (pulls in
|
// dist/static/stats.js served at /static/stats.js (pulls in
|
||||||
|
|
@ -50,7 +50,7 @@ await build({
|
||||||
loader: { ".css": "text" },
|
loader: { ".css": "text" },
|
||||||
});
|
});
|
||||||
|
|
||||||
// The main agent page (hyperhive#3685's Preact rewrite — app.js,
|
// The main agent page (the Preact rewrite — the old vanilla-JS app.js,
|
||||||
// which used to share this build step, is deleted). A separate bundle
|
// which used to share this build step, is deleted). A separate bundle
|
||||||
// from stats.js above rather than folded in: different loader needs
|
// from stats.js above rather than folded in: different loader needs
|
||||||
// (`.css: 'css'`, real stylesheets a component imports, vs. the raw-
|
// (`.css: 'css'`, real stylesheets a component imports, vs. the raw-
|
||||||
|
|
|
||||||
|
|
@ -1,52 +1,18 @@
|
||||||
// esbuild build for @hive/dashboard. Output layout (`dist/`):
|
// esbuild build for @hive/dashboard: one JS+CSS bundle per page (H0M3 at
|
||||||
//
|
// `/`, dashboard/flow/logs/core/builds/credentials at their own
|
||||||
// dist/index.html H0M3 menu hub — served by the Rust
|
// `.html`), each named after its own entry point below — see the
|
||||||
// router at GET / (the landing page)
|
// `entryPoints`/`for` lists for the exact map, not repeated here to
|
||||||
// dist/dashboard.html the operator dashboard SPA — served
|
// avoid this comment drifting out of sync with the real build steps.
|
||||||
// at GET /dashboard.html
|
|
||||||
// dist/flow.html served at GET /flow.html
|
|
||||||
// dist/logs.html served at GET /logs.html (AGENT/INFRA/SYSTEM)
|
|
||||||
// dist/core.html served at GET /core.html (C0R3: kept
|
|
||||||
// state / container load)
|
|
||||||
// dist/builds.html served at GET /builds.html (BU1LDS:
|
|
||||||
// rebuild queue / meta inputs / build logs)
|
|
||||||
// dist/credentials.html served at GET /credentials.html
|
|
||||||
// (CR3D3NTIALS: matrix + github accounts)
|
|
||||||
// dist/static/home.js index.html (H0M3) entry — menu tiles +
|
|
||||||
// matrix-tile gating + identity line
|
|
||||||
// dist/static/tabs.js dashboard.html entry — tab renderers +
|
|
||||||
// tab routing + refreshState
|
|
||||||
// dist/static/flow.js /flow.html entry — broker terminal +
|
|
||||||
// @-mention composer
|
|
||||||
// dist/static/logs.js /logs.html entry — agent/infra/system
|
|
||||||
// log viewer sub-tabs
|
|
||||||
// dist/static/builds.js /builds.html entry — rebuild queue,
|
|
||||||
// meta inputs, build log history
|
|
||||||
// dist/static/credentials.js /credentials.html entry — matrix +
|
|
||||||
// github account sub-tabs
|
|
||||||
// dist/static/{home,tabs,flow,logs,builds,credentials}.js.map source map
|
|
||||||
// siblings
|
|
||||||
// dist/static/common.css loaded by every page (@hive/shared
|
|
||||||
// imports + shared typography/badges/
|
|
||||||
// buttons/inbox/side-panel)
|
|
||||||
// dist/static/dashboard.css dashboard.html only (dashboard-specific)
|
|
||||||
// dist/static/flow.css /flow.html only (flow chrome + composer)
|
|
||||||
// dist/static/logs.css /logs.html only (log viewer sub-tabs)
|
|
||||||
// dist/static/builds.css /builds.html only (build lifecycle hub)
|
|
||||||
// dist/static/home.css index.html (H0M3) only (tile grid)
|
|
||||||
// dist/static/credentials.css /credentials.html only (matrix + github
|
|
||||||
// account forms)
|
|
||||||
//
|
//
|
||||||
// Each JS entry bundles `./common.js` (DOM helpers, Panel singleton,
|
// Each JS entry bundles `./common.js` (DOM helpers, Panel singleton,
|
||||||
// NOTIF, path linkification) independently — esbuild inlines the shared
|
// NOTIF, path linkification) independently — esbuild inlines the shared
|
||||||
// module into each bundle rather than emitting a shared chunk (no
|
// module into each bundle rather than emitting a shared chunk (no
|
||||||
// `splitting: true`). The Rust binary mounts `dist/` as a
|
// `splitting: true`). The Rust binary mounts `dist/` as a
|
||||||
// `tower_http::ServeDir` fallback (`append_index_html_on_directories`
|
// `tower_http::ServeDir` fallback (`append_index_html_on_directories`
|
||||||
// serves index.html at /); the layout above keeps every URL the HTML
|
// serves index.html at /); the dashboard SPA lives at /dashboard.html
|
||||||
// files reference reachable without rewriting paths in the HTML. The
|
// (a plain file, not a /dashboard/ prefix) so it never shadows the
|
||||||
// dashboard SPA lives at /dashboard.html (a plain file, not a /dashboard/
|
// exact-match /dashboard/stream + /dashboard/history SSE routes
|
||||||
// prefix) so it never shadows the exact-match /dashboard/stream +
|
// registered before the ServeDir fallback.
|
||||||
// /dashboard/history SSE routes registered before the ServeDir fallback.
|
|
||||||
|
|
||||||
import { build } from "esbuild";
|
import { build } from "esbuild";
|
||||||
import { mkdirSync, copyFileSync, rmSync } from "node:fs";
|
import { mkdirSync, copyFileSync, rmSync } from "node:fs";
|
||||||
|
|
@ -102,18 +68,17 @@ await build({
|
||||||
jsxImportSource: "preact",
|
jsxImportSource: "preact",
|
||||||
});
|
});
|
||||||
|
|
||||||
// Stream-worker entry (#448). Lives in a separate bundle: SharedWorker
|
// Stream-worker entry. Lives in a separate bundle: SharedWorker
|
||||||
// scripts run in a different global (`self` is the worker scope, no
|
// scripts run in a different global (`self` is the worker scope, no
|
||||||
// `window`) so they can't be inlined into tabs.js / flow.js. Output is
|
// `window`) so they can't be inlined into tabs.js / flow.js. Output is
|
||||||
// at `static/stream-worker.js`; common.js's `openStream` references
|
// at `static/stream-worker.js`; common.js's `openStream` references
|
||||||
// `/static/stream-worker.js` as the SharedWorker URL. `format: 'iife'`
|
// `/static/stream-worker.js` as the SharedWorker URL. `format: 'iife'`
|
||||||
// matches the classic-script load (`new SharedWorker(url, name)` with
|
// matches the classic-script load (`new SharedWorker(url, name)` with
|
||||||
// no `{ type: 'module' }`); Firefox is the #448 target and module
|
// no `{ type: 'module' }`); Firefox's module SharedWorker support is
|
||||||
// SharedWorker support there is patchy, so keeping the worker as a
|
// patchy, so keeping the worker as a classic script + IIFE bundle is
|
||||||
// classic script + IIFE bundle is the compatible default. argus nit
|
// the compatible default. argus's own review nit here: if a future
|
||||||
// on #453: if a future contributor adds an `import` to this bundle,
|
// contributor adds an `import` to this bundle, the IIFE format will
|
||||||
// the IIFE format will surface it as a build error rather than
|
// surface it as a build error rather than silently shipping broken code.
|
||||||
// silently shipping broken code.
|
|
||||||
await build({
|
await build({
|
||||||
entryPoints: [src("stream-worker.js")],
|
entryPoints: [src("stream-worker.js")],
|
||||||
outdir: staticDir(""),
|
outdir: staticDir(""),
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,38 @@
|
||||||
// esbuild build for @hive/swarm-ui (project-bootstrap scope). Output
|
// esbuild build for @hive/swarm-ui (project-bootstrap scope). Bundles
|
||||||
// layout (`dist/`):
|
// main.tsx + its companion CSS, theme.css, and swarm-ui.css into
|
||||||
|
// `dist/static/`, content-hashed (`[name]-[hash]`) so a redeploy's new
|
||||||
|
// bundle gets a new URL, then rewrites those real URLs into index.html
|
||||||
|
// and sw.js. See each output file's own name in the code below for what
|
||||||
|
// it's for — not repeated here to avoid this comment drifting out of
|
||||||
|
// sync with the actual build steps.
|
||||||
//
|
//
|
||||||
// dist/index.html served at GET /
|
// `colors.css` is the ONE static asset deliberately left UNHASHED, at a
|
||||||
// dist/static/main.js served at /static/main.js (ESM bundle,
|
// fixed `dist/static/colors.css`: nix/host-modules/swarm-ui.nix's stylix
|
||||||
// Preact + wouter-preact)
|
// theming swaps that exact path via an `= /static/colors.css` nginx
|
||||||
// dist/static/main.js.map source map sibling
|
// location override, no npm/esbuild rebuild involved. Hashing it would
|
||||||
// dist/static/main.css every component's own `import
|
// silently break that swap. See `colors.css`'s own top comment.
|
||||||
// './Foo.css'` (Shell.css, Panel.css, …),
|
|
||||||
// folded by esbuild into one companion
|
|
||||||
// output alongside main.js — no separate
|
|
||||||
// build step, this falls out of bundling
|
|
||||||
// main.tsx with `bundle: true`
|
|
||||||
// dist/static/colors.css served at /static/colors.css
|
|
||||||
// dist/static/theme.css served at /static/theme.css
|
|
||||||
// dist/static/swarm-ui.css served at /static/swarm-ui.css — just the
|
|
||||||
// shared base reset now (@import resolved
|
|
||||||
// from @hive/shared), NOT component styles
|
|
||||||
// dist/manifest.webmanifest served at /manifest.webmanifest (PWA)
|
|
||||||
// dist/sw.js served at /sw.js (PWA) — plain JS, no
|
|
||||||
// esbuild pass needed (see its own
|
|
||||||
// top comment for why); copied as-is.
|
|
||||||
//
|
//
|
||||||
// PWA icons (icon-192.png/icon-512.png/icon-512-maskable.png) are NOT
|
// `dist/sw.js` keeps its own fixed/unhashed filename too — the browser
|
||||||
// produced here — like favicon.svg, they're rasterized from
|
// polls this exact URL to detect a SW update, hashing it would make
|
||||||
// branding/*.svg and copied in by nix/packages/swarm-ui.nix's
|
// every deploy register as a brand new worker. Its `CACHE_VERSION`
|
||||||
// installPhase, outside the npm tree this script builds. A plain `npm
|
// placeholder and shell-asset URLs get rewritten below, same as
|
||||||
// run build` here has no `/icon-*.png`, same as it's always had no
|
// index.html's.
|
||||||
// `/favicon.svg`.
|
//
|
||||||
|
// PWA icons are NOT produced here — like favicon.svg, they're
|
||||||
|
// rasterized from branding/*.svg and copied in by
|
||||||
|
// nix/packages/swarm-ui.nix's installPhase, outside the npm tree this
|
||||||
|
// script builds.
|
||||||
//
|
//
|
||||||
// Not yet wired into any Rust binary's `ServeDir` — swarm-controller
|
// Not yet wired into any Rust binary's `ServeDir` — swarm-controller
|
||||||
// only serves `/health` today (see swarm-controller/README.md); this
|
// only serves `/health` today; this just makes `dist/` buildable so
|
||||||
// just makes `dist/` buildable so nix/packages/swarm-ui.nix has
|
// nix/packages/swarm-ui.nix has something to package. `.tsx` → JS:
|
||||||
// something to package. `.tsx` → JS: esbuild transpiles TypeScript
|
// esbuild transpiles TypeScript natively (types stripped, not checked)
|
||||||
// natively (types stripped, not checked) — run `npm run typecheck`
|
// — run `npm run typecheck` separately for real type errors.
|
||||||
// (plain `tsc --noEmit`) separately for real type errors; not yet
|
|
||||||
// wired into CI.
|
|
||||||
|
|
||||||
import { build } from "esbuild";
|
import { build } from "esbuild";
|
||||||
import { mkdirSync, copyFileSync, rmSync } from "node:fs";
|
import { mkdirSync, rmSync, readFileSync, writeFileSync } from "node:fs";
|
||||||
import { dirname, resolve } from "node:path";
|
import { createHash } from "node:crypto";
|
||||||
|
import { dirname, relative, resolve } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
const here = dirname(fileURLToPath(import.meta.url));
|
const here = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
@ -46,12 +40,23 @@ const src = (p) => resolve(here, "src", p);
|
||||||
const dist = (p) => resolve(here, "dist", p);
|
const dist = (p) => resolve(here, "dist", p);
|
||||||
const staticDir = (p) => resolve(here, "dist", "static", p);
|
const staticDir = (p) => resolve(here, "dist", "static", p);
|
||||||
|
|
||||||
|
// Every metafile path esbuild returns is relative to `absWorkingDir`
|
||||||
|
// (pinned to `here` on every build call below, regardless of the caller's
|
||||||
|
// own cwd) and always POSIX-style (`dist/static/main-<hash>.js`) — turn
|
||||||
|
// one into the URL nginx actually serves it at. A plain prefix strip, not
|
||||||
|
// `path.relative`: the latter resolves a relative argument against
|
||||||
|
// `process.cwd()`, which is exactly the caller-cwd dependency pinning
|
||||||
|
// `absWorkingDir` on every build call below was meant to avoid.
|
||||||
|
const toUrl = (metafilePath) => "/" + metafilePath.replace(/^dist\//, "");
|
||||||
|
|
||||||
rmSync(dist(""), { recursive: true, force: true });
|
rmSync(dist(""), { recursive: true, force: true });
|
||||||
mkdirSync(staticDir(""), { recursive: true });
|
mkdirSync(staticDir(""), { recursive: true });
|
||||||
|
|
||||||
await build({
|
const mainResult = await build({
|
||||||
|
absWorkingDir: here,
|
||||||
entryPoints: [src("main.tsx")],
|
entryPoints: [src("main.tsx")],
|
||||||
outfile: staticDir("main.js"),
|
outdir: staticDir(""),
|
||||||
|
entryNames: "[name]-[hash]",
|
||||||
bundle: true,
|
bundle: true,
|
||||||
format: "esm",
|
format: "esm",
|
||||||
platform: "browser",
|
platform: "browser",
|
||||||
|
|
@ -60,20 +65,103 @@ await build({
|
||||||
logLevel: "info",
|
logLevel: "info",
|
||||||
jsx: "automatic",
|
jsx: "automatic",
|
||||||
jsxImportSource: "preact",
|
jsxImportSource: "preact",
|
||||||
|
metafile: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const entry of ["colors.css", "theme.css", "swarm-ui.css"]) {
|
// Look up a build's real output path for one of its entry points, by the
|
||||||
await build({
|
// entry's own source path — rather than guessing esbuild's hash
|
||||||
entryPoints: [src(entry)],
|
// algorithm or assuming an output ordering. `entryPoint` in the metafile
|
||||||
outfile: staticDir(entry),
|
// is relative to `absWorkingDir` (`here`, pinned on every build call
|
||||||
|
// below); `path.relative` with two absolute arguments never touches
|
||||||
|
// `process.cwd()`, so this is stable regardless of the caller's own cwd.
|
||||||
|
const outputFor = (result, entrySrcPath) => {
|
||||||
|
const wantEntry = relative(here, entrySrcPath);
|
||||||
|
const found = Object.entries(result.metafile.outputs).find(
|
||||||
|
([, o]) => o.entryPoint === wantEntry,
|
||||||
|
);
|
||||||
|
if (!found) {
|
||||||
|
throw new Error(
|
||||||
|
`esbuild produced no output for entry point ${wantEntry} -- ` +
|
||||||
|
"either it failed silently or the metafile's entryPoint " +
|
||||||
|
"convention changed; update outputFor() to match.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
};
|
||||||
|
|
||||||
|
// main.tsx's bundle: the JS entry itself, plus its companion CSS output
|
||||||
|
// (`cssBundle` — every component's own `import './Foo.css'`, folded into
|
||||||
|
// one file alongside the JS, same as before this hashed).
|
||||||
|
const [mainJsPath, mainJsInfo] = outputFor(mainResult, src("main.tsx"));
|
||||||
|
if (!mainJsInfo.cssBundle) {
|
||||||
|
throw new Error(
|
||||||
|
"main.tsx produced no companion CSS bundle -- index.html/sw.js still " +
|
||||||
|
"reference /static/main.css, so this build can no longer keep that " +
|
||||||
|
"promise. Either a component's own CSS import got removed, or " +
|
||||||
|
"esbuild's output shape changed; update both the build and the " +
|
||||||
|
"files that reference /static/main.css together.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const mainJsUrl = toUrl(mainJsPath);
|
||||||
|
const mainCssUrl = toUrl(mainJsInfo.cssBundle);
|
||||||
|
|
||||||
|
// theme.css / swarm-ui.css: hashed, same as main.tsx above. colors.css is
|
||||||
|
// deliberately NOT in this list — see the top comment's explanation of
|
||||||
|
// why it stays at a fixed path.
|
||||||
|
const hashedCssResult = await build({
|
||||||
|
absWorkingDir: here,
|
||||||
|
entryPoints: [src("theme.css"), src("swarm-ui.css")],
|
||||||
|
outdir: staticDir(""),
|
||||||
|
entryNames: "[name]-[hash]",
|
||||||
bundle: true,
|
bundle: true,
|
||||||
loader: { ".css": "css" },
|
loader: { ".css": "css" },
|
||||||
logLevel: "info",
|
logLevel: "info",
|
||||||
});
|
metafile: true,
|
||||||
}
|
});
|
||||||
|
const themeCssUrl = toUrl(outputFor(hashedCssResult, src("theme.css"))[0]);
|
||||||
|
const swarmUiCssUrl = toUrl(outputFor(hashedCssResult, src("swarm-ui.css"))[0]);
|
||||||
|
|
||||||
copyFileSync(src("index.html"), dist("index.html"));
|
// colors.css: fixed, unhashed path — see the top comment.
|
||||||
copyFileSync(src("manifest.webmanifest"), dist("manifest.webmanifest"));
|
await build({
|
||||||
copyFileSync(src("sw.js"), dist("sw.js"));
|
absWorkingDir: here,
|
||||||
|
entryPoints: [src("colors.css")],
|
||||||
|
outfile: staticDir("colors.css"),
|
||||||
|
bundle: true,
|
||||||
|
loader: { ".css": "css" },
|
||||||
|
logLevel: "info",
|
||||||
|
});
|
||||||
|
|
||||||
|
// A build-derived cache-bust version for sw.js's own CACHE_NAME: any
|
||||||
|
// change to any hashed shell-asset URL (a real content change, or an
|
||||||
|
// asset added/removed) changes this, which changes CACHE_NAME, which
|
||||||
|
// makes the SW's own `activate` handler evict the old cache in full —
|
||||||
|
// no more hand-bumping a CACHE_VERSION const on every shell change.
|
||||||
|
const buildVersion = createHash("sha256")
|
||||||
|
.update(JSON.stringify([mainJsUrl, mainCssUrl, themeCssUrl, swarmUiCssUrl]))
|
||||||
|
.digest("hex")
|
||||||
|
.slice(0, 12);
|
||||||
|
|
||||||
|
const rewriteAssetUrls = (text) =>
|
||||||
|
text
|
||||||
|
.replaceAll("/static/main.js", mainJsUrl)
|
||||||
|
.replaceAll("/static/main.css", mainCssUrl)
|
||||||
|
.replaceAll("/static/theme.css", themeCssUrl)
|
||||||
|
.replaceAll("/static/swarm-ui.css", swarmUiCssUrl);
|
||||||
|
|
||||||
|
writeFileSync(
|
||||||
|
dist("index.html"),
|
||||||
|
rewriteAssetUrls(readFileSync(src("index.html"), "utf8")),
|
||||||
|
);
|
||||||
|
writeFileSync(
|
||||||
|
dist("sw.js"),
|
||||||
|
rewriteAssetUrls(readFileSync(src("sw.js"), "utf8")).replace(
|
||||||
|
'"__BUILD_VERSION__"',
|
||||||
|
JSON.stringify(buildVersion),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
writeFileSync(
|
||||||
|
dist("manifest.webmanifest"),
|
||||||
|
readFileSync(src("manifest.webmanifest")),
|
||||||
|
);
|
||||||
|
|
||||||
console.log("swarm-ui build ok →", dist(""));
|
console.log("swarm-ui build ok →", dist(""));
|
||||||
|
|
|
||||||
|
|
@ -7,26 +7,27 @@
|
||||||
// a cached fetch would be worse than showing nothing (mara: "scope looks
|
// a cached fetch would be worse than showing nothing (mara: "scope looks
|
||||||
// good" — approving that as a hard rule, not a short-TTL middle ground).
|
// good" — approving that as a hard rule, not a short-TTL middle ground).
|
||||||
//
|
//
|
||||||
// Network-first for the shell, not cache-first: `main.js`/`main.css` are
|
// Network-first for the shell, not cache-first: most assets below are
|
||||||
// unhashed filenames, so a cache-first strategy would risk wedging an
|
// content-hashed (a fresh URL per deploy, so a normal visit always gets
|
||||||
// operator on yesterday's JS after a deploy until they manually cleared
|
// the current bundle regardless of this SW), but `colors.css` stays
|
||||||
// it (a deploy changes the nix store path serving these but not the URL
|
// deliberately unhashed for the host-side stylix theme swap, so this
|
||||||
// the browser cached against — a separate, already-filed fix). This SW
|
// SW's own cached copy of it can only ever refresh via a real network
|
||||||
// only ever serves its cache on a FAILED fetch (offline/flaky network),
|
// round-trip. This SW only ever serves its cache on a FAILED fetch
|
||||||
// never in preference to a successful network response.
|
// (offline/flaky network), never in preference to a live response.
|
||||||
//
|
//
|
||||||
// Plain JS, not TypeScript, deliberately — the DOM lib swarm-ui's own
|
// Plain JS, not TypeScript, deliberately — the DOM lib swarm-ui's own
|
||||||
// tsconfig uses and the WebWorker lib a service worker's globals
|
// tsconfig uses and the WebWorker lib a service worker's globals need
|
||||||
// (`self`, `ExtendableEvent`, `FetchEvent`, `caches`, ...) need are
|
// (`self`, `ExtendableEvent`, `FetchEvent`, `caches`, ...) are mutually
|
||||||
// mutually exclusive in one tsc program, and this file is small/
|
// exclusive in one tsc program, and this file is small enough that a
|
||||||
// self-contained enough that a second tsconfig just to typecheck it
|
// second tsconfig just to typecheck it isn't worth the config surface.
|
||||||
// isn't worth the config surface. Same treatment `build.mjs` already
|
// Same treatment `build.mjs` already gets in this package.
|
||||||
// gets in this package.
|
|
||||||
//
|
//
|
||||||
// CACHE_VERSION is bumped by hand for now — once the filenames above are
|
// CACHE_VERSION is filled in by build.mjs from a hash of every hashed
|
||||||
// content-hashed, the cache name can derive from the build itself and
|
// shell-asset URL below, so any real content change gets a fresh cache
|
||||||
// this manual step goes away.
|
// name and `activate`'s old-cache sweep evicts the previous one in
|
||||||
const CACHE_VERSION = "v1";
|
// full. This literal placeholder is never served; the build always
|
||||||
|
// replaces it.
|
||||||
|
const CACHE_VERSION = "__BUILD_VERSION__";
|
||||||
const CACHE_NAME = `swarm-ui-shell-${CACHE_VERSION}`;
|
const CACHE_NAME = `swarm-ui-shell-${CACHE_VERSION}`;
|
||||||
|
|
||||||
// Every navigation (any client-side route wouter handles — /agents,
|
// Every navigation (any client-side route wouter handles — /agents,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
# exceeds MAX. Runs as its own CI job and IS a required check on the forge
|
# exceeds MAX. Runs as its own CI job and IS a required check on the forge
|
||||||
# (branch protection) — a hit blocks merge.
|
# (branch protection) — a hit blocks merge.
|
||||||
#
|
#
|
||||||
# Scope: tracked *.rs *.nix *.sh *.js *.ts *.tsx *.css *.html. Markdown is exempt
|
# Scope: tracked *.rs *.nix *.sh *.js *.mjs *.ts *.tsx *.css *.html. Markdown is exempt
|
||||||
# (it is prose by nature). Comment forms: `#` line comments (nix/sh), `//`
|
# (it is prose by nature). Comment forms: `#` line comments (nix/sh), `//`
|
||||||
# line comments (rs/js/ts), and `/* */` block comments (nix/rs/js/ts/css) +
|
# line comments (rs/js/ts), and `/* */` block comments (nix/rs/js/ts/css) +
|
||||||
# `<!-- -->` (html). A blank line separates two line-comment blocks (does NOT
|
# `<!-- -->` (html). A blank line separates two line-comment blocks (does NOT
|
||||||
|
|
@ -23,12 +23,12 @@ MAX=30
|
||||||
# Collect annotations into a variable (not via xargs/awk exit codes) so a
|
# Collect annotations into a variable (not via xargs/awk exit codes) so a
|
||||||
# hit in any xargs batch is preserved — mirrors scripts/check-issue-refs.sh.
|
# hit in any xargs batch is preserved — mirrors scripts/check-issue-refs.sh.
|
||||||
hits="$(
|
hits="$(
|
||||||
git ls-files -z '*.rs' '*.nix' '*.sh' '*.js' '*.ts' '*.tsx' '*.css' '*.html' \
|
git ls-files -z '*.rs' '*.nix' '*.sh' '*.js' '*.mjs' '*.ts' '*.tsx' '*.css' '*.html' \
|
||||||
| xargs -0 -r awk -v MAX="$MAX" '
|
| xargs -0 -r awk -v MAX="$MAX" '
|
||||||
function mode_of(fn) {
|
function mode_of(fn) {
|
||||||
if (fn ~ /\.nix$/) return "nix"
|
if (fn ~ /\.nix$/) return "nix"
|
||||||
if (fn ~ /\.sh$/) return "hash"
|
if (fn ~ /\.sh$/) return "hash"
|
||||||
if (fn ~ /\.(rs|js|ts|tsx)$/) return "slash"
|
if (fn ~ /\.(rs|js|mjs|ts|tsx)$/) return "slash"
|
||||||
if (fn ~ /\.css$/) return "cstyle"
|
if (fn ~ /\.css$/) return "cstyle"
|
||||||
if (fn ~ /\.html$/) return "html"
|
if (fn ~ /\.html$/) return "html"
|
||||||
return ""
|
return ""
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@
|
||||||
# Emits a CI error annotation per hit, exits 1 if any hit is found. Its own
|
# Emits a CI error annotation per hit, exits 1 if any hit is found. Its own
|
||||||
# required CI job (branch protection) — a hit blocks merge.
|
# required CI job (branch protection) — a hit blocks merge.
|
||||||
#
|
#
|
||||||
# Scope: every tracked `*.rs *.nix *.js *.ts *.tsx *.css *.html *.md *.yml
|
# Scope: every tracked `*.rs *.nix *.js *.mjs *.ts *.tsx *.css *.html *.md
|
||||||
# *.yaml`. CI workflow files (`.forgejo/workflows/*.yml`) are explicitly in
|
# *.yml *.yaml`. CI workflow files (`.forgejo/workflows/*.yml`) are explicitly in
|
||||||
# scope: a step comment is still a comment. The pattern matches a hash,
|
# scope: a step comment is still a comment. The pattern matches a hash,
|
||||||
# 2-5 digits, then a non-alphanumeric char or end-of-line (skips
|
# 2-5 digits, then a non-alphanumeric char or end-of-line (skips
|
||||||
# letter-bearing hex colours and digit-runs-then-letter, e.g. `#24h`;
|
# letter-bearing hex colours and digit-runs-then-letter, e.g. `#24h`;
|
||||||
|
|
@ -33,7 +33,7 @@ pattern='#[0-9]{2,5}([^0-9a-zA-Z]|$)|/issues/[0-9]+([^0-9a-zA-Z]|$)'
|
||||||
# an empty file list. Lines carrying the `lint:allow` marker are dropped
|
# an empty file list. Lines carrying the `lint:allow` marker are dropped
|
||||||
# (legitimate non-tracker hit; see the header).
|
# (legitimate non-tracker hit; see the header).
|
||||||
hits="$(
|
hits="$(
|
||||||
git ls-files -z '*.rs' '*.nix' '*.js' '*.ts' '*.tsx' '*.css' '*.html' '*.md' \
|
git ls-files -z '*.rs' '*.nix' '*.js' '*.mjs' '*.ts' '*.tsx' '*.css' '*.html' '*.md' \
|
||||||
'*.yml' '*.yaml' \
|
'*.yml' '*.yaml' \
|
||||||
| xargs -0 -r grep -nE "$pattern" /dev/null 2>/dev/null \
|
| xargs -0 -r grep -nE "$pattern" /dev/null 2>/dev/null \
|
||||||
| grep -v 'lint:allow' || true
|
| grep -v 'lint:allow' || true
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue