diff --git a/.github/helper/spawnGit.js b/.github/helper/spawnGit.js new file mode 100644 index 000000000..82027e3ff --- /dev/null +++ b/.github/helper/spawnGit.js @@ -0,0 +1,15 @@ +const cp = require('child_process') + +function spawnGit (args, { mock = false } = {}) { + console.log('> git', args.join(' ')) + if (mock) return + const result = cp.spawnSync('git', args, { stdio: 'inherit', shell: false }) + if (result.error) { + throw result.error + } + if (result.status !== 0) { + throw new Error(`git ${args.join(' ')} failed with exit code ${result.status}`) + } +} + +module.exports = spawnGit diff --git a/.github/helper/updator.js b/.github/helper/updator.js index 9245b80f2..91980deaf 100644 --- a/.github/helper/updator.js +++ b/.github/helper/updator.js @@ -3,11 +3,10 @@ * Updator script triggered from minecraft-data repository to auto generate PR */ const fs = require('fs') -const cp = require('child_process') const assert = require('assert') const github = require('gh-helpers')() const { join } = require('path') -const exec = (cmd) => github.mock ? console.log('> ', cmd) : (console.log('> ', cmd), cp.execSync(cmd, { stdio: 'inherit' })) +const spawnGit = require('./spawnGit') console.log('Starting update process...') // Sanitize and validate environment variables all non alpha numeric / underscore / dot @@ -56,12 +55,12 @@ async function main () { } const branchName = 'pc' + newVersion.replace(/[^a-zA-Z0-9_]/g, '_') - exec(`git checkout -b ${branchName}`) - exec('git config user.name "github-actions[bot]"') - exec('git config user.email "41898282+github-actions[bot]@users.noreply.github.com"') - exec('git add --all') - exec(`git commit -m "Update to version ${newVersion}"`) - exec(`git push origin ${branchName} --force`) + spawnGit(['checkout', '-b', branchName], { mock: github.mock }) + spawnGit(['config', 'user.name', 'github-actions[bot]'], { mock: github.mock }) + spawnGit(['config', 'user.email', '41898282+github-actions[bot]@users.noreply.github.com'], { mock: github.mock }) + spawnGit(['add', '--all'], { mock: github.mock }) + spawnGit(['commit', '-m', `Update to version ${newVersion}`], { mock: github.mock }) + spawnGit(['push', 'origin', branchName, '--force'], { mock: github.mock }) // createPullRequest(title: string, body: string, fromBranch: string, intoBranch?: string): Promise<{ number: number, url: string }>; const pr = await github.createPullRequest( `🎈 ${newVersion}`, diff --git a/test/spawnGitTest.js b/test/spawnGitTest.js new file mode 100644 index 000000000..f4b9e2c7a --- /dev/null +++ b/test/spawnGitTest.js @@ -0,0 +1,32 @@ +/* eslint-env mocha */ +const assert = require('assert') +const cp = require('child_process') +const spawnGit = require('../.github/helper/spawnGit') + +describe('spawnGit', () => { + const original = cp.spawnSync + afterEach(() => { cp.spawnSync = original }) + + it('throws when git exits with a non-zero status', () => { + cp.spawnSync = () => ({ status: 1, error: undefined }) + assert.throws(() => spawnGit(['push', 'origin', 'branch']), /exit code 1/) + }) + + it('throws when spawning git itself fails', () => { + const spawnError = new Error('spawn git ENOENT') + cp.spawnSync = () => ({ status: null, error: spawnError }) + assert.throws(() => spawnGit(['commit', '-m', 'x']), /ENOENT/) + }) + + it('does not throw when git exits 0', () => { + cp.spawnSync = () => ({ status: 0, error: undefined }) + assert.doesNotThrow(() => spawnGit(['add', '--all'])) + }) + + it('skips spawning entirely in mock mode', () => { + let called = false + cp.spawnSync = () => { called = true; return { status: 0 } } + spawnGit(['push'], { mock: true }) + assert.strictEqual(called, false) + }) +})