CI/CD для Go проектов: Настройка GitHub Actions

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

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

Начать курс

Введение: Почему CI/CD важен для Go проектов

Современная разработка на Go (Golang) требует не только написания чистого и эффективного кода, но и настройки процессов, которые автоматизируют проверку, сборку и доставку приложений. CI/CD (Continuous Integration / Continuous Delivery) — это набор практик, позволяющий быстро и безопасно поставлять изменения в продакшн. Для Go-разработчиков GitHub Actions стал одним из самых популярных инструментов благодаря тесной интеграции с репозиториями и простоте настройки.

В этой статье мы разберём, как создать полноценный CI/CD пайплайн для Go-проекта с использованием GitHub Actions. Вы узнаете, как автоматизировать тестирование, сборку бинарных файлов и деплой на сервер. Все примеры будут на Go (Golang) с практическими шагами.

1. Основы GitHub Actions для Go

GitHub Actions — это встроенная система автоматизации рабочих процессов (workflows). Каждый workflow представляет собой YAML-файл, который описывает шаги сборки, тестирования и развёртывания. Для Go-проектов минимальный пайплайн включает:

  • Установку Go
  • Кэширование зависимостей
  • Запуск тестов
  • Сборку приложения

Структура workflow-файла

Создайте в корне репозитория директорию .github/workflows/ и файл ci.yml. Вот базовая конфигурация для Go:

name: CI для Go проекта

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

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

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

      - name: Линтинг кода
        run: go vet ./...

      - name: Запуск тестов
        run: go test -v -race -coverprofile=coverage.out ./...

      - name: Сборка бинарного файла
        run: go build -o myapp ./cmd/main.go

Этот workflow запускается при пуше в main или develop, а также при создании pull request. Он проверяет код на ошибки, запускает тесты с флагом race (детектор гонок данных) и собирает бинарник.

2. Расширенный пайплайн: тестирование и качество кода

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

Добавление golangci-lint

golangci-lint — это агрегатор линтеров, который включает в себя go vet, errcheck, staticcheck и другие. Добавим его в workflow:

      - name: Установка golangci-lint
        uses: golangci/golangci-lint-action@v4
        with:
          version: latest

      - name: Запуск линтера
        run: golangci-lint run ./...

Отчёт о покрытии кода

Покрытие тестами — важный метрика качества. GitHub Actions может генерировать отчёты и даже блокировать PR при низком покрытии:

      - name: Генерация отчёта о покрытии
        run: go test -coverprofile=coverage.out -covermode=atomic ./...

      - name: Проверка минимального покрытия
        run: |
          go tool cover -func=coverage.out | grep total | awk '{print $3}' | sed 's/%//' > coverage.txt
          if [ $(cat coverage.txt) -lt 70 ]; then
            echo "Покрытие кода меньше 70%"
            exit 1
          fi

Теперь workflow будет падать, если покрытие тестами падает ниже 70%. Это отличная практика для поддержания качества Go-проекта.

3. Сборка и публикация Docker-образа

Go-приложения часто деплоятся в виде Docker-контейнеров. GitHub Actions позволяет автоматически собирать образы и публиковать их в Docker Hub или GitHub Container Registry.

Сборка Docker-образа в CI

Сначала создайте Dockerfile в корне проекта:

FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp ./cmd/main.go

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/myapp .
EXPOSE 8080
CMD ["./myapp"]

Теперь добавим шаг сборки и публикации в workflow. Для аутентификации используем секреты GitHub:

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

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

Также можно использовать GitHub Container Registry (ghcr.io). Для этого измените логин на docker.pkg.github.com и используйте токен GitHub.

4. Деплой на сервер через SSH

Финальный этап — развёртывание приложения на production-сервере. GitHub Actions поддерживает деплой через SSH, что удобно для небольших Go-проектов.

Настройка SSH-ключа

Добавьте приватный ключ в секреты репозитория (Settings → Secrets → Actions → New secret → SSH_PRIVATE_KEY). Публичный ключ должен быть добавлен на сервер в ~/.ssh/authorized_keys.

Шаг деплоя

      - name: Деплой на сервер
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /opt/myapp
            docker pull ${{ secrets.DOCKER_USERNAME }}/myapp:latest
            docker stop myapp || true
            docker rm myapp || true
            docker run -d --name myapp -p 8080:8080 \
              -e "DB_URL=${{ secrets.DB_URL }}" \                

Блоги

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