Skip to content

Commit d93562e

Browse files
authored
Merge pull request #174 from ucdavis/tools/fallow-jscpd
PR 1: feat(tooling): add fallow + jscpd with regression-gated CI
2 parents de9d033 + 5a53adb commit d93562e

17 files changed

Lines changed: 2197 additions & 72 deletions

.github/workflows/code-quality.yml

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
name: Code Quality
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
7+
# Detects whether a PR *adds* new dead code or duplication compared to main.
8+
# - fallow covers VueApp (dead code, unused exports, complexity, duplication)
9+
# - jscpd covers C# (web/Areas/**/*.cs) since fallow is JS/TS-only
10+
# Passes if counts are equal to or lower than main.
11+
12+
jobs:
13+
fallow-regression:
14+
name: Fallow regression (VueApp)
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout PR head
18+
uses: actions/checkout@v6
19+
with:
20+
fetch-depth: 0
21+
22+
- uses: actions/setup-node@v6
23+
with:
24+
node-version: 24
25+
cache: npm
26+
cache-dependency-path: |
27+
package-lock.json
28+
VueApp/package-lock.json
29+
30+
- name: Install dependencies (root)
31+
run: npm ci
32+
33+
- name: Install dependencies (VueApp)
34+
# fallow resolves the tsconfig chain (incl. @tsconfig/node24) and needs
35+
# VueApp's node_modules to produce accurate counts. Without this step,
36+
# CI reports inflated unresolved-imports / unused-types numbers.
37+
run: npm ci --prefix VueApp
38+
39+
- name: Audit fallow on changed files
40+
# `fallow audit` is purpose-built for PR-diff regression gating: it
41+
# scopes to files changed since --base and returns a pass/warn/fail
42+
# verdict (exit 0 if no regression).
43+
run: npx fallow audit --root VueApp --base origin/${{ github.base_ref }}
44+
45+
jscpd-regression-csharp:
46+
name: JSCPD regression (C#)
47+
runs-on: ubuntu-latest
48+
steps:
49+
- name: Checkout PR head
50+
uses: actions/checkout@v6
51+
with:
52+
fetch-depth: 0
53+
54+
- uses: actions/setup-node@v6
55+
with:
56+
node-version: 24
57+
cache: npm
58+
cache-dependency-path: |
59+
package-lock.json
60+
VueApp/package-lock.json
61+
62+
- name: Install dependencies (root)
63+
run: npm ci
64+
65+
- name: Baseline jscpd on main
66+
# Use a separate worktree at the base ref so the baseline scan sees
67+
# main's full tree — files added by the PR aren't present, files
68+
# changed by the PR carry main's content. Pathspec `git checkout`
69+
# would leave PR-only files in place and pollute the baseline.
70+
env:
71+
BASE_REF: ${{ github.base_ref }}
72+
run: |
73+
BASE_TREE="$(mktemp -d)"
74+
git worktree add --detach "$BASE_TREE" "origin/$BASE_REF"
75+
node scripts/audit-jscpd-regression.js --save .jscpd-baseline-cs.json "$BASE_TREE/web/Areas" --format csharp --pattern '**/*.cs' --min-lines 15
76+
git worktree remove --force "$BASE_TREE"
77+
78+
- name: Check jscpd regression on PR
79+
run: node scripts/audit-jscpd-regression.js --check .jscpd-baseline-cs.json web/Areas --format csharp --pattern '**/*.cs' --min-lines 15
80+
81+
jscpd-regression-vue:
82+
name: JSCPD regression (Vue/TS)
83+
runs-on: ubuntu-latest
84+
steps:
85+
- name: Checkout PR head
86+
uses: actions/checkout@v6
87+
with:
88+
fetch-depth: 0
89+
90+
- uses: actions/setup-node@v6
91+
with:
92+
node-version: 24
93+
cache: npm
94+
cache-dependency-path: |
95+
package-lock.json
96+
VueApp/package-lock.json
97+
98+
- name: Install dependencies (root)
99+
run: npm ci
100+
101+
- name: Baseline jscpd on main
102+
# See the C# baseline step above for why we use a worktree here.
103+
env:
104+
BASE_REF: ${{ github.base_ref }}
105+
run: |
106+
BASE_TREE="$(mktemp -d)"
107+
git worktree add --detach "$BASE_TREE" "origin/$BASE_REF"
108+
node scripts/audit-jscpd-regression.js --save .jscpd-baseline-vue.json "$BASE_TREE/VueApp/src"
109+
git worktree remove --force "$BASE_TREE"
110+
111+
- name: Check jscpd regression on PR
112+
run: node scripts/audit-jscpd-regression.js --check .jscpd-baseline-vue.json VueApp/src

.github/workflows/codeql.yml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,7 @@ jobs:
4747
uses: github/codeql-action/init@v4.35.2
4848
with:
4949
languages: ${{ matrix.language }}
50-
# If you wish to specify custom queries, you can do so here or in a config file.
51-
# By default, queries listed here will override any specified in a config file.
52-
# Prefix the list here with "+" to use these queries and those in the config file.
53-
54-
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
55-
# queries: security-extended,security-and-quality
50+
queries: security-and-quality
5651

5752
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
5853
# If this step fails, then you should remove it and run the build manually (see below)

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,3 +497,8 @@ awscredentials.xml
497497
web/Areas/Effort/Scripts/AnalysisOutput/
498498
web/Areas/Effort/Scripts/RemediationOutput/
499499
web/Areas/Effort/Scripts/Effort_Database_Schema_And_Data_LEGACY.txt
500+
501+
# Code-quality tool outputs (fallow cache + jscpd reports)
502+
.fallow/
503+
VueApp/.fallow/
504+
jscpd-report/

.jscpd.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"ignore": [
3+
"**/__tests__/**",
4+
"**/node_modules/**",
5+
"**/dist/**",
6+
"**/coverage/**",
7+
"**/bin/**",
8+
"**/obj/**"
9+
],
10+
"ignorePattern": [
11+
"^\\s*import\\s+.*from\\s+['\"][^'\"]+['\"]\\s*;?\\s*$"
12+
]
13+
}

