From e55c0cf45c85032ef82e485d128ee7fcaf60986c Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 18 Aug 2026 03:13:13 +0000 Subject: [PATCH 1/8] use posix separator for container manifest path --- cmd/soroban-cli/src/commands/contract/build/container.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/commands/contract/build/container.rs b/cmd/soroban-cli/src/commands/contract/build/container.rs index d90773827..56cf6e4c9 100644 --- a/cmd/soroban-cli/src/commands/contract/build/container.rs +++ b/cmd/soroban-cli/src/commands/contract/build/container.rs @@ -282,7 +282,12 @@ fn forwarded_build_args( .strip_prefix(workspace_root) .map(Path::to_path_buf) .unwrap_or(abs); - args.push(format!("--manifest-path={}", rel.display())); + let rel_posix = rel + .components() + .map(|c| c.as_os_str().to_string_lossy()) + .collect::>() + .join("/"); + args.push(format!("--manifest-path={rel_posix}")); } if cmd.profile != "release" { args.push(format!("--profile={}", cmd.profile)); From b5a02378637847017208a9287aaee3f7294855d8 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 18 Aug 2026 03:37:14 +0000 Subject: [PATCH 2/8] use path-slash for manifest path forward-slash join --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + cmd/soroban-cli/Cargo.toml | 1 + cmd/soroban-cli/src/commands/contract/build/container.rs | 8 ++------ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f3dc66cf..345636894 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3958,6 +3958,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "path-slash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" + [[package]] name = "pathdiff" version = "0.2.3" @@ -5417,6 +5423,7 @@ dependencies = [ "mockito", "num-bigint", "open", + "path-slash", "pathdiff", "phf", "predicates", diff --git a/Cargo.toml b/Cargo.toml index 71f7573e4..e1f618e05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -108,6 +108,7 @@ termcolor_output = "1.0.1" ed25519-dalek = ">= 2.1.1" http = "1.0.0" walkdir = "2.5.0" +path-slash = "0.2.1" toml_edit = "0.22.20" toml = "0.8.19" reqwest = "0.12.7" diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index 1e1d26225..038edb213 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -61,6 +61,7 @@ serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } serde-aux = { workspace = true } hex = { workspace = true } +path-slash = { workspace = true } num-bigint = "0.4" # Pinned to match the version pulled in by soroban-rpc (jsonrpsee-core) so that # downcasting RPC errors to `ErrorObjectOwned` resolves to the same type. diff --git a/cmd/soroban-cli/src/commands/contract/build/container.rs b/cmd/soroban-cli/src/commands/contract/build/container.rs index 56cf6e4c9..a3063888b 100644 --- a/cmd/soroban-cli/src/commands/contract/build/container.rs +++ b/cmd/soroban-cli/src/commands/contract/build/container.rs @@ -16,6 +16,7 @@ use std::path::{Path, PathBuf}; use std::process::Stdio; use cargo_metadata::MetadataCommand; +use path_slash::PathExt as _; use semver::Version; use crate::commands::{container::shared, global}; @@ -282,12 +283,7 @@ fn forwarded_build_args( .strip_prefix(workspace_root) .map(Path::to_path_buf) .unwrap_or(abs); - let rel_posix = rel - .components() - .map(|c| c.as_os_str().to_string_lossy()) - .collect::>() - .join("/"); - args.push(format!("--manifest-path={rel_posix}")); + args.push(format!("--manifest-path={}", rel.to_slash_lossy())); } if cmd.profile != "release" { args.push(format!("--profile={}", cmd.profile)); From ca56e8728f44d68ca0a33cf2befbfe973be2c6da Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 18 Aug 2026 03:41:45 +0000 Subject: [PATCH 3/8] add manual trigger to run windows CI job --- .github/workflows/rust.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index c99e70a64..50f9258fd 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -4,6 +4,12 @@ on: push: branches: [main, release/**] pull_request: + workflow_dispatch: + inputs: + run_windows: + description: "Also run the Windows build-and-test job" + type: boolean + default: false concurrency: group: @@ -94,7 +100,7 @@ jobs: rust-version: ${{ matrix.rust }} build-and-test-windows: - if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.head_ref, 'release/') + if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.head_ref, 'release/') || (github.event_name == 'workflow_dispatch' && inputs.run_windows) strategy: fail-fast: false matrix: From 30a3b193dab3395bfb20b28615bb0e7b0bbcfeca Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 18 Aug 2026 04:45:50 +0000 Subject: [PATCH 4/8] run windows CI job for this PR only --- .github/workflows/rust.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 50f9258fd..29e821ee4 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -4,12 +4,6 @@ on: push: branches: [main, release/**] pull_request: - workflow_dispatch: - inputs: - run_windows: - description: "Also run the Windows build-and-test job" - type: boolean - default: false concurrency: group: @@ -100,7 +94,7 @@ jobs: rust-version: ${{ matrix.rust }} build-and-test-windows: - if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.head_ref, 'release/') || (github.event_name == 'workflow_dispatch' && inputs.run_windows) + if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.head_ref, 'release/') || github.event.pull_request.number == 2688 strategy: fail-fast: false matrix: From 371219f63be0a8edee4f7b925d955a719ea48007 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 18 Aug 2026 05:21:30 +0000 Subject: [PATCH 5/8] absolutize ws() test fixture for windows drive prefix --- cmd/soroban-cli/src/commands/contract/build/container.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/commands/contract/build/container.rs b/cmd/soroban-cli/src/commands/contract/build/container.rs index a3063888b..f5d069581 100644 --- a/cmd/soroban-cli/src/commands/contract/build/container.rs +++ b/cmd/soroban-cli/src/commands/contract/build/container.rs @@ -769,7 +769,14 @@ mod tests { use crate::commands::contract::build::BuildArgs; fn ws() -> &'static Path { - Path::new("/tmp/ws") + // Routed through `std::path::absolute` (as `forwarded_build_args` itself does + // for `manifest_path`) so both sides of the `strip_prefix` in + // `forwarded_build_args` agree on drive letter/prefix on Windows. + Box::leak( + std::path::absolute(Path::new("/tmp/ws")) + .unwrap() + .into_boxed_path(), + ) } #[test] From f9abe4bd7948c321ae8dfb4b02a0590ccbb78ffb Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 18 Aug 2026 05:51:08 +0000 Subject: [PATCH 6/8] fix manifest-path arg quoting in build image test --- cmd/crates/soroban-test/tests/it/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/crates/soroban-test/tests/it/build.rs b/cmd/crates/soroban-test/tests/it/build.rs index dddf87fd8..84c42fd32 100644 --- a/cmd/crates/soroban-test/tests/it/build.rs +++ b/cmd/crates/soroban-test/tests/it/build.rs @@ -106,7 +106,7 @@ fn build_with_image_selects_package_by_manifest_path() { .arg("build") .arg("--image") .arg("docker.io/stellar/stellar-cli:latest") - .arg(manifest_path_arg(&add_path())) + .arg(format!("--manifest-path={}", add_path())) .arg("--print-commands-only") .assert() .success() From 8526a8399c8757831f92c018049aac9ee944466d Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 18 Aug 2026 08:32:32 +0000 Subject: [PATCH 7/8] avoid leaking ws() test fixture path --- .../src/commands/contract/build/container.rs | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/build/container.rs b/cmd/soroban-cli/src/commands/contract/build/container.rs index f5d069581..c6299e998 100644 --- a/cmd/soroban-cli/src/commands/contract/build/container.rs +++ b/cmd/soroban-cli/src/commands/contract/build/container.rs @@ -768,21 +768,17 @@ mod tests { use super::*; use crate::commands::contract::build::BuildArgs; - fn ws() -> &'static Path { + fn ws() -> PathBuf { // Routed through `std::path::absolute` (as `forwarded_build_args` itself does // for `manifest_path`) so both sides of the `strip_prefix` in // `forwarded_build_args` agree on drive letter/prefix on Windows. - Box::leak( - std::path::absolute(Path::new("/tmp/ws")) - .unwrap() - .into_boxed_path(), - ) + std::path::absolute(Path::new("/tmp/ws")).unwrap() } #[test] fn forwarded_build_args_defaults() { let cmd = Cmd::default(); - let args = forwarded_build_args(&cmd, ws(), None, true, true, true); + let args = forwarded_build_args(&cmd, &ws(), None, true, true, true); assert_eq!(args[..2], ["contract".to_string(), "build".to_string()]); // Default optimize=true → bare `--optimize`; no `--locked` unless asked. assert!(args.contains(&"--optimize".to_string())); @@ -796,7 +792,7 @@ mod tests { locked: true, ..Cmd::default() }; - let args = forwarded_build_args(&cmd, ws(), Some("contract-a"), true, true, true); + let args = forwarded_build_args(&cmd, &ws(), Some("contract-a"), true, true, true); assert!(args.contains(&"--locked".to_string())); assert!(args.contains(&"--package=contract-a".to_string())); } @@ -808,7 +804,7 @@ mod tests { locked: true, ..Cmd::default() }; - let args = forwarded_build_args(&cmd, ws(), None, false, true, true); + let args = forwarded_build_args(&cmd, &ws(), None, false, true, true); assert!(!args.iter().any(|a| a == "--locked")); } @@ -818,7 +814,7 @@ mod tests { // though optimize defaults to true. let cmd = Cmd::default(); assert!(cmd.build_args.optimize); - let args = forwarded_build_args(&cmd, ws(), None, true, false, false); + let args = forwarded_build_args(&cmd, &ws(), None, true, false, false); assert!(!args.iter().any(|a| a.starts_with("--optimize"))); } @@ -838,7 +834,7 @@ mod tests { }, ..Cmd::default() }; - let args = forwarded_build_args(&cmd, ws(), None, true, true, true); + let args = forwarded_build_args(&cmd, &ws(), None, true, true, true); assert!(args.contains(&"--profile=dev".to_string())); assert!(args.contains(&"--features=a,b".to_string())); assert!(args.contains(&"--all-features".to_string())); @@ -859,7 +855,7 @@ mod tests { }, ..Cmd::default() }; - let args = forwarded_build_args(&cmd, ws(), None, true, true, false); + let args = forwarded_build_args(&cmd, &ws(), None, true, true, false); assert!(!args.iter().any(|a| a.starts_with("--optimize"))); } @@ -869,7 +865,7 @@ mod tests { manifest_path: Some(PathBuf::from("/tmp/ws/contracts/add/Cargo.toml")), ..Cmd::default() }; - let args = forwarded_build_args(&cmd, ws(), None, true, true, true); + let args = forwarded_build_args(&cmd, &ws(), None, true, true, true); assert!(args.contains(&"--manifest-path=contracts/add/Cargo.toml".to_string())); } From 485617fc1c5ed6c534e0e177842165cbf52cfd50 Mon Sep 17 00:00:00 2001 From: Leigh <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 18 Aug 2026 20:30:07 +0000 Subject: [PATCH 8/8] revert temporary windows-ci trigger for this pr --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 29e821ee4..c99e70a64 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -94,7 +94,7 @@ jobs: rust-version: ${{ matrix.rust }} build-and-test-windows: - if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.head_ref, 'release/') || github.event.pull_request.number == 2688 + if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || startsWith(github.head_ref, 'release/') strategy: fail-fast: false matrix: