Автоматизация процесса сборки и публикации с помощью GitHub Actions (и реестра пакетов GitHub)
Это своего рода вопросы и ответы, я изложил свое решение в ответах.
Я участвую как в бета-версии GitHub Actions, так и в бета-версии реестра пакетов GitHub. Поскольку я очень ленив, я не только автоматизировал процесс сборки своего пакета npm, но и хотел автоматизировать его публикацию.
Для этого мне пришлось столкнуться с некоторыми проблемами:
- Как я могу убедиться, что задание "публикации" выполняется в только что созданной версии?
- Как я могу определить, когда версия пакета обновляется в GitHub Actions?
- Как я могу использовать результат этой проверки, чтобы изменить поведение рабочего процесса действий?
- Как я могу опубликовать пакет в npm из рабочего процесса?
- Как я могу после публикации в npm опубликовать ту же самую версию в реестре пакетов GitHub?
1 ответ
Примечание: результат всех этих шагов можно найти здесь, в файле рабочего процесса, который я фактически использовал для своего пакета.
1. Убедитесь, что задание "публикации" выполняется в только что созданной версии.
Самый простой способ, который я нашел, - это просто объединить два задания в один рабочий процесс и заставить их запускаться каждый раз. push
событие: задание публикации было ограничено для выполнения, только если на master
ветку и после первой.
- Строительная работа:
Ему необходимо собрать новую версию пакета, а затем зафиксировать ее в репозитории: фиксация имеет решающее значение, потому что это позволяет другому заданию выбрать собранную версию. Чтобы зафиксировать изменения, сделанные во время выполнения рабочего процесса, вы можете использовать одно из моих действий, add-and-commit
: он отправит изменения в репозиторий GitHub, используя "поддельного" пользователя git.
Ваш рабочий процесс должен выглядеть примерно так:
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v1.0.0
- name: Set up Node.js
uses: actions/setup-node@v1.2.0
with:
node-version: '10.x'
- name: Install dependencies
run: npm install
- name: Compile build
run: npm run build # This can be whatever command you use to build your package
- name: Commit changes
uses: EndBug/add-and-commit@v2.1.0
with: # More info about the arguments on the action page
author_name: Displayed name
author_email: Displayed email
message: "Message for the commit"
path: local/path/to/built/version
pattern: "*.js" # Pattern that matches the files to commit
force: true # Whether to use the --force flag
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This gets generated automatically
- Опубликовать вакансию:
Мы хотим, чтобы он работал только в master
ветвь после build
завершено, поэтому мы можем установить его так:
publish:
name: Publish to NPM & GitHub Package Registry
runs-on: ubuntu-latest
if: contains(github.ref, 'master') # This sets the branch
needs: build # This makes it wait for the build job
2. Обнаружение изменения версии
Я не нашел хорошего способа сделать это, поэтому сделал другое действие, version-check
: это действие сканирует коммиты каждого нажатия и пытается выяснить, включают ли они изменение версии.
Вам необходимо настроить эти два шага:
steps:
- name: Checkout repository
uses: actions/checkout@v1.0.0
with:
ref: master
- name: Check version changes
uses: EndBug/version-check@v1.0.0 # More info about the arguments on the action page
id: check # This will be the reference for later
3. Использование результатов проверки для редактирования поведения рабочего процесса.
version-check
обеспечивает два выхода: changed
(было ли обновление) и type
(тип обновления, например "патч", "незначительное", ...).
К этим выходам можно получить доступ через steps
контекст, и вы можете использовать их, чтобы решить, запускать шаг или нет, используя if
собственность. Это пример:
# check is the id we gave to the check step in the previous paragraph
- name: Version update detected
if: steps.check.outputs.changed == 'true'
run: 'echo "Version change! -> ${{ steps.check.outputs.type }}"'
4. Публикация пакета в NPM.
Опубликовать пакет в NPM довольно просто: вам нужно только настроить Node.js, а затем использовать npm publish
, как на своей машине. Единственное отличие состоит в том, что вам понадобится токен для аутентификации: вы можете создать его на https://npmjs.com/. После того, как вы создали его, НЕ включайте его в рабочий процесс: вы можете сохранить его как "секрет", вы можете найти больше информации о них здесь.
В этом примере я предполагаю, что ваш секрет называетсяNPM_TOKEN
:
- name: Set up Node.js for NPM
if: steps.check.outputs.changed == 'true'
uses: actions/setup-node@v1.2.0
with:
registry-url: 'https://registry.npmjs.org' # This is just the default registry URL
- name: Install dependencies
if: steps.check.outputs.changed == 'true'
run: npm install
- name: Publish the package to NPM
if: steps.check.outputs.changed == 'true'
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # NPM will automatically authenticate with this
5. Публикация пакета в реестре пакетов GitHub.
На данный момент с реестром пакетов GitHub не очень приятно работать, если вы хотите и дальше публиковать существующий пакет в npm: вот почему он требует, чтобы пакеты были ограничены, и это может испортить ситуацию (ваш пакет может не иметь области видимости или быть в области видимости под другим именем).
Я обнаружил, что самый простой способ справиться с этим - это обходной путь:
- В своем рабочем процессе переустановите Node.js, но добавив URL-адрес реестра GPR и область вашего имени.
- Создайте сценарий npm, который редактирует ваш package.json так, чтобы он изменял исходное имя пакета на то, которое вам нужно опубликовать в GPR (включая область действия)
- После вызова этого сценария в рабочем процессе используйте
npm publish
как и раньше, но на этот раз с помощью встроенногоGITHUB_TOKEN
какNODE_AUTH_TOKEN
.
{
"name": "YourPackageName",
...
"scripts": {
"gpr-setup": "node scripts/gpr.js"
}
}
// scripts/gpr.js
const fs = require('fs')
const { join } = require('path')
// Get the package obejct and change the name
const pkg = require('../package.json')
pkg.name = '@yourscope/YourPackageName'
// Update package.json with the udpated name
fs.writeFileSync(join(__dirname, '../package.json'), JSON.stringify(pkg))
- name: Set up Node.js for GPR
if: steps.check.outputs.changed == 'true'
uses: actions/setup-node@v1.2.0
with:
registry-url: 'https://npm.pkg.github.com/'
scope: '@endbug'
- name: Set up the package for GPR
if: steps.check.outputs.changed == 'true'
run: npm run gpr-setup
- name: Publish the package to GPR
if: steps.check.outputs.changed == 'true'
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Результат
Ваш пакет теперь опубликован как в NPM, так и в GPR (хотя описание необходимо добавить вручную в GPR). Вы можете найти все, о чем я говорю, в версии dbots 5.0.4: