Введение: Зачем C++ проектам CI/CD?
Разработка на C++ традиционно ассоциируется с ручной сборкой, запуском тестов и кропотливым контролем версий. Однако в современной разработке, особенно при работе в команде, такой подход становится узким местом. CI/CD (Continuous Integration / Continuous Deployment) — это практика, которая автоматизирует процессы сборки, тестирования и развертывания кода. Для C++ проектов, где ошибки компиляции или линковки могут проявляться только на определенных платформах, CI/CD критически важен.
GitHub Actions — это мощный и гибкий инструмент, встроенный в GitHub, который позволяет создавать пайплайны прямо в репозитории. В этой статье мы разберем, как настроить CI/CD для C++ проекта с нуля, используя GitHub Actions. Вы узнаете, как автоматизировать сборку с CMake, запускать юнит-тесты, проверять качество кода и даже публиковать релизы.
К концу статьи вы сможете самостоятельно настроить пайплайн, который сэкономит часы ручной работы и повысит надежность вашего проекта.
Основная часть: Пошаговое руководство по GitHub Actions для C++
1. Основы GitHub Actions: Workflow, Jobs и Steps
Прежде чем писать код, давайте разберемся с терминологией. GitHub Actions основан на workflow (рабочих процессах), которые описываются в YAML-файлах внутри директории .github/workflows/. Каждый workflow состоит из одного или нескольких jobs (заданий), которые выполняются параллельно или последовательно. Каждый job состоит из steps (шагов) — отдельных команд или действий.
Для C++ проекта типичный workflow включает:
- Сборка (Build): компиляция проекта с помощью CMake и Make/Ninja.
- Тестирование (Test): запуск юнит-тестов (например, с помощью Google Test или Catch2).
- Линтинг (Lint): проверка кода статическими анализаторами (Clang-Tidy, Cppcheck).
- Деплой (Deploy): публикация артефактов или релизов.
Первый workflow обычно создается для базовой сборки на Ubuntu, но C++ требует проверки на разных ОС (Linux, macOS, Windows). GitHub Actions поддерживает все три платформы.
2. Создание первого workflow: сборка и тестирование
Создайте файл .github/workflows/ci.yml в корне вашего репозитория. Ниже приведен пример для проекта, использующего CMake и Google Test.
name: C++ CI/CD Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
build_type: [Debug, Release]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y cmake g++ ninja-build
- name: Install dependencies (macOS)
if: runner.os == 'macOS'
run: brew install cmake ninja
- name: Install dependencies (Windows)
if: runner.os == 'Windows'
run: choco install cmake ninja -y
- name: Configure CMake
run: cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
- name: Build
run: cmake --build build --config ${{ matrix.build_type }}
- name: Run tests
working-directory: build
run: ctest --output-on-failure -C ${{ matrix.build_type }}
Этот workflow:
- Запускается при пуше в
mainилиdevelop, а также при создании Pull Request. - Использует матрицу стратегий для сборки на трех ОС и в двух конфигурациях (Debug/Release).
- Устанавливает зависимости (CMake, Ninja) в зависимости от ОС.
- Конфигурирует, собирает проект и запускает тесты.
Обратите внимание на условие if: runner.os == '...' — это позволяет выполнять разные команды для разных платформ.
3. Продвинутые техники: кэширование, линтинг и деплой
Базовая сборка — это только начало. Для ускорения пайплайна и повышения качества кода используйте следующие техники.
Кэширование зависимостей
Каждый запуск workflow начинается с чистой среды, что замедляет установку больших библиотек (например, Boost или Qt). Используйте action actions/cache для кэширования скомпилированных зависимостей.
- name: Cache CMake build
uses: actions/cache@v3
with:
path: build
key: ${{ runner.os }}-cmake-${{ hashFiles('**/CMakeLists.txt') }}
Это сохранит папку build между запусками, если не изменились файлы CMakeLists.txt.
Линтинг с Clang-Tidy
Добавьте статический анализ кода. Для этого потребуется установить Clang-Tidy и настроить CMake для его использования.
- name: Static analysis (Clang-Tidy)
if: runner.os == 'Linux'
run: |
cmake -B build -DCMAKE_CXX_CLANG_TIDY="clang-tidy"
cmake --build build 2>&1 | tee clang-tidy-output.log
if grep -q "warning:" clang-tidy-output.log; then exit 1; fi
Этот шаг завершится ошибкой, если Clang-Tidy найдет предупреждения.
Автоматический деплой релизов
Если ваш проект публикует бинарные файлы, вы можете автоматизировать создание релизов при пуше тегов.
jobs:
release:
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build for release
run: |
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: build/myapp*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Этот job создает GitHub Release и загружает туда скомпилированные бинарники.
4. Отладка и оптимизация workflow
Работа с GitHub Actions не всегда проходит гладко. Вот несколько советов:
- Логи: