mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-03 02:21:44 +00:00
2 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6bb99767ff
|
fix(auto-sync): HTTPS remotes, OpenSSH image, and rc embeddings (#3378)
* fix(docker): install OpenSSH in the CLI runtime image Auto-sync requires git SSH remotes, but the published image omitted openssh-client so every clone failed with ssh: not found. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(auto-sync): accept HTTPS remotes and reclone failed checkouts Allowlisted HTTPS URLs can clone without SSH keys, and a timed-out clone with no remote.origin is quarantined instead of blocking forever. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(auto-sync): honor .gitnexusrc embeddings and warn on empty vectors Auto-sync analyze now reads embeddings from the clone's project config, and query reports when an index has no vectors so keyword fallback is visible. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(review): warn when CodeEmbedding table is missing (U5) Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): wrap long openssh-client test line for prettier Co-authored-by: Cursor <cursoragent@cursor.com> * fix(query): keep keyword-only indexes off query.warning Empty or missing CodeEmbedding is the default index. Put the #3372 notice in a once-per-backend log line so FTS-success query results stay warning-free. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(review): bound rc reads and quarantine only a missing origin Drop the implementation plan from the branch. Auto-sync reads .gitnexusrc through the bounded control-file reader, and a git config failure no longer relocates a live checkout. The same allowlisted repo can switch between SSH and HTTPS without a refused pull. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(auto-sync): share repo identity and skip a second origin read Co-authored-by: Cursor <cursoragent@cursor.com> * test(auto-sync): clean temp fixtures and cover nested embeddings precedence Co-authored-by: Cursor <cursoragent@cursor.com> * test(auto-sync): skip the symlink rc fixture on Windows Co-authored-by: Cursor <cursoragent@cursor.com> * test(auto-sync): reject symlink rc files on every platform Co-authored-by: Cursor <cursoragent@cursor.com> * test(ci): run auto-sync symlink and clone tests on Windows and macOS Co-authored-by: Cursor <cursoragent@cursor.com> * test(git-clone): keep Windows CI on file URLs and POSIX permission checks Co-authored-by: Cursor <cursoragent@cursor.com> * test(git-clone): keep the SSH-to-HTTPS origin check offline Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
4f9d595c73
|
fix(docker): ship runtime-needed published assets (hooks/, skills/) into the image (#2130) (#2132)
* fix(docker): copy hooks/ into Dockerfile.cli runtime stage (#2130) `gitnexus analyze` inside the official image (akonlabs/gitnexus, ghcr.io/abhigyanpatwari/gitnexus) crashed at startup with: Error: Cannot find module '../../hooks/claude/resolve-analyze-cmd.cjs' Require stack: - /app/gitnexus/dist/cli/resolve-invocation.js `dist/cli/resolve-invocation.js` does `createRequire(import.meta.url)('../../hooks/claude/resolve-analyze-cmd.cjs')` at module load (it is the single source of truth for the npm-11 npx-crash invocation decision, #1939), and `analyze.ts` statically imports it. The Dockerfile.cli runtime stage copied dist/node_modules/package.json/the duckdb script/vendor but never `hooks/`, so the require throws before the command does any work. `hooks/` is in package.json `files`, so npm already ships it — Docker was the only distribution dropping it. Fix: copy `hooks/` into the runtime stage, mirroring what npm publishes. Also add `test/unit/dockerfile-runtime-asset-parity.test.ts`: a regression guard that derives every out-of-dist `require()`/`createRequire()` target from source and asserts each is a runtime-stage `COPY`. Scoped to the require family (not `fs.access`/`new URL`), so it locks the #2130 class without false-flagging the intentionally-omitted, gracefully-degrading `web/` and `skills/` assets. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docker): also ship skills/ into the runtime image Follow-up to the hooks/ fix: `skills/` is another published runtime asset (in package.json `files`) the Docker image dropped. The CLI reads the bundled SKILL.md templates from `<pkg>/skills/` for `gitnexus analyze --skills` (ai-context skill generation) and `gitnexus setup`/`uninstall` (installing skills into editor configs). Unlike the hooks/ require(), these reads degrade SILENTLY when the dir is absent — `--skills` writes minimal placeholder content (ai-context.ts), `setup` installs zero skills (setup.ts readdir → []) — so the image looked fine but produced wrong output. Copy `skills/` so the image is fully usable for all CLI tooling. `web/` (also in `files`) is intentionally NOT shipped: this image never builds gitnexus-web (the builder doesn't copy it, build.js logs "skipping web UI"), so it is API-only by design — the UI is the separate Dockerfile.web image / hosted app. The duckdb script is the only runtime asset needed from scripts/, so that stays a single-file copy. Extends the runtime-asset-parity guard with an explicit skills/ assertion. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(test): correct stale docstring that listed skills/ as not copied The 2nd commit on this branch added a skills/ COPY + an it('copies skills/…') assertion, but the top-of-file docstring still grouped skills/ with web/ as 'intentionally not copied / out of scope'. Drop skills/ from that sentence and note it is shipped (and covered by its own test). web/ remains the sole fs-accessed-but-uncopied example. Documentation-only; assertions unchanged. * fix(test): make runtime-stage detection case-insensitive on AS Docker accepts a lowercase `as runtime`; the parity guard's stage-detection regex was case-sensitive on `AS`, so a future Dockerfile reformat would empty the parsed COPY set and trip the named assertions. Add the /i flag. * fix(test): stop runtime-stage COPY parsing at the next FROM runtimeStageCopiedSources scanned from the runtime FROM to EOF. Bound the scan to the runtime stage (start after its FROM, break on the next FROM) so a build stage added after runtime can't have its COPY lines misattributed. No-op today (runtime is the last stage); the copied set is unchanged. * fix(test): assert at least one runtime COPY is parsed (no vacuous pass) If the runtime FROM or the /app/gitnexus/ source prefix ever stops matching, the copied set goes empty and the parity assertion passes vacuously. Add an explicit copied.length>0 guard so that failure mode is loud and named. * fix(test): strip line comments before require-scanning requiredExternalAssets() regex-scanned raw source, so a future doc-comment such as a commented-out require('../../web/x') in a shallow src file would resolve outside dist/ and spuriously fail the parity guard. Strip // line comments first. Block comments are deliberately not stripped (a naive block strip mangles slash-star inside string/glob literals). Verified the real-tree scanner output is byte-identical with and without the strip, and resolve-invocation.ts's multi-line createRequire is still detected. (Also swaps a stray non-ASCII glyph in the prior commit's comment for ASCII.) * fix(test): account for aliased + computed module-load requires (fail-closed) The parity scanner only matched string-literal require/createRequire, so it missed module-load requires via aliased createRequire bindings and computed paths — and already failed to see community-processor.ts's `_require(leidenPath)` -> vendor/leiden, making the "every out-of-dist asset" claim untrue. Broaden the scan: - Discover per-file createRequire bindings (requireCJS, _require, …) and match their literal-arg calls; keep the createRequire(...)('…') IIFE form. - Detect COMPUTED (non-literal) requires and gate them on MODULE-LOAD position (brace-depth 0), so the four in-function computed requires that target node_modules/package.json (optional-grammars, native-check, capabilities, parse-cache) are correctly out of charter and ignored. A module-load computed require must be vetted in KNOWN_COMPUTED_REQUIRES (seed: community-processor -> vendor/leiden) or the test FAILS CLOSED for manual review. - Allowlist entries are coverage-checked via isCovered, never trusted: a new test removes the `vendor` COPY from a fixture and asserts leiden surfaces as uncovered (so deleting a COPY can't silently pass — the #2130 class). - Exclude `<id>.resolve(...)` (a path lookup, not a load). - Upgrade the comment stripper to a string-aware pass that removes line AND block comments without mangling slash-star inside string/glob literals — the computed branch needs JSDoc requires (e.g. javascript/index.ts) gone, and the literal scan output stays byte-identical. Honest claim wording: the 4th test now says coverage = resolvable + vetted module-load requires, unrecognized computed requires fail for review. Adds unit tests for fail-closed, aliased-literal, and in-function-ignored paths. * fix(test): also scan shipped .cjs/.mjs assets for sibling requires The guard only scanned src/**/*.ts, so hand-written shipped runtime files were invisible — and they DO require siblings: hooks/claude/gitnexus-hook.cjs and hooks/antigravity/gitnexus-antigravity-hook.cjs each require('./hook-lock.cjs'), './hook-db-lock-probe.cjs', './resolve-analyze-cmd.cjs'. Add a second pass over shipped .cjs/.mjs assets (the runtime COPY set minus dep/data roots), resolving each relative require against the asset's OWN package-relative dir and checking COPY coverage — by prefix, NOT on-disk existence: the antigravity hook's './hook-lock.cjs' resolves to hooks/antigravity/hook-lock.cjs (which doesn't physically exist; hook-lock.cjs lives under hooks/claude) yet is covered by the whole-hooks COPY. All 6 shipped sibling requires resolve under the hooks COPY. * fix(docker): move hooks/skills COPYs past the DuckDB FTS RUN The hooks/ and skills/ COPYs sat between the vendor COPY and the DuckDB FTS-extension install RUN, so any edit to hook/skill content invalidated that RUN's cache layer — which performs a one-time network INSTALL of the extension (~tens of seconds per affected build). The COPYs have no input dependency on the DuckDB step; relocate them to after it (before USER node) so stable infrastructure layers are not rebuilt on hook/skill churn. Image contents are unchanged. The runtime-asset-parity guard still detects both (its scan covers the whole runtime stage), and the two are consolidated under one comment. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |