从CodePipeline将变量传递到buildspec.yml的AWS方法

59

我有一个AWS CodePipeline,它在构建阶段调用CodeBuild。

问题是如何从CodePipeline传递环境变量,在CodeBuild的buildspec.yml中读取?

我知道可以在CodeBuild中设置环境变量,但我想为开发、QA和生产环境使用同一个CodeBuild项目。我不知道如何传递来自CodePipeline的环境变量,并让它最终到达buildspec.yml。

示例buildspec.yml

version: 0.1

phases:   
  build:
    commands:
      - npm install
      - npm build -- --env ${CURRENT_ENVIRONMENT}

CURRENT_ENVIRONMENT将是我在CodePipeline阶段操作中设置的变量。


2
对于任何感兴趣的人,我解决这个问题的方法是在CodeBuild中设置环境变量,这些变量会传递到buildspec.yml。只要您可以将参数传递到AWS :: CodeBuild :: Project CloudFormation声明中,当运行buildspec.yml时,它们就会被捕获。 - user1432403
2
这是一个相当不幸的限制。我已经在 AWS 论坛的帖子这里中添加了对此的评论。如果对您很重要,请考虑发表意见让 AWS 知道。 - jandersen
1
如何在buildspec.yml中使用环境变量:npm build --env $THE_VARIABLE - ricka
10个回答

21

从今天起,您可以在管道中为CodeBuild构建作业设置环境变量。此改进使得可以将相同的构建项目用于多个操作,并简化在管道中部署到staging和production环境的过程。

name: Build
actions:
  - name: MyBuildJob
    actionTypeId:
      category: Build
      owner: AWS
      provider: CodeBuild
      version: '1'
    runOrder: 1
    configuration:
      ProjectName: my-build-project
      PrimarySource: MyApplicationSource1
      EnvironmentVariables: '[{"name":"CURRENT_ENVIRONMENT","value":"Production","type":"PLAINTEXT"},
                              {"name":"UseParamStore","value":"CURRENT_ENVIRONMENT","type":"PARAMETER_STORE"}]'

https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html#action-reference-CodeBuild-config


这是2021年以“官方AWS方式”最佳的答案。请注意EnvironmentVariables的(相当奇怪的)JSON字符串值。此外,所有Cloudfront YAML键都应该是CamelCase(我很惊讶示例代码能够正常工作)。 - kino1
要按照要求“从CodePipeline传递环境变量”,请使用{"name":"CURRENT_ENVIRONMENT","value":"#{StageNamespace.CurrentEnvironment}","type":"PLAINTEXT"}],并将Namespace: StageNamespace添加到提供变量的操作中。 - kino1
您好,请问这个要放在哪个文件中? - user13524876

12

您实际上可以按照以下方式在CodeBuild CloudFormation中传递环境变量:参考文档


Build:
    Type: AWS::CodeBuild::Project
    Properties:
      Name:
        !Sub Build-${AWS::StackName}
      Description: Build your project
      Environment:
        Type: LINUX_CONTAINER
        ComputeType: BUILD_GENERAL1_SMALL
        Image: node8
        EnvironmentVariables:
          - Name: CURRENT_ENVIRONMENT
            Type: PLAINTEXT
            Value: staging

在您的buildspec.yml文件中,您可以这样引用环境:

version: 0.2

phases:
  install:
    commands:
      - npm install

  build:
    commands:
      - npm build -- --env ${CURRENT_ENVIRONMENT}

这并不是很有帮助,因为通常情况下,人们希望在所有环境中都定义一个AWS::CodeBuild::Project。你的方法意味着为每个环境创建一个AWS::CodeBuild::Project,它们之间唯一的区别就是环境变量。 - Jim Tough

9

15
整整一年了,这个功能还是不可用? - pablochacin
没有比为每个环境创建新的构建更好的想法... - BartusZak
这个答案是无效的。现在有三种方法可以通过CloudFormation模板将Env Vars传递到CodeBuild步骤中:在CodeBuild资源“Environment.EnvironmentVariables”部分中,在使用CodeBuild的CodePipeline资源的Action步骤中,或者在CodeBuild的buildSpec文件本身中:https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#build-spec-ref-syntax。 - airtonix

8
  1. 创建一个Codebuild项目。
  2. 在Codepipline中创建流水线项目。
  3. 添加一个CodeBuild操作并在此操作中定义变量。
    例如:
    变量名称为:TAG
    变量值为:staging

enter image description here

在Codebuild项目的Buildspec文件中使用您在Codepipline中定义的变量: enter image description here

日志结果: enter image description here


尝试了这个并且顺利解决了问题。这个应该被接受为最佳答案,因为它用AWS当前可用的最佳和最简单的方式解释了问题所询问的内容(截至2021年8月)。 - SebaGra

