mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-27 06:12:20 +00:00
Some checks failed
Devcontainer Smoke / Config-transform unit tests (push) Has been cancelled
Devcontainer Smoke / Build devcontainer image (default) (push) Has been cancelled
Publish Development Images / publish (core) (push) Has been cancelled
Publish Development Images / publish (ui) (push) Has been cancelled
Devcontainer Smoke / Build devcontainer image (ui) (push) Has been cancelled
CodeQL / Analyze (python) (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
Gitleaks / gitleaks (push) Waiting to run
Publish / ci (push) Blocked by required conditions
Publish / Classify release event (push) Waiting to run
Publish / RC guard (marker + release-PR skip) (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
Skill copy sync / shipped skills drift guard (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-cli) (push) Waiting to run
Trivy Image Scan / Trivy (gitnexus-web) (push) Waiting to run
252 lines
9.6 KiB
JavaScript
252 lines
9.6 KiB
JavaScript
'use strict';
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const { execFileSync, spawnSync } = require('node:child_process');
|
|
const { ensureDependencies, markerName } = require('./dependencies.cjs');
|
|
|
|
function fixture(t) {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'gn-dependencies-'));
|
|
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
fs.writeFileSync(
|
|
path.join(root, 'package.json'),
|
|
JSON.stringify({ dependencies: { example: '1.0.0' } }),
|
|
);
|
|
fs.writeFileSync(path.join(root, 'package-lock.json'), '{}');
|
|
let installs = 0;
|
|
const run = () => {
|
|
installs++;
|
|
fs.mkdirSync(path.join(root, 'node_modules/example'), { recursive: true });
|
|
fs.writeFileSync(path.join(root, 'node_modules/example/package.json'), '{}');
|
|
};
|
|
return { root, run, count: () => installs };
|
|
}
|
|
|
|
test('reuses completed dependency volumes and reinstalls after lockfile changes', (t) => {
|
|
const f = fixture(t);
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), true);
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), false);
|
|
fs.writeFileSync(path.join(f.root, 'package-lock.json'), '{"lockfileVersion":3}');
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), true);
|
|
assert.equal(f.count(), 2);
|
|
});
|
|
|
|
test('repairs a missing direct dependency even if the receipt matches', (t) => {
|
|
const f = fixture(t);
|
|
ensureDependencies(f.root, { run: f.run });
|
|
fs.rmSync(path.join(f.root, 'node_modules/example'), { recursive: true });
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), true);
|
|
});
|
|
|
|
test('runtime ABI changes and explicit repair invalidate reuse', (t) => {
|
|
const f = fixture(t);
|
|
ensureDependencies(f.root, { run: f.run });
|
|
const runtime = {
|
|
version: 'v22.23.3',
|
|
versions: { modules: 'different' },
|
|
platform: 'linux',
|
|
arch: 'arm64',
|
|
};
|
|
assert.equal(ensureDependencies(f.root, { run: f.run, runtime }), true);
|
|
assert.equal(ensureDependencies(f.root, { run: f.run, runtime, force: true }), true);
|
|
});
|
|
|
|
for (const group of ['dependencies', 'devDependencies', 'optionalDependencies']) {
|
|
test(`local file-dependency manifest changes in ${group} invalidate reuse`, (t) => {
|
|
const f = fixture(t);
|
|
const local = path.join(f.root, 'local');
|
|
fs.mkdirSync(local);
|
|
fs.writeFileSync(path.join(local, 'package.json'), '{"version":"1.0.0"}');
|
|
const manifest = { dependencies: { example: '1.0.0' } };
|
|
manifest[group] ??= {};
|
|
manifest[group].local = 'file:./local';
|
|
fs.writeFileSync(path.join(f.root, 'package.json'), JSON.stringify(manifest));
|
|
const run = () => {
|
|
f.run();
|
|
fs.mkdirSync(path.join(f.root, 'node_modules/local'), { recursive: true });
|
|
fs.copyFileSync(
|
|
path.join(local, 'package.json'),
|
|
path.join(f.root, 'node_modules/local/package.json'),
|
|
);
|
|
};
|
|
ensureDependencies(f.root, { run });
|
|
assert.equal(ensureDependencies(f.root, { run }), false);
|
|
fs.writeFileSync(path.join(local, 'package.json'), '{"version":"1.0.1"}');
|
|
assert.equal(ensureDependencies(f.root, { run }), true);
|
|
assert.equal(ensureDependencies(f.root, { run }), false);
|
|
assert.equal(f.count(), 2);
|
|
});
|
|
}
|
|
|
|
test('tracked native source and installer edits invalidate reuse', (t) => {
|
|
const f = fixture(t);
|
|
fs.mkdirSync(path.join(f.root, 'scripts'));
|
|
fs.mkdirSync(path.join(f.root, 'vendor'));
|
|
fs.mkdirSync(path.join(f.root, 'prebuilds/bundled'), { recursive: true });
|
|
fs.writeFileSync(path.join(f.root, 'scripts/build-tree-sitter-grammars.cjs'), '// original');
|
|
fs.writeFileSync(path.join(f.root, 'scripts/arm64-prebuild.cjs'), '// original validator');
|
|
fs.writeFileSync(path.join(f.root, 'prebuilds/bundled/manifest.json'), '{"schemaVersion":1}');
|
|
fs.writeFileSync(path.join(f.root, 'prebuilds/bundled/grammar.node'), Buffer.from([1, 2, 3]));
|
|
fs.writeFileSync(path.join(f.root, 'vendor/grammar.c'), '// original');
|
|
const git = (...args) =>
|
|
execFileSync(
|
|
'git',
|
|
[
|
|
'-c',
|
|
'core.hooksPath=/dev/null',
|
|
'-c',
|
|
'commit.gpgsign=false',
|
|
'-c',
|
|
'user.name=Fixture',
|
|
'-c',
|
|
'user.email=fixture@example.invalid',
|
|
...args,
|
|
],
|
|
{ cwd: f.root, stdio: 'pipe' },
|
|
);
|
|
git('init');
|
|
git(
|
|
'add',
|
|
'package.json',
|
|
'package-lock.json',
|
|
'scripts/build-tree-sitter-grammars.cjs',
|
|
'scripts/arm64-prebuild.cjs',
|
|
'prebuilds/bundled',
|
|
'vendor/grammar.c',
|
|
);
|
|
git('commit', '-m', 'fixture');
|
|
ensureDependencies(f.root, { run: f.run });
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), false);
|
|
fs.writeFileSync(path.join(f.root, 'vendor/grammar.c'), '// changed grammar');
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), true);
|
|
fs.writeFileSync(
|
|
path.join(f.root, 'scripts/build-tree-sitter-grammars.cjs'),
|
|
'// changed installer',
|
|
);
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), true);
|
|
for (const [file, content] of [
|
|
['scripts/arm64-prebuild.cjs', '// changed validator'],
|
|
['prebuilds/bundled/manifest.json', '{"schemaVersion":2}'],
|
|
['prebuilds/bundled/grammar.node', Buffer.from([4, 5, 6])],
|
|
]) {
|
|
fs.writeFileSync(path.join(f.root, file), content);
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), true, file);
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), false, file);
|
|
}
|
|
});
|
|
|
|
test('failed reinstall removes its receipt and is retried', (t) => {
|
|
const f = fixture(t);
|
|
ensureDependencies(f.root, { run: f.run });
|
|
assert.throws(
|
|
() =>
|
|
ensureDependencies(f.root, {
|
|
force: true,
|
|
run: () => {
|
|
throw new Error('install failed');
|
|
},
|
|
}),
|
|
/install failed/,
|
|
);
|
|
assert.equal(fs.existsSync(path.join(f.root, 'node_modules', markerName)), false);
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), true);
|
|
});
|
|
|
|
test('changing optional-grammar policy invalidates the core install receipt', (t) => {
|
|
const f = fixture(t);
|
|
const previous = process.env.GITNEXUS_SKIP_OPTIONAL_GRAMMARS;
|
|
t.after(() => {
|
|
if (previous === undefined) delete process.env.GITNEXUS_SKIP_OPTIONAL_GRAMMARS;
|
|
else process.env.GITNEXUS_SKIP_OPTIONAL_GRAMMARS = previous;
|
|
});
|
|
fs.mkdirSync(path.join(f.root, 'scripts'));
|
|
fs.writeFileSync(path.join(f.root, 'scripts/build-tree-sitter-grammars.cjs'), '// fixture');
|
|
execFileSync('git', ['init', '-q'], { cwd: f.root });
|
|
execFileSync(
|
|
'git',
|
|
[
|
|
'-c',
|
|
'core.hooksPath=/dev/null',
|
|
'-c',
|
|
'commit.gpgsign=false',
|
|
'-c',
|
|
'user.name=Fixture',
|
|
'-c',
|
|
'user.email=fixture@example.invalid',
|
|
'commit',
|
|
'--allow-empty',
|
|
'-m',
|
|
'fixture',
|
|
],
|
|
{ cwd: f.root, stdio: 'pipe' },
|
|
);
|
|
process.env.GITNEXUS_SKIP_OPTIONAL_GRAMMARS = '1';
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), true);
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), false);
|
|
delete process.env.GITNEXUS_SKIP_OPTIONAL_GRAMMARS;
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), true);
|
|
process.env.GITNEXUS_SKIP_OPTIONAL_GRAMMARS = '0';
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), false);
|
|
process.env.GITNEXUS_SKIP_OPTIONAL_GRAMMARS = '1';
|
|
assert.equal(ensureDependencies(f.root, { run: f.run }), true);
|
|
assert.equal(f.count(), 3);
|
|
});
|
|
|
|
test('cached lifecycle restores real Husky and rebuilds changed sources', (t) => {
|
|
const f = fixture(t);
|
|
fs.writeFileSync(path.join(f.root, 'package.json'), '{}');
|
|
for (const name of ['gitnexus', 'gitnexus-web', 'gitnexus-shared']) {
|
|
fs.mkdirSync(path.join(f.root, name));
|
|
fs.writeFileSync(path.join(f.root, name, 'package.json'), '{}');
|
|
fs.writeFileSync(path.join(f.root, name, 'package-lock.json'), '{}');
|
|
}
|
|
fs.mkdirSync(path.join(f.root, '.husky'));
|
|
fs.writeFileSync(path.join(f.root, '.husky/pre-commit'), 'exit 0\n');
|
|
const global = path.join(f.root, 'gitconfig');
|
|
fs.writeFileSync(global, '');
|
|
const env = {
|
|
...process.env,
|
|
PATH: `${f.root}:${process.env.PATH}`,
|
|
HUSKY: '',
|
|
GIT_CONFIG_GLOBAL: global,
|
|
GIT_CONFIG_NOSYSTEM: '1',
|
|
GIT_CONFIG_COUNT: '0',
|
|
GITNEXUS_FORCE_DEPS: '0',
|
|
GITNEXUS_DEV_UI: '0',
|
|
};
|
|
for (const key of ['GIT_DIR', 'GIT_COMMON_DIR', 'GIT_WORK_TREE', 'GIT_INDEX_FILE'])
|
|
delete env[key];
|
|
execFileSync('git', ['init', '-q'], { cwd: f.root, env });
|
|
const husky = path.resolve(__dirname, '../node_modules/husky/bin.js');
|
|
fs.writeFileSync(
|
|
path.join(f.root, 'npm'),
|
|
`#!${process.execPath}
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const args = process.argv.slice(2);
|
|
if (args[0] === '--version') { console.log('10.9.2'); process.exit(0); }
|
|
fs.appendFileSync(${JSON.stringify(path.join(f.root, 'calls'))}, path.basename(process.cwd()) + ':' + args.join(' ') + '\\n');
|
|
if (args[0] === 'ci') fs.mkdirSync('node_modules', { recursive: true });
|
|
if (args.join(' ') === 'run prepare') require('node:child_process').execFileSync(process.execPath, [${JSON.stringify(husky)}], { stdio: 'inherit' });
|
|
`,
|
|
{ mode: 0o755 },
|
|
);
|
|
const invoke = () => {
|
|
const result = spawnSync(process.execPath, [path.join(__dirname, 'dependencies.cjs'), f.root], {
|
|
env,
|
|
encoding: 'utf8',
|
|
});
|
|
assert.equal(result.status, 0, result.stderr);
|
|
};
|
|
invoke();
|
|
fs.rmSync(path.join(f.root, '.husky/_'), { recursive: true });
|
|
fs.writeFileSync(path.join(f.root, 'calls'), '');
|
|
invoke();
|
|
const calls = fs.readFileSync(path.join(f.root, 'calls'), 'utf8');
|
|
assert.doesNotMatch(calls, /:ci/);
|
|
assert.match(calls, /:run prepare/);
|
|
assert.match(calls, /gitnexus:run build/);
|
|
assert.ok(fs.existsSync(path.join(f.root, '.husky/_/pre-commit')));
|
|
});
|