diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5ace4600a..3aa628a2c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,3 +4,13 @@ updates: directory: "/" schedule: interval: "weekly" + + - package-ecosystem: "npm" + directory: "/graph-ui" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + groups: + graph-ui-minor-patch: + patterns: ["*"] + update-types: ["minor", "patch"] diff --git a/.github/workflows/_build.yml b/.github/workflows/_build.yml index 47b5b17b5..d82a631d2 100644 --- a/.github/workflows/_build.yml +++ b/.github/workflows/_build.yml @@ -68,7 +68,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version-file: .node-version - name: Build release binary with UI env: @@ -131,7 +131,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version-file: .node-version - name: Build release binary with UI shell: msys2 {0} @@ -193,7 +193,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version-file: .node-version - name: Build release binary with UI shell: msys2 {0} @@ -252,7 +252,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version-file: .node-version - name: Build release binary with UI (static) env: diff --git a/.github/workflows/_lint.yml b/.github/workflows/_lint.yml index aa7eb7062..c42914db8 100644 --- a/.github/workflows/_lint.yml +++ b/.github/workflows/_lint.yml @@ -1,4 +1,4 @@ -# Reusable: lint only (cppcheck + clang-format). +# Reusable: workflow and C lint (actionlint + cppcheck + clang-format). # Security-static and CodeQL gate are separate — see _security.yml. name: Lint & Security @@ -9,8 +9,30 @@ permissions: contents: read jobs: + lint-workflows: + runs-on: ubuntu-24.04 + timeout-minutes: 5 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Install actionlint 1.7.12 + env: + ACTIONLINT_VERSION: "1.7.12" + ACTIONLINT_SHA256: 8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8 + run: | + curl -fsSL --retry 3 \ + "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" \ + -o "$RUNNER_TEMP/actionlint.tar.gz" + echo "$ACTIONLINT_SHA256 $RUNNER_TEMP/actionlint.tar.gz" | sha256sum --check --strict + mkdir -p "$RUNNER_TEMP/actionlint" + tar -xzf "$RUNNER_TEMP/actionlint.tar.gz" -C "$RUNNER_TEMP/actionlint" actionlint + echo "$RUNNER_TEMP/actionlint" >> "$GITHUB_PATH" + + - name: Lint GitHub Actions workflows + run: bash scripts/ci/lint-workflows.sh + lint: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 # 15 min proved too tight on a slow runner day and a timed-out lint reads # as "cancelled", which the release graph must treat as a hard stop; keep # a bound, but one only a genuine hang can hit (normal runtime ~5 min). @@ -60,7 +82,7 @@ jobs: # provability (never suppressed — the NOLINT ban applies here too). # Vendored-tree diagnostics are path-filtered, mirroring .cppcheck. lint-mem: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 60 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/.github/workflows/_test.yml b/.github/workflows/_test.yml index 2d28fb108..e4d54a0ca 100644 --- a/.github/workflows/_test.yml +++ b/.github/workflows/_test.yml @@ -174,6 +174,26 @@ jobs: env: CCACHE_DIR: ${{ github.workspace }}/.ccache + test-frontend: + name: Frontend (Node ${{ matrix.node }}) + runs-on: ubuntu-24.04 + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + node: ["22", "24"] + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: ${{ matrix.node }} + cache: npm + cache-dependency-path: graph-ui/package-lock.json + + - name: Test and build frontend + run: bash scripts/ci/test-frontend.sh + # The package wrappers own their own runtime-set publication and lease-lock # implementations. Run the same suites against both host families so Unix # inode/flock behavior and Windows handle/link behavior are each gating, @@ -183,6 +203,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest] + node: ["22", "24"] runs-on: ${{ matrix.os }} timeout-minutes: 30 steps: @@ -195,7 +216,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ${{ matrix.node }} - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: @@ -219,7 +240,7 @@ jobs: # parallel suite — catches what an older compiler-rt can miss. Same # canonical scripts/test.sh wave as every other leg. test-diag: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 120 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -566,7 +587,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version-file: .node-version - name: Compiler cache (content-verified) uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 03abb518e..7f889cccb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -221,7 +221,9 @@ jobs: run: python3 scripts/ci/generate-sbom.py "${{ inputs.version }}" - name: Attest SBOM - uses: actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e # v4.1.0 + uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0 + env: + NODE_OPTIONS: '--max-http-header-size=32768' with: subject-path: '*.tar.gz' sbom-path: 'sbom.json' @@ -456,7 +458,8 @@ jobs: - name: Setup Node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: '22' + node-version-file: .node-version + package-manager-cache: false registry-url: 'https://registry.npmjs.org' - name: Publish to npm diff --git a/.node-version b/.node-version new file mode 100644 index 000000000..cabf43b5d --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +24 \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 96ce8f861..376547cd9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,9 @@ Contributions are welcome. This guide covers setup, testing, and PR guidelines. **Prerequisites**: C compiler (gcc or clang), make, zlib, Git. Optional: Node.js 22+ (for graph UI). +CI builds and npm publishing use Node.js 24 from [.node-version](.node-version). +Node.js 22 remains supported and is tested alongside Node.js 24. + ```bash git clone https://github.com/DeusData/codebase-memory-mcp.git cd codebase-memory-mcp @@ -32,6 +35,15 @@ This builds with ASan + UBSan and runs the full C test suite. Key test files: - `tests/test_mcp.c` — MCP protocol and tool handler tests - `tests/test_store_*.c` — SQLite graph store tests +For the graph UI: + +```bash +bash scripts/ci/test-frontend.sh +``` + +This installs locked dependencies, runs Vitest, and builds the production UI. +CI runs the same entry point on Node.js 22 and 24. + ## Run Linter ```bash @@ -40,6 +52,16 @@ scripts/lint.sh Runs clang-tidy, cppcheck, and clang-format. All must pass before committing (also enforced by pre-commit hook). +For GitHub Actions workflows, install [actionlint 1.7.12](https://github.com/rhysd/actionlint/releases/tag/v1.7.12) +on PATH and run: + +```bash +bash scripts/ci/lint-workflows.sh +``` + +This checks workflow syntax and expressions. ShellCheck and Pyflakes are not +enabled by this entry point; existing repository checks remain unchanged. + ## Run Security Audit ```bash diff --git a/scripts/ci/lint-workflows.sh b/scripts/ci/lint-workflows.sh new file mode 100644 index 000000000..89937793c --- /dev/null +++ b/scripts/ci/lint-workflows.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -euo pipefail + +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" + +case "$*" in +-h | --help) + cat <<'EOF' +Usage: bash scripts/ci/lint-workflows.sh + +Validate all GitHub Actions workflows with actionlint 1.7.12 on PATH. +ShellCheck and Pyflakes are separate checks, not enabled by this entry point. +EOF + exit 0 + ;; +"") ;; +*) + echo "lint-workflows.sh: unexpected arguments '$*'. Please consult --help." >&2 + exit 2 + ;; +esac + +cd "$ROOT" +exec actionlint -shellcheck= -pyflakes= \ No newline at end of file diff --git a/scripts/ci/test-frontend.sh b/scripts/ci/test-frontend.sh new file mode 100644 index 000000000..c3ff64fcf --- /dev/null +++ b/scripts/ci/test-frontend.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -euo pipefail + +ROOT="$(cd "$(dirname "$0")/../.." && pwd)" + +case "$*" in +-h | --help) + cat <<'EOF' +Usage: bash scripts/ci/test-frontend.sh + +Install the locked frontend dependencies, run Vitest, and build the production +UI. Requires Node.js 22+ and npm; CI tests Node.js 22 and 24. +EOF + exit 0 + ;; +"") ;; +*) + echo "test-frontend.sh: unexpected arguments '$*'. Please consult --help." >&2 + exit 2 + ;; +esac + +cd "$ROOT/graph-ui" +npm ci +npm test +npm run build \ No newline at end of file diff --git a/tests/test_venue_parity_contract.sh b/tests/test_venue_parity_contract.sh index 4bcd694d7..3e482c700 100755 --- a/tests/test_venue_parity_contract.sh +++ b/tests/test_venue_parity_contract.sh @@ -245,6 +245,8 @@ REQUIRED = [ ("_soak.yml", r"scripts/ci/new-protected-temp-root\.ps1", "Windows soak uses the shared temp root"), ("_test.yml", r"scripts/ci/new-protected-temp-root\.ps1", "Windows tests use the shared temp root"), ("_test.yml", r"scripts/test\.sh", "the test legs run the canonical entry"), + ("_test.yml", r"run: bash scripts/ci/test-frontend\.sh", "frontend tests use the shared entry"), + ("_lint.yml", r"run: bash scripts/ci/lint-workflows\.sh", "workflow lint uses the shared entry"), ("pr.yml", r"vm-smoke\.sh", "PR CI smokes through the shared wrapper"), ("_build.yml", r"scripts/package-release\.sh", "release archives are produced by the canonical packaging entry"), @@ -388,6 +390,8 @@ scripts/smoke-invariants.sh scripts/ci/preflight-docker.sh scripts/ci/require-all-green.sh scripts/ci/verify-shard-union.sh +scripts/ci/test-frontend.sh +scripts/ci/lint-workflows.sh scripts/ci/generate-sbom.py scripts/package-release.sh scripts/ci/smoke-artifact.sh @@ -426,6 +430,8 @@ scripts/lint.sh scripts/smoke-local.sh scripts/soak-legs.sh scripts/ci/preflight-docker.sh +scripts/ci/test-frontend.sh +scripts/ci/lint-workflows.sh test-infrastructure/vm/vm-smoke.sh scripts/smoke-invariants.sh "