ci: add diff coverage workflow enforcing 80% on changed code only

Uses diff-cover to check that newly added or modified lines in PRs
have at least 80% test coverage, without requiring the entire
codebase to meet the threshold.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
fireddd 2026-03-31 09:26:36 +05:30
parent b8c67dca50
commit e6c3a06427
6 changed files with 116 additions and 0 deletions

65
.github/workflows/coverage.yml vendored Normal file
View File

@ -0,0 +1,65 @@
name: PR Diff Coverage
on:
pull_request:
branches: [main]
concurrency:
group: coverage-${{ github.ref }}
cancel-in-progress: true
jobs:
diff-coverage:
name: Diff Coverage (80% on changed code)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install diff-cover
run: pip install diff-cover
- name: Install tmux
run: sudo apt-get update && sudo apt-get install -y tmux
- name: Start tmux server
run: tmux start-server
- run: pnpm install --frozen-lockfile
- run: pnpm -r --filter '!@composio/ao-web' build
- name: Core tests with coverage
run: pnpm --filter @composio/ao-core exec vitest run --coverage
- name: CLI tests with coverage
run: pnpm --filter @composio/ao-cli exec vitest run --coverage
- name: Web tests with coverage
run: pnpm --filter @composio/ao-web exec vitest run --coverage
- name: Prepare lcov reports
run: |
mkdir -p combined-coverage
# Prefix source paths so they match git diff (repo-root-relative)
sed 's|^SF:|SF:packages/core/|' packages/core/coverage/lcov.info > combined-coverage/core.info
sed 's|^SF:|SF:packages/cli/|' packages/cli/coverage/lcov.info > combined-coverage/cli.info
sed 's|^SF:|SF:packages/web/|' packages/web/coverage/lcov.info > combined-coverage/web.info
cat combined-coverage/core.info combined-coverage/cli.info combined-coverage/web.info > combined-coverage/lcov.info
- name: Check diff coverage (80% on changed lines)
run: |
diff-cover combined-coverage/lcov.info \
--compare-branch=origin/${{ github.base_ref }} \
--fail-under=80 \
--diff-range-notation='...'

View File

@ -11,5 +11,9 @@ export default defineConfig({
maxThreads: 8,
},
},
coverage: {
provider: "v8",
reporter: ["lcov"],
},
},
});

View File

@ -16,5 +16,11 @@ export default defineConfig({
),
"@composio/ao-plugin-scm-github": resolve(__dirname, "../plugins/scm-github/src/index.ts"),
},
coverage: {
provider: "v8",
reporter: ["lcov"],
include: ["src/**/*.ts"],
exclude: ["src/__tests__/**", "src/index.ts", "src/recovery/index.ts"],
},
},
});

View File

@ -62,6 +62,7 @@
"tailwindcss": "^4.0.0",
"tsx": "^4.19.0",
"typescript": "^5.7.0",
"@vitest/coverage-v8": "^2.1.0",
"vitest": "^2.1.0"
}
}

View File

@ -9,6 +9,11 @@ export default defineConfig({
environment: "jsdom",
setupFiles: ["./src/__tests__/setup.ts"],
include: ["src/**/*.test.{ts,tsx}", "server/**/*.test.ts"],
coverage: {
provider: "v8",
reporter: ["lcov"],
include: ["src/**/*.{ts,tsx}", "server/**/*.ts"],
},
},
resolve: {
alias: {

View File

@ -649,6 +649,9 @@ importers:
'@vitejs/plugin-react':
specifier: ^4.3.0
version: 4.7.0(vite@5.4.21(@types/node@25.2.3)(lightningcss@1.30.2))
'@vitest/coverage-v8':
specifier: ^2.1.0
version: 2.1.9(vitest@2.1.9(@types/node@25.2.3)(jsdom@25.0.1)(lightningcss@1.30.2))
concurrently:
specifier: ^9.2.1
version: 9.2.1
@ -803,6 +806,9 @@ packages:
resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
engines: {node: '>=6.9.0'}
'@bcoe/v8-coverage@0.2.3':
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
'@bcoe/v8-coverage@1.0.2':
resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
engines: {node: '>=18'}
@ -2001,6 +2007,15 @@ packages:
peerDependencies:
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
'@vitest/coverage-v8@2.1.9':
resolution: {integrity: sha512-Z2cOr0ksM00MpEfyVE8KXIYPEcBFxdbLSs56L8PO0QQMxt/6bDj45uQfxoc96v05KW3clk7vvgP0qfDit9DmfQ==}
peerDependencies:
'@vitest/browser': 2.1.9
vitest: 2.1.9
peerDependenciesMeta:
'@vitest/browser':
optional: true
'@vitest/coverage-v8@3.2.4':
resolution: {integrity: sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==}
peerDependencies:
@ -4278,6 +4293,8 @@ snapshots:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
'@bcoe/v8-coverage@0.2.3': {}
'@bcoe/v8-coverage@1.0.2': {}
'@cfworker/json-schema@4.1.1': {}
@ -5385,6 +5402,24 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@vitest/coverage-v8@2.1.9(vitest@2.1.9(@types/node@25.2.3)(jsdom@25.0.1)(lightningcss@1.30.2))':
dependencies:
'@ampproject/remapping': 2.3.0
'@bcoe/v8-coverage': 0.2.3
debug: 4.4.3
istanbul-lib-coverage: 3.2.2
istanbul-lib-report: 3.0.1
istanbul-lib-source-maps: 5.0.6
istanbul-reports: 3.2.0
magic-string: 0.30.21
magicast: 0.3.5
std-env: 3.10.0
test-exclude: 7.0.2
tinyrainbow: 1.2.0
vitest: 2.1.9(@types/node@25.2.3)(jsdom@25.0.1)(lightningcss@1.30.2)
transitivePeerDependencies:
- supports-color
'@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/node@25.2.3)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))':
dependencies:
'@ampproject/remapping': 2.3.0