Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Мені часто доводиться будувати пайплайн для збирання проектів на Java. Іноді це опенсорс, іноді ні. Нещодавно я вирішив спробувати перенести частину своїх репозиторіїв із Travis-CI та TeamCity на GitHub Actions, і ось що з цього вийшло.

Що автоматизуватимемо

Для початку нам потрібен проект, який ми автоматизуватимемо, давайте зробимо невеликий додаток на Spring boot / Java 11 / Maven. В рамках цієї статті логіка програми нас цікавити не буде зовсім, нам важлива інфраструктура навколо програми, тому нам вистачить простенького REST API контролера.

Подивитись вихідники можна тут: github.com/antkorwin/github-actions всі етапи побудови pipeline-конвеєра відображені у пулл-реквестах цього проекту.

JIRA та планування

Варто сказати, що ми зазвичай використовуємо JIRA як трекер задач, так що давайте заведемо окрему борду під цей проект і накидаємо туди перші завдання:

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Трохи пізніше ми ще повернемося до того, що цікавого можуть дати у зв'язці JIRA та GitHub.

Автоматизуємо складання проекту

Наш тестовий проект збирається через maven, так що складання його досить просте, все, що нам потрібно, це mvn clean package.

Щоб зробити це за допомогою Github Actions, нам потрібно буде створити в репозиторії файл із описом нашого workflow, це можна зробити звичайним yml-файлом, не можу сказати, що мені подобається «програмування на yml», але що вдієш — робимо в директорії .github/ workflow/ файл build.yml в якому будемо описувати дії при складанні майстер гілки:

name: Build

on:
  pull_request:
    branches:
      - '*'
  push:
    branches:
      - 'master'

jobs:
  build:
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/checkout@v1
      - name: set up JDK 11
        uses: actions/setup-java@v1
        with:
          java-version: 1.11
      - name: Maven Package
        run: mvn -B clean package -DskipTests

on — це опис події, за якою запускатиметься наш скрипт.

on: pull_request / push - говорить про те, що цей workflow потрібно запускати при кожному пуші в майстер та створення пулл-реквестів.

Далі йде опис завдань (роботи) та кроки виконання (кроки) для кожного завдання.

runs-on - Тут ми можемо вибрати цільову ОС, напрочуд можна вибрати навіть Mac OS, але на приватних репозиторіях це досить дороге задоволення (порівняно з linux).

використовує дозволяє перевикористовувати інші екшени, наприклад за допомогою екшену actions/setup-java ми встановлюємо оточення для Java 11.

За допомогою з ми можемо вказати параметри з якими запускаємо дію, по суті, це аргументи, які будуть передаватися в екшен.

Залишається тільки запустити мавеном складання проекту: run: mvn -B clean package прапор -B говорить про те, що нам потрібен non-interactive mode, щоб раптом не захотів щось у нас запитати.

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Чудово! Тепер при кожному коміті в майстер запускається складання проекту.

Автоматизуємо запуск тестів

Складання це добре, але насправді проект може благополучно збиратися, але не працювати. Тому наступним кроком потрібно зайнятися автоматизацією прогону тестів. До того ж, досить зручно дивитися результат проходу тестів, коли робиш ревью PR - ти точно знаєш, що тести проходять і ніхто не забув, перед тим як робити merge, прогнати свою гілку.

Робимо запуск тестів при створенні пулл-реквесту і merge в майстер, а заразом додамо побудову звіту про code-coverage.

name: Build

on:
  pull_request:
    branches:
      - '*'
  push:
    branches:
      - 'master'

jobs:
  build:
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/checkout@v1
      - name: set up JDK 11
        uses: actions/setup-java@v1
        with:
          java-version: 1.11
      - name: Maven Verify
        run: mvn -B clean verify
      - name: Test Coverage
        uses: codecov/codecov-action@v1
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

Для покриття тестів я використовую codecov у зв'язці з jacoco плагіном. Codecov має свій екшен, але йому для роботи з нашим pull-request-ом потрібен токен:

