buildhive-agent 1.0.0-beta.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 (170) hide show
  1. package/README.md +166 -0
  2. package/dist/__tests__/fakes/FakeDockerManager.d.ts +115 -0
  3. package/dist/__tests__/fakes/FakeDockerManager.d.ts.map +1 -0
  4. package/dist/__tests__/fakes/FakeDockerManager.js +203 -0
  5. package/dist/__tests__/fakes/FakeDockerManager.js.map +1 -0
  6. package/dist/acceptanceChecker.d.ts +26 -0
  7. package/dist/acceptanceChecker.d.ts.map +1 -0
  8. package/dist/acceptanceChecker.js +64 -0
  9. package/dist/acceptanceChecker.js.map +1 -0
  10. package/dist/advancedAgent.d.ts +161 -0
  11. package/dist/advancedAgent.d.ts.map +1 -0
  12. package/dist/advancedAgent.js +604 -0
  13. package/dist/advancedAgent.js.map +1 -0
  14. package/dist/agent.d.ts +101 -0
  15. package/dist/agent.d.ts.map +1 -0
  16. package/dist/agent.js +490 -0
  17. package/dist/agent.js.map +1 -0
  18. package/dist/api/jobStatusApi.d.ts +88 -0
  19. package/dist/api/jobStatusApi.d.ts.map +1 -0
  20. package/dist/api/jobStatusApi.js +240 -0
  21. package/dist/api/jobStatusApi.js.map +1 -0
  22. package/dist/autoUpdater.d.ts +135 -0
  23. package/dist/autoUpdater.d.ts.map +1 -0
  24. package/dist/autoUpdater.js +494 -0
  25. package/dist/autoUpdater.js.map +1 -0
  26. package/dist/cacheManager.d.ts +108 -0
  27. package/dist/cacheManager.d.ts.map +1 -0
  28. package/dist/cacheManager.js +300 -0
  29. package/dist/cacheManager.js.map +1 -0
  30. package/dist/cli.d.ts +11 -0
  31. package/dist/cli.d.ts.map +1 -0
  32. package/dist/cli.js +749 -0
  33. package/dist/cli.js.map +1 -0
  34. package/dist/config/index.d.ts +30 -0
  35. package/dist/config/index.d.ts.map +1 -0
  36. package/dist/config/index.js +35 -0
  37. package/dist/config/index.js.map +1 -0
  38. package/dist/config/loader.d.ts +45 -0
  39. package/dist/config/loader.d.ts.map +1 -0
  40. package/dist/config/loader.js +269 -0
  41. package/dist/config/loader.js.map +1 -0
  42. package/dist/config/types.d.ts +193 -0
  43. package/dist/config/types.d.ts.map +1 -0
  44. package/dist/config/types.js +90 -0
  45. package/dist/config/types.js.map +1 -0
  46. package/dist/config/validation.d.ts +28 -0
  47. package/dist/config/validation.d.ts.map +1 -0
  48. package/dist/config/validation.js +397 -0
  49. package/dist/config/validation.js.map +1 -0
  50. package/dist/docker.d.ts +96 -0
  51. package/dist/docker.d.ts.map +1 -0
  52. package/dist/docker.js +411 -0
  53. package/dist/docker.js.map +1 -0
  54. package/dist/enhancedJobExecutor.d.ts +81 -0
  55. package/dist/enhancedJobExecutor.d.ts.map +1 -0
  56. package/dist/enhancedJobExecutor.js +223 -0
  57. package/dist/enhancedJobExecutor.js.map +1 -0
  58. package/dist/executors/executorFactory.d.ts +46 -0
  59. package/dist/executors/executorFactory.d.ts.map +1 -0
  60. package/dist/executors/executorFactory.js +80 -0
  61. package/dist/executors/executorFactory.js.map +1 -0
  62. package/dist/executors/index.d.ts +7 -0
  63. package/dist/executors/index.d.ts.map +1 -0
  64. package/dist/executors/index.js +6 -0
  65. package/dist/executors/index.js.map +1 -0
  66. package/dist/executors/nativeExecutor.d.ts +60 -0
  67. package/dist/executors/nativeExecutor.d.ts.map +1 -0
  68. package/dist/executors/nativeExecutor.js +311 -0
  69. package/dist/executors/nativeExecutor.js.map +1 -0
  70. package/dist/executors/types.d.ts +38 -0
  71. package/dist/executors/types.d.ts.map +1 -0
  72. package/dist/executors/types.js +9 -0
  73. package/dist/executors/types.js.map +1 -0
  74. package/dist/healthMonitor.d.ts +213 -0
  75. package/dist/healthMonitor.d.ts.map +1 -0
  76. package/dist/healthMonitor.js +547 -0
  77. package/dist/healthMonitor.js.map +1 -0
  78. package/dist/index.d.ts +16 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +16 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/jobExecutor.d.ts +117 -0
  83. package/dist/jobExecutor.d.ts.map +1 -0
  84. package/dist/jobExecutor.js +458 -0
  85. package/dist/jobExecutor.js.map +1 -0
  86. package/dist/lifecycleExecutor.d.ts +54 -0
  87. package/dist/lifecycleExecutor.d.ts.map +1 -0
  88. package/dist/lifecycleExecutor.js +230 -0
  89. package/dist/lifecycleExecutor.js.map +1 -0
  90. package/dist/main.d.ts +15 -0
  91. package/dist/main.d.ts.map +1 -0
  92. package/dist/main.js +77 -0
  93. package/dist/main.js.map +1 -0
  94. package/dist/metrics.d.ts +103 -0
  95. package/dist/metrics.d.ts.map +1 -0
  96. package/dist/metrics.js +360 -0
  97. package/dist/metrics.js.map +1 -0
  98. package/dist/recipes/builtinRecipes.d.ts +11 -0
  99. package/dist/recipes/builtinRecipes.d.ts.map +1 -0
  100. package/dist/recipes/builtinRecipes.js +688 -0
  101. package/dist/recipes/builtinRecipes.js.map +1 -0
  102. package/dist/recipes/index.d.ts +18 -0
  103. package/dist/recipes/index.d.ts.map +1 -0
  104. package/dist/recipes/index.js +17 -0
  105. package/dist/recipes/index.js.map +1 -0
  106. package/dist/recipes/recipeRegistry.d.ts +49 -0
  107. package/dist/recipes/recipeRegistry.d.ts.map +1 -0
  108. package/dist/recipes/recipeRegistry.js +264 -0
  109. package/dist/recipes/recipeRegistry.js.map +1 -0
  110. package/dist/recipes/types.d.ts +116 -0
  111. package/dist/recipes/types.d.ts.map +1 -0
  112. package/dist/recipes/types.js +10 -0
  113. package/dist/recipes/types.js.map +1 -0
  114. package/dist/recovery.d.ts +133 -0
  115. package/dist/recovery.d.ts.map +1 -0
  116. package/dist/recovery.js +299 -0
  117. package/dist/recovery.js.map +1 -0
  118. package/dist/registration/apiClient.d.ts +44 -0
  119. package/dist/registration/apiClient.d.ts.map +1 -0
  120. package/dist/registration/apiClient.js +149 -0
  121. package/dist/registration/apiClient.js.map +1 -0
  122. package/dist/registration/index.d.ts +41 -0
  123. package/dist/registration/index.d.ts.map +1 -0
  124. package/dist/registration/index.js +141 -0
  125. package/dist/registration/index.js.map +1 -0
  126. package/dist/registration/machineId.d.ts +30 -0
  127. package/dist/registration/machineId.d.ts.map +1 -0
  128. package/dist/registration/machineId.js +89 -0
  129. package/dist/registration/machineId.js.map +1 -0
  130. package/dist/registration/types.d.ts +32 -0
  131. package/dist/registration/types.d.ts.map +1 -0
  132. package/dist/registration/types.js +9 -0
  133. package/dist/registration/types.js.map +1 -0
  134. package/dist/resourceGovernor.d.ts +57 -0
  135. package/dist/resourceGovernor.d.ts.map +1 -0
  136. package/dist/resourceGovernor.js +125 -0
  137. package/dist/resourceGovernor.js.map +1 -0
  138. package/dist/security/secretManager.d.ts +107 -0
  139. package/dist/security/secretManager.d.ts.map +1 -0
  140. package/dist/security/secretManager.js +361 -0
  141. package/dist/security/secretManager.js.map +1 -0
  142. package/dist/security.d.ts +134 -0
  143. package/dist/security.d.ts.map +1 -0
  144. package/dist/security.js +470 -0
  145. package/dist/security.js.map +1 -0
  146. package/dist/storage/artifactUploader.d.ts +155 -0
  147. package/dist/storage/artifactUploader.d.ts.map +1 -0
  148. package/dist/storage/artifactUploader.js +554 -0
  149. package/dist/storage/artifactUploader.js.map +1 -0
  150. package/dist/types.d.ts +49 -0
  151. package/dist/types.d.ts.map +1 -0
  152. package/dist/types.js +7 -0
  153. package/dist/types.js.map +1 -0
  154. package/dist/utils/capabilities.d.ts +23 -0
  155. package/dist/utils/capabilities.d.ts.map +1 -0
  156. package/dist/utils/capabilities.js +200 -0
  157. package/dist/utils/capabilities.js.map +1 -0
  158. package/dist/utils/logger.d.ts +20 -0
  159. package/dist/utils/logger.d.ts.map +1 -0
  160. package/dist/utils/logger.js +188 -0
  161. package/dist/utils/logger.js.map +1 -0
  162. package/dist/utils/sdkScanner.d.ts +105 -0
  163. package/dist/utils/sdkScanner.d.ts.map +1 -0
  164. package/dist/utils/sdkScanner.js +459 -0
  165. package/dist/utils/sdkScanner.js.map +1 -0
  166. package/dist/websocketClient.d.ts +154 -0
  167. package/dist/websocketClient.d.ts.map +1 -0
  168. package/dist/websocketClient.js +422 -0
  169. package/dist/websocketClient.js.map +1 -0
  170. package/package.json +64 -0
