Мой топ-3 продвинутых функций, которые нельзя упустить в GitHub Actions

Привет, мои коллеги-разработчики!

В моей последней статье в блоге было показано, как использовать GitHub Actions для создания простых рабочих процессов непрерывной интеграции для ваших проектов, а сегодня я хотел бы поделиться расширенными возможностями GitHub Actions, которые я считаю наиболее интересными.

Вот мои 3 лучшие функции, которые вы не должны пропустить!

#1 Добро пожаловать в матрицу

Никакой революции здесь нет, но матричную стратегию можно объяснить как «Определено один раз, выполняется несколько раз». По сути, она позволяет вам определить структуру задания для выполнения в нескольких сценариях.

Согласно официальной документации: «Матрица позволяет вам создавать несколько заданий, выполняя замену переменных в одном определении задания. Например, с помощью матрицы можно создать задания для нескольких поддерживаемых версий языка программирования, операционной системы или инструмента. Матрица повторно использует конфигурацию задания и создает задание для каждой настроенной вами матрицы».

Так когда же матричная стратегия является ценной? Конечно, трудно определить все случаи, когда матрица полезна, но вот сценарии, основанные на моем собственном опыте:

  • Вы хотите запустить задание на нескольких версиях инструмента, например, Java 11 и 17, или на разных версиях ОС.
  • Вы хотите ввести переменные для выполнения заданий по-разному, например, изменить путь к вашим микрофронтендам.
  • Вы хотите объединить два вышеуказанных случая для достижения максимальной гибкости.

Рабочий процесс Entando Standard Banking Demo использует матричную стратегию для обеспечения того, чтобы задания микрофронтенда использовали одно и то же определение для всех компонентов. При этом меняется только конечная вложенная папка задания, а значение пути определяется «на лету» с помощью инъекции переменных.

Обратите внимание, что с помощью опции include мы можем указать несколько значений переменных задания, определенных матричной стратегией.

 micro-frontends:
    name: ${{ matrix.widget }} micro frontend
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        widget:
          - alert-bar-icon-react
          - dashboard-card-angular
          - dashboard-card-config
          - dashboard-card-react
          - transaction-table
        include:
          - widget: dashboard-card-angular
            test-script-name: test-ci
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2.1.4
        with:
          node-version: '14.15.0'
      - name: Run tests
        run: |
          cd $GITHUB_WORKSPACE/$PROJECT_NAME/ui/widgets/banking-widgets/${{ matrix.widget }}
          npm install
          npm run ${{ matrix.test-script-name || 'test' }}
Вход в полноэкранный режим Выход из полноэкранного режима

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

#2 Компонуйте задания с помощью составных действий

Вторая моя любимая функция GitHub Actions — составные действия. Да, вы не ослышались. Вы можете создавать многократно используемые действия и компоновать их для создания задания.

Эта функция доступна с лета 2021 года и позволяет не только использовать скрипты или действия с рынка, как это было раньше, но и ссылаться на действия, определенные в отдельных файлах.

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

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

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

В демонстрационном примере Standard Banking я снова использовал составные действия для улучшения своих конвейеров. Например, я создал одно действие, которое будет выполняться каждый раз, когда я хочу запустить тесты микросервиса бэкенда Spring Boot.

name: 'Unit testing Microservice backend application'
description: 'Run unit tests for a backend Spring boot application'
inputs:
  path:
    description: the project path
    required: true
runs:
  using: 'composite'
  steps:
    - name: Run backend tests
      shell: bash
      run: |
        cd ${{inputs.path}}
        chmod +x mvnw
        ./mvnw -ntp clean test
Войти в полноэкранный режим Выйти из полноэкранного режима

Обратите внимание, что нам нужно явно установить значение using в 'composite' и указать shell, которую мы используем для каждого шага (например, bash).

В следующем действии я использую одно входное значение (параметр) для определения пути к проекту. Мне придется задавать его каждый раз, когда я использую это действие.

name: Banking Plugin CI
on: push
env:
  PROJECT_NAME: banking-plugin
jobs:
  backend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-java@v1
        with:
          java-version: '11.x'
      - uses: ./.github/actions/ms-unit-tests
        with:
          path: $GITHUB_WORKSPACE/$PROJECT_NAME
      - uses: ./.github/actions/ms-build
        with:
          path: $GITHUB_WORKSPACE/$PROJECT_NAME
Войти в полноэкранный режим Выйти из полноэкранного режима

Обратите внимание, что для использования составного действия необходимо указать путь к файлу действия (например, uses: ./.github/actions/ms-unit-tests), а затем передать параметры с помощью ключевого слова with:..

#3 Связывайте задания друг с другом

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

Ключевое слово needs позволяет вам определить необходимость задания, которое должно быть выполнено до запуска другого задания. Если backend2 нуждается в backend1, то backend2 будет запущен только после успешного завершения backend1.

name: Banking Plugin CI
on: push
env:
  PROJECT_NAME: banking-plugin
jobs:
  backend1:
[...]
  backend2:
    needs: backend1
Вход в полноэкранный режим Выход из полноэкранного режима

Или же вы можете решить запустить второе задание, даже если первое завершается неудачно.

name: Banking Plugin CI
on: push
env:
  PROJECT_NAME: banking-plugin
jobs:
  backend1:
[...]
  backend2:
    if: ${{ always() }}
    needs: backend1
Войти в полноэкранный режим Выйти из полноэкранного режима

Совет профессионала

Параметр if позволяет запускать задание только при выполнении определенного условия, например, always() означает, что задание будет выполняться всегда (но после завершения предыдущего задания, успешного или нет). Это полезно, чтобы иметь гибкость в ваших конвейерах или запасные шаги.

Ниже приведен пример зависимости между заданиями из проекта JHipster-lite. Для выполнения матричных заданий нужны tests-windows и tests-linux, а для codecov нужны все матричные задания.

Заключение

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

Какие лучшие функции вы уже использовали в своих рабочих процессах GitHub Actions? Не стесняйтесь поделиться с нами в Twitter!

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *