From b21938fdd8cd8a687429db6da08c220975df84fe Mon Sep 17 00:00:00 2001 From: Julia Friesel Date: Fri, 14 Jun 2019 17:52:08 +0200 Subject: [PATCH] Add release wizard --- package.json | 10 ++-- tools/bin/commit-release.js | 12 ++++ tools/bin/tag-release.js | 12 ++++ tools/bin/update-changelog.js | 12 ++++ tools/bin/update-version.js | 12 ++++ tools/commit-release | 18 ------ tools/commit-release.js | 14 +++++ tools/release-wizard.js | 45 +++++++++++++++ tools/tag-release.js | 18 ++++++ tools/update-changelog.js | 23 ++++---- tools/update-version.js | 103 +++++++++++++++++----------------- 11 files changed, 194 insertions(+), 85 deletions(-) create mode 100755 tools/bin/commit-release.js create mode 100644 tools/bin/tag-release.js create mode 100644 tools/bin/update-changelog.js create mode 100644 tools/bin/update-version.js delete mode 100755 tools/commit-release create mode 100755 tools/commit-release.js create mode 100644 tools/release-wizard.js create mode 100755 tools/tag-release.js diff --git a/package.json b/package.json index 7f07792..f228d5d 100644 --- a/package.json +++ b/package.json @@ -15,11 +15,11 @@ "test-watch": "mocha --recursive --require @babel/register --watch test", "lint": "eslint components lib test", "devtool": "adb shell input keyevent 82", - "update-version": "./tools/update-version.js", - "build-android-release": "cd android && ./gradlew clean && ./gradlew assembleRelease && cd ..", - "commit-release": "./tools/commit-release", - "update-changelog": "./tools/update-changelog.js", - "release": "npm run update-version && npm run build-android-release && npm run commit-release" + "update-version": "node ./tools/bin/update-version.js", + "commit-release": "node ./tools/bin/commit-release.js", + "tag-release": "node ./tools/bin/tag-release.js", + "update-changelog": "node ./tools/bin/update-changelog.js", + "release": "node ./tools/release-wizard.js" }, "dependencies": { "@ptomasroos/react-native-multi-slider": "^1.0.0", diff --git a/tools/bin/commit-release.js b/tools/bin/commit-release.js new file mode 100755 index 0000000..7c52582 --- /dev/null +++ b/tools/bin/commit-release.js @@ -0,0 +1,12 @@ +#!/usr/bin/env node + +const makeCommitRelease = require('../commit-release'); + +(async () => { + try { + await makeCommitRelease() + } catch(err) { + console.error(err) + process.exit(1) + } +})() \ No newline at end of file diff --git a/tools/bin/tag-release.js b/tools/bin/tag-release.js new file mode 100644 index 0000000..c8fa028 --- /dev/null +++ b/tools/bin/tag-release.js @@ -0,0 +1,12 @@ +#!/usr/bin/env node + +const tagRelease = require('../tag-release'); + +(async () => { + try { + await tagRelease() + } catch(err) { + console.error(err) + process.exit(1) + } +})() \ No newline at end of file diff --git a/tools/bin/update-changelog.js b/tools/bin/update-changelog.js new file mode 100644 index 0000000..d1ee07c --- /dev/null +++ b/tools/bin/update-changelog.js @@ -0,0 +1,12 @@ +#!/usr/bin/env node + +const updateChangelog = require('../update-changelog'); + +(async () => { + try { + await updateChangelog() + } catch(err) { + console.error(err) + process.exit(1) + } +})() \ No newline at end of file diff --git a/tools/bin/update-version.js b/tools/bin/update-version.js new file mode 100644 index 0000000..a9d9e72 --- /dev/null +++ b/tools/bin/update-version.js @@ -0,0 +1,12 @@ +#!/usr/bin/env node + +const updateVersion = require('../update-version'); + +(async () => { + try { + await updateVersion() + } catch(err) { + console.error(err) + process.exit(1) + } +})() \ No newline at end of file diff --git a/tools/commit-release b/tools/commit-release deleted file mode 100755 index 4191119..0000000 --- a/tools/commit-release +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -# Any copyright is dedicated to the Public Domain. -# http://creativecommons.org/publicdomain/zero/1.0/ - -set -eEu -o pipefail -shopt -s extdebug -IFS=$'\n\t' -trap 'onFailure $?' ERR - -function onFailure() { - echo "Unhandled script error $1 at ${BASH_SOURCE[0]}:${BASH_LINENO[0]}" >&2 - exit 1 -} - -git add -A -git commit -m "release: $(cat package.json | $(npm bin)/jase version)" -git tag v$(cat package.json | $(npm bin)/jase version) diff --git a/tools/commit-release.js b/tools/commit-release.js new file mode 100755 index 0000000..8c87c78 --- /dev/null +++ b/tools/commit-release.js @@ -0,0 +1,14 @@ +const { exec } = require('child_process') + +module.exports = () => { + return new Promise((resolve, reject) => { + const version = require('../package.json').version + exec('git add -A', err => { + if (err) return reject(err.message) + exec(`git commit -m "Release: ${version}"`, err => { + if (err) return reject(err.message) + resolve() + }) + }) + }) +} diff --git a/tools/release-wizard.js b/tools/release-wizard.js new file mode 100644 index 0000000..fd63c50 --- /dev/null +++ b/tools/release-wizard.js @@ -0,0 +1,45 @@ +const readline = require('readline') +const updateVersion = require('./update-version') +const createTagForRelease = require('./tag-release') +const updateChangelog = require('./update-changelog') +const makeCommitRelease = require('./commit-release') + +process.on('unhandledRejection', err => { throw(err) }) + +async function leadThroughRelease() { + console.log("Yay, a release! Let's do this. First, let's update the version everywhere and create a new git tag.") + + await updateVersion() + await createTagForRelease() + + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }) + const shouldUpdateChangelog = await new Promise(resolve => { + rl.question('Would you like to update the changelog (y/n)?', yn => { + yn === 'y' || yn === 'Y' ? resolve(true) : resolve(false) + }) + }) + + if (shouldUpdateChangelog) { + await updateChangelog() + await new Promise(resolve => { + rl.question("Awesome. We've added all commits for this release to the changelog file. Please review, edit and summarize where necessary so it's useful for the app's users. Then come back here and press enter.", () => resolve()) + }) + } + + await makeCommitRelease() + + console.log(`Groovy. We've created a commit for this release that includes the version and changelog updates, as well as a git tag for the release. +Please review it, make any necessary changes, and if it's all good, push the commit and the tag up to master by running: +git push origin master +git push origin ${require('../package.json').version} + +Don't forget to also run 'npm run build-android-release' to package the apk and upload it to the app stores! +`) + + process.exit(0) +} + +leadThroughRelease() diff --git a/tools/tag-release.js b/tools/tag-release.js new file mode 100755 index 0000000..fcd7d6b --- /dev/null +++ b/tools/tag-release.js @@ -0,0 +1,18 @@ +const { exec } = require('child_process') + +module.exports = () => { + return new Promise((resolve, reject) => { + const version = require('../package.json').version + exec(`git tag v${version}`, err => { + if (err) { + console.error(`There was a problem creating the new tag. Typically, this happens when it already exists, in which case you can delete it with +git tag -d +or you might not have made the file executable yet, which you can do by running +chmod +x ./tools/tag-release`) + reject(err.message) + } else { + resolve() + } + }) + }) +} \ No newline at end of file diff --git a/tools/update-changelog.js b/tools/update-changelog.js index 7183b9b..322def6 100755 --- a/tools/update-changelog.js +++ b/tools/update-changelog.js @@ -1,16 +1,19 @@ -#!/usr/bin/env node - const updateChangelog = require('basic-changelog') const opts = { filterCommitsStartingWith: ['release:'] } -updateChangelog('./CHANGELOG.md', opts, err => { - if (err) { - console.error('Something went wrong trying to update the changelog:') - console.error(err) - return - } - console.log('Changelog successfully updated') -}) \ No newline at end of file +module.exports = () => { + return new Promise((resolve, reject) => { + updateChangelog('./CHANGELOG.md', opts, err => { + if (err) { + console.error('Something went wrong trying to update the changelog:') + reject(err) + return + } + console.log('Changelog successfully updated') + resolve() + }) + }) +} \ No newline at end of file diff --git a/tools/update-version.js b/tools/update-version.js index e948a14..0d46973 100755 --- a/tools/update-version.js +++ b/tools/update-version.js @@ -1,5 +1,3 @@ -#!/usr/bin/env node - // from https://gitlab.com/staltz/manyverse/blob/master/tools/update-version.js /* Any copyright is dedicated to the Public Domain. @@ -11,60 +9,61 @@ const leftPad = require('left-pad') const path = require('path') const fs = require('fs') -const currentVersion = JSON.parse(fs.readFileSync('./package.json')).version +module.exports = () => { + return new Promise((resolve, reject) => { -const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, -}) + const currentVersion = JSON.parse(fs.readFileSync('./package.json')).version -function createTodaysVersion(attempt) { - const today = new Date() - const yy = today.getFullYear() - 2000 // So it's two digits - const mm = leftPad(today.getMonth() + 1, 2, '0') - const d = today.getDate() - if (attempt === 0) { - return `0.${yy}${mm}.${d}-beta` - } else { - const letter = String.fromCharCode(97 + attempt) // 0=a, 1=b, 2=c, ... - return `0.${yy}${mm}.${d}-beta.${letter}` - } -} + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }) -let nextVersion -for (let i = 0 /* letter a */; i <= 25 /* letter z */; i++) { - nextVersion = createTodaysVersion(i) - if (nextVersion !== currentVersion) break -} -if (nextVersion === currentVersion) { - console.error('I dont know what else to generate beyong ' + nextVersion) - process.exit(1) -} + function createTodaysVersion(attempt) { + const today = new Date() + const yy = today.getFullYear() - 2000 // So it's two digits + const mm = leftPad(today.getMonth() + 1, 2, '0') + const d = today.getDate() + if (attempt === 0) { + return `0.${yy}${mm}.${d}-beta` + } else { + const letter = String.fromCharCode(96 + attempt) // 0=a, 1=b, 2=c, ... + return `0.${yy}${mm}.${d}-beta.${letter}` + } + } -rl.question('Next version will be `' + nextVersion + '`, okay? y/n ', yn => { - if (yn !== 'y' && yn !== 'Y') { - console.log('Release cancelled.\n') - process.exit(1) - return - } + let nextVersion + for (let i = 0 /* letter a */; i <= 25 /* letter z */; i++) { + nextVersion = createTodaysVersion(i) + if (nextVersion !== currentVersion) break + } + if (nextVersion === currentVersion) { + console.error('I dont know what else to generate beyond ' + nextVersion) + process.exit(1) + } - const pkgJSON = JSON.parse(fs.readFileSync('./package.json')) - const pkgLockJSON = JSON.parse(fs.readFileSync('./package-lock.json')) - pkgJSON.version = nextVersion - pkgLockJSON.version = nextVersion - fs.writeFileSync('./package.json', JSON.stringify(pkgJSON, null, 2)) - fs.writeFileSync('./package-lock.json', JSON.stringify(pkgLockJSON, null, 2)) + rl.question('Next version will be `' + nextVersion + '`, okay? y/n ', async yn => { + if (yn !== 'y' && yn !== 'Y') { + reject('Release cancelled.\n') + return + } - ReactNativeVersion.version( - { - neverAmend: true, - target: 'android', - }, - path.resolve(__dirname, '../'), - ).catch(err => { - console.error(err) - process.exit(1) + const pkgJSON = JSON.parse(fs.readFileSync('./package.json')) + const pkgLockJSON = JSON.parse(fs.readFileSync('./package-lock.json')) + pkgJSON.version = nextVersion + pkgLockJSON.version = nextVersion + fs.writeFileSync('./package.json', JSON.stringify(pkgJSON, null, 2)) + fs.writeFileSync('./package-lock.json', JSON.stringify(pkgLockJSON, null, 2)) + + await ReactNativeVersion.version( + { + neverAmend: true, + target: 'android', + }, + path.resolve(__dirname, '../'), + ) + rl.close() + resolve() + }) }) - - rl.close() -}) +} \ No newline at end of file