Введение: Почему CI/CD — стандарт современной Java-разработки
В мире Java-разработки скорость и качество поставки кода критичны. Каждый день команды вносят сотни изменений, и без автоматизации процесс интеграции превращается в хаос. CI/CD (Continuous Integration / Continuous Deployment) решает эту проблему: код автоматически собирается, тестируется и разворачивается на серверах.
Инструмент GitHub Actions — встроенное решение для CI/CD прямо в репозитории. Он позволяет создавать пайплайны (workflows) на YAML, которые реагируют на push, pull request или другие события. В этой статье мы разберём полный цикл настройки CI/CD для Java-проекта: от базового билда до деплоя в облако.
Вы узнаете, как ускорить разработку, избежать ошибок и автоматизировать рутину. Поехали!
1. Основы GitHub Actions: структура workflow
Что такое GitHub Actions?
GitHub Actions — это платформа для автоматизации рабочих процессов. Workflow (рабочий процесс) — это набор шагов, которые выполняются при наступлении события (например, push в ветку main). Каждый workflow состоит из:
- Event — триггер (push, pull_request, schedule).
- Jobs — задачи, которые выполняются на виртуальных машинах (runner).
- Steps — конкретные действия (запуск скрипта, установка зависимостей).
Для Java-проекта типичный workflow включает: загрузку кода, установку JDK, сборку Maven/Gradle, запуск тестов и публикацию артефактов.
Создание первого workflow для Java
Создайте в корне репозитория папку .github/workflows/ и файл ci.yml. Вот минимальный пример для Maven-проекта:
name: Java CI with Maven
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Maven
run: mvn clean compile
- name: Run tests
run: mvn test
Этот workflow запускается при push или pull request в main. Он проверяет, что код компилируется и тесты проходят. Если тест падает — workflow завершается ошибкой, и вы получаете уведомление.
2. Продвинутая настройка: кэширование, матрицы и артефакты
Кэширование зависимостей
Maven и Gradle каждый раз скачивают зависимости заново — это медленно. GitHub Actions поддерживает кэширование. Добавьте шаг с actions/cache:
- name: Cache Maven packages
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
Ключ кэша основан на хеше pom.xml. Если файл не менялся — зависимости восстанавливаются из кэша, время сборки сокращается в 2-3 раза.
Матрица сборок (Matrix Build)
Java-проекты часто тестируют на нескольких версиях JDK и ОС. Используйте стратегию matrix:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
java: [11, 17, 21]
steps:
- uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: 'temurin'
- name: Test with Maven
run: mvn test
GitHub создаст 3 параллельных джоба — для Java 11, 17 и 21. Это гарантирует совместимость кода с разными версиями JDK.
Сохранение артефактов
После сборки JAR-файл можно сохранить как артефакт, чтобы скачать его вручную или использовать в следующем джобе:
- name: Upload JAR artifact
uses: actions/upload-artifact@v4
with:
name: my-app-${{ github.sha }}
path: target/*.jar
3. Автоматизация деплоя: от сборки до продакшена
Деплой на сервер через SSH
Допустим, у вас есть VPS. Добавьте секреты в репозиторий (Settings → Secrets → Actions): SSH_HOST, SSH_USER, SSH_KEY. Workflow для деплоя:
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Build JAR
run: mvn package -DskipTests
- name: Deploy to server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
source: "target/*.jar"
target: "/opt/myapp/"
- name: Restart service
uses: appleboy/ssh-action@v1.1.0
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
systemctl restart myapp
Этот workflow копирует JAR на сервер и перезапускает сервис. Важно: используйте needs: build, чтобы сначала пройти тесты.
Деплой в Docker Hub и на Kubernetes
Для контейнеризации добавьте шаг сборки Docker-образа и отправки в Docker Hub:
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
push: true
tags: myuser/myapp:${{ github.sha }}
Для Kubernetes используйте kubectl или Helm: обновите образ в deployment-файле и примените изменения.
4. Безопасность и лучшие практики
Секреты и переменные окружения
Никогда не хардк