mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-11 22:50:06 +00:00
fix: Remove agent harness checksum validation (no-changelog) (#38776)
This commit is contained in:
@@ -2,6 +2,5 @@
|
||||
"repository": "n8n-io/cat-bot",
|
||||
"releaseTag": "harness-v0.3.0",
|
||||
"version": "0.3.0",
|
||||
"assetName": "n8n-opencode-harness-0.3.0.tgz",
|
||||
"sha256": "e1ff2d17291b7f9fb16c7238d23af3d6dc59fc0fe60639ef9e7d1035f21f0fe9"
|
||||
"assetName": "n8n-opencode-harness-0.3.0.tgz"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { createHash } from 'node:crypto';
|
||||
import {
|
||||
existsSync,
|
||||
lstatSync,
|
||||
@@ -25,8 +24,7 @@ export function validateLock(lock) {
|
||||
lock?.repository !== REPOSITORY ||
|
||||
!/^[0-9]+\.[0-9]+\.[0-9]+$/.test(lock.version) ||
|
||||
lock.releaseTag !== `harness-v${lock.version}` ||
|
||||
lock.assetName !== `n8n-opencode-harness-${lock.version}.tgz` ||
|
||||
!/^[0-9a-f]{64}$/.test(lock.sha256)
|
||||
lock.assetName !== `n8n-opencode-harness-${lock.version}.tgz`
|
||||
) {
|
||||
throw new Error('The agent harness lock is invalid.');
|
||||
}
|
||||
@@ -41,10 +39,6 @@ export function readLock(lockPath = join(REPO_ROOT, 'agent-harness.lock.json'))
|
||||
}
|
||||
}
|
||||
|
||||
export function sha256File(path) {
|
||||
return createHash('sha256').update(readFileSync(path)).digest('hex');
|
||||
}
|
||||
|
||||
export function downloadReleaseAsset(lock, destination, { run = execFileSync } = {}) {
|
||||
try {
|
||||
run(
|
||||
@@ -99,7 +93,7 @@ export function installAgentHarness({
|
||||
const pluginPath = join(bundlePath, 'plugins', PLUGIN_FILE);
|
||||
mkdirSync(cacheRoot, { recursive: true });
|
||||
|
||||
// The version cache is write-once and trusted after its checksum succeeds.
|
||||
// The version cache is write-once after a successful installation.
|
||||
const cacheHit = existsSync(pluginPath);
|
||||
if (!cacheHit) {
|
||||
const stagingRoot = mkdtempSync(join(cacheRoot, '.install-'));
|
||||
@@ -108,9 +102,6 @@ export function installAgentHarness({
|
||||
try {
|
||||
mkdirSync(stagedVersion);
|
||||
download(lock, stagedVersion);
|
||||
if (sha256File(archivePath) !== lock.sha256) {
|
||||
throw new Error('Agent harness checksum mismatch.');
|
||||
}
|
||||
// Cat-bot validates archive contents before publishing these pinned bytes.
|
||||
extract(archivePath, stagedVersion);
|
||||
if (!existsSync(join(stagedVersion, BUNDLE_ROOT, 'plugins', PLUGIN_FILE))) {
|
||||
|
||||
@@ -15,12 +15,7 @@ import { tmpdir } from 'node:os';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { afterEach, test } from 'node:test';
|
||||
|
||||
import {
|
||||
downloadReleaseAsset,
|
||||
installAgentHarness,
|
||||
sha256File,
|
||||
validateLock,
|
||||
} from './agent-harness.mjs';
|
||||
import { downloadReleaseAsset, installAgentHarness, validateLock } from './agent-harness.mjs';
|
||||
|
||||
const temporaryDirectories = [];
|
||||
|
||||
@@ -46,14 +41,13 @@ function makeAsset(root, version = '1.2.3') {
|
||||
return asset;
|
||||
}
|
||||
|
||||
function writeLock(root, asset, overrides = {}) {
|
||||
function writeLock(root, overrides = {}) {
|
||||
const version = '1.2.3';
|
||||
const lock = {
|
||||
repository: 'n8n-io/cat-bot',
|
||||
releaseTag: `harness-v${version}`,
|
||||
version,
|
||||
assetName: `n8n-opencode-harness-${version}.tgz`,
|
||||
sha256: sha256File(asset),
|
||||
...overrides,
|
||||
};
|
||||
const lockPath = join(root, 'agent-harness.lock.json');
|
||||
@@ -78,7 +72,6 @@ test('validates the pinned release values', () => {
|
||||
releaseTag: 'harness-v1.2.3',
|
||||
version: '1.2.3',
|
||||
assetName: 'n8n-opencode-harness-1.2.3.tgz',
|
||||
sha256: 'a'.repeat(64),
|
||||
};
|
||||
assert.equal(validateLock(lock), lock);
|
||||
for (const invalid of [
|
||||
@@ -86,18 +79,17 @@ test('validates the pinned release values', () => {
|
||||
{ releaseTag: 'latest' },
|
||||
{ version: '../outside' },
|
||||
{ assetName: 'other.tgz' },
|
||||
{ sha256: 'invalid' },
|
||||
]) {
|
||||
assert.throws(() => validateLock({ ...lock, ...invalid }), /lock is invalid/);
|
||||
}
|
||||
});
|
||||
|
||||
test('installs the verified release and activates its plugin', () => {
|
||||
test('installs the pinned release and activates its plugin', () => {
|
||||
const root = fixtureDirectory();
|
||||
const asset = makeAsset(root);
|
||||
const result = installAgentHarness({
|
||||
...installerPaths(root),
|
||||
lockPath: writeLock(root, asset),
|
||||
lockPath: writeLock(root),
|
||||
download: copyAsset(asset),
|
||||
});
|
||||
|
||||
@@ -115,7 +107,7 @@ test('reuses an installed release without downloading it again', () => {
|
||||
const asset = makeAsset(root);
|
||||
const options = {
|
||||
...installerPaths(root),
|
||||
lockPath: writeLock(root, asset),
|
||||
lockPath: writeLock(root),
|
||||
download: copyAsset(asset),
|
||||
};
|
||||
installAgentHarness(options);
|
||||
@@ -127,7 +119,7 @@ test('reuses an installed release without downloading it again', () => {
|
||||
assert.equal(result.cacheHit, true);
|
||||
});
|
||||
|
||||
test('keeps the active plugin when verification fails', () => {
|
||||
test('keeps the active plugin when installation fails', () => {
|
||||
const root = fixtureDirectory();
|
||||
const asset = makeAsset(root);
|
||||
const paths = installerPaths(root);
|
||||
@@ -140,10 +132,13 @@ test('keeps the active plugin when verification fails', () => {
|
||||
() =>
|
||||
installAgentHarness({
|
||||
...paths,
|
||||
lockPath: writeLock(root, asset, { sha256: '0'.repeat(64) }),
|
||||
lockPath: writeLock(root),
|
||||
download: copyAsset(asset),
|
||||
extract: () => {
|
||||
throw new Error('extraction failed');
|
||||
},
|
||||
}),
|
||||
/checksum mismatch/,
|
||||
/extraction failed/,
|
||||
);
|
||||
assert.equal(readlinkSync(paths.pluginLink), previous);
|
||||
});
|
||||
@@ -159,7 +154,7 @@ test('does not overwrite a user plugin file', () => {
|
||||
() =>
|
||||
installAgentHarness({
|
||||
...paths,
|
||||
lockPath: writeLock(root, asset),
|
||||
lockPath: writeLock(root),
|
||||
download: copyAsset(asset),
|
||||
}),
|
||||
/non-symlink path/,
|
||||
|
||||
Reference in New Issue
Block a user