Skip to content

Commit 48dedd8

Browse files
authored
Script that automatically applies labels to github
* Script that automatically applies labels to github * Add action to auto-run on PRs
1 parent 3f03d20 commit 48dedd8

File tree

2 files changed

+224
-0
lines changed

2 files changed

+224
-0
lines changed

.github/workflows/auto-triage.yml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Triage
2+
on:
3+
pull_request:
4+
types:
5+
- opened
6+
- edited
7+
branches:
8+
- master
9+
paths:
10+
- 'xep-*.xml'
11+
jobs:
12+
label_pr:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
pull-requests: write
16+
steps:
17+
- uses: awalsh128/cache-apt-pkgs-action@latest
18+
with:
19+
packages: libxml2-utils
20+
version: cachetag1
21+
22+
- run: bash tools/github_auto_triage_pr.sh ${{ github.event.pull_request.number }}
23+
env:
24+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25+
GH_REPO: ${{ github.repository }}

tools/github_auto_triage_pr.sh

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
#!/bin/bash
2+
3+
# this should enforce as much of docs/TRIAGING.md as possible, run in top directory of xeps repo
4+
5+
# usage: triage.sh $pr_number
6+
# the last two will be HEAD and `git merge-base $pr_commit master` by default if not sent in
7+
8+
# for testing you can:
9+
# git fetch origin +refs/pull/1254/merge
10+
# git checkout FETCH_HEAD
11+
# and only send in pr_title
12+
13+
# test cases:
14+
# multiple xeps changed: git checkout 58cec1b6fb30ccc3b44c9dff34b94f53e958c1ac; ./tools/triage.sh 'XEP-0072, XEP-0096, XEP-0214: fix xmlns in sipub examples' 58cec1b6fb30ccc3b44c9dff34b94f53e958c1ac e4d3f721c2cf9fc7ed42c3428d098b2b3be3c8ed
15+
# protoxep: git fetch origin +refs/pull/1254/merge; git checkout FETCH_HEAD; ./tools/triage.sh "ProtoXEP: Stream Limits Advertisement"
16+
# one xep changed: git fetch origin +refs/pull/1249/merge; git checkout FETCH_HEAD; ./tools/triage.sh 'XEP-0444: bla'
17+
18+
set -euo pipefail
19+
20+
pr_number="$1"
21+
shift
22+
pr_title="$(gh pr view "$pr_number" --json title -q .title)"
23+
24+
pr_commit="$(gh pr view "$pr_number" --json headRefOid -q .headRefOid)"
25+
merge_base="$(git merge-base "$pr_commit" "$(gh pr view "$pr_number" --json baseRefName -q .baseRefName)")"
26+
27+
xpath() {
28+
set -euo pipefail
29+
xmllint --nonet --noent --xpath "$2" "$1" --nowarning --dtdvalid xep.dtd
30+
}
31+
32+
add_tag() {
33+
gh pr edit "$pr_number" --add-label "$1"
34+
}
35+
36+
files_changed="$(git --no-pager diff --name-only "$pr_commit" "$merge_base")"
37+
38+
set +e
39+
protoxep="$(echo "$files_changed" | grep -E '^inbox/[^.]+.xml$')"
40+
num_protoxeps=$(echo "$protoxep" | grep -v '^$' | wc -l)
41+
42+
xeps_changed="$(echo "$files_changed" | grep -E '^xep-[0-9]{4}.xml$')"
43+
xep_likes_changed="$(echo "$files_changed" | grep -E '^xep-[^.]+.xml$')"
44+
num_xeps_changed=$(echo "$xeps_changed" | grep -v '^$' | wc -l)
45+
set -e
46+
47+
if [ $num_protoxeps -ge 1 ]
48+
then
49+
if [ $num_xeps_changed -ne 0 ]
50+
then
51+
echo "cannot change xeps and add ProtoXEP in 1 PR"
52+
exit 1
53+
fi
54+
# we are dealing with a protoxep here
55+
add_tag "ProtoXEP"
56+
if [ $num_protoxeps -ne 1 ]
57+
then
58+
echo "multiple ProtoXEPs cannot be created in 1 PR"
59+
exit 1
60+
fi
61+
expected_title="ProtoXEP: $(xpath "$protoxep" '/xep/header/title/text()')"
62+
if [ "$pr_title" != "$expected_title" ]
63+
then
64+
echo "expected title '$expected_title' got title '$pr_title'"
65+
exit 1
66+
fi
67+
add_tag "Ready to Merge"
68+
echo "manual: be sure type '$(xpath "$protoxep" '/xep/header/type/text()')' is appropriate for XEP content"
69+
exit 0
70+
fi
71+
72+
# we are *not* dealing with a protoxep here
73+
if [ "$xeps_changed" != "$xep_likes_changed" ]
74+
then
75+
echo "xep files created/changed but named incorrectly: $(echo "$xep_likes_changed" | tr '\n' ' ')"
76+
exit 1
77+
fi
78+
79+
if [ $num_xeps_changed -eq 0 ]
80+
then
81+
# some tag for this? tooling changes?
82+
echo "manual: no XEPs changed"
83+
exit 0
84+
fi
85+
86+
if [ $num_xeps_changed -gt 1 ]
87+
then
88+
echo "multiple XEPs changed"
89+
exit 1
90+
fi
91+
92+
all_approvers=""
93+
# a super approver can approve this entire PR, because they are author on all XEPs touched
94+
super_approvers=""
95+
for xep in $xeps_changed
96+
do
97+
xep_num="XEP-$(echo "$xep" | grep -Eo '[0-9]{4}')"
98+
if ! echo "$pr_title" | grep "$xep_num" &>/dev/null
99+
then
100+
echo "title did not include '$xep_num'"
101+
exit 1
102+
fi
103+
104+
status="$(xpath "$xep" '/xep/header/status/text()')"
105+
approvers=""
106+
if echo "$status" | grep -E '^(Experimental|Deferred)$' &>/dev/null
107+
then
108+
# Experimental or Deferred
109+
if [ "$status" == 'Deferred' ]
110+
then
111+
add_tag "Needs Editor Action"
112+
echo "move $xep_num status to Experimental before or with merge"
113+
exit 1
114+
fi
115+
116+
approvers="$(xpath "$xep" '/xep/header/author/email/text()' | sort -u)"
117+
else
118+
# *not* Experimental or Deferred
119+
approvers="$(xpath "$xep" '/xep/header/approver/text()' 2>/dev/null || echo 'Unknown')"
120+
fi
121+
122+
echo "info: $xep_num status '$status' needs approvers: '$(echo "$approvers" | tr '\n' ' ' | xargs)'"
123+
124+
new_all_approvers="$(echo -e "$all_approvers\n$approvers" | sort -u)"
125+
if [ "$all_approvers" != "$new_all_approvers" ]
126+
then
127+
# this isn't technically a problem if they all have an approver in common, ie super_approvers is non-empty, suppress warning?
128+
if [ "$all_approvers" != "" ]
129+
then
130+
echo "multiple XEPs modified with different approvers"
131+
super_approvers="$(comm -12 <(echo "$super_approvers") <(echo "$approvers") | sort -u)"
132+
exit 1
133+
else
134+
super_approvers="$new_all_approvers"
135+
fi
136+
all_approvers="$new_all_approvers"
137+
fi
138+
139+
# check revision block added and minor version bump
140+
versions="$(xpath "$xep" '/xep/header/revision/version/text()')"
141+
latest_num_versions="$(echo "$versions" | wc -l)"
142+
latest_version="$(echo "$versions" | head -n1)"
143+
# this git-cat-file usage assumes no entities etc are ever removed from xep.ent etc, this should be true
144+
# but if it ever isn't, then we'll have to check out the entire repo as of $merge_base to do that
145+
versions="$(git cat-file -p "$merge_base:./$xep" | xpath - '/xep/header/revision/version/text()')"
146+
merge_base_num_versions="$(echo "$versions" | wc -l)"
147+
merge_base_version="$(echo "$versions" | head -n1)"
148+
if [ $latest_num_versions -gt $merge_base_num_versions ]
149+
then
150+
if ! echo "$latest_version" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' &>/dev/null
151+
then
152+
echo "version is not semver format: '$latest_version'"
153+
exit 1
154+
fi
155+
if [ "$latest_version" == "$merge_base_version" ]
156+
then
157+
add_tag "Needs Version Block"
158+
# todo: anyone have a fancy way to check semver is higher in $latest_version ?
159+
# beware we have funky non-semver versions
160+
# for xep in xep-*.xml; do xpath "$xep" '/xep/header/revision/version/text()'; done | sort -u > xep_versions.txt
161+
fi
162+
else
163+
add_tag "Needs Version Block"
164+
fi
165+
done
166+
167+
if [ "$super_approvers" != "" ]
168+
then
169+
pr_authors="$(git --no-pager log --format="%aE" "$merge_base".."$pr_commit" | sort -u)"
170+
pr_authors_super_approvers="$(comm -12 <(echo "$super_approvers") <(echo "$pr_authors") | sort -u)"
171+
if [ "$pr_authors_super_approvers" != "" ]
172+
then
173+
echo "info: entire PR can be approved by one of the commit authors: '$(echo "$pr_authors" | tr '\n' ' ' | xargs)'"
174+
fi
175+
echo "info: entire PR can be approved by: '$(echo "$super_approvers" | tr '\n' ' ' | xargs)'"
176+
fi
177+
178+
if echo "$all_approvers" | grep '^Council$' &>/dev/null
179+
then
180+
add_tag "Needs Council"
181+
fi
182+
183+
if echo "$all_approvers" | grep '^Board$' &>/dev/null
184+
then
185+
add_tag "Needs Board"
186+
fi
187+
188+
if echo "$all_approvers" | grep '^Unknown$' &>/dev/null
189+
then
190+
echo "approver is unknown, perhaps old XEP that needs fixed?"
191+
exit 1
192+
fi
193+
194+
if echo "$all_approvers" | grep '@' &>/dev/null
195+
then
196+
add_tag "Needs Author"
197+
fi
198+
199+
echo "manual: if only editorial changes, may not need approval"

0 commit comments

Comments
 (0)