CI & Hooks
Use jscpd in CI
Run jscpd in GitHub Actions, GitLab CI, and other CI systems to enforce duplication thresholds.
GitHub Action
The jscpd-copy-paste-detector GitHub Action runs jscpd in your CI workflow. It installs the Rust engine, runs detection, uploads SARIF to GitHub Code Scanning, and optionally uploads the report as an artifact.
Basic Usage
.github/workflows/jscpd.yml
name: Duplication Check
on: [push, pull_request]
jobs:
jscpd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: kucherenko/jscpd@master
This scans the entire repository with default settings and uploads SARIF results to GitHub Code Scanning.
Fail on Threshold
Set threshold to fail the build when duplication exceeds a percentage:
- uses: kucherenko/jscpd@master
with:
threshold: 5
The workflow fails if more than 5% of the code is duplicated.
Action Inputs
| Input | Description | Default |
|---|---|---|
path | Paths to scan (space-separated) | . |
config | Path to .jscpd.json config file | — |
min-tokens | Minimum tokens for a clone | 50 |
min-lines | Minimum lines for a clone | 5 |
max-lines | Maximum lines per block | — |
mode | Detection mode: mild, weak, strict | mild |
format | Comma-separated formats to check | — |
ignore | Comma-separated glob patterns to ignore | — |
ignore-pattern | Comma-separated regex patterns to skip | — |
reporters | Comma-separated reporters | console |
output | Output directory for file reporters | report |
threshold | Max duplication % before exit 1 | — |
blame | Enrich clones with git blame data | false |
exit-code | Exit with code when duplicates found (true or integer) | — |
pattern | Glob pattern for file search | — |
max-size | Skip files larger than SIZE | — |
skip-local | Skip clones in same directory | false |
ignore-case | Ignore case of symbols (experimental) | false |
follow-symlinks | Follow symbolic links | false |
no-gitignore | Don't respect .gitignore files | false |
absolute | Use absolute paths in reports | false |
formats-exts | Custom format-to-extension mappings | — |
formats-names | Custom format-to-filename mappings | — |
version | jscpd version to install | latest |
install-prefix | Installation directory for the binary | — |
skip-install | Skip installation (binary already present) | false |
extra-args | Additional arguments passed to jscpd | — |
upload-report | Upload report directory as artifact | false |
upload-sarif | Upload SARIF to GitHub Code Scanning | true |
Action Outputs
| Output | Description |
|---|---|
duplication-percentage | Percentage of duplicated code found |
clones-found | Number of clone pairs found |
duplicated-lines | Number of duplicated lines |
total-lines | Total lines scanned |
files-count | Number of source files scanned |
report-path | Path to the output directory |
sarif-path | Path to the SARIF report file |
exit-code | Exit code from jscpd |
Examples
Scan specific directories with threshold
- uses: kucherenko/jscpd@master
with:
path: src/lib src/utils
threshold: 3
ignore: "**/*.test.*,**/*.spec.*"
Use a config file
- uses: kucherenko/jscpd@master
with:
config: .jscpd.json
upload-report: true
Multi-reporter with artifact upload
- uses: kucherenko/jscpd@master
with:
reporters: console,json,html,sarif
output: jscpd-report
upload-report: true
Pin a specific version
- uses: kucherenko/jscpd@master
with:
version: "5.0.9"
Skip install (binary already in image)
- uses: kucherenko/jscpd@master
with:
skip-install: true
Use outputs in subsequent steps
- uses: kucherenko/jscpd@master
id: jscpd
- name: Check results
if: steps.jscpd.outputs.duplication-percentage > 5
run: |
echo "Duplication is ${{ steps.jscpd.outputs.duplication-percentage }}%"
echo "Found ${{ steps.jscpd.outputs.clones-found }} clones"
GitLab CI
Use jscpd in GitLab CI with a simple pipeline job:
.gitlab-ci.yml
jscpd:
stage: test
image: node:20
before_script:
- npm install -g jscpd@5
script:
- jscpd --threshold 5 --reporters console,sarif .
artifacts:
paths:
- report/
Generic CI
Any CI system that can run shell commands works with jscpd:
npm install -g jscpd@5
jscpd --threshold 5 ./src
The --threshold flag makes jscpd exit with code 1 when duplication exceeds the specified percentage, which causes CI builds to fail.
Tips
- Use
--reporters console,sarifin CI to get both console output and SARIF for code scanning platforms - Use
--thresholdto set a failure threshold — the process exits with code 1 if exceeded - Use
--ignoreto exclude generated files, test fixtures, or vendor directories - For large repos, use the Rust engine (
jscpd@5/cpd) — it runs 24-37x faster, keeping CI times low - Consider
--formatto limit detection to specific languages during CI, with a full scan in a scheduled job