Gitlab CI / CD Передача артефактов / переменных между конвейерами

tl;dr

Как передать данные, например переменная $BUILD_VERSION между заданиями в разных конвейерах в Gitlab CI?


Фон

Рассмотрим следующий пример (полный yml ниже):

building:
    # only on merge requests
    stage: staging
    script:
        - echo "BUILD_VERSION=1.2.3" > build.env
    artifacts:
        reports:
            dotenv: build.env

deploying:
    # after merge request is merged
    stage: deploy
    dependencies: 
        - building
    script:
        - echo $BUILD_VERSION

У меня два этапа: постановка и развертывание. Задание building в staging создает приложение и создает приложение Review (для простоты отдельного этапа сборки нет). Затем задание deploying в deploy загружает новое приложение.

Конвейер, содержащий задание building, запускается всякий раз, когда открывается запрос на слияние. Таким образом создается приложение, и разработчик может щелкнуть значок «Обзор приложения» в запросе на слияние. Задание deploying запускается сразу после слияния запроса на слияние. Идея такая:

                         *staging* stage                         *deploy* stage

<open merge request> -> `building` job (and show)   ...   <merge> -> `deploying` job
                             │                                            ▲
                             └───────────── $BUILD_VERSION ───────────────┘

Проблема для меня в том, что staging / building создает некоторые данные, например а $BUILD_VERSION. Я хочу, чтобы это $BUILD_VERSION было в deploy / deploying, например для создания нового релиза через Gitlab API.

Итак, мой вопрос: как передать $BUILD_VERSION (и другие данные) из staging / building в deploy / deploying?


Что я пробовал до сих пор

artifacts.reports.dotenv

Описанный случай более менее описан в документации gitlab в Передать переменную среды другому заданию. Также файл yml, показанный ниже, в значительной степени вдохновлен этим примером. Тем не менее, это не работает.

Артефакт build.env создается в building, но всякий раз, когда выполняется задание deploying, файл build.env удаляется, как показано ниже в строке 15: Удаление build.env. Я пытался добавить build.env к .gitignore, но он все равно удаляется.

Подготовка среды - Запуск на runner - через gitlab-runner ... - Получение исходного кода из репозитория Git - Получение изменений с глубиной git, установленной на 50 ... - Повторная инициализация существующего репозитория Git в - Получение в качестве промежуточного ... - Удаление  build.env - Пропуск установки подмодулей Git - Выполнение этапа step_script сценария задания - Использование образа докера - echo $ BUILD_VERSION - Задание выполнено

После нескольких часов поиска я нашел в этот комментарий к проблеме gitlab и это сообщение stackoverflow о том, что artifacts.reports.dotenv не работает с dependencies или needs ключевыми словами.

Удаление dependencies не работает. Использование только needs тоже не работает. Использование обоих недопустимо.

Кто-нибудь знает, как заставить это работать? Я чувствую, что так и должно работать.

Получение артефактов в виде файла

Этот ответ сообщения stackoverflow Gitlab ci cd удаляет артефакт для запросов на слияние предлагает использовать build.env как обычный файл. Я тоже пробовал это. (Соответствующий) yml следующий:

building:
    # ...
    artifacts:
        paths:
            - build.env

deploying:
    # ...
    before_script:
        - source build.env

Результат такой же, как и выше. build.env удаляется. Затем команда source build.env завершается ошибкой, потому что build.env не существует. (Неважно, входит build.env в .gitignore или нет, проверял оба)

Получение артефактов из API

Я также нашел ответ в сообщении stackoverflow Использовать артефакты из задания слияния запроса в GitLab CI, в котором предлагается использовать API вместе с $CI_JOB_TOKEN. Но поскольку мне нужны артефакты в конвейере без запросов слияния, я не могу использовать предложенный CI_MERGE_REQUEST_REF_PATH.

Пробовал использовать $CI_COMMIT_REF_NAME. Тогда (важный раздел) yml:

deploying:
    # ...
    script:
        - url=$CI_API_V4_URL/projects/jobs/artifacts/$CI_COMMIT_REF_NAME/download?job=building
        - echo "Downloading $url"
        - 'curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --output $url'
        # ...

Но при этом запрос API отклоняется с ошибкой 404 Not Found. Поскольку SHA фиксации не поддерживаются, $CI_COMMIT_BEFORE_SHA или $CI_COMMIT_SHA тоже не работают.

Использование needs

Обновление: я нашел раздел Загрузка артефактов между конвейерами в одном проекте в документации gitlab, что мне и нужно. Но: я не могу заставить его работать.

yml после меньшего количества копий из документов выглядит следующим образом:

building:
    # ...
    artifacts:
        paths:
            - version
        expire_in: never

deploying
    # ...
    needs:
        - project: $CI_PROJECT_PATH
          job: building
          ref: staging # building runs on staging branch, main doesn't work either
          artifacts: true

Теперь задание deploying немедленно завершается ошибкой, и я получаю следующий баннер с ошибкой:

Это задание зависит от других заданий с просроченными / удаленными артефактами: см. Https://docs.gitlab.com/ee/ci/yaml/README.html#dependencies

