diff --git a/internal/pkg/cli/flag.go b/internal/pkg/cli/flag.go index c7b82161cfa..7e65fbc93de 100644 --- a/internal/pkg/cli/flag.go +++ b/internal/pkg/cli/flag.go @@ -39,15 +39,16 @@ const ( yesInitWorkloadFlag = "init-wkld" // Build flags. - dockerFileFlag = "dockerfile" - dockerFileContextFlag = "build-context" - imageTagFlag = "tag" - stackOutputDirFlag = "output-dir" - uploadAssetsFlag = "upload-assets" - deployFlag = "deploy" - diffFlag = "diff" - diffAutoApproveFlag = "diff-yes" - sourcesFlag = "sources" + dockerFileFlag = "dockerfile" + dockerFileContextFlag = "build-context" + dockerFileBuildArgsFlag = "build-args" + imageTagFlag = "tag" + stackOutputDirFlag = "output-dir" + uploadAssetsFlag = "upload-assets" + deployFlag = "deploy" + diffFlag = "diff" + diffAutoApproveFlag = "diff-yes" + sourcesFlag = "sources" // Flags for operational commands. limitFlag = "limit" @@ -192,6 +193,8 @@ var ( imageFlagDescription = fmt.Sprintf(`The location of an existing Docker image. Cannot be specified with --%s or --%s.`, dockerFileFlag, dockerFileContextFlag) dockerFileFlagDescription = fmt.Sprintf(`Path to the Dockerfile. +Cannot be specified with --%s.`, imageFlag) + dockerFileBuildArgsFlagDescription = fmt.Sprintf(`Key-value pairs converted to --build-args. Cannot be specified with --%s.`, imageFlag) dockerFileContextFlagDescription = fmt.Sprintf(`Path to the Docker build context. Cannot be specified with --%s.`, imageFlag) diff --git a/internal/pkg/cli/task_run.go b/internal/pkg/cli/task_run.go index 8b77bbd27bf..ce4f42d0bb1 100644 --- a/internal/pkg/cli/task_run.go +++ b/internal/pkg/cli/task_run.go @@ -114,6 +114,7 @@ type runTaskVars struct { image string dockerfilePath string dockerfileContextPath string + dockerfileBuildArgs map[string]string imageTag string taskRole string @@ -372,6 +373,10 @@ func (o *runTaskOpts) Validate() error { return errors.New("cannot specify both `--image` and `--build-context`") } + if o.image != "" && o.dockerfileBuildArgs != nil { + return errors.New("cannot specify both `--image` and `--build-args`") + } + if o.isDockerfileSet { if _, err := o.fs.Stat(o.dockerfilePath); err != nil { return fmt.Errorf("invalid `--dockerfile` path: %w", err) @@ -963,6 +968,7 @@ func (o *runTaskOpts) buildAndPushImage(uri string) error { Dockerfile: o.dockerfilePath, Context: ctx, Tags: append([]string{imageTagLatest}, additionalTags...), + Args: o.dockerfileBuildArgs, } buildArgsList, err := buildArgs.GenerateDockerBuildArgs(dockerengine.New(exec.NewCmd())) if err != nil { @@ -1175,7 +1181,9 @@ func BuildTaskRunCmd() *cobra.Command { Run a task using the current workspace with specific subnets and security groups. /code $ copilot task run --subnets subnet-123,subnet-456 --security-groups sg-123,sg-456 Run a task with a command. - /code $ copilot task run --command "python migrate-script.py"`, + /code $ copilot task run --command "python migrate-script.py" + Run a task with Docker build args. + /code $ copilot task run --build-args GO_VERSION=1.19"`, RunE: runCmdE(func(cmd *cobra.Command, args []string) error { opts, err := newTaskRunOpts(vars) if err != nil { @@ -1193,6 +1201,7 @@ func BuildTaskRunCmd() *cobra.Command { cmd.Flags().StringVarP(&vars.groupName, taskGroupNameFlag, nameFlagShort, "", taskGroupFlagDescription) cmd.Flags().StringVar(&vars.dockerfilePath, dockerFileFlag, defaultDockerfilePath, dockerFileFlagDescription) + cmd.Flags().StringToStringVar(&vars.dockerfileBuildArgs, dockerFileBuildArgsFlag, nil, dockerFileBuildArgsFlagDescription) cmd.Flags().StringVar(&vars.dockerfileContextPath, dockerFileContextFlag, "", dockerFileContextFlagDescription) cmd.Flags().StringVarP(&vars.image, imageFlag, imageFlagShort, "", imageFlagDescription) cmd.Flags().StringVar(&vars.imageTag, imageTagFlag, "", taskImageTagFlagDescription) @@ -1228,6 +1237,7 @@ func BuildTaskRunCmd() *cobra.Command { buildFlags := pflag.NewFlagSet("Build", pflag.ContinueOnError) buildFlags.AddFlag(cmd.Flags().Lookup(dockerFileFlag)) + buildFlags.AddFlag(cmd.Flags().Lookup(dockerFileBuildArgsFlag)) buildFlags.AddFlag(cmd.Flags().Lookup(dockerFileContextFlag)) buildFlags.AddFlag(cmd.Flags().Lookup(imageFlag)) buildFlags.AddFlag(cmd.Flags().Lookup(imageTagFlag)) diff --git a/internal/pkg/cli/task_run_test.go b/internal/pkg/cli/task_run_test.go index f85e62aed69..589ae10003b 100644 --- a/internal/pkg/cli/task_run_test.go +++ b/internal/pkg/cli/task_run_test.go @@ -68,6 +68,7 @@ func TestTaskRunOpts_Validate(t *testing.T) { inImage string inDockerfilePath string + inDockerfileBuildArgs map[string]string inDockerfileContextPath string inTaskRole string @@ -235,6 +236,16 @@ func TestTaskRunOpts_Validate(t *testing.T) { wantedError: errors.New("cannot specify both `--image` and `--build-context`"), }, + "both build args and image name specified": { + basicOpts: defaultOpts, + + inImage: "113459295.dkr.ecr.ap-northeast-1.amazonaws.com/my-app", + inDockerfileBuildArgs: map[string]string{ + "KEY": "VALUE", + }, + + wantedError: errors.New("cannot specify both `--image` and `--build-args`"), + }, "both dockerfile and image name specified": { basicOpts: defaultOpts, @@ -417,6 +428,7 @@ func TestTaskRunOpts_Validate(t *testing.T) { subnets: tc.inSubnets, securityGroups: tc.inSecurityGroups, dockerfilePath: tc.inDockerfilePath, + dockerfileBuildArgs: tc.inDockerfileBuildArgs, dockerfileContextPath: tc.inDockerfileContextPath, envVars: tc.inEnvVars, envFile: tc.inEnvFile,