当前位置: 首页 > 知识库问答 >
问题:

(@aws-cdk/pipelines)应用程序源代码的构建阶段

太叔烨霖
2023-03-14

我学习了CDK管道:AWS CDK应用程序的连续交付教程,该教程概述了如何使用新的CodePipeline API创建自变异CDK管道。

本教程创建了一个代码管道,每次将更改推送到主分支时,都会自动从GitHub repo检索CDK源代码。CDK代码使用CDK旁边定义的typescript处理程序定义lambda

对于我的用例,我想定义一个自变异的代码管道,每当我推送到包含应用程序源代码的第二个存储库时,它也会被触发。第二个存储库还将包含一个buildspec,它使用我的应用程序生成Docker映像,并将映像上载到ECR。然后,新映像将在我的管道的应用程序阶段部署到Fargate集群。

我在PublishAsset阶段之后创建了一个Application ationBuild阶段,其中包括一个CodeBuild项目。CodeBuild项目从我的存储库中读取并构建/上传到ECR;但是,我需要一种方法将此CodeBuild链接到管道的部署。我不清楚如何使用新的cdk CodePipeline API来做到这一点。

共有1个答案

燕俊明
2023-03-14

如果有人有同样的问题,我能够按照我在问题中提到的教程的存档版本,使用遗留的CdkPipeline API破解一个解决方案。

这是一个最小可行的管道堆栈,包括。。。

  1. CDK管道源操作(在“源”阶段)

库cdkpipelines-demo-pipeline-stack.ts

import * as codepipeline from '@aws-cdk/aws-codepipeline';
import * as codepipeline_actions from '@aws-cdk/aws-codepipeline-actions';
import * as core from '@aws-cdk/core';
import {Construct, SecretValue, Stack, StackProps} from '@aws-cdk/core';
import {CdkPipeline, SimpleSynthAction} from "@aws-cdk/pipelines";
import * as iam from "@aws-cdk/aws-iam";
import * as ecr from "@aws-cdk/aws-ecr";
import * as codebuild from "@aws-cdk/aws-codebuild";

/**
 * The stack that defines the application pipeline
 */
export class CdkpipelinesDemoPipelineStack extends Stack {
    constructor(scope: Construct, id: string, props?: StackProps) {
        super(scope, id, props);

        const sourceArtifact = new codepipeline.Artifact();
        const cloudAssemblyArtifact = new codepipeline.Artifact();

        const pipeline = new CdkPipeline(this, 'Pipeline', {
            // The pipeline name
            pipelineName: 'MyServicePipeline',
            cloudAssemblyArtifact,

            // Where the source can be found
            sourceAction: new codepipeline_actions.GitHubSourceAction({
                actionName: 'GitHub',
                output: sourceArtifact,
                oauthToken: SecretValue.secretsManager('github-token'),
                owner: 'OWNER',
                repo: 'REPO',
            }),

            // How it will be built and synthesized
            synthAction: SimpleSynthAction.standardNpmSynth({
                sourceArtifact,
                cloudAssemblyArtifact,

                // We need a build step to compile the TypeScript Lambda
                buildCommand: 'npm run build'
            }),
        });
        const pipelineRole = pipeline.codePipeline.role;

        // Add application source action
        const appSourceArtifact = new codepipeline.Artifact();
        const appSourceAction = this.createAppSourceAction(appSourceArtifact);
        const sourceStage = pipeline.stage("Source");
        sourceStage.addAction(appSourceAction);

        // Add application build action
        const codeBuildServiceRole = this.createCodeBuildServiceRole(this, pipelineRole);
        const repository = this.createApplicationRepository(this, codeBuildServiceRole);
        const pipelineProject = this.createCodeBuildPipelineProject(
            this, codeBuildServiceRole, repository, 'REGION', 'ACCOUNT_ID');
        const appBuildOutput = new codepipeline.Artifact();
        const appBuildAction = this.createAppCodeBuildAction(
            this, appSourceArtifact, appBuildOutput, pipelineProject, codeBuildServiceRole);
        const buildStage = pipeline.stage("Build");
        buildStage.addAction(appBuildAction);

        // This is where we add the application stages...
    }

    createAppSourceAction(appSourceArtifact: codepipeline.Artifact): codepipeline_actions.GitHubSourceAction {
        return new codepipeline_actions.GitHubSourceAction({
            actionName: 'GitHub-App-Source',
            output: appSourceArtifact,
            oauthToken: SecretValue.secretsManager('github-token'),
            owner: 'SOURCE-OWNER',
            repo: 'SOURCE-REPO',
        });
    }

