Skip to content

Commit 7d0b03a

Browse files
feat: allow for digest-pinned composefiles and test-coverage fixes (#7)
* feat: allow for digest-pinned composefiles * fix some coverage * Add unit tests for digest helper functions per PR review feedback (#8) * Initial plan * Export helper functions and add comprehensive unit tests Co-authored-by: Crow-Control <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: Crow-Control <[email protected]> * more fixes * more fixes * enforce coverage --------- Co-authored-by: Copilot <[email protected]>
1 parent 7d0a98b commit 7d0b03a

File tree

8 files changed

+795
-15
lines changed

8 files changed

+795
-15
lines changed

app/api/container.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,22 @@ describe('Container Router', () => {
10001000
expect(res.json).toHaveBeenCalledWith(expect.any(Array));
10011001
});
10021002

1003+
test('should associate trigger when configuration is missing', async () => {
1004+
const res = await callGetContainerTriggers({ id: 'c1' }, [
1005+
{ type: 'slack', name: 'default' },
1006+
]);
1007+
1008+
const triggers = getTriggersFromResponse(res);
1009+
expect(triggers).toHaveLength(1);
1010+
expect(triggers[0]).toEqual(
1011+
expect.objectContaining({
1012+
type: 'slack',
1013+
name: 'default',
1014+
configuration: {},
1015+
}),
1016+
);
1017+
});
1018+
10031019
test('should filter triggers with triggerInclude', async () => {
10041020
Trigger.parseIncludeOrIncludeTriggerString.mockReturnValue({ id: 'slack.default' });
10051021
Trigger.doesReferenceMatchId.mockImplementation((ref, id) => ref === id);
@@ -1043,6 +1059,16 @@ describe('Container Router', () => {
10431059
expect(getTriggersFromResponse(res)).toHaveLength(0);
10441060
});
10451061

1062+
test('should keep non-docker local triggers for remote containers', async () => {
1063+
const res = await callGetContainerTriggers({ id: 'c1', agent: 'agent-1' }, [
1064+
{ type: 'slack', name: 'default', configuration: {} },
1065+
]);
1066+
1067+
const triggers = getTriggersFromResponse(res);
1068+
expect(triggers).toHaveLength(1);
1069+
expect(triggers[0].type).toBe('slack');
1070+
});
1071+
10461072
test('should include triggers with matching include threshold', async () => {
10471073
Trigger.parseIncludeOrIncludeTriggerString.mockReturnValue({
10481074
id: 'slack.default',

app/api/trigger.test.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,27 @@ describe('Trigger Router', () => {
132132
expect(res.status).toHaveBeenCalledWith(200);
133133
});
134134

135+
test('should run trigger when mustTrigger is not a function', async () => {
136+
const mockTrigger = {
137+
mustTrigger: true,
138+
trigger: vi.fn().mockResolvedValue(undefined),
139+
};
140+
registry.getState.mockReturnValue({
141+
trigger: { 'slack.default': mockTrigger },
142+
});
143+
144+
const req = {
145+
params: { type: 'slack', name: 'default' },
146+
body: { id: 'c1' },
147+
};
148+
const res = createResponse();
149+
150+
await runTrigger(req, res);
151+
152+
expect(mockTrigger.trigger).toHaveBeenCalledWith(expect.objectContaining({ id: 'c1' }));
153+
expect(res.status).toHaveBeenCalledWith(200);
154+
});
155+
135156
test('should set default updateKind when missing', async () => {
136157
const mockTrigger = {
137158
mustTrigger: vi.fn().mockReturnValue(true),
@@ -240,6 +261,32 @@ describe('Trigger Router', () => {
240261
}),
241262
);
242263
});
264+
265+
test('should return 400 when trigger conditions are not met and container id is missing', async () => {
266+
const mockTrigger = {
267+
mustTrigger: vi.fn().mockReturnValue(false),
268+
trigger: vi.fn(),
269+
};
270+
registry.getState.mockReturnValue({
271+
trigger: { 'slack.default': mockTrigger },
272+
});
273+
274+
const req = {
275+
params: { type: 'slack', name: 'default' },
276+
body: {},
277+
};
278+
const res = createResponse();
279+
280+
await runTrigger(req, res);
281+
282+
expect(mockTrigger.trigger).not.toHaveBeenCalled();
283+
expect(res.status).toHaveBeenCalledWith(400);
284+
expect(res.json).toHaveBeenCalledWith(
285+
expect.objectContaining({
286+
error: expect.stringContaining('Trigger conditions not met'),
287+
}),
288+
);
289+
});
243290
});
244291

245292
describe('runRemoteTrigger', () => {
@@ -323,6 +370,36 @@ describe('Trigger Router', () => {
323370
expect(res.status).toHaveBeenCalledWith(200);
324371
});
325372

373+
test('should run remote trigger when local proxy mustTrigger is not a function', async () => {
374+
const mockAgentClient = {
375+
runRemoteTrigger: vi.fn().mockResolvedValue(undefined),
376+
};
377+
agent.getAgent.mockReturnValue(mockAgentClient);
378+
registry.getState.mockReturnValue({
379+
trigger: {
380+
'my-agent.slack.default': {
381+
mustTrigger: true,
382+
},
383+
},
384+
});
385+
386+
const handler = getRemoteTriggerHandler();
387+
const req = {
388+
params: { agent: 'my-agent', type: 'slack', name: 'default' },
389+
body: { id: 'c1' },
390+
};
391+
const res = createResponse();
392+
393+
await handler(req, res);
394+
395+
expect(mockAgentClient.runRemoteTrigger).toHaveBeenCalledWith(
396+
{ id: 'c1' },
397+
'slack',
398+
'default',
399+
);
400+
expect(res.status).toHaveBeenCalledWith(200);
401+
});
402+
326403
test('should return 400 when remote trigger conditions are not met', async () => {
327404
const mockAgentClient = {
328405
runRemoteTrigger: vi.fn().mockResolvedValue(undefined),

app/api/trigger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ async function runRemoteTrigger(req, res) {
115115
!localProxyTrigger.mustTrigger(containerToTrigger)
116116
) {
117117
log.warn(
118-
`Remote trigger conditions not met (agent=${sanitizeLogParam(agentName)}, type=${sanitizeLogParam(triggerType)}, name=${sanitizeLogParam(triggerName)}, container=${sanitizeLogParam(containerToTrigger.id || 'unknown')})`,
118+
`Remote trigger conditions not met (agent=${sanitizeLogParam(agentName)}, type=${sanitizeLogParam(triggerType)}, name=${sanitizeLogParam(triggerName)}, container=${sanitizeLogParam(containerToTrigger.id)})`,
119119
);
120120
res.status(400).json({
121121
error: `Trigger conditions not met for ${triggerType}.${triggerName} on agent ${agentName} (check include/exclude and requireinclude settings)`,

0 commit comments

Comments
 (0)