Skip to content

Commit 4fa715d

Browse files
committed
Add test split workflow
1 parent 5691383 commit 4fa715d

6 files changed

Lines changed: 19370 additions & 1 deletion

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Notify SCSS nesting sync
2+
3+
# src/app-css/scss-sync-report.md is a checklist of changes that were
4+
# applied to the flat src/css/*.css files and still need to be hand-ported
5+
# into the nested src/scss/*.scss partials (the "Sync app.css changes"
6+
# workflow writes to it, but a human may also edit it directly, e.g. to
7+
# check items off). This workflow doesn't touch the SCSS itself — nesting
8+
# decisions are made by hand — it just keeps a standing PR comment in sync
9+
# with the current checklist so it isn't easy to lose track of.
10+
11+
on:
12+
pull_request:
13+
branches: ['**']
14+
paths:
15+
- 'src/app-css/scss-sync-report.md'
16+
17+
permissions:
18+
pull-requests: write
19+
20+
jobs:
21+
notify:
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v7
25+
26+
- uses: actions/github-script@v8
27+
with:
28+
script: |
29+
const fs = require('fs');
30+
const marker = '<!-- scss-sync-report -->';
31+
let report;
32+
try {
33+
report = fs.readFileSync('src/app-css/scss-sync-report.md', 'utf8').trim();
34+
} catch {
35+
return;
36+
}
37+
38+
const remaining = (report.match(/^- \[ \]/gm) || []).length;
39+
const body = remaining === 0
40+
? `${marker}\nAll items in \`src/app-css/scss-sync-report.md\` are checked off.`
41+
: `${marker}\n**${remaining} item(s) pending** in \`src/app-css/scss-sync-report.md\` — port these into the nested \`src/scss/*.scss\` partials, then check them off:\n\n${report}`;
42+
43+
const { data: comments } = await github.rest.issues.listComments({
44+
owner: context.repo.owner,
45+
repo: context.repo.repo,
46+
issue_number: context.issue.number,
47+
});
48+
const existing = comments.find((c) => c.body.includes(marker));
49+
50+
if (existing) {
51+
await github.rest.issues.updateComment({
52+
owner: context.repo.owner,
53+
repo: context.repo.repo,
54+
comment_id: existing.id,
55+
body,
56+
});
57+
} else {
58+
await github.rest.issues.createComment({
59+
owner: context.repo.owner,
60+
repo: context.repo.repo,
61+
issue_number: context.issue.number,
62+
body,
63+
});
64+
}

