diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml new file mode 100644 index 000000000..b90db4145 --- /dev/null +++ b/.github/workflows/bump-version.yml @@ -0,0 +1,100 @@ +name: Bump BitBurner Version + +on: + workflow_dispatch: + inputs: + version: + description: 'Version (format: x.y.z)' + required: true + versionNumber: + description: 'Version Number (for saves migration)' + required: true + changelog: + description: 'Changelog (url that points to RAW markdown)' + default: '' + buildApp: + description: 'Include Application Build' + type: boolean + default: 'true' + required: true + buildDoc: + description: 'Include Documentation Build' + type: boolean + default: 'true' + required: true + prepareRelease: + description: 'Prepare Draft Release' + type: boolean + default: 'true' + required: true + +jobs: + bumpVersion: + name: Bump Version + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Install pandoc dependency + run: sudo apt-get install -y pandoc + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Use Node.js 16.13.1 + uses: actions/setup-node@v2 + with: + node-version: 16.13.1 + cache: 'npm' + - name: Install NPM dependencies for version updater + working-directory: ./tools/bump-version + run: npm ci + - name: Bump version & update changelogs + working-directory: ./tools/bump-version + run: | + curl ${{ github.event.inputs.changelog }} > changes.md + node index.js --version=${{ github.event.inputs.version }} --versionNumber=${{ github.event.inputs.versionNumber }} < changes.md + - name: Install NPM dependencies for app + if: ${{ github.event.inputs.buildApp == 'true' || github.event.inputs.buildDoc == 'true' }} + run: npm ci + - name: Build Production App + if: ${{ github.event.inputs.buildApp == 'true' }} + run: npm run build + - name: Build Documentation + if: ${{ github.event.inputs.buildDoc == 'true' }} + run: npm run doc + - name: Commit Files + run: | + git config --global user.name "GitHub" + git config --global user.email "noreply@github.com" + git checkout -b bump/v${{ github.event.inputs.version }} + git add -A + echo "Bump version to v${{ github.event.inputs.version }}" > commitmessage.txt + echo "" >> commitmessage.txt + cat ./tools/bump-version/changes.md >> commitmessage.txt + git commit -F commitmessage.txt + git push -u origin bump/v${{ github.event.inputs.version }} + - name: Create Pull Request + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh pr create \ + --base "${{ github.ref_name }}" \ + --head "bump/v${{ github.event.inputs.version }}" \ + --title "Bump version to v${{ github.event.inputs.version }}" \ + --body-file ./tools/bump-version/changes.md + - name: Prepare release + if: ${{ github.event.inputs.prepareRelease == 'true' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + RELEASE_TITLE="$(head -n 1 ./tools/bump-version/changes.md | sed 's/## //')" + RELEASE_TITLE="${RELEASE_TITLE:-v${{ github.event.inputs.version }}}" + gh release create \ + v${{ github.event.inputs.version }} \ + --target dev \ + --title "$RELEASE_TITLE" \ + --notes-file ./tools/bump-version/changes.md \ + --generate-notes \ + --draft diff --git a/tools/README.md b/tools/README.md index fb62f846f..b7fa5e55f 100644 --- a/tools/README.md +++ b/tools/README.md @@ -34,3 +34,15 @@ npm install export GITHUB_API_TOKEN=tokenhere # this could go into your .bashrc or .profile etc. node index.js --from=31ebdbb139981a604bd0e8fc1e364916762e11b9 > ../bump-version/changes.md ``` + +## Bump Version + +Used to update the game's various version identifier. +Requires pandoc installed to convert .md to .rst + +**Usage** +```sh +cd ./tools/bump-version +npm install +node index.js --version=1.10.3 --versionNumber=10 < changes.md +``` diff --git a/tools/bump-version/.gitignore b/tools/bump-version/.gitignore new file mode 100644 index 000000000..4764e2f2e --- /dev/null +++ b/tools/bump-version/.gitignore @@ -0,0 +1,2 @@ +node_modules +*.md diff --git a/tools/bump-version/index.js b/tools/bump-version/index.js new file mode 100644 index 000000000..8464bc189 --- /dev/null +++ b/tools/bump-version/index.js @@ -0,0 +1,118 @@ +// import { Octokit } from "@octokit/rest"; +import commandLineArgs from "command-line-args"; + +import fs from 'fs/promises'; +import { readFileSync } from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import pandoc from 'node-pandoc'; + +// https://github.com/75lb/command-line-args +const optionDefinitions = [ + { name: 'version', alias: 'v', type: String, required: true }, + { name: 'versionNumber', alias: 'n', type: Number }, + { name: 'versionDescription', alias: 'd', type: String }, + { name: 'changelog', alias: 'l', type: String }, +]; + +const cliArgs = commandLineArgs(optionDefinitions); + +const appPaths = {}; +appPaths.root = path.join(path.dirname(fileURLToPath(import.meta.url)), "../.."); +appPaths.mainPackage = path.join(appPaths.root, "./package.json"); +appPaths.electronPackage = path.join(appPaths.root, "./electron/package.json"); +appPaths.constants = path.join(appPaths.root, "./src/Constants.ts"); +appPaths.sphinxConf = path.join(appPaths.root, "./doc/source/conf.py"); +appPaths.sphinxChangelog = path.join(appPaths.root, "./doc/source/changelog.rst"); + +async function main(version, versionNumber, changelog) { + console.log(`Updating app files to match v${version}`); + + const [ major, minor ]= version.split('.'); + const shortVersion = `${major}.${minor}`; + const modifiedMainPackage = (await fs.readFile(appPaths.mainPackage, 'utf8')). + replace(/(^\s*"version":\s)"(.*)",$/m, `$1"${version}",`); + await fs.writeFile(appPaths.mainPackage, modifiedMainPackage); + console.log(`Modified ${appPaths.mainPackage}`); + + const modifiedElectronPackage = (await fs.readFile(appPaths.electronPackage, 'utf8')). + replace(/(^\s*"version":\s)"(.*)",$/m, `$1"${version}",`); + await fs.writeFile(appPaths.electronPackage, modifiedElectronPackage); + console.log(`Modified ${appPaths.electronPackage}`); + + let modifiedConstants = (await fs.readFile(appPaths.constants, 'utf8')). + replace(/(^\s*?VersionString:\s)"(.*)",/m, `$1"${version}",`); + modifiedConstants = modifiedConstants. + replace(/(^\s*?VersionNumber:\s)(.*),/m, `$1${versionNumber},`); + + if (changelog.trim() !== '') { + let htmlChangelog = ''; + try { + htmlChangelog = await transform(changelog, 'html'); + console.log('Converted markdown changelog to html') + } catch (error) { + console.error(error); + } + + const paddedChangelog = htmlChangelog.split('\n'). + map((line) => (line.trim() !== '' ? ' ' + line : '')). + join('\n').replaceAll('`', '\\`'); + + modifiedConstants = modifiedConstants. + replace(/(^\s*?LatestUpdate:\s`\n)(.*)`,$/ms, `$1${paddedChangelog}\n` + "`,"); + } + await fs.writeFile(appPaths.constants, modifiedConstants); + console.log(`Modified ${appPaths.constants}`); + + let modifiedSphinxConfig = (await fs.readFile(appPaths.sphinxConf, 'utf8')). + replace(/(^version = ')(.*)'$/m, `$1${shortVersion}'`); + modifiedSphinxConfig = modifiedSphinxConfig. + replace(/(^release = ')(.*)'$/m, `$1${version}'`); + await fs.writeFile(appPaths.sphinxConf, modifiedSphinxConfig); + console.log(`Modified ${appPaths.sphinxConf}`); + + if (changelog.trim() !== '') { + let modifiedSphinxChangelog = await fs.readFile(appPaths.sphinxChangelog, 'utf8'); + const lines = modifiedSphinxChangelog.split('\n'); + let rstChangelog = ''; + try { + rstChangelog = await transform(changelog, 'rst'); + console.log('Converted markdown changelog to rst') + } catch (error) { + console.error(error); + } + + lines.splice(5, 0, rstChangelog); + modifiedSphinxChangelog = lines.join('\n'); + await fs.writeFile(appPaths.sphinxChangelog, modifiedSphinxChangelog); + console.log(`Modified ${appPaths.sphinxChangelog}`); + } +} + +async function transform(markdown, format) { + return new Promise((resolve, reject) => { + const args = `-f markdown -t ${format}`; + pandoc(markdown, args, (error, rst) => { + if (error) { + reject(error); + } else { + resolve(rst); + } + }); + }); +} + +async function getChangelog() { + // Read from stdin + // https://stackoverflow.com/a/56012724 + try { + return readFileSync(0, 'utf-8').replace('\r\n', '\n'); + } catch (error) { + return ''; + } +} + +getChangelog().then((changes) => { + main(cliArgs.version, cliArgs.versionNumber, changes).then(() => console.log('Done')); +}) + diff --git a/tools/bump-version/package-lock.json b/tools/bump-version/package-lock.json new file mode 100644 index 000000000..d9632a14b --- /dev/null +++ b/tools/bump-version/package-lock.json @@ -0,0 +1,109 @@ +{ + "name": "update-version", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "update-version", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "command-line-args": "^5.2.0", + "node-pandoc": "^0.3.0" + } + }, + "node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/command-line-args": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.0.tgz", + "integrity": "sha512-4zqtU1hYsSJzcJBOcNZIbW5Fbk9BkjCp1pZVhQKoRaWL5J7N4XphDLwo8aWwdQpTugxwu+jf9u2ZhkXiqp5Z6A==", + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "node_modules/node-pandoc": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/node-pandoc/-/node-pandoc-0.3.0.tgz", + "integrity": "sha1-1GV3zQpyr0FTU/y4oBF622JC+cg=" + }, + "node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "engines": { + "node": ">=8" + } + } + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==" + }, + "command-line-args": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.0.tgz", + "integrity": "sha512-4zqtU1hYsSJzcJBOcNZIbW5Fbk9BkjCp1pZVhQKoRaWL5J7N4XphDLwo8aWwdQpTugxwu+jf9u2ZhkXiqp5Z6A==", + "requires": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + } + }, + "find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "requires": { + "array-back": "^3.0.1" + } + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "node-pandoc": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/node-pandoc/-/node-pandoc-0.3.0.tgz", + "integrity": "sha1-1GV3zQpyr0FTU/y4oBF622JC+cg=" + }, + "typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==" + } + } +} diff --git a/tools/bump-version/package.json b/tools/bump-version/package.json new file mode 100644 index 000000000..c40bdde24 --- /dev/null +++ b/tools/bump-version/package.json @@ -0,0 +1,16 @@ +{ + "name": "update-version", + "version": "1.0.0", + "type": "module", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "command-line-args": "^5.2.0", + "node-pandoc": "^0.3.0" + } +}