Repository navigation
95 lines (85 loc) · 4.29 KB
/
Copy pathaccepted-label.yml
File metadata and controls
95 lines (85 loc) · 4.29 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
name: Accepted label
# A merged PR counts on the leaderboard (oss.codercops.com) only with the
# codercops-accepted label, and only for an issue that was assigned to its
# author (CONTRIBUTING.md). PRs merged in October also get hacktoberfest-accepted.
# Maintainers add the label when they merge. This adds it when that was missed,
# by the same rule as the claim check: every issue the PR closes is assigned to
# the author. It runs once, at the merge, so removing the label later sticks.
#
# It uses pull_request_target so it can label fork PRs. That is safe here: the
# job never checks out or runs the PR's code.
on:
pull_request_target:
branches: [dev]
types: [closed]
permissions:
issues: read
pull-requests: write
jobs:
label:
name: Label a merged contributor PR
# Maintainers and bots don't claim issues, and spam never counts. Outside
# collaborators (contributors with Triage) are labeled like everyone else.
if: >-
github.event.pull_request.merged == true &&
github.event.pull_request.user.type != 'Bot' &&
!contains(fromJSON('["OWNER", "MEMBER"]'), github.event.pull_request.author_association) &&
!contains(github.event.pull_request.labels.*.name, 'codercops-accepted') &&
!contains(github.event.pull_request.labels.*.name, 'spam')
runs-on: ubuntu-latest
steps:
- name: Add the label if every linked issue is assigned to the author
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR: ${{ github.event.pull_request.number }}
MERGED_AT: ${{ github.event.pull_request.merged_at }}
run: |
set -euo pipefail
pr=$(gh api graphql \
-f owner="${REPO%/*}" -f name="${REPO#*/}" -F pr="$PR" \
-f query='query($owner: String!, $name: String!, $pr: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $pr) {
author { login }
body
closingIssuesReferences(first: 20) {
nodes { number repository { nameWithOwner } assignees(first: 20) { nodes { login } } }
}
}
}
}' \
--jq '.data.repository.pullRequest')
author=$(jq -r '.author.login // ""' <<<"$pr")
# The issues this PR closed ("Closes #12" in the description).
linked=$(jq --arg repo "$REPO" '[ .closingIssuesReferences.nodes[] | {
ref: (if .repository.nameWithOwner == $repo then "#\(.number)" else "\(.repository.nameWithOwner)#\(.number)" end),
assignees: [.assignees.nodes[].login]
} ]' <<<"$pr")
# Same fallback as the claim check: read "Closes #12" from the description.
if [ "$(jq length <<<"$linked")" -eq 0 ]; then
numbers=$(jq -r '[ (.body // "") | scan("(?i)\\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\\s*:?\\s+#([0-9]+)") | .[0] ] | unique | .[]' <<<"$pr")
for number in $numbers; do
if issue=$(gh api "repos/$REPO/issues/$number" --jq 'select(.pull_request == null) | {ref: "#\(.number)", assignees: [.assignees[].login]}' 2>/dev/null) && [ -n "$issue" ]; then
linked=$(jq --argjson issue "$issue" '. + [$issue]' <<<"$linked")
fi
done
fi
if [ "$(jq length <<<"$linked")" -eq 0 ]; then
echo "::notice title=Not labeled::This PR isn't linked to an issue, so it doesn't get codercops-accepted."
exit 0
fi
missing=$(jq -r --arg author "$author" '
[ .[]
| select(all(.assignees[]; ascii_downcase != ($author | ascii_downcase)))
| .ref ]
| join(", ")' <<<"$linked")
if [ -n "$missing" ]; then
echo "::notice title=Not labeled::$missing isn't assigned to @$author, so this PR doesn't get codercops-accepted."
exit 0
fi
labels=(-f "labels[]=codercops-accepted")
# Hacktoberfest only counts PRs merged in October (UTC).
if [ "${MERGED_AT:5:2}" = "10" ]; then labels+=(-f "labels[]=hacktoberfest-accepted"); fi
gh api -X POST "repos/$REPO/issues/$PR/labels" "${labels[@]}" --silent
echo "Labeled: $(jq -r '[.[].ref] | join(", ")' <<<"$linked") assigned to @$author"