Add Prettier and ESLint tooling (Refs #77)

This commit is contained in:
2026-10-09 15:56:13 -04:00
parent 8ed059b8d3
commit 16469e2d43
711 changed files with 99737 additions and 28286 deletions
+77 -29
View File
@@ -7,14 +7,21 @@ vi.mock('../../src/lib/server/pipeline/worker.js', () => ({ kick: vi.fn(async ()
let fixture: Fixture;
let prepared: Awaited<ReturnType<typeof prepareNativeHost>>;
const custom = 'registry.example/untrusted:latest';
const launch = { game: 't5' as const, gameMode: 'zombie' as const, mapSlug: 'theater', plutoKey: 'saved-key' };
const launch = {
game: 't5' as const,
gameMode: 'zombie' as const,
mapSlug: 'theater',
plutoKey: 'saved-key'
};
beforeEach(async () => {
vi.resetModules();
fixture = await newFixture([]);
prepared = await prepareNativeHost();
});
afterEach(async () => { await fixture.cleanup(); });
afterEach(async () => {
await fixture.cleanup();
});
async function cache(images: string[]) {
const hosts = await import('../../src/lib/server/hosts/index.js');
@@ -23,19 +30,31 @@ async function cache(images: string[]) {
}
describe('runtime image launch policy', () => {
it.each([false, true])('rejects an uncached custom image at POST /api/servers (automatic: %s)', async automatic => {
const { POST } = await import('../../src/routes/api/servers/+server.js');
const response = await POST({ request: new Request('https://controller.test/api/servers', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...launch, image: custom, ...(automatic ? {} : { hostId: prepared.host.id }) })
}) });
expect(response.status).toBe(400);
expect(await response.json()).toMatchObject({ error: expect.stringContaining('prepared by an admin') });
const { db } = await import('../../src/lib/server/db/index.js');
for (const table of ['native_creation_intents', 'server_deployments', 'server_keys']) {
expect(db().prepare(`SELECT * FROM ${table}`).all()).toEqual([]);
it.each([false, true])(
'rejects an uncached custom image at POST /api/servers (automatic: %s)',
async (automatic) => {
const { POST } = await import('../../src/routes/api/servers/+server.js');
const response = await POST({
request: new Request('https://controller.test/api/servers', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...launch,
image: custom,
...(automatic ? {} : { hostId: prepared.host.id })
})
})
});
expect(response.status).toBe(400);
expect(await response.json()).toMatchObject({
error: expect.stringContaining('prepared by an admin')
});
const { db } = await import('../../src/lib/server/db/index.js');
for (const table of ['native_creation_intents', 'server_deployments', 'server_keys']) {
expect(db().prepare(`SELECT * FROM ${table}`).all()).toEqual([]);
}
}
});
);
it('allows the configured default before it is cached', async () => {
await cache([]);
@@ -47,45 +66,74 @@ describe('runtime image launch policy', () => {
await cache([custom]);
const hosts = await import('../../src/lib/server/hosts/index.js');
const other = hosts.createHost({ name: 'Unprepared host' });
const { nativeLaunchSelection, nativeSelection } = await import('../../src/lib/server/provisioning/native.js');
expect(nativeLaunchSelection({ hostId: prepared.host.id, image: custom }, 't5').image).toBe(custom);
const { nativeLaunchSelection, nativeSelection } =
await import('../../src/lib/server/provisioning/native.js');
expect(nativeLaunchSelection({ hostId: prepared.host.id, image: custom }, 't5').image).toBe(
custom
);
expect(nativeSelection({ image: custom }, 't5').hostId).toBe(prepared.host.id);
expect(() => nativeLaunchSelection({ hostId: other.id, image: custom }, 't5')).toThrow(/prepared by an admin/);
expect(() => nativeLaunchSelection({ hostId: other.id, image: custom }, 't5')).toThrow(
/prepared by an admin/
);
hosts.updateHost(prepared.host.id, { mode: 'disabled' });
expect(() => nativeLaunchSelection({ image: custom }, 't5')).toThrow(/prepared by an admin/);
expect(() => nativeLaunchSelection({ image: custom }, 't5')).toThrow(
/prepared by an admin/
);
});
it('requires exact image references and does not treat a queued admin pull as cached', async () => {
const hosts = await import('../../src/lib/server/hosts/index.js');
hosts.queueHostOperation(prepared.host.id, 'runtime.pull', { image: custom });
const { nativeLaunchSelection } = await import('../../src/lib/server/provisioning/native.js');
expect(() => nativeLaunchSelection({ image: custom }, 't5')).toThrow(/prepared by an admin/);
const { nativeLaunchSelection } =
await import('../../src/lib/server/provisioning/native.js');
expect(() => nativeLaunchSelection({ image: custom }, 't5')).toThrow(
/prepared by an admin/
);
await cache([custom + '-other']);
expect(() => nativeLaunchSelection({ image: custom }, 't5')).toThrow(/prepared by an admin/);
expect(() => nativeLaunchSelection({ image: custom }, 't5')).toThrow(
/prepared by an admin/
);
});
it('rechecks cached images when submitting a saved single-server preview', async () => {
await cache([custom]);
const { previewNativeCreation, queueNativeCreation } = await import('../../src/lib/server/provisioning/native.js');
const { previewNativeCreation, queueNativeCreation } =
await import('../../src/lib/server/provisioning/native.js');
const preview = previewNativeCreation({ ...launch, image: custom });
await cache([]);
expect(queueNativeCreation({ ...launch, previewId: preview.id })).toMatchObject({
ok: false, message: expect.stringContaining('prepared by an admin')
ok: false,
message: expect.stringContaining('prepared by an admin')
});
});
it('rejects uncached collection images and rechecks saved previews before writing any jobs', async () => {
const { saveBlueprint } = await import('../../src/lib/server/fleet/launch-recipes.js');
const { previewCollection, queueCollection } = await import('../../src/lib/server/fleet/collections.js');
const blueprint = saveBlueprint({ name: 'Image policy', entries: [{ game: 't5', mapSlug: 'theater', count: 2 }] });
expect(() => previewCollection(blueprint.id, 'fill', { image: custom })).toThrow(/prepared by an admin/);
const { previewCollection, queueCollection } =
await import('../../src/lib/server/fleet/collections.js');
const blueprint = saveBlueprint({
name: 'Image policy',
entries: [{ game: 't5', mapSlug: 'theater', count: 2 }]
});
expect(() => previewCollection(blueprint.id, 'fill', { image: custom })).toThrow(
/prepared by an admin/
);
await cache([custom]);
const preview = previewCollection(blueprint.id, 'fill', { image: custom });
const keys = Object.fromEntries(preview.servers.map(server => [server.name!, 'key-' + server.name]));
const keys = Object.fromEntries(
preview.servers.map((server) => [server.name!, 'key-' + server.name])
);
await cache([]);
expect(() => queueCollection({ previewId: preview.id, keys })).toThrow(/prepared by an admin/);
expect(() => queueCollection({ previewId: preview.id, keys })).toThrow(
/prepared by an admin/
);
const { db } = await import('../../src/lib/server/db/index.js');
for (const table of ['server_launch_collections', 'native_creation_intents', 'server_deployments', 'server_keys']) {
for (const table of [
'server_launch_collections',
'native_creation_intents',
'server_deployments',
'server_keys'
]) {
expect(db().prepare(`SELECT * FROM ${table}`).all()).toEqual([]);
}
await cache([custom]);