Skip to content

Commit

Permalink
feat: --find-matching-prs for commits without PR-URL (#130)
Browse files Browse the repository at this point in the history
  • Loading branch information
rvagg authored Jun 16, 2022
1 parent 2a87620 commit 0aa7a2e
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 10 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ npm i changelog-maker -g

## Usage

**`changelog-maker [--plaintext|p] [--markdown|md] [--sha] [--group|-g] [--reverse] [--commit-url=<url/with/{ref}>] [--start-ref=<ref>] [--end-ref=<ref>] [github-user[, github-project]]`**
**`changelog-maker [--plaintext|p] [--markdown|md] [--sha] [--group|-g] [--reverse] [--find-matching-prs] [--commit-url=<url/with/{ref}>] [--start-ref=<ref>] [--end-ref=<ref>] [github-user[, github-project]]`**

`github-user` and `github-project` should point to the GitHub repository that can be used to find the `PR-URL` data if just an issue number is provided and will also impact how the PR-URL issue numbers are displayed

Expand All @@ -62,6 +62,7 @@ npm i changelog-maker -g
* `--start-ref=<ref>`: use the given git `<ref>` as a starting point rather than the _last tag_. The `<ref>` can be anything commit-ish including a commit sha, tag, branch name. If you specify a `--start-ref` argument the commit log will not be pruned so that version commits and `working on <version>` commits are left in the list.
* `--end-ref=<ref>`: use the given git `<ref>` as a end-point rather than the _now_. The `<ref>` can be anything commit-ish including a commit sha, tag, branch name.
* `--filter-release`: exclude Node-style release commits from the list. e.g. "Working on v1.0.0" or "2015-10-21 Version 2.0.0" and also "npm version X" style commits containing _only_ an `x.y.z` semver designator.
* `--find-matching-prs`: use the GitHub API to find the pull requests that match commits that don't have the `PR-URL` metadata in their message text. Without metadata, it may be necessary to also pass the org/user and repo name on the commandline (as the `github-user` and `github-project` arguments as demonstrated above, it may also be necessary to use `--find-matching-prs=true` in this case).
* `--quiet` or `-q`: do not print to `process.stdout`
* `--all` or `-a`: process all commits since beginning, instead of last tag.
* `--help` or `-h`: show usage and help.
Expand Down
12 changes: 12 additions & 0 deletions auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { promisify } from 'util'
import ghauth from 'ghauth'

const authOptions = {
configName: 'changelog-maker',
scopes: ['repo'],
noDeviceFlow: true
}

export async function auth () {
return await promisify(ghauth)(authOptions)
}
11 changes: 2 additions & 9 deletions collect-commit-labels.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
'use strict'

import { promisify } from 'util'
import ghauth from 'ghauth'
import { auth } from './auth.js'
import ghissues from 'ghissues'
import async from 'async'

const authOptions = {
configName: 'changelog-maker',
scopes: ['repo'],
noDeviceFlow: true
}

export async function collectCommitLabels (list) {
const sublist = list.filter((commit) => {
return typeof commit.ghIssue === 'number' && commit.ghUser && commit.ghProject
Expand All @@ -20,7 +13,7 @@ export async function collectCommitLabels (list) {
return
}

const authData = await promisify(ghauth)(authOptions)
const authData = await auth()

const cache = {}

Expand Down
72 changes: 72 additions & 0 deletions find-matching-prs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'use strict'

import { auth } from './auth.js'
import { graphql } from '@octokit/graphql'
import async from 'async'

// Query to find the first 4 pull requests that include the commit that we're
// concerned about. We'll filter them and take the first one that was MERGED
// as our prUrl.
const query = `
query ($owner: String!, $name: String!, $commit: GitObjectID!) {
repository(owner: $owner, name: $name) {
object(oid: $commit) {
... on Commit {
associatedPullRequests(first: 4) {
... on PullRequestConnection {
edges {
node {
... on PullRequest {
number
url
title
state
}
}
}
}
}
}
}
}
}
`

export async function findMatchingPrs (ghId, list) {
// only look up commits that don't have a prUrl from metadata
const sublist = list.filter((commit) => typeof commit.prUrl !== 'string')
if (!sublist.length) {
return
}

const authData = await auth()
const headers = { authorization: `token ${authData.token}` }
const cache = {}

const q = async.queue(async (commit, next) => {
if (commit.ghUser === 'iojs') {
commit.ghUser = 'nodejs' // forcibly rewrite as the GH API doesn't do it for us
}

// cache on commit, so we don't run the same commit twice (is this possible?)
cache[commit.sha] = cache[commit.sha] || (async () => {
try {
const res = await graphql(query, { owner: ghId.user, name: ghId.repo, commit: commit.sha, headers })
if (res.repository?.object?.associatedPullRequests?.edges?.length) {
const pr = res.repository.object.associatedPullRequests.edges.filter((e) => e.node?.state === 'MERGED')[0]
if (pr) {
commit.ghIssue = pr.node.number
commit.prUrl = pr.node.url
}
}
} catch (err) {
console.error(`Error querying GitHub to find pull request for commit: ${err}`)
}
})()
await cache[commit.sha]
next()
}, 15)

q.push(sublist)
await q.drain()
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"keywords": [],
"preferGlobal": true,
"dependencies": {
"@octokit/graphql": "^4.8.0",
"async": "^3.2.2",
"chalk": "^5.0.0",
"commit-stream": "^1.1.0",
Expand Down
5 changes: 5 additions & 0 deletions process-commits.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { toGroups } from './groups.js'
import { formatMarkdown } from './format.js'
import { supportsColor } from 'chalk'
import { collectCommitLabels } from './collect-commit-labels.js'
import { findMatchingPrs } from './find-matching-prs.js'

function getFormat (argv) {
if (argv.format && Object.values(formatType).includes(argv.format)) {
Expand Down Expand Up @@ -33,6 +34,10 @@ export async function processCommits (argv, ghId, list) {
const reverse = argv.reverse
const commitUrl = argv['commit-url'] || 'https://github.com/{ghUser}/{ghRepo}/commit/{ref}'

if (argv['find-matching-prs']) {
await findMatchingPrs(ghId, list)
}

await collectCommitLabels(list)

const format = getFormat(argv)
Expand Down
8 changes: 8 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,11 @@ test('test markdown punctuation chars in commit message and author name', (t) =>
`)
t.end()
})

test('test find-matching-prs', (t) => {
t.equal(
exec('--start-ref=a059bc7ca9 --end-ref=a059bc7ca9 --find-matching-prs=true nodejs changelog-maker'),
`* [a059bc7ca9] - chore(deps): remove package-lock.json (#118) (Rod Vagg) https://github.com/nodejs/changelog-maker/pull/118
`)
t.end()
})

0 comments on commit 0aa7a2e

Please sign in to comment.