Update Harbor client and gateway functionality
Build and Deploy Gateway / build-and-push (push) Successful in 35s
Build and Deploy Gateway / deploy (push) Successful in 14s

This commit is contained in:
2026-08-17 15:23:16 +03:00
parent 0b39211fbd
commit 7c255192b0
41 changed files with 1443 additions and 218 deletions
+56 -1
View File
@@ -61,7 +61,7 @@ test('schema v2 state migrates built-in .ru into a normal enabled rule', (t) =>
assert.equal(migrated.schemaVersion, STATE_SCHEMA_VERSION);
assert.deepEqual(migrated.routeRules, [
{ type: 'domain_suffix', value: 'ru', enabled: true },
{ type: 'domain_suffix', value: 'ru', enabled: true, outbound: 'direct' },
]);
const primary = migrated.profiles[0];
assert.equal(primary.label, 'Основной');
@@ -74,6 +74,61 @@ test('schema v2 state migrates built-in .ru into a normal enabled rule', (t) =>
assert.equal(JSON.parse(fs.readFileSync(filePath, 'utf8')).schemaVersion, STATE_SCHEMA_VERSION);
});
test('schema v5 migrates saved and applied rules to v6 with an exact backup', (t) => {
const filePath = fixture(t);
const legacy = {
schemaVersion: 5,
revision: 11,
routeRulesRevision: 7,
routeRules: [
{ type: 'domain', value: 'api.example.com', enabled: true },
{ type: 'domain_suffix', value: 'example.com', enabled: false },
],
appliedRouteRules: [
{ type: 'domain_suffix', value: 'example.com', enabled: false },
{ type: 'domain', value: 'api.example.com', enabled: true },
],
};
const bytes = JSON.stringify(legacy);
fs.writeFileSync(filePath, bytes);
const store = createStateStore(filePath, {
now: () => new Date('2026-08-17T12:00:00.000Z'),
});
const migrated = store.read();
assert.equal(migrated.schemaVersion, 6);
assert.equal(migrated.routeRulesRevision, 7);
assert.deepEqual(migrated.routeRules.map(({ outbound }) => outbound), ['direct', 'direct']);
assert.deepEqual(migrated.appliedRouteRules.map(({ type, outbound }) => [type, outbound]), [
['domain_suffix', 'direct'],
['domain', 'direct'],
]);
assert.equal(store.migration.fromVersion, 5);
assert.equal(store.migration.toVersion, 6);
assert.match(store.migration.backupPath, /\.backup-v5-/);
assert.equal(fs.readFileSync(store.migration.backupPath, 'utf8'), bytes);
});
test('schema v6 rejects missing or unknown outbound without rewriting source bytes', (t) => {
for (const [name, rule] of [
['missing', { type: 'domain', value: 'example.com', enabled: true }],
['unknown', { type: 'domain', value: 'example.com', enabled: true, outbound: 'block' }],
]) {
const filePath = `${fixture(t)}-${name}`;
const bytes = JSON.stringify({
schemaVersion: 6,
routeRules: [rule],
appliedRouteRules: [],
});
fs.writeFileSync(filePath, bytes);
const store = createStateStore(filePath);
assert.throws(() => store.read(), /outbound/);
assert.equal(fs.readFileSync(filePath, 'utf8'), bytes);
assert.equal(store.migration, null);
}
});
test('ambiguous legacy selectedTag explicitly requires a new choice', (t) => {
const filePath = fixture(t);
fs.writeFileSync(filePath, JSON.stringify({