5
您可以使用构建环境变量来有条件地从构建规范传递到npm build,方法是检测运行的CodeBuild作业或CodePipeline作业。例如,如果您有一个监听/dev提交和另一个监听/master提交的CodePipeline,则这种方法非常适用。
下面是一个示例,用于运行不同的PROD和DEV构建:
  build:
    commands:
   - |
     if expr "${CODEBUILD_BUILD_ARN}" : ".*build/MyProjectDev-" >/dev/null; then
       yarn run build-dev;
     fi
   - |
     if expr "${CODEBUILD_BUILD_ARN}" : ".*build/MyProject-" >/dev/null; then
       yarn run build-prod;
     fi

4

我相信上面发布了许多答案,但是我提供了一些我认为有用的额外信息。

CodePipeline开始支持在流水线级别支持环境变量,其中一些变量通过流水线具有本机支持 (CodePipeline生成的管道变量)

例如,如果我们需要在任何阶段获取CommitId,那么我们可以按照以下方式声明环境变量。

  1. 在源阶段为变量命名空间指定任何名称,例如“SourceVariables” enter image description here
  2. 在任何阶段中使用该命名空间,如"#{SourceVariables.CommitId}"。在此示例中,它在构建阶段中使用。 enter image description here

此外,我们可以从任何阶段生成自己的环境变量,这将可用于下一个阶段。更多信息可以在这里找到。

回到原来的问题,我们可以在构建操作中设置环境变量,这将帮助我们与构建规范文件一起使用它。但是,它仍然不允许我们在每次从源代码推送时动态传递它。因此,需要两个步骤,即更新流水线,然后触发流水线,以便它可以进入相应的阶段。


这确实是正确的,但你没有强调必须从CodePipeline->编辑:构建->环境变量-可选设置环境变量。如果你在CodeBuild->编辑->环境->附加配置->环境变量中设置这些变量,它不会起作用!虽然很蠢,但我自己也浪费了太多时间在这上面。 - Raphael Setin

4
如果您不想使用CF,则可以在AWS UI中为CodeBuild项目设置ENV变量。
在AWS中,进入您的代码构建器项目,在右上角单击“编辑”,然后选择“环境”。在编辑环境页面上,单击“附加配置”下拉菜单。在那里,您将看到“名称”和“值”的输入。 “名称”是您设置ENV的地方,“值”是您为该变量设置值的地方。
例如:在“名称”中设置 API_ENV ,在“值”中设置 development 。然后,在您的buildspec.yml中,您可以使用$API_ENV。

1
我创建了一个小型的Python脚本来解析传递的$CODEBUILD_INITIATOR变量。以下是buildspec.yml,下面是包含在构建中并调用的Python脚本。
      build:
        commands:
          - |
            PIPELINE_ENV=$(python3 codebuild_env_parser.py $CODEBUILD_INITIATOR)
            OUTPUT_STATUS=$?
            if [ "$OUTPUT_STATUS" = "0" ]; then
              echo "Success finding a valid environment from codebuild_env_parser.py."
            else
              echo "Failure finding a valid environment from codebuild_env_parser.py. Check the script to see if the codepipeline env was passed correctly."
            fi

Python脚本 (codebuild_env_parser.py):
    import sys
    
    
    def main():
        args = sys.argv
        if len(args) == 2:
            env_list = ["dev", "prod"]
            pipeline_invoker = args[1].lower()
            code_pipeline_name = pipeline_invoker.split("codepipeline/")[1]
            env_name = code_pipeline_name.split("-project-name")[0]
            if env_name in env_list:
                print("{}".format(env_name))
                sys.exit(0)
            else:
                sys.exit(1)
        else:
            sys.exit(1)
    
    
    main()

如果您想让这个工作,您需要调整一些变量值,特别是"-project-name"


0

CodeBuild的初始程序是CodeBuild中的环境变量,可以用于读取CodePipeline名称。

因此,如果在CodePipeline名称中包含环境作为后缀(例如-dev或-prod),则可以像这样解析它。

version: 0.2
phases:
  build:
    commands:
      - CURRENT_ENVIRONMENT=`echo $CODEBUILD_INITIATOR | cut -d '-' -f2 | tr '[:upper:]' '[:lower:]'`
      - echo "My env is $CURRENT_ENVIRONMENT"



0
我创建了一个 Lambda 函数,用于更新现有的 CodeBuild 项目环境变量。在更新变量后,您可以启动构建(codebuild.start)。代码类似于以下内容(Node.js):
var params = {
    "name": "Build-project-name",
    "description": "Build this project.",

    "environment": {
        "type": "LINUX_CONTAINER",
        "image": "aws/codebuild/standard:1.0",
        "computeType": "BUILD_GENERAL1_LARGE",
        "environmentVariables": [
        {
            "name": "MY_ENVIRONMENT_VARIABLE",
            "value": "VALUE_OF_ENVIRONMENT_VARIABLE",
            "type": "PLAINTEXT"
        }]
    }
}

codebuild.updateProject(params, function(err, data) {
    if (err) {
        console.log(err, err.stack); // an error occurred
    }
    else     {
        console.log(data);           // successful response
    }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接