Я попытался установить artifacts.expire_in = never (как показано), но все равно получаю ту же ошибку. Также в НастройкахCI / CDАртефакты установлен флажок Сохранять артефакты из самых последних успешных заданий. Значит артефакт должен присутствовать. Что я здесь пропустил? Это должно работать в соответствии с документами!


Я надеюсь, что кто-нибудь поможет мне получить $BUILD_VERSION работу deploying. Если есть другие способы, кроме тех, которые я пробовал, я очень рад их слышать. Заранее спасибо.


Пример .gitlab-ci.yml:

stages:
    - staging
    - deploy

building:
    tags: 
        - docker
    image: bash
    stage: staging
    rules:
        - if: ($CI_PIPELINE_SOURCE == "merge_request_event") && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "staging"
          when: always
        - when: never
    script:
        - echo "BUILD_VERSION=1.2.3" > build.env
    artifacts:
        reports:
            dotenv: build.env
    environment:
        name: Example
        url: https://example.com

deploying:
    tags: 
        - docker
    image: bash
    stage: deploy
    rules:
        - if: $CI_COMMIT_BRANCH == "staging"
          when: always
        - when: never
    dependencies:
        - building
    script:
        echo $BUILD_VERSION

person miile7    schedule 29.06.2021    source источник
comment
артефакты / зависимости должны работать. Избавьтесь от reports: dotenv: и сделайте вместо этого paths:. Затем сохраните dependencies: точно так же, как у вас, чтобы восстановить build.env в конвейере развертывания.   -  person Peter    schedule 30.06.2021
comment
@Peter К сожалению, это не работает. Я снова получаю Удаление build.env, как показано на скриншоте. Я скопировал yml из своего ответа и изменил только artifacts.reports из building на artifacts.paths: -build.env   -  person miile7    schedule 30.06.2021
comment
Извините, пропустил ту часть, где вы пытались пропустить этап building в некоторых сборках и пытались передать данные между несвязанными конвейерами. Смотри мой ответ   -  person Peter    schedule 30.06.2021


Ответы (2)


Вы не можете использовать CI / CD для передачи артефактов между совершенно несвязанными конвейерами. Тот факт, что сборка выполняется в ветке, которая определяет запрос на слияние, а развертывание выполняется на основе результата слияния, не означает, что развертывание - это просто следующий этап. Что, если бы между ними был объединен другой MR? Что делать, если возникли конфликты слияния?

Другими словами, вы не можете пропустить создание основной ветки только потому, что вы создали ветку разработки. Позвольте сборке происходить постоянно, и ограничьте развертывание основной веткой. В этой настройке вы можете легко передавать артефакты из здания в развертывание.

В качестве альтернативы, если вы хотите, чтобы событие слияния действительно обновляло основную ветвь с состоянием версии, просто используйте файл VERSION, управляемый исходным кодом. Для этого нужен git. Когда вы объединитесь, main возьмет ВЕРСИЮ из ветки. Если первой зашла другая ветка, вам придется разрешить конфликт, как и нужно.

person Peter    schedule 30.06.2021
comment
Большое тебе спасибо. Думаю, это ответ на мой вопрос: это не работает. Хотя это не то, что я хотел слышать. Есть ли способ связать трубопроводы? Я предположил, что они уже связаны, учитывая историю коммитов. Один конвейер работает на (одной из) родительской фиксации, следующий - в следующей фиксации. - person miile7; 01.07.2021

Это то, что вы можете передать по файлу.

Создать новую переменную в строительном задании:

 variables:
     CONFIG: "anyname"

затем в скрипте сделайте экспорт / копирование в файл, например:

- echo $BUILD_VERSION > $CI_PROJECT_DIR/$CONFIG

добавить пути в артефакты:

artifacts:
   paths:
   - $CONFIG

затем в развертывании

variables:
     CONFIG: "anyname"

и источник его

- source $CI_PROJECT_DIR/$CONFIG

Чтобы заставить его работать, просто попробуйте решить проходящие проблемы, сохранить зависимости и сохранить артефакты, просто используйте потребности, избегайте очистки артефактов в задании

person anynewscom    schedule 30.06.2021
comment
Спасибо за ваш ответ. Но, к сожалению, это не работает. Я получаю тот же результат, что и на скриншоте в моем вопросе. Он говорит об удалении любого имени в строке 15 снова. И задание deploy не выполняется, потому что файл источника не существует. (Кстати, $CONFIG_VERSION в artifacts.paths - это опечатка, я полагаю, верно? Тем не менее конвейер не работает с обоими.) - person miile7; 30.06.2021
comment
Да, извините, только что посмотрел build_version и скопировал. Хорошо, поэтому, если он стирается, вам нужно иметь опцию потребностей или начать использовать такие этапы: docs.gitlab.com/ee/ci/yaml/#stages, поиск источников - это решение проблем для большинства случаев использования, если конвейеры gitlab широкие - person anynewscom; 30.06.2021
comment
Что ж, я уже использую этапы и _1 _ / _ 2_. Не могли бы вы привести пример того, что вы хотите изменить, по сравнению с yml, указанным в моем вопросе в самом конце? - person miile7; 30.06.2021