在自定义阶段使用 AWS CodePipeline 变量

问题描述 投票:0回答:2

以下构建规范运行一些命令并最终导出一个变量:

env:
  exported-variables:
    - PROPERTY_FROM_BUILD

我想在自定义管道阶段中使用此变量,但我不知道如何在此处获取它:

import { Stage, StageProps } from 'aws-cdk-lib';
class MyStage extends Stage {
  constructor(scope: Construct, id: string, props: StageProps) {
    new Stack(this, 'MyStack', {
        PROPERTY_FROM_BUILD: '???'
    });
  }
}

为了以防万一,让我发布更多详细信息。我的代码管道如下所示:

const codePipeline = new cdk.pipelines.CodePipeline(this, 'MyPipeline', {...});
codePipeline.addStage(new MyStage(this, 'MyStage', {...})
codePipeline.buildPipeline();

如您所见,我只是创建一个管道,添加我的阶段并构建它。完成后,我创建一个代码构建项目和操作来运行我的构建规范:

const project = new cdk.aws_codebuild.PipelineProject(this, 'MyProject', {
  buildSpec: cdk.aws_codebuild.BuildSpec.fromSourceFilename(`buildspec.yml`),
});
const action = new cdk.aws_codepipeline_actions.CodeBuildAction({
  actionName: 'MyAction',
  project: project,
});
codePipeline.pipeline.addStage({
  stageName: 'MyActionStage',
  actions: [action],
  placement: {
    rightBefore: codePipeline.pipeline.stage('MyStage')
  }
});

它可以工作并生成一个很好的管道。有什么方法可以从变量传递我的

PROPERTY_FROM_BUILD
并在我的堆栈中使用它?

typescript amazon-web-services aws-cdk aws-codepipeline aws-codebuild
2个回答
0
投票

虽然我花了大约一周的时间才弄清楚这一点,但我终究还是成功了。让我把解决方案留在这里,以防其他人遇到这个问题:

在开始之前,使用自定义命名空间扩展您的

CodeBuildAction
,例如:

const action = new cdk.aws_codepipeline_actions.CodeBuildAction({
  actionName: 'MyAction',
  project: project,
  variablesNamespace: 'my_action_namespace',
});

首先,你必须找出部署阶段的索引,例如:

const deployIdx = codePipeline.pipeline.stages.indexOf(codePipeline.pipeline.stage('Deploy'));

然后,查找“changeset Replace”类型的所有操作:

const actionsIdxs = codePipeline.pipeline.stage('Deploy').actions.filter(x => x.actionProperties.category === 'Deploy').map((x,i)=>i);

接下来,使用此 Escape Hatches 功能编辑生成的模板并将 管道变量 作为

ParameterOverrides
附加到所有部署操作:

const cfnPipeline = codePipeline.pipeline.node.findChild('Resource') as cdk.aws_codepipeline.CfnPipeline;
for(const i of actionsIdxs){
  cfnPipeline.addOverride(
    `Properties.Stages.${deployIdx}.Actions.${i}.Configuration.ParameterOverrides`,
    JSON.stringify({
        // Use lowercase-only here to match the autogenerated name of the CfnParameter.
        propertyfrombuild: "#{my_action_namespace.PROPERTY_FROM_BUILD}"
    }));
}

最后,在我的堆栈中,我可以像这样访问该值:

const PROPERTY_FROM_BUILD = new cdk.CfnParameter(this, 'propertyfrombuild').valueAsString;

确保将变量命名为全小写且不含特殊字符,并将其放置在堆栈中(而不是子构造中)。


0
投票

显然这不是一个完整的答案,而是我为实现此目的所做的要点。

构建规范:

env:
  exported-variables:
    # Make the JAR filename available to the CodePipeline
    - JAR_OUTPUT_NAME
phases:
  build:
    commands:
      # Set the output variable
      - JAR_OUTPUT_NAME=App-${CODEBUILD_RESOLVED_SOURCE_VERSION:0:7}.jar
      # Your build steps would go here...

管道中的构建操作:

const buildAction = new codepipelineActions.CodeBuildAction({
    actionName: 'Build',
    project: codeBuildProject,
    input: sourceOutput,
    outputs: [codeBuildOutput],
    variablesNamespace: 'BuildVariables',
});

使用输出变量的操作:

const prepareAction = new codepipelineActions.CloudFormationCreateReplaceChangeSetAction({
    actionName: 'App.Prepare',
    stackName: 'App',
    changeSetName: 'codepipeline-#{codepipeline.PipelineExecutionId}',
    templatePath: codeBuildOutput.atPath('stack.yml'),
    templateConfiguration: codeBuildOutput.atPath(
        `app-parameters.json`
    ),
    parameterOverrides: {
        // Here we use the output variable from CodeBuild
        CodeContentFileKey: `app/code/${buildAction.variable('JAR_OUTPUT_NAME')}`,
    },
    cfnCapabilities: [cdk.CfnCapabilities.ANONYMOUS_IAM],
    adminPermissions: true,
    account: deployEnv.account,
    region: deployEnv.region,
    role: cdkDeploymentRoles[deployEnv.environment],
    deploymentRole: cdkCloudformationExecRoles[deployEnv.environment],
    runOrder: 1,
});
© www.soinside.com 2019 - 2024. All rights reserved.