From 9537869df0660dc0f797e055581adfac2728a2a5 Mon Sep 17 00:00:00 2001 From: Ralph Meier Date: Wed, 21 Nov 2018 15:35:04 +0100 Subject: [PATCH] feat: add new command create-downstream-release-branch --- .../create-downstream-release-branch.js | 108 ++++++++++++++++++ .../octokit.js | 67 +++++++++++ .../pullrequest.template.js | 14 +++ package.json | 1 + 4 files changed, 190 insertions(+) create mode 100644 lib/commands/create-downstream-release-branch.js create mode 100644 lib/commands/create-downstream-release-branch/octokit.js create mode 100644 lib/commands/create-downstream-release-branch/pullrequest.template.js diff --git a/lib/commands/create-downstream-release-branch.js b/lib/commands/create-downstream-release-branch.js new file mode 100644 index 0000000..e85b9e4 --- /dev/null +++ b/lib/commands/create-downstream-release-branch.js @@ -0,0 +1,108 @@ +const Octokit = require('./create-downstream-release-branch/octokit') +const pullrequestTemplate = require('./create-downstream-release-branch/pullrequest.template') + +module.exports = function (dep) { + const { logBgMagenta } = dep + const cmd = {} + cmd.command = 'create-downstream-release-branch' + cmd.desc = 'Create a downstream release branch' + cmd.builder = { + 'owner': { + alias: 'o', + describe: "github repository owner e.g. 'livingdocsIO'", + demandOption: true + }, + 'repo': { + alias: 'r', + describe: "github repository name e.g. 'livingdocs-editor'", + demandOption: true + }, + 'gh-token': { + alias: 't', + describe: 'github token with write access', + demandOption: true + }, + 'base-branch': { + describe: "base branch name where the release branch will be branched from e.g. 'upstream-release-2018-09'", + demandOption: true + }, + 'target-branch': { + describe: "this branch will be created e.g. 'upstream-release-2018-11'", + demandOption: true + }, + 'target-release-name': { + describe: "release name e.g. 'November 2018'", + demandOption: true + }, + 'upstream-repo-name': { + describe: "upstream repository name e.g. 'livingdocs-editor' or 'livingdocs-server'", + demandOption: true + }, + 'dry-run': { + alias: 'd', + describe: "No execution of the script (just logs) '--dry-run true' (default: false)", + demandOption: false, + default: false, + boolean: true + } + } + + cmd.handler = async function (argv) { + const o = new Octokit(argv.ghToken) + logBgMagenta(`Setup downstream release branch ${argv.targetBranch}`) + + // get readme of base branch + const readmeBase64 = await o.getReadme({ + owner: argv.owner, + repo: argv.repo, + ref: argv.baseBranch + }) + + // add an empty line to the readme to have a code diff for the upcoming pull request + const readme = Buffer.from(readmeBase64.data.content, 'base64').toString('ascii') + const newLineReadme = `\n ${readme}` + const newLineReadmeEncoded = Buffer.from(newLineReadme).toString('base64') + + // get latest commit of base branch + const latestBaseBranchCommit = await o.getCommitByRef({ + owner: argv.owner, + repo: argv.repo, + ref: `refs/heads/${argv.baseBranch}` + }) + + // create new release-branch + await o.createBranch({ + owner: argv.owner, + repo: argv.repo, + ref: `refs/heads/${argv.targetBranch}`, + sha: latestBaseBranchCommit.data.sha + }) + + // add a new commit to the release-branch + await o.updateReadme({ + owner: argv.owner, + repo: argv.repo, + path: readmeBase64.data.path, + message: `chore(release-management): add change to initialise ${argv.targetBranch} branch`, + content: newLineReadmeEncoded, + sha: readmeBase64.data.sha, + branch: argv.targetBranch + }) + + // create the integration branch pull request + const pullRequest = await o.createPullRequest({ + owner: argv.owner, + repo: argv.repo, + title: `Livingdocs Release ${argv.targetReleaseName}`, + head: argv.targetBranch, + base: argv.baseBranch, + body: pullrequestTemplate(argv.upstreamRepoName) + }) + + console.log(`created new downstream integration pull request at ${pullRequest.data.html_url}`) + + return pullRequest + } + + return cmd +} diff --git a/lib/commands/create-downstream-release-branch/octokit.js b/lib/commands/create-downstream-release-branch/octokit.js new file mode 100644 index 0000000..0375cf4 --- /dev/null +++ b/lib/commands/create-downstream-release-branch/octokit.js @@ -0,0 +1,67 @@ +const octokit = require('@octokit/rest')() + +module.exports = class Octokit { + constructor (token) { + if (token) { + octokit.authenticate({ + type: 'oauth', + token: token + }) + } + } + + // ref: name of the new branch + // e.g. 'refs/heads/my-new-branch' + // sha: sha of the base commit + async createBranch ({owner, repo, ref, sha}) { + return octokit.gitdata.createRef({ + owner, + repo, + ref, + sha + }) + } + + async createPullRequest ({owner, repo, title, head, base, body}) { + return octokit.pullRequests.create({ + owner: owner, + repo: repo, + title: title, + head: head, + base: base, + body: body, + maintainer_can_modify: true + }) + } + + // @param {String} ref The name of the commit/branch/tag + // https://octokit.github.io/rest.js/#api-Repos-getReadme + async getReadme ({owner, repo, ref}) { + return octokit.repos.getReadme({ + owner, + repo, + ref + }) + } + + async updateReadme ({owner, repo, path, message, content, sha, branch}) { + return octokit.repos.updateFile({ + owner, + repo, + path, + message, + content, + sha, + branch + }) + } + + // @param {String} ref The name of the commit/branch/tag + async getCommitByRef ({owner, repo, ref}) { + return octokit.repos.getCommitRefSha({ + owner, + repo, + ref + }) + } +} diff --git a/lib/commands/create-downstream-release-branch/pullrequest.template.js b/lib/commands/create-downstream-release-branch/pullrequest.template.js new file mode 100644 index 0000000..a1a7e9d --- /dev/null +++ b/lib/commands/create-downstream-release-branch/pullrequest.template.js @@ -0,0 +1,14 @@ +module.exports = (repo) => { + return ` +Relations: +* ${repo}: TODO + +Upstream Versions: +- Server: \`vX.Y.Z\` +- Editor: \`vX.Y.Z\` + +# Integrated Upstream Breaking Changes + +[0.0.0](https://github.com/livingdocsIO/${repo}/releases/tag/v0.0.0) - some description +` +} diff --git a/package.json b/package.json index 504f07d..e4fd700 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ }, "homepage": "https://github.com/livingdocsIO/release-tools#readme", "dependencies": { + "@octokit/rest": "^16.0.1", "camelcase": "^5.0.0", "chalk": "^2.3.2", "require-dir": "^1.0.0",