通过 CDK 的 AWS CodeBuild 失败并显示“/codebuild/output/tmp/script.sh: 4: [[: not found”

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

CDK 管道很简单:

    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"
            ]
        )
    )

这会生成 Cfn 模板,其中某处有一个 CodeBuild BuildSpec,断言为 additional_inputs 指定的输出目录不得已经退出。为此,它使用:

"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"

如您所见,它是一个 bash 结构,因为 [[ ... ]] 不受纯 POSIX 外壳的支持。当它在 CodePipeline 构建步骤中合成时,它失败并显示:

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

因此,aws 使用的任何上面的脚本都可能不 bash 兼容,或者环境未设置为 bash。

我该如何解决这个问题?有什么方法可以从 CDK 代码中以某种方式修改构建规范?

(使用:cdk 版本 1.129.0 和 python3.8)

这是使用的 shell 的问题。似乎 ShellStep 没有将底层 CodeBuild 配置为至少在 additional_inputs.

中使用 bash

使用更精细的子类 CodeBuildStep 并将 shell 显式设置为 bash 解决了这个问题:

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

由于 additional_inputs 不能通过 ShellStep 使用,因此它要么不公开它(并且只能通过 CodeBuildStep 提供),要么 the factory method in aws-cdk source code 应该更改为使用 POSIX 兼容的结构 - 所以 [ .. 而不是 [[ ..

如果这是真的,我会认为它是 cdk 中的错误。无论如何,同时我们可以按照上面的方法解决。