CI/CD для Go проектов: GitHub Actions продвинутый уровень

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Продвинутый CI/CD для Go проектов с GitHub Actions

Автоматизация сборки, тестирования и развертывания — основа современной Go-разработки. Базовые пайплайны хороши для старта, но когда проект растет, требуются продвинутые техники: кэширование зависимостей, параллельные джобы, матричные сборки под разные ОС и архитектуры, публикация артефактов в Docker Hub и умный деплой. В этой статье мы разберем, как настроить GitHub Actions для Go-проекта на профессиональном уровне.

1. Кэширование Go-модулей и бинарников

Каждый запуск пайплайна может скачивать десятки мегабайт зависимостей. Чтобы ускорить процесс, используем встроенное кэширование GitHub Actions для go mod и кэша сборки.

name: Go CI (продвинутый)
on: [push, pull_request]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Установка Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.22'

      - name: Кэширование Go-модулей
        uses: actions/cache@v4
        with:
          path: |
            ~/go/pkg/mod
            ~/.cache/go-build
          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
          restore-keys: |
            ${{ runner.os }}-go-

      - name: Загрузка зависимостей
        run: go mod download

      - name: Линтер (golangci-lint)
        uses: golangci/golangci-lint-action@v6
        with:
          version: latest

      - name: Тесты с покрытием
        run: go test -v -race -coverprofile=coverage.out ./...

      - name: Сборка бинарника
        run: go build -o myapp ./cmd/app

Ключ hashFiles('**/go.sum') инвалидирует кэш только при изменении зависимостей. Кэш сборки (~/.cache/go-build) сохраняет скомпилированные объекты, ускоряя пересборку.

2. Матричные сборки: тестирование под разные версии Go и ОС

Go-проекты часто должны работать на Linux, macOS и Windows, а также поддерживать несколько версий языка. Матрица (matrix strategy) позволяет запускать параллельные джобы для каждой комбинации.

jobs:
  matrix-test:
    strategy:
      matrix:
        go-version: ['1.21', '1.22', '1.23']
        os: [ubuntu-latest, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - name: Установка Go ${{ matrix.go-version }}
        uses: actions/setup-go@v5
        with:
          go-version: ${{ matrix.go-version }}
      - name: Тесты
        run: go test ./...

Этот подход выявляет проблемы совместимости на разных платформах. Для Windows может потребоваться дополнительная настройка путей и переносов строк. Добавьте fail-fast: false, чтобы остальные джобы продолжали работу, даже если одна упала.

3. Публикация Docker-образа и GitHub Release

После успешного тестирования логично опубликовать артефакты: Docker-образ в Docker Hub (или GitHub Container Registry) и бинарник в GitHub Release. Рассмотрим оба сценария.

Публикация Docker-образа

Создадим джобу, которая запускается только после тестов и только при пуше в main или при создании тега.

jobs:
  docker:
    needs: [build-and-test]
    if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Логин в Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Сборка и пуш образа
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            ${{ secrets.DOCKER_USERNAME }}/myapp:latest
            ${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.sha }}

Не забудьте создать Dockerfile в корне проекта. Для Go-приложений часто используют multi-stage сборку, чтобы образ был минимальным.

Создание GitHub Release

Для бинарных артефактов используем softprops/action-gh-release. Сначала собираем бинарники под разные платформы с помощью go build с указанием GOOS и GOARCH.

jobs:
  release:
    needs: [build-and-test]
    if: startsWith(github.ref, 'refs/tags/v')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.22'

      - name: Сборка под Linux и macOS
        run: |
          GOOS=linux GOARCH=amd64 go build -o myapp-linux ./cmd/app
          GOOS=darwin GOARCH=amd64 go build -o myapp-darwin ./cmd/app

      - name: Создание релиза
        uses: softprops/action-gh-release@v2
        with:
          files: |
            myapp-linux
            myapp-darwin
          generate_release_notes: true

Теперь при пуше тега вида v1.2.3 автоматически создается релиз с бинарниками и заметками из коммитов.

4. Условный деплой и окружения

Продвинутый пайплайн должен уметь деплоить в разные окружения (staging, production) в зависимости от ветки или тега. Используем GitHub Environments для защиты sensitive-данных.

jobs:
  deploy:
    needs: [docker]
    runs-on: ubuntu-latest
    environment:
      name: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
      url: ${{ steps.deploy.outputs.url }}
    steps:
      - name: Деплой на сервер
        run: |
          # Пример: SSH-команда для обновления контейнера
          ssh user@server "docker pull myapp:latest && docker compose up -d"

Для staging можно использовать отдельный сервер или ветку develop. В секции environment можно настроить обязательные ревьюверов и тайм-ауты — это защитит продакшн от случайного деплоя.

Заключение

Продвинутый CI/CD с GitHub Actions для Go-проектов — это

Блоги

Рекомендаций по книгам