1+ name : apply-test-ids
2+
3+ on :
4+ pull_request_target :
5+ types : [opened, synchronize]
6+
7+ permissions :
8+ contents : write
9+ pull-requests : write
10+
11+ jobs :
12+ apply :
13+ runs-on : ubuntu-latest
14+
15+ steps :
16+ # 1. Checkout base branch (trusted code )
17+ - name : Checkout base branch
18+ uses : actions/checkout@v4
19+ with :
20+ ref : ${{ github.event.pull_request.base.ref }}
21+ fetch-depth : 0
22+
23+ # 2. Save trusted scripts before checking out PR code
24+ - name : Save base automation scripts
25+ run : |
26+ mkdir -p /tmp/base-scripts/scripts/utils
27+ cp scripts/add-test-ids.js /tmp/base-scripts/scripts/add-test-ids.js
28+ cp scripts/normalize.js /tmp/base-scripts/scripts/normalize.js
29+ cp scripts/load-remotes.js /tmp/base-scripts/scripts/load-remotes.js
30+ cp scripts/utils/generateTestIds.js /tmp/base-scripts/scripts/utils/generateTestIds.js
31+ cp scripts/utils/jsonfiles.js /tmp/base-scripts/scripts/utils/jsonfiles.js
32+
33+ # 3. Checkout PR branch (contributor test files)
34+ - name : Checkout PR branch
35+ uses : actions/checkout@v4
36+ with :
37+ ref : ${{ github.event.pull_request.head.sha }}
38+ fetch-depth : 0
39+
40+ # 4. Restore trusted scripts over PR code (prevents script injection)
41+ - name : Restore trusted scripts
42+ run : |
43+ cp /tmp/base-scripts/scripts/add-test-ids.js scripts/add-test-ids.js
44+ cp /tmp/base-scripts/scripts/normalize.js scripts/normalize.js
45+ cp /tmp/base-scripts/scripts/load-remotes.js scripts/load-remotes.js
46+ cp /tmp/base-scripts/scripts/utils/generateTestIds.js scripts/utils/generateTestIds.js
47+ cp /tmp/base-scripts/scripts/utils/jsonfiles.js scripts/utils/jsonfiles.js
48+
49+ # 5. Setup Node.js
50+ - name : Setup Node.js
51+ uses : actions/setup-node@v4
52+ with :
53+ node-version : 18
54+
55+ # 6. Install dependencies
56+ - name : Install dependencies
57+ run : npm ci
58+
59+ # 7. Fetch list of files changed in this PR
60+ - name : Get changed test files
61+ env :
62+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
63+ run : |
64+ curl -s \
65+ -H "Authorization: Bearer $GITHUB_TOKEN" \
66+ "${{ github.event.pull_request.url }}/files?per_page=100" \
67+ | jq -r ".[].filename" \
68+ > changed-files.txt
69+
70+ grep -E "^tests/(draft[^/]+)/.*\.json$" changed-files.txt \
71+ | sed -E "s|^tests/([^/]+)/.*|\1|" \
72+ | sort -u \
73+ > affected-drafts.txt
74+
75+ # 8. Run add-test-ids.js for each changed file
76+ - name : Apply missing test IDs
77+ env :
78+ CI : " false"
79+ run : |
80+ if [ ! -s affected-drafts.txt ]; then
81+ echo "No test JSON files changed - nothing to do."
82+ exit 0
83+ fi
84+
85+ while IFS= read -r draft; do
86+ echo "Processing dialect: $draft"
87+ grep -E "^tests/${draft}/.*\.json$" changed-files.txt | while IFS= read -r file; do
88+ if [ -f "$file" ]; then
89+ echo " -> $file"
90+ node scripts/add-test-ids.js "$draft" "$file"
91+ fi
92+ done
93+ done < affected-drafts.txt
94+
95+ # 9. Commit and push back to the PR branch
96+ - name : Commit and push changes
97+ env :
98+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
99+ run : |
100+ git config user.name "test-id-bot"
101+ git config user.email "test-id-bot@users.noreply.github.com"
102+
103+ git add "tests/**/*.json"
104+
105+ if git diff --cached --quiet; then
106+ echo "No test ID changes needed - nothing to commit."
107+ echo "CHANGES_MADE=false" >> $GITHUB_ENV
108+ else
109+ SUMMARY=""
110+ TOTAL=0
111+ while IFS= read -r file; do
112+ COUNT=$(git diff --cached -- "$file" | grep "^+" | grep '"id":' | wc -l | tr -d " ")
113+ if [ "$COUNT" -gt 0 ]; then
114+ SUMMARY="${SUMMARY}\n- \`${file}\` - **${COUNT}** ID(s) added"
115+ TOTAL=$((TOTAL + COUNT))
116+ fi
117+ done < <(git diff --cached --name-only)
118+
119+ printf "%b" "$SUMMARY" > /tmp/summary.txt
120+ echo "TOTAL_IDS=${TOTAL}" >> $GITHUB_ENV
121+
122+ git commit -m "chore: auto-add missing test IDs"
123+
124+ COMMIT_SHA=$(git rev-parse HEAD)
125+ echo "COMMIT_SHA=${COMMIT_SHA}" >> $GITHUB_ENV
126+
127+ git push \
128+ https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.event.pull_request.head.repo.full_name }}.git \
129+ HEAD:refs/heads/${{ github.event.pull_request.head.ref }}
130+
131+ echo "CHANGES_MADE=true" >> $GITHUB_ENV
132+ fi
133+
134+ # 10. Post a summary comment on the PR
135+ - name : Post PR comment
136+ if : env.CHANGES_MADE == 'true'
137+ env :
138+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
139+ run : |
140+ SUMMARY=$(cat /tmp/summary.txt)
141+ COMMIT_URL="https://github.com/${{ github.event.pull_request.head.repo.full_name }}/commit/${COMMIT_SHA}"
142+
143+ BODY="### test-id-bot added ${TOTAL_IDS} missing test ID(s)\n\n${SUMMARY}\n\nView the full diff of added IDs: ${COMMIT_URL}\n\n> IDs are deterministic hashes based on the schema, test data, and expected result."
144+
145+ curl -s -X POST \
146+ -H "Authorization: Bearer $GITHUB_TOKEN" \
147+ -H "Content-Type: application/json" \
148+ "${{ github.event.pull_request.comments_url }}" \
149+ --data "$(jq -n --arg body "$(printf '%b' "$BODY")" '{body: $body}')"
0 commit comments