.github/workflows/sync-app-css.yml

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
name: Sync app.css changes
2+
3+
# When a PR adds a new src/app-css/app-x.y.z.css snapshot, diff it against
4+
# the previous snapshot and apply the same additions/removals/changes to
5+
# the flat src/css/*.css files. src/scss/*.scss is hand-nested and not
6+
# safe to auto-edit, so instead this appends a checklist to
7+
# src/app-css/scss-sync-report.md for a human to port by hand (see the
8+
# separate "Notify SCSS nesting sync" workflow).
9+
10+
on:
11+
pull_request:
12+
branches: ['**']
13+
paths:
14+
- 'src/app-css/app-*.css'
15+
16+
permissions:
17+
contents: write
18+
pull-requests: write
19+
20+
jobs:
21+
sync:
22+
runs-on: ubuntu-latest
23+
if: github.event.pull_request.head.repo.full_name == github.repository
24+
steps:
25+
- uses: actions/checkout@v7
26+
with:
27+
ref: ${{ github.event.pull_request.head.ref }}
28+
fetch-depth: 0
29+
30+
- uses: actions/setup-node@v7
31+
with:
32+
node-version: '24.x'
33+
34+
- name: Find newly added app-*.css snapshots
35+
id: added
36+
run: |
37+
FILES=$(git diff --name-only --diff-filter=A "${{ github.event.pull_request.base.sha }}" "${{ github.event.pull_request.head.sha }}" -- 'src/app-css/app-*.css')
38+
if [ -z "$FILES" ]; then
39+
echo "No new app-*.css snapshot added in this PR — nothing to sync."
40+
echo "found=false" >> "$GITHUB_OUTPUT"
41+
else
42+
echo "found=true" >> "$GITHUB_OUTPUT"
43+
echo "files<<EOF" >> "$GITHUB_OUTPUT"
44+
echo "$FILES" >> "$GITHUB_OUTPUT"
45+
echo "EOF" >> "$GITHUB_OUTPUT"
46+
fi
47+
48+
- name: Run sync for each new snapshot
49+
if: steps.added.outputs.found == 'true'
50+
run: |
51+
while IFS= read -r file; do
52+
[ -z "$file" ] && continue
53+
echo "::group::sync-app-css.mjs --new $file"
54+
node sync-app-css.mjs --new "$file"
55+
echo "::endgroup::"
56+
done <<< "${{ steps.added.outputs.files }}"
57+
58+
- name: Commit and push updates
59+
if: steps.added.outputs.found == 'true'
60+
id: commit
61+
run: |
62+
git config user.name "github-actions[bot]"
63+
git config user.email "github-actions[bot]@users.noreply.github.com"
64+
if git status --porcelain -- src/css src/app-css | grep -q .; then
65+
git add src/css src/app-css
66+
git commit -m "Sync src/css with $(basename "$(echo "${{ steps.added.outputs.files }}" | head -n1)")"
67+
git push origin "HEAD:${{ github.event.pull_request.head.ref }}"
68+
echo "committed=true" >> "$GITHUB_OUTPUT"
69+
else
70+
echo "committed=false" >> "$GITHUB_OUTPUT"
71+
fi
72+
73+
- name: Comment on PR
74+
if: steps.added.outputs.found == 'true'
75+
uses: actions/github-script@v8
76+
with:
77+
script: |
78+
const fs = require('fs');
79+
let summary;
80+
try {
81+
summary = JSON.parse(fs.readFileSync('sync-summary.json', 'utf8'));
82+
} catch {
83+
return;
84+
}
85+
const lines = [
86+
`**app.css sync**: \`${summary.oldVersion}\` → \`${summary.newVersion}\``,
87+
'',
88+
`- Changed selectors applied to \`src/css/*.css\`: ${summary.changed}`,
89+
`- Removed selectors applied to \`src/css/*.css\`: ${summary.removed}`,
90+
`- New selectors staged in \`src/app-css/_new-selectors.css\`: ${summary.added}`,
91+
];
92+
if (summary.notFoundLocally > 0) {
93+
lines.push(`- ${summary.notFoundLocally} changed/removed selector(s) from the old baseline were not found in any \`src/css/*.css\` file (already customized or removed by hand) — check the workflow log.`);
94+
}
95+
if (summary.scssReportUpdated) {
96+
lines.push('', '`src/app-css/scss-sync-report.md` was updated with a checklist for porting these changes into the hand-nested `src/scss/*.scss` partials.');
97+
}
98+
if (summary.added > 0) {
99+
lines.push('', 'New selectors need a manual home in `src/css/` before they can be ported to SCSS — see `src/app-css/_new-selectors.css`.');
100+
}
101+
await github.rest.issues.createComment({
102+
owner: context.repo.owner,
103+
repo: context.repo.repo,
104+
issue_number: context.issue.number,
105+
body: lines.join('\n'),
106+
});

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ node_modules
1010

1111
# Mac
1212
.DS_Store
13+
14+
# sync-app-css.mjs output
15+
sync-summary.json

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"version": "1.0.0",
44
"scripts": {
55
"version": "node version-bump.mjs && git add manifest.json versions.json",
6-
"lint": "stylelint \"**/*.css\""
6+
"lint": "stylelint \"**/*.css\"",
7+
"sync-app-css": "node sync-app-css.mjs"
78
},
89
"devDependencies": {
910
"stylelint": "^17.0.0",

0 commit comments

Comments
 (0)