与现有代码管道一起使用的 AWS CDK 管道

Posted

技术标签:

【中文标题】与现有代码管道一起使用的 AWS CDK 管道【英文标题】:AWS CDK Pipelines using with an existing codepipeline 【发布时间】:2021-10-18 08:29:14 【问题描述】:

@aws-cdk/pipelines 的文档似乎建议可以使用 codePipeline 属性将 CDK 管道添加到现有的 @aws-cdk/aws-codepipeline/Pipeline:https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_pipelines.CodePipeline.html

codePipeline? Pipeline An existing Pipeline to be reused and built upon.

但是,我无法使其正常工作,并且在cdk synth 步骤中遇到多个错误,具体取决于我尝试设置它的方式。据我所知,目前还没有任何文档可以涵盖这种情况。

基本上,我们正在尝试创建一个运行类似以下内容的管道:

克隆 lint / 类型检查 / 单元测试 cdk 部署到测试环境 集成测试 部署到 preprod 冒烟测试 人工审批 部署到产品

我猜只是不清楚这个 codebuild 管道和 cdk 管道之间的区别。此外,阶段的命名约定似乎有点不清楚 - 参考这个问题:https://github.com/aws/aws-cdk/issues/15945

参见:https://github.com/ChrisSargent/cdk-issues/blob/pipelines/lib/cdk-test-stack.ts 及以下:

import * as cdk from "@aws-cdk/core";
import * as pipelines from "@aws-cdk/pipelines";
import * as codepipeline from "@aws-cdk/aws-codepipeline";
import * as codepipeline_actions from "@aws-cdk/aws-codepipeline-actions";

export class CdkTestStack extends cdk.Stack 
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) 
    super(scope, id, props);

    const cdkInput = pipelines.CodePipelineSource.gitHub(
      "ChrisSargent/cdk-issues",
      "pipelines"
    );

    // Setup the code source action
    const sourceOutput = new codepipeline.Artifact();
    const sourceAction = new codepipeline_actions.GitHubSourceAction(
      owner: "ChrisSargent",
      repo: "cdk-issues",
      branch: "pipelines",
      actionName: "SourceAction",
      output: sourceOutput,
      oauthToken: cdk.SecretValue.secretsManager("git/ChrisSargent"),
    );

    const pipeline = new codepipeline.Pipeline(this, "Pipeline", 
      stages: [
        
          actions: [sourceAction],
          stageName: "GitSource",
        ,
      ],
    );

    const cdkPipeline = new pipelines.CodePipeline(this, "CDKPipeline", 
      codePipeline: pipeline,
      synth: new pipelines.ShellStep("Synth", 
        // Without input, we get: Error: CodeBuild action 'Synth' requires an input (and the pipeline doesn't have a Source to fall back to). Add an input or a pipeline source.
        // With input, we get:Error: Validation failed with the following errors: Source actions may only occur in first stage
        input: cdkInput,
        commands: ["yarn install --frozen-lockfile", "npx cdk synth"],
      ),
    );

    // Produces: Stage 'PreProd' must have at least one action
    // pipeline.addStage(new MyApplication(this, "PreProd"));

    // Produces: The given Stage construct ('CdkTestStack/PreProd') should contain at least one Stack
    cdkPipeline.addStage(new MyApplication(this, "PreProd"));
  


class MyApplication extends cdk.Stage 
  constructor(scope: cdk.Construct, id: string, props?: cdk.StageProps) 
    super(scope, id, props);

    console.log("Nothing to deploy");
  

任何有关这方面的指导或经验将不胜感激。

【问题讨论】:

【参考方案1】:

首先,错误Pipeline must have at least two stages是正确的。 您只有 GitHub checkout/clone 命令作为一个阶段。 对于第二阶段,您可以使用 CodeBuild 项目来编译/lint/单元测试...如您所述。

但是,您希望如何处理已编译的工件? 构建容器以便稍后部署它们? 如果是这样,CDK 有更好的方法来做到这一点 (DockerImageAsset)。 这也可以节省您预先存在的管道,您可以直接使用 CDK 管道。

请您尝试设置属性restartExecutionOnUpdate: true, 你的常规管道,就像我下面的 sn-p 一样?

 const pipeline = new codepipeline.Pipeline(this, "Pipeline", 
      restartExecutionOnUpdate: true,
      stages: [
        
          actions: [sourceAction],
          stageName: "GitSource",
        ,
      ],
    );

这是 CDK 管道的自突变能力所必需的。

【讨论】:

