mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-06 02:49:56 +00:00
Some checks failed
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (push) Blocked by required conditions
Publish / ci (push) Blocked by required conditions
Publish / Publish to npm (push) Blocked by required conditions
Publish / Build & Push RC Docker images (push) Blocked by required conditions
Scorecard / Scorecard analysis (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
Devcontainer Smoke / Config-transform unit tests (push) Has been cancelled
Devcontainer Smoke / Build devcontainer image (push) Has been cancelled
* fix(search): index description column for FTS so doc comments are keyword-searchable Closes #2299. descriptionExtractor (#2286) populates the `description` column for every symbol table, but FTS only indexed name+content on 5 tables, so doc-comment keywords (Javadoc/KDoc/godoc/Rust ///) were invisible to BM25 keyword search. - Add `description` to the Function/Class/Method/Interface FTS indexes (File has no description column, left as name+content). - Add FTS indexes for the remaining EMBEDDABLE_LABELS symbol tables (Struct, Enum, Trait, Impl, Macro, Namespace, Constructor, TypeAlias, Typedef, Const, Property, Record, Union, Static, Variable). - createSearchFTSIndexes now drops-then-creates each index so the schema change reaches existing DBs on incremental re-analyze and --repair-fts (createFTSIndex is idempotent-by-name and would otherwise skip stale indexes). Tests: fts-schema column-subset + coverage guards; drop-before-create order; e2e doc-comment keyword search (Java class + Rust struct found by description-only terms). bm25-search assertions derive from FTS_INDEXES. * fix(review): apply autofix feedback - Guard the --repair-fts path on FTS-extension availability before createSearchFTSIndexes drops-then-creates indexes (P1 regression: without the gate, an unavailable extension could drop existing indexes then fail to recreate them, leaving the DB index-less). Mirrors the analyze path's ftsAvailable gate and fails loudly first. - Add a re-analyze upgrade integration test: seed an old name+content-only DB (no Struct index), run the real createSearchFTSIndexes(), and assert description keyword search + the previously un-indexed Struct now resolve. Proves drop-then-create upgrades a live stale index end-to-end. * fix(ci): add loadFTSExtension to --repair-fts test mocks The R3 review fix added a loadFTSExtension availability gate to the --repair-fts path, but run-analyze-fts-repair.test.ts mocked the lbug adapter without that export, so both repair tests threw `No "loadFTSExtension" export`. Add loadFTSExtension to the two mocks (returning true to preserve their original intent) and add a dedicated test proving the guard fails loudly — and does NOT drop any index — when the extension is unavailable. * test(fts): run fts-description-search in the sequential lbug-db project It was the only FTS-index-creating integration test left in the parallel `default` vitest project; every other ftsIndexes-using test (search-core, search-pool, augmentation, …) runs in the `lbug-db` project, which forces fileParallelism: false to avoid LadybugDB native mmap file-lock conflicts in parallel forks (Windows). Add it to the lbug-db include list and the default exclude list to match the convention and remove the flake risk. * test(ci): fail loudly when FTS extension is unavailable, never silently skip FTS-dependent lbug integration suites (search-core, search-pool, augmentation, fts-description-search, …) self-skip via ctx.skip() when the LadybugDB FTS extension can't load, emitting only a console.warn while the job stays green. That means a broken/missing FTS extension in CI would make these integration tests silently vanish with no signal — false confidence. withTestLbugDB now honors GITNEXUS_REQUIRE_FTS=1: when set and the extension is unavailable, setup() throws instead of skipping, so the suite fails loudly. The CI test jobs (ubuntu coverage + windows/macOS cross-platform) set the flag; local/offline runs leave it unset and keep skipping gracefully. (Verified the extension currently loads on all three runners, so this is a guard against regression, not a behavior change today.) * test(ci): run fts-description-search on macOS/Windows cross-platform jobs The new FTS description-search suite was registered in the sequential lbug-db vitest project (ubuntu/coverage) but absent from LBUG_NATIVE, so the macOS/Windows platform-sensitive jobs (which run only the explicit ALL_CROSS_PLATFORM allowlist via run-cross-platform.ts) never executed it. The GITNEXUS_REQUIRE_FTS=1 hardening on those jobs guarded the old FTS fixtures but not the new 20-index/description path. Add the suite to LBUG_NATIVE so the new path is validated cross-platform too. Refs #2299. * fix(search): verify FTS indexes cover description, not just queryability verifySearchFTSIndexes probed each index with QUERY_FTS_INDEX and treated 'queryable' as 'present'. A stale name+content-only index left on a pre-#2299 DB stays queryable yet silently misses the description column, so verification would pass green while doc-comment search stayed broken. Switch to a single CALL SHOW_INDEXES() that exposes property_names per index, and report an index as missing when it is absent OR does not cover its configured columns. Return contract (string[] of table.indexName) is unchanged, so both run-analyze.ts call sites are untouched. The per-index string interpolation is gone, so the now-dead safeIdentifier helper is removed. The real caller of the live function in tests is bm25-search.test.ts (the repair test mocks verifySearchFTSIndexes wholesale); its two probe-shaped cases are rewritten to feed SHOW_INDEXES rows and now assert column coverage, plus an absent-index case. Refs #2299. * test(search): assert description search via the public query surface The #2299 integration suite only exercised the searchFTSFromLbug helper. Add a third block that drives the public LocalBackend.callTool('query') path — which resolves the repo via the registry and routes BM25 through the pool adapter (a different connection context than the core-adapter helper) — and asserts a description-only keyword returns the seeded class. Reuses the existing description-only SEED and production FTS_INDEXES; partial-mocks repo-manager so listRegisteredRepos points at the test DB while cleanupOldKuzuFiles and the rest stay real. Refs #2299. * test(search): make lbug-core-adapter FTS gate honor GITNEXUS_REQUIRE_FTS lbug-core-adapter.test.ts has its own per-test FTS gate (skipUnlessFtsAvailable) that called ctx.skip() whenever the extension could not load — bypassing the GITNEXUS_REQUIRE_FTS=1 hardening that withTestLbugDB already honors. Since this file is in LBUG_NATIVE it runs on the ubuntu/macOS/windows jobs that all set GITNEXUS_REQUIRE_FTS=1, so an FTS regression on a runner would have let these FTS-primitive tests silently vanish from a green run — the exact gap #2299's test-infra hardening set out to close. Make the helper mirror withTestLbugDB: when GITNEXUS_REQUIRE_FTS=1 and the extension is unavailable, throw (hard fail) instead of skipping. Offline/local runs (no env var) still skip gracefully. Refs #2299.
317 lines
13 KiB
YAML
317 lines
13 KiB
YAML
name: Tests
|
|
|
|
on:
|
|
workflow_call:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
tests:
|
|
name: ubuntu / coverage
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 25
|
|
# Fail loudly (don't silently skip) if the FTS extension is unavailable, so
|
|
# FTS-dependent lbug integration suites are guaranteed to run in CI.
|
|
env:
|
|
GITNEXUS_REQUIRE_FTS: '1'
|
|
steps:
|
|
# persist-credentials: false — this job runs tests and uploads a
|
|
# test-reports artifact (if: always()). The default-persisted token in
|
|
# .git/config must not be capturable through that upload (zizmor
|
|
# credential-persistence / artipacked audit). The job never pushes.
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
- uses: ./.github/actions/setup-gitnexus
|
|
with:
|
|
build: 'true'
|
|
|
|
- name: Run all tests with coverage
|
|
run: >-
|
|
npx vitest run
|
|
--reporter=default
|
|
--reporter=json
|
|
--outputFile=test-results.json
|
|
--coverage
|
|
--coverage.reporter=json-summary
|
|
--coverage.reporter=json
|
|
--coverage.reporter=text
|
|
--coverage.thresholdAutoUpdate=false
|
|
--coverage.reportOnFailure=true
|
|
working-directory: gitnexus
|
|
|
|
# gitnexus-shared already built by setup-gitnexus action above
|
|
- name: Install gitnexus-web dependencies
|
|
run: npm ci
|
|
working-directory: gitnexus-web
|
|
|
|
- name: Run gitnexus-web unit tests
|
|
run: >-
|
|
npx vitest run
|
|
--reporter=default
|
|
--reporter=json
|
|
--outputFile=web-test-results.json
|
|
working-directory: gitnexus-web
|
|
|
|
- name: Run docker-server integration tests
|
|
run: node --test docker-server.test.mjs
|
|
|
|
- name: Upload test reports
|
|
if: always()
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: test-reports
|
|
path: |
|
|
gitnexus/coverage/coverage-summary.json
|
|
gitnexus/coverage/coverage-final.json
|
|
gitnexus/test-results.json
|
|
gitnexus-web/web-test-results.json
|
|
retention-days: 5
|
|
|
|
# Platform-sensitive subset only — the full suite runs on Ubuntu above.
|
|
# See gitnexus/scripts/cross-platform-tests.ts for the file list and
|
|
# rationale for each included test.
|
|
cross-platform:
|
|
name: ${{ matrix.os }} (platform-sensitive)
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
# Ubuntu already covered by the coverage job above
|
|
os: [windows-latest, macos-latest]
|
|
runs-on: ${{ matrix.os }}
|
|
timeout-minutes: 20
|
|
# Same guarantee on the platform-sensitive runners: FTS-dependent suites in
|
|
# the cross-platform subset must run, not silently skip.
|
|
env:
|
|
GITNEXUS_REQUIRE_FTS: '1'
|
|
steps:
|
|
# persist-credentials: false — runs tests only, never pushes (zizmor
|
|
# credential-persistence / artipacked audit).
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
- uses: ./.github/actions/setup-gitnexus
|
|
with:
|
|
build: 'true'
|
|
- name: Run platform-sensitive tests
|
|
run: npx tsx scripts/run-cross-platform.ts
|
|
working-directory: gitnexus
|
|
|
|
# Tree-sitter ABI gate (#1922). Two halves, both blocking:
|
|
# 1. Static, offline: assert every grammar's compiled ABI loads on the
|
|
# pinned runtime (check-tree-sitter-upgrade-readiness.py --assert-current).
|
|
# 2. Dynamic: run the parser-loader ABI load-smoke on the OS matrix so an
|
|
# ABI-incompatible committed vendor prebuilt (e.g. Swift's — the static
|
|
# check introspects source, not the shipped .node) fails on the platform
|
|
# it ships to.
|
|
abi-assert:
|
|
name: tree-sitter ABI (${{ matrix.os }})
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
runs-on: ${{ matrix.os }}
|
|
timeout-minutes: 20
|
|
steps:
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
- uses: ./.github/actions/setup-gitnexus
|
|
with:
|
|
build: 'true'
|
|
|
|
- name: Assert installed + vendored grammar ABIs (static)
|
|
shell: bash
|
|
run: python3 .github/scripts/check-tree-sitter-upgrade-readiness.py --assert-current
|
|
|
|
- name: Run parser-loader ABI load-smoke (dynamic)
|
|
run: npx vitest run test/unit/parser-loader-abi.test.ts
|
|
working-directory: gitnexus
|
|
|
|
# End-to-end smoke test for the #1728 packaging fix: pack the published
|
|
# tarball, install it globally into a temp prefix, and assert no junction
|
|
# creation (the EPERM root cause) plus working CLI plus vendor cleanliness
|
|
# (#836). Runs on windows-latest because that is the platform the fix
|
|
# targets; the in-repo `npm ci` job above only exercises the dev-tree path
|
|
# and skips the tarball reify step where the historical EPERM occurred.
|
|
packaged-install-smoke:
|
|
name: packaged install smoke (${{ matrix.os }})
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [windows-latest, ubuntu-latest]
|
|
runs-on: ${{ matrix.os }}
|
|
timeout-minutes: 15
|
|
steps:
|
|
# persist-credentials: false — this job runs npm pack + npm install -g
|
|
# from a tarball and never pushes back; the token in .git/config would
|
|
# be at risk of leaking through any future artifact-upload step
|
|
# (zizmor artipacked audit). Disable upfront.
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
- uses: ./.github/actions/setup-gitnexus
|
|
with:
|
|
build: 'true'
|
|
|
|
- name: Pack gitnexus tarball
|
|
shell: bash
|
|
run: npm pack
|
|
working-directory: gitnexus
|
|
|
|
- name: Install gitnexus tarball into isolated prefix
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
PREFIX="$RUNNER_TEMP/gitnexus-smoke"
|
|
mkdir -p "$PREFIX"
|
|
TARBALL=$(find . -maxdepth 1 -name 'gitnexus-*.tgz' -print -quit)
|
|
if [ -z "$TARBALL" ]; then
|
|
echo "ERROR: no gitnexus-*.tgz tarball found in $(pwd)" >&2
|
|
exit 1
|
|
fi
|
|
echo "Installing $TARBALL into $PREFIX"
|
|
npm install -g --prefix "$PREFIX" "./$TARBALL" --no-audit --no-fund
|
|
echo "PREFIX=$PREFIX" >> "$GITHUB_ENV"
|
|
working-directory: gitnexus
|
|
|
|
- name: Assert no junctions or vendor build artifacts
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
# Locate the installed gitnexus package across npm prefix layouts
|
|
# (lib/node_modules on POSIX, node_modules on Windows).
|
|
for candidate in "$PREFIX/lib/node_modules/gitnexus" "$PREFIX/node_modules/gitnexus"; do
|
|
if [ -d "$candidate" ]; then
|
|
INSTALLED="$candidate"
|
|
break
|
|
fi
|
|
done
|
|
if [ -z "${INSTALLED:-}" ]; then
|
|
echo "ERROR: installed gitnexus package not found under $PREFIX" >&2
|
|
ls -la "$PREFIX" || true
|
|
exit 1
|
|
fi
|
|
echo "Installed package at: $INSTALLED"
|
|
|
|
# #836 invariant: no node_modules/ or build/ under any vendor/*.
|
|
BAD=$(find "$INSTALLED/vendor" \( -name node_modules -o -name build \) -print 2>/dev/null || true)
|
|
if [ -n "$BAD" ]; then
|
|
echo "ERROR: vendor tree contains forbidden build artifacts (#836):" >&2
|
|
echo "$BAD" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# #1728 invariant: materialized grammar dirs are real directories,
|
|
# not junctions/symlinks (which is what the EPERM regression created).
|
|
for name in tree-sitter-dart tree-sitter-proto tree-sitter-swift; do
|
|
entry="$INSTALLED/node_modules/$name"
|
|
if [ ! -e "$entry" ]; then
|
|
echo "WARN: $name not materialized (toolchain/prebuild may be unavailable on $RUNNER_OS)"
|
|
continue
|
|
fi
|
|
if [ -L "$entry" ]; then
|
|
echo "ERROR: $entry is a symlink/junction — #1728 regression" >&2
|
|
exit 1
|
|
fi
|
|
if [ ! -d "$entry" ]; then
|
|
echo "ERROR: $entry is not a directory" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
- name: Assert gitnexus --version works
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if [ "$RUNNER_OS" = "Windows" ]; then
|
|
"$PREFIX/gitnexus.cmd" --version
|
|
else
|
|
"$PREFIX/bin/gitnexus" --version
|
|
fi
|
|
|
|
# ── Dedicated benchmark gate ─────────────────────────────────────
|
|
# The cross-language `*-pipeline-benchmark.test.ts` suites are gated behind
|
|
# GITNEXUS_BENCH (they generate synthetic codebases at scale), so the main
|
|
# coverage job above SKIPS them — their O(n^2) scaling guards never ran in CI.
|
|
# Run them here with GITNEXUS_BENCH=1, alongside the Python scope-capture and
|
|
# import-resolution fingerprint + scaling guards (PR #1918 P2a).
|
|
#
|
|
# `--no-file-parallelism` is REQUIRED: these suites measure wall-clock and peak
|
|
# heap, so parallel forks both skew the timings and OOM the worker pool — they
|
|
# must run one file at a time.
|
|
#
|
|
# go-pipeline-benchmark.test.ts is deliberately NOT included: its
|
|
# worker-pool (#1848) suite spins a real worker pool that exits unexpectedly
|
|
# under vitest's fork pool (reproduced in validation), which would make this
|
|
# gate flaky. Go is already guarded by its non-gated O(n^2) tripwire (runs in
|
|
# the main coverage job) plus its golden capture-parity test.
|
|
benchmarks:
|
|
name: benchmarks (GITNEXUS_BENCH)
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 25
|
|
steps:
|
|
# persist-credentials: false — this job only runs npm + vitest benchmarks
|
|
# and never pushes; the default-persisted token in .git/config would be at
|
|
# risk of leaking through an artifact upload (zizmor credential-persistence
|
|
# / artipacked audit). Mirrors the packaged-install-smoke job below.
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
with:
|
|
persist-credentials: false
|
|
- uses: ./.github/actions/setup-gitnexus
|
|
with:
|
|
build: 'true'
|
|
|
|
- name: Python scope-capture + import-resolution fingerprint / scaling guards
|
|
run: |
|
|
node --import tsx bench/python-scope/measure.mjs --check
|
|
node --import tsx bench/python-scope/import-target-fingerprint.mjs --check
|
|
working-directory: gitnexus
|
|
|
|
- name: Cross-language scope-capture fingerprint + scaling guards
|
|
# Build-free: asserts emit<Lang>ScopeCaptures output is unchanged
|
|
# (fingerprint) and stays linear (scaling < 1.5) for go/csharp/rust/php/
|
|
# ruby/cobol. Catches an O(n^2) re-regression without the worker pool.
|
|
run: node --import tsx bench/scope-capture/measure.mjs --check
|
|
working-directory: gitnexus
|
|
|
|
- name: CFG construction time / disk / memory guards (#2081 M1)
|
|
# Build-free: asserts collectFunctionCfgs output is unchanged
|
|
# (fingerprint) and that wall-time, cfgSideChannel disk bytes, AND
|
|
# retained heap all stay sub-quadratic for the straight-line /
|
|
# many-functions / branchy scenarios. Catches an O(n^2) re-regression in
|
|
# the per-function CFG builder (e.g. an extendBlock concat chain) and a
|
|
# memory/disk blow-up. --expose-gc enables the retained-heap measurement.
|
|
run: node --expose-gc --import tsx bench/cfg/measure.mjs --check
|
|
working-directory: gitnexus
|
|
|
|
- name: Emit-persistence throughput / byte-identity guards (#2203)
|
|
# Build-free: asserts streamAllCSVsToDisk output is byte-identical
|
|
# (order-independent CSV-line fingerprint — the #2203 U2/U3 emit
|
|
# optimisations must not change graph content) and that emit wall-time
|
|
# stays linear in node+edge count. The LadybugDB COPY half needs a real
|
|
# DB, so its timing lives in the runtime PROF_LBUG_LOAD breakdown.
|
|
run: node --import tsx bench/emit-persistence/measure.mjs --check
|
|
working-directory: gitnexus
|
|
|
|
- name: Streaming PDG-emit byte-identity / bounded-RSS guards (#2202)
|
|
# Build-free: asserts the streaming PdgEmitSink emits a CSV row SET
|
|
# byte-identical to the whole-graph streamAllCSVsToDisk emit, AND that
|
|
# the in-memory graph retains zero BasicBlock nodes (the O(chunk) peak-RSS
|
|
# bound that unblocks full-kernel-scale repos). Fails on fingerprint drift
|
|
# or any resident BasicBlock.
|
|
run: node --import tsx bench/emit-persistence/measure-streaming.mjs --check
|
|
working-directory: gitnexus
|
|
|
|
- name: Cross-language pipeline benchmarks (GITNEXUS_BENCH, serial)
|
|
env:
|
|
GITNEXUS_BENCH: '1'
|
|
run: >-
|
|
npx vitest run --no-file-parallelism
|
|
test/integration/cobol-pipeline-benchmark.test.ts
|
|
test/integration/csharp-pipeline-benchmark.test.ts
|
|
test/integration/rust-pipeline-benchmark.test.ts
|
|
test/integration/php-pipeline-benchmark.test.ts
|
|
test/integration/ruby-pipeline-benchmark.test.ts
|
|
working-directory: gitnexus
|