@action-llama/action-llama 0.10.2 → 0.11.0
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/AGENTS.md +17 -6
- package/README.md +8 -4
- package/dist/agents/container-entry.d.ts.map +1 -1
- package/dist/agents/container-entry.js +37 -0
- package/dist/agents/container-entry.js.map +1 -1
- package/dist/agents/container-runner.d.ts +4 -0
- package/dist/agents/container-runner.d.ts.map +1 -1
- package/dist/agents/container-runner.js +82 -5
- package/dist/agents/container-runner.js.map +1 -1
- package/dist/agents/execution-engine.d.ts +2 -0
- package/dist/agents/execution-engine.d.ts.map +1 -1
- package/dist/agents/execution-engine.js +5 -1
- package/dist/agents/execution-engine.js.map +1 -1
- package/dist/agents/runner.d.ts +3 -0
- package/dist/agents/runner.d.ts.map +1 -1
- package/dist/agents/runner.js +45 -2
- package/dist/agents/runner.js.map +1 -1
- package/dist/cli/commands/chat.d.ts +5 -2
- package/dist/cli/commands/chat.d.ts.map +1 -1
- package/dist/cli/commands/chat.js +240 -23
- package/dist/cli/commands/chat.js.map +1 -1
- package/dist/cli/commands/cloud-deploy.d.ts.map +1 -1
- package/dist/cli/commands/cloud-deploy.js +5 -47
- package/dist/cli/commands/cloud-deploy.js.map +1 -1
- package/dist/cli/commands/cloud-setup.d.ts.map +1 -1
- package/dist/cli/commands/cloud-setup.js +20 -33
- package/dist/cli/commands/cloud-setup.js.map +1 -1
- package/dist/cli/commands/cloud-teardown.d.ts.map +1 -1
- package/dist/cli/commands/cloud-teardown.js +6 -126
- package/dist/cli/commands/cloud-teardown.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts +0 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +19 -14
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/kill.d.ts +1 -1
- package/dist/cli/commands/kill.d.ts.map +1 -1
- package/dist/cli/commands/kill.js +17 -6
- package/dist/cli/commands/kill.js.map +1 -1
- package/dist/cli/commands/logs.d.ts.map +1 -1
- package/dist/cli/commands/logs.js +104 -58
- package/dist/cli/commands/logs.js.map +1 -1
- package/dist/cli/commands/pause.d.ts +1 -1
- package/dist/cli/commands/pause.d.ts.map +1 -1
- package/dist/cli/commands/pause.js +9 -6
- package/dist/cli/commands/pause.js.map +1 -1
- package/dist/cli/commands/resume.d.ts +1 -1
- package/dist/cli/commands/resume.d.ts.map +1 -1
- package/dist/cli/commands/resume.js +9 -6
- package/dist/cli/commands/resume.js.map +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +12 -54
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +22 -39
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/gateway-client.d.ts +12 -0
- package/dist/cli/gateway-client.d.ts.map +1 -0
- package/dist/cli/gateway-client.js +27 -0
- package/dist/cli/gateway-client.js.map +1 -0
- package/dist/cli/main.js +49 -14
- package/dist/cli/main.js.map +1 -1
- package/dist/{shared/aws-constants.d.ts → cloud/aws/constants.d.ts} +3 -34
- package/dist/cloud/aws/constants.d.ts.map +1 -0
- package/dist/{shared/aws-constants.js → cloud/aws/constants.js} +3 -34
- package/dist/cloud/aws/constants.js.map +1 -0
- package/dist/cloud/{deploy-apprunner.d.ts → aws/deploy.d.ts} +6 -6
- package/dist/cloud/aws/deploy.d.ts.map +1 -0
- package/dist/cloud/{deploy-apprunner.js → aws/deploy.js} +2 -2
- package/dist/cloud/aws/deploy.js.map +1 -0
- package/dist/cloud/aws/iam.d.ts +37 -0
- package/dist/cloud/aws/iam.d.ts.map +1 -0
- package/dist/{cli/commands/cloud-iam.js → cloud/aws/iam.js} +30 -179
- package/dist/cloud/aws/iam.js.map +1 -0
- package/dist/cloud/aws/provider.d.ts +69 -0
- package/dist/cloud/aws/provider.d.ts.map +1 -0
- package/dist/cloud/aws/provider.js +173 -0
- package/dist/cloud/aws/provider.js.map +1 -0
- package/dist/cloud/aws/provision.d.ts +9 -0
- package/dist/cloud/aws/provision.d.ts.map +1 -0
- package/dist/{cli/commands/cloud-setup-ecs.js → cloud/aws/provision.js} +10 -9
- package/dist/cloud/aws/provision.js.map +1 -0
- package/dist/cloud/aws/teardown.d.ts +15 -0
- package/dist/cloud/aws/teardown.d.ts.map +1 -0
- package/dist/cloud/aws/teardown.js +74 -0
- package/dist/cloud/aws/teardown.js.map +1 -0
- package/dist/cloud/gcp/constants.d.ts +16 -0
- package/dist/cloud/gcp/constants.d.ts.map +1 -0
- package/dist/cloud/gcp/constants.js +16 -0
- package/dist/cloud/gcp/constants.js.map +1 -0
- package/dist/cloud/{deploy-cloudrun.d.ts → gcp/deploy.d.ts} +6 -6
- package/dist/cloud/gcp/deploy.d.ts.map +1 -0
- package/dist/cloud/{deploy-cloudrun.js → gcp/deploy.js} +7 -7
- package/dist/cloud/gcp/deploy.js.map +1 -0
- package/dist/cloud/gcp/iam.d.ts +20 -0
- package/dist/cloud/gcp/iam.d.ts.map +1 -0
- package/dist/cloud/gcp/iam.js +179 -0
- package/dist/cloud/gcp/iam.js.map +1 -0
- package/dist/cloud/gcp/provider.d.ts +28 -0
- package/dist/cloud/gcp/provider.d.ts.map +1 -0
- package/dist/cloud/gcp/provider.js +84 -0
- package/dist/cloud/gcp/provider.js.map +1 -0
- package/dist/cloud/gcp/provision.d.ts +14 -0
- package/dist/cloud/gcp/provision.d.ts.map +1 -0
- package/dist/cloud/gcp/provision.js +37 -0
- package/dist/cloud/gcp/provision.js.map +1 -0
- package/dist/cloud/gcp/teardown.d.ts +12 -0
- package/dist/cloud/gcp/teardown.d.ts.map +1 -0
- package/dist/cloud/gcp/teardown.js +67 -0
- package/dist/cloud/gcp/teardown.js.map +1 -0
- package/dist/cloud/image-builder.d.ts.map +1 -1
- package/dist/cloud/image-builder.js +115 -18
- package/dist/cloud/image-builder.js.map +1 -1
- package/dist/cloud/provider.d.ts +57 -0
- package/dist/cloud/provider.d.ts.map +1 -0
- package/dist/cloud/provider.js +21 -0
- package/dist/cloud/provider.js.map +1 -0
- package/dist/cloud/scheduler-image.d.ts.map +1 -1
- package/dist/cloud/scheduler-image.js +16 -3
- package/dist/cloud/scheduler-image.js.map +1 -1
- package/dist/cloud/state.d.ts +17 -0
- package/dist/cloud/state.d.ts.map +1 -0
- package/dist/cloud/state.js +48 -0
- package/dist/cloud/state.js.map +1 -0
- package/dist/docker/aws-shared.d.ts +6 -4
- package/dist/docker/aws-shared.d.ts.map +1 -1
- package/dist/docker/aws-shared.js +405 -23
- package/dist/docker/aws-shared.js.map +1 -1
- package/dist/docker/cloud-run-runtime.d.ts.map +1 -1
- package/dist/docker/cloud-run-runtime.js +10 -9
- package/dist/docker/cloud-run-runtime.js.map +1 -1
- package/dist/docker/ecs-runtime.d.ts +3 -1
- package/dist/docker/ecs-runtime.d.ts.map +1 -1
- package/dist/docker/ecs-runtime.js +78 -29
- package/dist/docker/ecs-runtime.js.map +1 -1
- package/dist/docker/image.d.ts +7 -0
- package/dist/docker/image.d.ts.map +1 -1
- package/dist/docker/image.js +31 -4
- package/dist/docker/image.js.map +1 -1
- package/dist/docker/lambda-runtime.js +1 -1
- package/dist/docker/lambda-runtime.js.map +1 -1
- package/dist/docker/local-runtime.js +4 -4
- package/dist/docker/local-runtime.js.map +1 -1
- package/dist/docker/network.d.ts.map +1 -1
- package/dist/docker/network.js +2 -2
- package/dist/docker/network.js.map +1 -1
- package/dist/docker/runtime.d.ts +23 -0
- package/dist/docker/runtime.d.ts.map +1 -1
- package/dist/gateway/api-key.d.ts +10 -0
- package/dist/gateway/api-key.d.ts.map +1 -0
- package/dist/gateway/api-key.js +19 -0
- package/dist/gateway/api-key.js.map +1 -0
- package/dist/gateway/auth.d.ts +16 -0
- package/dist/gateway/auth.d.ts.map +1 -0
- package/dist/gateway/auth.js +60 -0
- package/dist/gateway/auth.js.map +1 -0
- package/dist/gateway/index.d.ts +1 -0
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +33 -2
- package/dist/gateway/index.js.map +1 -1
- package/dist/gateway/routes/control.d.ts +6 -0
- package/dist/gateway/routes/control.d.ts.map +1 -1
- package/dist/gateway/routes/control.js +117 -0
- package/dist/gateway/routes/control.js.map +1 -1
- package/dist/gateway/routes/dashboard.d.ts +1 -1
- package/dist/gateway/routes/dashboard.d.ts.map +1 -1
- package/dist/gateway/routes/dashboard.js +144 -53
- package/dist/gateway/routes/dashboard.js.map +1 -1
- package/dist/gateway/views/dashboard-page.d.ts.map +1 -1
- package/dist/gateway/views/dashboard-page.js +93 -20
- package/dist/gateway/views/dashboard-page.js.map +1 -1
- package/dist/gateway/views/login-page.d.ts +2 -0
- package/dist/gateway/views/login-page.d.ts.map +1 -0
- package/dist/gateway/views/login-page.js +54 -0
- package/dist/gateway/views/login-page.js.map +1 -0
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +154 -36
- package/dist/scheduler/index.js.map +1 -1
- package/dist/scheduler/runner-pool.d.ts +5 -0
- package/dist/scheduler/runner-pool.d.ts.map +1 -1
- package/dist/scheduler/runner-pool.js +14 -0
- package/dist/scheduler/runner-pool.js.map +1 -1
- package/dist/scheduler/runtime-factory.d.ts +2 -0
- package/dist/scheduler/runtime-factory.d.ts.map +1 -1
- package/dist/scheduler/runtime-factory.js +35 -65
- package/dist/scheduler/runtime-factory.js.map +1 -1
- package/dist/setup/scaffold.d.ts.map +1 -1
- package/dist/setup/scaffold.js +25 -0
- package/dist/setup/scaffold.js.map +1 -1
- package/dist/shared/asm-backend.d.ts.map +1 -1
- package/dist/shared/asm-backend.js +2 -2
- package/dist/shared/asm-backend.js.map +1 -1
- package/dist/shared/config.d.ts +28 -13
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/shared/config.js +40 -4
- package/dist/shared/config.js.map +1 -1
- package/dist/shared/constants.d.ts +34 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +34 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/shared/credential-backend.d.ts +1 -1
- package/dist/shared/filesystem-backend.d.ts +1 -1
- package/dist/shared/filesystem-backend.js +1 -1
- package/dist/shared/gsm-backend.d.ts.map +1 -1
- package/dist/shared/gsm-backend.js +2 -2
- package/dist/shared/gsm-backend.js.map +1 -1
- package/dist/shared/paths.d.ts +2 -0
- package/dist/shared/paths.d.ts.map +1 -1
- package/dist/shared/paths.js +3 -1
- package/dist/shared/paths.js.map +1 -1
- package/dist/shared/remote.d.ts +1 -0
- package/dist/shared/remote.d.ts.map +1 -1
- package/dist/shared/remote.js +4 -16
- package/dist/shared/remote.js.map +1 -1
- package/dist/shared/usage.d.ts +22 -0
- package/dist/shared/usage.d.ts.map +1 -0
- package/dist/shared/usage.js +43 -0
- package/dist/shared/usage.js.map +1 -0
- package/dist/telemetry/index.d.ts +57 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +189 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/providers/otel.d.ts +15 -0
- package/dist/telemetry/providers/otel.d.ts.map +1 -0
- package/dist/telemetry/providers/otel.js +77 -0
- package/dist/telemetry/providers/otel.js.map +1 -0
- package/dist/telemetry/providers/xray.d.ts +13 -0
- package/dist/telemetry/providers/xray.d.ts.map +1 -0
- package/dist/telemetry/providers/xray.js +33 -0
- package/dist/telemetry/providers/xray.js.map +1 -0
- package/dist/telemetry/types.d.ts +59 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/telemetry/types.js +2 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +2 -0
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/plain-logger.d.ts.map +1 -1
- package/dist/tui/plain-logger.js +8 -2
- package/dist/tui/plain-logger.js.map +1 -1
- package/dist/tui/status-tracker.d.ts +4 -1
- package/dist/tui/status-tracker.d.ts.map +1 -1
- package/dist/tui/status-tracker.js +11 -1
- package/dist/tui/status-tracker.js.map +1 -1
- package/docker/adot-collector-config.yaml +57 -0
- package/package.json +9 -1
- package/dist/cli/commands/cloud-iam.d.ts +0 -17
- package/dist/cli/commands/cloud-iam.d.ts.map +0 -1
- package/dist/cli/commands/cloud-iam.js.map +0 -1
- package/dist/cli/commands/cloud-setup-ecs.d.ts +0 -9
- package/dist/cli/commands/cloud-setup-ecs.d.ts.map +0 -1
- package/dist/cli/commands/cloud-setup-ecs.js.map +0 -1
- package/dist/cloud/deploy-apprunner.d.ts.map +0 -1
- package/dist/cloud/deploy-apprunner.js.map +0 -1
- package/dist/cloud/deploy-cloudrun.d.ts.map +0 -1
- package/dist/cloud/deploy-cloudrun.js.map +0 -1
- package/dist/shared/aws-constants.d.ts.map +0 -1
- package/dist/shared/aws-constants.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler-image.js","sourceRoot":"","sources":["../../src/cloud/scheduler-image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/F,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAGpC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"scheduler-image.js","sourceRoot":"","sources":["../../src/cloud/scheduler-image.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud provisioning state persistence.
|
|
3
|
+
* Stores provisioned resource information at ~/.action-llama/state/<project-hash>.json.
|
|
4
|
+
*/
|
|
5
|
+
import type { ProvisionedResource } from "./provider.js";
|
|
6
|
+
export interface ProvisionedState {
|
|
7
|
+
projectPath: string;
|
|
8
|
+
provider: "ecs" | "cloud-run";
|
|
9
|
+
createdAt: string;
|
|
10
|
+
updatedAt: string;
|
|
11
|
+
resources: ProvisionedResource[];
|
|
12
|
+
}
|
|
13
|
+
export declare function loadState(projectPath: string): ProvisionedState | null;
|
|
14
|
+
export declare function saveState(state: ProvisionedState): void;
|
|
15
|
+
export declare function deleteState(projectPath: string): void;
|
|
16
|
+
export declare function createState(projectPath: string, provider: "ecs" | "cloud-run", resources: ProvisionedResource[]): ProvisionedState;
|
|
17
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/cloud/state.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEzD,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,KAAK,GAAG,WAAW,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,mBAAmB,EAAE,CAAC;CAClC;AAUD,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAQtE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAKvD;AAED,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAKrD;AAED,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,KAAK,GAAG,WAAW,EAC7B,SAAS,EAAE,mBAAmB,EAAE,GAC/B,gBAAgB,CASlB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud provisioning state persistence.
|
|
3
|
+
* Stores provisioned resource information at ~/.action-llama/state/<project-hash>.json.
|
|
4
|
+
*/
|
|
5
|
+
import { createHash } from "crypto";
|
|
6
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from "fs";
|
|
7
|
+
import { resolve } from "path";
|
|
8
|
+
import { STATE_DIR } from "../shared/paths.js";
|
|
9
|
+
function projectHash(projectPath) {
|
|
10
|
+
return createHash("sha256").update(projectPath).digest("hex").slice(0, 12);
|
|
11
|
+
}
|
|
12
|
+
function stateFilePath(projectPath) {
|
|
13
|
+
return resolve(STATE_DIR, `${projectHash(projectPath)}.json`);
|
|
14
|
+
}
|
|
15
|
+
export function loadState(projectPath) {
|
|
16
|
+
const filePath = stateFilePath(projectPath);
|
|
17
|
+
if (!existsSync(filePath))
|
|
18
|
+
return null;
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(readFileSync(filePath, "utf-8"));
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function saveState(state) {
|
|
27
|
+
mkdirSync(STATE_DIR, { recursive: true });
|
|
28
|
+
const filePath = stateFilePath(state.projectPath);
|
|
29
|
+
state.updatedAt = new Date().toISOString();
|
|
30
|
+
writeFileSync(filePath, JSON.stringify(state, null, 2));
|
|
31
|
+
}
|
|
32
|
+
export function deleteState(projectPath) {
|
|
33
|
+
const filePath = stateFilePath(projectPath);
|
|
34
|
+
if (existsSync(filePath)) {
|
|
35
|
+
unlinkSync(filePath);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function createState(projectPath, provider, resources) {
|
|
39
|
+
const now = new Date().toISOString();
|
|
40
|
+
return {
|
|
41
|
+
projectPath,
|
|
42
|
+
provider,
|
|
43
|
+
createdAt: now,
|
|
44
|
+
updatedAt: now,
|
|
45
|
+
resources,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/cloud/state.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACpF,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAW/C,SAAS,WAAW,CAAC,WAAmB;IACtC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,aAAa,CAAC,WAAmB;IACxC,OAAO,OAAO,CAAC,SAAS,EAAE,GAAG,WAAW,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,WAAmB;IAC3C,MAAM,QAAQ,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC5C,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAqB,CAAC;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAuB;IAC/C,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAClD,KAAK,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,WAAmB;IAC7C,MAAM,QAAQ,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC5C,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,WAAmB,EACnB,QAA6B,EAC7B,SAAgC;IAEhC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO;QACL,WAAW;QACX,QAAQ;QACR,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;QACd,SAAS;KACV,CAAC;AACJ,CAAC"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Extracted from ECSFargateRuntime to avoid duplicating CodeBuild,
|
|
5
5
|
* ECR, Secrets Manager, and S3 logic across runtimes.
|
|
6
6
|
*/
|
|
7
|
-
import type { RuntimeCredentials, BuildImageOpts } from "./runtime.js";
|
|
7
|
+
import type { RuntimeCredentials, BuildImageOpts, AssembleImageOpts } from "./runtime.js";
|
|
8
8
|
export interface AwsSharedConfig {
|
|
9
9
|
awsRegion: string;
|
|
10
10
|
ecrRepository: string;
|
|
@@ -33,6 +33,9 @@ export declare class AwsSharedUtils {
|
|
|
33
33
|
ensureBuildBucket(): Promise<string>;
|
|
34
34
|
ensureCodeBuildProject(projectName: string, bucket: string): Promise<void>;
|
|
35
35
|
buildImageCodeBuild(opts: BuildImageOpts, onProgress?: (message: string) => void): Promise<string>;
|
|
36
|
+
assembleImageDirect(opts: AssembleImageOpts): Promise<string>;
|
|
37
|
+
private uploadBlob;
|
|
38
|
+
buildMultipleImagesCodeBuild(builds: BuildImageOpts[], onProgress?: (message: string) => void): Promise<string[]>;
|
|
36
39
|
private logGroupsCreated;
|
|
37
40
|
ensureLogGroup(logGroupName: string): Promise<void>;
|
|
38
41
|
getLogEvents(logGroup: string, logStream: string, nextToken?: string): Promise<{
|
|
@@ -43,9 +46,8 @@ export declare class AwsSharedUtils {
|
|
|
43
46
|
}>;
|
|
44
47
|
/**
|
|
45
48
|
* Scan log events in a time window using FilterLogEvents.
|
|
46
|
-
* Returns events in ascending order
|
|
47
|
-
*
|
|
48
|
-
* through all matching events rather than capping at `limit` oldest entries.
|
|
49
|
+
* Returns events in ascending order. Uses time-bounded queries and limits
|
|
50
|
+
* to improve performance by starting with a narrower time window.
|
|
49
51
|
*/
|
|
50
52
|
filterLogEvents(logGroupName: string, logStreamPrefix: string, limit: number, startTime?: number): Promise<string[]>;
|
|
51
53
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aws-shared.d.ts","sourceRoot":"","sources":["../../src/docker/aws-shared.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"aws-shared.d.ts","sourceRoot":"","sources":["../../src/docker/aws-shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,11 +8,12 @@ import { execFileSync } from "child_process";
|
|
|
8
8
|
import { createReadStream } from "fs";
|
|
9
9
|
import { SecretsManagerClient, ListSecretsCommand, GetSecretValueCommand, } from "@aws-sdk/client-secrets-manager";
|
|
10
10
|
import { CloudWatchLogsClient, GetLogEventsCommand, FilterLogEventsCommand, CreateLogGroupCommand, } from "@aws-sdk/client-cloudwatch-logs";
|
|
11
|
-
import { CodeBuildClient, StartBuildCommand, BatchGetBuildsCommand, CreateProjectCommand, } from "@aws-sdk/client-codebuild";
|
|
11
|
+
import { CodeBuildClient, StartBuildCommand, BatchGetBuildsCommand, CreateProjectCommand, UpdateProjectCommand, } from "@aws-sdk/client-codebuild";
|
|
12
12
|
import { S3Client, PutObjectCommand, CreateBucketCommand, HeadBucketCommand, } from "@aws-sdk/client-s3";
|
|
13
|
-
import { ECRClient, BatchGetImageCommand, } from "@aws-sdk/client-ecr";
|
|
13
|
+
import { ECRClient, BatchGetImageCommand, PutImageCommand, GetDownloadUrlForLayerCommand, InitiateLayerUploadCommand, UploadLayerPartCommand, CompleteLayerUploadCommand, } from "@aws-sdk/client-ecr";
|
|
14
14
|
import { parseCredentialRef, sanitizeEnvPart } from "../shared/credentials.js";
|
|
15
|
-
import {
|
|
15
|
+
import { CONSTANTS } from "../shared/constants.js";
|
|
16
|
+
import { AWS_CONSTANTS } from "../cloud/aws/constants.js";
|
|
16
17
|
export class AwsSharedUtils {
|
|
17
18
|
config;
|
|
18
19
|
prefix;
|
|
@@ -23,7 +24,7 @@ export class AwsSharedUtils {
|
|
|
23
24
|
ecrClient;
|
|
24
25
|
constructor(config) {
|
|
25
26
|
this.config = config;
|
|
26
|
-
this.prefix = config.secretPrefix ||
|
|
27
|
+
this.prefix = config.secretPrefix || CONSTANTS.DEFAULT_SECRET_PREFIX;
|
|
27
28
|
const clientConfig = { region: config.awsRegion };
|
|
28
29
|
this.smClient = new SecretsManagerClient(clientConfig);
|
|
29
30
|
this.logsClient = new CloudWatchLogsClient(clientConfig);
|
|
@@ -154,6 +155,7 @@ export class AwsSharedUtils {
|
|
|
154
155
|
}
|
|
155
156
|
catch { }
|
|
156
157
|
const serviceRole = `arn:aws:iam::${accountId}:role/${AWS_CONSTANTS.CODEBUILD_ROLE}`;
|
|
158
|
+
const cache = { type: "LOCAL", modes: ["LOCAL_DOCKER_LAYER_CACHE"] };
|
|
157
159
|
try {
|
|
158
160
|
await this.cbClient.send(new CreateProjectCommand({
|
|
159
161
|
name: projectName,
|
|
@@ -173,6 +175,7 @@ export class AwsSharedUtils {
|
|
|
173
175
|
{ name: "DOCKERFILE", value: "Dockerfile" },
|
|
174
176
|
],
|
|
175
177
|
},
|
|
178
|
+
cache,
|
|
176
179
|
serviceRole,
|
|
177
180
|
}));
|
|
178
181
|
}
|
|
@@ -180,6 +183,16 @@ export class AwsSharedUtils {
|
|
|
180
183
|
if (err.name !== "ResourceAlreadyExistsException") {
|
|
181
184
|
throw err;
|
|
182
185
|
}
|
|
186
|
+
// Project exists — ensure cache config is applied
|
|
187
|
+
try {
|
|
188
|
+
await this.cbClient.send(new UpdateProjectCommand({
|
|
189
|
+
name: projectName,
|
|
190
|
+
cache,
|
|
191
|
+
}));
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// Best-effort — build still works without local cache
|
|
195
|
+
}
|
|
183
196
|
}
|
|
184
197
|
}
|
|
185
198
|
async buildImageCodeBuild(opts, onProgress) {
|
|
@@ -334,6 +347,7 @@ export class AwsSharedUtils {
|
|
|
334
347
|
const projectName = AWS_CONSTANTS.CODEBUILD_PROJECT;
|
|
335
348
|
await this.ensureCodeBuildProject(projectName, bucket);
|
|
336
349
|
const registry = this.config.ecrRepository.split("/")[0];
|
|
350
|
+
const cacheTag = `${this.config.ecrRepository}:${nameTag}-cache`;
|
|
337
351
|
const buildspec = [
|
|
338
352
|
"version: 0.2",
|
|
339
353
|
"phases:",
|
|
@@ -343,11 +357,14 @@ export class AwsSharedUtils {
|
|
|
343
357
|
// archive is still present (e.g. when sourceType handling changes).
|
|
344
358
|
" - if ls *.tar.gz 1>/dev/null 2>&1; then tar xzf *.tar.gz && rm -f *.tar.gz; fi",
|
|
345
359
|
" - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ECR_REGISTRY",
|
|
360
|
+
" - docker pull $CACHE_TAG || true",
|
|
346
361
|
" build:",
|
|
347
362
|
" commands:",
|
|
348
363
|
" - ls -la",
|
|
349
|
-
" - docker build -t $IMAGE_URI -f $DOCKERFILE .",
|
|
364
|
+
" - docker build --cache-from $CACHE_TAG -t $IMAGE_URI -f $DOCKERFILE .",
|
|
350
365
|
" - docker push $IMAGE_URI",
|
|
366
|
+
" - docker tag $IMAGE_URI $CACHE_TAG",
|
|
367
|
+
" - docker push $CACHE_TAG",
|
|
351
368
|
].join("\n");
|
|
352
369
|
const buildRes = await this.cbClient.send(new StartBuildCommand({
|
|
353
370
|
projectName,
|
|
@@ -358,6 +375,7 @@ export class AwsSharedUtils {
|
|
|
358
375
|
{ name: "IMAGE_URI", value: remoteTag },
|
|
359
376
|
{ name: "ECR_REGISTRY", value: registry },
|
|
360
377
|
{ name: "DOCKERFILE", value: "Dockerfile" },
|
|
378
|
+
{ name: "CACHE_TAG", value: cacheTag },
|
|
361
379
|
],
|
|
362
380
|
}));
|
|
363
381
|
const buildId = buildRes.build?.id;
|
|
@@ -396,6 +414,350 @@ export class AwsSharedUtils {
|
|
|
396
414
|
}
|
|
397
415
|
}
|
|
398
416
|
}
|
|
417
|
+
// --- Direct image assembly (bypass CodeBuild for thin agents) ---
|
|
418
|
+
async assembleImageDirect(opts) {
|
|
419
|
+
const { join, dirname: dirnameFn } = await import("path");
|
|
420
|
+
const { mkdirSync, writeFileSync, rmSync, readFileSync: readFileSyncBuf } = await import("fs");
|
|
421
|
+
const { execFileSync } = await import("child_process");
|
|
422
|
+
const { createHash, randomUUID } = await import("crypto");
|
|
423
|
+
const { gzipSync } = await import("zlib");
|
|
424
|
+
const { tmpdir } = await import("os");
|
|
425
|
+
// Compute content hash for cache check
|
|
426
|
+
const hash = createHash("sha256");
|
|
427
|
+
hash.update(opts.baseImage);
|
|
428
|
+
const sortedEntries = Object.entries(opts.extraFiles).sort(([a], [b]) => a.localeCompare(b));
|
|
429
|
+
for (const [name, content] of sortedEntries) {
|
|
430
|
+
hash.update(name);
|
|
431
|
+
hash.update(content);
|
|
432
|
+
}
|
|
433
|
+
const contentHash = hash.digest("hex").slice(0, 16);
|
|
434
|
+
const nameTag = opts.tag.replace(":", "-");
|
|
435
|
+
const hashTag = `${nameTag}-${contentHash}`;
|
|
436
|
+
const remoteTag = `${this.config.ecrRepository}:${hashTag}`;
|
|
437
|
+
const repoName = this.config.ecrRepository.split("/").pop();
|
|
438
|
+
opts.onProgress?.(`Checking cache (${hashTag})`);
|
|
439
|
+
const exists = await this.ecrImageExists(repoName, hashTag, opts.onProgress);
|
|
440
|
+
if (exists) {
|
|
441
|
+
opts.onProgress?.("Image unchanged — reusing cached build");
|
|
442
|
+
return remoteTag;
|
|
443
|
+
}
|
|
444
|
+
opts.onProgress?.("Assembling image directly (no CodeBuild)");
|
|
445
|
+
// Create temp dir with the layer structure: app/static/...
|
|
446
|
+
const tmpDir = join(tmpdir(), `al-assemble-${randomUUID().slice(0, 8)}`);
|
|
447
|
+
mkdirSync(join(tmpDir, "app", "static"), { recursive: true });
|
|
448
|
+
for (const [filename, content] of Object.entries(opts.extraFiles)) {
|
|
449
|
+
const filePath = join(tmpDir, "app", "static", filename);
|
|
450
|
+
mkdirSync(dirnameFn(filePath), { recursive: true });
|
|
451
|
+
writeFileSync(filePath, content);
|
|
452
|
+
}
|
|
453
|
+
// Create layer tar via system tar (consistent with buildImageCodeBuild)
|
|
454
|
+
const tarPath = join(tmpdir(), `al-layer-${randomUUID().slice(0, 8)}.tar`);
|
|
455
|
+
try {
|
|
456
|
+
execFileSync("tar", ["cf", tarPath, "-C", tmpDir, "app"], {
|
|
457
|
+
timeout: 30_000,
|
|
458
|
+
env: { ...process.env, COPYFILE_DISABLE: "1" },
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
finally {
|
|
462
|
+
try {
|
|
463
|
+
rmSync(tmpDir, { recursive: true });
|
|
464
|
+
}
|
|
465
|
+
catch { }
|
|
466
|
+
}
|
|
467
|
+
const tarBuffer = readFileSyncBuf(tarPath);
|
|
468
|
+
try {
|
|
469
|
+
rmSync(tarPath);
|
|
470
|
+
}
|
|
471
|
+
catch { }
|
|
472
|
+
const compressedLayer = gzipSync(tarBuffer);
|
|
473
|
+
const layerDigest = `sha256:${createHash("sha256").update(compressedLayer).digest("hex")}`;
|
|
474
|
+
const diffId = `sha256:${createHash("sha256").update(tarBuffer).digest("hex")}`;
|
|
475
|
+
// Get base image manifest
|
|
476
|
+
opts.onProgress?.("Fetching base image manifest");
|
|
477
|
+
const baseTag = opts.baseImage.includes(":")
|
|
478
|
+
? opts.baseImage.split(":").pop()
|
|
479
|
+
: opts.baseImage;
|
|
480
|
+
const baseRes = await this.ecrClient.send(new BatchGetImageCommand({
|
|
481
|
+
repositoryName: repoName,
|
|
482
|
+
imageIds: [{ imageTag: baseTag }],
|
|
483
|
+
}));
|
|
484
|
+
if (!baseRes.images?.length)
|
|
485
|
+
throw new Error(`Base image ${baseTag} not found in ECR`);
|
|
486
|
+
const manifest = JSON.parse(baseRes.images[0].imageManifest);
|
|
487
|
+
// Fetch config blob via pre-signed URL
|
|
488
|
+
opts.onProgress?.("Fetching base image config");
|
|
489
|
+
const configDigest = manifest.config.digest;
|
|
490
|
+
const configDownload = await this.ecrClient.send(new GetDownloadUrlForLayerCommand({
|
|
491
|
+
repositoryName: repoName,
|
|
492
|
+
layerDigest: configDigest,
|
|
493
|
+
}));
|
|
494
|
+
const configRes = await fetch(configDownload.downloadUrl);
|
|
495
|
+
const configJson = JSON.parse(await configRes.text());
|
|
496
|
+
// Extend config with our layer
|
|
497
|
+
configJson.rootfs.diff_ids.push(diffId);
|
|
498
|
+
configJson.history = configJson.history || [];
|
|
499
|
+
configJson.history.push({
|
|
500
|
+
created: new Date().toISOString(),
|
|
501
|
+
created_by: "action-llama assembleImageDirect",
|
|
502
|
+
});
|
|
503
|
+
const newConfigBytes = Buffer.from(JSON.stringify(configJson));
|
|
504
|
+
const newConfigDigest = `sha256:${createHash("sha256").update(newConfigBytes).digest("hex")}`;
|
|
505
|
+
// Upload layer blob
|
|
506
|
+
opts.onProgress?.("Uploading layer");
|
|
507
|
+
await this.uploadBlob(repoName, layerDigest, compressedLayer);
|
|
508
|
+
// Upload new config blob
|
|
509
|
+
await this.uploadBlob(repoName, newConfigDigest, newConfigBytes);
|
|
510
|
+
// Build and push new manifest
|
|
511
|
+
const newManifest = {
|
|
512
|
+
schemaVersion: manifest.schemaVersion,
|
|
513
|
+
mediaType: manifest.mediaType,
|
|
514
|
+
config: {
|
|
515
|
+
mediaType: manifest.config.mediaType,
|
|
516
|
+
size: newConfigBytes.length,
|
|
517
|
+
digest: newConfigDigest,
|
|
518
|
+
},
|
|
519
|
+
layers: [
|
|
520
|
+
...manifest.layers,
|
|
521
|
+
{
|
|
522
|
+
mediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
|
523
|
+
size: compressedLayer.length,
|
|
524
|
+
digest: layerDigest,
|
|
525
|
+
},
|
|
526
|
+
],
|
|
527
|
+
};
|
|
528
|
+
opts.onProgress?.("Pushing image manifest");
|
|
529
|
+
await this.ecrClient.send(new PutImageCommand({
|
|
530
|
+
repositoryName: repoName,
|
|
531
|
+
imageManifest: JSON.stringify(newManifest),
|
|
532
|
+
imageTag: hashTag,
|
|
533
|
+
}));
|
|
534
|
+
return remoteTag;
|
|
535
|
+
}
|
|
536
|
+
async uploadBlob(repoName, digest, data) {
|
|
537
|
+
const initRes = await this.ecrClient.send(new InitiateLayerUploadCommand({
|
|
538
|
+
repositoryName: repoName,
|
|
539
|
+
}));
|
|
540
|
+
await this.ecrClient.send(new UploadLayerPartCommand({
|
|
541
|
+
repositoryName: repoName,
|
|
542
|
+
uploadId: initRes.uploadId,
|
|
543
|
+
partFirstByte: 0,
|
|
544
|
+
partLastByte: data.length - 1,
|
|
545
|
+
layerPartBlob: new Uint8Array(data),
|
|
546
|
+
}));
|
|
547
|
+
await this.ecrClient.send(new CompleteLayerUploadCommand({
|
|
548
|
+
repositoryName: repoName,
|
|
549
|
+
uploadId: initRes.uploadId,
|
|
550
|
+
layerDigests: [digest],
|
|
551
|
+
}));
|
|
552
|
+
}
|
|
553
|
+
// --- Batched CodeBuild (multiple images in one job) ---
|
|
554
|
+
async buildMultipleImagesCodeBuild(builds, onProgress) {
|
|
555
|
+
if (builds.length === 0)
|
|
556
|
+
return [];
|
|
557
|
+
if (builds.length === 1)
|
|
558
|
+
return [await this.buildImageCodeBuild(builds[0], onProgress)];
|
|
559
|
+
const { join, isAbsolute, dirname: dirnameFn } = await import("path");
|
|
560
|
+
const { readFileSync, writeFileSync, mkdirSync, copyFileSync, cpSync, existsSync, rmSync, readdirSync } = await import("fs");
|
|
561
|
+
const { createHash, randomUUID } = await import("crypto");
|
|
562
|
+
const { tmpdir } = await import("os");
|
|
563
|
+
const { execFileSync } = await import("child_process");
|
|
564
|
+
onProgress?.(`Preparing ${builds.length} build contexts`);
|
|
565
|
+
const combinedCtx = join(tmpdir(), `al-multi-ctx-${randomUUID().slice(0, 8)}`);
|
|
566
|
+
mkdirSync(combinedCtx, { recursive: true });
|
|
567
|
+
// Per-build info: compute hash, check cache, prepare context
|
|
568
|
+
const buildInfos = [];
|
|
569
|
+
for (let i = 0; i < builds.length; i++) {
|
|
570
|
+
const opts = builds[i];
|
|
571
|
+
const subdir = `build-${i}`;
|
|
572
|
+
const subPath = join(combinedCtx, subdir);
|
|
573
|
+
mkdirSync(subPath, { recursive: true });
|
|
574
|
+
const hasExtraFiles = opts.extraFiles && Object.keys(opts.extraFiles).length > 0;
|
|
575
|
+
// Prepare Dockerfile
|
|
576
|
+
let dockerfileContent;
|
|
577
|
+
if (opts.dockerfileContent) {
|
|
578
|
+
dockerfileContent = opts.dockerfileContent;
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
const resolvedDockerfile = isAbsolute(opts.dockerfile)
|
|
582
|
+
? opts.dockerfile
|
|
583
|
+
: join(opts.contextDir, opts.dockerfile);
|
|
584
|
+
dockerfileContent = readFileSync(resolvedDockerfile, "utf-8");
|
|
585
|
+
if (opts.baseImage) {
|
|
586
|
+
dockerfileContent = dockerfileContent.replace(/^FROM\s+\S+/m, `FROM ${opts.baseImage}`);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
if (hasExtraFiles && !dockerfileContent.includes("COPY static/ /app/static/")) {
|
|
590
|
+
const copyLine = "COPY static/ /app/static/";
|
|
591
|
+
const userIdx = dockerfileContent.indexOf("\nUSER ");
|
|
592
|
+
if (userIdx !== -1) {
|
|
593
|
+
dockerfileContent = dockerfileContent.slice(0, userIdx) + "\n" + copyLine + dockerfileContent.slice(userIdx);
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
dockerfileContent += "\n" + copyLine + "\n";
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
writeFileSync(join(subPath, "Dockerfile"), dockerfileContent);
|
|
600
|
+
if (!opts.dockerfileContent) {
|
|
601
|
+
copyFileSync(join(opts.contextDir, "package.json"), join(subPath, "package.json"));
|
|
602
|
+
cpSync(join(opts.contextDir, "dist"), join(subPath, "dist"), { recursive: true });
|
|
603
|
+
const binSrc = join(opts.contextDir, "docker", "bin");
|
|
604
|
+
if (existsSync(binSrc)) {
|
|
605
|
+
cpSync(binSrc, join(subPath, "docker", "bin"), { recursive: true });
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
if (hasExtraFiles) {
|
|
609
|
+
const staticDir = join(subPath, "static");
|
|
610
|
+
mkdirSync(staticDir, { recursive: true });
|
|
611
|
+
for (const [filename, content] of Object.entries(opts.extraFiles)) {
|
|
612
|
+
const filePath = join(staticDir, filename);
|
|
613
|
+
mkdirSync(dirnameFn(filePath), { recursive: true });
|
|
614
|
+
writeFileSync(filePath, content);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
// Compute content hash (same algorithm as buildImageCodeBuild)
|
|
618
|
+
const hash = createHash("sha256");
|
|
619
|
+
const hashFile = (p) => { hash.update(p); hash.update(readFileSync(join(subPath, p))); };
|
|
620
|
+
const hashDir = (dir) => {
|
|
621
|
+
const entries = readdirSync(join(subPath, dir), { withFileTypes: true })
|
|
622
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
623
|
+
for (const entry of entries) {
|
|
624
|
+
const p = join(dir, entry.name);
|
|
625
|
+
if (entry.isDirectory())
|
|
626
|
+
hashDir(p);
|
|
627
|
+
else
|
|
628
|
+
hashFile(p);
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
hash.update("Dockerfile");
|
|
632
|
+
hash.update(readFileSync(join(subPath, "Dockerfile")));
|
|
633
|
+
if (!opts.dockerfileContent) {
|
|
634
|
+
hashFile("package.json");
|
|
635
|
+
hashDir("dist");
|
|
636
|
+
if (existsSync(join(subPath, "docker")))
|
|
637
|
+
hashDir("docker");
|
|
638
|
+
}
|
|
639
|
+
if (hasExtraFiles)
|
|
640
|
+
hashDir("static");
|
|
641
|
+
const contentHash = hash.digest("hex").slice(0, 16);
|
|
642
|
+
const nameTag = opts.tag.replace(":", "-");
|
|
643
|
+
const hashTag = `${nameTag}-${contentHash}`;
|
|
644
|
+
const remoteTag = `${this.config.ecrRepository}:${hashTag}`;
|
|
645
|
+
buildInfos.push({ idx: i, remoteTag, hashTag, nameTag, cached: false, subdir });
|
|
646
|
+
}
|
|
647
|
+
// Check cache for all builds in parallel
|
|
648
|
+
const repoName = this.config.ecrRepository.split("/").pop();
|
|
649
|
+
const cacheResults = await Promise.all(buildInfos.map(info => this.ecrImageExists(repoName, info.hashTag, onProgress)));
|
|
650
|
+
for (let i = 0; i < buildInfos.length; i++) {
|
|
651
|
+
buildInfos[i].cached = cacheResults[i];
|
|
652
|
+
}
|
|
653
|
+
const uncached = buildInfos.filter(b => !b.cached);
|
|
654
|
+
if (uncached.length === 0) {
|
|
655
|
+
onProgress?.("All images unchanged — reusing cached builds");
|
|
656
|
+
try {
|
|
657
|
+
rmSync(combinedCtx, { recursive: true });
|
|
658
|
+
}
|
|
659
|
+
catch { }
|
|
660
|
+
return buildInfos.map(b => b.remoteTag);
|
|
661
|
+
}
|
|
662
|
+
onProgress?.(`Cache: ${buildInfos.length - uncached.length} hit, ${uncached.length} miss — building`);
|
|
663
|
+
// Tar only uncached build subdirs
|
|
664
|
+
const tarEntries = uncached.map(b => b.subdir);
|
|
665
|
+
const tarPath = join(tmpdir(), `al-multi-${randomUUID().slice(0, 8)}.tar.gz`);
|
|
666
|
+
try {
|
|
667
|
+
execFileSync("tar", ["czf", tarPath, "-C", combinedCtx, ...tarEntries], {
|
|
668
|
+
timeout: 120_000,
|
|
669
|
+
env: { ...process.env, COPYFILE_DISABLE: "1" },
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
finally {
|
|
673
|
+
try {
|
|
674
|
+
rmSync(combinedCtx, { recursive: true });
|
|
675
|
+
}
|
|
676
|
+
catch { }
|
|
677
|
+
}
|
|
678
|
+
onProgress?.("Uploading combined build context to S3");
|
|
679
|
+
const bucket = await this.ensureBuildBucket();
|
|
680
|
+
const s3Key = `${AWS_CONSTANTS.BUILD_S3_PREFIX}/multi-${Date.now()}.tar.gz`;
|
|
681
|
+
await this.s3Client.send(new PutObjectCommand({
|
|
682
|
+
Bucket: bucket,
|
|
683
|
+
Key: s3Key,
|
|
684
|
+
Body: createReadStream(tarPath),
|
|
685
|
+
}));
|
|
686
|
+
try {
|
|
687
|
+
rmSync(tarPath);
|
|
688
|
+
}
|
|
689
|
+
catch { }
|
|
690
|
+
const projectName = AWS_CONSTANTS.CODEBUILD_PROJECT;
|
|
691
|
+
await this.ensureCodeBuildProject(projectName, bucket);
|
|
692
|
+
const registry = this.config.ecrRepository.split("/")[0];
|
|
693
|
+
// Generate multi-image buildspec
|
|
694
|
+
const buildCommands = uncached.flatMap((b) => {
|
|
695
|
+
const cacheTag = `${this.config.ecrRepository}:${b.nameTag}-cache`;
|
|
696
|
+
return [
|
|
697
|
+
`echo "Building ${b.subdir}: ${b.remoteTag}"`,
|
|
698
|
+
`docker pull ${cacheTag} || true`,
|
|
699
|
+
`docker build --cache-from ${cacheTag} -t ${b.remoteTag} -f ${b.subdir}/Dockerfile ${b.subdir}`,
|
|
700
|
+
`docker push ${b.remoteTag}`,
|
|
701
|
+
`docker tag ${b.remoteTag} ${cacheTag}`,
|
|
702
|
+
`docker push ${cacheTag}`,
|
|
703
|
+
];
|
|
704
|
+
});
|
|
705
|
+
const buildspec = [
|
|
706
|
+
"version: 0.2",
|
|
707
|
+
"phases:",
|
|
708
|
+
" pre_build:",
|
|
709
|
+
" commands:",
|
|
710
|
+
" - if ls *.tar.gz 1>/dev/null 2>&1; then tar xzf *.tar.gz && rm -f *.tar.gz; fi",
|
|
711
|
+
` - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin ${registry}`,
|
|
712
|
+
" build:",
|
|
713
|
+
" commands:",
|
|
714
|
+
...buildCommands.map(cmd => ` - ${cmd}`),
|
|
715
|
+
].join("\n");
|
|
716
|
+
const buildRes = await this.cbClient.send(new StartBuildCommand({
|
|
717
|
+
projectName,
|
|
718
|
+
sourceTypeOverride: "S3",
|
|
719
|
+
sourceLocationOverride: `${bucket}/${s3Key}`,
|
|
720
|
+
buildspecOverride: buildspec,
|
|
721
|
+
environmentVariablesOverride: [
|
|
722
|
+
{ name: "ECR_REGISTRY", value: registry },
|
|
723
|
+
],
|
|
724
|
+
}));
|
|
725
|
+
const buildId = buildRes.build?.id;
|
|
726
|
+
if (!buildId)
|
|
727
|
+
throw new Error("CodeBuild did not return a build ID");
|
|
728
|
+
onProgress?.(`Queued — building ${uncached.length} images in CodeBuild`);
|
|
729
|
+
while (true) {
|
|
730
|
+
await sleep(10_000);
|
|
731
|
+
const status = await this.cbClient.send(new BatchGetBuildsCommand({ ids: [buildId] }));
|
|
732
|
+
const build = status.builds?.[0];
|
|
733
|
+
if (!build)
|
|
734
|
+
throw new Error(`CodeBuild build ${buildId} not found`);
|
|
735
|
+
if (build.currentPhase) {
|
|
736
|
+
const phaseLabels = {
|
|
737
|
+
SUBMITTED: "Submitted",
|
|
738
|
+
QUEUED: "Queued",
|
|
739
|
+
PROVISIONING: "Provisioning build environment",
|
|
740
|
+
DOWNLOAD_SOURCE: "Downloading source",
|
|
741
|
+
INSTALL: "Installing dependencies",
|
|
742
|
+
PRE_BUILD: "Logging in to ECR",
|
|
743
|
+
BUILD: `Building ${uncached.length} images`,
|
|
744
|
+
POST_BUILD: "Finalizing",
|
|
745
|
+
UPLOAD_ARTIFACTS: "Uploading artifacts",
|
|
746
|
+
FINALIZING: "Finalizing",
|
|
747
|
+
COMPLETED: "Complete",
|
|
748
|
+
};
|
|
749
|
+
const label = phaseLabels[build.currentPhase] || build.currentPhase;
|
|
750
|
+
onProgress?.(label);
|
|
751
|
+
}
|
|
752
|
+
if (build.buildComplete) {
|
|
753
|
+
if (build.buildStatus !== "SUCCEEDED") {
|
|
754
|
+
const logs = build.logs?.deepLink || "";
|
|
755
|
+
throw new Error(`CodeBuild batch build failed (${build.buildStatus}). Logs: ${logs}`);
|
|
756
|
+
}
|
|
757
|
+
return buildInfos.map(b => b.remoteTag);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
399
761
|
// --- CloudWatch Logs ---
|
|
400
762
|
logGroupsCreated = new Set();
|
|
401
763
|
async ensureLogGroup(logGroupName) {
|
|
@@ -424,28 +786,48 @@ export class AwsSharedUtils {
|
|
|
424
786
|
}
|
|
425
787
|
/**
|
|
426
788
|
* Scan log events in a time window using FilterLogEvents.
|
|
427
|
-
* Returns events in ascending order
|
|
428
|
-
*
|
|
429
|
-
* through all matching events rather than capping at `limit` oldest entries.
|
|
789
|
+
* Returns events in ascending order. Uses time-bounded queries and limits
|
|
790
|
+
* to improve performance by starting with a narrower time window.
|
|
430
791
|
*/
|
|
431
792
|
async filterLogEvents(logGroupName, logStreamPrefix, limit, startTime) {
|
|
432
|
-
|
|
793
|
+
// Start with a narrow time window (last 1 hour) for better performance
|
|
794
|
+
let queryStartTime = startTime ?? (Date.now() - 3600_000); // last 1 hour
|
|
795
|
+
const fallbackStartTime = startTime ?? (Date.now() - 24 * 3600_000); // last 24 hours
|
|
433
796
|
const allEvents = [];
|
|
434
797
|
let nextToken;
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
798
|
+
const MAX_PAGES = 10;
|
|
799
|
+
let pageCount = 0;
|
|
800
|
+
// Try narrow window first, expand if needed
|
|
801
|
+
for (const currentStartTime of [queryStartTime, fallbackStartTime]) {
|
|
802
|
+
if (allEvents.length >= limit)
|
|
803
|
+
break;
|
|
804
|
+
if (currentStartTime === fallbackStartTime && queryStartTime >= fallbackStartTime)
|
|
805
|
+
break;
|
|
806
|
+
nextToken = undefined;
|
|
807
|
+
pageCount = 0;
|
|
808
|
+
do {
|
|
809
|
+
const res = await this.logsClient.send(new FilterLogEventsCommand({
|
|
810
|
+
logGroupName,
|
|
811
|
+
...(logStreamPrefix ? { logStreamNamePrefix: logStreamPrefix } : {}),
|
|
812
|
+
startTime: currentStartTime,
|
|
813
|
+
...(nextToken ? { nextToken } : {}),
|
|
814
|
+
}));
|
|
815
|
+
for (const e of res.events ?? []) {
|
|
816
|
+
const msg = e.message?.trimEnd();
|
|
817
|
+
if (msg) {
|
|
818
|
+
allEvents.push(msg);
|
|
819
|
+
// Early exit if we have enough events
|
|
820
|
+
if (allEvents.length >= limit * 3)
|
|
821
|
+
break;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
nextToken = res.nextToken;
|
|
825
|
+
pageCount++;
|
|
826
|
+
} while (nextToken && pageCount < MAX_PAGES && allEvents.length < limit * 3);
|
|
827
|
+
// If we got enough results, no need to try the wider window
|
|
828
|
+
if (allEvents.length >= limit)
|
|
829
|
+
break;
|
|
830
|
+
}
|
|
449
831
|
return allEvents.slice(-limit);
|
|
450
832
|
}
|
|
451
833
|
/**
|