VueApp/.fallowrc.json

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/fallow-schema.json",
3+
"entry": [
4+
"src/main.ts",
5+
"src/CAHFS/cahfs.ts",
6+
"src/CMS/cms.ts",
7+
"src/CTS/cts.ts",
8+
"src/ClinicalScheduler/clinicalscheduler.ts",
9+
"src/Computing/computing.ts",
10+
"src/Effort/effort.ts",
11+
"src/Students/students.ts",
12+
"index.html",
13+
"src/CAHFS/index.html",
14+
"src/CMS/index.html",
15+
"src/CTS/index.html",
16+
"src/ClinicalScheduler/index.html",
17+
"src/Computing/index.html",
18+
"src/Effort/index.html",
19+
"src/Students/index.html"
20+
],
21+
"ignorePatterns": [
22+
"node_modules/**",
23+
"dist/**",
24+
"coverage/**",
25+
"obj/**",
26+
"bin/**",
27+
"public/**"
28+
],
29+
"ignoreDependencies": [
30+
"@tsconfig/node24",
31+
"vue-eslint-parser"
32+
],
33+
"duplicates": {
34+
"ignoreImports": true,
35+
"ignore": [
36+
"**/__tests__/**"
37+
]
38+
}
39+
}

VueApp/package-lock.json

Lines changed: 0 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

VueApp/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
"test:run": "vitest run"
2626
},
2727
"dependencies": {
28-
"@quasar/extras": "^1.18.0",
2928
"@vueuse/core": "^14.0.0",
3029
"chart.js": "^4.4.3",
3130
"inflection": "^3.0.2",
@@ -39,7 +38,6 @@
3938
"devDependencies": {
4039
"@codecov/vite-plugin": "^2.0.1",
4140
"@eslint/js": "^10.0.0",
42-
"@pinia/testing": "^1.0.2",
4341
"@quasar/app-vite": "^2.6.0",
4442
"@quasar/vite-plugin": "^1.9.0",
4543
"@tsconfig/node24": "^24.0.4",

VueApp/tsconfig.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,11 @@
1010
{
1111
"path": "./tsconfig.vitest.json"
1212
}
13-
]
13+
],
14+
"compilerOptions": {
15+
"baseUrl": ".",
16+
"paths": {
17+
"@/*": ["./src/*"]
18+
}
19+
}
1420
}

0 commit comments

Comments
 (0)