${{ secrets.CODECOV_TOKEN }} — таку конструкцію ми зустрічатимемо ще не один раз, secrets це механізм зберігання секретів у гітхабі, ми можемо там прописати паролі/токени/хости/url-и та інші дані, якими не варто світити в кодовій базі репозиторію.

Додати змінну в secrets, можна в налаштуваннях репозиторію на GitHub:

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Отримати токен можна на codecov.io після авторизації через GitHub, для додавання public проекту потрібно просто пройти за посиланням: GitHub user name/[Repo name]. Приватний репозиторій теж можна додати, для цього треба дати права кодеків додатку в гітхабі.

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Додаємо jacoco плагін у POM-файл:

<plugin>
	<groupId>org.jacoco</groupId>
	<artifactId>jacoco-maven-plugin</artifactId>
	<version>0.8.4</version>
	<executions>
		<execution>
			<goals>
				<goal>prepare-agent</goal>
			</goals>
		</execution>
		<!-- attached to Maven test phase -->
		<execution>
			<id>report</id>
			<phase>test</phase>
			<goals>
				<goal>report</goal>
			</goals>
		</execution>
	</executions>
</plugin>
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-surefire-plugin</artifactId>
	<version>2.22.2</version>
	<configuration>
		<reportFormat>plain</reportFormat>
		<includes>
			<include>**/*Test*.java</include>
			<include>**/*IT*.java</include>
		</includes>
	</configuration>
</plugin>

Тепер у кожен наш пулл-реквест заходитиме codecov бот і додаватиме графік зміни покриття:

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Додамо статичний аналізатор

У більшості своїх oпенсорс-проектів я використовую sonar cloud для статичного аналізу коду, його досить легко підключити до travis-ci. Так що це логічний крок при міграції на GitHub Actions, зробити те саме. Маркет екшенів - кльова штука, але цього разу він трохи підвів, тому що я звичкою знайшов потрібний екшен і прописав його в workflow. А виявилося, що sonar не підтримує роботу через дію для аналізу проектів на maven чи gradle. Про це звичайно написано в документації, але хто її читає?!

Через дію не можна, тому робитимемо через mvn плагін:

name: SonarCloud

on:
  push:
    branches:
      - master
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  sonarcloud:
    runs-on: ubuntu-16.04
    steps:
      - uses: actions/checkout@v1
      - name: Set up JDK
        uses: actions/setup-java@v1
        with:
          java-version: 1.11
      - name: Analyze with SonarCloud
#       set environment variables:
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
#       run sonar maven plugin:
        run: mvn -B verify sonar:sonar -Dsonar.projectKey=antkorwin_github-actions -Dsonar.organization=antkorwin-github -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=$SONAR_TOKEN -Dsonar.coverage.jacoco.xmlReportPaths=./target/site/jacoco/jacoco.xml

SONAR_TOKEN - Можна отримати в sonarcloud.io і потрібно прописати його в secrets. GITHUB_TOKEN — це вбудований токен, який генерує гітхаб, за допомогою якого sonarcloud[bot] зможе авторизуватися в гіті, щоб залишати нам повідомлення в пулл-реквестах.

Dsonar.projectKey - Назва проекту в сонарі, можна подивитися в налаштуваннях проекту.

Dsonar.organization - Назва організації з GitHub.

Робимо пулл-реквест і чекаємо, коли sonarcloud[bot] прийде у коментарі:

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Управління випуском

Білд налаштували, тести прогнали, можна й реліз зробити. Давайте подивимося, як GitHub Actions допомагає значно спростити release management.

На роботі я маю проекти, кодова база яких лежить у bitbucket (все як у тій історії «вдень пишу в бітбакет, вночі коммічу в GitHub»). На жаль, у bitbucket немає вбудованих засобів для керування релізами. Це проблема, тому що під кожен реліз доводиться руками заводити сторінку в confluence і скидати туди всі фічі, що ввійшли в реліз, шерстить чертоги розуму, таски в jira, комміти в репозиторії. Шансів помилитися багато, можна щось забути чи вписати те, що вже релізували минулого разу, іноді просто не зрозуміло, до чого віднести якийсь пулл-реквест — це фіча чи фікс багів, чи правка тестів, чи щось інфраструктурне .

