Skip to content

Commit eb142af

Browse files
committed
fix(workflow): Runs targeted checks only on files changed in a pull request
1 parent 6c0a366 commit eb142af

3 files changed

Lines changed: 131 additions & 76 deletions

File tree

.github/scripts/ciScript.js

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
const isTestFile = (file) => /\.(test|spec)\.[jt]sx?$/.test(file);
2+
3+
const deriveTestFiles = (files) => {
4+
return files.map((file) => {
5+
if (isTestFile(file)) return file;
6+
7+
const withoutExt = file.replace(/\.[jt]sx?$/, '');
8+
const parts = withoutExt.split('/');
9+
const baseName = parts[parts.length - 1];
10+
const dir = parts.slice(0, -1).join('/');
11+
12+
return `${dir}/__tests__/${baseName}.test.ts`;
13+
});
14+
};
15+
116
module.exports = async ({ github, context, core }) => {
217
const owner = context.repo.owner;
318
const repo = context.repo.repo;
@@ -40,36 +55,19 @@ module.exports = async ({ github, context, core }) => {
4055
}
4156
});
4257

43-
console.log({
44-
backendFiles,
45-
mobileFiles,
46-
webFiles
47-
});
48-
49-
core.setOutput(
50-
"backendFiles",
51-
backendFiles
52-
.map(file => file.replace("apps/backend/", ""))
53-
.join(" ")
54-
)
55-
56-
core.setOutput(
57-
"mobileFiles",
58-
mobileFiles
59-
.map(file => file.replace("apps/mobile/", ""))
60-
.join(" ")
61-
)
58+
const strippedBackend = backendFiles.map(f => f.replace('apps/backend/', ''));
59+
const strippedMobile = mobileFiles.map(f => f.replace('apps/mobile/', ''));
6260

63-
core.setOutput(
64-
"webFiles",
65-
webFiles
66-
.map(file => file.replace("apps/web/", ""))
67-
.join(" ")
68-
)
61+
console.log({ backendFiles, mobileFiles, webFiles });
6962

70-
core.setOutput("backendChanged", backendFiles.length > 0)
71-
core.setOutput("mobileChanged", mobileFiles.length > 0)
72-
core.setOutput("webChanged", webFiles.length > 0)
63+
core.setOutput('backendFiles', strippedBackend.join(' '));
64+
core.setOutput('mobileFiles', strippedMobile.join(' '));
65+
core.setOutput('webFiles', webFiles.map(f => f.replace('apps/web/', '')).join(' '));
66+
core.setOutput('backendTestFiles', deriveTestFiles(strippedBackend).join(' '));
67+
core.setOutput('mobileTestFiles', deriveTestFiles(strippedMobile).join(' '));
68+
core.setOutput('backendChanged', backendFiles.length > 0);
69+
core.setOutput('mobileChanged', mobileFiles.length > 0);
70+
core.setOutput('webChanged', webFiles.length > 0);
7371

