Часть 1, Часть 2
Давайте добавим Arduino Zero. Модифицируем часть программы, которая устанавливает ядро AVR, и добавляем другой код:
# Установка ядер Arduino
arduino-cli core install arduino:avr
arduino-cli core install arduino:samd
Давайте также поменяем код для компиляции наших скетчей:
# Компилируем все файлы с расширениями *.ino для Arduino Uno
for f in {,**/}*.ino ; do
arduino-cli compile -b arduino:avr:uno $f
arduino-cli compile -b arduino:samd:arduino_zero_native $f
done
Так вы автоматически проверите код на разных платформах и увидите, появятся ли ошибки.
Если добавить изменения и отправить их в репозиторий на GitHub, а потом перейти на вкладку Actions (Действия), то вы увидите свой новенький рабочий поток и его выходные данные:
При нажатии на название сборки вы увидите что-то подобное:
Если один из шагов закончится неудачно, вы можете нажать на его название и просмотреть подробную историю лога. Также будет полезно добавить дополнительный вывод скриптам оболочки, чтобы лучше понимать, что выполняется.
Автоматизированные сборки PlatformIO
Скрипт выше будет работать и для скетчей, и для библиотек Arduino со скетчами-образцами. Он не подходит для проектов PlatformIO. Для проектов такого типа рекомендуется создавать автоматизированные сборки с помощью интерфейса командной строки PlatformIO вместо аналога в Arduino.
С таким подходом вы сделаете непрерывную интеграцию для любого типа проектов из PlatformIO, а не только для проектов из Arduino. И это его самое большое преимущество. В целом этапы схожи. Добавляем шаг в build.yml
:
…
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build on PlatformIO
run: bash ci/build-platformio.sh
Теперь добавляем скрипт оболочки build-platformio.sh
:
MyPlatformIOProject
├── .github
│ └── workflows
│ └── build.yml
├── ci
│ └── build-platformio.sh
…
А дальше следуем инструкции по установке PlatformIO:
#!/bin/bash
# Немедленный выход, если у команды не нулевой статус
set -e
# Переход в рабочее пространство github
cd $GITHUB_WORKSPACE
# Устанавливаем PlatformIO CLI
export PATH=$PATH:~/.platformio/penv/bin
curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -o get-platformio.py
python3 get-platformio.py
Теперь устанавливаем платформы для тестирования:
# Устанавливаем платформу Atmel AVR
pio platform install "atmelavr"
Если вы корректно настроили platformio.ini
, вам осталось пройти всего один шаг:
# Компилируем проект
pio run
Как вариант — можно напрямую пойти в окружения, определённые в platformio.ini
:
# Компилируем проект для Uno
pio run -e uno
Вот и все. Процесс оказался ещё проще, чем при работе с Arduino CLI.
Укрепляем красивый стиль форматирования кода
Инструмент clang-format (CF) помогает проверять код на соответствие определенным правилам стиля форматирования в программах на C или C++.
Стилей программирования много — выбирайте тот, что вам ближе: LLVM, GNU, Google, Mozilla или Microsoft. Вы также можете настроить инструмент проверки CF, чтобы писать код в одном стиле. Просто выберите любой из них, если не можете решить. Наличие одного приоритетного стиля важнее, чем поиск идеального. Всегда можно изменить или переопределить его позже, а всю базу кода просто переформатировать.
Если вы работаете в VSC, вы можете добавить расширение, чтобы форматировать код при каждом сохранении файла. Тогда у вас больше не будет повода волноваться об этом. Все будет автоматизировано. Для других редакторов доступны похожие плагины. Я предлагаю добавлять в проект файл .clang-format
:
MyArduinoLibrary
├── .clang-format
…
Выберите основной стиль и конфигурируйте его в файле вместе с вашими конфигурационными опциями. Вот как выглядит мой .clang-format
:
BasedOnStyle: Google
Language: Cpp
IndentWidth: 4
AlignConsecutiveMacros: true
Не стесняйтесь изучать остальные возможности clang-format. У этого инструмента есть что предложить.
После добавления CF в проект вы также можете интегрировать его в свой конвейер сборок, чтобы проверить правильность форматирования в базе кода.
Чтобы этого достичь, создаём новый шаг Check clang-format conformity
в файле build.yml
. Предлагаю добавить его прямо после шага проверки (Checkout):
…
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Check clang-format conformity
run: bash ci/clang-lint.sh
- name: Build on Arduino CLI
run: bash ci/build-arduino.sh
Так запускается скрипт оболочки clang-lint.sh
. Добавляем в файл несколько строчек для установки clang-format:
#!/bin/bash
# Немедленный выход, если у команды не нулевой статус
set -e
# Включаем опцию оболочки globstar
shopt -s globstar
# Переходим в рабочее пространство github
cd $GITHUB_WORKSPACE
# Устанавливаем clang-format
sudo apt-get -y install clang-format-10
Теперь делаем цикл по всем исходным файлам с кодом. Проверяем, правильно ли отформатировано их содержимое:
# Проверка вывода clang-format
for f in {,**/}*.{h,c,hpp,cpp,ino} ; do
if [ -f "$f" ]; then
diff $f <(clang-format -assume-filename=main.cpp $f) 1>&2
fi
done
Здесь есть одна главная строчка:
diff $f <(clang-format -assume-filename=main.cpp $f) 1>&2
Она запускает работу CF над файлом и сравнивает вывод с текущим содержимым файла. Если они одинаковые, значит файл отформатирован правильно. Если они отличаются, значит цель ещё не достигнута.
Вывод команды diff
перенаправляется в stderr
, а это значит, что любой вывод считается ошибочным. Если файл отформатирован правильно, у diff
не будет вывода и не будет ошибок. Если вывод сборки будет неудачным, то вы увидите неверно форматированные строчки кода.
Очень рекомендую добавлять какой-либо вывод прямо после команды diff, чтобы лучше понимать, какие файлы проверяются. Например, вот так:
echo "Checking file ${f}"
diff $f <(clang-format -assume-filename=main.cpp $f) 1>&2
Если вы знаете как обойти скрипты оболочки, то на выходе конвейера сборок вы получите кое-что интересное:
Мысли напоследок
Мы убедились, что начать пользоваться непрерывной интеграцией для своих собственных проектов довольно просто. А после выполнения базовой настройки вы сможете перенастраивать и переиспользовать этот инструмент еще и в других своих проектах.
Если к конвейеру автоматизированных сборок добавить юнит-тесты, он станет ещё более мощным дополнением при работе над программами. Интеграция и того, и другого в ваш поток — это всего одна команда в скрипте: pio test
.
Вам решать, будет ли непрерывная интеграция улучшать ваш конкретный случай. Я советую серьезно рассмотреть этот вопрос, особенно когда вы будете делиться своим кодом и работать над проектом совместно с другими.
Читайте также:
- Scrum мёртв. Восславим нового короля - Kanban!
- Худшие способы нанять хороших программистов
- 6 команд терминала для раздражающих задач
Читайте нас в телеграмме, vk и Яндекс.Дзен
Перевод статьиRaphael Stäbler: How to Create an Automated Build Pipeline for Your Arduino Project