@dependabit/action 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +225 -0
- package/action.yml +85 -0
- package/dist/actions/check.d.ts +33 -0
- package/dist/actions/check.d.ts.map +1 -0
- package/dist/actions/check.js +162 -0
- package/dist/actions/check.js.map +1 -0
- package/dist/actions/generate.d.ts +9 -0
- package/dist/actions/generate.d.ts.map +1 -0
- package/dist/actions/generate.js +152 -0
- package/dist/actions/generate.js.map +1 -0
- package/dist/actions/update.d.ts +9 -0
- package/dist/actions/update.d.ts.map +1 -0
- package/dist/actions/update.js +246 -0
- package/dist/actions/update.js.map +1 -0
- package/dist/actions/validate.d.ts +33 -0
- package/dist/actions/validate.d.ts.map +1 -0
- package/dist/actions/validate.js +226 -0
- package/dist/actions/validate.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +114 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +154 -0
- package/dist/logger.js.map +1 -0
- package/dist/utils/agent-config.d.ts +31 -0
- package/dist/utils/agent-config.d.ts.map +1 -0
- package/dist/utils/agent-config.js +42 -0
- package/dist/utils/agent-config.js.map +1 -0
- package/dist/utils/agent-router.d.ts +33 -0
- package/dist/utils/agent-router.d.ts.map +1 -0
- package/dist/utils/agent-router.js +57 -0
- package/dist/utils/agent-router.js.map +1 -0
- package/dist/utils/errors.d.ts +51 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +219 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/inputs.d.ts +35 -0
- package/dist/utils/inputs.d.ts.map +1 -0
- package/dist/utils/inputs.js +47 -0
- package/dist/utils/inputs.js.map +1 -0
- package/dist/utils/metrics.d.ts +66 -0
- package/dist/utils/metrics.d.ts.map +1 -0
- package/dist/utils/metrics.js +116 -0
- package/dist/utils/metrics.js.map +1 -0
- package/dist/utils/outputs.d.ts +43 -0
- package/dist/utils/outputs.d.ts.map +1 -0
- package/dist/utils/outputs.js +146 -0
- package/dist/utils/outputs.js.map +1 -0
- package/dist/utils/performance.d.ts +100 -0
- package/dist/utils/performance.d.ts.map +1 -0
- package/dist/utils/performance.js +185 -0
- package/dist/utils/performance.js.map +1 -0
- package/dist/utils/reporter.d.ts +43 -0
- package/dist/utils/reporter.d.ts.map +1 -0
- package/dist/utils/reporter.js +122 -0
- package/dist/utils/reporter.js.map +1 -0
- package/dist/utils/secrets.d.ts +45 -0
- package/dist/utils/secrets.d.ts.map +1 -0
- package/dist/utils/secrets.js +94 -0
- package/dist/utils/secrets.js.map +1 -0
- package/package.json +45 -0
- package/src/actions/check.ts +223 -0
- package/src/actions/generate.ts +181 -0
- package/src/actions/update.ts +284 -0
- package/src/actions/validate.ts +292 -0
- package/src/index.ts +43 -0
- package/src/logger.test.ts +200 -0
- package/src/logger.ts +210 -0
- package/src/utils/agent-config.ts +61 -0
- package/src/utils/agent-router.ts +67 -0
- package/src/utils/errors.ts +251 -0
- package/src/utils/inputs.ts +75 -0
- package/src/utils/metrics.ts +169 -0
- package/src/utils/outputs.ts +202 -0
- package/src/utils/performance.ts +248 -0
- package/src/utils/reporter.ts +169 -0
- package/src/utils/secrets.ts +124 -0
- package/test/actions/check.test.ts +216 -0
- package/test/actions/generate.test.ts +82 -0
- package/test/actions/update.test.ts +70 -0
- package/test/actions/validate.test.ts +257 -0
- package/test/utils/agent-config.test.ts +112 -0
- package/test/utils/agent-router.test.ts +129 -0
- package/test/utils/metrics.test.ts +221 -0
- package/test/utils/reporter.test.ts +196 -0
- package/test/utils/secrets.test.ts +217 -0
- package/tsconfig.json +15 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { validateAction } from '../../src/actions/validate.js';
|
|
3
|
+
import type { DependencyManifest, DependabitConfig } from '@dependabit/manifest';
|
|
4
|
+
|
|
5
|
+
// Mock the manifest module
|
|
6
|
+
vi.mock('@dependabit/manifest', async () => {
|
|
7
|
+
const actual = await vi.importActual('@dependabit/manifest');
|
|
8
|
+
return {
|
|
9
|
+
...actual,
|
|
10
|
+
readManifest: vi.fn(),
|
|
11
|
+
validateManifest: vi.fn(),
|
|
12
|
+
readConfig: vi.fn()
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe('Validate Action', () => {
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
vi.clearAllMocks();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('validateAction', () => {
|
|
22
|
+
it('should validate a valid manifest successfully', async () => {
|
|
23
|
+
const { readManifest, validateManifest } = await import('@dependabit/manifest');
|
|
24
|
+
|
|
25
|
+
const validManifest: DependencyManifest = {
|
|
26
|
+
version: '1.0.0',
|
|
27
|
+
generatedAt: new Date().toISOString(),
|
|
28
|
+
generatedBy: {
|
|
29
|
+
action: 'dependabit',
|
|
30
|
+
version: '1.0.0',
|
|
31
|
+
llmProvider: 'github-copilot',
|
|
32
|
+
llmModel: 'gpt-4'
|
|
33
|
+
},
|
|
34
|
+
repository: {
|
|
35
|
+
owner: 'test-owner',
|
|
36
|
+
name: 'test-repo',
|
|
37
|
+
branch: 'main',
|
|
38
|
+
commit: 'abc123'
|
|
39
|
+
},
|
|
40
|
+
dependencies: [
|
|
41
|
+
{
|
|
42
|
+
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
43
|
+
url: 'https://github.com/microsoft/TypeScript',
|
|
44
|
+
type: 'reference-implementation',
|
|
45
|
+
accessMethod: 'github-api',
|
|
46
|
+
name: 'TypeScript',
|
|
47
|
+
currentStateHash: 'hash1',
|
|
48
|
+
detectionMethod: 'package-json',
|
|
49
|
+
detectionConfidence: 1.0,
|
|
50
|
+
detectedAt: new Date().toISOString(),
|
|
51
|
+
lastChecked: new Date().toISOString(),
|
|
52
|
+
referencedIn: [{ file: 'package.json', line: 15 }],
|
|
53
|
+
changeHistory: []
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
statistics: {
|
|
57
|
+
totalDependencies: 1,
|
|
58
|
+
byType: { 'reference-implementation': 1 },
|
|
59
|
+
byAccessMethod: { 'github-api': 1 },
|
|
60
|
+
byDetectionMethod: { 'package-json': 1 },
|
|
61
|
+
averageConfidence: 1.0
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
vi.mocked(readManifest).mockResolvedValue(validManifest);
|
|
66
|
+
vi.mocked(validateManifest).mockReturnValue(validManifest);
|
|
67
|
+
|
|
68
|
+
const result = await validateAction('.dependabit/manifest.json');
|
|
69
|
+
|
|
70
|
+
expect(result.valid).toBe(true);
|
|
71
|
+
expect(result.errors).toHaveLength(0);
|
|
72
|
+
expect(readManifest).toHaveBeenCalledWith('.dependabit/manifest.json');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should detect schema validation errors', async () => {
|
|
76
|
+
const { readManifest, validateManifest } = await import('@dependabit/manifest');
|
|
77
|
+
|
|
78
|
+
const invalidManifest = {
|
|
79
|
+
version: '2.0.0', // Invalid version
|
|
80
|
+
dependencies: []
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
vi.mocked(readManifest).mockResolvedValue(invalidManifest as any);
|
|
84
|
+
vi.mocked(validateManifest).mockImplementation(() => {
|
|
85
|
+
throw new Error('Invalid manifest version');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const result = await validateAction('.dependabit/manifest.json');
|
|
89
|
+
|
|
90
|
+
expect(result.valid).toBe(false);
|
|
91
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
92
|
+
expect(result.errors[0]).toContain('Invalid manifest version');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should detect duplicate dependency IDs', async () => {
|
|
96
|
+
const { readManifest, validateManifest } = await import('@dependabit/manifest');
|
|
97
|
+
|
|
98
|
+
const duplicateManifest: DependencyManifest = {
|
|
99
|
+
version: '1.0.0',
|
|
100
|
+
generatedAt: new Date().toISOString(),
|
|
101
|
+
generatedBy: {
|
|
102
|
+
action: 'dependabit',
|
|
103
|
+
version: '1.0.0',
|
|
104
|
+
llmProvider: 'github-copilot'
|
|
105
|
+
},
|
|
106
|
+
repository: {
|
|
107
|
+
owner: 'test',
|
|
108
|
+
name: 'test',
|
|
109
|
+
branch: 'main',
|
|
110
|
+
commit: 'abc'
|
|
111
|
+
},
|
|
112
|
+
dependencies: [
|
|
113
|
+
{
|
|
114
|
+
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
115
|
+
url: 'https://github.com/owner/repo1',
|
|
116
|
+
type: 'reference-implementation',
|
|
117
|
+
accessMethod: 'github-api',
|
|
118
|
+
name: 'Repo1',
|
|
119
|
+
currentStateHash: 'hash1',
|
|
120
|
+
detectionMethod: 'manual',
|
|
121
|
+
detectionConfidence: 1.0,
|
|
122
|
+
detectedAt: new Date().toISOString(),
|
|
123
|
+
lastChecked: new Date().toISOString(),
|
|
124
|
+
referencedIn: [],
|
|
125
|
+
changeHistory: []
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: '550e8400-e29b-41d4-a716-446655440000', // Duplicate ID
|
|
129
|
+
url: 'https://github.com/owner/repo2',
|
|
130
|
+
type: 'reference-implementation',
|
|
131
|
+
accessMethod: 'github-api',
|
|
132
|
+
name: 'Repo2',
|
|
133
|
+
currentStateHash: 'hash2',
|
|
134
|
+
detectionMethod: 'manual',
|
|
135
|
+
detectionConfidence: 1.0,
|
|
136
|
+
detectedAt: new Date().toISOString(),
|
|
137
|
+
lastChecked: new Date().toISOString(),
|
|
138
|
+
referencedIn: [],
|
|
139
|
+
changeHistory: []
|
|
140
|
+
}
|
|
141
|
+
],
|
|
142
|
+
statistics: {
|
|
143
|
+
totalDependencies: 2,
|
|
144
|
+
byType: { 'reference-implementation': 2 },
|
|
145
|
+
byAccessMethod: { 'github-api': 2 },
|
|
146
|
+
byDetectionMethod: { manual: 2 },
|
|
147
|
+
averageConfidence: 1.0
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
vi.mocked(readManifest).mockResolvedValue(duplicateManifest);
|
|
152
|
+
vi.mocked(validateManifest).mockReturnValue(duplicateManifest);
|
|
153
|
+
|
|
154
|
+
const result = await validateAction('.dependabit/manifest.json');
|
|
155
|
+
|
|
156
|
+
expect(result.valid).toBe(false);
|
|
157
|
+
expect(result.errors.some((e) => e.includes('duplicate') || e.includes('Duplicate'))).toBe(
|
|
158
|
+
true
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should detect invalid URLs', async () => {
|
|
163
|
+
const { readManifest, validateManifest } = await import('@dependabit/manifest');
|
|
164
|
+
|
|
165
|
+
const invalidUrlManifest: any = {
|
|
166
|
+
version: '1.0.0',
|
|
167
|
+
generatedAt: new Date().toISOString(),
|
|
168
|
+
generatedBy: {
|
|
169
|
+
action: 'dependabit',
|
|
170
|
+
version: '1.0.0',
|
|
171
|
+
llmProvider: 'github-copilot'
|
|
172
|
+
},
|
|
173
|
+
repository: {
|
|
174
|
+
owner: 'test',
|
|
175
|
+
name: 'test',
|
|
176
|
+
branch: 'main',
|
|
177
|
+
commit: 'abc'
|
|
178
|
+
},
|
|
179
|
+
dependencies: [
|
|
180
|
+
{
|
|
181
|
+
id: '550e8400-e29b-41d4-a716-446655440000',
|
|
182
|
+
url: 'not-a-valid-url',
|
|
183
|
+
type: 'reference-implementation',
|
|
184
|
+
accessMethod: 'github-api',
|
|
185
|
+
name: 'Invalid',
|
|
186
|
+
currentStateHash: 'hash1',
|
|
187
|
+
detectionMethod: 'manual',
|
|
188
|
+
detectionConfidence: 1.0,
|
|
189
|
+
detectedAt: new Date().toISOString(),
|
|
190
|
+
lastChecked: new Date().toISOString(),
|
|
191
|
+
referencedIn: [],
|
|
192
|
+
changeHistory: []
|
|
193
|
+
}
|
|
194
|
+
],
|
|
195
|
+
statistics: {
|
|
196
|
+
totalDependencies: 1,
|
|
197
|
+
byType: { 'reference-implementation': 1 },
|
|
198
|
+
byAccessMethod: { 'github-api': 1 },
|
|
199
|
+
byDetectionMethod: { manual: 1 },
|
|
200
|
+
averageConfidence: 1.0
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
vi.mocked(readManifest).mockResolvedValue(invalidUrlManifest);
|
|
205
|
+
vi.mocked(validateManifest).mockImplementation(() => {
|
|
206
|
+
throw new Error('Invalid URL format');
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const result = await validateAction('.dependabit/manifest.json');
|
|
210
|
+
|
|
211
|
+
expect(result.valid).toBe(false);
|
|
212
|
+
expect(result.errors.some((e) => e.includes('URL') || e.includes('url'))).toBe(true);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('should validate with config file when provided', async () => {
|
|
216
|
+
const { readManifest, readConfig, validateManifest } = await import('@dependabit/manifest');
|
|
217
|
+
|
|
218
|
+
const manifest: DependencyManifest = {
|
|
219
|
+
version: '1.0.0',
|
|
220
|
+
generatedAt: new Date().toISOString(),
|
|
221
|
+
generatedBy: {
|
|
222
|
+
action: 'dependabit',
|
|
223
|
+
version: '1.0.0',
|
|
224
|
+
llmProvider: 'github-copilot'
|
|
225
|
+
},
|
|
226
|
+
repository: {
|
|
227
|
+
owner: 'test',
|
|
228
|
+
name: 'test',
|
|
229
|
+
branch: 'main',
|
|
230
|
+
commit: 'abc'
|
|
231
|
+
},
|
|
232
|
+
dependencies: [],
|
|
233
|
+
statistics: {
|
|
234
|
+
totalDependencies: 0,
|
|
235
|
+
byType: {},
|
|
236
|
+
byAccessMethod: {},
|
|
237
|
+
byDetectionMethod: {},
|
|
238
|
+
averageConfidence: 0
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const config: DependabitConfig = {
|
|
243
|
+
version: '1',
|
|
244
|
+
schedule: { interval: 'daily', timezone: 'UTC' }
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
vi.mocked(readManifest).mockResolvedValue(manifest);
|
|
248
|
+
vi.mocked(readConfig).mockResolvedValue(config);
|
|
249
|
+
vi.mocked(validateManifest).mockReturnValue(manifest);
|
|
250
|
+
|
|
251
|
+
const result = await validateAction('.dependabit/manifest.json', '.dependabit/config.yml');
|
|
252
|
+
|
|
253
|
+
expect(result.valid).toBe(true);
|
|
254
|
+
expect(readConfig).toHaveBeenCalledWith('.dependabit/config.yml');
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { parseAgentConfig, type AgentAssignmentConfig } from '../../src/utils/agent-config.js';
|
|
3
|
+
import type { DependabitConfig } from '@dependabit/manifest';
|
|
4
|
+
|
|
5
|
+
describe('Agent Config Parser', () => {
|
|
6
|
+
describe('parseAgentConfig', () => {
|
|
7
|
+
it('should parse agent assignment configuration', () => {
|
|
8
|
+
const config: DependabitConfig = {
|
|
9
|
+
version: '1',
|
|
10
|
+
schedule: { interval: 'daily', timezone: 'UTC' },
|
|
11
|
+
issues: {
|
|
12
|
+
labels: ['dependabit'],
|
|
13
|
+
assignees: [],
|
|
14
|
+
aiAgentAssignment: {
|
|
15
|
+
enabled: true,
|
|
16
|
+
breaking: 'copilot',
|
|
17
|
+
major: 'claude',
|
|
18
|
+
minor: 'copilot'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const result = parseAgentConfig(config);
|
|
24
|
+
|
|
25
|
+
expect(result.enabled).toBe(true);
|
|
26
|
+
expect(result.severityMapping).toEqual({
|
|
27
|
+
breaking: 'copilot',
|
|
28
|
+
major: 'claude',
|
|
29
|
+
minor: 'copilot'
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should return disabled config when aiAgentAssignment is not set', () => {
|
|
34
|
+
const config: DependabitConfig = {
|
|
35
|
+
version: '1',
|
|
36
|
+
schedule: { interval: 'daily', timezone: 'UTC' }
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const result = parseAgentConfig(config);
|
|
40
|
+
|
|
41
|
+
expect(result.enabled).toBe(false);
|
|
42
|
+
expect(result.severityMapping).toEqual({});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should return disabled config when aiAgentAssignment is explicitly disabled', () => {
|
|
46
|
+
const config: DependabitConfig = {
|
|
47
|
+
version: '1',
|
|
48
|
+
schedule: { interval: 'daily', timezone: 'UTC' },
|
|
49
|
+
issues: {
|
|
50
|
+
labels: ['dependabit'],
|
|
51
|
+
assignees: [],
|
|
52
|
+
aiAgentAssignment: {
|
|
53
|
+
enabled: false,
|
|
54
|
+
breaking: 'copilot'
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const result = parseAgentConfig(config);
|
|
60
|
+
|
|
61
|
+
expect(result.enabled).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should handle partial severity mappings', () => {
|
|
65
|
+
const config: DependabitConfig = {
|
|
66
|
+
version: '1',
|
|
67
|
+
schedule: { interval: 'daily', timezone: 'UTC' },
|
|
68
|
+
issues: {
|
|
69
|
+
labels: ['dependabit'],
|
|
70
|
+
assignees: [],
|
|
71
|
+
aiAgentAssignment: {
|
|
72
|
+
enabled: true,
|
|
73
|
+
breaking: 'copilot'
|
|
74
|
+
// major and minor not specified
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const result = parseAgentConfig(config);
|
|
80
|
+
|
|
81
|
+
expect(result.enabled).toBe(true);
|
|
82
|
+
expect(result.severityMapping.breaking).toBe('copilot');
|
|
83
|
+
expect(result.severityMapping.major).toBeUndefined();
|
|
84
|
+
expect(result.severityMapping.minor).toBeUndefined();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should normalize agent names to lowercase', () => {
|
|
88
|
+
const config: DependabitConfig = {
|
|
89
|
+
version: '1',
|
|
90
|
+
schedule: { interval: 'daily', timezone: 'UTC' },
|
|
91
|
+
issues: {
|
|
92
|
+
labels: ['dependabit'],
|
|
93
|
+
assignees: [],
|
|
94
|
+
aiAgentAssignment: {
|
|
95
|
+
enabled: true,
|
|
96
|
+
breaking: 'COPILOT',
|
|
97
|
+
major: 'Claude',
|
|
98
|
+
minor: 'CoPiLoT'
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const result = parseAgentConfig(config);
|
|
104
|
+
|
|
105
|
+
expect(result.severityMapping).toEqual({
|
|
106
|
+
breaking: 'copilot',
|
|
107
|
+
major: 'claude',
|
|
108
|
+
minor: 'copilot'
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
routeToAgent,
|
|
4
|
+
getAssigneeLabel,
|
|
5
|
+
type AgentAssignmentConfig
|
|
6
|
+
} from '../../src/utils/agent-router.js';
|
|
7
|
+
import type { Severity } from '@dependabit/manifest';
|
|
8
|
+
|
|
9
|
+
describe('Agent Router', () => {
|
|
10
|
+
describe('routeToAgent', () => {
|
|
11
|
+
it('should route breaking changes to configured agent', () => {
|
|
12
|
+
const config: AgentAssignmentConfig = {
|
|
13
|
+
enabled: true,
|
|
14
|
+
severityMapping: {
|
|
15
|
+
breaking: 'copilot',
|
|
16
|
+
major: 'claude',
|
|
17
|
+
minor: 'copilot'
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const result = routeToAgent('breaking', config);
|
|
22
|
+
|
|
23
|
+
expect(result).toBe('copilot');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should route major changes to configured agent', () => {
|
|
27
|
+
const config: AgentAssignmentConfig = {
|
|
28
|
+
enabled: true,
|
|
29
|
+
severityMapping: {
|
|
30
|
+
breaking: 'copilot',
|
|
31
|
+
major: 'claude',
|
|
32
|
+
minor: 'copilot'
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const result = routeToAgent('major', config);
|
|
37
|
+
|
|
38
|
+
expect(result).toBe('claude');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should route minor changes to configured agent', () => {
|
|
42
|
+
const config: AgentAssignmentConfig = {
|
|
43
|
+
enabled: true,
|
|
44
|
+
severityMapping: {
|
|
45
|
+
breaking: 'copilot',
|
|
46
|
+
major: 'claude',
|
|
47
|
+
minor: 'copilot'
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const result = routeToAgent('minor', config);
|
|
52
|
+
|
|
53
|
+
expect(result).toBe('copilot');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should return null when routing is disabled', () => {
|
|
57
|
+
const config: AgentAssignmentConfig = {
|
|
58
|
+
enabled: false,
|
|
59
|
+
severityMapping: {
|
|
60
|
+
breaking: 'copilot'
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const result = routeToAgent('breaking', config);
|
|
65
|
+
|
|
66
|
+
expect(result).toBeNull();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should return null when no mapping exists for severity', () => {
|
|
70
|
+
const config: AgentAssignmentConfig = {
|
|
71
|
+
enabled: true,
|
|
72
|
+
severityMapping: {
|
|
73
|
+
breaking: 'copilot'
|
|
74
|
+
// major and minor not specified
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const result = routeToAgent('major', config);
|
|
79
|
+
|
|
80
|
+
expect(result).toBeNull();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should return null for unknown severity levels', () => {
|
|
84
|
+
const config: AgentAssignmentConfig = {
|
|
85
|
+
enabled: true,
|
|
86
|
+
severityMapping: {
|
|
87
|
+
breaking: 'copilot',
|
|
88
|
+
major: 'claude',
|
|
89
|
+
minor: 'copilot'
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const result = routeToAgent('unknown' as Severity, config);
|
|
94
|
+
|
|
95
|
+
expect(result).toBeNull();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should handle empty severity mapping', () => {
|
|
99
|
+
const config: AgentAssignmentConfig = {
|
|
100
|
+
enabled: true,
|
|
101
|
+
severityMapping: {}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const result = routeToAgent('breaking', config);
|
|
105
|
+
|
|
106
|
+
expect(result).toBeNull();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('getAssigneeLabel', () => {
|
|
111
|
+
it('should generate assignee label for copilot', () => {
|
|
112
|
+
const result = getAssigneeLabel('copilot');
|
|
113
|
+
|
|
114
|
+
expect(result).toBe('assigned:copilot');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should generate assignee label for claude', () => {
|
|
118
|
+
const result = getAssigneeLabel('claude');
|
|
119
|
+
|
|
120
|
+
expect(result).toBe('assigned:claude');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should handle null agent gracefully', () => {
|
|
124
|
+
const result = getAssigneeLabel(null);
|
|
125
|
+
|
|
126
|
+
expect(result).toBeNull();
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|