Skip to content

Commit 5219351

Browse files
jordanstephensnullfunclionello
authored
Normalize compose commands when generating for heroku migration (#1384)
* normalize compose commands for heroku migration to avoid the issue where the railpack container drops command arguments because the entrypoint is `bash -c`. * shell quote * update nix vendorHash * comment type Co-authored-by: Eric Liu <[email protected]> * use shellescape.QuoteCommand Co-authored-by: Lio李歐 <[email protected]> --------- Co-authored-by: Eric Liu <[email protected]> Co-authored-by: Lio李歐 <[email protected]>
1 parent e2b9be6 commit 5219351

File tree

5 files changed

+103
-1
lines changed

5 files changed

+103
-1
lines changed

pkgs/defang/cli.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ buildGoModule {
77
pname = "defang-cli";
88
version = "git";
99
src = ../../src;
10-
vendorHash = "sha256-g8for7OBYwgOlEl6iB4Bkc71WL5OYzhBbU9WFf6fwqo="; # TODO: use fetchFromGitHub
10+
vendorHash = "sha256-SpV97d+MskTCcdsBYJe/afzxzCo5TUtAef9m+lZT6/o="; # TODO: use fetchFromGitHub
1111

1212
subPackages = [ "cmd/cli" ];
1313

src/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ require (
119119
)
120120

121121
require (
122+
al.essio.dev/pkg/shellescape v1.6.0
122123
github.com/Microsoft/go-winio v0.6.2 // indirect
123124
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect
124125
github.com/aws/aws-sdk-go-v2/credentials v1.16.16

src/go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
al.essio.dev/pkg/shellescape v1.6.0 h1:NxFcEqzFSEVCGN2yq7Huv/9hyCEGVa/TncnOOBBeXHA=
2+
al.essio.dev/pkg/shellescape v1.6.0/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890=
13
cel.dev/expr v0.20.0 h1:OunBvVCfvpWlt4dN7zg3FM6TDkzOePe1+foGJ9AXeeI=
24
cel.dev/expr v0.20.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
35
cloud.google.com/go v0.120.0 h1:wc6bgG9DHyKqF5/vQvX1CiZrtHnxJjBlKUyF9nP6meA=
@@ -181,6 +183,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE
181183
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
182184
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
183185
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
186+
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
187+
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
184188
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
185189
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
186190
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=

src/pkg/migrate/migrate.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"slices"
1010
"strings"
1111

12+
"al.essio.dev/pkg/shellescape"
1213
"github.com/DefangLabs/defang/src/pkg/cli/client"
1314
"github.com/DefangLabs/defang/src/pkg/cli/compose"
1415
"github.com/DefangLabs/defang/src/pkg/surveyor"
@@ -232,6 +233,50 @@ func cleanupComposeFile(in string) (string, error) {
232233
})
233234
}
234235
}
236+
237+
// railpack generates images with `Entrypoint: "bash -c"`, and
238+
// compose-go normalizes string commands into arrays, for example:
239+
// `command: npm start` -> `command: [ "npm", "start" ]`. As a
240+
// result, the command which ultimately gets run is
241+
// `bash -c npm start`. When this gets run, `bash` will ignore
242+
// `start` and `npm` will get run in a subprocess--only printing
243+
// the help text. As it is common for users to type their service
244+
// command as a string, this cleanup step will help ensure the
245+
// command is run as intended by replacing `command: npm start`
246+
// with `command: [ "npm start" ]`.
247+
if kk.Value == "command" {
248+
if vk.Kind == yaml.ScalarNode {
249+
cmd := vk.Value
250+
vk.Value = ""
251+
vk.Kind = yaml.SequenceNode
252+
vk.Tag = "!!seq"
253+
vk.Content = []*yaml.Node{
254+
{
255+
Tag: "!!str",
256+
Kind: yaml.ScalarNode,
257+
Value: cmd,
258+
},
259+
}
260+
}
261+
// We will do the same for
262+
// `command: ["npm", "start"]`, which will also get transformed
263+
// to `command: [ "npm start" ]`.
264+
if vk.Kind == yaml.SequenceNode && len(vk.Content) > 1 {
265+
var parts []string
266+
for _, c := range vk.Content {
267+
parts = append(parts, c.Value)
268+
}
269+
cmd := shellescape.QuoteCommand(parts)
270+
// combine content nodes into one
271+
vk.Content = []*yaml.Node{
272+
{
273+
Tag: "!!str",
274+
Kind: yaml.ScalarNode,
275+
Value: cmd,
276+
},
277+
}
278+
}
279+
}
235280
}
236281
}
237282
}

src/pkg/migrate/migrate_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,58 @@ services:
469469
db:
470470
image: postgres:latest # EOL comment
471471
x-defang-postgres: "true"
472+
`,
473+
expectingError: false,
474+
},
475+
{
476+
name: "string command",
477+
input: `
478+
services:
479+
web:
480+
build: .
481+
command: npm start
482+
`,
483+
expected: `services:
484+
web:
485+
build: .
486+
command:
487+
- npm start
488+
`,
489+
expectingError: false,
490+
},
491+
{
492+
name: "array command",
493+
input: `
494+
services:
495+
web:
496+
build: .
497+
command:
498+
- npm
499+
- start
500+
`,
501+
expected: `services:
502+
web:
503+
build: .
504+
command:
505+
- npm start
506+
`,
507+
expectingError: false,
508+
},
509+
{
510+
name: "array command with multiple words",
511+
input: `
512+
services:
513+
web:
514+
build: .
515+
command:
516+
- echo
517+
- hello world
518+
`,
519+
expected: `services:
520+
web:
521+
build: .
522+
command:
523+
- echo 'hello world'
472524
`,
473525
expectingError: false,
474526
},

0 commit comments

Comments
 (0)