Skip to content

Commit 8af147d

Browse files
authored
feat(CODEOWNERS): Workaround for PR reviewers (#13662)
A while ago we made this change #8868 so that we can have codeowner review requirement enforced, but still have a reference on who owns what. This prevented the codeowners from becoming a blocker especially when we have teams working across time zones. But it became a bit inconvenient as the owners of files don't get tagged in PR automatically and informed for review. This PR is meant to fix that. The new workflow file will be triggered on all PRs, identify all the modified files in the PR, and cross match with all the commented lines in CODEOWNERS files, if there's any match it will add the owners as reviewer automatically. Note: Approvals from reviewers added by this PR will not be required before PR can be merged, this is more of an informational and making sure proper teams are involved and informed on changes.
1 parent f60629e commit 8af147d

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
name: Codeowner assignment
2+
3+
on: [pull_request]
4+
5+
jobs:
6+
codeowner_assignment:
7+
name: Codeowner assignment
8+
runs-on: ubuntu-latest
9+
permissions:
10+
contents: write
11+
pull-requests: write
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- uses: actions/[email protected]
17+
id: token
18+
with:
19+
app-id: ${{ vars.CODEOWNER_ASSIGNMENT_GITHUB_APP_ID }}
20+
private-key: ${{ secrets.CODEOWNER_ASSIGNMENT_PRI_KEY }}
21+
owner: ${{ github.repository_owner }}
22+
repositories: |
23+
sentry-docs
24+
25+
- name: Parse CODEOWNERS and assign reviewers
26+
id: assign-reviewers
27+
env:
28+
PR_NUMBER: ${{ github.event.number }}
29+
GH_TOKEN: ${{ steps.token.outputs.token }}
30+
run: |
31+
# locate CODEOWNERS file exists
32+
if [[ -f .github/CODEOWNERS ]]; then
33+
codeowner_path=".github/CODEOWNERS"
34+
elif [[ -f CODEOWNERS ]]; then
35+
codeowner_path="CODEOWNERS"
36+
else
37+
echo "CODEOWNERS file not found, skipping."
38+
exit 0
39+
fi
40+
41+
# Get changed files in the PR
42+
git fetch origin ${{ github.event.pull_request.base.ref }} \
43+
${{ github.event.pull_request.head.ref }}
44+
CHANGED_FILES=$(git diff --name-only origin/${{ github.event.pull_request.base.ref }} \
45+
origin/${{ github.event.pull_request.head.ref }})
46+
47+
echo "----------------------------------------"
48+
echo "Changed files:"
49+
echo "$CHANGED_FILES" | tr ' ' '\n' | sed 's/^/- /'
50+
echo "----------------------------------------"
51+
52+
# Parse CODEOWNERS and find commented lines
53+
# Add newline to the end of the file if it doesn't have one, otherwise sed will not read the last line
54+
sed -i -e '$a\' $codeowner_path
55+
56+
while read -r LINE; do
57+
# Skip lines that are not commented, GitHub will take care of un-commented lines
58+
if [[ ! "$LINE" =~ ^# ]]; then continue; fi
59+
60+
# Extract pattern and reviewer from the commented line
61+
PATTERN=$(echo "$LINE" | sed -E 's/^#\s*([^@]+).*$/\1/' | xargs)
62+
# Capture both individual users and GitHub teams reviewers that have "/" in the name
63+
REVIEWERS=$(echo "$LINE" | grep -o "@[a-zA-Z0-9_-]\+\(/[a-zA-Z0-9_-]\+\)\?" | tr '\n' ' ' | xargs)
64+
65+
# Skip if no reviewers found
66+
if [[ -z "$REVIEWERS" ]]; then
67+
continue
68+
fi
69+
70+
# Convert pattern to a regex for matching
71+
REGEX_PATTERN=$(echo "$PATTERN" | sed -e 's/\./\\./g' -e 's/\*/.*/g' -e 's/\?/./g' -e 's|^/||')
72+
73+
# Match changed files to the pattern
74+
for FILE in $CHANGED_FILES; do
75+
# For glob patterns(e.g. "**/"), use a different matching approach
76+
if [[ "$PATTERN" == *"*"* ]]; then
77+
# Special handling for **/ pattern
78+
if [[ "$PATTERN" == "**/"* ]]; then
79+
# Get the filename part after **/
80+
FILENAME=${PATTERN#**/}
81+
# Match either the filename directly or with any path prefix
82+
if [[ "$FILE" == "$FILENAME" ]] || [[ "$FILE" == */"$FILENAME" ]]; then
83+
echo "File $FILE matches glob pattern $PATTERN"
84+
# Assign each reviewer
85+
for REVIEWER in $REVIEWERS; do
86+
# Remove @ symbol from reviewer name
87+
REVIEWER_NAME=${REVIEWER#@}
88+
echo " - Assigning $REVIEWER_NAME to review changes in $FILE"
89+
gh pr edit $PR_NUMBER --add-reviewer "$REVIEWER_NAME"
90+
done
91+
fi
92+
else
93+
# Convert other glob patterns to regex for matching
94+
GLOB_PATTERN=$(echo "$PATTERN" | sed -e 's/\./\\./g' -e 's/\*/.*/g' -e 's/\?/./g')
95+
if [[ "$FILE" =~ $GLOB_PATTERN ]]; then
96+
echo "File $FILE matches glob pattern $PATTERN"
97+
# Assign each reviewer
98+
for REVIEWER in $REVIEWERS; do
99+
# Remove @ symbol from reviewer name
100+
REVIEWER_NAME=${REVIEWER#@}
101+
echo " - Assigning $REVIEWER_NAME to review changes in $FILE"
102+
gh pr edit $PR_NUMBER --add-reviewer "$REVIEWER_NAME"
103+
done
104+
fi
105+
fi
106+
else
107+
# Original directory matching logic
108+
if [[ "$FILE" == ${REGEX_PATTERN}* ]]; then
109+
echo "File $FILE matches pattern $PATTERN"
110+
# Assign each reviewer
111+
for REVIEWER in $REVIEWERS; do
112+
# Remove @ symbol from reviewer name
113+
REVIEWER_NAME=${REVIEWER#@}
114+
echo " - Assigning $REVIEWER_NAME to review changes in $FILE"
115+
gh pr edit $PR_NUMBER --add-reviewer "$REVIEWER_NAME"
116+
done
117+
fi
118+
fi
119+
done
120+
done < $codeowner_path
121+

0 commit comments

Comments
 (0)