Skip to content

Commit b0fb895

Browse files
authored
Merge pull request #93 from ghinks/feature/close-draft-pr
2 parents 0c185d7 + ba96374 commit b0fb895

File tree

17 files changed

+468
-11
lines changed

17 files changed

+468
-11
lines changed

.wiby.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
{
22
"dependents": [
33
{
4-
"repository": "https://github.com/wiby-test/partial"
4+
"repository": "https://github.com/wiby-test/partial",
5+
"pullRequest": false
56
},
67
{
7-
"repository": "git://github.com/wiby-test/fail"
8+
"repository": "git://github.com/wiby-test/fail",
9+
"pullRequest": false
810
},
911
{
10-
"repository": "git+https://github.com/wiby-test/pass"
12+
"repository": "git+https://github.com/wiby-test/pass",
13+
"pullRequest": true
1114
}
1215
]
1316
}

bin/commands/close-pr.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict'
2+
3+
const wiby = require('../..')
4+
5+
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.'
6+
7+
exports.builder = (yargs) => yargs
8+
.option('dependent', {
9+
desc: 'URL of a dependent',
10+
type: 'string',
11+
conflicts: 'config'
12+
})
13+
.option('config', {
14+
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`',
15+
type: 'string'
16+
})
17+
18+
exports.handler = async (params) => {
19+
const config = params.dependent
20+
? {
21+
dependents: [{ repository: params.dependent, pullRequest: true }]
22+
}
23+
: wiby.validate({ config: params.config })
24+
25+
const result = await wiby.closePR(config)
26+
// TODO, something more like the result process output
27+
const output = `${result.length} PRs closed`
28+
console.log(output)
29+
}

bin/commands/result.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ exports.builder = (yargs) => yargs
1717

1818
exports.handler = async (params) => {
1919
const config = params.dependent
20-
? { dependents: [{ repository: params.dependent }] }
20+
? {
21+
dependents: [{ repository: params.dependent }]
22+
}
2123
: wiby.validate({ config: params.config })
2224

2325
const result = await wiby.result(config)

bin/commands/test.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,22 @@ exports.builder = (yargs) => yargs
1010
type: 'string',
1111
conflicts: 'config'
1212
})
13+
.option('pull-request', {
14+
desc: 'Raise a draft PR in addition to creating a branch',
15+
alias: 'pr',
16+
type: 'boolean',
17+
conflicts: 'config'
18+
})
1319
.option('config', {
1420
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`',
1521
type: 'string'
1622
})
1723

1824
exports.handler = (params) => {
1925
const config = params.dependent
20-
? { dependents: [{ repository: params.dependent }] }
26+
? {
27+
dependents: [{ repository: params.dependent, pullRequest: !!params['pull-request'] }]
28+
}
2129
: wiby.validate({ config: params.config })
2230

2331
return wiby.test(config)

lib/closePR.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
'use strict'
2+
3+
const github = require('../lib/github')
4+
const logger = require('./logger')
5+
const context = require('./context')
6+
const gitURLParse = require('git-url-parse')
7+
8+
const debug = logger('wiby:closepr')
9+
10+
module.exports = async ({ dependents }) => {
11+
const closedPrs = []
12+
for (const { repository: url, pullRequest } of dependents) {
13+
if (pullRequest) {
14+
const dependentPkgInfo = gitURLParse(url)
15+
const parentBranchName = await context.getParentBranchName()
16+
const branch = await context.getTestingBranchName(parentBranchName)
17+
const resp = await github.getChecks(dependentPkgInfo.owner, dependentPkgInfo.name, branch)
18+
const closedPR = await closeDependencyPR(dependentPkgInfo.owner, dependentPkgInfo.name, branch, resp.data.check_runs)
19+
if (closedPR) {
20+
closedPrs.push(closedPR)
21+
}
22+
}
23+
}
24+
return closedPrs
25+
}
26+
27+
const closeDependencyPR = module.exports.closeDependencyPR = async function closeDependencyPR (owner, repo, branch, checkRuns) {
28+
if (!checkRuns) {
29+
return
30+
}
31+
// TODO, in reality multiple checks could exist and they may not all have passed
32+
const prsToClose = checkRuns.reduce((acc, check) => {
33+
if (check.status === 'completed' &&
34+
check.conclusion === 'success' &&
35+
check.pull_requests &&
36+
check.pull_requests.length !== 0) {
37+
check.pull_requests.forEach((pr) => {
38+
if (pr.head.ref === branch) {
39+
acc.push({
40+
number: pr.number
41+
})
42+
}
43+
})
44+
}
45+
return acc
46+
}, [])
47+
debug(`Dependent module: ${JSON.stringify(prsToClose, null, 2)}`)
48+
return await Promise.all(prsToClose.map((pr) => github.closePR(owner, repo, pr.number)))
49+
}

lib/config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ const dependentSchema = joi.object({
1313
'git',
1414
'git+https'
1515
]
16-
})
16+
}),
17+
pullRequest: joi.boolean().optional()
1718
}).unknown(false)
1819

1920
exports.schema = joi.object({

lib/github.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ module.exports.getWibyBranches = async function (owner, repo) {
4242
return edges.map(({ node: { branchName } }) => branchName)
4343
}
4444

45+
module.exports.getDefaultBranch = async function (owner, repo) {
46+
const resp = await graphqlWithAuth({
47+
query: queries.getDefaultBranch,
48+
owner: owner,
49+
repo: repo
50+
})
51+
return resp.repository.defaultBranchRef.name
52+
}
53+
4554
module.exports.getShas = async function getShas (owner, repo) {
4655
const resp = await octokit.repos.listCommits({
4756
owner,
@@ -136,3 +145,24 @@ module.exports.getCommitStatusesForRef = async function getCommitStatusesForRef
136145
ref: branch
137146
})
138147
}
148+
149+
module.exports.createPR = async function createPR (owner, repo, title, head, base, draft, body) {
150+
return octokit.pulls.create({
151+
owner,
152+
repo,
153+
title,
154+
head,
155+
base,
156+
draft,
157+
body
158+
})
159+
}
160+
161+
module.exports.closePR = async function closePR (owner, repo, pullNumber) {
162+
return octokit.rest.pulls.update({
163+
owner,
164+
repo,
165+
pull_number: pullNumber,
166+
state: 'closed'
167+
})
168+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
query getExistingRepoBranches($owner: String!, $repo: String!) {
2+
repository(name: $repo, owner: $owner) {
3+
defaultBranchRef {
4+
name
5+
}
6+
}
7+
}

lib/graphql/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ const path = require('path')
66
exports.getPackageJson = fs.readFileSync(path.join(__dirname, 'getPackageJson.graphql')).toString()
77

88
exports.getWibyBranches = fs.readFileSync(path.join(__dirname, 'getWibyBranches.graphql')).toString()
9+
10+
exports.getDefaultBranch = fs.readFileSync(path.join(__dirname, 'getDefaultBranch.graphql')).toString()

lib/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ exports.test = require('./test')
77
exports.result = require('./result')
88

99
exports.validate = require('./config').validate
10+
11+
exports.closePR = require('./closePR')

0 commit comments

Comments
 (0)