Skip to content

Commit

Permalink
feat: clean PR
Browse files Browse the repository at this point in the history
add new feature flag...
for PR removal
  • Loading branch information
ghinks committed Apr 18, 2021
1 parent 562ace0 commit c6138ce
Show file tree
Hide file tree
Showing 9 changed files with 292 additions and 93 deletions.
32 changes: 32 additions & 0 deletions bin/commands/close-pr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict'

const wiby = require('../..')

exports.desc = 'Use this command to close the PRs raised against your dependents. wiby will go off to the dependent’s repo and close the PRs raised that trigger jobs `package.json` pointing to your latest version (with the new changes) triggering the dependent’s CI to run.'

exports.builder = (yargs) => yargs
.option('dependent', {
desc: 'URL of a dependent',
type: 'string',
conflicts: 'config'
})
.option('pull-request', {
desc: 'Raise a draft PR in addition to creating a branch',
alias: 'pr',
type: 'boolean',
conflicts: 'config'
})
.option('config', {
desc: 'Path to the configuration file. By default it will try to load the configuration from the first file it finds in the current working directory: `.wiby.json`, `.wiby.js`',
type: 'string'
})

exports.handler = (params) => {
const config = params.dependent
? {
dependents: [{ repository: params.dependent, pullRequest: !!params['pull-request'] }]
}
: wiby.validate({ config: params.config })

return wiby.closePR(config)
}
8 changes: 1 addition & 7 deletions bin/commands/result.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@ exports.builder = (yargs) => yargs
type: 'string',
conflicts: 'config'
})
.option('pull-request', {
desc: 'close a draft PR created in the test phase',
alias: 'pr',
type: 'boolean',
conflicts: 'config'
})
.option('config', {
desc: 'Path to the configuration file. By default it will try to load the configuration from the first file it finds in the current working directory: `.wiby.json`, `.wiby.js`',
type: 'string'
Expand All @@ -24,7 +18,7 @@ exports.builder = (yargs) => yargs
exports.handler = async (params) => {
const config = params.dependent
? {
dependents: [{ repository: params.dependent, pullRequest: !!params['pull-request'] }]
dependents: [{ repository: params.dependent }]
}
: wiby.validate({ config: params.config })

Expand Down
48 changes: 48 additions & 0 deletions lib/closePR.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict'

const github = require('../lib/github')
const logger = require('./logger')
const context = require('./context')
const gitURLParse = require('git-url-parse')

const debug = logger('wiby:closepr')

module.exports = async ({ dependents }) => {
const closedPrs = [];
for (const { repository: url, pullRequest } of dependents) {
if (pullRequest) {
const dependentPkgInfo = gitURLParse(url)
const parentBranchName = await context.getParentBranchName()
const branch = await context.getTestingBranchName(parentBranchName)
const resp = await github.getChecks(dependentPkgInfo.owner, dependentPkgInfo.name, branch)
const closedPR = await closeDependencyPR(dependentPkgInfo.owner, dependentPkgInfo.name, branch, resp.data.check_runs)
if (!!closedPR) {
closedPrs.push(closedPR)
}
}
}
return closedPrs;
}

const closeDependencyPR = module.exports.closeDependencyPR = async function closeDependencyPR (owner, repo, branch, checkRuns) {
if (!checkRuns || checkRuns.length === 0) {
return
}
const prsToClose = checkRuns.reduce((acc, check) => {
if (check.status === 'completed' &&
check.conclusion === 'success' &&
check.pull_requests &&
check.pull_requests.length !== 0) {
check.pull_requests.forEach((pr) => {
if (pr.head.ref === branch) {
acc.push({
number: pr.number
})
}
})
}
return acc
}, [])
debug(`Dependent module: ${JSON.stringify(prsToClose, null, 2)}`)
return await Promise.all(prsToClose.map((pr) => github.closePR(owner, repo, pr.number)))
}
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ exports.test = require('./test')
exports.result = require('./result')

exports.validate = require('./config').validate

exports.closePR = require('./closePR')
29 changes: 1 addition & 28 deletions lib/result.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module.exports = async function ({ dependents }) {

debug(`Parent module: ${parentPkgInfo.owner}/${parentPkgJSON.name}`)

for (const { repository: url, pullRequest } of dependents) {
for (const { repository: url } of dependents) {
const dependentPkgInfo = gitURLParse(url)
const dependentPkgJSON = await github.getPackageJson(dependentPkgInfo.owner, dependentPkgInfo.name)
debug(`Dependent module: ${dependentPkgInfo.owner}/${dependentPkgInfo.name}`)
Expand All @@ -37,9 +37,6 @@ module.exports = async function ({ dependents }) {
const parentBranchName = await context.getParentBranchName()
const branch = await context.getTestingBranchName(parentBranchName)
let resp = await github.getChecks(dependentPkgInfo.owner, dependentPkgInfo.name, branch)
if (pullRequest) {
await closePR(dependentPkgInfo.owner, dependentPkgInfo.name, branch, resp.data.check_runs)
}
if (resp.data.check_runs.length === 0) {
resp = await github.getCommitStatusesForRef(dependentPkgInfo.owner, dependentPkgInfo.name, branch)
}
Expand Down Expand Up @@ -165,27 +162,3 @@ function resolveCodeAndExit (overallStatus) {
process.exit(PENDING_RESULT_EXIT_CODE)
}
}

const closePR = module.exports.closePR = async function closePR (owner, repo, branch, checkRuns) {
if (!checkRuns || checkRuns.length === 0) {
return
}
const prsToClose = checkRuns.reduce((acc, check) => {
if (check.status === 'completed' &&
check.conclusion === 'success' &&
check.pull_requests &&
check.pull_requests.length !== 0) {
check.pull_requests.forEach((pr) => {
if (pr.head.ref === branch) {
acc.push({
number: pr.number
})
}
})
}
return acc
}, [])
debug(`Dependent module: ${JSON.stringify(prsToClose, null, 2)}`)
const result = await prsToClose.map((pr) => github.closePR(owner, repo, pr.number))
return result
}
27 changes: 27 additions & 0 deletions test/cli/closePR.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use strict'
/*
const tap = require('tap')
const gitFixture = require('../fixtures/git')
const childProcess = require('child_process')
const nock = require('nock')
const path = require('path')
const fs = require('fs')
const wibyCommand = path.join(__dirname, '..', '..', 'bin', 'wiby')
const fixturesPath = path.resolve(path.join(__dirname, '..', 'fixtures'))
tap.test('closePRs command', async (tap) => {
tap.beforeEach(async () => {
nock.disableNetConnect()
gitFixture.init()
})
tap.afterEach(async () => {
nock.cleanAll()
nock.enableNetConnect()
})
tap.test('close PRs should result in a successful outcome', async (t) => {
})
tap.end()
})
*/
131 changes: 131 additions & 0 deletions test/closePR.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
const nock = require('nock')
const tap = require('tap')
const context = require('../lib/context')
const gitFixture = require('./fixtures/git')
const closePR = require('../lib/closePR')

tap.test('close PR', (t) => {
t.test('checks on internal call to github', (t) => {
const owner = 'pkgjs'
const repo = 'wiby'
const branch = 'wiby-main'
t.plan(6)
t.test('no checkruns returns', async (t) => {
const result = await closePR.closeDependencyPR(owner, repo, branch, null)
t.equal(result, undefined)
})
t.test('status not completed returns empty array', async (t) => {
const result = await closePR.closeDependencyPR(owner, repo, branch, [{ status: 'queued' }])
t.equal(result.length, 0)
})
t.test('conclusion not a success returns empty array', async (t) => {
const result = await closePR.closeDependencyPR(owner, repo, branch, [{ status: 'queued', conclusion: 'failure' }])
t.equal(result.length, 0)
})
t.test('no pull requests returns empty array', async (t) => {
const result = await closePR.closeDependencyPR(owner, repo, branch, [{
status: 'completed',
conclusion: 'success'
}])
t.equal(result.length, 0)
})
t.test('empty pull requests returns empty array', async (t) => {
const result = await closePR.closeDependencyPR(owner, repo, branch, [{
status: 'completed',
conclusion: 'success',
pull_requests: []
}])
t.equal(result.length, 0)
})
t.test('pull requests with numbers returns values', async (t) => {
nock('https://api.github.com')
// get package json
.patch('/repos/pkgjs/wiby/pulls/1')
.reply(200, {
data: {}
})
const result = await closePR.closeDependencyPR(owner, repo, branch, [{
status: 'completed',
conclusion: 'success',
pull_requests: [{
number: 1,
head: {
ref: branch
}
}, {
number: 2,
head: {
ref: 'any-other-branch'
}
}]
}])
t.equal(result.length, 1)
})
})
t.test('closePR Cli function tests', (t) => {
t.plan(2)
t.test('closePR should not close PRs', async(t) => {
//nock setup
nock('https://api.github.com')
.get(/repos.*check\-runs/)
.reply(200, {
data: {}
})
const result = await closePR({
dependents: [
{
repository: 'https://github.com/wiby-test/fakeRepo',
pullRequest: true
}
]
})

t.equal(result.length, 0)
})
t.test('closePR should close a single PR', async(t) => {
gitFixture.init()
const branch = context.getTestingBranchName(await context.getParentBranchName())
//nock setup
nock('https://api.github.com')
.get(/repos.*check\-runs/)
.reply(200, {
check_runs: [
{
status: 'completed',
conclusion: 'success',
pull_requests: [{
number: 1,
head: {
ref: branch
}
}, {
number: 2,
head: {
ref: 'any-other-branch'
}
}]
}
]
})
.patch(/repos.*pulls\/1/)
.reply(200, {
state: 'closed',
title: 'wiby test pr'
})
const result = await closePR({
dependents: [
{
repository: 'https://github.com/wiby-test/fakeRepo1'
},
{
repository: 'https://github.com/wiby-test/fakeRepo2',
pullRequest: true
}
]
})

t.equal(result.length, 1)
})
})
t.end()
})
50 changes: 50 additions & 0 deletions test/fixtures/http/close-pr-command-positive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use strict'

/*
Mocks of HTTP calls for close-pr command
*/
const nock = require('nock')

nock.disableNetConnect()

function nockRepo (nockInstance, owner, repo, branch) {
return nockInstance
// /repos/{owner}/{repo}/commits/{ref}/check-runs
.get(`repos/${owner}/${repo}/commits/${branch}/check-runs`)
.reply(200, {
check_runs: [
{
status: 'completed',
conclusion: 'success',
pull_requests: [{
number: 1,
head: {
ref: branch
}
}, {
status: 'completed',
conclusion: 'success',
number: 2,
head: {
ref: 'any-other-branch'
}
}]
}
]
})
.patch(/repos.*pulls\/1/)
.reply(200, {
state: 'closed',
title: 'wiby test pr'
})
}

function buildNock () {
let nockInstance = nock('https://api.github.com')

nockInstance = nockRepo(nockInstance, 'fakeRepo')

return nockInstance
}

buildNock()
Loading

0 comments on commit c6138ce

Please sign in to comment.