AWS передать переменную в buildspec.yml из CodePipeline

У меня есть AWS CodePipeline, которая вызывает CodeBuild на этапе сборки.

Вопрос в том, как передать переменную окружения из CodePipeline, которую можно прочитать в buildspec.yml CodeBuild?

Я знаю, что могу устанавливать переменные среды в CodeBuild, но я хочу использовать один и тот же проект CodeBuild для сред dev, qa и prod. Я не понимаю, как я могу передать переменную окружения из CodePipeline, которая делает его полностью в buildspec.yml

Пример buildspec.yml

version: 0.1

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

Где CURRENT_ENVIRONMENT будет переменной, которую я установил в действии Этапа CodePipeline.

10 ответов

На сегодняшний день вы можете устанавливать переменные среды для заданий сборки CodeBuild в своем конвейере. Это улучшение позволяет повторно использовать один и тот же проект сборки для нескольких действий и упростить развертывание в промежуточной и производственной средах в вашем конвейере.

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

На самом деле вы можете передавать переменные среды в облачной информации CodeBuild, как показано ниже:

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}

Эта функция не доступна сегодня.

Обходной путь должен был бы создать различный проект CodeBuild для каждого этапа с различными переменными среды.

Вы можете найти подробную информацию об использовании переменной окружения в ваших командах builspec.yml здесь: http://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html

  1. Создайте проект сборки кода.
  2. Создайте проект конвейера внутри Codepipline.
  3. Добавьте действие CodeBuild и определите свои переменные в этом действии.
    Например:
    Имя переменной: TAG
    Значение переменной: staging

Используя переменную, которую вы определили в файле Codepipline Buildspec в проекте Codebuild:

результаты регистрации:

Вы можете использовать переменные среды сборки для условного перехода от buildspec к npm build определив, какое задание CodeBuild или CodePipeline выполняется. Например, если у вас есть одна CodePipeline, которая прослушивает / dev, а другая - / master, это работает отлично.

Вот пример, который запускает другую сборку PROD vs 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

Если вы не хотите использовать CF, вы можете установить переменные ENV в своем проекте CodeBuild в пользовательском интерфейсе AWS.

В AWS перейдите к проекту компоновщика кода, в правом верхнем углу нажмите "изменить" и выберите "среда". На странице редактирования среды щелкните раскрывающийся список "Дополнительная конфигурация". Там вы увидите входные данные для "имени" и "значения". "Имя" - это то, где вы устанавливаете свой ENV, а "значение" - это то, где вы устанавливаете свое значение для этой переменной.

Пример: набор API_ENV в "имя" и development в цене." Затем в вашем buildspec.yml вы можете использовать $API_ENV.

Я уверен, что выше опубликовано много ответов, но есть дополнительная информация, которую я нашел полезной.

CodePipeline начал поддерживать переменную среды на уровне конвейера, где некоторые из них имеют встроенную поддержку через конвейер (переменные конвейера, созданные CodePipeline)

Так, например, если нам нужно получить CommitId на любом этапе, мы можем объявить переменную среды, как показано ниже.

  1. Дайте любое имя пространству имен переменных на исходной сцене, например "SourceVariables"
  2. Используйте это пространство имен на любом этапе как "#{SourceVariables.CommitId}", в этом случае оно будет использоваться на этапе сборки.

Также мы можем сгенерировать нашу собственную переменную среды на любом этапе, которая будет доступна для использования на следующих этапах. Более подробная информация доступна здесь.

Возвращаясь к исходному вопросу, мы можем установить переменную среды для действия сборки, которая поможет нам использовать ее вместе с файлом спецификации сборки. Но все же это не позволит нам динамически передавать его при каждом нажатии кода из источника. И из-за этого требуется два шага, такие как конвейер обновления, а затем запуск конвейера, чтобы он мог перейти на соответствующий этап.

Я создал небольшой скрипт на 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".

Инициатор 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"


Я создал лямбда-функцию, которая обновляет переменные среды существующего проекта сборки кода. Вы можете запустить сборку (codebuild.start) после обновления переменных. Выглядит примерно так (nodejs):

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
    }
});
Другие вопросы по тегам