KnowSQL
KnowSQL

Reputation: 85

AWS CodeBuild through CDK fails with "/codebuild/output/tmp/script.sh: 4: [[: not found"

The CDK pipeline is simply:

    source0 = CodePipelineSource.connection("some-owner/some-repo-2", "master",
        connection_arn="arn:aws:codestar-connections:us-east-1:<123456789012>:connection/<some-uuid>"
    )

    pipeline = CodePipeline(self, "Abcdef",
        synth=ShellStep("Synth",
            input=CodePipelineSource.connection("some-owner/some-repo-1", "master",
                connection_arn="arn:aws:codestar-connections:us-east-1:<123456789012>:connection/<some-uuid>"
            ),
            additional_inputs={
                "../some-repo-2": source0,
            },
            commands=[
                "npm install -g aws-cdk",
                "pip install -r requirements.txt",
                "cdk synth"
            ]
        )
    )

This generates Cfn template that has somewhere in it a CodeBuild BuildSpec that asserts that the output directory specified for the additional_inputs must not already exit. To do that it uses:

"BuildSpec": "{\n  \"version\": \"0.2\",\n  \"phases\": {\n    \"install\": {\n      \"commands\": [\n        \"[[ ! -d \\\"../some-repo-2\\\" ]] || { echo 'additionalInputs: \\\"../some-repo-2\\\" must not exist yet. If you want to merge multiple artifacts, use a \\\"cp\\\" command.'; exit 1; } && ln -s -- \\\"$CODEBUILD_SRC_DIR_some_owner_some_repo_2_Source\\\" \\\"../some-repo-2\\\"\"\n      ]\n    },\n    \"build\": {\n      \"commands\": [\n        \"npm install -g aws-cdk\",\n        \"pip install -r requirements.txt\",\n        \"cdk synth\"\n      ]\n    }\n  },\n  \"artifacts\": {\n    \"base-directory\": \"cdk.out\",\n    \"files\": \"**/*\"\n  }\n}",
"Type": "CODEPIPELINE"

As you can see it's a bash construct since [[ ... ]] is not something supported by pure POSIX only shells. When this is synthesised in the CodePipeline Build step it fails with:

/codebuild/output/tmp/script.sh: 4: [[: not found

So whatever that script above that aws uses is probably not bash compliant or the environment is not set to bash.

How do I work around this? Is there a way I can modify the build spec from within the CDK code somehow?

(using: cdk version 1.129.0 with python3.8)

Upvotes: 0

Views: 759

Answers (1)

ustulation
ustulation

Reputation: 3760

It's an issue with the shell being used. Seems ShellStep doesn't configure the underlying CodeBuild to use bash at-least for additional_inputs.

Using a more granular subclass CodeBuildStep and setting the shell explicitly to bash solves this:

pipeline = CodePipeline(self, "...",
            synth=CodeBuildStep("Synth",
                partial_build_spec=BuildSpec.from_object({
                    "version": "0.2",
                    "env": {
                        "shell": "bash"
                    }
                }),
                input=...,
                additional_inputs={ ... },
                commands= [ ... ],
                ...

Since additional_inputs cannot be used via ShellStep then, it must either not expose it (and be made available only via CodeBuildStep) or the factory method in aws-cdk source code should change to use POSIX compliant constructs - so [ .. instead of [[ ..

If all that's true I would consider it a bug in cdk. Anyway, in the meantime we can solve it as above.

Upvotes: 2

Related Questions