Технология внедрения непрерывной интеграции в крупных высоконагруженных системах с минимизацией ошибок и временных потерь со стороны разработчиков
Манаев Руслан Гайратович,
бакалавр, кафедра вычислительной математики и кибернетики Уфимский Государственный Авиационный Технический Университет, [email protected]
Целью работы является исследование и внедрение технологии непрерывной интеграции в крупных высоконагруженных системах. В работе демонстрируется конфигурирование и работа с технологией GitHub Actions на примере проекта, который использует язык программирования C++. Результат: Получена технология интеграции сервиса GitHub Actions в целях реализации непрерывной интеграции в высоконагруженных системах. Даны практические рекомендации и инструкции по сборке конвейера непрерывной интеграции, которая будет сохранять стабильность проекта - собираемость, тестируемость. В дополнение продемонстрирован способ проверки стиля кодирования кода. Практическая значимость: использование непрерывной интеграции минимизирует возникновение ошибок и временные потери со стороны разработчиков во время непосредственной разработки систем. Предоставленная технология может использоваться как малых, так и в крупных высоко-нагруженных системах.
Ключевые слова: непрерывная интеграция, автоматическое тестирование, высоконагруженные системы.
Введение
При создании программного обеспечения чаще всего разработка ведется с использованием систем контроля версий [1]. Широкое распространение получила система контроля версий Git [2]. Но вне зависимости от используемой системы контроля версий, для проверки корректности нового кода с большой долей вероятности будет использоваться технология непрерывной интеграции.
[3]
Непрерывная интеграция (CI, англ. Continuous Integration) - технология, которая позволяет автоматизировать сборку и тестирование рабочих копий программных систем для скорейшего выявления потенциальных дефектов и решения интеграционных проблем
[4]. В терминах системы контроля версий Git [5], рабочими копиями можно назвать ветки (branch), отведенные от основной, и которые ожидают тестирования системой непрерывной интеграции. Часто изменениями разработчиков нельзя дополнить основной проект пока система непрерывной интеграции не выдаст положительный вердикт.
Системы непрерывной интеграции могут являться отдельными сервисами, например AppVeyor, Travis CI, а могут присутствовать непосредственно в сервисах, которые предоставляют инфраструктуру для хранения Git репозиториев, например сервис GitHub предоставляет систему GitHub Actions для целей конфигурирования системы непрерывной интеграции.
Целью работы является исследование и внедрение технологии непрерывной интеграции в крупных высоконагруженных системах. В данной статье демонстрируется конфигурирование и работа с технологией GitHub Actions на примере проекта, который использует язык программирования C++.
Структура проекта
Проект, на примере которого будет демонстрироваться внедрение непрерывной интеграции, использует язык программирования C++ как основной и состоит из следующих компонентов: исполняемая программа, библиотека, состоящая из заголовочных файлов, статическая библиотека. В качестве системы сборки используется CMake, так как данная система сборки является наиболее распространенной [6]. Проект имеет заранее определенные toolchain файлы, которые определяют опции и используемые системой сборки компиляторы. Подразумевается, что проект возможно собрать на платформах Linux, Windows и Mac. Проект включает в себя следующие зависимости: Google Test - для тестирования проекта, Google Benchmark - для проведения замеров производительности кода, а также для сравнительного анализа, range-v3 - используется как пример подключения внешней библиотеки, состоящей только из заголовочных файлов.
X X
о го А с.
X
го m
о
2 О
м о
о es о es
о ш m
X
<
m О X X
К тому же, в проекте принято соглашение о кодировании Google Code Style, а для автоматизации форматирования в корне проекта размещен файл «.clang-format», с содержимым «BasedOnStyle: Google». Интеграция GitHub Actions
Сервис GitHub Actions позволяет определять действия над проектом, в качестве действий могут выступать: проверка собираемости кода, проверка соглашения о кодировании, запуск тестов и прочее. Действия определяются в специальных *.yml файлах, которые должны располагаться по пути «.github/workflows» относительно корня проекта.
Определим файл main.yml в котором опишем действие по сборке и тестированию проекта. Первое с чего начинается файл это определение имени действия: «name: main», если не указывать имя, то в качестве имени будет использоваться путь до определяемого файла «.github/workflows/main.yml».
Затем необходимо указать условие активации действия: «on: [push]», наше действие будет срабатывать каждый раз при отправке кода командой «git push». Действия также могут активироваться по расписанию или по активностям в проекте, например возможно сконфигурировать действие которое будет срабатывать при создание новой задачи (issue) в проекте или при комментировании во время ревью кода.
В дальнейшем следует описание заданий (jobs) и шагов выполнения (steps), полный листинг кода main.yml: name: main
on: [push]
jobs:
build:
strategy:
matrix:
os:
- ubuntu-latest toolchain:
- linux_clang
- linux_clang_asan
- linux_clang_lsan
- linux_clang_tsan
- linux_clang_ubsan
- linux_gcc build_type:
- Debug include:
- os: macos-latest toolchain: macos_clang build_type: Debug
- os: windows-latest toolchain: windows_msvc build_type: Debug
- os: ubuntu-latest toolchain: linux_clang build_type: Release
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Bootstrap toolchain ${{ matrix.toolchain }} if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo python matrix.toolchain }}
.github/workflows/bootstrap.py ${{
- name: Configure ${{ matrix.build_type }}
run: cmake -S . -B .build -DCMAKE_TOOLCHAIN_FILE="toolchain/${{ matrix.toolchain }}.cmake" -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
- name: Build
run: cmake --build .build --parallel 8
- name: Test
run: (cd .build && ctest --extra-verbose) Листинг 1. Файл «main.yml».
Задания могут обозначаться произвольным идентификатором, в нашем случае «build». Далее идет определение сборочной матрицы, которая необходима для параметризации действия. В сборочной матрице определяются следующие параметры: os - операционная система, на которой выполняется задача; toolchain - набор инструментов для CMake, данный параметр определяет конфигурацию компиляторов и опций проекта, а также целевую платформу; build_type - тип сборки.
По умолчанию параметр os определяется как ubuntu-latest, что обеспечит запуск действия на актуальной версии ubuntu.
Параметр toolchain, определяет такие значения, как например linux_clang и linux_gcc, что позволяет собирать проект с компиляторами clang и gcc. Собирать проект на разных компиляторах крайне полезно, так как компиляторы имеют встроенные статические анализаторы кода, устройство которых различно. Не стоит забывать о том, что в компиляторах могут присутствовать дефекты или они могут по-разному интерпретировать стандарт C++. В проекте заданы дополнительные сборки санитайзеров [7]: asan, lsan, tsan, ubsan. Сани-тайзеры осуществляют динамический анализ кода, что положительно влияет на качество кода.
По умолчанию параметр build_type определяется как Debug, что обеспечивает сборку проекта в режиме отладки.
Матрица дополняется параметрами, которые сконфигурированы для запуска на Mac и Windows, в которых выбирается соответствующий toolchain. В добавок сконфигурирован запуск, в котором параметр build_type равен Release, для дополнительной проверки собираемости проекта в данном режиме.
Следующей строкой «runs-on: ${{ matrix.os }}» определяется операционная система, исполняющая задание. Название операционной системы подставляется непосредственно из сборочной матрицы.
Далее проводится определение шагов выполнения задания.
Шаги могут использовать действия, например «uses: actions/checkout@v2» будет запускать действие, исходный код которого располагается в репозитории «https://github.com/actions/checkout». С помощью «with» такие действия возможно конфигурировать. Кроме того, шагам можно задавать имя используя «name», задавать непосредственную команду исполнения используя «run» и задавать условный шаг используя «if». Рассмотрим каждый шаг подробнее:
Шаг «uses: actions/checkout@v2» производит работу по выкачиванию тестируемого кода.
Шаг «name: Bootstrap toolchain ${{ matrix.toolchain }}» выполняет установку компиляторов и инструментов необходимых для toolchain. Например, linux_clang, требует компилятор clang-12, который отсутствует в окружении, но благодаря данному шагу необходимый компилятор будет установлен. Так как выполнение данного шага необходимо только на платформе Linux, реализовано условное выполнение данного шага с помощью «if: ${{ matrix.os == 'ubuntu-latest' }}». Установка необходимого окружения происходит с помощью скрипта «bootstrap.py», в который пробрасывается toolchain в качестве аргумента параметра.
Шаг «name: Configure ${{ matrix.build_type }}» выполняет конфигурирование проекта с помощью системы сборки CMake. Параметр «-S» задает расположение исходных кодов. Параметр «-B» задает директорию, в которой необходимо сконфигурировать проект для последующей сборки. Параметр «-DCMAKE_TOOLCHAIN_FILE=» задает используемый toolchain.
Шаг «name: Build» выполняет сборку с помощью системы сборки CMake. Параметр «--build» задает расположение сконфигурированного проекта для сборки и запускает сборку проекта. Параметр «--parallel» определяет максимальное количество параллельных процессов при сборке проекта.
Шаг «name: Test» выполняет тестирование проекта с помощью утилиты CTest.
Таким образом будет сгенерировано 9 задач, которые соберут и протестируют проект на разных целевых платформах:
в Improve Cl {#1)
».IT*. ф 4 BÜVdH
main
✓ (ubuntu .¡¡t-,: I -Iji Hi i 'II'I .Villi::-, r r ■S IvJ'i ti n: L? in,:. I:-! i i nil
OS completed jobs in 3m 6s
v buJd(ubu(vtu tsT«Llirvji!.c(nri9... Anitocii
V buJd (ubupitu Lalrti I '^i■ r! i v| ■S buW l.x.ni. |мея I nw 'Y-'. 0
•S KJl' *"':!, Ill lllll "IIII 11 '|J
•J build iLSindort'.-ia tt:[ ■J huHd tin' It'r i:. l-i»
Рис 1. Результат запуска CI.
Проверка стиля кодирования
Помимо сборки и тестирования кода, можно выполнять проверку стиля кодирования. Данное действие необходимо, чтобы обеспечить единообразие стиля кодирования в проекте. Для этого создадим файл «clang_format_lintyml» в той же папке «.github/workflows» со следующим содержимым:
name: clang_format_lint
on: [push]
jobs: build:
runs-on: ubuntu-latest steps:
- uses: actions/checkout@v2
- uses: DoozyX/[email protected] with:
clangFormatVersion: 11 Листинг 2. Файл «clang_format_lint.yml».
Данная задача не требует запуска на разных платформах, поэтому здесь отсутствует сборочная матрица. В качестве платформы запуска используется ubuntu-latest, как наиболее быстрая платформа.
В шагах присутствует уже знакомое действе «uses: actions/checkout@v2», которые выкачивает код проекта. Далее используется действие «uses: DoozyX/[email protected]», которое параметризуется с помощью ключа «clangFormatVersion: 11». Данный шаг использует утилиту clang-format [8] для проверки соблюдения стиля кодирования. Ключ clangFormatVersion задает версию используемой утилиты.
Таким образом будет сгенерирована задача по проверке стиля о кодировании.
Вывод
Получена технология интеграции сервиса GitHub Actions в целях реализации непрерывной интеграции в высоконагруженных системах. Продемонстрированы способы конфигурирования сервиса: для запуска статического и динамического анализа кода систем, для запуска проверки стиля кодирования.
Литература
1. Loeliger J., McCullough M. Version Control with Git: Powerful tools and techniques for collaborative software developmen. // O'Reilly Media, Inc. 2012.
2. Compare Repositories // Synopsys. Black Duck Open Hub [Электронный ресурс]. URL: https://www.openhub.net/repositories/compare (дата обращения 28.11.2020).
3. Файзрахманов Р.А., Мурзакаев Р.Т., Брюханова А.А., Командная разработка и непрерывная интеграция в системах автоматизированного проектирования фигурного раскроя // Научное обозрение. 2015. № 1. С. 95-101.
4. Дюваль П. М., Матиас С. М., Гловер Э. Непрерывная интеграция: улучшение качества программного обеспечения и снижение риска // ООО «И.Д. Вильямс». 2008.
5. Loeliger J., McCullough M., Version Control with Git: Powerful tools and techniques for collaborative software development // O'Reilly Media, Inc. 2012.
6. Makeev A., CMake vs. the others, round 1 // JetBrains Blog. 2014. [Электронный ресурс]. URL: https://blog.jetbrains.com/clion/2014/09/cmake-vs-the-others-round-1/ (дата обращения 28.11.2020).
7. V'yukova N.I., Galatenko V.A., Samborskii S.V., Dynamic Program Analysis Tools in GCC and CLANG Compilers // Programming and Computer Software. 2020. № 46(4). С. 281-296.
8. Lippuner J., C++ Introduction and Best Practices // Los Alamos National Lab. (LANL), Los Alamos, NM (United States). 2019.
Technology of introducing continuous integration in large high-load systems with minimizing errors and time losses on the part of developers Manaev R.G.
Ufa State Aviation Technical University
The aim of this work is to research and implement continuous integration technology in large high-load systems. This paper demonstrates how to configure and work with GitHub Actions technology using the example of a project that uses the
X X О го А С.
X
го m
о
2 О M
о
C++programming language. Result: github Actions integration technology has been Developed to implement continuous integration in high-load systems. Practical recommendations and instructions are given for building a continuous integration pipeline that will maintain the stability of the project -assemblability, testability. In addition, a method for checking the coding style of the code is demonstrated. Practical significance: the use of continuous integration minimizes the occurrence of errors and time losses on the part of developers during the direct development of systems. The provided technology can be used in both small and large high-load systems.
Key words: Continuous Integration, automatic testing, high-load systems.
References
1. Loeliger J., McCullough M. Version Control with Git: Powerful
tools and techniques for collaborative software developmen. // O'Reilly Media, Inc. 2012.
2. Compare Repositories // Synopsys. Black Duck Open Hub [Communication networks of special purpose]. URL: https://www.openhub.net/repositories/compare (accessed 28 November 2020).
3. Faizrakhmanov R.A., Murzakaev R.T., Bryukhanova A.A., Team
development and continuous integration in the systems of automated design of shape nesting // Scientific review. 2015. 1. pp. 95-101. (in Russian).
4. Duvall P.M., Matyas S., Glover, A., Continuous integration: improving software quality and reducing risk. // Pearson Education. 2007.
5. Loeliger J., McCullough M., Version Control with Git: Powerful
tools and techniques for collaborative software development // O'Reilly Media, Inc. 2012.
6. Makeev A., CMake vs. the others, round 1 // JetBrains Blog. 2014.
[Communication networks of special purpose]. URL: https://blog.jetbrains.com/clion/2014/09/cmake-vs-the-others-round-1/ (accessed 28 November 2020).
7. V'yukova N.I., Galatenko V.A., Samborskii S.V., Dynamic Program Analysis Tools in GCC and CLANG Compilers // Programming and Computer Software. 2020. 46(4). pp. 281296.
8. Lippuner J., C++ Introduction and Best Practices // Los Alamos
National Lab. (LANL), Los Alamos, NM (United States). 2019.
o
CN O CN
O HI
m x
<
m o x
X