From bf52e1108f9407eb6d99decfbec2d5913b675d5a Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Fri, 2 Dec 2016 08:06:36 -0800 Subject: [PATCH] use async await --- .babelrc | 2 +- package.json | 1 + src/gitlab.js | 290 +++++++++++++++++++++++--------------------------- src/index.js | 267 +++++++++++++++++++--------------------------- 4 files changed, 245 insertions(+), 315 deletions(-) diff --git a/.babelrc b/.babelrc index 10ee50a..25f0a61 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,3 @@ { - "presets": ["porch"] + "presets": ["react-app"] } \ No newline at end of file diff --git a/package.json b/package.json index 1a2852a..8cea150 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "babel-cli": "^6.6.5", "babel-polyfill": "^6.13.0", "babel-preset-porch": "^1.0.1", + "babel-preset-react-app": "^1.0.0", "babel-register": "^6.11.6", "bunyan": "^1.8.5", "bunyan-prettystream": "^0.1.3", diff --git a/src/gitlab.js b/src/gitlab.js index 30cce0d..c316c0d 100644 --- a/src/gitlab.js +++ b/src/gitlab.js @@ -61,193 +61,167 @@ export default class GitLab { this.org = org; } - fetchRepo = log(({ repo, logger }) => { - logger.trace(`fetchRepo ${repo}`); - - return Q.fcall(() => ( - this.fetchRepos({ logger }) - )).then(repos => ( - repos.find(({ name }) => name === repo) - )).finally(() => { - logger.trace(`fetchRepo ${repo} complete`); - }); + fetchRepo = log(async ({ repo, logger }) => { + logger.trace('fetchRepo'); + const repos = await this.fetchRepos({ logger }); + return repos.find(({ name }) => name === repo); }); - fetchRepos = log(({ logger }) => { + fetchRepos = log(async ({ logger }) => { logger.trace('fetchRepos'); - return Q.fcall(() => ( - this.paginate({ - cached: true, - uri: '/projects' - }) - )).then(repos => ( - repos.filter(({ namespace: { name }}) => name === this.org) - )).tap(repos => ( - logger.trace(`${repos.length} repos found`) - )); + const repos = await this.paginate({ + cached: true, + uri: '/projects' + }); + return repos.filter(({ namespace: { name }}) => name === this.org); }); - createPackageChangeMarkdown = log(({ base, head, repo, logger }) => { + createPackageChangeMarkdown = log(async ({ base, head, repo, logger }) => { logger.trace(`createPackageChangeMarkdown ${base} ${head} ${repo}`); - return Q.fcall(() => ( - this.fetchRepo({ repo, logger }) - )).then(({ id }) => ( - this.api({ - cached: true, - uri: `/projects/${id}/repository/compare`, - qs: { - from: base, - to: head - } - }) - )).then(({ commits }) => ([ + const { id: repoId } = await this.fetchRepo({ repo, logger }); + const { commits } = await this.api({ + cached: true, + uri: `/projects/${repoId}/repository/compare`, + qs: { + from: base, + to: head + } + }); + return [ '### Diff', `[${base}...${head}](https://${this.host}/${this.org}/${repo}/compare/${base}...${head})`, '### Commits', commits.map(({ - id, + id: commitId, author_name: authorName, title }) => { const strippedTitle = title.replace(' [ci skip]', '').replace(' [skip ci]', ''); - return `- ${authorName} - [${strippedTitle}](https://${this.host}/${this.org}/${repo}/commit/${id})`; // eslint-disable-line camelcase + return `- ${authorName} - [${strippedTitle}](https://${this.host}/${this.org}/${repo}/commit/${commitId})`; // eslint-disable-line camelcase }).reverse().join('\n') - ].join('\n\n'))); + ].join('\n\n'); }); - fetchDependantRepos = log(({ packageName, logger }) => { + fetchDependantRepos = log(async ({ packageName, logger }) => { logger.trace(`fetchDependantRepos ${packageName}`); - return Q.fcall(() => ( - this.fetchRepos({ logger }) - )).then(repos => ( - filter(repos, ({ id }) => ( - Q.fcall(() => ( - this.api({ - cached: true, - uri: `/projects/${id}/repository/blobs/master`, - qs: { - filepath: 'package.json' - } - }) - )).then(({ dependencies = {}, devDependencies = {}, peerDependencies = {} }) => ( + const repos = await this.fetchRepos({ logger }); + return filter(repos, async ({ id }) => { + try { + const { + dependencies = {}, + devDependencies = {}, + peerDependencies = {} + } = await this.api({ + cached: true, + uri: `/projects/${id}/repository/blobs/master`, + qs: { + filepath: 'package.json' + } + }); + return ( dependencies.hasOwnProperty(packageName) || devDependencies.hasOwnProperty(packageName) || peerDependencies.hasOwnProperty(packageName) - )).catch(() => false) - )) - )); + ); + } catch (err) { + return false; + } + }); }); - createMergeRequest = log(({ body, title, head, repo, accept, logger }) => { + createMergeRequest = log(async ({ body, title, head, repo, accept, logger }) => { logger.trace(`createMergeRequest ${title}, ${head}, ${repo}, ${accept}`); - return Q.fcall(() => ( - this.fetchRepo({ repo, logger }) - )).then(({ id }) => ( - Q.fcall(() => ( - this.paginate({ - uri: `/projects/${id}/merge_requests`, - qs: { - state: 'opened' - } - }) - )).then(mergeRequests => ( - mergeRequests.filter(({ - target_branch: targetBranch, - source_branch: sourceBranch - }) => ( - targetBranch === 'master' && - sourceBranch === head - )) - )).then(mrs => { - if (!!mrs.length) { - assert.equal(mrs.length, 1, `${head} not found`); - - const [mr] = mrs; - return this.api({ - method: 'PUT', - uri: `/projects/${id}/merge_requests/${mr.id}`, - body: { - title, - description: body - } - }); + const { id } = await this.fetchRepo({ repo, logger }); + const mergeRequests = await this.paginate({ + uri: `/projects/${id}/merge_requests`, + qs: { + state: 'opened' + } + }); + const mrs = mergeRequests.filter(({ + target_branch: targetBranch, + source_branch: sourceBranch + }) => ( + targetBranch === 'master' && + sourceBranch === head + )); + + assert(mrs.length === 0 || mrs.length === 1); + + const mr = mrs.length === 0 ? ( + await this.api({ + method: 'POST', + uri: `/projects/${id}/merge_requests`, + body: { + source_branch: head, + target_branch: 'master', + title, + description: body } - return this.api({ - method: 'POST', - uri: `/projects/${id}/merge_requests`, - body: { - source_branch: head, - target_branch: 'master', - title, - description: body - } - }); - }).then(mr => { - if (accept) { - logger.trace('accepting merge request'); - - const isIssueOpen = true; // https://gitlab.com/gitlab-org/gitlab-ce/issues/22740 - - return Q.fcall(() => { - return isIssueOpen && Q.fcall(() => ( - this.paginate({ - uri: `/projects/${id}/pipelines` - }) - )).then(pipelines => ( - pipelines.find(({ sha }) => sha === mr.sha) - )).tap(pipeline => { - assert(pipeline, `pipeline for ${mr.sha} required`); - }).tap(() => ( - logger.trace('waiting for pipeline') - )).then(pipeline => ( - Q.fcall(() => ( - // wait for the pipeline to complete - until(() => ( - this.api({ - uri: `/projects/${id}/pipelines/${pipeline.id}` - }).then(({ status }) => { - logger.trace(`pipeline status ${status}`); - return status !== 'running' && status !== 'pending'; - }) - ), 60000) - )).then(() => { - logger.trace('pipeline no longer running'); - // ensure the pipeline was successful - return this.api({ - uri: `/projects/${id}/pipelines/${pipeline.id}` - }).then(({ status }) => { - logger.trace(`pipeline status ${status}`); - assert.equal(status, 'success'); - }); - }).then(() => ( - // ensure that the mr hasn't been updated - this.api({ - uri: `/projects/${id}/merge_request/${mr.id}` - }).then(({ sha }) => { - logger.trace(`merge request update check ${mr.sha} ${sha}`); - assert.equal(sha, mr.sha); - }) - )) - )); - }).then(() => ( - this.api({ - method: 'PUT', - uri: `/projects/${id}/merge_requests/${mr.id}/merge`, - body: { - should_remove_source_branch: true, - merge_when_build_succeeds: true - } - }).then(() => { - logger.trace(`merged merge request ${title} ${head} ${repo}`); - }) - )); + }) + ) : ( + await this.api({ + method: 'PUT', + uri: `/projects/${id}/merge_requests/${mrs[0].id}`, + body: { + title, + description: body } - logger.trace('not auto merging merge request'); - return Q.resolve(); }) - )); + ); + if (!accept) { + logger.trace('not auto merging merge request'); + return; + } + + logger.trace('accepting merge request'); + + const isIssueOpen = true; // https://gitlab.com/gitlab-org/gitlab-ce/issues/22740 + if (isIssueOpen) { + const pipelines = await this.paginate({ + uri: `/projects/${id}/pipelines` + }); + const pipeline = pipelines.find(({ sha }) => sha === mr.sha); + assert(pipeline, `pipeline for ${mr.sha} required`); + + logger.trace('waiting for pipeline to complete'); + // wait for the pipeline to complete + await until(() => ( + this.api({ + uri: `/projects/${id}/pipelines/${pipeline.id}` + }).then(({ status }) => { + logger.trace(`pipeline status ${status}`); + return status !== 'running' && status !== 'pending'; + }) + ), 60000); + + logger.trace('pipeline no longer running'); + // ensure the pipeline was successful + const { status } = await this.api({ + uri: `/projects/${id}/pipelines/${pipeline.id}` + }); + logger.trace(`pipeline status ${status}`); + assert.equal(status, 'success'); + + // ensure that the mr hasn't been updated + const { sha } = await this.api({ + uri: `/projects/${id}/merge_request/${mr.id}` + }); + logger.trace(`merge request update check ${mr.sha} ${sha}`); + assert.equal(sha, mr.sha); + } + + await this.api({ + method: 'PUT', + uri: `/projects/${id}/merge_requests/${mr.id}/merge`, + body: { + should_remove_source_branch: true, + merge_when_build_succeeds: true + } + }); + logger.trace(`merged merge request ${title} ${head} ${repo}`); }); } diff --git a/src/index.js b/src/index.js index 4180152..299219c 100644 --- a/src/index.js +++ b/src/index.js @@ -13,37 +13,31 @@ const GITHUB_HOSTNAME = 'github.com'; const getPackageBranchName = packageName => `up-to-code-${packageName}`; -const getPackageChangeMarkdown = log(({ base, head, packageName, gitlabHost, githubOrg, githubToken, gitlabOrg, gitlabToken, logger }) => ( - Q.fcall(() => ( - exec(`npm view ${packageName} repository.url`, { logger }) - )).then(stdout => ( - url.parse(stdout).hostname - )).then(hostname => { - const isGithubHosted = hostname === GITHUB_HOSTNAME; - const isGitlabHosted = hostname === gitlabHost; +const getPackageChangeMarkdown = log(async ({ base, head, packageName, gitlabHost, githubOrg, githubToken, gitlabOrg, gitlabToken, logger }) => { + const stdout = await exec(`npm view ${packageName} repository.url`, { logger }); + const { hostname } = url.parse(stdout); - assert(isGithubHosted || isGitlabHosted, 'git repo not found'); - assert(!!isGithubHosted ^ !!isGitlabHosted, 'multiple git repos found'); + const isGithubHosted = hostname === GITHUB_HOSTNAME; + const isGitlabHosted = hostname === gitlabHost; - if (isGithubHosted) { - const github = new GitHub({ org: githubOrg, token: githubToken }); - return github.createPackageChangeMarkdown({ repo: packageName, base, head, logger }); - } - if (isGitlabHosted) { - const gitlab = new GitLab({ org: gitlabOrg, token: gitlabToken, host: gitlabHost }); - return gitlab.createPackageChangeMarkdown({ repo: packageName, base, head, logger }); - } + assert(isGithubHosted || isGitlabHosted, 'git repo not found'); + assert(!!isGithubHosted ^ !!isGitlabHosted, 'multiple git repos found'); - // redundant...should be caught above - logger.error('git repo not found'); - throw new Error('git repo not found'); - }).catch(err => { - logger.error({ err }); - throw err; - }) -)); + if (isGithubHosted) { + const github = new GitHub({ org: githubOrg, token: githubToken }); + return github.createPackageChangeMarkdown({ repo: packageName, base, head, logger }); + } + if (isGitlabHosted) { + const gitlab = new GitLab({ org: gitlabOrg, token: gitlabToken, host: gitlabHost }); + return gitlab.createPackageChangeMarkdown({ repo: packageName, base, head, logger }); + } -const updateGithubRepoDependency = log(({ + // redundant...should be caught above + logger.error('git repo not found'); + throw new Error('git repo not found'); +}); + +const updateGithubRepoDependency = log(async ({ repo, packageName, githubToken, @@ -53,58 +47,38 @@ const updateGithubRepoDependency = log(({ gitlabToken, logger }) => { - logger.trace(`time to clone and update github repo ${repo}`); const cwd = `repos/github/${repo}`; - return Q.fcall(() => ( - logger.trace('clone') - )).then(() => ( - exec(`git clone --depth 1 https://${githubToken}@github.com/${githubOrg}/${repo}.git ${cwd}`, { logger }) - )).then(() => ( - logger.trace('checkout') - )).then(() => ( - exec(`git checkout -B ${getPackageBranchName(packageName)}`, { cwd, logger }) - )).then(() => ( - logger.trace('version bump') - )).then(() => ( - updateDependency({ - path: path.resolve(cwd, 'package.json'), - packageName, - logger - }) - )).then(([before, after]) => ( - getPackageChangeMarkdown({ - packageName, - base: `v${before}`, - head: `v${after}`, - gitlabHost, - githubOrg, - githubToken, - gitlabOrg, - gitlabToken, - logger - }) - )).then(body => ( - Q.fcall(() => { - logger.trace('commit'); - return exec(`git commit -a -m "Up-to-code bump of ${packageName}"`, { cwd, logger }); - }).then(() => { - logger.trace('push'); - return exec('git push -fu origin HEAD', { cwd, logger }); - }).then(() => { - logger.trace('create pull request'); - const github = new GitHub({ org: githubOrg, token: githubToken, logger }); - return github.createPullRequest({ - body, - title: `Up to code - ${packageName}`, - head: getPackageBranchName(packageName), - repo, - logger - }); - }) - )); + await exec(`git clone --depth 1 https://${githubToken}@github.com/${githubOrg}/${repo}.git ${cwd}`, { logger }); + await exec(`git checkout -B ${getPackageBranchName(packageName)}`, { cwd, logger }); + const [ before, after ] = await updateDependency({ + path: path.resolve(cwd, 'package.json'), + packageName, + logger + }); + const body = await getPackageChangeMarkdown({ + packageName, + base: `v${before}`, + head: `v${after}`, + gitlabHost, + githubOrg, + githubToken, + gitlabOrg, + gitlabToken, + logger + }); + await exec(`git commit -a -m "Up-to-code bump of ${packageName}"`, { cwd, logger }); + await exec('git push -fu origin HEAD', { cwd, logger }); + const github = new GitHub({ org: githubOrg, token: githubToken, logger }); + return github.createPullRequest({ + body, + title: `Up to code - ${packageName}`, + head: getPackageBranchName(packageName), + repo, + logger + }); }); -export const updateGitlabRepoDependency = log(({ +export const updateGitlabRepoDependency = log(async ({ repo, packageName, githubToken, @@ -115,58 +89,37 @@ export const updateGitlabRepoDependency = log(({ gitlabUser, logger }) => { - logger.trace(`time to clone and update gitlab repo ${repo}`); const cwd = `repos/gitlab/${repo}`; - return Q.fcall(() => { - logger.trace('clone'); - return exec(`git clone --depth 1 https://${gitlabUser}:${gitlabToken}@${gitlabHost}/${gitlabOrg}/${repo}.git ${cwd}`, { logger }); - }).then(() => { - logger.trace('checkout'); - return exec(`git checkout -B ${getPackageBranchName(packageName)}`, { cwd, logger }); - }).then(() => { - logger.trace('version bump'); - return updateDependency({ - path: path.resolve(cwd, 'package.json'), - packageName, - logger - }); - }).then(([before, after]) => ( - Q.fcall(() => ( - getPackageChangeMarkdown({ - packageName, - base: `v${before}`, - head: `v${after}`, - gitlabHost, - githubOrg, - githubToken, - gitlabOrg, - gitlabToken, - logger - }) - )).then(body => ( - Q.fcall(() => { - logger.trace('diff'); - return exec('git diff', { cwd, logger }); - }).then(() => { - logger.trace('commit'); - return exec(`git commit -a -m "Up to code bump of ${packageName}"`, { cwd, logger }); - }).then(() => { - logger.trace('push'); - return exec('git push -fu origin HEAD', { cwd, logger }); - }).then(() => { - logger.trace('create merge request'); - const gitlab = new GitLab({ org: gitlabOrg, token: gitlabToken, host: gitlabHost, logger }); - return gitlab.createMergeRequest({ - body, - title: `Up to code - ${packageName}`, - head: getPackageBranchName(packageName), - repo, - accept: major(before) === major(after), - logger - }); - }) - )) - )); + await exec(`git clone --depth 1 https://${gitlabUser}:${gitlabToken}@${gitlabHost}/${gitlabOrg}/${repo}.git ${cwd}`, { logger }); + await exec(`git checkout -B ${getPackageBranchName(packageName)}`, { cwd, logger }); + const [ before, after ] = await updateDependency({ + path: path.resolve(cwd, 'package.json'), + packageName, + logger + }); + const body = await getPackageChangeMarkdown({ + packageName, + base: `v${before}`, + head: `v${after}`, + gitlabHost, + githubOrg, + githubToken, + gitlabOrg, + gitlabToken, + logger + }); + await exec('git diff', { cwd, logger }); + await exec(`git commit -a -m "Up to code bump of ${packageName}"`, { cwd, logger }); + await exec('git push -fu origin HEAD', { cwd, logger }); + const gitlab = new GitLab({ org: gitlabOrg, token: gitlabToken, host: gitlabHost, logger }); + return gitlab.createMergeRequest({ + body, + title: `Up to code - ${packageName}`, + head: getPackageBranchName(packageName), + repo, + accept: major(before) === major(after), + logger + }); }); export default log(({ @@ -185,34 +138,36 @@ export default log(({ const gitlab = new GitLab({ org: gitlabOrg, token: gitlabToken, host: gitlabHost }); return Q.all([ - Q.fcall(() => ( - github.fetchDependantRepos({ packageName, logger }) - )).then(githubRepos => Q.allSettled(githubRepos.map(({ name: repo }) => ( - updateGithubRepoDependency({ - repo, - packageName, - githubToken, - githubOrg, - gitlabHost, - gitlabOrg, - gitlabToken, - logger - }) - )))), - Q.fcall(() => ( - gitlab.fetchDependantRepos({ packageName, logger }) - )).then(gitlabRepos => Q.allSettled(gitlabRepos.map(({ name: repo }) => ( - updateGitlabRepoDependency({ - repo, - packageName, - githubToken, - githubOrg, - gitlabHost, - gitlabOrg, - gitlabToken, - gitlabUser, - logger - }) - )))) + Q.fcall(async () => { + const githubRepos = await github.fetchDependantRepos({ packageName, logger }); + return Q.allSettled(githubRepos.map(({ name: repo }) => ( + updateGithubRepoDependency({ + repo, + packageName, + githubToken, + githubOrg, + gitlabHost, + gitlabOrg, + gitlabToken, + logger + }) + ))); + }), + Q.fcall(async () => { + const gitlabRepos = await gitlab.fetchDependantRepos({ packageName, logger }); + return Q.allSettled(gitlabRepos.map(({ name: repo }) => ( + updateGitlabRepoDependency({ + repo, + packageName, + githubToken, + githubOrg, + gitlabHost, + gitlabOrg, + gitlabToken, + gitlabUser, + logger + }) + ))); + }) ]); });