fix(fleet): align migration preview and clean CI
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1136,6 +1136,70 @@ describe('v1-to-v2 migration preview', (): void => {
|
||||
expect(preview.environment.map(({ agent }) => agent)).toEqual(['coder0']);
|
||||
});
|
||||
|
||||
it.each([
|
||||
[
|
||||
'tmux connector with matrix settings',
|
||||
'connector:\n kind: tmux\n matrix:\n homeserver_url: https://rejected-matrix.example.test\n user_id: "@bot:example.test"\n room_id: "!room:example.test"\n',
|
||||
'connector.matrix',
|
||||
'https://rejected-matrix.example.test',
|
||||
],
|
||||
[
|
||||
'tmux connector with discord settings',
|
||||
'connector:\n kind: tmux\n discord:\n channel_id: rejected-discord-channel\n',
|
||||
'connector.discord',
|
||||
'rejected-discord-channel',
|
||||
],
|
||||
[
|
||||
'discord connector with matrix settings',
|
||||
'connector:\n kind: discord\n discord:\n channel_id: channel\n matrix:\n homeserver_url: https://rejected-matrix.example.test\n user_id: "@bot:example.test"\n room_id: "!room:example.test"\n',
|
||||
'connector.matrix',
|
||||
'https://rejected-matrix.example.test',
|
||||
],
|
||||
[
|
||||
'matrix connector with discord settings',
|
||||
'connector:\n kind: matrix\n matrix:\n homeserver_url: https://matrix.example.test\n user_id: "@bot:example.test"\n room_id: "!room:example.test"\n discord:\n channel_id: rejected-discord-channel\n',
|
||||
'connector.discord',
|
||||
'rejected-discord-channel',
|
||||
],
|
||||
] as const)(
|
||||
'blocks %s to match production v1 connector exclusivity',
|
||||
async (_label, connectorSource, expectedPath, rejectedValue) => {
|
||||
const preview = await previewV1ToV2Migration({
|
||||
source: v1Source.replace(/connector:\n[\s\S]*$/, connectorSource),
|
||||
decisions: decisions(),
|
||||
observations: observations(),
|
||||
personaDirs: await semanticDirs(),
|
||||
});
|
||||
|
||||
expect(preview.status).toBe('blocked');
|
||||
expect(preview.blockers).toContainEqual(
|
||||
expect.objectContaining({ code: 'invalid-connector', path: expectedPath }),
|
||||
);
|
||||
expect(preview).not.toHaveProperty('canonicalRoster');
|
||||
expect(preview).not.toHaveProperty('canonicalYaml');
|
||||
expect(JSON.stringify(preview.blockers)).not.toContain(rejectedValue);
|
||||
},
|
||||
);
|
||||
|
||||
it('blocks whitespace-padded connector kinds to match exact production v1 parsing', async () => {
|
||||
const rejectedKind = ' discord ';
|
||||
const preview = await previewV1ToV2Migration({
|
||||
source: v1Source.replace('kind: discord', `kind: "${rejectedKind}"`),
|
||||
decisions: decisions(),
|
||||
observations: observations(),
|
||||
personaDirs: await semanticDirs(),
|
||||
});
|
||||
|
||||
expect(preview.status).toBe('blocked');
|
||||
expect(preview.blockers).toContainEqual(
|
||||
expect.objectContaining({ code: 'invalid-connector', path: 'connector.kind' }),
|
||||
);
|
||||
expect(preview).not.toHaveProperty('canonicalRoster');
|
||||
expect(preview).not.toHaveProperty('canonicalYaml');
|
||||
expect(preview.evidence).not.toHaveProperty('candidate');
|
||||
expect(JSON.stringify(preview.blockers)).not.toContain(rejectedKind);
|
||||
});
|
||||
|
||||
it('blocks malformed schema-only remote and connector fields', async () => {
|
||||
const source = v1Source
|
||||
.replace('host: build.example.test', 'host: 42')
|
||||
|
||||
@@ -1005,10 +1005,48 @@ function validateConnector(
|
||||
): void {
|
||||
if (!present) return;
|
||||
rejectUnknownKeys(connector, new Set(['kind', 'matrix', 'discord']), 'connector', blockers);
|
||||
const kind = stringValue(connector.kind);
|
||||
const kind = typeof connector.kind === 'string' ? connector.kind : undefined;
|
||||
if (!kind || !['tmux', 'discord', 'matrix'].includes(kind)) {
|
||||
blockers.push(blocker('invalid-connector', 'connector.kind', 'Unsupported connector kind.'));
|
||||
}
|
||||
if (kind === 'tmux') {
|
||||
if (connector.matrix !== undefined) {
|
||||
blockers.push(
|
||||
blocker(
|
||||
'invalid-connector',
|
||||
'connector.matrix',
|
||||
'Tmux connector must not define Matrix connector data.',
|
||||
),
|
||||
);
|
||||
}
|
||||
if (connector.discord !== undefined) {
|
||||
blockers.push(
|
||||
blocker(
|
||||
'invalid-connector',
|
||||
'connector.discord',
|
||||
'Tmux connector must not define Discord connector data.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
if (kind === 'discord' && connector.matrix !== undefined) {
|
||||
blockers.push(
|
||||
blocker(
|
||||
'invalid-connector',
|
||||
'connector.matrix',
|
||||
'Discord connector must not define Matrix connector data.',
|
||||
),
|
||||
);
|
||||
}
|
||||
if (kind === 'matrix' && connector.discord !== undefined) {
|
||||
blockers.push(
|
||||
blocker(
|
||||
'invalid-connector',
|
||||
'connector.discord',
|
||||
'Matrix connector must not define Discord connector data.',
|
||||
),
|
||||
);
|
||||
}
|
||||
if (kind === 'matrix' && connector.matrix === undefined) {
|
||||
blockers.push(
|
||||
blocker('invalid-connector', 'connector.matrix', 'Matrix connector data is required.'),
|
||||
|
||||
8
packages/mosaic/turbo.json
Normal file
8
packages/mosaic/turbo.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": ["//"],
|
||||
"tasks": {
|
||||
"test": {
|
||||
"dependsOn": ["^build", "build"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user