@@ -2,12 +2,16 @@ name: Check Changeset
22
33on :
44 pull_request :
5+ types : [opened, synchronize, edited]
56 branches :
67 - main
78
89jobs :
910 changeset-check :
1011 runs-on : ubuntu-latest
12+ permissions :
13+ contents : read
14+ pull-requests : write
1115 steps :
1216 - name : Checkout
1317 uses : actions/checkout@v4
@@ -19,18 +23,95 @@ jobs:
1923 with :
2024 node-version : " 20"
2125
26+ - name : Check for skip changeset flag
27+ id : skip_check
28+ uses : actions/github-script@v7
29+ with :
30+ script : |
31+ const { data: pr } = await github.rest.pulls.get({
32+ owner: context.repo.owner,
33+ repo: context.repo.repo,
34+ pull_number: context.issue.number,
35+ });
36+
37+ const prBody = pr.body || '';
38+ const shouldSkip = prBody.includes('#skip-changeset');
39+
40+ if (shouldSkip) {
41+ console.log('🔄 Found #skip-changeset in PR description. Skipping changeset check.');
42+ }
43+
44+ return { skip: shouldSkip };
45+
46+ - name : Comment on PR - Skipped
47+ if : fromJSON(steps.skip_check.outputs.result).skip == true
48+ uses : actions/github-script@v7
49+ with :
50+ script : |
51+ const commentBody = `## 🔄 Changeset Check Skipped
52+
53+ This PR has been marked to skip the changeset requirement using \`#skip-changeset\`.
54+
55+ **Note:** This should only be used for changes that don't affect the published package, such as:
56+ - Documentation updates
57+ - CI/CD changes
58+ - Development tooling changes
59+ - README updates
60+
61+ If this PR contains code changes that affect the public API, please remove \`#skip-changeset\` and add a proper changeset.
62+
63+ <!-- changeset-check-comment -->`;
64+
65+ // Find existing comment
66+ const { data: comments } = await github.rest.issues.listComments({
67+ owner: context.repo.owner,
68+ repo: context.repo.repo,
69+ issue_number: context.issue.number,
70+ });
71+
72+ const existingComment = comments.find(comment =>
73+ comment.body.includes('<!-- changeset-check-comment -->')
74+ );
75+
76+ if (existingComment) {
77+ // Update existing comment
78+ await github.rest.issues.updateComment({
79+ owner: context.repo.owner,
80+ repo: context.repo.repo,
81+ comment_id: existingComment.id,
82+ body: commentBody
83+ });
84+ } else {
85+ // Create new comment
86+ await github.rest.issues.createComment({
87+ owner: context.repo.owner,
88+ repo: context.repo.repo,
89+ issue_number: context.issue.number,
90+ body: commentBody
91+ });
92+ }
93+
94+ - name : Exit early if skipped
95+ if : fromJSON(steps.skip_check.outputs.result).skip == true
96+ run : |
97+ echo "✅ Changeset check skipped via PR description flag"
98+ exit 0
99+
22100 - name : Install pnpm
101+ if : fromJSON(steps.skip_check.outputs.result).skip != true
23102 uses : pnpm/action-setup@v2
24103 with :
25104 version : 10
26105 run_install : false
27106
28107 - name : Get pnpm store directory
108+ if : fromJSON(steps.skip_check.outputs.result).skip != true
29109 shell : bash
30110 run : |
31111 echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
32112
33113 - name : Setup pnpm cache
114+ if : fromJSON(steps.skip_check.outputs.result).skip != true
34115 uses : actions/cache@v3
35116 with :
36117 path : ${{ env.STORE_PATH }}
@@ -39,18 +120,145 @@ jobs:
39120 ${{ runner.os }}-pnpm-store-
40121
41122 - name : Install dependencies
123+ if : fromJSON(steps.skip_check.outputs.result).skip != true
42124 run : pnpm install --frozen-lockfile
43125
44126 - name : Check for changeset
127+ if : fromJSON(steps.skip_check.outputs.result).skip != true
128+ id : changeset_check
45129 run : |
46- # Check if there are any changesets in the .changeset directory
47- if [ -z "$(find .changeset -name '*.md' -not -name 'README.md' -print -quit)" ]; then
48- echo "❌ No changeset found!"
49- echo "Please add a changeset by running 'pnpm changeset' and commit the generated file."
50- echo "This helps us understand what changes you're making and manage versioning."
51- exit 1
130+ echo "Checking if this PR added a changeset file..."
131+
132+ # Check if this PR has added any new changeset files compared to main
133+ git fetch origin main:main
134+
135+ # Look for new changeset files added in this PR (excluding README.md)
136+ new_changesets=$(git diff --name-only --diff-filter=A main...HEAD | grep '^\.changeset/.*\.md$' | grep -v 'README\.md' || true)
137+
138+ if [ -n "$new_changesets" ]; then
139+ echo "✅ This PR added the following changeset(s):"
140+ echo "$new_changesets" | while read -r file; do
141+ echo " - $(basename "$file")"
142+ done
143+ echo "status=success" >> $GITHUB_OUTPUT
52144 else
53- echo "✅ Changeset found!"
54- echo "The following changesets were found:"
55- find .changeset -name '*.md' -not -name 'README.md' -exec basename {} \;
145+ echo "❌ This PR has not added any changeset files."
146+
147+ # Check if there are actually package changes that would require a changeset
148+ status_output=$(pnpm changeset status --since=main 2>&1 || true)
149+ echo "Changeset status output:"
150+ echo "$status_output"
151+
152+ # If changeset status indicates changes but no changesets, we need one
153+ if echo "$status_output" | grep -q "The following packages are changed but have no changesets"; then
154+ echo "❌ Changes detected in packages but no changeset found in this PR!"
155+ echo "status=missing" >> $GITHUB_OUTPUT
156+ elif echo "$status_output" | grep -q "No changesets present"; then
157+ echo "✅ No changeset needed (no package changes detected)"
158+ echo "status=no_changes" >> $GITHUB_OUTPUT
159+ else
160+ echo "❌ Unable to determine status, requiring changeset for safety"
161+ echo "status=missing" >> $GITHUB_OUTPUT
162+ fi
56163 fi
164+
165+ - name : Comment on PR - Missing Changeset
166+ if : fromJSON(steps.skip_check.outputs.result).skip != true && steps.changeset_check.outputs.status == 'missing'
167+ uses : actions/github-script@v7
168+ with :
169+ script : |
170+ const commentBody = `## ❌ Missing Changeset
171+
172+ This PR appears to have changes but is missing a changeset.
173+
174+ **What you need to do:**
175+ 1. Run \`pnpm changeset\` in your local repository
176+ 2. Follow the prompts to describe your changes
177+ 3. Commit the generated changeset file
178+ 4. Push the changes to this PR
179+
180+ **Why changesets?**
181+ Changesets help us:
182+ - Track what changed between versions
183+ - Generate accurate changelogs
184+ - Determine appropriate version bumps
185+ - Ensure nothing gets released without proper documentation
186+
187+ [Learn more about changesets](https://github.com/changesets/changesets)
188+
189+ <!-- changeset-check-comment -->`;
190+
191+ // Find existing comment
192+ const { data: comments } = await github.rest.issues.listComments({
193+ owner: context.repo.owner,
194+ repo: context.repo.repo,
195+ issue_number: context.issue.number,
196+ });
197+
198+ const existingComment = comments.find(comment =>
199+ comment.body.includes('<!-- changeset-check-comment -->')
200+ );
201+
202+ if (existingComment) {
203+ // Update existing comment
204+ await github.rest.issues.updateComment({
205+ owner: context.repo.owner,
206+ repo: context.repo.repo,
207+ comment_id: existingComment.id,
208+ body: commentBody
209+ });
210+ } else {
211+ // Create new comment
212+ await github.rest.issues.createComment({
213+ owner: context.repo.owner,
214+ repo: context.repo.repo,
215+ issue_number: context.issue.number,
216+ body: commentBody
217+ });
218+ }
219+
220+ - name : Comment on PR - Changeset Found
221+ if : fromJSON(steps.skip_check.outputs.result).skip != true && steps.changeset_check.outputs.status == 'success'
222+ uses : actions/github-script@v7
223+ with :
224+ script : |
225+ const commentBody = `## ✅ Changeset Found
226+
227+ Great! This PR includes the required changeset(s). The changes are properly documented and ready for review.
228+
229+ <!-- changeset-check-comment -->`;
230+
231+ // Find existing comment
232+ const { data: comments } = await github.rest.issues.listComments({
233+ owner: context.repo.owner,
234+ repo: context.repo.repo,
235+ issue_number: context.issue.number,
236+ });
237+
238+ const existingComment = comments.find(comment =>
239+ comment.body.includes('<!-- changeset-check-comment -->')
240+ );
241+
242+ if (existingComment) {
243+ // Update existing comment
244+ await github.rest.issues.updateComment({
245+ owner: context.repo.owner,
246+ repo: context.repo.repo,
247+ comment_id: existingComment.id,
248+ body: commentBody
249+ });
250+ } else {
251+ // Create new comment
252+ await github.rest.issues.createComment({
253+ owner: context.repo.owner,
254+ repo: context.repo.repo,
255+ issue_number: context.issue.number,
256+ body: commentBody
257+ });
258+ }
259+
260+ - name : Fail if changeset is missing
261+ if : fromJSON(steps.skip_check.outputs.result).skip != true && steps.changeset_check.outputs.status == 'missing'
262+ run : |
263+ echo "❌ This PR requires a changeset. Please add one and push the changes."
264+ exit 1
0 commit comments