Repository navigation
Expand file tree
/
Copy pathreusable-cleanup-pull-requests.yml
More file actions
136 lines (115 loc) · 6.16 KB
/
Copy pathreusable-cleanup-pull-requests.yml
File metadata and controls
136 lines (115 loc) · 6.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
##
# A reusable workflow that finds and closes any pull requests that are linked to Trac
# tickets that are referenced as fixed in commit messages.
#
# More info about using GitHub pull requests for contributing to WordPress can be found in the handbook: https://make.wordpress.org/core/handbook/contribute/git/github-pull-requests-for-code-review/.
#
# This workflow is used by `trunk` and branches >= 6.8.
##
name: Run pull request cleanup
on:
workflow_call:
jobs:
# Finds and closes pull requests referencing fixed Trac tickets in commit messages using the
# documented expected format
#
# Commit message format is documented in the Core handbook: https://make.wordpress.org/core/handbook/best-practices/commit-messages/.
#
# Performs the following steps:
# - Parse fixed ticket numbers from the commit message.
# - Parse the SVN revision from the commit message.
# - Searches for pull requests referencing any fixed tickets.
# - Comments on pull requests referencing any fixed tickets before closing.
close-prs:
name: Find and close PRs
runs-on: ubuntu-24.04
permissions:
pull-requests: write
steps:
- name: Find fixed ticket numbers
id: trac-tickets
env:
COMMIT_MSG_RAW: ${{ github.event.head_commit.message }}
run: |
COMMIT_MESSAGE="$(echo "$COMMIT_MSG_RAW" | sed -n '/^Fixes #/,/\./p')"
echo "fixed_list=$(echo "$COMMIT_MESSAGE" | sed -n 's/.*Fixes #\([0-9]\+\).*/\1/p' | tr '\n' ' ')" >> "$GITHUB_OUTPUT"
- name: Get the SVN revision
id: git-svn-id
env:
COMMIT_MSG_RAW: ${{ github.event.head_commit.message }}
run: |
COMMIT_MESSAGE="$(echo "$COMMIT_MSG_RAW" | sed -n '$p')"
echo "svn_revision_number=$(echo "$COMMIT_MESSAGE" | sed -n 's/.*git-svn-id: https:\/\/develop.svn.wordpress.org\/[^@]*@\([0-9]*\) .*/\1/p')" >> "$GITHUB_OUTPUT"
- name: Find, comment on, and close pull requests
if: ${{ steps.trac-tickets.outputs.fixed_list != '' && steps.git-svn-id.outputs.svn_revision_number != '' }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
FIXED_LIST: ${{ steps.trac-tickets.outputs.fixed_list }}
SVN_REVISION_NUMBER: ${{ steps.git-svn-id.outputs.svn_revision_number }}
with:
script: |
const fixedList = process.env.FIXED_LIST.split(' ').filter(Boolean);
const svnRevisionNumber = process.env.SVN_REVISION_NUMBER;
const githubSha = process.env.GITHUB_SHA;
let prNumbers = [];
core.notice(`Processing pull request cleanup for SVN changeset: https://core.trac.wordpress.org/changeset/${svnRevisionNumber}`);
for (const ticket of fixedList) {
const tracTicketUrl = `https://core.trac.wordpress.org/ticket/${ticket}`;
const corePrefix = `core-${ticket}`;
core.info(`Ticket: ${tracTicketUrl}`);
const query = `
query($searchQuery: String!) {
search(query: $searchQuery, type: ISSUE_ADVANCED, first: 20) {
nodes {
... on PullRequest {
number
body
}
}
}
}
`;
// The PR template only asks for "a link to the WordPress Trac ticket", so some
// PRs reference it as a Markdown link with just the ticket number as the link
// text (e.g. "Trac ticket: [65864](https://core.trac.wordpress.org/ticket/65864)").
// GitHub's search index doesn't cover Markdown link targets, only the rendered
// text, so the bare ticket number is searched for too to surface those PRs.
const searchQuery = `repo:${context.repo.owner}/${context.repo.repo} is:pr is:open ( "${tracTicketUrl}" OR "${corePrefix}" OR "${ticket}" )`;
const result = await github.graphql(query, {
searchQuery,
});
// Since search queries will match anywhere for any activity on a pull request, the body
// specifically needs to be manually checked. The raw `body` (rather than `bodyText`) is used
// here because `bodyText` strips Markdown links down to just their visible text, which would
// drop the Trac ticket URL entirely for PRs that link the ticket via its number.
const matchingPRs = result.search.nodes
.filter(pr => {
const bodyLower = pr.body.toLowerCase();
return bodyLower.includes(tracTicketUrl.toLowerCase()) || bodyLower.includes(corePrefix.toLowerCase());
}).map(pr => pr.number);
prNumbers.push(...matchingPRs);
}
const commentBody = `A commit was made that fixes the Trac ticket referenced in the description of this pull request.
SVN changeset: [${svnRevisionNumber}](https://core.trac.wordpress.org/changeset/${svnRevisionNumber})
GitHub commit: https://github.com/WordPress/wordpress-develop/commit/${githubSha}
This PR will be closed, but please confirm the accuracy of this and reopen if there is more work to be done.`;
const uniquePrNumbers = [...new Set(prNumbers)];
core.info(`Found ${uniquePrNumbers.length} pull request(s) to close.`);
// Update all matched pull requests.
for (const prNumber of uniquePrNumbers) {
core.info(`Closing pull request: https://github.com/${context.repo.owner}/${context.repo.repo}/pull/${prNumber}`);
// Comment on the pull request with details.
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: commentBody
});
// Close the pull request.
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
state: 'closed'
});
}