感谢您的回答。我更新了我的代码以包含第二个“阶段”,我实际上认为我的代码中的cdkPipeline 会根据需要添加多个阶段。但是,这并没有让我通过 input 错误,这似乎只是现在的 catch-22。 “但是,您想对编译后的工件做什么?”我们所做的一切都是无服务器的,没有 Docker 容器。 lambda 是用 Golang 编写的,并内置在 cdk synth 命令中。构建/部署后,我们希望将端到端测试作为管道中的一个新阶段运行 @ChrisSargent 我这里的情况非常相似。你发现这里有什么工作吗? @jobcrazy - 不是真的,我或多或少地放弃了 CodePipeline,主要是因为重新部署失败的堆栈的问题。也可以看:github.com/aws/aws-cdk/issues/16488 @ChrisSargent,我有一个解决方案,请查看我发布的答案。【参考方案2】:

我可以通过在 CDK 管道中添加只有 prepost 步骤的波/阶段来实现类似的效果,示例代码如下所示,我正在修改您的原始代码 sn-p:

import * as cdk from "@aws-cdk/core";
import * as pipelines from "@aws-cdk/pipelines";
import * as codepipeline from "@aws-cdk/aws-codepipeline";
import * as codepipeline_actions from "@aws-cdk/aws-codepipeline-actions";

export class CdkTestStack extends cdk.Stack 
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) 
    super(scope, id, props);

    const cdkInput = pipelines.CodePipelineSource.gitHub(
      "ChrisSargent/cdk-issues",
      "pipelines"
    );

    const cdkPipeline = new pipelines.CodePipeline(this, "CDKPipeline", 
      selfMutation: true,
      crossAccountKeys: true, //can be false if you don't need to deploy to a different account.
      pipelineName,
      synth: new pipelines.ShellStep("Synth", 
        // Without input, we get: Error: CodeBuild action 'Synth' requires an input (and the pipeline doesn't have a Source to fall back to). Add an input or a pipeline source.
        // With input, we get:Error: Validation failed with the following errors: Source actions may only occur in first stage
        input: cdkInput,
        commands: ["yarn install --frozen-lockfile", "npx cdk synth"],
        primaryOutputDirectory: 'cdk.out'
      ),
    );

    // add any additional test step here, they will run parallels in waves
    cdkPipeline.addWave('test', post: [provideUnitTestStep(this, 'unitTest')]);
    // add a manual approve step if needed.
    cdkPipeline.addWave('promotion', post: [new ManualApprovalStep('PromoteToUat')]);

    // Produces: Stage 'PreProd' must have at least one action
    // pipeline.addStage(new MyApplication(this, "PreProd"));

    // Produces: The given Stage construct ('CdkTestStack/PreProd') should contain at least one Stack
    cdkPipeline.addStage(new MyApplication(this, "PreProd"));
  


class MyApplication extends cdk.Stage 
  constructor(scope: cdk.Construct, id: string, props?: cdk.StageProps) 
    super(scope, id, props);

    console.log("Nothing to deploy");
  

值得注意的是,您可能需要将编写 Codebuild 操作的方式隐蔽到新的 cdk CodeBuildStep。一个示例单元测试步骤可能如下所示:

const provideUnitTestStep = (
    id: string
): cdkpipeline.CodeBuildStep => 
    const props: CodeBuildStepProps = 
        partialBuildSpec: codebuild.BuildSpec.fromObject(
            version: '0.2',
            env: 
                variables: 
                    DEFINE_VARIBLES: 'someVariables'
                
            ,
            phases: 
                install: 
                    commands: [
                        'install some dependencies',
                    ]
                ,
                build: 
                    commands: [
                        'run some test!'
                    ]
                
            
        ),
        commands: [],
        buildEnvironment: 
            buildImage: codebuild.LinuxBuildImage.STANDARD_5_0
        
    ;
    return new cdkpipeline.CodeBuildStep(`$id`, props);
;

检索下划线CodeBuild 项目Role 并不是那么简单(并且足够简单),您需要在CodeBuildStep 道具中传递rolePolicyStatements 属性以授予测试所需的额外权限。

【讨论】:

好的,有道理。最后我们决定放弃 CodePipeline,因为我们一直遇到它的限制。

以上是关于与现有代码管道一起使用的 AWS CDK 管道的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 CDK 禁用代码管道中的转换?

AWS CDK - 多个堆栈 - 找不到 Lambda 代码位置的参数

使用 CDK、AWS 和 Github 私有存储库部署的最佳实践?

代码管道中的资产执行步骤失败 - CDK (Java)

在 CDK CodePipelines 中添加手动审批阶段

覆盖现有插入模式如何在 aws 数据管道的 redshiftcopyactivity 中工作