Npm publish: простая автоматическая публикация

Npm publish: простая автоматическая публикация

От автора: один из самых распространенных вопрос от людей, использующих npm для публикации, особенно в системах CI — как лучше всего автоматизировать процесс, особенно при работе с несколькими ветками.

В течение некоторого времени я использовал шаблон, который почти полностью устраняет человеческое взаимодействие, поскольку я склонен все портить, когда набираю что-то руками. Это хорошо работает для автоматической публикации из CI или при публикации вручную из терминала. Я не ввожу вручную npm publish уже некоторое время, и это хорошо.

Перво-наперво, хорошие тесты

Я большой поклонник проведения тестов со 100% охватом. Это не идеальная защита от всех проблем, но это позволяет мне не совершать разные глупости, например, предполагая, что я знаю, что делает моя программа.

Я использую библиотеку тестов tap, но вы можете сделать это с помощью любой библиотекой тестирования, которая поддерживает охват кода. Если она не поддерживает охват кода из коробки, вы можете использовать nyc для запуска любого процесса Node.js с отслеживанием охвата.

Чтобы использовать его, запустите npm i tap -D, а затем добавьте его в раздел scripts в package.json:

{ "scripts": { "test": "tap" }, "tap": { "check-coverage": true }
}

Команда npm version

Команда npm version устанавливает, какой должна быть следующая версия, редактирует файл package.json и даже помещает его в git с подписанным тегом. Ее преимущество заключается в том, что npm version также предотвращает изменение версии, когда вы не отслеживали изменения в рабочем каталоге git, и предоставляет некоторые подключаемые скрипты, которые могут выполнять другие действия до или после повышения версии.

В разделе scripts файла package.json я добавляю скрипт preversion, который запускает тесты:

{ "scripts": { "preversion": "npm test", "test": "tap" }, "tap": { "check-coverage": true }
}

Теперь, прежде чем я смогу поднять версию, npm проверит, чтобы тесты были пройдены. Если тест не пройден (или если охват не на 100%), то команда не выполнится.

Публикация при изменении версии

Поднять версию — это хорошо, но пришло время поделиться ею. Наряду с preversion команда postversion выполняет действия после повышения версии. Итак, давайте подключимся, чтобы опубликовать пакет.

{ "scripts": { "postversion": "npm publish", "preversion": "npm test", "test": "tap" }, "tap": { "check-coverage": true }
}

Синхронизация Git и npm

Это хорошо для отправки в npm, но я должен помнить, что нужно отправить изменения и в git. (Я много раз забывал это делать и получал проблемы, потому что код на npm отсутствует в GitHub, что обычно является плохим признаком). К счастью, npm также дает нам возможность подключить скрипт к событию publish, поэтому давайте воспользуемся этим:

{ "scripts": { "postpublish": "git push origin --all; git push origin --tags", "postversion": "npm publish", "preversion": "npm test", "test": "tap" }, "tap": { "check-coverage": true }
}

Это запускает две команды. Первая вводит все ветви, а вторая — все теги (включая мой недавно опубликованный тег версии).

Ветки и dist-tag

Иногда я работаю над какой-нибудь большой функцией для нового релиза, который еще не готов к прайм-тайму. В функциональной ветке я изменяю скрипты, добавляя аргумент —tag в команду npm publish, чтобы поместить его в dist-tag, отличный от latest.

{ "scripts": { "postversion": "npm publish --tag=next", "postpublish": "git push origin --all; git push origin --tags", "preversion": "npm test", "test": "tap" }, "tap": { "check-coverage": true }
}

Теперь я могу сказать людям, чтобы они запускали npm install my-module@next и пробовали новую предварительную версию. С другой стороны, я мог бы пожелать исправить ошибку или сделать бэкпорт для устаревшей версии. Для этого я создаю ветку git со старой версией и обновляю package.json, чтобы добавить тег legacy.

{ "scripts": { "postversion": "npm publish --tag=legacy", "postpublish": "git push origin --all; git push origin --tags", "preversion": "npm test", "test": "tap" }, "tap": { "check-coverage": true }
}

Бонус: подпись версий

Git поддерживает подпись PGP с тегами коммитов. Чтобы указать npm воспользоваться этой функцией, установите эти два значения конфигурации:

npm config set sign-git-commit true
npm config set sign-git-tag true

Если настройка PGP и подключение его к Git — это для вас головная боль, то вы не одиноки в этом. Я ботаник, который очень долго работает с компьютером, и я не могу с этим справиться. Кроме того, я всегда беспокоюсь о том, что мои ключи просто хранятся на компьютере в текстовых файлах, даже если они зашифрованы парольной фразой. И если они будут зашифрованы с помощью ключевой фразы, то я должен постоянно вводить ее, а это просто слишком много работы.

Я большой поклонник Krypton. Он хранит личные ключи PGP и SSH в безопасном хранилище вашего мобильного устройства, а затем отправляет push-уведомление, чтобы оно могло что-то делать с этими ключами. Он чрезвычайно прост в настройке и в использовании, это дает вам второй аппаратный фактор для всего, что имеет значение.

Конечно, и я точно не знаю, является ли это ошибкой или так должно быть, всякий раз, когда я запускаю npm version, между коммитом, подписью, тегом и двумя SSH-соединениями, мой телефон много гудит.

Запуск npm version для тестирования и публикации

После этого я использую команду npm version, чтобы выполнить все публикации. Для исправления ошибок я запускаю npm version patch. Для новых функций я запускаю npm version minor. Для внесения изменений — npm version major.

Если вы используете Conventional Commits или аналогичные инструменты, вы даже можете автоматизировать обнаружение того, какая версия должна вводиться, хотя это мы оставим для вашего самостоятельного изучения.

Такой подход использования скрпитов npm для автоматизации процесса хорошо работает с любой системой, в которой вы будете публиковать проекты. Настройте это в своем следующем проекте, и полагайтесь на руки немного меньше :)

PS: конфигурация npm очень гибкая

Вы заметите, что я использовал в командах публикации выше —tag=. Вы также можете настроить npm другими способами. Может быть установлено любое значение конфигурации (в том числе tag в случае npm publish):

явно в командной строке, например, —tag=whatever

в среде, например, NPM_CONFIG_TAG=whatever

в файле .npmrc в корне проекта, например, tag = whatever

в файле .npmrc в домашнем каталоге

в /usr/local/etc/npmrc (или /usr/etc/npmrc в некоторых системах).

Это работает в формате наследования, поэтому, чем выше значение в этом списке, тем выше приоритет.

Для систем CI / CD это означает, что вы можете иногда устанавливать переменные среды для управления поведением команд npm без необходимости изменять код или вставлять файлы в определенные места. Если вам проще управлять им с помощью файла (например, проверяя файл .npmrc в git), то это тоже работает.

Источник: https://blog.npmjs.org

Редакция: Команда webformyself.