Как создать условный рабочий процесс с расширенными действиями GitHub
20 апреля 2022 г.Постановка задачи 🍀
GitHub Actions предоставляет возможность создавать автоматизированные рабочие нагрузки и конвейеры CI/CD. У меня есть 3 разные ветки: dev, beta и main. У них один и тот же процесс, который заключается в сборке, тестировании и развертывании моего приложения в Google Cloud App Engine. Более подробная информация была рассмотрена в моей статье о процессе развертывания с GitHub на Google Cloud App Engine.
В моем случае отличаются только конфигурации (секреты и переменные окружения). Поддерживать 3 разных рабочих процесса GitHub Actions, по одному для каждого, не рекомендуется из-за дублирования кода. С учетом сказанного, как я могу создать один рабочий процесс, который использует разные секреты на основе запущенной ветки?
Прежде чем мы начнем, если вы не знакомы с GitHub Actions, вы можете прочитать мою [введение в статью о компонентах GitHub Actions] (https://hungvu.tech/what-is-github-actions-a-not-so-eli5). -введение-в-2022) первым!
Ключевые моменты 🍀
Могу ли я заставить все 3 ветки запускать один и тот же рабочий процесс? 🔑
Да, для этой цели есть ключ «on».
``ямл
Название: Мой рабочий процесс
Определите, какое действие запускает рабочий процесс
на:
Название действия
толкать:
Фильтруем, определяем, какая ветка запускает действие
Я хочу, чтобы все ветки запускали этот рабочий процесс
ветви:
- dev # Прямая отправка разрешена, это развертывает на промежуточный сервер
- beta # Защищенная ветвь, без прямой отправки, разрешено только принятое слияние
- main # Защищенная ветвь, без прямой отправки, разрешено только принятое слияние
Как насчет оператора if / else if / else для проверки ветвлений? 🔑
GitHub Actions поддерживает ключ «if», но «else if/else» отсутствует. Кроме того, я могу использовать контексты, чтобы прочитать имя текущей ветки.
Синтаксис контекстов ${{ <context> }}, поэтому у меня есть что-то вроде ниже:
``ямл
шаги:
- название: Мой шаг
Контекст github.ref используется для определения имени ветки
Он оценивается по имени ссылки git
Неправильный синтаксис
если: ${{ github.ref }} == 'что-то'
Правильный синтаксис
Здесь я должен использовать одинарную кавычку
Мне потребовалось некоторое время, чтобы определить, что двойная кавычка нарушила рабочий процесс
если: ${{ github.ref == 'ref/heads/main' }}
Клавиши else if / else не существует. 🔑
Ну, я могу использовать 3 разных «если» в 3 разных шагах. Каждый из них представляет определенную ветвь.
Я использую google-github-actions/auth на первом этапе своей работы для аутентификации в GCP. На данный момент у меня есть 6 разных секретов GitHub для проверки концепции. Каждая ветвь имеет два секрета в формате BRANCH_WIP и BRANCH_SA.
```ямл
Шаг для основной ветки
- имя: ГЛАВНАЯ аутентификация
если: ${{ github.ref == 'ref/heads/main' }} && ${{ secrets.MAIN_WIP != null }} && ${{ secrets.MAIN_SA != null }}
использует: google-github-actions/auth@v0
с:
workload_identity_provider: ${{ секреты.MAIN_WIP }}
service_account: $${{ секреты.MAIN_SA }}
Шаги для веток beta и dev имеют одинаковую структуру
Но приведенный выше код НЕ будет работать, я объясню ниже
Я использую nektos/act для локального тестирования рабочего процесса, но он завершается с сообщением Error: exit with 'FAILURE': 1. Угадайте, что secrets нельзя использовать в ключе if, отсюда и ошибка.
Секреты GitHub нельзя прочитать в условном выражении. 🔑
GitHub Actions имеет ключ env для определения переменных среды в разных областях рабочего процесса. Я использую его на уровне шага для импорта «секретов», потому что «env» можно прочитать в ключе «if».
``ямл
- имя: ГЛАВНАЯ аутентификация
среда:
Определите пару ключей, используя переменную окружения.
WIP: ${{ секреты.MAIN_WIP }}
SA: ${{ секреты.MAIN_SA }}
если: ${{ github.ref == 'ref/heads/main' }} && env.WIP != null && env.SA != null
использует: google-github-actions/auth@v0
с:
workload_identity_provider: ${{ env.WIP }}
service_account: ${{ env.SA }}
Обратите внимание, мне нужно использовать '${{ }}' в многоразовом рабочем процессе 'auth@v0' для чтения 'env'
При этом не обязательно в ключе 'if'.
Это стоило мне довольно много времени на отладку
Предварительно скомпилированная кодовая база может читать переменные окружения. 🔑
Однако помните, что только то, что выполняется внутри виртуальной машины GitHub, может читать переменные. Серверная часть, загружаемая в GAE, создается и тестируется в среде GCP. У него нет доступа к ресурсам GitHub.
``ямл
- имя: Конфигурация для переменных среды React
если: ${{ github.ref == 'refs/heads/dev' }}
Шаг сборки может читать REACT_APP_DEV
запустить: |
эхо "REACT_APP_DEV=${{ secrets.DEV }}" >> $GITHUB_ENV
Создание действия 3 раза для 3 веток приводит к дублированию кода, должен ли быть способ его рефакторинга? 🔑
На данный момент область действия переменных среды ограничена шагом, на котором они остаются. Внутри задания у меня есть ключ steps, который содержит несколько шагов внизу. Поэтому, как минимум, мне нужно, чтобы переменные окружения имели область действия steps.
Действительно, область действия steps работает. В задании я могу записать переменные в $GITHUB_ENV на первом шаге в ключе steps, чтобы все последующие шаги могли получить доступ к переменным среды. Обратите внимание, я не могу создать условный оператор в области задания, так что, возможно, работает только область шаги.
Я столкнулся с подходом, использующим команду set-env. Однако set-env устарел из-за CVE-2020-15228 и больше не может использоваться.
Теперь вместо этого я использую echo "MY_ENV=${{ secrets.MY_SECRET }}" >> $GITHUB_ENV.
``ямл
имя: конвейер CI/CD
Определите, какое действие запускает рабочий процесс
на:
толкать:
ветви:
- dev # Прямая отправка разрешена, это развертывает на промежуточный сервер
- beta # Защищенная ветвь, без прямой отправки, разрешено только принятое слияние
- main # Защищенная ветвь, без прямой отправки, разрешено только принятое слияние
вакансии:
авторизация:
имя: Аутентификация в GCP
запуски: ubuntu-последняя
стратегия:
матрица:
версия узла: [16.x]
разрешения:
содержание: читать
id-токен: написать
шаги:
Мне нужно объявить переменные окружения только один раз в начале
Последующие шаги могут получить доступ к переменным по умолчанию
- имя: Конфигурация для основной ветки
если: ${{ github.ref == 'refs/heads/main' }}
Примечание: здесь я могу запустить любую команду Linux, а не только 'echo'
запустить: |
echo "GCP_WIP=${{ secrets.MAIN_WIP }}" >> $GITHUB_ENV
echo "GCP_SA=${{ secrets.MAIN_SA }}" >> $GITHUB_ENV
- название: Конфигурация для бета-ветки
если: ${{ github.ref == 'refs/heads/beta' }}
запустить: |
echo "GCP_WIP=${{ secrets.BETA_WIP }}" >> $GITHUB_ENV
echo "GCP_SA=${{ secrets.BETA_SA }}" >> $GITHUB_ENV
- название: Конфигурация для бета-ветки
если: ${{ github.ref == 'refs/heads/dev' }}
запустить: |
echo "GCP_WIP=${{ secrets.DEV_WIP }}" >> $GITHUB_ENV
echo "GCP_SA=${{ secrets.DEV_SA }}" >> $GITHUB_ENV
- имя: Аутентификация в GCP
если: env.GCP_WIP != null && env.GCP_SA != null
использует: google-github-actions/auth@v0
с:
workload_identity_provider: ${{ env.GCP_WIP }}
service_account: ${{ env.GCP_SA }}
Подведение итогов 🍀
Первоначально мое использование GitHub Actions включало только простые действия, такие как «сборка», «тест». С условным рабочим процессом открывается совершенно новый набор возможностей. В статье основное внимание уделяется условному рабочему процессу. Однако я также должен знать о некоторых концепциях, которые прямо или косвенно прямо или косвенно упоминаются в статье.
- Контексты
- Область действия и иерархический доступ
- Повторно используемый рабочий процесс
- Пользовательские команды Linux (рабочий процесс запускается на виртуальной машине)
Затем я потрачу некоторое время на [документ GitHub Actions] (https://docs.github.com/en/actions).
- Также опубликовано [здесь] (https://hungvu.tech/advanced-github-actions-conditional-workflow)*
Оригинал