У меня есть сценарий, который я хочу запустить при объединении запроса на включение в GitHub. Скрипт написан на JavaScript с использованием библиотеки ZX.
Цель скрипта — автоматически определить следующую версию пакета, который будет опубликован в npm, и действия, включая получение последних тегов git из GitHub, чтобы договориться, под какой версией выпустить.
К сожалению, мне очень сложно выполнить простое git pull --tags
действие. Мне удалось установить act, который позволяет мне запускать скрипт локально.
Когда скрипт достигает шага, на котором он извлекает данные из git, время ожидания истекает. Сообщение об ошибке не очень понятно, но я вижу что-то с «Именем пользователя», поэтому подозреваю, что он пытается пройти аутентификацию с помощью GitHub, используя пароль вместо токена личного доступа:
| Username for 'https://github.com': /Users/work/projects/aves/node_modules/zx/build/core.cjs:245
| const output = new ProcessOutput(
| ^
|
| ProcessOutput [Error]:
| at /Users/work/projects/aves/scripts/prepublish.js:609:37
| exit code: null
| signal: SIGTERM
| at EventEmitter.end (/Users/work/projects/aves/node_modules/zx/build/core.cjs:245:28)
| at EventEmitter.emit (node:events:519:28)
| at ChildProcess.<anonymous> (/Users/work/projects/aves/node_modules/zx/build/vendor.cjs:20283:16)
| at ChildProcess.emit (node:events:519:28)
| at maybeClose (node:internal/child_process:1105:16)
| at Socket.<anonymous> (node:internal/child_process:457:11)
| at Socket.emit (node:events:519:28)
| at Pipe.<anonymous> (node:net:338:12) {
| _code: null,
| _signal: 'SIGTERM',
| _stdout: '',
| _stderr: '',
| _combined: ''
| }
|
| Node.js v20.15.0
error Command failed with exit code 1.
Это мой рабочий процесс:
name: Publish Package to npmjs
on:
pull_request:
branches:
- main
types: ['closed']
jobs:
build:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Git checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js and copy .npmrc file
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- name: Configure git for HTTPS
run: |
git config --global url.https://github.com/.insteadOf [email protected]:
git config --global url.https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/.insteadOf https://github.com/
- name: Fetch tags
run: yarn && yarn zx ./scripts/prepublish.js --ci
Изначально вместо prepublish.js
в последней строке я набрал:
run: git pull --tags
И какое-то время это работало, пока я не внес какое-то изменение, которого не помню, а теперь оно также терпит неудачу, если я извлекаю его непосредственно из рабочего процесса.
Внутри prepublish.js
Пробовал разное:
Я попробовал распечатать GITHUB_TOKEN
. Оно работает.
Я пробовал вызывать команды git, которые не требуют аутентификации, с помощью удаленного репозитория, например git status
, и все работает нормально.
Я попробовал запустить git config --list
и распечатать результат. Интересно, что я заметил, что токен не включается в выходные данные. Я не уверен, есть ли в GitHub какая-то логика для удаления конфиденциальных токенов перед печатью, но я попытался удалить строку x-access-token из рабочего процесса и вместо этого запустить ее внутри prepublish.js
вот так:
await $`git config --global url.https://x-access-token:${process.env.GITHUB_TOKEN}@github.com/.insteadOf https://github.com/`;
Последующая печать конфигурации git действительно включает токен в URL-адрес, но вызовы git push
по-прежнему завершаются с той же ошибкой, и я не могу придумать никаких других шагов, которые можно было бы попробовать на данный момент.
Вот что у меня сейчас есть prepublish.js
#!/usr/bin/env zx
const zx = require('zx');
const { $, spinner } = zx;
(async () => {
await $`git config --global url.https://x-access-token:${process.env.GITHUB_TOKEN}@github.com/.insteadOf https://github.com/`;
const { stdout: gitConfig } = await $`git config --list`;
console.info({ gitConfig });
const { stdout, stderr } = await $`git pull --tags`.timeout('2m');
if (stderr) {
console.error('stderr:', stderr);
}
console.info('stdout:', stdout);
return;
})()
В настоящее время я пропустил эту часть сценария, чтобы сосредоточиться на работе команд git. Я использую npm version
, чтобы установить фактическую версию, но это специальный скрипт, который должен определить, является ли это версией patch
, minor
или major
`.
Такое ощущение, что можно было бы выиграть от «не использования специального решения» и вместо использования JS-версии Octokit, чтобы вы могли общаться с github «обычным» способом? (например, docs.github.com/en/rest/guides/…, где даже описано, как интегрироваться с действиями github)
Вы правы, я мог бы использовать Octokit для получения метаданных, таких как теги. Но после запуска npm version
я все равно застрял бы, потому что все равно не смог бы запустить git push --tags
и отправить новую версию на пульт.
Как упоминалось в вопросе выше, я сталкиваюсь с той же проблемой, если пытаюсь запустить команды git непосредственно в действии github, а не в файле javascript. Я уже написал полный сценарий, который работает в локальной среде, поэтому я бы предпочел использовать его повторно. Но я понимаю, что мне может понадобиться другой подход к моему рабочему процессу действий Github, но ничего не будет работать, если я не смогу вытащить и отправить в git.
Верно, но я хочу сказать, что ваш скрипт использует голую https-аутентификацию имени пользователя:пароля вместо «правильной» аутентификации API. В журнале, который вы показываете, git сообщает вам, что вам необходимо войти в систему в интерактивном режиме, поскольку URL-адрес в вашем пользовательском скрипте этого не делает. То, с чем вы не столкнетесь при использовании официальной библиотеки API.
Хорошо, я не осознавал, что именно это означает вывод, но это имеет смысл. Но каков тогда «нормальный» способ аутентификации команд git (а не вызовов API) в рабочем процессе действий Github? Я не думаю, что смогу использовать Octokit для создания команды git push --tags
?
Хорошо, у меня был некоторый прогресс. Вместо того, чтобы переписывать URL-адрес, я смог повторно добавить пульт с аутентификацией по токену: git remote remove origin
git remote add org https://<user>:<token>@github.com/<org>/<repo>.git
После этого я смог git pull --tags
. К сожалению, я не могу прочитать токен из .env
с помощью ${{ secrets.GITHUB_TOKEN }}
, и мне пришлось жестко запрограммировать токен, что явно невозможно. Однако GITHUB_TOKEN
доступен в моем javascript.
Что вы имеете в виду под «Я не могу прочитать токен из .env
»? Действия Guthub используют секреты github вашего проекта, а не файлы .env
(см. docs.github.com/en/actions/security-guides/…)
Я тестирую рабочий процесс локально с помощью act и для этой цели добавил файл .env
. Я нашел решение. См. ниже.
Ах, мои извинения, я пропустил ту часть, где вы тестировали act
: с первого дня это страдало от того, что было «похоже», но на самом деле не «то же самое, что» реальные действия github.
Мне удалось найти решение самостоятельно.
Во-первых, я неправильно ссылался на переменную среды GITHUB_TOKEN
в разделе запуска. Вместо ${{ secrets.GITHUB_TOKEN }}
мне нужно было использовать ${{ env.GITHUB_TOKEN }}
.
Во-вторых, вместо переписывания URL-адресов мне нужно было заново добавить пульт с правильным форматом URL-адресов:
git remote remove origin
git remote add org https://<user>:${{ env.GITHUB_TOKEN }}@github.com/<organisation>/<repo>.git
В итоге мой рабочий процесс стал выглядеть так:
name: Publish Package to npmjs
on:
pull_request:
branches:
- main
types: ['closed']
jobs:
build:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Git checkout
uses: actions/checkout@v4
- name: Setup Node.js and copy .npmrc file
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- name: Configure git for HTTPS
run: |
git remote remove origin
git remote add org https://GITHUB_ACTIONS_BOT:${{ env.GITHUB_TOKEN }}@github.com/<org>/<repo>.git
- name: Fetch tags
run: yarn && yarn zx ./scripts/prepublish.js --ci
Внутри prepublish.js
теперь я могу выполнять команды git:
...
const version = ...
await $`npm version ${version}`
await $`git push --tags`
...
Не уверен, что понимаю: «Цель сценария — автоматически определить следующую версию пакета, который будет опубликован в npm»? Разве не для этого нужны
npm version major
,npm verison minor
иnpm version patch
? Вы запускаете их, нажимаете на главную с помощью--tags
, затем запускаетеnpm publish
. Потому что единственная «свобода» заключается в том, какая из этих троих будет нарушена, и я не вижу в вашем сценарии ничего, что бы это проверяло (а это означает, что можно с уверенностью предположить, что вы нарушаете semver atm, и в этом случае просто продолжайте нарушать это). но используя обычные команды npm?)