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,494 @@
1
+ /**
2
+ * Auto-Updater Module
3
+ *
4
+ * Handles automatic updates for the BuildHive agent including:
5
+ * - Version checking
6
+ * - Secure download and verification
7
+ * - Graceful update process
8
+ * - Rollback capabilities
9
+ *
10
+ * Requirements: 6.1
11
+ */
12
+ import * as fs from 'fs';
13
+ import * as path from 'path';
14
+ import * as crypto from 'crypto';
15
+ import * as https from 'https';
16
+ import { EventEmitter } from 'events';
17
+ import { createLogger } from './utils/logger.js';
18
+ const logger = createLogger('auto-updater');
19
+ export class AutoUpdater extends EventEmitter {
20
+ options;
21
+ currentVersion;
22
+ checkInterval = null;
23
+ isUpdating = false;
24
+ updateInProgress = false;
25
+ constructor(currentVersion, options = {}) {
26
+ super();
27
+ this.currentVersion = currentVersion;
28
+ this.options = {
29
+ updateServerUrl: 'https://updates.buildhive.dev/agent',
30
+ checkInterval: 4 * 60 * 60, // 4 hours
31
+ autoInstall: false,
32
+ allowPrerelease: false,
33
+ backupEnabled: true,
34
+ maxRetries: 3,
35
+ ...options
36
+ };
37
+ }
38
+ /**
39
+ * Start the auto-updater
40
+ */
41
+ start() {
42
+ if (this.checkInterval) {
43
+ logger.warn('Auto-updater is already running');
44
+ return;
45
+ }
46
+ logger.info('Starting auto-updater', {
47
+ currentVersion: this.currentVersion,
48
+ checkInterval: this.options.checkInterval,
49
+ autoInstall: this.options.autoInstall
50
+ });
51
+ // Perform initial check
52
+ this.checkForUpdates().catch(error => {
53
+ logger.error('Initial update check failed:', error);
54
+ });
55
+ // Schedule periodic checks
56
+ this.checkInterval = setInterval(() => {
57
+ this.checkForUpdates().catch(error => {
58
+ logger.error('Periodic update check failed:', error);
59
+ });
60
+ }, this.options.checkInterval * 1000);
61
+ this.emit('started');
62
+ }
63
+ /**
64
+ * Stop the auto-updater
65
+ */
66
+ stop() {
67
+ if (this.checkInterval) {
68
+ clearInterval(this.checkInterval);
69
+ this.checkInterval = null;
70
+ }
71
+ logger.info('Auto-updater stopped');
72
+ this.emit('stopped');
73
+ }
74
+ /**
75
+ * Check for available updates
76
+ */
77
+ async checkForUpdates() {
78
+ if (this.isUpdating) {
79
+ logger.debug('Update check skipped - update in progress');
80
+ return null;
81
+ }
82
+ this.emit('progress', {
83
+ phase: 'checking',
84
+ progress: 0,
85
+ message: 'Checking for updates...'
86
+ });
87
+ try {
88
+ logger.debug('Checking for updates from:', this.options.updateServerUrl);
89
+ const manifest = await this.fetchUpdateManifest();
90
+ if (!manifest) {
91
+ logger.debug('No update manifest available');
92
+ return null;
93
+ }
94
+ const updateAvailable = this.compareVersions(manifest.version, this.currentVersion) > 0;
95
+ if (!updateAvailable) {
96
+ logger.debug(`No update available. Current: ${this.currentVersion}, Latest: ${manifest.version}`);
97
+ return null;
98
+ }
99
+ logger.info(`Update available: ${this.currentVersion} -> ${manifest.version}`, {
100
+ critical: manifest.critical,
101
+ size: manifest.size
102
+ });
103
+ this.emit('updateAvailable', manifest);
104
+ if (this.options.autoInstall || manifest.critical) {
105
+ logger.info('Starting automatic update installation');
106
+ await this.installUpdate(manifest);
107
+ }
108
+ return manifest;
109
+ }
110
+ catch (error) {
111
+ logger.error('Failed to check for updates:', error);
112
+ this.emit('progress', {
113
+ phase: 'error',
114
+ progress: 0,
115
+ message: 'Failed to check for updates',
116
+ error: error
117
+ });
118
+ throw error;
119
+ }
120
+ }
121
+ /**
122
+ * Install an update
123
+ */
124
+ async installUpdate(manifest) {
125
+ if (this.updateInProgress) {
126
+ throw new Error('Update already in progress');
127
+ }
128
+ this.updateInProgress = true;
129
+ this.isUpdating = true;
130
+ try {
131
+ logger.info(`Installing update to version ${manifest.version}`);
132
+ this.emit('updateStarted', manifest);
133
+ // Phase 1: Download
134
+ this.emit('progress', {
135
+ phase: 'downloading',
136
+ progress: 0,
137
+ message: `Downloading version ${manifest.version}...`
138
+ });
139
+ const downloadPath = await this.downloadUpdate(manifest);
140
+ // Phase 2: Verify
141
+ this.emit('progress', {
142
+ phase: 'verifying',
143
+ progress: 80,
144
+ message: 'Verifying download...'
145
+ });
146
+ await this.verifyDownload(downloadPath, manifest.checksumSha256);
147
+ // Phase 3: Backup current version
148
+ if (this.options.backupEnabled) {
149
+ await this.createBackup();
150
+ }
151
+ // Phase 4: Install
152
+ this.emit('progress', {
153
+ phase: 'installing',
154
+ progress: 90,
155
+ message: 'Installing update...'
156
+ });
157
+ await this.performInstallation(downloadPath, manifest);
158
+ // Phase 5: Complete
159
+ this.emit('progress', {
160
+ phase: 'complete',
161
+ progress: 100,
162
+ message: 'Update completed successfully'
163
+ });
164
+ logger.info(`Update to version ${manifest.version} completed successfully`);
165
+ this.emit('updateCompleted', manifest);
166
+ }
167
+ catch (error) {
168
+ logger.error('Update installation failed:', error);
169
+ this.emit('progress', {
170
+ phase: 'error',
171
+ progress: 0,
172
+ message: 'Update installation failed',
173
+ error: error
174
+ });
175
+ this.emit('updateFailed', { manifest, error });
176
+ // Attempt rollback if backup exists
177
+ if (this.options.backupEnabled) {
178
+ try {
179
+ await this.rollbackUpdate();
180
+ logger.info('Successfully rolled back to previous version');
181
+ }
182
+ catch (rollbackError) {
183
+ logger.error('Rollback failed:', rollbackError);
184
+ }
185
+ }
186
+ throw error;
187
+ }
188
+ finally {
189
+ this.updateInProgress = false;
190
+ this.isUpdating = false;
191
+ }
192
+ }
193
+ /**
194
+ * Rollback to previous version
195
+ */
196
+ async rollbackUpdate() {
197
+ logger.info('Rolling back to previous version');
198
+ const backupPath = this.getBackupPath();
199
+ if (!fs.existsSync(backupPath)) {
200
+ throw new Error('No backup available for rollback');
201
+ }
202
+ try {
203
+ const currentPath = this.getCurrentExecutablePath();
204
+ // Replace current executable with backup
205
+ fs.copyFileSync(backupPath, currentPath);
206
+ fs.chmodSync(currentPath, 0o755);
207
+ logger.info('Rollback completed successfully');
208
+ this.emit('rollbackCompleted');
209
+ }
210
+ catch (error) {
211
+ logger.error('Rollback failed:', error);
212
+ this.emit('rollbackFailed', error);
213
+ throw error;
214
+ }
215
+ }
216
+ /**
217
+ * Get current version
218
+ */
219
+ getCurrentVersion() {
220
+ return this.currentVersion;
221
+ }
222
+ /**
223
+ * Check if update is in progress
224
+ */
225
+ isUpdateInProgress() {
226
+ return this.updateInProgress;
227
+ }
228
+ /**
229
+ * Fetch update manifest from server
230
+ */
231
+ async fetchUpdateManifest() {
232
+ const manifestUrl = `${this.options.updateServerUrl}/manifest.json`;
233
+ return new Promise((resolve, reject) => {
234
+ const request = https.get(manifestUrl, (response) => {
235
+ if (response.statusCode !== 200) {
236
+ reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));
237
+ return;
238
+ }
239
+ let data = '';
240
+ response.on('data', chunk => data += chunk);
241
+ response.on('end', () => {
242
+ try {
243
+ const manifest = JSON.parse(data);
244
+ resolve(manifest);
245
+ }
246
+ catch (error) {
247
+ reject(new Error(`Invalid manifest JSON: ${error}`));
248
+ }
249
+ });
250
+ });
251
+ request.on('error', reject);
252
+ request.setTimeout(30000, () => {
253
+ request.destroy();
254
+ reject(new Error('Request timeout'));
255
+ });
256
+ });
257
+ }
258
+ /**
259
+ * Download update file
260
+ */
261
+ async downloadUpdate(manifest) {
262
+ const downloadPath = path.join(this.getTempDir(), `buildhive-agent-${manifest.version}`);
263
+ return new Promise((resolve, reject) => {
264
+ const file = fs.createWriteStream(downloadPath);
265
+ let downloadedBytes = 0;
266
+ const request = https.get(manifest.downloadUrl, (response) => {
267
+ if (response.statusCode !== 200) {
268
+ reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));
269
+ return;
270
+ }
271
+ response.pipe(file);
272
+ response.on('data', (chunk) => {
273
+ downloadedBytes += chunk.length;
274
+ const progress = Math.floor((downloadedBytes / manifest.size) * 70); // 0-70% for download
275
+ this.emit('progress', {
276
+ phase: 'downloading',
277
+ progress,
278
+ message: `Downloaded ${this.formatBytes(downloadedBytes)} of ${this.formatBytes(manifest.size)}`
279
+ });
280
+ });
281
+ response.on('end', () => {
282
+ file.close();
283
+ resolve(downloadPath);
284
+ });
285
+ });
286
+ request.on('error', (error) => {
287
+ fs.unlink(downloadPath, () => { }); // Clean up partial download
288
+ reject(error);
289
+ });
290
+ file.on('error', (error) => {
291
+ fs.unlink(downloadPath, () => { }); // Clean up partial download
292
+ reject(error);
293
+ });
294
+ request.setTimeout(300000, () => {
295
+ request.destroy();
296
+ fs.unlink(downloadPath, () => { });
297
+ reject(new Error('Download timeout'));
298
+ });
299
+ });
300
+ }
301
+ /**
302
+ * Verify downloaded file
303
+ */
304
+ async verifyDownload(filePath, expectedChecksum) {
305
+ return new Promise((resolve, reject) => {
306
+ const hash = crypto.createHash('sha256');
307
+ const stream = fs.createReadStream(filePath);
308
+ stream.on('data', data => hash.update(data));
309
+ stream.on('end', () => {
310
+ const actualChecksum = hash.digest('hex');
311
+ if (actualChecksum === expectedChecksum) {
312
+ resolve();
313
+ }
314
+ else {
315
+ reject(new Error(`Checksum mismatch. Expected: ${expectedChecksum}, Actual: ${actualChecksum}`));
316
+ }
317
+ });
318
+ stream.on('error', reject);
319
+ });
320
+ }
321
+ /**
322
+ * Create backup of current version
323
+ */
324
+ async createBackup() {
325
+ const currentPath = this.getCurrentExecutablePath();
326
+ const backupPath = this.getBackupPath();
327
+ // Ensure backup directory exists
328
+ const backupDir = path.dirname(backupPath);
329
+ if (!fs.existsSync(backupDir)) {
330
+ fs.mkdirSync(backupDir, { recursive: true });
331
+ }
332
+ fs.copyFileSync(currentPath, backupPath);
333
+ logger.debug(`Backup created at: ${backupPath}`);
334
+ }
335
+ /**
336
+ * Perform the actual installation
337
+ */
338
+ async performInstallation(downloadPath, manifest) {
339
+ const currentPath = this.getCurrentExecutablePath();
340
+ // Make downloaded file executable
341
+ fs.chmodSync(downloadPath, 0o755);
342
+ // Replace current executable
343
+ fs.copyFileSync(downloadPath, currentPath);
344
+ // Clean up download
345
+ fs.unlinkSync(downloadPath);
346
+ // Update current version
347
+ this.currentVersion = manifest.version;
348
+ logger.debug(`Installation completed: ${currentPath}`);
349
+ }
350
+ /**
351
+ * Compare version strings
352
+ */
353
+ compareVersions(a, b) {
354
+ const aParts = a.split('.').map(Number);
355
+ const bParts = b.split('.').map(Number);
356
+ for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
357
+ const aPart = aParts[i] || 0;
358
+ const bPart = bParts[i] || 0;
359
+ if (aPart > bPart)
360
+ return 1;
361
+ if (aPart < bPart)
362
+ return -1;
363
+ }
364
+ return 0;
365
+ }
366
+ /**
367
+ * Get current executable path
368
+ */
369
+ getCurrentExecutablePath() {
370
+ return process.execPath;
371
+ }
372
+ /**
373
+ * Get backup file path
374
+ */
375
+ getBackupPath() {
376
+ const backupDir = path.join(this.getTempDir(), 'buildhive-backups');
377
+ return path.join(backupDir, `buildhive-agent-${this.currentVersion}.backup`);
378
+ }
379
+ /**
380
+ * Get temporary directory
381
+ */
382
+ getTempDir() {
383
+ const tempDir = path.join(process.cwd(), '.buildhive', 'temp');
384
+ if (!fs.existsSync(tempDir)) {
385
+ fs.mkdirSync(tempDir, { recursive: true });
386
+ }
387
+ return tempDir;
388
+ }
389
+ /**
390
+ * Format bytes for display
391
+ */
392
+ formatBytes(bytes) {
393
+ if (bytes === 0)
394
+ return '0 Bytes';
395
+ const k = 1024;
396
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
397
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
398
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
399
+ }
400
+ }
401
+ /**
402
+ * Compare two semver strings. Returns positive if a > b, negative if a < b, 0 if equal.
403
+ */
404
+ function compareSemver(a, b) {
405
+ const aParts = a.replace(/^v/, '').split('.').map(Number);
406
+ const bParts = b.replace(/^v/, '').split('.').map(Number);
407
+ for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
408
+ const diff = (aParts[i] || 0) - (bParts[i] || 0);
409
+ if (diff !== 0)
410
+ return diff;
411
+ }
412
+ return 0;
413
+ }
414
+ /**
415
+ * Fetch the latest version of a package from the npm registry.
416
+ */
417
+ async function fetchLatestNpmVersion(packageName) {
418
+ return new Promise((resolve) => {
419
+ const url = `https://registry.npmjs.org/${packageName}/latest`;
420
+ https.get(url, { timeout: 10000 }, (res) => {
421
+ let data = '';
422
+ res.on('data', (chunk) => (data += chunk));
423
+ res.on('end', () => {
424
+ try {
425
+ const json = JSON.parse(data);
426
+ resolve(json.version ?? null);
427
+ }
428
+ catch {
429
+ resolve(null);
430
+ }
431
+ });
432
+ }).on('error', () => resolve(null));
433
+ });
434
+ }
435
+ /**
436
+ * Gracefully wait for active jobs to finish before restarting.
437
+ * Polls the provided predicate every `intervalMs` ms up to `maxWaitMs`.
438
+ */
439
+ async function waitForJobsDrained(isIdle, maxWaitMs = 5 * 60 * 1000, intervalMs = 5000) {
440
+ const deadline = Date.now() + maxWaitMs;
441
+ while (!isIdle() && Date.now() < deadline) {
442
+ await new Promise((r) => setTimeout(r, intervalMs));
443
+ }
444
+ }
445
+ /**
446
+ * Startup version check (Task 2.1.3).
447
+ *
448
+ * Called once when the agent starts. Compares the local package version against
449
+ * the npm registry. If a newer version is available:
450
+ * - Always logs a warning with the upgrade command.
451
+ * - If `autoUpdate` is true, runs `npm install -g <package>` after draining
452
+ * active jobs and then exits so the process manager can restart with the new
453
+ * binary (graceful restart pattern).
454
+ *
455
+ * @param packageName npm package name (default: "@buildhive/agent")
456
+ * @param localVersion current version string from package.json
457
+ * @param autoUpdate whether to auto-install the update (default: false)
458
+ * @param isIdle predicate returning true when no jobs are active (for graceful drain)
459
+ */
460
+ export async function checkStartupVersion(options) {
461
+ const { packageName = '@buildhive/agent', localVersion, autoUpdate = false, isIdle = () => true, } = options;
462
+ const updateLogger = createLogger('auto-updater');
463
+ try {
464
+ updateLogger.info(`Checking for updates (current: ${localVersion})...`);
465
+ const latestVersion = await fetchLatestNpmVersion(packageName);
466
+ if (!latestVersion) {
467
+ updateLogger.warn('Could not fetch latest version from npm registry — skipping update check.');
468
+ return;
469
+ }
470
+ if (compareSemver(latestVersion, localVersion) <= 0) {
471
+ updateLogger.info(`Agent is up to date (${localVersion}).`);
472
+ return;
473
+ }
474
+ updateLogger.warn(`Update available: ${localVersion} → ${latestVersion}. ` +
475
+ `Run \`npm install -g ${packageName}@${latestVersion}\` to upgrade.`);
476
+ if (!autoUpdate) {
477
+ return;
478
+ }
479
+ // Auto-update: drain active jobs first, then install and restart
480
+ updateLogger.info('Auto-update enabled. Waiting for active jobs to finish...');
481
+ await waitForJobsDrained(isIdle);
482
+ updateLogger.info(`Installing ${packageName}@${latestVersion}...`);
483
+ const { execSync } = await import('child_process');
484
+ execSync(`npm install -g ${packageName}@${latestVersion}`, { stdio: 'inherit' });
485
+ updateLogger.info('Update installed. Restarting agent process...');
486
+ // Exit cleanly so the process manager (systemd, PM2, etc.) restarts with the new binary
487
+ process.exit(0);
488
+ }
489
+ catch (error) {
490
+ // Version check must never crash the agent startup
491
+ updateLogger.error('Startup version check failed (non-fatal):', error);
492
+ }
493
+ }
494
+ //# sourceMappingURL=autoUpdater.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoUpdater.js","sourceRoot":"","sources":["../src/autoUpdater.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Cache Manager - Build cache volume mount system
3
+ *
4
+ * Manages persistent build caches across job executions.
5
+ * Supports LRU, FIFO, and LFU eviction strategies.
6
+ * Generates Docker volume mount arguments for cache directories.
7
+ *
8
+ * Requirements: Build caching for CI cost reduction
9
+ */
10
+ export interface CacheEntry {
11
+ name: string;
12
+ hostPath: string;
13
+ sizeBytes: number;
14
+ lastUsed: Date;
15
+ hitCount: number;
16
+ createdAt: Date;
17
+ }
18
+ export interface CacheStats {
19
+ totalEntries: number;
20
+ totalSizeBytes: number;
21
+ maxSizeBytes: number;
22
+ hitRate: number;
23
+ totalHits: number;
24
+ totalMisses: number;
25
+ }
26
+ export interface CacheVolumeMount {
27
+ hostPath: string;
28
+ containerPath: string;
29
+ readOnly: boolean;
30
+ }
31
+ export declare class CacheManager {
32
+ private cacheDir;
33
+ private maxSizeBytes;
34
+ private strategy;
35
+ private entries;
36
+ private totalHits;
37
+ private totalMisses;
38
+ private preConfiguredVolumes;
39
+ constructor(config: {
40
+ directory: string;
41
+ maxSizeGB: number;
42
+ strategy: 'lru' | 'fifo' | 'lfu';
43
+ volumes?: Record<string, string>;
44
+ });
45
+ /**
46
+ * Initialize cache directory and load metadata
47
+ */
48
+ initialize(): Promise<void>;
49
+ /**
50
+ * Get or create a named cache volume. Returns the host path.
51
+ * If the cache doesn't exist, creates the directory.
52
+ * Records a cache hit or miss.
53
+ */
54
+ getCache(name: string): Promise<string>;
55
+ /**
56
+ * Generate Docker volume mount args from recipe cache config.
57
+ * Maps recipe cache paths to host cache directories.
58
+ */
59
+ generateVolumeMounts(recipeCacheConfig: {
60
+ paths: string[];
61
+ key?: string;
62
+ }): CacheVolumeMount[];
63
+ /**
64
+ * Convert volume mounts to Docker -v arguments
65
+ */
66
+ toDockerArgs(mounts: CacheVolumeMount[]): string[];
67
+ /**
68
+ * Evict caches based on strategy until under maxSize.
69
+ * Returns names of evicted entries.
70
+ */
71
+ evict(): Promise<string[]>;
72
+ /**
73
+ * Get cache statistics
74
+ */
75
+ getStats(): CacheStats;
76
+ /**
77
+ * Clear all caches
78
+ */
79
+ clear(): Promise<void>;
80
+ /**
81
+ * Save cache metadata to disk
82
+ */
83
+ saveMetadata(): Promise<void>;
84
+ /**
85
+ * Load cache metadata from disk
86
+ */
87
+ loadMetadata(): Promise<void>;
88
+ /**
89
+ * Update the recorded size of a cache entry by scanning its directory.
90
+ */
91
+ updateEntrySize(name: string): Promise<void>;
92
+ /**
93
+ * Get total size of a directory in bytes
94
+ */
95
+ private getDirectorySize;
96
+ private getTotalSize;
97
+ /**
98
+ * Select the next entry to evict based on the configured strategy.
99
+ */
100
+ private selectVictim;
101
+ /**
102
+ * Convert a filesystem path to a cache name.
103
+ * e.g. "~/.gradle/caches" -> "gradle-caches"
104
+ * "/root/.gradle/caches" -> "gradle-caches"
105
+ */
106
+ private pathToCacheName;
107
+ }
108
+ //# sourceMappingURL=cacheManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cacheManager.d.ts","sourceRoot":"","sources":["../src/cacheManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,IAAI,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAyBD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,oBAAoB,CAAyB;gBAEzC,MAAM,EAAE;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;QACjC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAClC;IAOD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBjC;;;;OAIG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA4B7C;;;OAGG;IACH,oBAAoB,CAAC,iBAAiB,EAAE;QACtC,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GAAG,gBAAgB,EAAE;IAkBtB;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,EAAE;IAWlD;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IA2BhC;;OAEG;IACH,QAAQ,IAAI,UAAU;IAYtB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAc5B;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBnC;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BnC;;OAEG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWlD;;OAEG;YACW,gBAAgB;IAmB9B,OAAO,CAAC,YAAY;IAQpB;;OAEG;IACH,OAAO,CAAC,YAAY;IA6BpB;;;;OAIG;IACH,OAAO,CAAC,eAAe;CAcxB"}