@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.
Files changed (92) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +225 -0
  4. package/action.yml +85 -0
  5. package/dist/actions/check.d.ts +33 -0
  6. package/dist/actions/check.d.ts.map +1 -0
  7. package/dist/actions/check.js +162 -0
  8. package/dist/actions/check.js.map +1 -0
  9. package/dist/actions/generate.d.ts +9 -0
  10. package/dist/actions/generate.d.ts.map +1 -0
  11. package/dist/actions/generate.js +152 -0
  12. package/dist/actions/generate.js.map +1 -0
  13. package/dist/actions/update.d.ts +9 -0
  14. package/dist/actions/update.d.ts.map +1 -0
  15. package/dist/actions/update.js +246 -0
  16. package/dist/actions/update.js.map +1 -0
  17. package/dist/actions/validate.d.ts +33 -0
  18. package/dist/actions/validate.d.ts.map +1 -0
  19. package/dist/actions/validate.js +226 -0
  20. package/dist/actions/validate.js.map +1 -0
  21. package/dist/index.d.ts +8 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +35 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/logger.d.ts +114 -0
  26. package/dist/logger.d.ts.map +1 -0
  27. package/dist/logger.js +154 -0
  28. package/dist/logger.js.map +1 -0
  29. package/dist/utils/agent-config.d.ts +31 -0
  30. package/dist/utils/agent-config.d.ts.map +1 -0
  31. package/dist/utils/agent-config.js +42 -0
  32. package/dist/utils/agent-config.js.map +1 -0
  33. package/dist/utils/agent-router.d.ts +33 -0
  34. package/dist/utils/agent-router.d.ts.map +1 -0
  35. package/dist/utils/agent-router.js +57 -0
  36. package/dist/utils/agent-router.js.map +1 -0
  37. package/dist/utils/errors.d.ts +51 -0
  38. package/dist/utils/errors.d.ts.map +1 -0
  39. package/dist/utils/errors.js +219 -0
  40. package/dist/utils/errors.js.map +1 -0
  41. package/dist/utils/inputs.d.ts +35 -0
  42. package/dist/utils/inputs.d.ts.map +1 -0
  43. package/dist/utils/inputs.js +47 -0
  44. package/dist/utils/inputs.js.map +1 -0
  45. package/dist/utils/metrics.d.ts +66 -0
  46. package/dist/utils/metrics.d.ts.map +1 -0
  47. package/dist/utils/metrics.js +116 -0
  48. package/dist/utils/metrics.js.map +1 -0
  49. package/dist/utils/outputs.d.ts +43 -0
  50. package/dist/utils/outputs.d.ts.map +1 -0
  51. package/dist/utils/outputs.js +146 -0
  52. package/dist/utils/outputs.js.map +1 -0
  53. package/dist/utils/performance.d.ts +100 -0
  54. package/dist/utils/performance.d.ts.map +1 -0
  55. package/dist/utils/performance.js +185 -0
  56. package/dist/utils/performance.js.map +1 -0
  57. package/dist/utils/reporter.d.ts +43 -0
  58. package/dist/utils/reporter.d.ts.map +1 -0
  59. package/dist/utils/reporter.js +122 -0
  60. package/dist/utils/reporter.js.map +1 -0
  61. package/dist/utils/secrets.d.ts +45 -0
  62. package/dist/utils/secrets.d.ts.map +1 -0
  63. package/dist/utils/secrets.js +94 -0
  64. package/dist/utils/secrets.js.map +1 -0
  65. package/package.json +45 -0
  66. package/src/actions/check.ts +223 -0
  67. package/src/actions/generate.ts +181 -0
  68. package/src/actions/update.ts +284 -0
  69. package/src/actions/validate.ts +292 -0
  70. package/src/index.ts +43 -0
  71. package/src/logger.test.ts +200 -0
  72. package/src/logger.ts +210 -0
  73. package/src/utils/agent-config.ts +61 -0
  74. package/src/utils/agent-router.ts +67 -0
  75. package/src/utils/errors.ts +251 -0
  76. package/src/utils/inputs.ts +75 -0
  77. package/src/utils/metrics.ts +169 -0
  78. package/src/utils/outputs.ts +202 -0
  79. package/src/utils/performance.ts +248 -0
  80. package/src/utils/reporter.ts +169 -0
  81. package/src/utils/secrets.ts +124 -0
  82. package/test/actions/check.test.ts +216 -0
  83. package/test/actions/generate.test.ts +82 -0
  84. package/test/actions/update.test.ts +70 -0
  85. package/test/actions/validate.test.ts +257 -0
  86. package/test/utils/agent-config.test.ts +112 -0
  87. package/test/utils/agent-router.test.ts +129 -0
  88. package/test/utils/metrics.test.ts +221 -0
  89. package/test/utils/reporter.test.ts +196 -0
  90. package/test/utils/secrets.test.ts +217 -0
  91. package/tsconfig.json +15 -0
  92. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,33 @@
