1+ name : Notify on OpenAPI Schema Changes
2+
3+ on :
4+ push :
5+ branches : [master]
6+
7+ jobs :
8+ detect-and-notify :
9+ runs-on : ubuntu-latest
10+ permissions :
11+ contents : read
12+ pull-requests : write
13+ actions : read
14+ steps :
15+ - name : Checkout code
16+ uses : actions/checkout@v4
17+ with :
18+ fetch-depth : 0
19+
20+ - name : Find changed schema files
21+ id : schema_changes
22+ run : |
23+ git fetch origin master
24+
25+ # include both schema changes and the merged OpenAPI JSON
26+ CHANGED=$(git diff --name-only origin/master...HEAD \
27+ specification/schemas/ \
28+ dist/merged-woosmap-openapi3.json \
29+ )
30+
31+ echo "changed_files<<EOF" >> $GITHUB_OUTPUT
32+ echo "$CHANGED" >> $GITHUB_OUTPUT
33+ echo "EOF" >> $GITHUB_OUTPUT
34+
35+ - name : Find PR
36+ uses : jwalton/gh-find-current-pr@master
37+ id : findPr
38+ with :
39+ state : all
40+
41+ - name : No PR found
42+ if : steps.findPr.outputs.number == ''
43+ run : echo "No PR found for this push. Skipping comment and issue creation."
44+
45+ - name : Comment on PR or linked Issue if schemas changed
46+ if : steps.schema_changes.outputs.changed_files && steps.findPr.outputs.number != ''
47+ uses : actions/github-script@v6
48+ with :
49+ github-token : ${{ secrets.HELPER_TOKEN }}
50+ script : |
51+ const publicOwner = context.repo.owner;
52+ const publicRepo = context.repo.repo;
53+ const prNumber = ${{ steps.findPr.outputs.number }};
54+
55+ // 1) grab PR details
56+ const { data: pr } = await github.request('GET /repos/{owner}/{repo}/pulls/{pull_number}', {
57+ owner: publicOwner,
58+ repo: publicRepo,
59+ pull_number: prNumber
60+ });
61+
62+ const body = pr.body || "";
63+
64+ // Try both "Owner/Repo#123" and full "https://github.com/Owner/Repo/issues/123"
65+ const urlRegex = /https:\/\/github\.com\/([^\/]+)\/([^\/]+)\/issues\/(\d+)/;
66+ const shortRegex = /([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)#(\d+)/;
67+
68+ let match = body.match(urlRegex) || body.match(shortRegex);
69+ let targetOwner, targetRepo, targetNumber;
70+
71+ if (match) {
72+ // In both cases, groups 1=owner, 2=repo, 3=number
73+ [, targetOwner, targetRepo, targetNumber] = match;
74+ targetNumber = parseInt(targetNumber, 10);
75+ } else {
76+ // No external issue reference → comment on this PR
77+ targetOwner = context.repo.owner;
78+ targetRepo = context.repo.repo;
79+ targetNumber = pr.number;
80+ }
81+
82+ await github.rest.issues.createComment({
83+ owner: targetOwner,
84+ repo: targetRepo,
85+ issue_number: targetNumber,
86+ body: "🔔 OpenAPI schema has changed. Dependent libraries/SDKs/Plugins need to be updated as well."
87+ });
88+
89+
90+ - name : Create issue in Woosmap/woosmap if schemas changed
91+ if : steps.schema_changes.outputs.changed_files && steps.findPr.outputs.number != ''
92+ uses : actions/github-script@v6
93+ with :
94+ github-token : ${{ secrets.HELPER_TOKEN }}
95+ script : |
96+ // 0) Grab the PR payload
97+ const publicOwner = context.repo.owner;
98+ const publicRepo = context.repo.repo;
99+ const prNumber = ${{ steps.findPr.outputs.number }};
100+
101+ // 1) grab PR details
102+ const { data: pr } = await github.request('GET /repos/{owner}/{repo}/pulls/{pull_number}', {
103+ owner: publicOwner,
104+ repo: publicRepo,
105+ pull_number: prNumber
106+ });
107+
108+ // 1) Prepare private target repo
109+ const targetOwner = 'Woosmap';
110+ const targetRepo = 'woosmap';
111+ const issueTitle = `OpenAPI change: #${pr.number} - ${pr.title}`;
112+ const author = pr.user.login;
113+
114+ // 2) Dedup via listForRepo on the private repo
115+ const { data: openIssues } = await github.rest.issues.listForRepo({
116+ owner: targetOwner,
117+ repo: targetRepo,
118+ state: 'open',
119+ per_page: 100
120+ });
121+ if (openIssues.some(i => i.title === issueTitle)) {
122+ console.log(`Issue "${issueTitle}" already exists; skipping creation.`);
123+ return;
124+ }
125+
126+ // 3) Fetch diff from the PUBLIC repo where this PR lives
127+ let diffText = '';
128+ try {
129+ const diffRes = await github.request(
130+ 'GET /repos/{owner}/{repo}/pulls/{pull_number}',
131+ {
132+ owner: publicOwner,
133+ repo: publicRepo,
134+ pull_number: pr.number,
135+ mediaType: { format: 'diff' }
136+ }
137+ );
138+ diffText = diffRes.data;
139+ } catch (err) {
140+ console.warn('Unable to fetch PR diff:', err.message);
141+ }
142+
143+ // 4) Truncate or embed the diff
144+ let diffBlock = '';
145+ if (diffText) {
146+ const MAX_FULL = 2000;
147+ const MAX_SNIP = 500;
148+ if (diffText.length <= MAX_FULL) {
149+ diffBlock = '```diff\n' + diffText + '\n```';
150+ } else {
151+ const snippet = diffText.slice(0, MAX_SNIP) + '\n...';
152+ diffBlock = '```diff\n' + snippet + '\n```';
153+ }
154+ }
155+
156+ // 5) Build the issue body with a checklist
157+ const bodyLines = [
158+ `Schema files under \`specification/schemas/\` were updated in PR ${pr.html_url}.`,
159+ '',
160+ `> ${pr.title}`,
161+ '',
162+ diffBlock,
163+ '',
164+ '**Please update these dependent libraries/SDKs/Plugins:**',
165+ '- [ ] MapsJS',
166+ '- [ ] Native SDK',
167+ '- [ ] RN Plugin',
168+ '- [ ] Flutter Plugin'
169+ ].filter(Boolean);
170+
171+
172+ // 6) Create the issue in the PRIVATE repo, assigned to the PR author
173+ await github.rest.issues.create({
174+ owner: targetOwner,
175+ repo: targetRepo,
176+ title: issueTitle,
177+ body: bodyLines.join('\n'),
178+ assignees: [author]
179+ });
180+
181+ # - name: Send Slack notification if schemas changed
182+ # if: steps.schema_changes.outputs.changed_files != ''
183+ # uses: slackapi/slack-github-action@v1
184+ # with:
185+ # payload: |
186+ # {
187+ # "channel": "#mobile",
188+ # "text": "🚨 OpenAPI schema has changed. Please refer to the PR <${{ github.event.pull_request.html_url }}|#${{ github.event.pull_request.number }}> for more insights."
189+ # }
190+ # env:
191+ # SLACK_WEBHOOK_URL: ${{ secrets.WOOSMAP_SLACK_WEBHOOK }}
0 commit comments