@@ -0,0 +1,554 @@
1
+ /**
2
+ * Artifact Uploader - MVP.4.2.4
3
+ *
4
+ * Handles artifact upload to storage backends (local or S3).
5
+ *
6
+ * Features:
7
+ * - Local file storage with configurable base path
8
+ * - S3 upload with multipart support for large files (>50MB)
9
+ * - S3-compatible storage support (MinIO, Cloudflare R2, etc.)
10
+ * - Presigned download URL generation
11
+ * - Retry logic with exponential backoff
12
+ * - Proper error handling and logging
13
+ * - Cleanup of temporary files after upload
14
+ * - Batch S3 object deletion for retention cleanup
15
+ *
16
+ * @module storage/artifactUploader
17
+ */
18
+ import { promises as fs } from 'fs';
19
+ import { createReadStream } from 'fs';
20
+ import { join, dirname } from 'path';
21
+ import { createLogger } from '../utils/logger.js';
22
+ import { S3Client, PutObjectCommand, GetObjectCommand, ListObjectsV2Command, DeleteObjectsCommand, } from '@aws-sdk/client-s3';
23
+ import { Upload } from '@aws-sdk/lib-storage';
24
+ import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
25
+ const logger = createLogger('ArtifactUploader');
26
+ /** Threshold in bytes above which multipart upload is used (50 MB) */
27
+ const MULTIPART_THRESHOLD = 50 * 1024 * 1024;
28
+ export class ArtifactUploader {
29
+ config;
30
+ s3Client = null;
31
+ constructor(config) {
32
+ this.config = config;
33
+ logger.info('ArtifactUploader initialized', {
34
+ type: config.type,
35
+ localPath: config.localPath,
36
+ s3Bucket: config.s3?.bucket
37
+ });
38
+ }
39
+ /**
40
+ * Lazily create and cache an S3Client instance based on the current config.
41
+ */
42
+ getS3Client() {
43
+ if (this.s3Client) {
44
+ return this.s3Client;
45
+ }
46
+ const s3Cfg = this.config.s3;
47
+ if (!s3Cfg) {
48
+ throw new Error('S3 configuration is missing');
49
+ }
50
+ const clientConfig = {
51
+ region: s3Cfg.region,
52
+ };
53
+ // Support explicit credentials; omit to use AWS default credential chain
54
+ if (s3Cfg.accessKeyId && s3Cfg.secretAccessKey) {
55
+ clientConfig.credentials = {
56
+ accessKeyId: s3Cfg.accessKeyId,
57
+ secretAccessKey: s3Cfg.secretAccessKey,
58
+ };
59
+ }
60
+ // Support S3-compatible endpoints (MinIO, R2, etc.)
61
+ if (s3Cfg.endpoint) {
62
+ clientConfig.endpoint = s3Cfg.endpoint;
63
+ clientConfig.forcePathStyle = true; // Required for most S3-compatible stores
64
+ }
65
+ this.s3Client = new S3Client(clientConfig);
66
+ return this.s3Client;
67
+ }
68
+ /**
69
+ * Build the S3 object key from an artifact name, applying the configured path prefix.
70
+ */
71
+ buildS3Key(artifactName) {
72
+ const prefix = this.config.s3?.pathPrefix || '';
73
+ // Normalise: strip leading slash from artifact name, ensure prefix ends without double slashes
74
+ const cleanPrefix = prefix.endsWith('/') ? prefix : prefix ? `${prefix}/` : '';
75
+ const cleanName = artifactName.startsWith('/') ? artifactName.slice(1) : artifactName;
76
+ return `${cleanPrefix}${cleanName}`;
77
+ }
78
+ /**
79
+ * Build a public-style S3 URL for an object.
80
+ */
81
+ buildS3Url(key) {
82
+ const s3Cfg = this.config.s3;
83
+ if (s3Cfg.endpoint) {
84
+ // S3-compatible storage - use endpoint-based URL
85
+ const base = s3Cfg.endpoint.replace(/\/$/, '');
86
+ return `${base}/${s3Cfg.bucket}/${key}`;
87
+ }
88
+ return `https://${s3Cfg.bucket}.s3.${s3Cfg.region}.amazonaws.com/${key}`;
89
+ }
90
+ /**
91
+ * Upload an artifact to the configured storage backend
92
+ *
93
+ * @param sourcePath - Absolute path to the artifact file
94
+ * @param artifactName - Name/path for the artifact in storage
95
+ * @param options - Upload options
96
+ * @returns Upload result with URL and metadata
97
+ */
98
+ async uploadArtifact(sourcePath, artifactName, options = {}) {
99
+ const { maxRetries = 3, retryDelayMs = 1000, deleteAfterUpload = this.config.cleanupAfterUpload } = options;
100
+ logger.info('Uploading artifact', { sourcePath, artifactName, backend: this.config.type });
101
+ try {
102
+ // Verify source file exists
103
+ const stats = await fs.stat(sourcePath);
104
+ if (!stats.isFile()) {
105
+ throw new Error(`Source path is not a file: ${sourcePath}`);
106
+ }
107
+ let result;
108
+ // Upload based on storage type
109
+ if (this.config.type === 's3') {
110
+ result = await this.uploadToS3(sourcePath, artifactName, maxRetries, retryDelayMs);
111
+ }
112
+ else {
113
+ result = await this.uploadToLocal(sourcePath, artifactName, maxRetries, retryDelayMs);
114
+ }
115
+ logger.info('Artifact uploaded successfully', {
116
+ url: result.url,
117
+ size: result.size
118
+ });
119
+ // Clean up source file if requested
120
+ if (deleteAfterUpload) {
121
+ await this.deleteFile(sourcePath);
122
+ }
123
+ return result;
124
+ }
125
+ catch (error) {
126
+ logger.error('Failed to upload artifact', {
127
+ sourcePath,
128
+ artifactName,
129
+ error: error.message
130
+ });
131
+ throw error;
132
+ }
133
+ }
134
+ /**
135
+ * Upload artifact to local storage
136
+ *
137
+ * @param sourcePath - Source file path
138
+ * @param artifactName - Target artifact name
139
+ * @param maxRetries - Maximum retry attempts
140
+ * @param retryDelayMs - Retry delay in milliseconds
141
+ * @returns Upload result
142
+ */
143
+ async uploadToLocal(sourcePath, artifactName, maxRetries, retryDelayMs) {
144
+ const basePath = this.config.localPath || '/tmp/buildhive/artifacts';
145
+ const targetPath = join(basePath, artifactName);
146
+ logger.debug('Uploading to local storage', { sourcePath, targetPath });
147
+ // Ensure target directory exists
148
+ await fs.mkdir(dirname(targetPath), { recursive: true });
149
+ // Copy file with retry logic
150
+ await this.retryOperation(async () => {
151
+ await fs.copyFile(sourcePath, targetPath);
152
+ }, maxRetries, retryDelayMs, `copy ${sourcePath} to ${targetPath}`);
153
+ // Get file stats
154
+ const stats = await fs.stat(targetPath);
155
+ return {
156
+ url: `file://${targetPath}`,
157
+ size: stats.size,
158
+ uploadedAt: new Date()
159
+ };
160
+ }
161
+ /**
162
+ * Upload artifact to S3
163
+ *
164
+ * Uses PutObjectCommand for files <= 50 MB and multipart Upload for larger files.
165
+ * Supports S3-compatible storage (MinIO, Cloudflare R2) via custom endpoint.
166
+ *
167
+ * @param sourcePath - Source file path
168
+ * @param artifactName - Target artifact name
169
+ * @param maxRetries - Maximum retry attempts
170
+ * @param retryDelayMs - Retry delay in milliseconds
171
+ * @returns Upload result
172
+ */
173
+ async uploadToS3(sourcePath, artifactName, maxRetries, retryDelayMs) {
174
+ if (!this.config.s3) {
175
+ throw new Error('S3 configuration is missing');
176
+ }
177
+ const client = this.getS3Client();
178
+ const key = this.buildS3Key(artifactName);
179
+ const stats = await fs.stat(sourcePath);
180
+ const fileSize = stats.size;
181
+ logger.info('Uploading to S3', {
182
+ sourcePath,
183
+ bucket: this.config.s3.bucket,
184
+ key,
185
+ fileSize,
186
+ multipart: fileSize > MULTIPART_THRESHOLD
187
+ });
188
+ try {
189
+ if (fileSize > MULTIPART_THRESHOLD) {
190
+ // Multipart upload for large files
191
+ await this.retryOperation(async () => {
192
+ const upload = new Upload({
193
+ client,
194
+ params: {
195
+ Bucket: this.config.s3.bucket,
196
+ Key: key,
197
+ Body: createReadStream(sourcePath),
198
+ },
199
+ // 10 MB part size, 4 concurrent uploads
200
+ partSize: 10 * 1024 * 1024,
201
+ queueSize: 4,
202
+ });
203
+ upload.on('httpUploadProgress', (progress) => {
204
+ logger.debug('Multipart upload progress', {
205
+ key,
206
+ loaded: progress.loaded,
207
+ total: progress.total,
208
+ });
209
+ });
210
+ await upload.done();
211
+ }, maxRetries, retryDelayMs, `multipart upload ${artifactName} to S3`);
212
+ }
213
+ else {
214
+ // Single PutObject for smaller files
215
+ await this.retryOperation(async () => {
216
+ const fileStream = createReadStream(sourcePath);
217
+ await client.send(new PutObjectCommand({
218
+ Bucket: this.config.s3.bucket,
219
+ Key: key,
220
+ Body: fileStream,
221
+ ContentLength: fileSize,
222
+ }));
223
+ }, maxRetries, retryDelayMs, `upload ${artifactName} to S3`);
224
+ }
225
+ }
226
+ catch (error) {
227
+ throw new Error(`Failed to upload artifact "${artifactName}" to S3 bucket "${this.config.s3.bucket}": ${error.message}`);
228
+ }
229
+ const url = this.buildS3Url(key);
230
+ return {
231
+ url,
232
+ size: fileSize,
233
+ uploadedAt: new Date(),
234
+ };
235
+ }
236
+ /**
237
+ * Generate a presigned download URL for an artifact in S3.
238
+ *
239
+ * @param artifactName - The artifact name/path in storage
240
+ * @param expiresInSeconds - URL expiration time (default: 3600 = 1 hour)
241
+ * @returns Presigned download URL
242
+ */
243
+ async getSignedDownloadUrl(artifactName, expiresInSeconds = 3600) {
244
+ if (this.config.type !== 's3' || !this.config.s3) {
245
+ throw new Error('Signed URLs are only available with S3 storage');
246
+ }
247
+ const client = this.getS3Client();
248
+ const key = this.buildS3Key(artifactName);
249
+ try {
250
+ const command = new GetObjectCommand({
251
+ Bucket: this.config.s3.bucket,
252
+ Key: key,
253
+ });
254
+ const signedUrl = await getSignedUrl(client, command, {
255
+ expiresIn: expiresInSeconds,
256
+ });
257
+ logger.info('Generated presigned download URL', {
258
+ artifactName,
259
+ key,
260
+ expiresInSeconds,
261
+ });
262
+ return signedUrl;
263
+ }
264
+ catch (error) {
265
+ throw new Error(`Failed to generate presigned URL for "${artifactName}": ${error.message}`);
266
+ }
267
+ }
268
+ /**
269
+ * Delete S3 objects in batch using DeleteObjectsCommand.
270
+ *
271
+ * @param keys - Array of S3 object keys to delete
272
+ * @returns Number of objects successfully deleted
273
+ */
274
+ async deleteS3Objects(keys) {
275
+ if (this.config.type !== 's3' || !this.config.s3) {
276
+ throw new Error('S3 deletion is only available with S3 storage');
277
+ }
278
+ if (keys.length === 0) {
279
+ return 0;
280
+ }
281
+ const client = this.getS3Client();
282
+ let totalDeleted = 0;
283
+ // DeleteObjects supports max 1000 keys per request
284
+ const batchSize = 1000;
285
+ for (let i = 0; i < keys.length; i += batchSize) {
286
+ const batch = keys.slice(i, i + batchSize);
287
+ try {
288
+ const response = await client.send(new DeleteObjectsCommand({
289
+ Bucket: this.config.s3.bucket,
290
+ Delete: {
291
+ Objects: batch.map((k) => ({ Key: k })),
292
+ Quiet: true,
293
+ },
294
+ }));
295
+ const errCount = response.Errors?.length || 0;
296
+ totalDeleted += batch.length - errCount;
297
+ if (errCount > 0) {
298
+ logger.warn('Some S3 objects failed to delete', {
299
+ errors: response.Errors?.slice(0, 5),
300
+ });
301
+ }
302
+ }
303
+ catch (error) {
304
+ logger.error('Batch S3 deletion failed', {
305
+ batchStart: i,
306
+ batchSize: batch.length,
307
+ error: error.message,
308
+ });
309
+ throw new Error(`Failed to delete S3 objects (batch starting at ${i}): ${error.message}`);
310
+ }
311
+ }
312
+ logger.info('S3 batch deletion complete', {
313
+ requested: keys.length,
314
+ deleted: totalDeleted,
315
+ });
316
+ return totalDeleted;
317
+ }
318
+ /**
319
+ * Delete a file from the filesystem
320
+ *
321
+ * @param filePath - Path to the file to delete
322
+ */
323
+ async deleteFile(filePath) {
324
+ try {
325
+ await fs.unlink(filePath);
326
+ logger.debug('Deleted file after upload', { filePath });
327
+ }
328
+ catch (error) {
329
+ logger.warn('Failed to delete file after upload', {
330
+ filePath,
331
+ error: error.message
332
+ });
333
+ // Don't throw - deletion failure is not critical
334
+ }
335
+ }
336
+ /**
337
+ * Retry an operation with exponential backoff
338
+ *
339
+ * @param operation - Async operation to retry
340
+ * @param maxRetries - Maximum number of retry attempts
341
+ * @param baseDelayMs - Base delay for exponential backoff
342
+ * @param operationName - Name for logging
343
+ */
344
+ async retryOperation(operation, maxRetries, baseDelayMs, operationName) {
345
+ let lastError;
346
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
347
+ try {
348
+ return await operation();
349
+ }
350
+ catch (error) {
351
+ lastError = error;
352
+ if (attempt < maxRetries) {
353
+ const delay = baseDelayMs * Math.pow(2, attempt);
354
+ logger.warn(`Operation failed, retrying (${attempt + 1}/${maxRetries})`, {
355
+ operation: operationName,
356
+ error: error.message,
357
+ retryDelayMs: delay
358
+ });
359
+ await new Promise(resolve => setTimeout(resolve, delay));
360
+ }
361
+ }
362
+ }
363
+ throw new Error(`Operation failed after ${maxRetries} retries: ${operationName}. ` +
364
+ `Last error: ${lastError?.message}`);
365
+ }
366
+ /**
367
+ * Clean up old artifacts based on retention policy
368
+ *
369
+ * @param basePath - Base path to scan for old artifacts
370
+ * @returns Number of files deleted
371
+ */
372
+ async cleanupOldArtifacts(basePath) {
373
+ const path = basePath || this.config.localPath || '/tmp/buildhive/artifacts';
374
+ const retentionMs = this.config.retentionDays * 24 * 60 * 60 * 1000;
375
+ const cutoffTime = Date.now() - retentionMs;
376
+ logger.info('Starting artifact cleanup', {
377
+ path,
378
+ retentionDays: this.config.retentionDays
379
+ });
380
+ try {
381
+ const files = await this.findOldFiles(path, cutoffTime);
382
+ let deletedCount = 0;
383
+ for (const file of files) {
384
+ try {
385
+ await fs.unlink(file);
386
+ deletedCount++;
387
+ logger.debug('Deleted old artifact', { file });
388
+ }
389
+ catch (error) {
390
+ logger.warn('Failed to delete old artifact', {
391
+ file,
392
+ error: error.message
393
+ });
394
+ }
395
+ }
396
+ logger.info('Artifact cleanup complete', { deletedCount });
397
+ return deletedCount;
398
+ }
399
+ catch (error) {
400
+ logger.error('Artifact cleanup failed', { error: error.message });
401
+ return 0;
402
+ }
403
+ }
404
+ /**
405
+ * Recursively find files older than the cutoff time
406
+ *
407
+ * @param dirPath - Directory to scan
408
+ * @param cutoffTime - Cutoff timestamp (files older than this will be included)
409
+ * @returns Array of file paths
410
+ */
411
+ async findOldFiles(dirPath, cutoffTime) {
412
+ const oldFiles = [];
413
+ try {
414
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
415
+ for (const entry of entries) {
416
+ const fullPath = join(dirPath, entry.name);
417
+ if (entry.isDirectory()) {
418
+ const subDirFiles = await this.findOldFiles(fullPath, cutoffTime);
419
+ oldFiles.push(...subDirFiles);
420
+ }
421
+ else if (entry.isFile()) {
422
+ const stats = await fs.stat(fullPath);
423
+ if (stats.mtimeMs < cutoffTime) {
424
+ oldFiles.push(fullPath);
425
+ }
426
+ }
427
+ }
428
+ }
429
+ catch (error) {
430
+ if (error.code !== 'ENOENT') {
431
+ logger.warn('Error scanning directory for old files', {
432
+ dirPath,
433
+ error: error.message
434
+ });
435
+ }
436
+ }
437
+ return oldFiles;
438
+ }
439
+ /**
440
+ * Get storage statistics
441
+ *
442
+ * @returns Storage usage statistics
443
+ */
444
+ async getStorageStats() {
445
+ if (this.config.type === 's3') {
446
+ return this.getS3StorageStats();
447
+ }
448
+ const basePath = this.config.localPath || '/tmp/buildhive/artifacts';
449
+ const files = await this.findAllFiles(basePath);
450
+ let totalSize = 0;
451
+ let oldestTime;
452
+ let newestTime;
453
+ for (const file of files) {
454
+ const stats = await fs.stat(file);
455
+ totalSize += stats.size;
456
+ const mtime = stats.mtimeMs;
457
+ if (oldestTime === undefined || mtime < oldestTime) {
458
+ oldestTime = mtime;
459
+ }
460
+ if (newestTime === undefined || mtime > newestTime) {
461
+ newestTime = mtime;
462
+ }
463
+ }
464
+ return {
465
+ type: 'local',
466
+ totalFiles: files.length,
467
+ totalSizeBytes: totalSize,
468
+ oldestFileDate: oldestTime ? new Date(oldestTime) : undefined,
469
+ newestFileDate: newestTime ? new Date(newestTime) : undefined
470
+ };
471
+ }
472
+ /**
473
+ * Recursively find all files in a directory
474
+ *
475
+ * @param dirPath - Directory to scan
476
+ * @returns Array of file paths
477
+ */
478
+ async findAllFiles(dirPath) {
479
+ const allFiles = [];
480
+ try {
481
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
482
+ for (const entry of entries) {
483
+ const fullPath = join(dirPath, entry.name);
484
+ if (entry.isDirectory()) {
485
+ const subDirFiles = await this.findAllFiles(fullPath);
486
+ allFiles.push(...subDirFiles);
487
+ }
488
+ else if (entry.isFile()) {
489
+ allFiles.push(fullPath);
490
+ }
491
+ }
492
+ }
493
+ catch (error) {
494
+ if (error.code !== 'ENOENT') {
495
+ logger.warn('Error scanning directory for files', {
496
+ dirPath,
497
+ error: error.message
498
+ });
499
+ }
500
+ }
501
+ return allFiles;
502
+ }
503
+ /**
504
+ * Retrieve storage statistics from S3 using ListObjectsV2 with pagination.
505
+ */
506
+ async getS3StorageStats() {
507
+ if (!this.config.s3) {
508
+ throw new Error('S3 configuration is missing');
509
+ }
510
+ const client = this.getS3Client();
511
+ const prefix = this.config.s3.pathPrefix || '';
512
+ let totalFiles = 0;
513
+ let totalSizeBytes = 0;
514
+ let oldestTime;
515
+ let newestTime;
516
+ let continuationToken;
517
+ try {
518
+ do {
519
+ const response = await client.send(new ListObjectsV2Command({
520
+ Bucket: this.config.s3.bucket,
521
+ Prefix: prefix || undefined,
522
+ ContinuationToken: continuationToken,
523
+ }));
524
+ for (const obj of response.Contents || []) {
525
+ totalFiles++;
526
+ totalSizeBytes += obj.Size || 0;
527
+ if (obj.LastModified) {
528
+ const mtime = obj.LastModified.getTime();
529
+ if (oldestTime === undefined || mtime < oldestTime) {
530
+ oldestTime = mtime;
531
+ }
532
+ if (newestTime === undefined || mtime > newestTime) {
533
+ newestTime = mtime;
534
+ }
535
+ }
536
+ }
537
+ continuationToken = response.IsTruncated
538
+ ? response.NextContinuationToken
539
+ : undefined;
540
+ } while (continuationToken);
541
+ }
542
+ catch (error) {
543
+ throw new Error(`Failed to retrieve S3 storage stats for bucket "${this.config.s3.bucket}": ${error.message}`);
544
+ }
545
+ return {
546
+ type: 's3',
547
+ totalFiles,
548
+ totalSizeBytes,
549
+ oldestFileDate: oldestTime ? new Date(oldestTime) : undefined,
550
+ newestFileDate: newestTime ? new Date(newestTime) : undefined,
551
+ };
552
+ }
553
+ }
554
+ //# sourceMappingURL=artifactUploader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifactUploader.js","sourceRoot":"","sources":["../../src/storage/artifactUploader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Agent Type Definitions
3
+ *
4
+ * Shared type definitions for the BuildHive agent
5
+ */
6
+ import type { SDKScanResult } from './utils/sdkScanner.js';
7
+ export interface AgentCapabilities {
8
+ os: string;
9
+ arch: string;
10
+ cpuCores: number;
11
+ memoryGB: number;
12
+ diskSpaceGB: number;
13
+ dockerVersion?: string;
14
+ }
15
+ /**
16
+ * Extended capabilities that include SDK/toolchain information and
17
+ * auto-generated tags for job matching.
18
+ */
19
+ export interface DetailedCapabilities extends AgentCapabilities {
20
+ /** Detected SDKs and toolchains on this machine. */
21
+ sdks: SDKScanResult;
22
+ /** Auto-generated capability tags (e.g. "java-17", "docker", "arm64"). */
23
+ tags: string[];
24
+ }
25
+ export interface JobSubmissionRequest {
26
+ externalId: string;
27
+ source: 'GITHUB_ACTIONS' | 'JENKINS' | 'GITLAB_CI' | 'AZURE_DEVOPS' | 'MANUAL';
28
+ repository: string;
29
+ branch: string;
30
+ commitSha: string;
31
+ jobType: string;
32
+ dockerImage: string;
33
+ buildCommand: string;
34
+ environment?: Record<string, string>;
35
+ artifacts?: string[];
36
+ requiredOS?: string;
37
+ requiredArch?: string;
38
+ requiredMemoryGB?: number;
39
+ requiredTags?: string[];
40
+ estimatedDuration?: number;
41
+ /**
42
+ * GitHub App installation token or Personal Access Token used to authenticate
43
+ * git clone operations for private repositories.
44
+ * Injected into the clone URL as: https://x-access-token:{token}@github.com/...
45
+ * Never logged or stored beyond the duration of the job.
46
+ */
47
+ githubToken?: string;
48
+ }
49
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,oDAAoD;IACpD,IAAI,EAAE,aAAa,CAAC;IACpB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,gBAAgB,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,GAAG,QAAQ,CAAC;IAC/E,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Agent Type Definitions
3
+ *
4
+ * Shared type definitions for the BuildHive agent
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Capabilities Detection
3
+ *
4
+ * Detects system capabilities for agent registration using systeminformation library
5
+ * for accurate cross-platform system metrics.
6
+ *
7
+ * Requirements: MVP.4.1.2
8
+ */
9
+ import { AgentCapabilities, DetailedCapabilities } from '../types.js';
10
+ /**
11
+ * Detect system capabilities with systeminformation
12
+ */
13
+ export declare function detectCapabilities(): Promise<AgentCapabilities>;
14
+ /**
15
+ * Detect detailed capabilities including SDK/toolchain information and
16
+ * auto-generated tags. This extends the basic {@link detectCapabilities}
17
+ * with an SDK scan and tag generation pass.
18
+ *
19
+ * @param manualTags - Optional tags supplied by the user configuration that
20
+ * will be merged (and deduplicated) with auto-detected tags.
21
+ */
22
+ export declare function detectDetailedCapabilities(manualTags?: string[]): Promise<DetailedCapabilities>;
23
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/utils/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAOtE;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAgCrE;AAsID;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAC9C,UAAU,GAAE,MAAM,EAAO,GACxB,OAAO,CAAC,oBAAoB,CAAC,CAuB/B"}