Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,22 @@ jobs:
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
# `git diff --check` with no args compares the working tree against the index -- on this checkout's
# default shallow, single-commit fetch they're always identical immediately after checkout, so this
# unconditionally passed regardless of what the PR's actual diff contained (a false-green: the step
# promised a whitespace check that never fired). Fetch just the one comparison SHA (still shallow,
# cheap) and diff against it directly instead. On push (github.event.before can be the null SHA for
# a branch's first push -- not reachable for `main` itself, but kept defensive) or when the fetch
# target isn't resolvable, skip rather than fail the whole pipeline over a best-effort check.
- name: Check whitespace
run: git diff --check
run: |
BASE_SHA="${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}"
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
echo "No comparison SHA available (e.g. branch's first push) -- skipping."
exit 0
fi
git fetch --depth=1 origin "$BASE_SHA"
git diff --check "$BASE_SHA" HEAD
- name: Filter changed paths
id: filter
uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4
Expand Down Expand Up @@ -244,13 +258,12 @@ jobs:
node_modules
apps/loopover-ui/node_modules
key: ${{ steps.node-modules-cache.outputs.cache-primary-key }}
# apps/loopover-ui/.source (fumadocs-mdx codegen -- the collections/* alias
# apps/loopover-ui/tsconfig.json depends on) lives outside node_modules and is normally produced by
# npm ci's own postinstall. A node_modules cache hit above skips npm ci entirely, so .source/ would
# otherwise never exist on a cache-hit run. Regenerate it explicitly and unconditionally: cheap,
# deterministic, and a harmless no-op re-run of the same postinstall on a cache miss.
- name: Generate fumadocs content-collection sources
run: npm --workspace @loopover/ui run postinstall
# apps/loopover-ui/.source (fumadocs-mdx codegen) is regenerated by "Generate docs content
# collections" below, gated on push||ui==true -- nothing between here and there reads it (docs-drift,
# env-reference, manifest/engine-parity/branding-drift checks all read raw source files directly, and
# the root Typecheck step's tsconfig.json excludes apps/loopover-ui entirely), so it doesn't need to
# be regenerated unconditionally this early too (a prior version of this step duplicated that one,
# added independently and unconditionally before either author noticed the other already existed).
- name: Lint workflows
if: ${{ github.event_name == 'push' || needs.changes.outputs.backend == 'true' }}
run: npm run actionlint
Expand Down Expand Up @@ -497,15 +510,23 @@ jobs:
- name: Generate docs content collections
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
run: npm run postinstall --workspace @loopover/ui
# ui:lint/ui:typecheck/ui:test (package.json) each independently re-run ui:kit:build as their own
# first step -- correct as standalone, portable scripts (nothing else in a bare `npm run ui:lint`
# invocation would have built ui-kit first), but redundant here specifically: "Build UI-kit package"
# above already built it once for all four of lint/typecheck/tests/build in this same job. Same
# "call the underlying subcommands directly, skip the redundant rebuild" fix "UI build" below
# already applies -- deliberately NOT changing the package.json scripts themselves, since
# ui-deploy.yml and CONTRIBUTING.md's documented local gate sequence both call ui:lint/ui:typecheck
# directly with no prior ui-kit build step and rely on that self-sufficiency.
- name: UI lint
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
run: npm run ui:lint
run: npm --workspace @loopover/ui run lint && npm --workspace @loopover/ui-miner run lint
- name: UI typecheck
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
run: npm run ui:typecheck
run: npm --workspace @loopover/ui run typecheck && npm --workspace @loopover/ui-miner run typecheck
- name: UI tests
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
run: npm run ui:test
run: npm --workspace @loopover/ui run test && npm --workspace @loopover/ui-miner run test && npm --workspace @loopover/miner-extension run test
- name: Extension lint
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
run: npm run extension:lint && npm run miner-extension:lint
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/ui-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,15 @@ on:
# build job below skips draft PRs, marking a PR ready must itself trigger a real preview build (#6670),
# not wait for the next push. Mirrors ci.yml's pull_request.types comment/list exactly.
types: [opened, synchronize, reopened, ready_for_review]
# Scoped to exactly what apps/loopover-ui actually depends on (packages/loopover-ui-kit only) --
# NOT the whole "packages/**" workspace, which also matches loopover-miner/loopover-mcp/loopover-engine/
# discovery-index and previously built+deployed a pointless preview for every PR touching those (#ci-scope).
# This check isn't required (see branch protection), so a future package apps/loopover-ui starts
# depending on that isn't added here will silently stop getting previews rather than failing loud --
# keep this list in sync with what apps/loopover-ui/package.json actually imports.
paths:
- "apps/loopover-ui/**"
- "packages/**"
- "packages/loopover-ui-kit/**"

permissions:
contents: read
Expand Down
10 changes: 9 additions & 1 deletion packages/loopover-engine/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@
"declaration": true,
"rootDir": "src",
"outDir": "dist",
"noEmit": false
"noEmit": false,
// Without this, the inherited root value (tsconfig.json:24, "./.tsbuildinfo") resolves relative to
// the ROOT config's location, not this one -- this package's build and the root Typecheck step would
// then read/write the exact same cache file at the repo root and corrupt each other's incremental
// state (the same collision packages/loopover-miner/tsconfig.json already documents and fixes the
// same way). Currently masked in CI by step order (the root cache restore always runs after this
// package's build and overwrites whatever it just wrote, before Typecheck reads it) -- but that
// makes the inherited value a landmine for the next reordering, not a working fix.
"tsBuildInfoFile": "./.tsbuildinfo"
},
"include": ["src"],
"exclude": ["src/signals/engine.ts"]
Expand Down
8 changes: 7 additions & 1 deletion packages/loopover-engine/tsconfig.test.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@
"rootDir": "test",
"outDir": "dist-test",
"declaration": false,
"noEmit": false
"noEmit": false,
// Distinct from tsconfig.json's own "./.tsbuildinfo" (this config extends that file, so without an
// override here it would inherit the SAME explicit path -- two different rootDir/outDir/include sets
// sharing one incremental-state file, corrupting each other exactly like the collision this fixes).
// Named to END in ".tsbuildinfo" (not start with it) so it's still matched by .gitignore's existing
// "*.tsbuildinfo" glob -- ".tsbuildinfo-test" would NOT match that pattern and would leak as untracked.
"tsBuildInfoFile": "./.test.tsbuildinfo"
},
"include": ["test"]
}