Як нам допомогти GitHub actions? Є відмінний екшен - release drafter, він дозволяє задати шаблон файлу release notes, щоб налаштувати категорії пулл-реквестів і автоматично групувати їх у release notes файлі:

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Приклад шаблону для налаштування звіту (.github/release-drafter.yml):

name-template: 'v$NEXT_PATCH_VERSION'
tag-template: 'v$NEXT_PATCH_VERSION'
categories:
  - title: ' New Features'
    labels:
      - 'type:features'
# в эту категорию собираем все PR с меткой type:features

  - title: ' Bugs Fixes'
    labels:
      - 'type:fix'
# аналогично для метки type:fix и т.д.

  - title: ' Documentation'
    labels:
      - 'type:documentation'

  - title: ' Configuration'
    labels:
      - 'type:config'

change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
template: |
  ## Changes
  $CHANGES

Додаємо скрипт для генерації чернетки релізу (.github/workflows/release-draft.yml):

name: "Create draft release"

on:
  push:
    branches:
      - master

jobs:
  update_draft_release:
    runs-on: ubuntu-18.04
    steps:
      - uses: release-drafter/release-drafter@v5
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Усі пулл-реквести з цього моменту будуть збиратися в release notes автоматично – magic!

Тут може виникнути питання: а якщо розробники забудуть проставити мітки в PR? Тоді незрозуміло, до якої категорії його віднести, і знову доведеться розбиратися вручну, з кожним PR-ом окремо. Щоб виправити цю проблему, ми можемо скористатися ще одним екшеном – label verifier – він перевіряє наявність тегів на пулл-реквесті. Якщо немає жодного обов'язкового тега, то перевірку буде завалено і повідомлення про це ми побачимо в нашому пул-реквесті.

name: "Verify type labels"

on:
  pull_request:
    types: [opened, labeled, unlabeled, synchronize]

jobs:
  triage:
    runs-on: ubuntu-18.04
    steps:
      - uses: zwaldowski/match-label-action@v2
        with:
          allowed: 'type:fix, type:features, type:documentation, type:tests, type:config'

Тепер будь-який pull-request потрібно позначити одним із тегів: type:fix, type:features, type:documentation, type:tests, type:config.

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Авто-анотування пулл-реквестів

Якщо ми торкнулися такої теми як ефективна робота з пулл-реквестами, то варто сказати ще про такий екшен, як labeler, він проставляє мітки в PR на підставі того, які файли були змінені. Наприклад, ми можемо позначити як [build] будь-який пул-реквест у якому є зміни в каталозі .github/workflow.

Підключити його досить просто:

name: "Auto-assign themes to PR"

on:
  - pull_request

jobs:
  triage:
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/labeler@v2
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}

Ще нам знадобиться файл із описом відповідності каталогів проекту з тематиками пулл-реквестів:

theme:build:
  - ".github/**"
  - "pom.xml"
  - ".travis.yml"
  - ".gitignore"
  - "Dockerfile"

theme:code:
  - "src/main/*"

theme:tests:
  - "src/test/*"

theme:documentation:
  - "docs/**"

theme:TRASH:
  - ".idea/**"
  - "target/**"

Подружити дію, що автоматично проставляє мітки в пулл-реквести і дію, що перевіряє наявність обов'язкових міток, у мене не вийшло, match-label на відріз не хоче бачити проставлені ботом мітки. Схоже простіше написати свою дію, що поєднує обидва етапи. Але навіть у такому вигляді користуватися досить зручно, потрібно вибрати мітку зі списку під час створення пулл-реквесту.

Пора деплоїти

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Я спробував кілька варіантів деплою через GitHub Actions (через ssh, через scp і за допомогою docker-hub), і можу сказати, що, швидше за все, ви знайдете спосіб залити бінарку на сервер, яким би збоченим не був ваш pipeline.

Мені сподобався варіант тримати всю інфраструктуру в одному місці, тому розглянемо, як зробити деплою у GitHub Packages (це репозиторій для бінарного контенту, npm, jar, docker).

Cкприпт складання docker образу та публікації його в GitHub Packages:

name: Deploy docker image

on:
  push:
    branches:
      - 'master'

jobs:

  build_docker_image:
    runs-on: ubuntu-18.04
    steps:

#     Build JAR:
      - uses: actions/checkout@v1
      - name: set up JDK 11
        uses: actions/setup-java@v1
        with:
          java-version: 1.11
      - name: Maven Package
        run: mvn -B clean compile package -DskipTests

#     Set global environment variables:
      - name: set global env
        id: global_env
        run: |
          echo "::set-output name=IMAGE_NAME::${GITHUB_REPOSITORY#*/}"
          echo "::set-output name=DOCKERHUB_IMAGE_NAME::docker.pkg.github.com/${GITHUB_REPOSITORY}/${GITHUB_REPOSITORY#*/}"

#     Build Docker image:
      - name: Build and tag image
        run: |
          docker build -t "${{ steps.global_env.outputs.DOCKERHUB_IMAGE_NAME }}:latest" -t "${{ steps.global_env.outputs.DOCKERHUB_IMAGE_NAME }}:${GITHUB_SHA::8}" .

      - name: Docker login
        run: docker login docker.pkg.github.com -u $GITHUB_ACTOR -p ${{secrets.GITHUB_TOKEN}}

#     Publish image to github package repository:
      - name: Publish image
        env:
          IMAGE_NAME: $GITHUB_REPOSITORY
        run: docker push "docker.pkg.github.com/$GITHUB_REPOSITORY/${{ steps.global_env.outputs.IMAGE_NAME }}"

