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
package/README.md ADDED
@@ -0,0 +1,166 @@
1
+ # BuildHive Agent
2
+
3
+ The BuildHive Agent is a lightweight service that runs on developer machines to execute CI/CD build jobs in a secure, isolated environment.
4
+
5
+ ## Configuration
6
+
7
+ The agent uses a hierarchical configuration system that loads settings from:
8
+
9
+ 1. Default configuration values
10
+ 2. Configuration files (JSON format)
11
+ 3. Environment variable overrides
12
+
13
+ ### Configuration Files
14
+
15
+ The agent searches for configuration files in the following locations (in order):
16
+
17
+ 1. `./buildhive-agent.json` (current directory)
18
+ 2. `./config/buildhive-agent.json`
19
+ 3. `./.config/buildhive-agent.json`
20
+ 4. `~/.buildhive/buildhive-agent.json` (user home directory)
21
+ 5. `/etc/buildhive/buildhive-agent.json` (system-wide)
22
+
23
+ Alternative file names are also supported:
24
+ - `buildhive-agent.config.json`
25
+ - `.buildhive-agent.json`
26
+
27
+ ### Environment Variables
28
+
29
+ All configuration options can be overridden using environment variables:
30
+
31
+ | Environment Variable | Configuration Field | Type | Example |
32
+ |---------------------|---------------------|------|---------|
33
+ | `BUILDHIVE_PLATFORM_URL` | `platformUrl` | string | `https://api.buildhive.dev` |
34
+ | `BUILDHIVE_API_KEY` | `apiKey` | string | `your-api-key` |
35
+ | `BUILDHIVE_AGENT_ID` | `agentId` | string | `agent-123` |
36
+ | `BUILDHIVE_AGENT_NAME` | `name` | string | `My Agent` |
37
+ | `BUILDHIVE_MAX_CONCURRENT_JOBS` | `maxConcurrentJobs` | number | `2` |
38
+ | `BUILDHIVE_HEARTBEAT_INTERVAL` | `heartbeatInterval` | number | `30` |
39
+ | `BUILDHIVE_TAGS` | `tags` | string (comma-separated) | `android,linux` |
40
+ | `BUILDHIVE_LOG_LEVEL` | `logLevel` | string | `info` |
41
+ | `BUILDHIVE_JOB_TIMEOUT_MINUTES` | `jobTimeoutMinutes` | number | `60` |
42
+ | `BUILDHIVE_ENABLE_METRICS` | `enableMetrics` | boolean | `true` |
43
+ | `BUILDHIVE_ENABLE_AUTO_UPDATES` | `enableAutoUpdates` | boolean | `false` |
44
+
45
+ ### Configuration Schema
46
+
47
+ #### Required Fields
48
+
49
+ - `platformUrl`: URL of the BuildHive platform API
50
+ - `apiKey`: Authentication key for the agent
51
+ - `agentId`: Unique identifier for this agent
52
+ - `name`: Human-readable name for the agent
53
+
54
+ #### Optional Fields
55
+
56
+ - `maxConcurrentJobs` (default: 1): Maximum number of jobs to run simultaneously
57
+ - `heartbeatInterval` (default: 30): Heartbeat interval in seconds
58
+ - `tags` (default: []): Tags for job matching
59
+ - `logLevel` (default: "info"): Logging level (debug, info, warn, error)
60
+ - `jobTimeoutMinutes` (default: 60): Maximum job execution time
61
+ - `enableMetrics` (default: true): Enable metrics collection
62
+ - `enableAutoUpdates` (default: true): Enable automatic agent updates
63
+
64
+ #### Docker Configuration
65
+
66
+ - `dockerConfig.baseImage` (default: "ubuntu:22.04"): Base Docker image
67
+ - `dockerConfig.networkMode` (default: "none"): Network isolation mode
68
+ - `dockerConfig.memoryLimit` (default: "2g"): Memory limit for containers
69
+ - `dockerConfig.cpuLimit` (default: "1.0"): CPU limit for containers
70
+ - `dockerConfig.volumeMounts` (default: []): Volume mount configurations
71
+
72
+ #### Resource Limits
73
+
74
+ - `maxMemoryUsage` (default: 80): Maximum memory usage percentage
75
+ - `maxCpuUsage` (default: 80): Maximum CPU usage percentage
76
+ - `maxDiskUsage` (default: 90): Maximum disk usage percentage
77
+
78
+ #### Security
79
+
80
+ - `allowedRepositories`: Whitelist of allowed repositories (optional)
81
+ - `blockedRepositories`: Blacklist of blocked repositories (optional)
82
+
83
+ Note: You cannot specify both `allowedRepositories` and `blockedRepositories`.
84
+
85
+ ### Example Configuration
86
+
87
+ ```json
88
+ {
89
+ "platformUrl": "https://api.buildhive.dev",
90
+ "apiKey": "your-api-key-here",
91
+ "agentId": "agent-unique-id",
92
+ "name": "My Build Agent",
93
+ "maxConcurrentJobs": 2,
94
+ "heartbeatInterval": 30,
95
+ "tags": ["android", "linux", "docker"],
96
+ "dockerConfig": {
97
+ "baseImage": "ubuntu:22.04",
98
+ "networkMode": "none",
99
+ "memoryLimit": "4g",
100
+ "cpuLimit": "2.0",
101
+ "volumeMounts": [
102
+ {
103
+ "hostPath": "/tmp/buildhive-cache",
104
+ "containerPath": "/cache",
105
+ "readOnly": false
106
+ }
107
+ ]
108
+ },
109
+ "maxMemoryUsage": 80,
110
+ "maxCpuUsage": 75,
111
+ "maxDiskUsage": 90,
112
+ "logLevel": "info",
113
+ "logRetentionDays": 7,
114
+ "allowedRepositories": [
115
+ "myorg/repo1",
116
+ "myorg/repo2"
117
+ ],
118
+ "jobTimeoutMinutes": 120,
119
+ "connectionTimeoutSeconds": 30,
120
+ "enableMetrics": true,
121
+ "enableAutoUpdates": true
122
+ }
123
+ ```
124
+
125
+ ## Installation
126
+
127
+ ```bash
128
+ npm install
129
+ ```
130
+
131
+ ## Development
132
+
133
+ ```bash
134
+ # Build the project
135
+ npm run build
136
+
137
+ # Run tests
138
+ npm test
139
+
140
+ # Run tests in watch mode
141
+ npm run test:watch
142
+
143
+ # Run tests with coverage
144
+ npm run test:coverage
145
+
146
+ # Development mode with auto-rebuild
147
+ npm run dev
148
+ ```
149
+
150
+ ## Usage
151
+
152
+ ```typescript
153
+ import { loadConfig, saveConfig, validateConfigFile } from '@buildhive/agent';
154
+
155
+ // Load configuration
156
+ const config = await loadConfig();
157
+
158
+ // Save configuration
159
+ await saveConfig(config, './my-config.json');
160
+
161
+ // Validate a configuration file
162
+ const validation = validateConfigFile('./config.json');
163
+ if (!validation.isValid) {
164
+ console.error('Configuration errors:', validation.errors);
165
+ }
166
+ ```
@@ -0,0 +1,115 @@
1
+ /**
2
+ * FakeDockerManager — in-memory test double for DockerManager.
3
+ *
4
+ * Implements the same public API surface as the real DockerManager
5
+ * (createContainer, startContainer, executeCommand, stopContainer,
6
+ * removeContainer, pullImage, copyFromContainer) without touching
7
+ * the real Docker daemon or the filesystem.
8
+ *
9
+ * Usage in tests:
10
+ *
11
+ * const fake = new FakeDockerManager();
12
+ * fake.setCommandResult('echo hi', { exitCode: 0, output: 'hi' });
13
+ * const id = await fake.createContainer({ image: 'node:20', ... });
14
+ * await fake.startContainer(id);
15
+ * const result = await fake.executeCommand(id, 'echo hi');
16
+ * expect(result.exitCode).toBe(0);
17
+ */
18
+ import type { ContainerConfig, ExecutionOptions, ExecutionResult } from '../../docker.js';
19
+ type ContainerState = 'created' | 'running' | 'stopped' | 'removed';
20
+ interface ContainerRecord {
21
+ config: ContainerConfig;
22
+ state: ContainerState;
23
+ id: string;
24
+ }
25
+ export interface FakeCommandResult {
26
+ exitCode: number;
27
+ output: string;
28
+ error?: string;
29
+ }
30
+ export declare class FakeDockerManager {
31
+ private containers;
32
+ private pulledImages;
33
+ private commandOverrides;
34
+ private defaultCommandResult;
35
+ private copyLog;
36
+ private idCounter;
37
+ /**
38
+ * Override the result returned when executeCommand is called with the exact
39
+ * command string. Pass undefined to remove the override.
40
+ */
41
+ setCommandResult(command: string, result: FakeCommandResult | undefined): void;
42
+ /**
43
+ * Set the result returned by executeCommand when no per-command override
44
+ * matches. Defaults to { exitCode: 0, output: '' }.
45
+ */
46
+ setDefaultCommandResult(result: FakeCommandResult): void;
47
+ /**
48
+ * Reset all internal state (containers, pulled images, overrides, copy log).
49
+ * Call this in beforeEach to ensure test isolation.
50
+ */
51
+ reset(): void;
52
+ /** Returns true if the container ID is known (not removed). */
53
+ hasContainer(containerId: string): boolean;
54
+ /** Returns the state of a container, or undefined if it does not exist. */
55
+ getContainerState(containerId: string): ContainerState | undefined;
56
+ /** Returns the config used to create a container, or undefined. */
57
+ getContainerConfig(containerId: string): ContainerConfig | undefined;
58
+ /** Returns all containers currently tracked (not yet removed). */
59
+ getActiveContainers(): ReadonlyMap<string, ContainerRecord>;
60
+ /** Returns whether an image has been pulled via pullImage(). */
61
+ isImagePulled(image: string): boolean;
62
+ /** Returns the log of all copyFromContainer calls in call order. */
63
+ getCopyLog(): ReadonlyArray<{
64
+ containerId: string;
65
+ containerPath: string;
66
+ hostPath: string;
67
+ }>;
68
+ /**
69
+ * Resolves immediately. Marks the image as pulled so tests can assert
70
+ * pullImage() was called.
71
+ */
72
+ pullImage(image: string): Promise<void>;
73
+ /**
74
+ * Creates an in-memory container record in the 'created' state and returns
75
+ * its ID. The ID follows the same "buildhive-<n>" pattern as the real
76
+ * implementation (predictable in tests).
77
+ */
78
+ createContainer(containerConfig: ContainerConfig): Promise<string>;
79
+ /**
80
+ * Transitions the container from 'created' to 'running'.
81
+ * Throws if the container does not exist or is not in 'created' state.
82
+ */
83
+ startContainer(containerId: string): Promise<void>;
84
+ /**
85
+ * Executes a command against a running container.
86
+ *
87
+ * - If a per-command override has been registered via setCommandResult() the
88
+ * override result is returned.
89
+ * - Otherwise the default result (exitCode: 0, output: '') is returned.
90
+ * - The optional onOutput callback is invoked with the output string when
91
+ * output is non-empty, mirroring the streaming behaviour of the real impl.
92
+ * - Throws if the container is not in 'running' state.
93
+ */
94
+ executeCommand(containerId: string, command: string, options?: ExecutionOptions): Promise<ExecutionResult>;
95
+ /**
96
+ * Transitions the container to 'stopped' state.
97
+ * Silently succeeds if the container is already stopped (matches the real
98
+ * impl's defensive behaviour).
99
+ */
100
+ stopContainer(containerId: string, _timeout?: number): Promise<void>;
101
+ /**
102
+ * Stops the container (if running) and removes it from the internal map.
103
+ * Does NOT throw if the container is not found — mirrors the real impl's
104
+ * "don't throw from cleanup" contract.
105
+ */
106
+ removeContainer(containerId: string): Promise<void>;
107
+ /**
108
+ * Records the copy operation in the copy log so tests can assert it was
109
+ * called with the correct paths. Throws if the container is not running.
110
+ */
111
+ copyFromContainer(containerId: string, containerPath: string, hostPath: string): Promise<void>;
112
+ private requireContainer;
113
+ }
114
+ export {};
115
+ //# sourceMappingURL=FakeDockerManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FakeDockerManager.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fakes/FakeDockerManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAM1F,KAAK,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpE,UAAU,eAAe;IACvB,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,cAAc,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;CACZ;AAMD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,qBAAa,iBAAiB;IAE5B,OAAO,CAAC,UAAU,CAAsC;IAGxD,OAAO,CAAC,YAAY,CAAqB;IAKzC,OAAO,CAAC,gBAAgB,CAAwC;IAGhE,OAAO,CAAC,oBAAoB,CAAkD;IAG9E,OAAO,CAAC,OAAO,CAA+E;IAG9F,OAAO,CAAC,SAAS,CAAK;IAMtB;;;OAGG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,SAAS,GAAG,IAAI;IAQ9E;;;OAGG;IACH,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAIxD;;;OAGG;IACH,KAAK,IAAI,IAAI;IAab,+DAA+D;IAC/D,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAI1C,2EAA2E;IAC3E,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIlE,mEAAmE;IACnE,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAIpE,kEAAkE;IAClE,mBAAmB,IAAI,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC;IAI3D,gEAAgE;IAChE,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIrC,oEAAoE;IACpE,UAAU,IAAI,aAAa,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAQ7F;;;OAGG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C;;;;OAIG;IACG,eAAe,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAUxE;;;OAGG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUxD;;;;;;;;;OASG;IACG,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC;IAqB3B;;;;OAIG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO1E;;;;OAIG;IACG,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASzD;;;OAGG;IACG,iBAAiB,CACrB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAchB,OAAO,CAAC,gBAAgB;CAOzB"}
@@ -0,0 +1,203 @@
1
+ /**
2
+ * FakeDockerManager — in-memory test double for DockerManager.
3
+ *
4
+ * Implements the same public API surface as the real DockerManager
5
+ * (createContainer, startContainer, executeCommand, stopContainer,
6
+ * removeContainer, pullImage, copyFromContainer) without touching
7
+ * the real Docker daemon or the filesystem.
8
+ *
9
+ * Usage in tests:
10
+ *
11
+ * const fake = new FakeDockerManager();
12
+ * fake.setCommandResult('echo hi', { exitCode: 0, output: 'hi' });
13
+ * const id = await fake.createContainer({ image: 'node:20', ... });
14
+ * await fake.startContainer(id);
15
+ * const result = await fake.executeCommand(id, 'echo hi');
16
+ * expect(result.exitCode).toBe(0);
17
+ */
18
+ // ---------------------------------------------------------------------------
19
+ // FakeDockerManager
20
+ // ---------------------------------------------------------------------------
21
+ export class FakeDockerManager {
22
+ // Map of containerId -> record
23
+ containers = new Map();
24
+ // Set of images that have been pulled
25
+ pulledImages = new Set();
26
+ // Per-command overrides keyed by the command string.
27
+ // When a command matches a key the configured result is returned;
28
+ // otherwise the default result is used.
29
+ commandOverrides = new Map();
30
+ // Default result returned by executeCommand when no override matches.
31
+ defaultCommandResult = { exitCode: 0, output: '' };
32
+ // Track every copy operation for assertion in tests.
33
+ copyLog = [];
34
+ // Counter used to generate deterministic container IDs in tests.
35
+ idCounter = 0;
36
+ // ---------------------------------------------------------------------------
37
+ // Configuration helpers (call these from test setup)
38
+ // ---------------------------------------------------------------------------
39
+ /**
40
+ * Override the result returned when executeCommand is called with the exact
41
+ * command string. Pass undefined to remove the override.
42
+ */
43
+ setCommandResult(command, result) {
44
+ if (result === undefined) {
45
+ this.commandOverrides.delete(command);
46
+ }
47
+ else {
48
+ this.commandOverrides.set(command, result);
49
+ }
50
+ }
51
+ /**
52
+ * Set the result returned by executeCommand when no per-command override
53
+ * matches. Defaults to { exitCode: 0, output: '' }.
54
+ */
55
+ setDefaultCommandResult(result) {
56
+ this.defaultCommandResult = result;
57
+ }
58
+ /**
59
+ * Reset all internal state (containers, pulled images, overrides, copy log).
60
+ * Call this in beforeEach to ensure test isolation.
61
+ */
62
+ reset() {
63
+ this.containers.clear();
64
+ this.pulledImages.clear();
65
+ this.commandOverrides.clear();
66
+ this.copyLog = [];
67
+ this.idCounter = 0;
68
+ this.defaultCommandResult = { exitCode: 0, output: '' };
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Inspection helpers (for assertions in tests)
72
+ // ---------------------------------------------------------------------------
73
+ /** Returns true if the container ID is known (not removed). */
74
+ hasContainer(containerId) {
75
+ return this.containers.has(containerId);
76
+ }
77
+ /** Returns the state of a container, or undefined if it does not exist. */
78
+ getContainerState(containerId) {
79
+ return this.containers.get(containerId)?.state;
80
+ }
81
+ /** Returns the config used to create a container, or undefined. */
82
+ getContainerConfig(containerId) {
83
+ return this.containers.get(containerId)?.config;
84
+ }
85
+ /** Returns all containers currently tracked (not yet removed). */
86
+ getActiveContainers() {
87
+ return this.containers;
88
+ }
89
+ /** Returns whether an image has been pulled via pullImage(). */
90
+ isImagePulled(image) {
91
+ return this.pulledImages.has(image);
92
+ }
93
+ /** Returns the log of all copyFromContainer calls in call order. */
94
+ getCopyLog() {
95
+ return this.copyLog;
96
+ }
97
+ // ---------------------------------------------------------------------------
98
+ // Public API — mirrors DockerManager method signatures exactly
99
+ // ---------------------------------------------------------------------------
100
+ /**
101
+ * Resolves immediately. Marks the image as pulled so tests can assert
102
+ * pullImage() was called.
103
+ */
104
+ async pullImage(image) {
105
+ this.pulledImages.add(image);
106
+ }
107
+ /**
108
+ * Creates an in-memory container record in the 'created' state and returns
109
+ * its ID. The ID follows the same "buildhive-<n>" pattern as the real
110
+ * implementation (predictable in tests).
111
+ */
112
+ async createContainer(containerConfig) {
113
+ const containerId = `buildhive-fake-${++this.idCounter}`;
114
+ this.containers.set(containerId, {
115
+ id: containerId,
116
+ config: containerConfig,
117
+ state: 'created',
118
+ });
119
+ return containerId;
120
+ }
121
+ /**
122
+ * Transitions the container from 'created' to 'running'.
123
+ * Throws if the container does not exist or is not in 'created' state.
124
+ */
125
+ async startContainer(containerId) {
126
+ const record = this.requireContainer(containerId);
127
+ if (record.state !== 'created') {
128
+ throw new Error(`FakeDockerManager: cannot start container ${containerId} — current state is '${record.state}'`);
129
+ }
130
+ record.state = 'running';
131
+ }
132
+ /**
133
+ * Executes a command against a running container.
134
+ *
135
+ * - If a per-command override has been registered via setCommandResult() the
136
+ * override result is returned.
137
+ * - Otherwise the default result (exitCode: 0, output: '') is returned.
138
+ * - The optional onOutput callback is invoked with the output string when
139
+ * output is non-empty, mirroring the streaming behaviour of the real impl.
140
+ * - Throws if the container is not in 'running' state.
141
+ */
142
+ async executeCommand(containerId, command, options = {}) {
143
+ const record = this.requireContainer(containerId);
144
+ if (record.state !== 'running') {
145
+ throw new Error(`FakeDockerManager: cannot execute command in container ${containerId} — current state is '${record.state}'`);
146
+ }
147
+ const override = this.commandOverrides.get(command);
148
+ const result = override
149
+ ? { ...override }
150
+ : { ...this.defaultCommandResult };
151
+ // Mirror the real impl: call onOutput if there is output to stream.
152
+ if (options.onOutput && result.output) {
153
+ options.onOutput(result.output);
154
+ }
155
+ return result;
156
+ }
157
+ /**
158
+ * Transitions the container to 'stopped' state.
159
+ * Silently succeeds if the container is already stopped (matches the real
160
+ * impl's defensive behaviour).
161
+ */
162
+ async stopContainer(containerId, _timeout) {
163
+ const record = this.requireContainer(containerId);
164
+ if (record.state !== 'removed') {
165
+ record.state = 'stopped';
166
+ }
167
+ }
168
+ /**
169
+ * Stops the container (if running) and removes it from the internal map.
170
+ * Does NOT throw if the container is not found — mirrors the real impl's
171
+ * "don't throw from cleanup" contract.
172
+ */
173
+ async removeContainer(containerId) {
174
+ const record = this.containers.get(containerId);
175
+ if (!record) {
176
+ return; // already removed — no-op
177
+ }
178
+ record.state = 'removed';
179
+ this.containers.delete(containerId);
180
+ }
181
+ /**
182
+ * Records the copy operation in the copy log so tests can assert it was
183
+ * called with the correct paths. Throws if the container is not running.
184
+ */
185
+ async copyFromContainer(containerId, containerPath, hostPath) {
186
+ const record = this.requireContainer(containerId);
187
+ if (record.state !== 'running') {
188
+ throw new Error(`FakeDockerManager: cannot copy from container ${containerId} — current state is '${record.state}'`);
189
+ }
190
+ this.copyLog.push({ containerId, containerPath, hostPath });
191
+ }
192
+ // ---------------------------------------------------------------------------
193
+ // Private helpers
194
+ // ---------------------------------------------------------------------------
195
+ requireContainer(containerId) {
196
+ const record = this.containers.get(containerId);
197
+ if (!record) {
198
+ throw new Error(`FakeDockerManager: container not found: ${containerId}`);
199
+ }
200
+ return record;
201
+ }
202
+ }
203
+ //# sourceMappingURL=FakeDockerManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FakeDockerManager.js","sourceRoot":"","sources":["../../../src/__tests__/fakes/FakeDockerManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Acceptance Checker
3
+ *
4
+ * Evaluates whether a job should be accepted based on configured
5
+ * acceptance rules (recipe patterns, repository patterns, duration, Docker).
6
+ */
7
+ import { AcceptanceRules } from './config/types.js';
8
+ export interface JobCandidate {
9
+ recipe?: string;
10
+ repository?: string;
11
+ estimatedDurationMinutes?: number;
12
+ requiresDocker?: boolean;
13
+ }
14
+ export interface AcceptanceDecision {
15
+ accepted: boolean;
16
+ reason?: string;
17
+ }
18
+ export declare class AcceptanceChecker {
19
+ private rules;
20
+ constructor(rules: AcceptanceRules);
21
+ /**
22
+ * Check if a job should be accepted based on the configured acceptance rules.
23
+ */
24
+ shouldAccept(job: JobCandidate): AcceptanceDecision;
25
+ }
26
+ //# sourceMappingURL=acceptanceChecker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acceptanceChecker.d.ts","sourceRoot":"","sources":["../src/acceptanceChecker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAoBD,qBAAa,iBAAiB;IAChB,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,eAAe;IAE1C;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,YAAY,GAAG,kBAAkB;CAqCpD"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Acceptance Checker
3
+ *
4
+ * Evaluates whether a job should be accepted based on configured
5
+ * acceptance rules (recipe patterns, repository patterns, duration, Docker).
6
+ */
7
+ /**
8
+ * Simple glob matcher supporting * and ? wildcards.
9
+ * Avoids external dependency on minimatch.
10
+ */
11
+ function globMatch(pattern, value) {
12
+ // Convert glob to regex
13
+ const escaped = pattern
14
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&') // escape regex special chars (except * and ?)
15
+ .replace(/\*/g, '.*')
16
+ .replace(/\?/g, '.');
17
+ const regex = new RegExp(`^${escaped}$`, 'i');
18
+ return regex.test(value);
19
+ }
20
+ function matchesAny(patterns, value) {
21
+ return patterns.some(p => globMatch(p, value));
22
+ }
23
+ export class AcceptanceChecker {
24
+ rules;
25
+ constructor(rules) {
26
+ this.rules = rules;
27
+ }
28
+ /**
29
+ * Check if a job should be accepted based on the configured acceptance rules.
30
+ */
31
+ shouldAccept(job) {
32
+ // Check blocked recipes first (takes precedence)
33
+ if (job.recipe && this.rules.blockedRecipes.length > 0) {
34
+ if (matchesAny(this.rules.blockedRecipes, job.recipe)) {
35
+ return { accepted: false, reason: `Recipe "${job.recipe}" is blocked` };
36
+ }
37
+ }
38
+ // Check allowed recipes
39
+ if (job.recipe && this.rules.allowedRecipes.length > 0) {
40
+ if (!matchesAny(this.rules.allowedRecipes, job.recipe)) {
41
+ return { accepted: false, reason: `Recipe "${job.recipe}" is not in allowed list` };
42
+ }
43
+ }
44
+ // Check allowed repositories
45
+ if (job.repository && this.rules.allowedRepositories.length > 0) {
46
+ if (!matchesAny(this.rules.allowedRepositories, job.repository)) {
47
+ return { accepted: false, reason: `Repository "${job.repository}" is not in allowed list` };
48
+ }
49
+ }
50
+ // Check max duration
51
+ if (job.estimatedDurationMinutes !== undefined && job.estimatedDurationMinutes > this.rules.maxJobDurationMinutes) {
52
+ return {
53
+ accepted: false,
54
+ reason: `Estimated duration (${job.estimatedDurationMinutes}m) exceeds max (${this.rules.maxJobDurationMinutes}m)`
55
+ };
56
+ }
57
+ // Check Docker requirement
58
+ if (this.rules.requireDocker && job.requiresDocker === false) {
59
+ return { accepted: false, reason: 'Agent requires Docker but job does not use Docker' };
60
+ }
61
+ return { accepted: true };
62
+ }
63
+ }
64
+ //# sourceMappingURL=acceptanceChecker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acceptanceChecker.js","sourceRoot":"","sources":["../src/acceptanceChecker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgBH;;;GAGG;AACH,SAAS,SAAS,CAAC,OAAe,EAAE,KAAa;IAC/C,wBAAwB;IACxB,MAAM,OAAO,GAAG,OAAO;SACpB,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC,8CAA8C;SACnF,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvB,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,OAAO,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,UAAU,CAAC,QAAkB,EAAE,KAAa;IACnD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,OAAO,iBAAiB;IACR;IAApB,YAAoB,KAAsB;QAAtB,UAAK,GAAL,KAAK,CAAiB;IAAG,CAAC;IAE9C;;OAEG;IACH,YAAY,CAAC,GAAiB;QAC5B,iDAAiD;QACjD,IAAI,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,GAAG,CAAC,MAAM,cAAc,EAAE,CAAC;YAC1E,CAAC;QACH,CAAC;QAED,wBAAwB;QACxB,IAAI,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,GAAG,CAAC,MAAM,0BAA0B,EAAE,CAAC;YACtF,CAAC;QACH,CAAC;QAED,6BAA6B;QAC7B,IAAI,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAAE,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;gBAChE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,GAAG,CAAC,UAAU,0BAA0B,EAAE,CAAC;YAC9F,CAAC;QACH,CAAC;QAED,qBAAqB;QACrB,IAAI,GAAG,CAAC,wBAAwB,KAAK,SAAS,IAAI,GAAG,CAAC,wBAAwB,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,EAAE,CAAC;YAClH,OAAO;gBACL,QAAQ,EAAE,KAAK;gBACf,MAAM,EAAE,uBAAuB,GAAG,CAAC,wBAAwB,mBAAmB,IAAI,CAAC,KAAK,CAAC,qBAAqB,IAAI;aACnH,CAAC;QACJ,CAAC;QAED,2BAA2B;QAC3B,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,IAAI,GAAG,CAAC,cAAc,KAAK,KAAK,EAAE,CAAC;YAC7D,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,mDAAmD,EAAE,CAAC;QAC1F,CAAC;QAED,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC5B,CAAC;CACF"}