当我将此 BucketDeployment 添加到我的 CDK CodePipeline 时,cdk 合成器永远不会完成

pup*_*eno 4 amazon-web-services aws-codepipeline aws-cdk

我正在尝试使用 CDK 和 CodePipeline 构建 React 应用程序并将其部署到 S3。在该CodePipeline阶段之后,在我自己的堆栈中,我定义了 S3 存储桶,如下所示:

const bucket = new Bucket(this, "Bucket", {
    websiteIndexDocument: "index.html",
    websiteErrorDocument: "error.html",
})
Run Code Online (Sandbox Code Playgroud)

这有效。然后我定义了我构建的 React 应用程序的部署,如下所示:

new BucketDeployment(this, "WebsiteDeployment", {
    sources: [Source.asset("./")],
    destinationBucket: bucket
})
Run Code Online (Sandbox Code Playgroud)

这似乎不起作用。这样的用法BucketDeployment正确吗?

当我添加这些行时发生的奇怪的事情BucketDeploymentcdk synthor cdk deploy,它们永远不会完成,并且它们似乎在 中生成无限递归树cdk.out,所以那里肯定有问题。

如果我更改为Source.asset("./build")我收到错误:

> cdk synth
C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\core\lib\asset-staging.ts:109
      throw new Error(`Cannot find asset at ${this.sourcePath}`);
            ^
Error: Cannot find asset at C:\Users\pupeno\Code\ww3fe\build
    at new AssetStaging (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\core\lib\asset-staging.ts:109:13)
    at new Asset (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-assets\lib\asset.ts:72:21)
    at Object.bind (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-deployment\lib\source.ts:55:23)
    at C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-deployment\lib\bucket-deployment.ts:170:83
    at Array.map (<anonymous>)
    at new BucketDeployment (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-deployment\lib\bucket-deployment.ts:170:51)
    at new MainStack (C:\Users\pupeno\Code\ww3fe\infra\pipeline-stack.ts:16:9)
    at new DeployStage (C:\Users\pupeno\Code\ww3fe\infra\pipeline-stack.ts:28:26)
    at new PipelineStack (C:\Users\pupeno\Code\ww3fe\infra\pipeline-stack.ts:56:24)
    at Object.<anonymous> (C:\Users\pupeno\Code\ww3fe\infra\pipeline.ts:6:1)
Subprocess exited with error 1
Run Code Online (Sandbox Code Playgroud)

这表明这是非常错误的。为什么它要搜索build我机器上的目录?构建后,它应该在 CodePipeline 中搜索它。

我的整个管道是:

> cdk synth
C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\core\lib\asset-staging.ts:109
      throw new Error(`Cannot find asset at ${this.sourcePath}`);
            ^
Error: Cannot find asset at C:\Users\pupeno\Code\ww3fe\build
    at new AssetStaging (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\core\lib\asset-staging.ts:109:13)
    at new Asset (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-assets\lib\asset.ts:72:21)
    at Object.bind (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-deployment\lib\source.ts:55:23)
    at C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-deployment\lib\bucket-deployment.ts:170:83
    at Array.map (<anonymous>)
    at new BucketDeployment (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-deployment\lib\bucket-deployment.ts:170:51)
    at new MainStack (C:\Users\pupeno\Code\ww3fe\infra\pipeline-stack.ts:16:9)
    at new DeployStage (C:\Users\pupeno\Code\ww3fe\infra\pipeline-stack.ts:28:26)
    at new PipelineStack (C:\Users\pupeno\Code\ww3fe\infra\pipeline-stack.ts:56:24)
    at Object.<anonymous> (C:\Users\pupeno\Code\ww3fe\infra\pipeline.ts:6:1)
Subprocess exited with error 1
Run Code Online (Sandbox Code Playgroud)

我在AWS中遇到的实际错误是这样的:

