1+ use std:: io:: Read ;
2+
13use camino_tempfile:: NamedUtf8TempFile as NamedTempFile ;
24use indoc:: { formatdoc, indoc} ;
35use predicates:: { prelude:: PredicateBooleanExt , str:: contains} ;
@@ -25,7 +27,7 @@ fn build_adapter_script_single() {
2527 build:
2628 steps:
2729 - type: script
28- command: sh -c ' cp {path} "$ICP_WASM_OUTPUT_PATH"'
30+ command: cp {path} "$ICP_WASM_OUTPUT_PATH"
2931 "# } ;
3032
3133 write_string (
@@ -62,7 +64,7 @@ fn build_adapter_script_multiple() {
6264 - type: script
6365 command: echo "before"
6466 - type: script
65- command: sh -c ' cp {path} "$ICP_WASM_OUTPUT_PATH"'
67+ command: cp {path} "$ICP_WASM_OUTPUT_PATH"
6668 - type: script
6769 command: echo "after"
6870 "# } ;
@@ -99,14 +101,14 @@ fn build_adapter_display_failing_build_output() {
99101 - type: script
100102 command: echo "success 2"
101103 - type: script
102- command: sh -c ' for i in $(seq 1 5); do echo "failing build step $i"; done; exit 1'
104+ command: for i in $(seq 1 5); do echo "failing build step $i"; done; exit 1
103105 - name: unimportant-canister
104106 build:
105107 steps:
106108 - type: script
107109 command: echo "hide this"
108110 - type: script
109- command: sh -c ' touch "$ICP_WASM_OUTPUT_PATH"'
111+ command: touch "$ICP_WASM_OUTPUT_PATH"
110112 "# } ;
111113
112114 write_string (
@@ -125,13 +127,13 @@ fn build_adapter_display_failing_build_output() {
125127 Building: script (command: echo "success 2") 2 of 3
126128 success 2
127129
128- Building: script (command: sh -c ' for i in $(seq 1 5); do echo "failing build step $i"; done; exit 1' ) 3 of 3
130+ Building: script (command: for i in $(seq 1 5); do echo "failing build step $i"; done; exit 1) 3 of 3
129131 failing build step 1
130132 failing build step 2
131133 failing build step 3
132134 failing build step 4
133135 failing build step 5
134- Failed to build canister: command 'sh -c ' for i in $(seq 1 5); do echo "failing build step $i"; done; exit 1' ' failed with status code 1
136+ Failed to build canister: command 'for i in $(seq 1 5); do echo "failing build step $i"; done; exit 1' failed with status code 1
135137 "# } ;
136138
137139 ctx. icp ( )
@@ -205,7 +207,7 @@ fn build_adapter_display_failing_build_output_no_output() {
205207 - type: script
206208 command: echo "step 1 succeeded"
207209 - type: script
208- command: sh -c ' exit 1'
210+ command: exit 1
209211 "# } ;
210212
211213 write_string (
@@ -221,9 +223,9 @@ fn build_adapter_display_failing_build_output_no_output() {
221223 Building: script (command: echo "step 1 succeeded") 1 of 2
222224 step 1 succeeded
223225
224- Building: script (command: sh -c ' exit 1' ) 2 of 2
226+ Building: script (command: exit 1) 2 of 2
225227 <no output>
226- Failed to build canister: command 'sh -c ' exit 1' ' failed with status code 1
228+ Failed to build canister: command 'exit 1' failed with status code 1
227229 "# } ;
228230
229231 ctx. icp ( )
@@ -250,14 +252,14 @@ fn build_adapter_display_multiple_failing_canisters() {
250252 - type: script
251253 command: echo "canister-one step 1"
252254 - type: script
253- command: sh -c ' echo "canister-one error"; exit 1'
255+ command: echo "canister-one error"; exit 1
254256 - name: canister-two
255257 build:
256258 steps:
257259 - type: script
258260 command: echo "canister-two step 1"
259261 - type: script
260- command: sh -c ' echo "canister-two error"; exit 1'
262+ command: echo "canister-two error"; exit 1
261263 "# } ;
262264
263265 write_string (
@@ -273,9 +275,9 @@ fn build_adapter_display_multiple_failing_canisters() {
273275 Building: script (command: echo "canister-one step 1") 1 of 2
274276 canister-one step 1
275277
276- Building: script (command: sh -c ' echo "canister-one error"; exit 1' ) 2 of 2
278+ Building: script (command: echo "canister-one error"; exit 1) 2 of 2
277279 canister-one error
278- Failed to build canister: command 'sh -c ' echo "canister-one error"; exit 1' ' failed with status code 1
280+ Failed to build canister: command 'echo "canister-one error"; exit 1' failed with status code 1
279281 "# } ;
280282
281283 let expected_output_two = indoc ! { r#"
@@ -284,9 +286,9 @@ fn build_adapter_display_multiple_failing_canisters() {
284286 Building: script (command: echo "canister-two step 1") 1 of 2
285287 canister-two step 1
286288
287- Building: script (command: sh -c ' echo "canister-two error"; exit 1' ) 2 of 2
289+ Building: script (command: echo "canister-two error"; exit 1) 2 of 2
288290 canister-two error
289- Failed to build canister: command 'sh -c ' echo "canister-two error"; exit 1' ' failed with status code 1
291+ Failed to build canister: command 'echo "canister-two error"; exit 1' failed with status code 1
290292 "# } ;
291293
292294 ctx. icp ( )
@@ -297,3 +299,44 @@ fn build_adapter_display_multiple_failing_canisters() {
297299 . stdout ( contains ( expected_output_one) )
298300 . stdout ( contains ( expected_output_two) ) ;
299301}
302+
303+ #[ test]
304+ fn build_adapter_script_with_explicit_sh_c ( ) {
305+ let ctx = TestContext :: new ( ) ;
306+
307+ // Setup project
308+ let project_dir = ctx. create_project_dir ( "icp" ) ;
309+
310+ // Create temporary file
311+ let mut f = NamedTempFile :: new ( ) . expect ( "failed to create temporary file" ) ;
312+ let path = f. path ( ) ;
313+
314+ // Project manifest with explicit sh -c
315+ let pm = formatdoc ! { r#"
316+ canister:
317+ name: my-canister
318+ build:
319+ steps:
320+ - type: script
321+ command: sh -c 'echo "nested shell" > {path} && cp {path} "$ICP_WASM_OUTPUT_PATH"'
322+ "# } ;
323+
324+ write_string (
325+ & project_dir. join ( "icp.yaml" ) , // path
326+ & pm, // contents
327+ )
328+ . expect ( "failed to write project manifest" ) ;
329+
330+ // Invoke build
331+ ctx. icp ( )
332+ . current_dir ( project_dir)
333+ . args ( [ "build" ] )
334+ . assert ( )
335+ . success ( ) ;
336+
337+ // Verify the file contains the expected output
338+ let mut contents = String :: new ( ) ;
339+ f. read_to_string ( & mut contents)
340+ . expect ( "failed to read temporary file" ) ;
341+ assert_eq ! ( contents, "nested shell\n " ) ;
342+ }
0 commit comments