Skip to content

Commit

Permalink
include-paths: Permit filtering only PRs that modify path prefixes (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Devon Stewart committed Mar 3, 2022
1 parent d8ca1fa commit 836e045
Show file tree
Hide file tree
Showing 18 changed files with 675 additions and 22 deletions.
77 changes: 62 additions & 15 deletions bin/generate-fixtures.js
Expand Up @@ -3,7 +3,10 @@
const fs = require('fs')
const path = require('path')
const fetch = require('node-fetch')
const { findCommitsWithAssociatedPullRequestsQuery } = require('../lib/commits')
const {
findCommitsWithAssociatedPullRequestsQuery,
findCommitsWithPathChangesQuery,
} = require('../lib/commits')

const REPO_NAME = 'release-drafter-test-repo'
const GITHUB_GRAPHQL_API_ENDPOINT = 'https://api.github.com/graphql'
Expand Down Expand Up @@ -38,25 +41,14 @@ const repos = [
},
]

for (const repo of repos) {
const runQuery = (kind, repo, body) => {
const options = {
body,
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `bearer ${GITHUB_TOKEN}`,
},
body: JSON.stringify({
query: findCommitsWithAssociatedPullRequestsQuery,
variables: {
owner: repo.owner,
name: REPO_NAME,
ref: repo.branch,
withPullRequestBody: true,
withPullRequestURL: true,
withBaseRefName: true,
withHeadRefName: true,
},
}),
}

fetch(GITHUB_GRAPHQL_API_ENDPOINT, options)
Expand All @@ -72,10 +64,65 @@ for (const repo of repos) {
path.resolve(
__dirname,
'../test/fixtures/__generated__',
`graphql-commits-${repo.branch}.json`
`graphql-${kind}-${repo.branch}.json`
),
string + '\n'
)
})
.catch(console.error)
}

for (const repo of repos) {
runQuery(
'commits',
repo,
JSON.stringify({
query: findCommitsWithAssociatedPullRequestsQuery,
variables: {
owner: repo.owner,
name: REPO_NAME,
targetCommitish: repo.branch,
withPullRequestBody: true,
withPullRequestURL: true,
withBaseRefName: true,
withHeadRefName: true,
},
})
)

runQuery(
'include-null-path',
repo,
JSON.stringify({
query: findCommitsWithPathChangesQuery,
variables: {
owner: repo.owner,
name: REPO_NAME,
targetCommitish: repo.branch,
withPullRequestBody: true,
withPullRequestURL: true,
withBaseRefName: true,
withHeadRefName: true,
path: null,
},
})
)

runQuery(
'include-path-src-5.md',
repo,
JSON.stringify({
query: findCommitsWithPathChangesQuery,
variables: {
owner: repo.owner,
name: REPO_NAME,
targetCommitish: repo.branch,
withPullRequestBody: true,
withPullRequestURL: true,
withBaseRefName: true,
withHeadRefName: true,
path: 'src/5.md',
},
})
)
}
77 changes: 74 additions & 3 deletions dist/index.js
Expand Up @@ -128725,6 +128725,33 @@ const _ = __nccwpck_require__(90250)
const { log } = __nccwpck_require__(71911)
const { paginate } = __nccwpck_require__(46418)

const findCommitsWithPathChangesQuery = /* GraphQL */ `
query findCommitsWithPathChangesQuery(
$name: String!
$owner: String!
$targetCommitish: String!
$since: GitTimestamp
$after: String
$path: String
) {
repository(name: $name, owner: $owner) {
object(expression: $targetCommitish) {
... on Commit {
history(path: $path, since: $since, after: $after) {
pageInfo {
hasNextPage
endCursor
}
nodes {
id
}
}
}
}
}
}
`

