Skip to content

Commit 9545361

Browse files
isaacroldanclaude
andcommitted
Auto-label PRs and use native release notes generation
Replaces the empty release body with GitHub's native --generate-notes output, made useful by two new pieces of automation: - .github/workflows/label-pr.yml runs on PR open/sync and inspects any changeset files added in the PR. PRs with no changeset get the no-changelog label; PRs with a changeset get an Area: @shopify/... label derived from the packages in the changeset frontmatter. Multi-package changesets fold to Area: @shopify/cli. - .github/release.yml configures --generate-notes to exclude PRs labeled no-changelog and to bucket the rest into App / Theme / CLI / Other categories using the area labels. Fork PRs are skipped by the labeler (read-only token); they fall into the Other category in release notes until labeled by hand. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 6780212 commit 9545361

3 files changed

Lines changed: 88 additions & 1 deletion

File tree

.github/release.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
changelog:
2+
exclude:
3+
labels:
4+
- no-changelog
5+
categories:
6+
- title: App
7+
labels:
8+
- "Area: @shopify/app"
9+
- title: Theme
10+
labels:
11+
- "Area: @shopify/theme"
12+
- title: CLI
13+
labels:
14+
- "Area: @shopify/cli"
15+
- title: Other
16+
labels:
17+
- "*"

.github/workflows/label-pr.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: Label PR
2+
3+
on:
4+
pull_request:
5+
types:
6+
- opened
7+
- synchronize
8+
- reopened
9+
10+
jobs:
11+
label:
12+
name: Apply labels from changesets
13+
# Skip fork PRs — GITHUB_TOKEN is read-only there and the labeling would fail.
14+
if: github.event.pull_request.head.repo.full_name == github.repository
15+
runs-on: ubuntu-latest
16+
permissions:
17+
pull-requests: write
18+
contents: read
19+
steps:
20+
- uses: actions/checkout@v4
21+
with:
22+
fetch-depth: 0
23+
- name: Determine and apply label
24+
env:
25+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26+
PR_NUM: ${{ github.event.pull_request.number }}
27+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
28+
run: |
29+
set -euo pipefail
30+
31+
CHANGESETS=$(git diff --name-only --diff-filter=A "$BASE_SHA" HEAD -- '.changeset/*.md' | grep -v 'README\.md$' || true)
32+
33+
if [ -z "$CHANGESETS" ]; then
34+
TARGET="no-changelog"
35+
else
36+
HAS_APP=0
37+
HAS_THEME=0
38+
HAS_OTHER=0
39+
while IFS= read -r FILE; do
40+
[ -z "$FILE" ] && continue
41+
FRONTMATTER=$(awk '/^---$/{c++; if (c==2) exit; next} c==1' "$FILE")
42+
while IFS= read -r PKG; do
43+
case "$PKG" in
44+
@shopify/app|@shopify/create-app) HAS_APP=1 ;;
45+
@shopify/theme) HAS_THEME=1 ;;
46+
@shopify/*) HAS_OTHER=1 ;;
47+
esac
48+
done < <(echo "$FRONTMATTER" | grep -oE "'@shopify/[a-z-]+'" | tr -d "'")
49+
done <<< "$CHANGESETS"
50+
51+
AREA_COUNT=$((HAS_APP + HAS_THEME + HAS_OTHER))
52+
if [ "$AREA_COUNT" -eq 1 ] && [ "$HAS_APP" -eq 1 ]; then
53+
TARGET="Area: @shopify/app"
54+
elif [ "$AREA_COUNT" -eq 1 ] && [ "$HAS_THEME" -eq 1 ]; then
55+
TARGET="Area: @shopify/theme"
56+
else
57+
TARGET="Area: @shopify/cli"
58+
fi
59+
fi
60+
61+
echo "Target label: $TARGET"
62+
63+
# Idempotently keep only the target label from the managed set.
64+
for L in "no-changelog" "Area: @shopify/app" "Area: @shopify/theme" "Area: @shopify/cli"; do
65+
if [ "$L" = "$TARGET" ]; then
66+
gh pr edit "$PR_NUM" --add-label "$L"
67+
else
68+
gh pr edit "$PR_NUM" --remove-label "$L" 2>/dev/null || true
69+
fi
70+
done

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ jobs:
166166
fi
167167
gh release create "$TAG" \
168168
--title "$TAG" \
169-
--notes "" \
169+
--generate-notes \
170170
--latest=legacy
171171
echo "Created release $TAG"
172172

0 commit comments

Comments
 (0)