Skip to content

Commit 0dec8d7

Browse files
Copilotnitrocode
andauthored
chore: simplify CI workflows and build scripts for weekly maintenance (#91)
* chore: simplify CI workflows and build scripts Agent-Logs-Url: https://github.com/nitrocode/token-deathclock/sessions/d47a2eb0-3a98-427d-8ddb-d539503e61f5 Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com> * fix: checkout repo before using local composite action Agent-Logs-Url: https://github.com/nitrocode/token-deathclock/sessions/b4a46e0d-829f-438a-a389-22e704bd74ad Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com> * fix: validate pr_count parse, paginate duplicate-issue check, fix bundle separators and ratio NaN Agent-Logs-Url: https://github.com/nitrocode/token-deathclock/sessions/96190522-cc07-4b03-99c0-cf0948a23a2e Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com> * fix: correct line count in build-bundle.js log (remove off-by-one) Agent-Logs-Url: https://github.com/nitrocode/token-deathclock/sessions/24d22b66-7021-4e64-afe0-bd4be732fffb Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: nitrocode <7775707+nitrocode@users.noreply.github.com>
1 parent e403cd9 commit 0dec8d7

9 files changed

Lines changed: 250 additions & 187 deletions

File tree

.github/actions/setup/action.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: 'Setup Node.js environment'
2+
description: 'Configure Node.js 22 with npm cache and install dependencies'
3+
4+
runs:
5+
using: composite
6+
steps:
7+
- name: Set up Node.js
8+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
9+
with:
10+
node-version: '22'
11+
cache: 'npm'
12+
13+
- name: Install dependencies
14+
run: npm ci
15+
shell: bash
Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
name: Unit Tests
1+
name: CI
22

33
on:
4+
schedule:
5+
- cron: '0 9 * * 1' # Every Monday at 09:00 UTC
46
push:
57
branches:
68
- main
@@ -14,13 +16,16 @@ jobs:
1416
changes:
1517
runs-on: ubuntu-latest
1618
outputs:
17-
code: ${{ steps.filter.outputs.code }}
19+
# On scheduled runs there is no diff to compare — always run tests.
20+
# On push/PR, only run when relevant files changed.
21+
code: ${{ github.event_name == 'schedule' || steps.filter.outputs.code == 'true' }}
1822
steps:
1923
- name: Checkout
2024
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2125

2226
- name: Detect relevant file changes
2327
uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
28+
if: github.event_name != 'schedule'
2429
id: filter
2530
with:
2631
filters: |
@@ -36,17 +41,8 @@ jobs:
3641
if: needs.changes.outputs.code == 'true'
3742
runs-on: ubuntu-latest
3843
steps:
39-
- name: Checkout
40-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
41-
42-
- name: Set up Node.js
43-
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
44-
with:
45-
node-version: '22'
46-
cache: 'npm'
47-
48-
- name: Install dependencies
49-
run: npm ci
44+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
45+
- uses: ./.github/actions/setup
5046

5147
- name: Build generated files needed for tests
5248
run: npm run build:milestones && npm run build:js
@@ -65,6 +61,23 @@ jobs:
6561
verbose: true
6662
fail_ci_if_error: false
6763

64+
test-e2e:
65+
needs: changes
66+
if: needs.changes.outputs.code == 'true'
67+
runs-on: ubuntu-latest
68+
steps:
69+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
70+
- uses: ./.github/actions/setup
71+
72+
- name: Install Playwright browsers
73+
run: npx playwright install --with-deps chromium
74+
75+
- name: Build generated files
76+
run: npm run build
77+
78+
- name: Run E2E tests
79+
run: npm run test:e2e
80+
6881
unit-test-status:
6982
needs: [changes, test]
7083
if: always()
@@ -77,3 +90,16 @@ jobs:
7790
exit 1
7891
fi
7992
echo "Unit tests passed or were skipped (no relevant files changed)"
93+
94+
e2e-test-status:
95+
needs: [changes, test-e2e]
96+
if: always()
97+
runs-on: ubuntu-latest
98+
steps:
99+
- name: Report status
100+
run: |
101+
if [[ "${{ needs.test-e2e.result }}" == "failure" ]]; then
102+
echo "E2E tests failed"
103+
exit 1
104+
fi
105+
echo "E2E tests passed or were skipped (no relevant files changed)"

.github/workflows/deploy.yml

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,32 +20,11 @@ jobs:
2020
name: github-pages
2121
url: https://nitrocode.github.io/token-deathclock/
2222
steps:
23-
- name: Checkout
24-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
23+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
24+
- uses: ./.github/actions/setup
2525

26-
- name: Set up Node.js
27-
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
28-
with:
29-
node-version: '22'
30-
cache: 'npm'
31-
32-
- name: Install dependencies
33-
run: npm ci
34-
35-
- name: Regenerate milestones-data.js from YAML
36-
run: npm run build:milestones
37-
38-
- name: Regenerate changelog-data.js from CHANGELOG.md
39-
run: npm run build:changelog
40-
41-
- name: Regenerate project-stats-data.js from YAML
42-
run: npm run build:project-stats
43-
44-
- name: Rebuild script.js from src/js/ source files
45-
run: npm run build:js
46-
47-
- name: Rebuild styles.css from styles/ source files
48-
run: npm run build:css
26+
- name: Build all generated files
27+
run: npm run build
4928

5029
- name: Deploy to GitHub Pages (gh-pages branch)
5130
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0

.github/workflows/e2e-tests.yml

Lines changed: 0 additions & 71 deletions
This file was deleted.

.github/workflows/preview.yml

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,8 @@ jobs:
1212
preview:
1313
runs-on: ubuntu-latest
1414
steps:
15-
- name: Checkout
16-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
17-
18-
- name: Set up Node.js
19-
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
20-
with:
21-
node-version: '22'
22-
cache: 'npm'
23-
24-
- name: Install dependencies
25-
run: npm ci
15+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
16+
- uses: ./.github/actions/setup
2617

2718
- name: Build all generated files
2819
run: npm run build
@@ -35,8 +26,8 @@ jobs:
3526
destination_dir: previews/pr-${{ github.event.number }}
3627
# Preserve existing previews and production files
3728
keep_files: true
38-
# Exclude non-site files
39-
exclude_assets: '.github,node_modules,tests,scripts,package-lock.json,package.json,milestones.yaml'
29+
# Exclude non-site files (keep in sync with deploy.yml)
30+
exclude_assets: '.github,node_modules,tests,scripts,package-lock.json,package.json,milestones.yaml,project-stats.yaml'
4031

4132
- name: Post or update preview URL comment
4233
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: Weekly Project Stats Check
2+
3+
# Opens a reminder issue when the recorded pr_count in project-stats.yaml
4+
# is lower than the actual number of merged PRs in the repository.
5+
6+
on:
7+
schedule:
8+
- cron: '0 9 * * 1' # Every Monday at 09:00 UTC
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
issues: write
14+
15+
jobs:
16+
check-stats:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
21+
22+
- name: Check project-stats.yaml against actual merged PR count
23+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
24+
with:
25+
script: |
26+
const fs = require('fs');
27+
28+
// Read the recorded pr_count from project-stats.yaml
29+
const yaml = fs.readFileSync('project-stats.yaml', 'utf8');
30+
const match = yaml.match(/^pr_count:\s*(\d+)/m);
31+
if (!match) {
32+
throw new Error('Invalid or missing pr_count in project-stats.yaml');
33+
}
34+
const recordedCount = parseInt(match[1], 10);
35+
if (!Number.isInteger(recordedCount)) {
36+
throw new Error('Invalid or missing pr_count in project-stats.yaml');
37+
}
38+
39+
// Count actual merged PRs via the GitHub API
40+
let page = 1;
41+
let totalMerged = 0;
42+
while (true) {
43+
const { data } = await github.rest.pulls.list({
44+
owner: context.repo.owner,
45+
repo: context.repo.repo,
46+
state: 'closed',
47+
per_page: 100,
48+
page,
49+
});
50+
if (data.length === 0) break;
51+
totalMerged += data.filter(pr => pr.merged_at !== null).length;
52+
if (data.length < 100) break;
53+
page++;
54+
}
55+
56+
console.log(`Recorded pr_count: ${recordedCount}, actual merged PRs: ${totalMerged}`);
57+
58+
if (recordedCount >= totalMerged) {
59+
console.log('project-stats.yaml is up to date — no action needed.');
60+
return;
61+
}
62+
63+
const title = `chore: update project-stats.yaml (recorded ${recordedCount}, actual ${totalMerged} merged PRs)`;
64+
const body = [
65+
'## 📊 Project Stats Are Out of Date',
66+
'',
67+
`**Recorded \`pr_count\`:** ${recordedCount}`,
68+
`**Actual merged PRs:** ${totalMerged}`,
69+
`**Difference:** ${totalMerged - recordedCount} untracked PR(s)`,
70+
'',
71+
'After the next agent session, update `project-stats.yaml`:',
72+
'',
73+
'```yaml',
74+
`pr_count: ${totalMerged}`,
75+
'```',
76+
'',
77+
'Then run `npm run build:project-stats` to regenerate `project-stats-data.js`, or let the deploy workflow handle it.',
78+
].join('\n');
79+
80+
// Avoid duplicate open issues (paginate to cover all open items, exclude PRs)
81+
const openIssues = await github.paginate(github.rest.issues.listForRepo, {
82+
owner: context.repo.owner,
83+
repo: context.repo.repo,
84+
state: 'open',
85+
});
86+
const duplicate = openIssues.find(i =>
87+
i.title.startsWith('chore: update project-stats.yaml') && !i.pull_request
88+
);
89+
if (duplicate) {
90+
console.log(`Reminder issue already open: #${duplicate.number} — skipping.`);
91+
return;
92+
}
93+
94+
const { data: issue } = await github.rest.issues.create({
95+
owner: context.repo.owner,
96+
repo: context.repo.repo,
97+
title,
98+
body,
99+
});
100+
console.log(`Created reminder issue: #${issue.number}`);

0 commit comments

Comments
 (0)