Skip to content

Commit 4214f20

Browse files
committed
Added devconfig-validator.
1 parent bfed6a1 commit 4214f20

File tree

3 files changed

+661
-2
lines changed

3 files changed

+661
-2
lines changed
Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
name: DevConfig Comment Handler
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
7+
permissions:
8+
contents: write
9+
pull-requests: write
10+
issues: write
11+
12+
jobs:
13+
check-comment:
14+
runs-on: ubuntu-latest
15+
if: contains(github.event.comment.body, '/add-devconfig') || contains(github.event.comment.body, '/delete-devconfig') || contains(github.event.comment.body, '/amend-devconfig')
16+
outputs:
17+
should_process: ${{ steps.check.outputs.should_process }}
18+
pr_number: ${{ github.event.issue.number }}
19+
has_custom_json: ${{ steps.extract-json.outputs.has_custom_json }}
20+
custom_json: ${{ steps.extract-json.outputs.custom_json }}
21+
command: ${{ steps.determine-command.outputs.command }}
22+
steps:
23+
- name: Check if comment is on a PR
24+
id: check
25+
run: |
26+
if [ "${{ github.event.issue.pull_request != '' }}" = "true" ]; then
27+
echo "should_process=true" >> $GITHUB_OUTPUT
28+
echo "Comment is on PR #${{ github.event.issue.number }}"
29+
else
30+
echo "should_process=false" >> $GITHUB_OUTPUT
31+
echo "Comment is not on a PR"
32+
fi
33+
34+
- name: Determine command
35+
id: determine-command
36+
if: steps.check.outputs.should_process == 'true'
37+
run: |
38+
# Save the comment to a file to avoid shell interpretation issues
39+
echo '${{ github.event.comment.body }}' > comment_raw.txt
40+
41+
# Convert Windows line endings to Unix and extract first line
42+
tr -d '\r' < comment_raw.txt | head -n 1 > first_line.txt
43+
FIRST_LINE=$(cat first_line.txt)
44+
45+
echo "First line of comment: $FIRST_LINE"
46+
47+
if [[ "$FIRST_LINE" == "/add-devconfig"* ]]; then
48+
echo "command=add" >> $GITHUB_OUTPUT
49+
echo "Command: add-devconfig"
50+
elif [[ "$FIRST_LINE" == "/delete-devconfig"* ]]; then
51+
echo "command=delete" >> $GITHUB_OUTPUT
52+
echo "Command: delete-devconfig"
53+
elif [[ "$FIRST_LINE" == "/amend-devconfig"* ]]; then
54+
echo "command=amend" >> $GITHUB_OUTPUT
55+
echo "Command: amend-devconfig"
56+
else
57+
echo "No valid command found in first line"
58+
exit 1
59+
fi
60+
61+
- name: Extract custom JSON
62+
id: extract-json
63+
if: steps.check.outputs.should_process == 'true' && (steps.determine-command.outputs.command == 'add' || steps.determine-command.outputs.command == 'amend')
64+
run: |
65+
# Save the comment to a file to avoid shell interpretation issues
66+
echo '${{ github.event.comment.body }}' > comment.txt
67+
68+
# Convert Windows line endings to Unix
69+
tr -d '\r' < comment.txt > comment_unix.txt
70+
71+
# Check if the comment contains JSON
72+
if grep -q '```json' comment_unix.txt; then
73+
echo "Found JSON block in comment"
74+
75+
# Extract everything between ```json and ``` markers
76+
# Use sed to extract the content between markers
77+
sed -n '/```json/,/```/p' comment_unix.txt | sed '1d;$d' > extracted_json.txt
78+
79+
if [ -s extracted_json.txt ]; then
80+
echo "has_custom_json=true" >> $GITHUB_OUTPUT
81+
echo "custom_json<<EOF" >> $GITHUB_OUTPUT
82+
cat extracted_json.txt >> $GITHUB_OUTPUT
83+
echo "EOF" >> $GITHUB_OUTPUT
84+
echo "JSON content extracted successfully"
85+
else
86+
echo "has_custom_json=false" >> $GITHUB_OUTPUT
87+
echo "No JSON content found between markers"
88+
fi
89+
else
90+
echo "has_custom_json=false" >> $GITHUB_OUTPUT
91+
echo "No JSON block found in comment"
92+
fi
93+
94+
- name: Add processing comment to PR
95+
if: steps.check.outputs.should_process == 'true'
96+
uses: actions/github-script@v7
97+
with:
98+
github-token: ${{ secrets.GITHUB_TOKEN }}
99+
script: |
100+
const command = '${{ steps.determine-command.outputs.command }}';
101+
let message = '';
102+
103+
if (command === 'add') {
104+
message = '⏳ Processing `/add-devconfig` command... DevConfig file is being generated and will be added to this PR shortly.';
105+
} else if (command === 'delete') {
106+
message = '⏳ Processing `/delete-devconfig` command... DevConfig file will be removed from this PR shortly.';
107+
} else if (command === 'amend') {
108+
message = '⏳ Processing `/amend-devconfig` command... DevConfig file is being updated in this PR.';
109+
}
110+
111+
await github.rest.issues.createComment({
112+
issue_number: ${{ github.event.issue.number }},
113+
owner: context.repo.owner,
114+
repo: context.repo.repo,
115+
body: message
116+
});
117+
118+
process-comment:
119+
needs: check-comment
120+
if: needs.check-comment.outputs.should_process == 'true'
121+
runs-on: ubuntu-latest
122+
steps:
123+
- name: Checkout repository
124+
uses: actions/checkout@v4
125+
with:
126+
fetch-depth: 0
127+
token: ${{ secrets.GITHUB_TOKEN }}
128+
129+
- name: Get PR details
130+
id: pr-details
131+
run: |
132+
PR_NUMBER="${{ needs.check-comment.outputs.pr_number }}"
133+
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
134+
135+
# Get PR head ref
136+
PR_DATA=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
137+
"https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER")
138+
HEAD_REF=$(echo "$PR_DATA" | jq -r .head.ref)
139+
echo "pr_head_ref=$HEAD_REF" >> $GITHUB_OUTPUT
140+
141+
echo "PR Number: $PR_NUMBER"
142+
echo "PR Head Ref: $HEAD_REF"
143+
144+
- name: Checkout PR branch
145+
run: |
146+
git fetch origin
147+
git checkout ${{ steps.pr-details.outputs.pr_head_ref }}
148+
149+
- name: Add DevConfig file
150+
id: add-devconfig
151+
if: needs.check-comment.outputs.command == 'add'
152+
run: |
153+
# Create DevConfig directory
154+
mkdir -p ./generator/.DevConfigs
155+
156+
# Use PR number for the filename
157+
PR_NUMBER="${{ needs.check-comment.outputs.pr_number }}"
158+
DEVCONFIG_FILE="./generator/.DevConfigs/pr-${PR_NUMBER}.json"
159+
160+
# Check if custom content was provided
161+
if [ "${{ needs.check-comment.outputs.has_custom_json }}" == "true" ]; then
162+
# Use the provided content
163+
echo '${{ needs.check-comment.outputs.custom_json }}' > $DEVCONFIG_FILE
164+
echo "Using custom DevConfig content from comment"
165+
else
166+
# Generate content based on detected changes
167+
echo "Generating DevConfig content based on detected changes"
168+
169+
# Get PR title as the changelog message
170+
PR_DATA=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
171+
"https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER")
172+
COMMIT_MSG=$(echo "$PR_DATA" | jq -r .title)
173+
174+
# If PR title is empty, fall back to the latest commit message
175+
if [ -z "$COMMIT_MSG" ]; then
176+
COMMIT_MSG=$(git log -1 --pretty=%B)
177+
fi
178+
179+
# Start building the DevConfig JSON
180+
echo "{" > $DEVCONFIG_FILE
181+
182+
# Check for core changes
183+
CORE_CHANGES=$(git diff --name-only origin/main... | grep -v "^sdk/src/Services/" | wc -l || echo 0)
184+
if [ $CORE_CHANGES -gt 0 ]; then
185+
echo ' "core": {' >> $DEVCONFIG_FILE
186+
echo ' "changeLogMessages": [' >> $DEVCONFIG_FILE
187+
echo " \"$COMMIT_MSG\"" >> $DEVCONFIG_FILE
188+
echo ' ],' >> $DEVCONFIG_FILE
189+
echo ' "type": "patch",' >> $DEVCONFIG_FILE
190+
echo ' "updateMinimum": true' >> $DEVCONFIG_FILE
191+
echo ' }' >> $DEVCONFIG_FILE
192+
fi
193+
194+
# Check for service changes
195+
SERVICE_CHANGES=$(git diff --name-only origin/main... | grep "^sdk/src/Services/" | wc -l || echo 0)
196+
if [ $SERVICE_CHANGES -gt 0 ]; then
197+
# If we added a core section, we need a comma
198+
if [ $CORE_CHANGES -gt 0 ]; then
199+
echo ',' >> $DEVCONFIG_FILE
200+
fi
201+
202+
echo ' "services": [' >> $DEVCONFIG_FILE
203+
204+
# Extract service names
205+
SERVICES=$(git diff --name-only origin/main... | grep "^sdk/src/Services/" | cut -d'/' -f4 | sort | uniq | jq -R -s -c 'split("\n") | map(select(length > 0))')
206+
SERVICES_ARRAY=$(echo $SERVICES | jq -c '.')
207+
208+
FIRST=true
209+
echo $SERVICES_ARRAY | jq -c '.[]' | while read -r SERVICE; do
210+
# Remove quotes from service name
211+
SERVICE=$(echo $SERVICE | tr -d '"')
212+
213+
if [ "$FIRST" == "true" ]; then
214+
FIRST=false
215+
else
216+
echo ',' >> $DEVCONFIG_FILE
217+
fi
218+
219+
echo ' {' >> $DEVCONFIG_FILE
220+
echo " \"serviceName\": \"$SERVICE\"," >> $DEVCONFIG_FILE
221+
echo ' "type": "patch",' >> $DEVCONFIG_FILE
222+
echo ' "changeLogMessages": [' >> $DEVCONFIG_FILE
223+
echo " \"$COMMIT_MSG\"" >> $DEVCONFIG_FILE
224+
echo ' ]' >> $DEVCONFIG_FILE
225+
echo ' }' >> $DEVCONFIG_FILE
226+
done
227+
228+
echo ' ]' >> $DEVCONFIG_FILE
229+
fi
230+
231+
echo "}" >> $DEVCONFIG_FILE
232+
fi
233+
234+
# Format the JSON for better readability
235+
cat $DEVCONFIG_FILE | jq . > ${DEVCONFIG_FILE}.formatted || cp $DEVCONFIG_FILE ${DEVCONFIG_FILE}.formatted
236+
mv ${DEVCONFIG_FILE}.formatted $DEVCONFIG_FILE
237+
238+
echo "Applied DevConfig file:"
239+
cat $DEVCONFIG_FILE
240+
241+
- name: Amend DevConfig file
242+
id: amend-devconfig
243+
if: needs.check-comment.outputs.command == 'amend' && needs.check-comment.outputs.has_custom_json == 'true'
244+
run: |
245+
# Create DevConfig directory if it doesn't exist
246+
mkdir -p ./generator/.DevConfigs
247+
248+
# Use PR number for the filename
249+
PR_NUMBER="${{ needs.check-comment.outputs.pr_number }}"
250+
DEVCONFIG_FILE="./generator/.DevConfigs/pr-${PR_NUMBER}.json"
251+
252+
# Use the provided content
253+
echo '${{ needs.check-comment.outputs.custom_json }}' > $DEVCONFIG_FILE
254+
echo "Using custom DevConfig content from comment"
255+
256+
# Format the JSON for better readability
257+
cat $DEVCONFIG_FILE | jq . > ${DEVCONFIG_FILE}.formatted || cp $DEVCONFIG_FILE ${DEVCONFIG_FILE}.formatted
258+
mv ${DEVCONFIG_FILE}.formatted $DEVCONFIG_FILE
259+
260+
echo "Updated DevConfig file:"
261+
cat $DEVCONFIG_FILE
262+
263+
- name: Delete DevConfig file
264+
id: delete-devconfig
265+
if: needs.check-comment.outputs.command == 'delete'
266+
run: |
267+
# Use PR number for the filename
268+
PR_NUMBER="${{ needs.check-comment.outputs.pr_number }}"
269+
DEVCONFIG_FILE="./generator/.DevConfigs/pr-${PR_NUMBER}.json"
270+
271+
if [ -f "$DEVCONFIG_FILE" ]; then
272+
rm "$DEVCONFIG_FILE"
273+
echo "DevConfig file deleted: $DEVCONFIG_FILE"
274+
else
275+
echo "DevConfig file not found: $DEVCONFIG_FILE"
276+
exit 1
277+
fi
278+
279+
- name: Commit and push changes
280+
run: |
281+
git config --global user.name "GitHub Action"
282+
git config --global user.email "[email protected]"
283+
284+
COMMAND="${{ needs.check-comment.outputs.command }}"
285+
PR_NUMBER="${{ needs.check-comment.outputs.pr_number }}"
286+
287+
if [ "$COMMAND" == "add" ]; then
288+
git add ./generator/.DevConfigs/pr-${PR_NUMBER}.json
289+
git commit -m "Add DevConfig file for PR #${PR_NUMBER}"
290+
elif [ "$COMMAND" == "amend" ]; then
291+
git add ./generator/.DevConfigs/pr-${PR_NUMBER}.json
292+
git commit -m "Update DevConfig file for PR #${PR_NUMBER}"
293+
elif [ "$COMMAND" == "delete" ]; then
294+
git add -A ./generator/.DevConfigs/
295+
git commit -m "Remove DevConfig file for PR #${PR_NUMBER}"
296+
fi
297+
298+
git push origin ${{ steps.pr-details.outputs.pr_head_ref }}
299+
300+
- name: Add confirmation comment to PR
301+
uses: actions/github-script@v7
302+
with:
303+
github-token: ${{ secrets.GITHUB_TOKEN }}
304+
script: |
305+
const command = '${{ needs.check-comment.outputs.command }}';
306+
let message = '';
307+
308+
if (command === 'add') {
309+
message = '✅ DevConfig file has been added to this PR.';
310+
} else if (command === 'delete') {
311+
message = '✅ DevConfig file has been removed from this PR.';
312+
} else if (command === 'amend') {
313+
message = '✅ DevConfig file has been updated in this PR.';
314+
}
315+
316+
await github.rest.issues.createComment({
317+
issue_number: ${{ needs.check-comment.outputs.pr_number }},
318+
owner: context.repo.owner,
319+
repo: context.repo.repo,
320+
body: message
321+
});

0 commit comments

Comments
 (0)