Skip to content

Commit ef03f83

Browse files
authored
ci: add sample sync check workflow (#13203)
ci: add workflow to check HTML and React sample sync Adds a GitHub Actions workflow that runs on PRs touching website samples and comments when HTML or React samples are changed without updating the other, reminding authors to keep both in sync.
1 parent 73fe253 commit ef03f83

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
name: Check React Samples Sync
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- 'packages/website/docs/_samples/**/sample.html'
7+
- 'packages/website/docs/_samples/**/main.js'
8+
- 'packages/website/docs/_samples/**/main.css'
9+
- 'packages/website/docs/_samples/**/sample.tsx'
10+
11+
jobs:
12+
check:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
pull-requests: write
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Check sample sync
20+
uses: actions/github-script@v7
21+
with:
22+
script: |
23+
const { data: files } = await github.rest.pulls.listFiles({
24+
owner: context.repo.owner,
25+
repo: context.repo.repo,
26+
pull_number: context.issue.number,
27+
per_page: 300,
28+
});
29+
30+
const samplesDir = 'packages/website/docs/_samples/';
31+
const htmlSampleDirs = new Set();
32+
const reactSampleDirs = new Set();
33+
34+
for (const file of files) {
35+
if (!file.filename.startsWith(samplesDir)) continue;
36+
37+
const rel = file.filename.slice(samplesDir.length);
38+
const dir = rel.substring(0, rel.lastIndexOf('/'));
39+
40+
if (rel.endsWith('/sample.html') || rel.endsWith('/main.js') || rel.endsWith('/main.css')) {
41+
htmlSampleDirs.add(dir);
42+
}
43+
if (rel.endsWith('/sample.tsx')) {
44+
reactSampleDirs.add(dir);
45+
}
46+
}
47+
48+
const htmlOnly = [...htmlSampleDirs].filter(dir => !reactSampleDirs.has(dir)).sort();
49+
const reactOnly = [...reactSampleDirs].filter(dir => !htmlSampleDirs.has(dir)).sort();
50+
51+
if (htmlOnly.length === 0 && reactOnly.length === 0) {
52+
console.log('All changed samples are in sync.');
53+
return;
54+
}
55+
56+
const sections = ['### Sample sync reminder', ''];
57+
58+
if (htmlOnly.length > 0) {
59+
sections.push(
60+
'HTML sample changed but **React sample** (`sample.tsx`) not updated:',
61+
'',
62+
...htmlOnly.map(dir => `- \`${dir}\``),
63+
'',
64+
);
65+
}
66+
67+
if (reactOnly.length > 0) {
68+
sections.push(
69+
'React sample changed but **HTML sample** (`sample.html`/`main.js`/`main.css`) not updated:',
70+
'',
71+
...reactOnly.map(dir => `- \`${dir}\``),
72+
'',
73+
);
74+
}
75+
76+
sections.push('Please keep both samples in sync, or ignore if the change does not apply to both.');
77+
const body = sections.join('\n');
78+
79+
// Check for existing comment to avoid duplicates
80+
const marker = 'Sample sync reminder';
81+
const { data: comments } = await github.rest.issues.listComments({
82+
owner: context.repo.owner,
83+
repo: context.repo.repo,
84+
issue_number: context.issue.number,
85+
});
86+
const existing = comments.find(c =>
87+
c.user.type === 'Bot' && c.body.includes(marker)
88+
);
89+
90+
if (existing) {
91+
await github.rest.issues.updateComment({
92+
owner: context.repo.owner,
93+
repo: context.repo.repo,
94+
comment_id: existing.id,
95+
body,
96+
});
97+
} else {
98+
await github.rest.issues.createComment({
99+
owner: context.repo.owner,
100+
repo: context.repo.repo,
101+
issue_number: context.issue.number,
102+
body,
103+
});
104+
}

0 commit comments

Comments
 (0)