GitNexus/gitnexus/test/unit/gitnexus-rc-embeddings.test.ts
Gergő Magyar 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>
2026-09-25 19:42:26 +01:00

57 lines
2 KiB
TypeScript

import { describe, it, expect, afterEach } from 'vitest';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import {
embeddingsFromGitnexusRc,
AutoSyncGitnexusRcError,
} from '../../src/core/gitnexus-rc-embeddings.js';
describe('embeddingsFromGitnexusRc', () => {
const dirs: string[] = [];
const tempDir = (): string => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gn-rc-'));
dirs.push(dir);
return dir;
};
afterEach(() => {
for (const dir of dirs.splice(0)) fs.rmSync(dir, { recursive: true, force: true });
});
it('returns empty when no rc file exists', async () => {
await expect(embeddingsFromGitnexusRc(tempDir())).resolves.toEqual({});
});
it('reads embeddings true from a committed rc', async () => {
const dir = tempDir();
fs.writeFileSync(path.join(dir, '.gitnexusrc'), '{"embeddings": true}');
await expect(embeddingsFromGitnexusRc(dir)).resolves.toEqual({ embeddings: true });
});
it('prefers nested analyze.embeddings over a conflicting top-level value', async () => {
const dir = tempDir();
fs.writeFileSync(
path.join(dir, '.gitnexusrc'),
'{"embeddings": false, "analyze": {"embeddings": 100}}',
);
await expect(embeddingsFromGitnexusRc(dir)).resolves.toEqual({
embeddings: true,
embeddingsNodeLimit: 100,
});
});
it('fails closed on invalid JSON', async () => {
const dir = tempDir();
fs.writeFileSync(path.join(dir, '.gitnexusrc'), '{');
await expect(embeddingsFromGitnexusRc(dir)).rejects.toThrow(AutoSyncGitnexusRcError);
});
it('refuses a symlink .gitnexusrc', async () => {
const dir = tempDir();
const outside = path.join(dir, 'outside.json');
fs.writeFileSync(outside, '{"embeddings": true}');
// 'file' is required for a file symlink on Windows and ignored on other platforms.
fs.symlinkSync(outside, path.join(dir, '.gitnexusrc'), 'file');
await expect(embeddingsFromGitnexusRc(dir)).rejects.toThrow(/symbolic link/);
});
});