    createCodeBuildServiceRole(scope: core.Construct, pipelineRole: iam.IRole): iam.Role {
        const role = new iam.Role(scope, 'CodeBuildServiceRole', {
            assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'),
        });
        role.assumeRolePolicy?.addStatements(new iam.PolicyStatement({
            sid: "PipelineAssumeCodeBuildServiceRole",
            effect: iam.Effect.ALLOW,
            actions: ["sts:AssumeRole"],
            principals: [pipelineRole]
        }));

        // Required policies to create an AWS CodeBuild service role
        role.addToPolicy(new iam.PolicyStatement({
            sid: "CloudWatchLogsPolicy",
            effect: iam.Effect.ALLOW,
            actions: [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            resources: ["*"]
        }));
        role.addToPolicy(new iam.PolicyStatement({
            sid: "CodeCommitPolicy",
            effect: iam.Effect.ALLOW,
            actions: ["codecommit:GitPull"],
            resources: ["*"]
        }));
        role.addToPolicy(new iam.PolicyStatement({
            sid: "S3GetObjectPolicy",
            effect: iam.Effect.ALLOW,
            actions: [
                "s3:GetObject",
                "s3:GetObjectVersion"
            ],
            resources: ["*"]
        }));
        role.addToPolicy(new iam.PolicyStatement({
            sid: "S3PutObjectPolicy",
            effect: iam.Effect.ALLOW,
            actions: [
                "s3:PutObject"
            ],
            resources: ["*"]
        }));
        role.addToPolicy(new iam.PolicyStatement({
            sid: "S3BucketIdentity",
            effect: iam.Effect.ALLOW,
            actions: [
                "s3:GetBucketAcl",
                "s3:GetBucketLocation"
            ],
            resources: ["*"]
        }));

        // This statement allows CodeBuild to upload Docker images to Amazon ECR repositories.
        // source: https://docs.aws.amazon.com/codebuild/latest/userguide/sample-docker.html#sample-docker-running
        role.addToPolicy(new iam.PolicyStatement({
            sid: "ECRUploadPolicy",
            effect: iam.Effect.ALLOW,
            actions: [
                "ecr:BatchCheckLayerAvailability",
                "ecr:CompleteLayerUpload",
                "ecr:GetAuthorizationToken",
                "ecr:InitiateLayerUpload",
                "ecr:PutImage",
                "ecr:UploadLayerPart"
            ],
            resources: ["*"]
        }));

        return role;
    }

    createApplicationRepository(scope: core.Construct, codeBuildServiceRole: iam.Role): ecr.Repository {
        const repository = new ecr.Repository(scope, 'Repository', {
            repositoryName: 'cdkpipelines-demo-image-repository'
        });
        repository.grantPullPush(codeBuildServiceRole);
        return repository;
    }

    createCodeBuildPipelineProject(scope: core.Construct,
                                   codeBuildServiceRole: iam.Role,
                                   repository: ecr.Repository,
                                   region: string,
                                   accountId: string): codebuild.PipelineProject {
        return new codebuild.PipelineProject(scope, 'BuildProject', {
            buildSpec: codebuild.BuildSpec.fromSourceFilename("buildspec.yml"),
            environment: {
                buildImage: codebuild.LinuxBuildImage.fromCodeBuildImageId("aws/codebuild/standard:4.0"),
                privileged: true,
                computeType: codebuild.ComputeType.SMALL,
                environmentVariables: {
                    AWS_DEFAULT_REGION: {value: region},
                    AWS_ACCOUNT_ID: {value: accountId},
                    IMAGE_REPO_NAME: {value: repository.repositoryName},
                    IMAGE_TAG: {value: "latest"},
                }
            },
            role: codeBuildServiceRole
        });
    }

    createAppCodeBuildAction(scope: core.Construct,
                             input: codepipeline.Artifact,
                             output: codepipeline.Artifact,
                             pipelineProject: codebuild.PipelineProject,
                             serviceRole: iam.Role) {
        return new codepipeline_actions.CodeBuildAction({
            actionName: "App-Build",
            checkSecretsInPlainTextEnvVariables: false,
            input: input,
            outputs: [output],
            project: pipelineProject,
            role: serviceRole,
            type: codepipeline_actions.CodeBuildActionType.BUILD,
        })
    }
}
 类似资料:
  • 我正在尝试使用代码构建操作在AWS代码管道上部署AWS CDK应用程序。 构建和部署在本地完美工作(因为它会!)但是在CodeBuild上运行时,命令失败 这很可能是一些琐碎的事情,但我却在挠头,想弄明白是什么! 项目结构是自动生成的(使用) 对于阶段是 是(此阶段的输入目录是阶段的工件,即目录) 阶段抛出cdk ls步骤中的错误。由于上面的构建/部署步骤在本地工作(在干净的签出中),我怀疑这可能

  • 我有一个AWS架构,其中我介绍了一个配置数据库,多个Lambdas将依赖于此。 配置数据库通过CDK填充:通过创建S3 bucket,将数据上传到S3 bucket,S3 bucket反过来通知将填充数据库的Lambda。 我有其他Lambda依赖于正在填充的数据库,其中一个Lambda位于cron上,最初由CDK通过自定义资源调用,因此计时非常关键。 目前,所有AWS资源都是通过单个堆栈部署的,

  • 我开始学习AWS的CI/CD功能。到目前为止,我一直在基于microsoft/windowsservercore映像在Windows Server 2016本地创建docker映像,并手动将其推送到ECR(amazon容器注册表)。 在这一点上,我没有试图在CodeBuild中编译应用程序。我只是想建造容器。在本地,二进制文件位于子目录中,并复制到容器中。 CodeBuild项目失败,出现错误:无

  • 问题内容: 我有一个我想混合使用Java和Scala源代码的应用程序(实际上是将Java应用程序迁移到Scala的应用程序,但一次)。 我可以在IDE中很好地完成这项工作。但是我不确定如何使用Maven做到这一点- scalac可以编译Java和Scala交织在一起,但是如何为模块设置Maven? 另外,我的Scala源代码是否必须与Java文件夹不同? 问题答案: 使用maven scala插件

  • 我试图生成我的REST API客户端Android使用OpenAPI生成器从build.gradle脚本。这样,我就不必每次规格改变时都运行生成器命令行。理想情况下,这将在我构建/组装我的应用程序时生成,源将最终在java(生成)文件夹中,在那里生成的源可以从代码中访问(这就是BuildConfig.java文件的情况)。 下面是他们官方GitHub的链接,这里是构建。我最终得到的gradle文件

  • 我正在构建一个具有多种不同风格的应用程序。我的问题是,如果我为基于flavor的活动使用不同的代码,我是否需要在所有flavor directores中包含该代码的副本,或者如果我只将代码副本保留在app/src/main/java目录中,如果我不将其包含在flavor目录中,其他所有flavor是否会使用main/java中的文件。 我有 app/src/main/java/com/mycomp