Для початку нам треба зібрати JAR-файл нашої програми, після чого ми обчислюємо шлях до GitHub docker registry та назву нашого образу. Тут є кілька хитрощів, з якими ми ще не стикалися.

  • конструкція виду: echo "::set-output name=NAME::VALUE" дозволяє задати значення змінної в поточному кроці, так щоб його потім можна було прочитати у всіх інших кроках.
  • отримати значення змінної, встановленої на попередньому кроці, можна через ідентифікатор цього кроку: ${{ steps.global_env.outputs.DOCKERHUB_IMAGE_NAME }}
  • У стандартній змінній GITHUB_REPOSITORY зберігається назва репозиторію та його власник (owner/repo-name). Для того, щоб вирізати з цього рядка все, крім назви репозиторію, скористаємося bash синтаксисом: ${GITHUB_REPOSITORY#*/}

Далі нам потрібно зібрати докер-образ:

docker build -t "docker.pkg.github.com/antkorwin/github-actions/github-actions:latest"

Авторизуватися в registry:

docker login docker.pkg.github.com -u $GITHUB_ACTOR -p ${{secrets.GITHUB_TOKEN}}

І опублікувати образ у GitHub Packages Repository:

docker push "docker.pkg.github.com/antkorwin/github-actions/github-actions"

Для того щоб вказати версію образу, ми використовуємо перші цифри з SHA-хеша комміта - GITHUB_SHA тут теж є нюанси, якщо ви робитимете такі зборки не тільки при merge в master, а ще й за подією створення пулл-реквесту, то SHA може не збігатися з хеш, який ми бачимо в історії гіта, тому що дія actions/checkout робить свій унікальний хеш, щоб уникнути взаємних блокувань дій у PR.

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Якщо все вийшло благополучно, то відкривши розділ packages (https://github.com/antkorwin/github-actions/packages) у репозиторії, ви побачите новий докер образ:

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Там же можна переглянути список версій докер-образу.

Залишається тільки налаштувати наш сервер працювати з цим registry і запустити перезапуск сервісу. Про те, як це зробити через systemd, я, мабуть, розповім в інший раз.

моніторинг

Давайте подивимося нескладний варіант, як робити health check нашої програми за допомогою GitHub Actions. У нашому бутовому додатку є actuator, так що API для перевірки його стану навіть писати не треба, для лінивих вже все зробили. Потрібно тільки смикнути хост: SERVER-URL:PORT/actuator/health

$ curl -v 127.0.0.1:8080/actuator/health

> GET /actuator/health HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.61.1
> Accept: */*

< HTTP/1.1 200
< Content-Type: application/vnd.spring-boot.actuator.v3+json
< Transfer-Encoding: chunked
< Date: Thu, 04 Jun 2020 12:33:37 GMT

{"status":"UP"}

Все, що нам потрібно — написати таск перевірки сервера по крону, а якщо раптом він нам не відповість, то надсилатимемо повідомлення в телеграм.

Для початку розберемося, як запустити workflow по крону:

on:
  schedule:
    - cron:  '*/5 * * * *'

Все просто, навіть не віриться, що в гітхабі можна зробити такі івенти, які зовсім не вкладаються в webhook-і. Деталі є в документації: help.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule

Перевірку статусу сервера зробимо руками через curl:

jobs:
  ping:
    runs-on: ubuntu-18.04
    steps:

      - name: curl actuator
        id: ping
        run: |
          echo "::set-output name=status::$(curl ${{secrets.SERVER_HOST}}/api/actuator/health)"

      - name: health check
        run: |
          if [[ ${{ steps.ping.outputs.status }} != *"UP"* ]]; then
            echo "health check is failed"
            exit 1
          fi
          echo "It's OK"

Спочатку зберігаємо в змінну те, що відповів сервер на запит, на наступному кроці перевіряємо що статус UP і якщо це не так, то виходимо з помилкою. Якщо потрібно руками «завалити» дію, то вихід 1 - Відповідна зброя.

  - name: send alert in telegram
    if: ${{ failure() }}
    uses: appleboy/telegram-action@master
    with:
      to: ${{ secrets.TELEGRAM_TO }}
      token: ${{ secrets.TELEGRAM_TOKEN }}
      message: |
        Health check of the:
        ${{secrets.SERVER_HOST}}/api/actuator/health
        failed with the result:
        ${{ steps.ping.outputs.status }}

Відправлення в телеграм робимо тільки якщо дія завалилася на попередньому кроці. Для надсилання повідомлення використовуємо appleboy/telegram-action, про те, як отримати токен бота та id чату можна почитати в документації: github.com/appleboy/telegram-action

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Не забудьте прописати в секретах на гітхабі: URL для сервера та токени для телеграм бота.

Бонус трек - JIRA для лінивих

Я обіцяв що ми повернемося до JIRA, та ми повернулися. Сотні разів спостерігав на стендапах ситуацію, коли розробники зробили фічу, злили гілку, але забули перетягнути завдання у JIRA. Звичайно, якби все це робилося в одному місці, то було б простіше, але фактично ми пишемо код в IDE, зливаємо гілки в bitbucket або GitHub, а завдання потім тягаємо в Jira, для цього треба відкривати нові вікна, іноді ще раз логінуватися і і т.д. Коли ти чудово пам'ятаєш, що треба робити далі, то відкривати борду вкотре немає сенсу. У результаті вранці на стендапі треба витрачати час на актуалізацію дошки завдань.

GitHub допоможе нам і в цьому рутинному занятті, спочатку ми можемо перетягувати завдання автоматично, в колонку code_review, коли закинули пулл-реквест. Все, що потрібно — це дотримуватись угоди у найменуванні гілок:

[имя проекта]-[номер таска]-название

наприклад, якщо ключ проекту GitHub Actions буде GA, то GA-8-jira-bot може бути гілкою для реалізації задачі GA-8.

Інтеграція з JIRA працює через екшен від Atlassian, вони не ідеальні, треба сказати, що деякі з них у мене взагалі не заробили. Але ми обговоримо лише ті, що точно працюють та активно використовуються.

Для початку потрібно пройти авторизацію в JIRA за допомогою дії: atlassian/gajira-login

jobs:
  build:
    runs-on: ubuntu-latest
    name: Jira Workflow
    steps:
      - name: Login
        uses: atlassian/gajira-login@master
        env:
          JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
          JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
          JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}

Для цього треба отримати токен у JIRA, як це зробити розписано тут: confluence.atlassian.com/cloud/api-tokens-938839638.html

Виокремлюємо ідентифікатор задачі з назви гілки:

  - name: Find Issue
    id: find_issue
    shell: bash
    run: |
      echo "::set-output name=ISSUE_ID::$(echo ${GITHUB_HEAD_REF} | egrep -o 'GA-[0-9]{1,4}')"
      echo brach name: $GITHUB_HEAD_REF
      echo extracted issue: ${GITHUB_HEAD_REF} | egrep -o 'GA-[0-9]{1,4}'

  - name: Check Issue
    shell: bash
    run: |
      if [[ "${{steps.find_issue.outputs.ISSUE_ID}}" == "" ]]; then
        echo "Please name your branch according to the JIRA issue: [project_key]-[task_number]-branch_name"
        exit 1
      fi
      echo succcessfully found JIRA issue: ${{steps.find_issue.outputs.ISSUE_ID}}

Якщо пошукати в GitHub marketplace, то можна знайти дію для цього завдання, але мені довелося написати те саме через grep за назвою гілки, тому що ця дія від Atlassian ні в яку не захотіла працювати на моєму проекті, розбиратися, що там не так. довше, ніж зробити руками те саме.

Залишилося тільки перемістити завдання до колонки Code review при створенні пулл-реквесту:

  - name: Transition issue
    if: ${{ success() }}
    uses: atlassian/gajira-transition@master
    with:
      issue: ${{ steps.find_issue.outputs.ISSUE_ID }}
      transition: "Code review"

Для цього є спеціальна дія на GitHub, все, що йому потрібно, — це ідентифікатор завдання, отриманий на попередньому кроці та авторизація в JIRA, яку ми робили вище.

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Так само можна перетягувати завдання при merge в майстер, та інших подіях з GitHub workflow. Загалом, все залежить від вашої фантазії та бажання автоматизувати рутинні процеси.

Висновки

Якщо подивитися на класичну діаграму DEVOPS, то ми покрили всі етапи, хіба що крім operate, думаю, якщо постаратися, то можна знайти якийсь екшен у маркеті для інтеграції з help-desk системою, так що вважатимемо що pipeline вийшов ґрунтовний і на на підставі його використання можна зробити висновки.

Кола пекла з GitHub Actions (будуємо CI/CD pipeline для Java-проекту)

Плюси:

  • Marketplace з готовими діями на всі випадки життя, це дуже круто. У більшості з них ще й вихідники можна подивитися, щоб зрозуміти, як вирішити схоже завдання або запостити feature request автору прямо в гітхаб репозиторії.
  • Вибір цільової платформи для збирання: Linux, mac os, windows досить цікава фіча.
  • Github Packages чудова річ, тримати всю інфраструктуру в одному місці зручно, не треба серфити по різних віконцях, все в радіусі одного-двох кліків миші та чудово інтегровано з GitHub Actions. Підтримка docker registry у безкоштовній версії – це також гарна перевага.
  • GitHub ховає секрети в логах складання, тому користуватися ним для зберігання паролів і токенів не так вже й страшно. За весь час експериментів мені не вдалося жодного разу побачити секрет у чистому вигляді у консолі.
  • Безкоштовний для Open Source проектів

Мінуси:

  • YML, ну, не люблю я його. При роботі з таким флоу у мене найчастіший commit message це "fix yml format", то забудеш десь таб поставити, то не на тому рядку напишеш. Загалом, сидіти перед екраном з транспортиром і лінійкою не найприємніше заняття.
  • DEBUG, налагоджувати флоу коммітами, запуском перескладання та виведенням у консоль не завжди зручно, але це більше з розряду «ви зажерлися», звикли працювати зі зручними IDEA, коли можна налагоджувати все, що завгодно.
  • Свій екшен можна написати на будь-що якщо загорнути його в докер, але нативно підтримується тільки javascript, звичайно це справа смаку, але я б віддав перевагу щось інше замість js.

Нагадаю, що репозиторій зі всіма скриптами тут: github.com/antkorwin/github-actions

Наступного тижня я виступатиму з доповіддю на конференції Heisenbug 2020 Piter. Розповім не тільки, як уникнути помилок під час підготовки тестових даних, але й поділюся своїми секретами роботи з наборами даних у Java-додатках!

Джерело: habr.com