From 6e236d846c2deed035546dea2c01e5a2bcf0a9ed Mon Sep 17 00:00:00 2001 From: Alon Gubkin Date: Thu, 11 Jun 2026 21:09:33 +0300 Subject: [PATCH 1/4] fix: rebase prebuilt artifact paths across platforms --- Cargo.lock | 66 ++++++++++---------- crates/alien-cli/src/commands/release.rs | 76 +++++++++++++++--------- 2 files changed, 81 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8213c816..2f77cc56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,7 +85,7 @@ dependencies = [ [[package]] name = "alien-agent" -version = "1.6.0" +version = "1.7.1" dependencies = [ "aegis", "alien-client-config", @@ -120,7 +120,7 @@ dependencies = [ [[package]] name = "alien-aws-clients" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-aws-clients", "alien-client-core", @@ -162,7 +162,7 @@ dependencies = [ [[package]] name = "alien-azure-clients" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-client-core", "alien-core", @@ -205,7 +205,7 @@ dependencies = [ [[package]] name = "alien-bindings" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-aws-clients", "alien-azure-clients", @@ -255,7 +255,7 @@ dependencies = [ [[package]] name = "alien-build" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-build", "alien-core", @@ -289,7 +289,7 @@ dependencies = [ [[package]] name = "alien-cli" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-bindings", "alien-build", @@ -356,7 +356,7 @@ dependencies = [ [[package]] name = "alien-cli-common" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-core", "alien-deployment", @@ -370,7 +370,7 @@ dependencies = [ [[package]] name = "alien-client-config" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-aws-clients", "alien-azure-clients", @@ -388,7 +388,7 @@ dependencies = [ [[package]] name = "alien-client-core" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-error", "anyhow", @@ -407,7 +407,7 @@ dependencies = [ [[package]] name = "alien-cloudformation" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-core", "alien-error", @@ -422,7 +422,7 @@ dependencies = [ [[package]] name = "alien-commands" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-aws-clients", "alien-azure-clients", @@ -456,7 +456,7 @@ dependencies = [ [[package]] name = "alien-commands-client" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-core", "base64 0.22.1", @@ -471,7 +471,7 @@ dependencies = [ [[package]] name = "alien-core" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-error", "alien-macros", @@ -501,7 +501,7 @@ dependencies = [ [[package]] name = "alien-deploy-cli" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-agent", "alien-cli-common", @@ -539,7 +539,7 @@ dependencies = [ [[package]] name = "alien-deployment" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-aws-clients", "alien-azure-clients", @@ -569,7 +569,7 @@ dependencies = [ [[package]] name = "alien-error" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-error-derive", "anyhow", @@ -582,7 +582,7 @@ dependencies = [ [[package]] name = "alien-error-derive" -version = "1.6.0" +version = "1.7.1" dependencies = [ "proc-macro2", "quote", @@ -592,7 +592,7 @@ dependencies = [ [[package]] name = "alien-gcp-clients" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-client-core", "alien-core", @@ -625,7 +625,7 @@ dependencies = [ [[package]] name = "alien-helm" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-core", "alien-error", @@ -639,7 +639,7 @@ dependencies = [ [[package]] name = "alien-infra" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-aws-clients", "alien-azure-clients", @@ -699,7 +699,7 @@ dependencies = [ [[package]] name = "alien-k8s-clients" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-client-core", "alien-core", @@ -728,7 +728,7 @@ dependencies = [ [[package]] name = "alien-local" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-bindings", "alien-build", @@ -765,7 +765,7 @@ dependencies = [ [[package]] name = "alien-macros" -version = "1.6.0" +version = "1.7.1" dependencies = [ "proc-macro2", "quote", @@ -774,7 +774,7 @@ dependencies = [ [[package]] name = "alien-manager" -version = "1.6.0" +version = "1.7.1" dependencies = [ "aegis", "alien-bindings", @@ -832,7 +832,7 @@ dependencies = [ [[package]] name = "alien-manager-api" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-error", "chrono", @@ -849,7 +849,7 @@ dependencies = [ [[package]] name = "alien-permissions" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-core", "alien-error", @@ -868,7 +868,7 @@ dependencies = [ [[package]] name = "alien-platform-api" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-error", "chrono", @@ -885,7 +885,7 @@ dependencies = [ [[package]] name = "alien-preflights" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-core", "alien-error", @@ -902,7 +902,7 @@ dependencies = [ [[package]] name = "alien-runtime" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-bindings", "alien-commands", @@ -959,14 +959,14 @@ dependencies = [ [[package]] name = "alien-sdk" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-bindings", ] [[package]] name = "alien-terraform" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-core", "alien-error", @@ -981,7 +981,7 @@ dependencies = [ [[package]] name = "alien-test" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-aws-clients", "alien-azure-clients", @@ -1027,7 +1027,7 @@ dependencies = [ [[package]] name = "alien-test-app" -version = "1.6.0" +version = "1.7.1" dependencies = [ "alien-bindings", "alien-error", diff --git a/crates/alien-cli/src/commands/release.rs b/crates/alien-cli/src/commands/release.rs index 7febef78..e3b4bd94 100644 --- a/crates/alien-cli/src/commands/release.rs +++ b/crates/alien-cli/src/commands/release.rs @@ -404,7 +404,7 @@ async fn release_task_core( // Local platform pushes to a cloud registry — the alien-agent pulls from it. let pushed_stack = if platform != Platform::Test { if args.prebuilt { - rebase_prebuilt_stack_image_paths(&mut built_stack, &output_dir, platform_str)?; + rebase_prebuilt_stack_image_paths(&mut built_stack, &output_dir)?; } // Load push cache — maps content-hashed dir names to previously pushed URIs @@ -1147,18 +1147,15 @@ fn parse_kubernetes_base_platform( /// `alien build` writes local artifact directories into stack.json. CI may build /// those artifacts in one checkout and copy `.alien/build` into another image, /// so a prebuilt release must resolve stale `.alien/build/{platform}/{artifact}` -/// paths before pushing. -fn rebase_prebuilt_stack_image_paths( - stack: &mut Stack, - output_dir: &Path, - platform: &str, -) -> Result<()> { +/// paths before pushing. The artifact path may point at a different platform +/// than the release currently being pushed when platforms share a built image. +fn rebase_prebuilt_stack_image_paths(stack: &mut Stack, output_dir: &Path) -> Result<()> { for (_resource_id, resource_entry) in stack.resources_mut() { if let Some(func) = resource_entry.config.downcast_ref::() { match &func.code { WorkerCode::Image { image } => { if let Some(rebased) = - rebase_prebuilt_image_path("worker", &func.id, image, output_dir, platform)? + rebase_prebuilt_image_path("worker", &func.id, image, output_dir)? { let mut updated = func.clone(); updated.code = WorkerCode::Image { image: rebased }; @@ -1172,13 +1169,9 @@ fn rebase_prebuilt_stack_image_paths( } else if let Some(container) = resource_entry.config.downcast_ref::() { match &container.code { ContainerCode::Image { image } => { - if let Some(rebased) = rebase_prebuilt_image_path( - "container", - &container.id, - image, - output_dir, - platform, - )? { + if let Some(rebased) = + rebase_prebuilt_image_path("container", &container.id, image, output_dir)? + { let mut updated = container.clone(); updated.code = ContainerCode::Image { image: rebased }; resource_entry.config = alien_core::Resource::new(updated); @@ -1191,9 +1184,9 @@ fn rebase_prebuilt_stack_image_paths( } else if let Some(daemon) = resource_entry.config.downcast_ref::() { match &daemon.code { DaemonCode::Image { image } => { - if let Some(rebased) = rebase_prebuilt_image_path( - "daemon", &daemon.id, image, output_dir, platform, - )? { + if let Some(rebased) = + rebase_prebuilt_image_path("daemon", &daemon.id, image, output_dir)? + { let mut updated = daemon.clone(); updated.code = DaemonCode::Image { image: rebased }; resource_entry.config = alien_core::Resource::new(updated); @@ -1213,15 +1206,18 @@ fn rebase_prebuilt_image_path( resource_id: &str, image: &str, output_dir: &Path, - platform: &str, ) -> Result> { let image_path = PathBuf::from(image); if image_path.exists() { return Ok(None); } - if let Some(artifact_dir) = artifact_dir_from_build_path(&image_path, platform) { - let rebased_path = output_dir.join("build").join(platform).join(&artifact_dir); + if let Some((artifact_platform, artifact_dir)) = artifact_location_from_build_path(&image_path) + { + let rebased_path = output_dir + .join("build") + .join(&artifact_platform) + .join(&artifact_dir); if rebased_path.exists() && rebased_path.is_dir() { info!( "Rebased prebuilt {} '{}' image artifact from '{}' to '{}'", @@ -1260,15 +1256,15 @@ fn rebase_prebuilt_image_path( Ok(None) } -fn artifact_dir_from_build_path(path: &Path, platform: &str) -> Option { +fn artifact_location_from_build_path(path: &Path) -> Option<(String, String)> { let components = path .components() .filter_map(|component| component.as_os_str().to_str()) .collect::>(); components.windows(4).find_map(|window| { - if window[0] == ".alien" && window[1] == "build" && window[2] == platform { - Some(window[3].to_string()) + if window[0] == ".alien" && window[1] == "build" { + Some((window[2].to_string(), window[3].to_string())) } else { None } @@ -1597,8 +1593,7 @@ mod tests { let artifact_dir = output_dir.join("build").join("gcp").join("writer-12345678"); std::fs::create_dir_all(&artifact_dir).unwrap(); - let original_image = - "/home/runner/work/platform/platform/alien/examples/byoc-database/.alien/build/gcp/writer-12345678"; + let original_image = "/tmp/original-checkout/.alien/build/gcp/writer-12345678"; let mut stack = Stack::new("demo".to_string()) .add( test_container("writer", original_image.to_string()), @@ -1606,7 +1601,32 @@ mod tests { ) .build(); - rebase_prebuilt_stack_image_paths(&mut stack, &output_dir, "gcp").unwrap(); + rebase_prebuilt_stack_image_paths(&mut stack, &output_dir).unwrap(); + + let (_, entry) = stack.resources().next().unwrap(); + let container = entry.config.downcast_ref::().unwrap(); + assert_eq!( + container_image(container), + artifact_dir.to_string_lossy().as_ref() + ); + } + + #[test] + fn rebase_prebuilt_stack_image_paths_rewrites_cross_platform_artifact_path() { + let temp = tempfile::tempdir().unwrap(); + let output_dir = temp.path().join(".alien"); + let artifact_dir = output_dir.join("build").join("aws").join("web-12345678"); + std::fs::create_dir_all(&artifact_dir).unwrap(); + + let original_image = "/tmp/original-checkout/.alien/build/aws/web-12345678"; + let mut stack = Stack::new("demo".to_string()) + .add( + test_container("web", original_image.to_string()), + alien_core::ResourceLifecycle::Live, + ) + .build(); + + rebase_prebuilt_stack_image_paths(&mut stack, &output_dir).unwrap(); let (_, entry) = stack.resources().next().unwrap(); let container = entry.config.downcast_ref::().unwrap(); @@ -1628,7 +1648,7 @@ mod tests { ) .build(); - rebase_prebuilt_stack_image_paths(&mut stack, &output_dir, "gcp").unwrap(); + rebase_prebuilt_stack_image_paths(&mut stack, &output_dir).unwrap(); let (_, entry) = stack.resources().next().unwrap(); let container = entry.config.downcast_ref::().unwrap(); From 9ec5791f018c2e369fa8077aeeee222361fb9e30 Mon Sep 17 00:00:00 2001 From: Alon Gubkin Date: Thu, 11 Jun 2026 21:13:32 +0300 Subject: [PATCH 2/4] chore: rerun ci after pr title fix From 2a058980aebb71e24180d92669c700d03036790d Mon Sep 17 00:00:00 2001 From: Alon Gubkin Date: Thu, 11 Jun 2026 21:16:16 +0300 Subject: [PATCH 3/4] chore: format files checked by ci --- .../compute-cluster/management.jsonc | 16 ++++------------ .../permission-sets/container/provision.jsonc | 5 +---- packages/core/src/__tests__/error.test.ts | 2 +- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/crates/alien-permissions/permission-sets/compute-cluster/management.jsonc b/crates/alien-permissions/permission-sets/compute-cluster/management.jsonc index c789a0fd..d2938d56 100644 --- a/crates/alien-permissions/permission-sets/compute-cluster/management.jsonc +++ b/crates/alien-permissions/permission-sets/compute-cluster/management.jsonc @@ -65,9 +65,7 @@ }, "binding": { "stack": { - "resources": [ - "arn:aws:ec2:${awsRegion}:${awsAccountId}:launch-template/*" - ], + "resources": ["arn:aws:ec2:${awsRegion}:${awsAccountId}:launch-template/*"], "condition": { "StringEquals": { "aws:ResourceTag/${stackTag}": "${stackPrefix}", @@ -76,9 +74,7 @@ } }, "resource": { - "resources": [ - "arn:aws:ec2:${awsRegion}:${awsAccountId}:launch-template/*" - ], + "resources": ["arn:aws:ec2:${awsRegion}:${awsAccountId}:launch-template/*"], "condition": { "StringEquals": { "aws:ResourceTag/${stackTag}": "${stackPrefix}", @@ -98,9 +94,7 @@ }, "binding": { "stack": { - "resources": [ - "arn:aws:ec2:${awsRegion}:${awsAccountId}:security-group/*" - ], + "resources": ["arn:aws:ec2:${awsRegion}:${awsAccountId}:security-group/*"], "condition": { "StringEquals": { "aws:ResourceTag/${stackTag}": "${stackPrefix}", @@ -110,9 +104,7 @@ } }, "resource": { - "resources": [ - "arn:aws:ec2:${awsRegion}:${awsAccountId}:security-group/*" - ], + "resources": ["arn:aws:ec2:${awsRegion}:${awsAccountId}:security-group/*"], "condition": { "StringEquals": { "aws:ResourceTag/${stackTag}": "${stackPrefix}", diff --git a/crates/alien-permissions/permission-sets/container/provision.jsonc b/crates/alien-permissions/permission-sets/container/provision.jsonc index bea1128a..474a7df3 100644 --- a/crates/alien-permissions/permission-sets/container/provision.jsonc +++ b/crates/alien-permissions/permission-sets/container/provision.jsonc @@ -248,10 +248,7 @@ { "label": "Manage setup compute security group ingress", "grant": { - "actions": [ - "ec2:AuthorizeSecurityGroupIngress", - "ec2:RevokeSecurityGroupIngress" - ] + "actions": ["ec2:AuthorizeSecurityGroupIngress", "ec2:RevokeSecurityGroupIngress"] }, "binding": { "stack": { diff --git a/packages/core/src/__tests__/error.test.ts b/packages/core/src/__tests__/error.test.ts index 5680c3d9..a0e73b2f 100644 --- a/packages/core/src/__tests__/error.test.ts +++ b/packages/core/src/__tests__/error.test.ts @@ -584,7 +584,7 @@ describe("External API Sanitization", async () => { expect(external.code).toBe("AUTH_FAILED") expect((external.source as AlienErrorOptions)?.code).toBe("DATABASE_CONNECTION_FAILED") - expect(((external.source as AlienErrorOptions)?.source as AlienErrorOptions)).toEqual({ + expect((external.source as AlienErrorOptions)?.source as AlienErrorOptions).toEqual({ code: "GENERIC_ERROR", message: "Internal server error", retryable: false, From 5cfb463a779b82e67a7500954f42a292a6fb769a Mon Sep 17 00:00:00 2001 From: Alon Gubkin Date: Fri, 12 Jun 2026 22:01:14 +0300 Subject: [PATCH 4/4] ci: fix fast and skipped e2e cleanup --- .github/workflows/ci-fast.yml | 3 +++ .github/workflows/e2e-cloud.yml | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-fast.yml b/.github/workflows/ci-fast.yml index 14f09e60..dc20c724 100644 --- a/.github/workflows/ci-fast.yml +++ b/.github/workflows/ci-fast.yml @@ -73,6 +73,9 @@ jobs: - name: Install protoc run: sudo apt-get update && sudo apt-get install -y protobuf-compiler + - name: Install CloudFormation linter + run: pipx install cfn-lint + - name: Install zig (needed by cargo-zigbuild for example builds) run: pip3 install ziglang diff --git a/.github/workflows/e2e-cloud.yml b/.github/workflows/e2e-cloud.yml index 446e6069..cdef175f 100644 --- a/.github/workflows/e2e-cloud.yml +++ b/.github/workflows/e2e-cloud.yml @@ -192,7 +192,7 @@ jobs: echo "build_images=true" >> $GITHUB_OUTPUT echo "build_base_image=true" >> $GITHUB_OUTPUT echo "build_agent_image=true" >> $GITHUB_OUTPUT - echo "skip_cleanup=false" >> $GITHUB_OUTPUT + echo "skip_cleanup=true" >> $GITHUB_OUTPUT echo "test_filter=" >> $GITHUB_OUTPUT echo "network_mode=none" >> $GITHUB_OUTPUT exit 0 @@ -1314,7 +1314,10 @@ jobs: cleanup: needs: [compute-matrix, setup, push-test, cloudformation-test, terraform-test, local-test] - if: always() && needs.compute-matrix.outputs.skip_cleanup != 'true' + if: | + always() && + needs.compute-matrix.outputs.skip_cleanup != 'true' && + needs.setup.result == 'success' runs-on: depot-ubuntu-24.04-arm timeout-minutes: 30 steps: