【问题标题】:AWS CDK Pipelines using with an existing codepipeline与现有代码管道一起使用的 AWS CDK 管道
【发布时间】: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");
  }
}

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

【问题讨论】:

    标签: aws-cdk aws-codepipeline aws-codebuild


    【解决方案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,因为我们一直遇到它的限制。
    猜你喜欢
    • 2021-09-06
    • 1970-01-01
    • 2023-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-14
    相关资源
    最近更新 更多