Непрерывная интеграция является необходимостью в наши дни. А для социальных проектов с открытым исходным кодом это имеет решающее значение. Наш любимый инструмент для автоматизированного тестирования — Travis CI. Как и большинство инструментов, Travis делает то, что делает хорошо. К сожалению, это не очень умно. Да поможет вам небо, если у вас есть большой или модульный проект с множеством тестов — вы будете ждать вечность между сборками.
И это именно то, с чем мы столкнулись. У нас есть репозиторий, содержащий 30 модулей NPM, каждый со своими спецификациями (тестами). Эти модули являются частью конвейера стареющих активов, о котором я кратко упомянул на прошлой неделе. Таким образом, каждый модуль подвергается большому количеству задач каждый раз, когда вносятся изменения. Travis CI подключается к репозиторию и для каждого запроса на включение будет запускать спецификации для каждого модуля, гарантируя отсутствие ошибок в изменениях кода, содержащихся в PR. Когда вы работаете только над одним или двумя модулями, время выполнения задач относительно невелико; обычно 1-2 минуты. Это, конечно, зависит от таких вещей, как npm install
время, так как каждый модуль требует установки для тестирования. Умножьте это на 30, и вы начнете видеть, где возникает проблема.
Ожидание отстой
Без целевого тестирования сборки нам приходится ждать или менять задачи, пока сборка не завершится успешно. Наша потребность была ясна: выяснить, какие файлы были затронуты, сопоставить и отфильтровать результаты, а также запустить только спецификации для модулей, измененных в каком-либо конкретном запросе на включение или отправке. Вот где в игру вступает travis-target.
Вот фрагмент нашей структуры репо для справки:
ui-tracking |--src |--common |--event_registry |--tracking_metadata |--tracking |--cart |--etc..
Цель получена
Чтобы ориентироваться на модули, нам нужно знать, каковы их нормализованные имена; имена, под которыми мы публикуем их в NPM. Из-за некоторых устаревших вещей, встроенных в наш конвейер, мы храним модули в group/name
, но публикуем их как group.name
. Итак, давайте запустим travis-target
(имейте в виду, что мы используем синтаксис ES6, который поддерживает Node v7).
const target = require('travis-target'); const pattern = /^src\//; let targets = await target();
Давайте представим, что оба модуля common.event_registry
и tracking.cart
были изменены в одном запросе на слияние (общий для нас шаблон) — наши результаты могли бы выглядеть так:
[ 'README.md', 'src/common/event_registry/js/event_registry.js', 'src/common/event_registry/js/registry.js', 'src/common/event_registry/package.json', 'src/tracking/cart/js/cart.js', 'src/tracking/cart/package.json' ]
Но это просто глупо, так что давайте travis-target
дадим несколько вариантов для работы:
const target = require('travis-target'); const pattern = /^src\//; let targets = await target({ pattern: pattern, map: (result) => { let parts; result = result.replace(pattern, ''); parts = result.split('/'); return parts.slice(0, 2).join('.'); } });
Передавая pattern
в параметрах, мы говорим travis-target
фильтровать (или возвращать только те результаты, которые соответствуют) шаблону регулярного выражения. Это дает нам исходный набор каталогов, начинающихся с src/
.
[ 'src/common/event_registry/js', 'src/tracking/cart/js' ]
Вы заметите, что первоначальный пример результатов содержал несколько повторяющихся каталогов; travis-target убирает это за вас.
Далее мы указываем функцию map
в опциях. Это позволит нам преобразовать каждый элемент в Array
результатов, чтобы он был готов к использованию. Теперь наши результаты будут выглядеть так:
[ 'common.event_registry', 'tracking.cart' ]
Великая справедливость
Используя этот последний набор результатов, мы теперь знаем, какие модули были затронуты в PR, и мы знаем, для каких модулей нужно запускать спецификации. Наши следующие шаги — запустить последовательность команд оболочки с использованием @exponent/spawn-async, которая хорошо работает с шаблонами async/await
, которые теперь поддерживаются в Node v7.1 с флагом --harmony-async-await
.
Поскольку мы внедрили этот шаблон, время сборки наших PR находится в диапазоне 1–2 минут; значительное улучшение, которое в какой-то степени принесет разработчику удовольствие.
Ваше здоровье!
Первоначально опубликовано на shellscape.org 16 ноября 2016 г.