[Container] 2022/01/25 20:28:27 Phase complete: BUILD State: SUCCEEDED
[Container] 2022/01/25 20:28:27 Phase context status code:  Message: 
[Container] 2022/01/25 20:28:27 Entering phase POST_BUILD
[Container] 2022/01/25 20:28:27 Phase complete: POST_BUILD State: SUCCEEDED
[Container] 2022/01/25 20:28:27 Phase context status code:  Message: 
[Container] 2022/01/25 20:28:27 Expanding base directory path: cdk.out
[Container] 2022/01/25 20:28:27 Assembling file list
[Container] 2022/01/25 20:28:27 Expanding cdk.out
[Container] 2022/01/25 20:28:27 Skipping invalid file path cdk.out
[Container] 2022/01/25 20:28:27 Phase complete: UPLOAD_ARTIFACTS State: FAILED
[Container] 2022/01/25 20:28:27 Phase context status code: CLIENT_ERROR Message: no matching base directory path found for cdk.out
Run Code Online (Sandbox Code Playgroud)

如果重要的话, by cdk.json,在我的存储库的根目录中,包含:

import {Construct} from "constructs"
import {CodeBuildStep, CodePipeline, CodePipelineSource} from "aws-cdk-lib/pipelines"
import {Stage, CfnOutput, StageProps, Stack, StackProps} from "aws-cdk-lib"
import {Bucket} from "aws-cdk-lib/aws-s3"
import {BucketDeployment, Source} from "aws-cdk-lib/aws-s3-deployment"

export class MainStack extends Stack {
    constructor(scope: Construct, id: string, props?: StageProps) {
        super(scope, id, props)

        const bucket = new Bucket(this, "Bucket", {
            websiteIndexDocument: "index.html",
            websiteErrorDocument: "error.html",
        })

        new BucketDeployment(this, "WebsiteDeployment", {
            sources: [Source.asset("./")],
            destinationBucket: bucket
        })

        new CfnOutput(this, "BucketOutput", {value: bucket.bucketArn})
    }
}

export class DeployStage extends Stage {
    public readonly mainStack: MainStack

    constructor(scope: Construct, id: string, props?: StageProps) {
        super(scope, id, props)
        this.mainStack = new MainStack(this, "example")
    }
}

export class PipelineStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
        super(scope, id, props)

        const pipeline = new CodePipeline(this, id, {
            pipelineName: id,
            synth: new CodeBuildStep("Synth", {
                    input: CodePipelineSource.connection("user/example", "main", {
                        connectionArn: "arn:aws:codestar-connections:....",
                    }),
                    installCommands: [
                        "npm install -g aws-cdk"
                    ],
                    commands: [
                        "npm ci",
                        "npm run build",
                        "npx cdk synth"
                    ]
                }
            ),
        })

        const deploy = new DeployStage(this, "Staging")
        const deployStage = pipeline.addStage(deploy)
    }
}
Run Code Online (Sandbox Code Playgroud)

fed*_*nev 5

TL;DR 通过两项更改,管道成功部署了 React 应用程序:(1)Source.asset需要完整路径build,(2) 需要将 React 构建命令添加到合成步骤中。

给出Source.assetReact 目录的完整路径build

new BucketDeployment(this, "WebsiteDeployment", {
    sources: [Source.asset(path.join(__dirname, './build'))], // relative to the Stack dir
    destinationBucket: bucket
})
Run Code Online (Sandbox Code Playgroud)

React 构建工件通常是.gitignored 的,因此CodePipeline需要构建 React 应用程序。我的版本有一个单独的package.jsonReact 应用程序,因此构建步骤1需要更多命令:

synth: new pipelines.CodeBuildStep('Synth', {
  commands: [
    // build react (new)
    'cd react-app',  // path from project root to React app package.json
    'npm ci',
    'npm run build',
    'cd ..',
    // synth cdk (as in OP)
    "npm ci",
    "npm run build",
    "npx cdk synth"  // synth must run AFTER the React build step
  ],
Run Code Online (Sandbox Code Playgroud)

React 应用程序部署到 S3 URL:

// MainStack
new cdk.CfnOutput(this, 'WebsiteUrl', {
  value: `http://${this.websiteBucket.bucketName}.s3-website-${this.region}.amazonaws.com`,
});
Run Code Online (Sandbox Code Playgroud)

(1) pipelines.CodePipeline部署 Stacks 的固执己见的构造。较低级别的codepipeline.Pipeline构造具有许多应用程序所需的功能,例如分离构建步骤以及在步骤之间传递构建时环境变量(例如使用环境变量将 API URL 注入客户端包REACT_APP_API_URL)。