7472
} catch (error) {
7573
console.error(error);

.github/scripts/commentResults.js

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,61 +10,60 @@ module.exports = async ({
1010
mobileLint,
1111
mobileTest,
1212
webCheck,
13-
webBuild
13+
webBuild,
14+
backendLintOutput,
15+
mobileLintOutput,
1416
}) => {
1517
const owner = context.repo.owner;
1618
const repo = context.repo.repo;
1719
const prNumber = context.payload.pull_request.number;
1820

19-
const emoji = (status) => {
20-
if (status === 'success') return '';
21-
if (status === 'failure') return '';
22-
if (status === 'skipped') return '⏭️';
23-
return '';
21+
const status = (s) => {
22+
if (s === 'success') return 'PASS';
23+
if (s === 'failure') return 'FAIL';
24+
if (s === 'skipped') return 'SKIP';
25+
return '-';
2426
};
2527

26-
const label = (status) => {
27-
if (!status) return '⚪ unknown';
28-
return `${emoji(status)} ${status}`;
28+
const lintDetails = (output) => {
29+
if (!output || !output.trim()) return '';
30+
return `\n<details>\n<summary>View lint errors</summary>\n\n\`\`\`\n${output.trim()}\n\`\`\`\n</details>`;
2931
};
3032

31-
const anyFailure = [
32-
backend,
33-
mobile,
34-
web
35-
].includes('failure');
36-
37-
const title = anyFailure
38-
? '❌ Some checks failed'
39-
: '✅ CI completed';
40-
33+
const anyFailure = [backend, mobile, web].includes('failure');
34+
const title = anyFailure ? 'CI — Checks Failed' : 'CI — All Checks Passed';
4135
const timestamp = new Date().toUTCString();
4236

43-
const body = `## CI Results — ${title}
37+
const body = `## ${title}
38+
39+
### Backend — ${status(backend)}
4440
45-
### 🖥️ Backend (${label(backend)})
46-
| Check | Status |
41+
| Check | Result |
4742
|---|---|
48-
| Lint | ${label(backendLint)} |
49-
| Test | ${label(backendTest)} |
50-
| Typecheck | ${label(backendTypecheck)} |
43+
| Lint | ${status(backendLint)} |
44+
| Test | ${status(backendTest)} |
45+
| Typecheck | ${status(backendTypecheck)} |
46+
${backendLint === 'failure' ? lintDetails(backendLintOutput) : ''}
5147
52-
### 📱 Mobile (${label(mobile)})
53-
| Check | Status |
48+
### Mobile — ${status(mobile)}
49+
50+
| Check | Result |
5451
|---|---|
55-
| Lint | ${label(mobileLint)} |
56-
| Test | ${label(mobileTest)} |
52+
| Lint | ${status(mobileLint)} |
53+
| Test | ${status(mobileTest)} |
54+
${mobileLint === 'failure' ? lintDetails(mobileLintOutput) : ''}
55+
56+
### Web — ${status(web)}
5757
58-
### 🌐 Web (${label(web)})
59-
| Check | Status |
58+
| Check | Result |
6059
|---|---|
61-
| Check | ${label(webCheck)} |
62-
| Build | ${label(webBuild)} |
60+
| Check | ${status(webCheck)} |
61+
| Build | ${status(webBuild)} |
6362
6463
---
65-
🕐 Last updated: \`${timestamp}\``;
64+
Last updated: \`${timestamp}\``;
6665

67-
const COMMENT_MARKER = '## CI Results —';
66+
const COMMENT_MARKER = '## CI —';
6867

6968
try {
7069
const comments = await github.paginate(

.github/workflows/ci.yml

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,20 @@ jobs:
1212
runs-on: ubuntu-latest
1313

1414
outputs:
15-
backendChanged: ${{ steps.detect.outputs.backendChanged }}
16-
mobileChanged: ${{ steps.detect.outputs.mobileChanged }}
17-
webChanged: ${{ steps.detect.outputs.webChanged }}
18-
backendFiles: ${{ steps.detect.outputs.backendFiles }}
19-
mobileFiles: ${{ steps.detect.outputs.mobileFiles }}
20-
webFiles: ${{ steps.detect.outputs.webFiles }}
15+
backendChanged: ${{ steps.detect.outputs.backendChanged }}
16+
mobileChanged: ${{ steps.detect.outputs.mobileChanged }}
17+
webChanged: ${{ steps.detect.outputs.webChanged }}
18+
backendFiles: ${{ steps.detect.outputs.backendFiles }}
19+
mobileFiles: ${{ steps.detect.outputs.mobileFiles }}
20+
webFiles: ${{ steps.detect.outputs.webFiles }}
21+
backendTestFiles: ${{ steps.detect.outputs.backendTestFiles }}
22+
mobileTestFiles: ${{ steps.detect.outputs.mobileTestFiles }}
2123

2224
steps:
2325
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
26+
with:
27+
ref: ${{ github.event.pull_request.head.sha }}
28+
2429

2530
- name: Detect changed files
2631
id: detect
@@ -36,8 +41,15 @@ jobs:
3641
if: needs.detect-changes.outputs.backendChanged == 'true'
3742
runs-on: ubuntu-latest
3843

44+
outputs:
45+
lint_result: ${{ steps.backend_lint.outcome }}
46+
test_result: ${{ steps.backend_test.outcome }}
47+
typecheck_result: ${{ steps.backend_typecheck.outcome }}
48+
3949
steps:
4050
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
51+
with:
52+
ref: ${{ github.event.pull_request.head.sha }}
4153

4254
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
4355
with:
@@ -49,23 +61,40 @@ jobs:
4961

5062
- name: Backend lint
5163
id: backend_lint
64+
continue-on-error: true
5265
run: cd apps/backend && pnpm eslint ${{ needs.detect-changes.outputs.backendFiles }}
5366

5467
- name: Backend test
5568
id: backend_test
56-
run: cd apps/backend && pnpm test ${{ needs.detect-changes.outputs.backendFiles }}
69+
if: needs.detect-changes.outputs.backendTestFiles != ''
70+
continue-on-error: true
71+
run: cd apps/backend && pnpm test --passWithNoTests ${{ needs.detect-changes.outputs.backendTestFiles }}
5772

5873
- name: Backend typecheck
5974
id: backend_typecheck
60-
run: cd apps/backend && pnpm typecheck ${{ needs.detect-changes.outputs.backendFiles }}
75+
continue-on-error: true
76+
run: cd apps/backend && pnpm typecheck
77+
78+
- name: Fail job if any check failed
79+
if: >
80+
steps.backend_lint.outcome == 'failure' ||
81+
steps.backend_test.outcome == 'failure' ||
82+
steps.backend_typecheck.outcome == 'failure'
83+
run: exit 1
6184

6285
web-ci:
6386
needs: detect-changes
6487
if: needs.detect-changes.outputs.webChanged == 'true'
6588
runs-on: ubuntu-latest
6689

90+
outputs:
91+
check_result: ${{ steps.web_check.outcome }}
92+
build_result: ${{ steps.web_build.outcome }}
93+
6794
steps:
6895
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
96+
with:
97+
ref: ${{ github.event.pull_request.head.sha }}
6998

7099
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
71100
with:
@@ -77,19 +106,33 @@ jobs:
77106

78107
- name: Web check
79108
id: web_check
109+
continue-on-error: true
80110
run: cd apps/web && pnpm check
81111

82112
- name: Web build
83113
id: web_build
114+
continue-on-error: true
84115
run: cd apps/web && pnpm build
85116

117+
- name: Fail job if any check failed
118+
if: >
119+
steps.web_check.outcome == 'failure' ||
120+
steps.web_build.outcome == 'failure'
121+
run: exit 1
122+
86123
mobile-ci:
87124
needs: detect-changes
88125
if: needs.detect-changes.outputs.mobileChanged == 'true'
89126
runs-on: ubuntu-latest
90127

128+
outputs:
129+
lint_result: ${{ steps.mobile_lint.outcome }}
130+
test_result: ${{ steps.mobile_test.outcome }}
131+
91132
steps:
92133
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
134+
with:
135+
ref: ${{ github.event.pull_request.head.sha }}
93136

94137
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
95138
with:
@@ -101,11 +144,20 @@ jobs:
101144

102145
- name: Mobile lint
103146
id: mobile_lint
147+
continue-on-error: true
104148
run: cd apps/mobile && pnpm eslint ${{ needs.detect-changes.outputs.mobileFiles }}
105149

106150
- name: Mobile test
107151
id: mobile_test
108-
run: cd apps/mobile && pnpm test
152+
if: needs.detect-changes.outputs.mobileTestFiles != ''
153+
continue-on-error: true
154+
run: cd apps/mobile && pnpm test --passWithNoTests ${{ needs.detect-changes.outputs.mobileTestFiles }}
155+
156+
- name: Fail job if any check failed
157+
if: >
158+
steps.mobile_lint.outcome == 'failure' ||
159+
steps.mobile_test.outcome == 'failure'
160+
run: exit 1
109161

110162
comment-results:
111163
needs:
@@ -124,11 +176,17 @@ jobs:
124176
github-token: ${{ secrets.GITHUB_TOKEN }}
125177
script: |
126178
const script = require('./.github/scripts/commentResults.js');
127-
128179
await script({
129180
github,
130181
context,
131-
backend: '${{ needs.backend-ci.result }}',
132-
web: '${{ needs.web-ci.result }}',
133-
mobile: '${{ needs.mobile-ci.result }}'
182+
backend: '${{ needs.backend-ci.result }}',
183+
web: '${{ needs.web-ci.result }}',
184+
mobile: '${{ needs.mobile-ci.result }}',
185+
backendLint: '${{ needs.backend-ci.outputs.lint_result }}',
186+
backendTest: '${{ needs.backend-ci.outputs.test_result }}',
187+
backendTypecheck: '${{ needs.backend-ci.outputs.typecheck_result }}',
188+
webCheck: '${{ needs.web-ci.outputs.check_result }}',
189+
webBuild: '${{ needs.web-ci.outputs.build_result }}',
190+
mobileLint: '${{ needs.mobile-ci.outputs.lint_result }}',
191+
mobileTest: '${{ needs.mobile-ci.outputs.test_result }}',
134192
});

0 commit comments

Comments
 (0)