const findCommitsWithAssociatedPullRequestsQuery = /* GraphQL */ `
query findCommitsWithAssociatedPullRequests(
$name: String!
Expand Down Expand Up @@ -128804,10 +128831,40 @@ const findCommitsWithAssociatedPullRequests = async ({
withBaseRefName: config['change-template'].includes('$BASE_REF_NAME'),
withHeadRefName: config['change-template'].includes('$HEAD_REF_NAME'),
}
const includePaths = config['include-paths']
const dataPath = ['repository', 'object', 'history']
const repoNameWithOwner = `${owner}/${repo}`

let data, commits
let data,
allCommits,
includedIds = {}

if (includePaths.length > 0) {
var anyChanges = false
for (const path of includePaths) {
const pathData = await paginate(
context.octokit.graphql,
findCommitsWithPathChangesQuery,
lastRelease
? { ...variables, since: lastRelease.created_at, path }
: { ...variables, path },
dataPath
)
const commitsWithPathChanges = _.get(pathData, [...dataPath, 'nodes'])

includedIds[path] = includedIds[path] || new Set([])
for (const { id } of commitsWithPathChanges) {
anyChanges = true
includedIds[path].add(id)
}
}

if (!anyChanges) {
// Short circuit to avoid blowing GraphQL budget
return { commits: [], pullRequests: [] }
}
}

if (lastRelease) {
log({
context,
Expand All @@ -128822,7 +128879,7 @@ const findCommitsWithAssociatedPullRequests = async ({
)
// GraphQL call is inclusive of commits from the specified dates. This means the final
// commit from the last tag is included, so we remove this here.
commits = _.get(data, [...dataPath, 'nodes']).filter(
allCommits = _.get(data, [...dataPath, 'nodes']).filter(
(commit) => commit.committedDate != lastRelease.created_at
)
} else {
Expand All @@ -128834,9 +128891,16 @@ const findCommitsWithAssociatedPullRequests = async ({
variables,
dataPath
)
commits = _.get(data, [...dataPath, 'nodes'])
allCommits = _.get(data, [...dataPath, 'nodes'])
}

const commits =
includePaths.length > 0
? allCommits.filter((commit) =>
includePaths.some((path) => includedIds[path].has(commit.id))
)
: allCommits

const pullRequests = _.uniqBy(
commits.flatMap((commit) => commit.associatedPullRequests.nodes),
'number'
Expand All @@ -128850,6 +128914,8 @@ const findCommitsWithAssociatedPullRequests = async ({
exports.findCommitsWithAssociatedPullRequestsQuery =
findCommitsWithAssociatedPullRequestsQuery

exports.findCommitsWithPathChangesQuery = findCommitsWithPathChangesQuery

exports.findCommitsWithAssociatedPullRequests =
findCommitsWithAssociatedPullRequests

Expand Down Expand Up @@ -128944,6 +129010,7 @@ const DEFAULT_CONFIG = Object.freeze({
categories: [],
'exclude-labels': [],
'include-labels': [],
'include-paths': [],
'exclude-contributors': [],
'no-contributors-template': 'No contributors',
replacers: [],
Expand Down Expand Up @@ -129514,6 +129581,10 @@ const schema = (context) => {
.items(Joi.string())
.default(DEFAULT_CONFIG['include-labels']),

'include-paths': Joi.array()
.items(Joi.string())
.default(DEFAULT_CONFIG['include-paths']),

'exclude-contributors': Joi.array()
.items(Joi.string())
.default(DEFAULT_CONFIG['exclude-contributors']),
Expand Down
72 changes: 69 additions & 3 deletions lib/commits.js
Expand Up @@ -2,6 +2,33 @@ const _ = require('lodash')
const { log } = require('./log')
const { paginate } = require('./pagination')

const findCommitsWithPathChangesQuery = /* GraphQL */ `
query findCommitsWithPathChangesQuery(
$name: String!
$owner: String!
$targetCommitish: String!
$since: GitTimestamp
$after: String
$path: String
) {
repository(name: $name, owner: $owner) {
object(expression: $targetCommitish) {
... on Commit {
history(path: $path, since: $since, after: $after) {
pageInfo {
hasNextPage
endCursor
}
nodes {
id
}
}
}
}
}
}
`

const findCommitsWithAssociatedPullRequestsQuery = /* GraphQL */ `
query findCommitsWithAssociatedPullRequests(
$name: String!
Expand Down Expand Up @@ -81,10 +108,40 @@ const findCommitsWithAssociatedPullRequests = async ({
withBaseRefName: config['change-template'].includes('$BASE_REF_NAME'),
withHeadRefName: config['change-template'].includes('$HEAD_REF_NAME'),
}
const includePaths = config['include-paths']
const dataPath = ['repository', 'object', 'history']
const repoNameWithOwner = `${owner}/${repo}`

let data, commits
let data,
allCommits,
includedIds = {}

if (includePaths.length > 0) {
var anyChanges = false
for (const path of includePaths) {
const pathData = await paginate(
context.octokit.graphql,
findCommitsWithPathChangesQuery,
lastRelease
? { ...variables, since: lastRelease.created_at, path }
: { ...variables, path },
dataPath
)
const commitsWithPathChanges = _.get(pathData, [...dataPath, 'nodes'])

includedIds[path] = includedIds[path] || new Set([])
for (const { id } of commitsWithPathChanges) {
anyChanges = true
includedIds[path].add(id)
}
}

if (!anyChanges) {
// Short circuit to avoid blowing GraphQL budget
return { commits: [], pullRequests: [] }
}
}

if (lastRelease) {
log({
context,
Expand All @@ -99,7 +156,7 @@ const findCommitsWithAssociatedPullRequests = async ({
)
// GraphQL call is inclusive of commits from the specified dates. This means the final
// commit from the last tag is included, so we remove this here.
commits = _.get(data, [...dataPath, 'nodes']).filter(
allCommits = _.get(data, [...dataPath, 'nodes']).filter(
(commit) => commit.committedDate != lastRelease.created_at
)
} else {
Expand All @@ -111,9 +168,16 @@ const findCommitsWithAssociatedPullRequests = async ({
variables,
dataPath
)
commits = _.get(data, [...dataPath, 'nodes'])
allCommits = _.get(data, [...dataPath, 'nodes'])
}

const commits =
includePaths.length > 0
? allCommits.filter((commit) =>
includePaths.some((path) => includedIds[path].has(commit.id))
)
: allCommits

const pullRequests = _.uniqBy(
commits.flatMap((commit) => commit.associatedPullRequests.nodes),
'number'
Expand All @@ -127,5 +191,7 @@ const findCommitsWithAssociatedPullRequests = async ({
exports.findCommitsWithAssociatedPullRequestsQuery =
findCommitsWithAssociatedPullRequestsQuery

exports.findCommitsWithPathChangesQuery = findCommitsWithPathChangesQuery

exports.findCommitsWithAssociatedPullRequests =
findCommitsWithAssociatedPullRequests
1 change: 1 addition & 0 deletions lib/default-config.js
Expand Up @@ -16,6 +16,7 @@ const DEFAULT_CONFIG = Object.freeze({
categories: [],
'exclude-labels': [],
'include-labels': [],
'include-paths': [],
'exclude-contributors': [],
'no-contributors-template': 'No contributors',
replacers: [],
Expand Down
4 changes: 4 additions & 0 deletions lib/schema.js
Expand Up @@ -51,6 +51,10 @@ const schema = (context) => {
.items(Joi.string())
.default(DEFAULT_CONFIG['include-labels']),

'include-paths': Joi.array()
.items(Joi.string())
.default(DEFAULT_CONFIG['include-paths']),

'exclude-contributors': Joi.array()
.items(Joi.string())
.default(DEFAULT_CONFIG['exclude-contributors']),
Expand Down
1 change: 0 additions & 1 deletion test/fixtures/__generated__/README.md

This file was deleted.

0 comments on commit 836e045

Please sign in to comment.