Skip to content

Commit f375625

Browse files
Use shared workflow
1 parent 6d8feea commit f375625

File tree

1 file changed

+1
-159
lines changed

1 file changed

+1
-159
lines changed

.github/workflows/pr-quality.yml

Lines changed: 1 addition & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -8,164 +8,6 @@ env:
88
on:
99
pull_request:
1010
types: [opened, edited, synchronize, labeled, unlabeled, reopened]
11-
12-
permissions:
13-
contents: read
14-
pull-requests: write
15-
issues: write
16-
1711
jobs:
1812
pr-checklist:
19-
runs-on: ubuntu-latest
20-
21-
steps:
22-
- name: Validate PR quality
23-
id: validate
24-
env:
25-
TITLE: ${{ github.event.pull_request.title }}
26-
BODY: ${{ github.event.pull_request.body }}
27-
LABELS_CSV: ${{ join(github.event.pull_request.labels.*.name, ',') }}
28-
run: |
29-
set -euo pipefail
30-
31-
failures=""
32-
33-
# ---- Settings ----
34-
MIN_WORDS=5
35-
MAX_WORDS=18
36-
TITLE_BYPASS_LABEL="pr:ignore-for-release"
37-
38-
has_label () {
39-
case ",${LABELS_CSV}," in
40-
*,"$1",*) return 0 ;;
41-
*) return 1 ;;
42-
esac
43-
}
44-
45-
has_any_pr_label () {
46-
IFS=',' read -ra LBL <<< "${LABELS_CSV}"
47-
for l in "${LBL[@]}"; do
48-
l="$(echo "$l" | xargs)"
49-
[[ $l == pr:* ]] && return 0
50-
done
51-
return 1
52-
}
53-
54-
# --- 1) Title check
55-
if ! has_label "$TITLE_BYPASS_LABEL"; then
56-
title_words=$(echo "$TITLE" | tr -s '[:space:]' ' ' | sed -e 's/^ *//' -e 's/ *$//' | wc -w | xargs)
57-
if [ -z "$title_words" ]; then title_words=0; fi
58-
if [ "$title_words" -lt "$MIN_WORDS" ] || [ "$title_words" -gt "$MAX_WORDS" ]; then
59-
failures="${failures}\n- **Title** should be ${MIN_WORDS}–${MAX_WORDS} words for release notes. Current: ${title_words} word(s). (Add \`${TITLE_BYPASS_LABEL}\` to bypass.)"
60-
fi
61-
fi
62-
63-
# --- 2) Has pr:* label
64-
if ! has_any_pr_label; then
65-
failures="${failures}\n- Missing required label: at least one label starting with \`pr:\`."
66-
fi
67-
68-
# --- 3) Sections non-empty
69-
section_nonempty () {
70-
local hdr="$1"
71-
local section
72-
section="$(printf "%s" "$BODY" | awk -v h="^###[[:space:]]*$hdr[[:space:]]*$" '
73-
BEGIN { insec=0 }
74-
$0 ~ h { insec=1; next }
75-
insec && $0 ~ /^##[[:space:]]/ { insec=0 }
76-
insec { print }
77-
')"
78-
section="$(printf "%s" "$section" \
79-
| sed -E 's/<!--(.|\n)*?-->//g' \
80-
| sed -E 's/^[[:space:]]+|[[:space:]]+$//g' \
81-
| sed '/^[[:space:]]*$/d')"
82-
[ -n "$section" ]
83-
}
84-
85-
for hdr in Goal Implementation Testing; do
86-
if ! section_nonempty "$hdr"; then
87-
failures="${failures}\n- Section **${hdr}** is missing or empty."
88-
fi
89-
done
90-
91-
if [ -n "$failures" ]; then
92-
echo "has_failures=true" >> "$GITHUB_OUTPUT"
93-
{
94-
echo 'failures<<EOF'
95-
printf "%b\n" "$failures"
96-
echo 'EOF'
97-
} >> "$GITHUB_OUTPUT"
98-
exit 1
99-
else
100-
echo "has_failures=false" >> "$GITHUB_OUTPUT"
101-
fi
102-
103-
# Compute the latest sticky comment id (by our anchor). If none, output is empty.
104-
- name: Compute sticky comment id
105-
if: always()
106-
id: sticky_comment
107-
uses: actions/github-script@v7
108-
with:
109-
script: |
110-
const anchor = "<!-- pr-quality-anchor -->"; // must match the body below
111-
const { owner, repo } = context.repo;
112-
const issue_number = context.payload.pull_request.number;
113-
114-
// Get up to 100 comments; paginate to be safe.
115-
const comments = await github.paginate(
116-
github.rest.issues.listComments,
117-
{ owner, repo, issue_number, per_page: 100 }
118-
);
119-
120-
const matches = comments.filter(c => (c.body || "").includes(anchor));
121-
if (matches.length === 0) {
122-
core.setOutput("comment_id", "");
123-
return;
124-
}
125-
// Pick the most recently updated one
126-
matches.sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at));
127-
core.setOutput("comment_id", String(matches[0].id));
128-
129-
- name: Sticky comment id
130-
if: always()
131-
run: echo "sticky comment-id=${{ steps.sticky_comment.outputs.comment_id }}"
132-
133-
# Update/create the sticky comment on failure
134-
- name: Create or update failure comment
135-
if: failure()
136-
uses: peter-evans/create-or-update-comment@v4
137-
with:
138-
issue-number: ${{ github.event.pull_request.number }}
139-
comment-id: ${{ steps.sticky_comment.outputs.comment_id }} # empty => creates new
140-
edit-mode: replace
141-
body: |
142-
<!-- pr-quality-anchor -->
143-
### PR checklist ❌
144-
145-
The following issues were detected:
146-
147-
${{ steps.validate.outputs.failures }}
148-
149-
**What we check**
150-
1. Title is concise (5–18 words) unless labeled `pr:ignore-for-release`.
151-
2. At least one `pr:` label exists (e.g., `pr:bug`, `pr:new-feature`).
152-
3. Sections `### Goal`, `### Implementation`, and `### Testing` contain content.
153-
154-
# Flip the same sticky comment to ✅ on success
155-
- name: Create or update success comment
156-
if: success()
157-
uses: peter-evans/create-or-update-comment@v4
158-
with:
159-
issue-number: ${{ github.event.pull_request.number }}
160-
comment-id: ${{ steps.sticky_comment.outputs.comment_id }} # updates if found
161-
edit-mode: replace
162-
body: |
163-
<!-- pr-quality-anchor -->
164-
### PR checklist ✅
165-
166-
All required conditions are satisfied:
167-
- Title length is OK (or ignored by label).
168-
- At least one `pr:` label exists.
169-
- Sections `### Goal`, `### Implementation`, and `### Testing` are filled.
170-
171-
🎉 Great job! This PR is ready for review.
13+
uses: GetStream/android-ci-actions/.github/workflows/pr-quality.yml@main

0 commit comments

Comments
 (0)