1
+ import type { Severity } from '@dependabit/manifest';
2
+ import type { AgentAssignmentConfig } from './agent-config';
3
+ /**
4
+ * Route issue to appropriate AI agent based on severity
5
+ *
6
+ * Uses severity-to-agent mapping from configuration to determine
7
+ * which AI agent should be assigned to handle the issue.
8
+ *
9
+ * @param severity Change severity (breaking, major, minor)
10
+ * @param config Agent assignment configuration
11
+ * @returns Agent name (e.g., 'copilot', 'claude') or null if not configured
12
+ */
13
+ export declare function routeToAgent(severity: Severity, config: AgentAssignmentConfig): string | null;
14
+ /**
15
+ * Generate assignee label for issue
16
+ *
17
+ * Creates a label in format "assigned:agent" that can be used
18
+ * to trigger agent-specific workflows or assign the issue.
19
+ *
20
+ * @param agent Agent name or null
21
+ * @returns Label string or null
22
+ */
23
+ export declare function getAssigneeLabel(agent: string | null): string | null;
24
+ /**
25
+ * Get all configured agents
26
+ *
27
+ * Returns list of unique agent names configured in the severity mapping
28
+ *
29
+ * @param config Agent assignment configuration
30
+ * @returns Array of agent names
31
+ */
32
+ export declare function getConfiguredAgents(config: AgentAssignmentConfig): string[];
33
+ //# sourceMappingURL=agent-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-router.d.ts","sourceRoot":"","sources":["../../src/utils/agent-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC5D;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI,CAO7F;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAMpE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,EAAE,CAoB3E"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Route issue to appropriate AI agent based on severity
3
+ *
4
+ * Uses severity-to-agent mapping from configuration to determine
5
+ * which AI agent should be assigned to handle the issue.
6
+ *
7
+ * @param severity Change severity (breaking, major, minor)
8
+ * @param config Agent assignment configuration
9
+ * @returns Agent name (e.g., 'copilot', 'claude') or null if not configured
10
+ */
11
+ export function routeToAgent(severity, config) {
12
+ if (!config.enabled) {
13
+ return null;
14
+ }
15
+ const agent = config.severityMapping[severity];
16
+ return agent || null;
17
+ }
18
+ /**
19
+ * Generate assignee label for issue
20
+ *
21
+ * Creates a label in format "assigned:agent" that can be used
22
+ * to trigger agent-specific workflows or assign the issue.
23
+ *
24
+ * @param agent Agent name or null
25
+ * @returns Label string or null
26
+ */
27
+ export function getAssigneeLabel(agent) {
28
+ if (!agent) {
29
+ return null;
30
+ }
31
+ return `assigned:${agent}`;
32
+ }
33
+ /**
34
+ * Get all configured agents
35
+ *
36
+ * Returns list of unique agent names configured in the severity mapping
37
+ *
38
+ * @param config Agent assignment configuration
39
+ * @returns Array of agent names
40
+ */
41
+ export function getConfiguredAgents(config) {
42
+ if (!config.enabled) {
43
+ return [];
44
+ }
45
+ const agents = new Set();
46
+ if (config.severityMapping.breaking) {
47
+ agents.add(config.severityMapping.breaking);
48
+ }
49
+ if (config.severityMapping.major) {
50
+ agents.add(config.severityMapping.major);
51
+ }
52
+ if (config.severityMapping.minor) {
53
+ agents.add(config.severityMapping.minor);
54
+ }
55
+ return Array.from(agents);
56
+ }
57
+ //# sourceMappingURL=agent-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-router.js","sourceRoot":"","sources":["../../src/utils/agent-router.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,QAAkB,EAAE,MAA6B,EAAiB;IAC7F,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO,KAAK,IAAI,IAAI,CAAC;AAAA,CACtB;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAoB,EAAiB;IACpE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,YAAY,KAAK,EAAE,CAAC;AAAA,CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAA6B,EAAY;IAC3E,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IAEjC,IAAI,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAAA,CAC3B"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Error categorization and remediation messages
3
+ * Provides actionable error messages with remediation steps
4
+ */
5
+ export declare enum ErrorCategory {
6
+ AUTHENTICATION = "authentication",
7
+ RATE_LIMIT = "rate_limit",
8
+ NETWORK = "network",
9
+ VALIDATION = "validation",
10
+ NOT_FOUND = "not_found",
11
+ PERMISSION = "permission",
12
+ CONFIGURATION = "configuration",
13
+ INTERNAL = "internal"
14
+ }
15
+ export interface CategorizedError {
16
+ category: ErrorCategory;
17
+ message: string;
18
+ originalError: Error;
19
+ remediation: string[];
20
+ context?: Record<string, unknown> | undefined;
21
+ }
22
+ /**
23
+ * Error categorizer with remediation suggestions
24
+ */
25
+ export declare class ErrorCategorizer {
26
+ /**
27
+ * Categorize an error and provide remediation steps
28
+ */
29
+ categorize(error: Error, context?: Record<string, unknown>): CategorizedError;
30
+ /**
31
+ * Format error with remediation for display
32
+ */
33
+ format(categorizedError: CategorizedError): string;
34
+ /**
35
+ * Check if error is retryable
36
+ */
37
+ isRetryable(categorizedError: CategorizedError): boolean;
38
+ /**
39
+ * Get recommended retry delay in milliseconds
40
+ */
41
+ getRetryDelay(categorizedError: CategorizedError): number;
42
+ }
43
+ /**
44
+ * Create a categorized error from an exception
45
+ */
46
+ export declare function categorizeError(error: Error, context?: Record<string, unknown>): CategorizedError;
47
+ /**
48
+ * Format error with remediation steps
49
+ */
50
+ export declare function formatError(error: Error, context?: Record<string, unknown>): string;
51
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oBAAY,aAAa;IACvB,cAAc,mBAAmB;IACjC,UAAU,eAAe;IACzB,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,SAAS,cAAc;IACvB,UAAU,eAAe;IACzB,aAAa,kBAAkB;IAC/B,QAAQ,aAAa;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,KAAK,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAC/C;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,CA8J5E;IAED;;OAEG;IACH,MAAM,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,MAAM,CAiBjD;IAED;;OAEG;IACH,WAAW,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAEvD;IAED;;OAEG;IACH,aAAa,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,MAAM,CASxD;CACF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,CAGjG;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAInF"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Error categorization and remediation messages
3
+ * Provides actionable error messages with remediation steps
4
+ */
5
+ export { ErrorCategory };
6
+ var ErrorCategory;
7
+ (function (ErrorCategory) {
8
+ ErrorCategory["AUTHENTICATION"] = "authentication";
9
+ ErrorCategory["RATE_LIMIT"] = "rate_limit";
10
+ ErrorCategory["NETWORK"] = "network";
11
+ ErrorCategory["VALIDATION"] = "validation";
12
+ ErrorCategory["NOT_FOUND"] = "not_found";
13
+ ErrorCategory["PERMISSION"] = "permission";
14
+ ErrorCategory["CONFIGURATION"] = "configuration";
15
+ ErrorCategory["INTERNAL"] = "internal";
16
+ })(ErrorCategory || (ErrorCategory = {}));
17
+ /**
18
+ * Error categorizer with remediation suggestions
19
+ */
20
+ export class ErrorCategorizer {
21
+ /**
22
+ * Categorize an error and provide remediation steps
23
+ */
24
+ categorize(error, context) {
25
+ const message = error.message.toLowerCase();
26
+ // Authentication errors
27
+ if (message.includes('authentication') ||
28
+ message.includes('unauthorized') ||
29
+ message.includes('invalid token') ||
30
+ message.includes('bad credentials')) {
31
+ return {
32
+ category: ErrorCategory.AUTHENTICATION,
33
+ message: error.message,
34
+ originalError: error,
35
+ remediation: [
36
+ 'Verify that GITHUB_TOKEN is set correctly',
37
+ 'Check token has required permissions (repo, issues, contents)',
38
+ 'Ensure token has not expired',
39
+ 'For fine-grained tokens, verify repository access is granted',
40
+ 'Try regenerating the token if issues persist'
41
+ ],
42
+ context
43
+ };
44
+ }
45
+ // Rate limit errors
46
+ if (message.includes('rate limit') ||
47
+ message.includes('api rate limit exceeded') ||
48
+ message.includes('secondary rate limit')) {
49
+ return {
50
+ category: ErrorCategory.RATE_LIMIT,
51
+ message: error.message,
52
+ originalError: error,
53
+ remediation: [
54
+ 'Wait for rate limit to reset (check X-RateLimit-Reset header)',
55
+ 'Consider using authenticated requests (higher rate limits)',
56
+ 'Implement request batching or caching',
57
+ 'Review API usage patterns to reduce calls',
58
+ 'For GitHub Actions, consider using GITHUB_TOKEN instead of PAT'
59
+ ],
60
+ context
61
+ };
62
+ }
63
+ // Network errors
64
+ if (message.includes('econnrefused') ||
65
+ message.includes('enotfound') ||
66
+ message.includes('timeout') ||
67
+ message.includes('network')) {
68
+ return {
69
+ category: ErrorCategory.NETWORK,
70
+ message: error.message,
71
+ originalError: error,
72
+ remediation: [
73
+ 'Check internet connectivity',
74
+ 'Verify API endpoint is accessible',
75
+ 'Check for firewall or proxy blocking requests',
76
+ 'Retry the operation after a short delay',
77
+ 'Verify DNS resolution is working'
78
+ ],
79
+ context
80
+ };
81
+ }
82
+ // Not found errors
83
+ if (message.includes('not found') || message.includes('404')) {
84
+ return {
85
+ category: ErrorCategory.NOT_FOUND,
86
+ message: error.message,
87
+ originalError: error,
88
+ remediation: [
89
+ 'Verify the repository owner and name are correct',
90
+ 'Check if the resource exists (branch, file, issue)',
91
+ 'Ensure you have access to the repository (private repos)',
92
+ 'Verify the URL or path is correct',
93
+ 'Check if the resource was recently deleted'
94
+ ],
95
+ context
96
+ };
97
+ }
98
+ // Permission errors
99
+ if (message.includes('permission') ||
100
+ message.includes('forbidden') ||
101
+ message.includes('403')) {
102
+ return {
103
+ category: ErrorCategory.PERMISSION,
104
+ message: error.message,
105
+ originalError: error,
106
+ remediation: [
107
+ 'Verify token has required scopes (repo, admin:org, etc.)',
108
+ 'Check repository access permissions',
109
+ 'For organization repos, verify org membership',
110
+ 'Ensure not attempting to modify protected branches',
111
+ 'Review repository settings and branch protection rules'
112
+ ],
113
+ context
114
+ };
115
+ }
116
+ // Validation errors
117
+ if (message.includes('validation') ||
118
+ message.includes('invalid') ||
119
+ message.includes('malformed')) {
120
+ return {
121
+ category: ErrorCategory.VALIDATION,
122
+ message: error.message,
123
+ originalError: error,
124
+ remediation: [
125
+ 'Check input data format and structure',
126
+ 'Verify required fields are provided',
127
+ 'Validate data types match API expectations',
128
+ 'Review API documentation for correct format',
129
+ 'Check for special characters that need escaping'
130
+ ],
131
+ context
132
+ };
133
+ }
134
+ // Configuration errors
135
+ if (message.includes('config') || message.includes('missing')) {
136
+ return {
137
+ category: ErrorCategory.CONFIGURATION,
138
+ message: error.message,
139
+ originalError: error,
140
+ remediation: [
141
+ 'Verify all required configuration values are set',
142
+ 'Check .dependabit/config.yml exists and is valid',
143
+ 'Validate configuration schema',
144
+ 'Review example configuration in documentation',
145
+ 'Ensure environment variables are properly set'
146
+ ],
147
+ context
148
+ };
149
+ }
150
+ // Default to internal error
151
+ return {
152
+ category: ErrorCategory.INTERNAL,
153
+ message: error.message,
154
+ originalError: error,
155
+ remediation: [
156
+ 'This may be an internal error or unexpected condition',
157
+ 'Check error details for more information',
158
+ 'Try running the operation again',
159
+ 'If issue persists, report it with error details',
160
+ 'Check GitHub status page for service issues'
161
+ ],
162
+ context
163
+ };
164
+ }
165
+ /**
166
+ * Format error with remediation for display
167
+ */
168
+ format(categorizedError) {
169
+ const lines = [
170
+ `Error [${categorizedError.category}]: ${categorizedError.message}`,
171
+ '',
172
+ 'Remediation steps:',
173
+ ...categorizedError.remediation.map((step, i) => ` ${i + 1}. ${step}`)
174
+ ];
175
+ if (categorizedError.context && Object.keys(categorizedError.context).length > 0) {
176
+ lines.push('');
177
+ lines.push('Context:');
178
+ for (const [key, value] of Object.entries(categorizedError.context)) {
179
+ lines.push(` ${key}: ${JSON.stringify(value)}`);
180
+ }
181
+ }
182
+ return lines.join('\n');
183
+ }
184
+ /**
185
+ * Check if error is retryable
186
+ */
187
+ isRetryable(categorizedError) {
188
+ return [ErrorCategory.NETWORK, ErrorCategory.RATE_LIMIT].includes(categorizedError.category);
189
+ }
190
+ /**
191
+ * Get recommended retry delay in milliseconds
192
+ */
193
+ getRetryDelay(categorizedError) {
194
+ switch (categorizedError.category) {
195
+ case ErrorCategory.RATE_LIMIT:
196
+ return 60000; // 1 minute
197
+ case ErrorCategory.NETWORK:
198
+ return 5000; // 5 seconds
199
+ default:
200
+ return 0; // Not retryable
201
+ }
202
+ }
203
+ }
204
+ /**
205
+ * Create a categorized error from an exception
206
+ */
207
+ export function categorizeError(error, context) {
208
+ const categorizer = new ErrorCategorizer();
209
+ return categorizer.categorize(error, context);
210
+ }
211
+ /**
212
+ * Format error with remediation steps
213
+ */
214
+ export function formatError(error, context) {
215
+ const categorizer = new ErrorCategorizer();
216
+ const categorized = categorizer.categorize(error, context);
217
+ return categorizer.format(categorized);
218
+ }
219
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Action Input Parsing
3
+ * Handles parsing and validation of GitHub Action inputs
4
+ */
5
+ export interface GenerateActionInputs {
6
+ repoPath: string;
7
+ llmProvider: 'github-copilot' | 'claude' | 'openai';
8
+ llmModel?: string;
9
+ llmApiKey?: string;
10
+ manifestPath: string;
11
+ enableDebug: boolean;
12
+ }
13
+ export interface UpdateActionInputs {
14
+ repoPath: string;
15
+ manifestPath: string;
16
+ commits: string[];
17
+ }
18
+ export interface CheckActionInputs {
19
+ manifestPath: string;
20
+ createIssues: boolean;
21
+ issueLabels: string[];
22
+ }
23
+ /**
24
+ * Parse inputs for the generate action
25
+ */
26
+ export declare function parseGenerateInputs(): GenerateActionInputs;
27
+ /**
28
+ * Parse inputs for the update action
29
+ */
30
+ export declare function parseUpdateInputs(): UpdateActionInputs;
31
+ /**
32
+ * Parse inputs for the check action
33
+ */
34
+ export declare function parseCheckInputs(): CheckActionInputs;
35
+ //# sourceMappingURL=inputs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputs.d.ts","sourceRoot":"","sources":["../../src/utils/inputs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,oBAAoB,CAa1D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,kBAAkB,CAStD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,iBAAiB,CAWpD"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Action Input Parsing
3
+ * Handles parsing and validation of GitHub Action inputs
4
+ */
5
+ import * as core from '@actions/core';
6
+ /**
7
+ * Parse inputs for the generate action
8
+ */
9
+ export function parseGenerateInputs() {
10
+ const llmModelInput = core.getInput('llm_model');
11
+ const llmApiKeyInput = core.getInput('llm_api_key') || process.env['GITHUB_TOKEN'] || process.env['OPENAI_API_KEY'];
12
+ return {
13
+ repoPath: core.getInput('repo_path') || process.cwd(),
14
+ llmProvider: (core.getInput('llm_provider') || 'github-copilot'),
15
+ ...(llmModelInput && { llmModel: llmModelInput }),
16
+ ...(llmApiKeyInput && { llmApiKey: llmApiKeyInput }),
17
+ manifestPath: core.getInput('manifest_path') || '.dependabit/manifest.json',
18
+ enableDebug: core.getInput('debug') === 'true'
19
+ };
20
+ }
21
+ /**
22
+ * Parse inputs for the update action
23
+ */
24
+ export function parseUpdateInputs() {
25
+ const commitsInput = core.getInput('commits');
26
+ const commits = commitsInput ? commitsInput.split(',').map((c) => c.trim()) : [];
27
+ return {
28
+ repoPath: core.getInput('repo_path') || process.cwd(),
29
+ manifestPath: core.getInput('manifest_path') || '.dependabit/manifest.json',
30
+ commits
31
+ };
32
+ }
33
+ /**
34
+ * Parse inputs for the check action
35
+ */
36
+ export function parseCheckInputs() {
37
+ const labelsInput = core.getInput('issue_labels');
38
+ const labels = labelsInput
39
+ ? labelsInput.split(',').map((l) => l.trim())
40
+ : ['dependabit', 'dependency-update'];
41
+ return {
42
+ manifestPath: core.getInput('manifest_path') || '.dependabit/manifest.json',
43
+ createIssues: core.getBooleanInput('create_issues') !== false,
44
+ issueLabels: labels
45
+ };
46
+ }
47
+ //# sourceMappingURL=inputs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputs.js","sourceRoot":"","sources":["../../src/utils/inputs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,IAAI,MAAM,eAAe,CAAC;AAuBtC;;GAEG;AACH,MAAM,UAAU,mBAAmB,GAAyB;IAC1D,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACjD,MAAM,cAAc,GAClB,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAE/F,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE;QACrD,WAAW,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,gBAAgB,CAAqB;QACpF,GAAG,CAAC,aAAa,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;QACjD,GAAG,CAAC,cAAc,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;QACpD,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,2BAA2B;QAC3E,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,MAAM;KAC/C,CAAC;AAAA,CACH;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,GAAuB;IACtD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEjF,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE;QACrD,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,2BAA2B;QAC3E,OAAO;KACR,CAAC;AAAA,CACH;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,GAAsB;IACpD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,WAAW;QACxB,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7C,CAAC,CAAC,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC;IAExC,OAAO;QACL,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,2BAA2B;QAC3E,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,KAAK,KAAK;QAC7D,WAAW,EAAE,MAAM;KACpB,CAAC;AAAA,CACH"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Metrics calculator for false positive rate tracking
3
+ * Implements 30-day rolling window analysis and trend detection
4
+ */
5
+ export interface MetricsConfig {
6
+ windowDays?: number;
7
+ threshold?: number;
8
+ }
9
+ export interface FeedbackSummary {
10
+ truePositives: number;
11
+ falsePositives: number;
12
+ total: number;
13
+ }
14
+ export interface DataPoint {
15
+ date: string;
16
+ falsePositiveRate: number;
17
+ }
18
+ export interface Trend {
19
+ direction: 'improving' | 'worsening' | 'stable' | 'no-data';
20
+ slope: number;
21
+ }
22
+ export interface ThresholdCheck {
23
+ passed: boolean;
24
+ rate: number;
25
+ threshold: number;
26
+ }
27
+ export interface MetricsReport {
28
+ currentRate: number;
29
+ rollingAverage: number;
30
+ trend: Trend;
31
+ thresholdCheck: ThresholdCheck;
32
+ totalFeedback: number;
33
+ }
34
+ /**
35
+ * Calculator for false positive metrics with rolling window analysis
36
+ */
37
+ export declare class MetricsCalculator {
38
+ private windowDays;
39
+ private threshold;
40
+ constructor(config?: MetricsConfig);
41
+ /**
42
+ * Calculate false positive rate from feedback data
43
+ */
44
+ calculateFalsePositiveRate(feedback: FeedbackSummary): number;
45
+ /**
46
+ * Calculate rolling average over the time window
47
+ */
48
+ calculateRollingAverage(dataPoints: DataPoint[], windowDays?: number, referenceDate?: Date): number;
49
+ /**
50
+ * Detect trend direction using linear regression
51
+ */
52
+ getTrend(dataPoints: DataPoint[]): Trend;
53
+ /**
54
+ * Check if rate is within acceptable threshold
55
+ */
56
+ checkThreshold(rate: number, threshold?: number): ThresholdCheck;
57
+ /**
58
+ * Generate comprehensive metrics report
59
+ */
60
+ generateReport(currentFeedback: FeedbackSummary, history: DataPoint[]): MetricsReport;
61
+ /**
62
+ * Format rate as percentage string
63
+ */
64
+ formatRate(rate: number): string;
65
+ }
66
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/utils/metrics.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,KAAK;IACpB,SAAS,EAAE,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC5D,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAE1B,YAAY,MAAM,GAAE,aAAkB,EAGrC;IAED;;OAEG;IACH,0BAA0B,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAK5D;IAED;;OAEG;IACH,uBAAuB,CACrB,UAAU,EAAE,SAAS,EAAE,EACvB,UAAU,CAAC,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,IAAI,GACnB,MAAM,CAkBR;IAED;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,CAsCvC;IAED;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,cAAc,CAO/D;IAED;;OAEG;IACH,cAAc,CAAC,eAAe,EAAE,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,aAAa,CAapF;IAED;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/B;CACF"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Metrics calculator for false positive rate tracking
3
+ * Implements 30-day rolling window analysis and trend detection
4
+ */
5
+ /**
6
+ * Calculator for false positive metrics with rolling window analysis
7
+ */
8
+ export class MetricsCalculator {
9
+ windowDays;
10
+ threshold;
11
+ constructor(config = {}) {
12
+ this.windowDays = config.windowDays || 30;
13
+ this.threshold = config.threshold || 0.1; // 10% default threshold
14
+ }
15
+ /**
16
+ * Calculate false positive rate from feedback data
17
+ */
18
+ calculateFalsePositiveRate(feedback) {
19
+ if (feedback.total === 0) {
20
+ return 0;
21
+ }
22
+ return feedback.falsePositives / feedback.total;
23
+ }
24
+ /**
25
+ * Calculate rolling average over the time window
26
+ */
27
+ calculateRollingAverage(dataPoints, windowDays, referenceDate) {
28
+ const days = windowDays || this.windowDays;
29
+ const endDate = referenceDate || new Date();
30
+ const startDate = new Date(endDate);
31
+ startDate.setDate(startDate.getDate() - days);
32
+ // Filter data points within the window
33
+ const windowData = dataPoints.filter((point) => {
34
+ const pointDate = new Date(point.date);
35
+ return pointDate >= startDate && pointDate <= endDate;
36
+ });
37
+ if (windowData.length === 0) {
38
+ return 0;
39
+ }
40
+ const sum = windowData.reduce((acc, point) => acc + point.falsePositiveRate, 0);
41
+ return sum / windowData.length;
42
+ }
43
+ /**
44
+ * Detect trend direction using linear regression
45
+ */
46
+ getTrend(dataPoints) {
47
+ if (dataPoints.length < 2) {
48
+ return { direction: 'no-data', slope: 0 };
49
+ }
50
+ // Simple linear regression
51
+ const n = dataPoints.length;
52
+ let sumX = 0;
53
+ let sumY = 0;
54
+ let sumXY = 0;
55
+ let sumX2 = 0;
56
+ dataPoints.forEach((point, index) => {
57
+ const x = index;
58
+ const y = point.falsePositiveRate;
59
+ sumX += x;
60
+ sumY += y;
61
+ sumXY += x * y;
62
+ sumX2 += x * x;
63
+ });
64
+ const denominator = n * sumX2 - sumX * sumX;
65
+ if (denominator === 0) {
66
+ return { direction: 'no-data', slope: 0 };
67
+ }
68
+ const slope = (n * sumXY - sumX * sumY) / denominator;
69
+ // Determine direction based on slope
70
+ let direction;
71
+ if (Math.abs(slope) < 0.001) {
72
+ direction = 'stable';
73
+ }
74
+ else if (slope < 0) {
75
+ direction = 'improving';
76
+ }
77
+ else {
78
+ direction = 'worsening';
79
+ }
80
+ return { direction, slope };
81
+ }
82
+ /**
83
+ * Check if rate is within acceptable threshold
84
+ */
85
+ checkThreshold(rate, threshold) {
86
+ const targetThreshold = threshold !== undefined ? threshold : this.threshold;
87
+ return {
88
+ passed: rate <= targetThreshold,
89
+ rate,
90
+ threshold: targetThreshold
91
+ };
92
+ }
93
+ /**
94
+ * Generate comprehensive metrics report
95
+ */
96
+ generateReport(currentFeedback, history) {
97
+ const currentRate = this.calculateFalsePositiveRate(currentFeedback);
98
+ const rollingAverage = this.calculateRollingAverage(history);
99
+ const trend = this.getTrend(history);
100
+ const thresholdCheck = this.checkThreshold(rollingAverage);
101
+ return {
102
+ currentRate,
103
+ rollingAverage,
104
+ trend,
105
+ thresholdCheck,
106
+ totalFeedback: currentFeedback.total
107
+ };
108
+ }
109
+ /**
110
+ * Format rate as percentage string
111
+ */
112
+ formatRate(rate) {
113
+ return `${(rate * 100).toFixed(1)}%`;
114
+ }
115
+ }
116
+ //# sourceMappingURL=metrics.js.map