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.
- package/README.md +166 -0
- package/dist/__tests__/fakes/FakeDockerManager.d.ts +115 -0
- package/dist/__tests__/fakes/FakeDockerManager.d.ts.map +1 -0
- package/dist/__tests__/fakes/FakeDockerManager.js +203 -0
- package/dist/__tests__/fakes/FakeDockerManager.js.map +1 -0
- package/dist/acceptanceChecker.d.ts +26 -0
- package/dist/acceptanceChecker.d.ts.map +1 -0
- package/dist/acceptanceChecker.js +64 -0
- package/dist/acceptanceChecker.js.map +1 -0
- package/dist/advancedAgent.d.ts +161 -0
- package/dist/advancedAgent.d.ts.map +1 -0
- package/dist/advancedAgent.js +604 -0
- package/dist/advancedAgent.js.map +1 -0
- package/dist/agent.d.ts +101 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +490 -0
- package/dist/agent.js.map +1 -0
- package/dist/api/jobStatusApi.d.ts +88 -0
- package/dist/api/jobStatusApi.d.ts.map +1 -0
- package/dist/api/jobStatusApi.js +240 -0
- package/dist/api/jobStatusApi.js.map +1 -0
- package/dist/autoUpdater.d.ts +135 -0
- package/dist/autoUpdater.d.ts.map +1 -0
- package/dist/autoUpdater.js +494 -0
- package/dist/autoUpdater.js.map +1 -0
- package/dist/cacheManager.d.ts +108 -0
- package/dist/cacheManager.d.ts.map +1 -0
- package/dist/cacheManager.js +300 -0
- package/dist/cacheManager.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +749 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/index.d.ts +30 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +35 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +45 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +269 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +193 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +90 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validation.d.ts +28 -0
- package/dist/config/validation.d.ts.map +1 -0
- package/dist/config/validation.js +397 -0
- package/dist/config/validation.js.map +1 -0
- package/dist/docker.d.ts +96 -0
- package/dist/docker.d.ts.map +1 -0
- package/dist/docker.js +411 -0
- package/dist/docker.js.map +1 -0
- package/dist/enhancedJobExecutor.d.ts +81 -0
- package/dist/enhancedJobExecutor.d.ts.map +1 -0
- package/dist/enhancedJobExecutor.js +223 -0
- package/dist/enhancedJobExecutor.js.map +1 -0
- package/dist/executors/executorFactory.d.ts +46 -0
- package/dist/executors/executorFactory.d.ts.map +1 -0
- package/dist/executors/executorFactory.js +80 -0
- package/dist/executors/executorFactory.js.map +1 -0
- package/dist/executors/index.d.ts +7 -0
- package/dist/executors/index.d.ts.map +1 -0
- package/dist/executors/index.js +6 -0
- package/dist/executors/index.js.map +1 -0
- package/dist/executors/nativeExecutor.d.ts +60 -0
- package/dist/executors/nativeExecutor.d.ts.map +1 -0
- package/dist/executors/nativeExecutor.js +311 -0
- package/dist/executors/nativeExecutor.js.map +1 -0
- package/dist/executors/types.d.ts +38 -0
- package/dist/executors/types.d.ts.map +1 -0
- package/dist/executors/types.js +9 -0
- package/dist/executors/types.js.map +1 -0
- package/dist/healthMonitor.d.ts +213 -0
- package/dist/healthMonitor.d.ts.map +1 -0
- package/dist/healthMonitor.js +547 -0
- package/dist/healthMonitor.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/jobExecutor.d.ts +117 -0
- package/dist/jobExecutor.d.ts.map +1 -0
- package/dist/jobExecutor.js +458 -0
- package/dist/jobExecutor.js.map +1 -0
- package/dist/lifecycleExecutor.d.ts +54 -0
- package/dist/lifecycleExecutor.d.ts.map +1 -0
- package/dist/lifecycleExecutor.js +230 -0
- package/dist/lifecycleExecutor.js.map +1 -0
- package/dist/main.d.ts +15 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +77 -0
- package/dist/main.js.map +1 -0
- package/dist/metrics.d.ts +103 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +360 -0
- package/dist/metrics.js.map +1 -0
- package/dist/recipes/builtinRecipes.d.ts +11 -0
- package/dist/recipes/builtinRecipes.d.ts.map +1 -0
- package/dist/recipes/builtinRecipes.js +688 -0
- package/dist/recipes/builtinRecipes.js.map +1 -0
- package/dist/recipes/index.d.ts +18 -0
- package/dist/recipes/index.d.ts.map +1 -0
- package/dist/recipes/index.js +17 -0
- package/dist/recipes/index.js.map +1 -0
- package/dist/recipes/recipeRegistry.d.ts +49 -0
- package/dist/recipes/recipeRegistry.d.ts.map +1 -0
- package/dist/recipes/recipeRegistry.js +264 -0
- package/dist/recipes/recipeRegistry.js.map +1 -0
- package/dist/recipes/types.d.ts +116 -0
- package/dist/recipes/types.d.ts.map +1 -0
- package/dist/recipes/types.js +10 -0
- package/dist/recipes/types.js.map +1 -0
- package/dist/recovery.d.ts +133 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +299 -0
- package/dist/recovery.js.map +1 -0
- package/dist/registration/apiClient.d.ts +44 -0
- package/dist/registration/apiClient.d.ts.map +1 -0
- package/dist/registration/apiClient.js +149 -0
- package/dist/registration/apiClient.js.map +1 -0
- package/dist/registration/index.d.ts +41 -0
- package/dist/registration/index.d.ts.map +1 -0
- package/dist/registration/index.js +141 -0
- package/dist/registration/index.js.map +1 -0
- package/dist/registration/machineId.d.ts +30 -0
- package/dist/registration/machineId.d.ts.map +1 -0
- package/dist/registration/machineId.js +89 -0
- package/dist/registration/machineId.js.map +1 -0
- package/dist/registration/types.d.ts +32 -0
- package/dist/registration/types.d.ts.map +1 -0
- package/dist/registration/types.js +9 -0
- package/dist/registration/types.js.map +1 -0
- package/dist/resourceGovernor.d.ts +57 -0
- package/dist/resourceGovernor.d.ts.map +1 -0
- package/dist/resourceGovernor.js +125 -0
- package/dist/resourceGovernor.js.map +1 -0
- package/dist/security/secretManager.d.ts +107 -0
- package/dist/security/secretManager.d.ts.map +1 -0
- package/dist/security/secretManager.js +361 -0
- package/dist/security/secretManager.js.map +1 -0
- package/dist/security.d.ts +134 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +470 -0
- package/dist/security.js.map +1 -0
- package/dist/storage/artifactUploader.d.ts +155 -0
- package/dist/storage/artifactUploader.d.ts.map +1 -0
- package/dist/storage/artifactUploader.js +554 -0
- package/dist/storage/artifactUploader.js.map +1 -0
- package/dist/types.d.ts +49 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/capabilities.d.ts +23 -0
- package/dist/utils/capabilities.d.ts.map +1 -0
- package/dist/utils/capabilities.js +200 -0
- package/dist/utils/capabilities.js.map +1 -0
- package/dist/utils/logger.d.ts +20 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +188 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/sdkScanner.d.ts +105 -0
- package/dist/utils/sdkScanner.d.ts.map +1 -0
- package/dist/utils/sdkScanner.js +459 -0
- package/dist/utils/sdkScanner.js.map +1 -0
- package/dist/websocketClient.d.ts +154 -0
- package/dist/websocketClient.d.ts.map +1 -0
- package/dist/websocketClient.js +422 -0
- package/dist/websocketClient.js.map +1 -0
- 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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"}
|
package/dist/types.d.ts
ADDED
|
@@ -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 @@
|
|
|
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"}
|