This is the docker engine we use at Codacy to have pmd support. You can also create a docker to integrate the tool and language of your choice! Check the Docs section for more information.
sbt 'set version in Docker := "dev"' 'set name := "pmd"' docker:publishLocal
| Repository Branch | Docker Image |
|---|---|
| master | codacy-pmd |
| pmd-legacy | codacy-pmdjava |
docker run --user=docker --rm=true -v <PATH-TO-CODE>:/src -v <PATH-TO>/ruleset.xml:/src/ruleset.xml codacy/pmd:dev
Make sure all the volumes mounted have the right permissions for user
docker
-
Update
toolVersionKeyinbuild.sbt -
Run the DocGenerator
sbt "runMain com.codacy.pmd.DocGenerator"Tool Developer Guide - Using Scala
We use the codacy-plugins-test to test our external tools integration. You can follow the instructions there to make sure your tool is working as expected.
This section is written for an AI coding agent (or a human) tasked with updating this repo — most commonly bumping the wrapped PMD version, but also base image / sbt / CircleCI orb bumps. Follow it top to bottom; it tells you what to change, how to regenerate derived files, how to test locally, and how to interpret CI so you can iterate on failures without guessing.
This is a Codacy engine: a Scala (2.13, sbt build) wrapper around PMD, built on codacy-engine-scala-seed, packaged as a Docker image that Codacy's platform runs against a customer's source code. PMD itself is pulled in as a set of ordinary sbt/Maven library dependencies (pmd-core, pmd-java, pmd-apex, pmd-jsp, pmd-javascript, pmd-plsql, pmd-vm, pmd-xml, pmd-visualforce, plus a forced rhino version) — there is no separate git clone of the PMD repo at build time.
The docs/ directory (src/main/resources/docs/) is machine-consumed configuration, same family as other Codacy engines:
docs/patterns.json— the full list of PMD rules ("patterns"), their parameters/defaults, and which are enabled by default. Generated file, do not hand-edit.docs/description/description.json+docs/description/*.md— human-readable titles/descriptions per pattern, used in the Codacy UI. Generated file, do not hand-edit.docs/tests/*anddocs/multiple-tests/*— fixtures used bycodacy-plugins-testto validate the engine against real code samples.docs/tool-description.md— short blurb about the tool, hand-maintained.
All the generated artifacts above come from DocGenerator (src/main/scala/com/codacy/pmd/DocGenerator.scala, run via sbt "runMain com.codacy.pmd.DocGenerator"). Unlike some sibling Codacy engines, it does not clone an external GitHub repo — it reads the ruleset XML files bundled as classpath resources inside the pmd-* jars that were just resolved for the new toolVersionKey, via ResourceHelper/Languages/RuleSets. It also regenerates src/main/scala/com.codacy/pmd/RuleSets.scala (marked AUTOGENERATED: DO NOT CHANGE HERE). This means an sbt dependency resolution (network access to Maven Central) is enough — no separate git clone or pandoc is needed here.
| File | What it controls | What to check |
|---|---|---|
build.sbt → toolVersionKey |
The PMD version bundled and used to generate docs/patterns.json |
Bump to the target PMD release. Confirm all pmd-* artifacts (pmd-core, pmd-java, pmd-apex, pmd-jsp, pmd-javascript, pmd-plsql, pmd-vm, pmd-xml, pmd-visualforce) still publish that version on Maven Central — PMD has occasionally dropped/renamed a module between majors (e.g. pmd-vm had no PMD 7 release at the time of this repo's PMD-7 attempt and had to be commented out). |
build.sbt → org.mozilla % rhino forced version |
Workaround for pmd/pmd#2081 | Only touch if instructed or if the PMD bump reintroduces that bug; otherwise leave as-is. |
build.sbt → codacy-engine-scala-seed dependency |
Codacy's engine SDK/base library | Check Maven Central if asked to bump it; not tied to PMD bumps. |
build.sbt → dockerBaseImage |
JRE the packaged app runs on (currently amazoncorretto:11-alpine3.18) |
Only bump if the new PMD version raises its minimum JDK requirement (check PMD's release notes) or if asked explicitly. |
build.sbt → scalaVersion |
Scala compiler version | Rarely tied to a PMD bump; bump only if asked or if the build fails to resolve. |
project/build.properties |
sbt version | Sometimes bumped alongside major tool bumps; check only if the build itself fails to load. |
.circleci/config.yml → codacy/base orb |
Shared CircleCI steps (checkout, versioning, sbt build, docker publish, tagging) | Check the latest published version, or use git log -p .circleci/config.yml for prior bump history as a fallback reference. |
.circleci/config.yml → codacy/plugins-test orb |
Runs codacy-plugins-test in CI after the image is built |
Same as above. |
Look at recent bump commits for the shape of a typical diff: git log --oneline --all | grep -iE "bump|update pmd", then git show <hash>. Routine PMD point-releases (e.g. commit feb32e8, "bump pmd to latest version 6.55.0") touch only build.sbt plus the regenerated docs/description/*.md, docs/description/description.json, and docs/patterns.json. Major PMD version bumps are riskier: commit 98efa78 ("Bump to PMD 7") also touched .circleci/config.yml (orb bumps), project/build.properties, dockerBaseImage, added/removed pmd-* module dependencies, and even touched a Java helper class (CodacyInMemoryRenderer.java) — and it was subsequently reverted in commit 8b17d55 ("Revert tool (#128)": "Revert PMD to version 7. Version 7 will be launched as a different tool") because of a real regression (duplicated violations on the same file/line). Treat a major-version PMD bump as substantially higher risk than a point-release bump, and be prepared for it to need dedicated engine-code changes, not just a version string change.
- Bump the version(s) in
build.sbt(toolVersionKey, anddockerBaseImage/scalaVersion/project/build.propertiesonly if actually required) and.circleci/config.ymlorbs, as scoped by the task. - Regenerate the docs. Requires network access to resolve the new PMD jars from Maven Central (no separate git clone or pandoc needed):
This rewrites
sbt "runMain com.codacy.pmd.DocGenerator"docs/patterns.json,docs/description/description.json,docs/description/*.md, andsrc/main/scala/com.codacy/pmd/RuleSets.scala. Review the diff for new/removed/renamed rules and stale fixtures underdocs/tests//docs/multiple-tests/. Watch the console output forRuleset ... is missing from rulesets.propertieswarnings. - Format and compile:
(This is the same sequence CI's
sbt "scalafmt::test; test:scalafmt::test; sbt:scalafmt::test" sbt "set Docker / version := \"latest\"; Docker / publishLocal"
publish_docker_localjob runs.) - Run
codacy-plugins-testlocally before pushing. CI runs it withrun_multiple_tests: true, meaning both the single-pattern/json tests (docs/tests/) and the multiple-tests suite (docs/multiple-tests/) — clone https://github.com/codacy/codacy-plugins-test and run the corresponding DockerTest commands against your localcodacy-pmd:latestimage. - Iterate on failures, re-running only the relevant test command after each fix.
- Commit the version bump(s) together with the regenerated
docs/andRuleSets.scalafiles in one change. - Push and open a PR. CI (CircleCI only — the GitHub Actions workflows in
.github/workflows/are unrelated Jira-ticket-sync automation, not build/test) runscodacy/checkout_and_version->publish_docker_local(runsDocGeneratoragain + scalafmt + docker build) ->plugins_test->codacy/publish_docker(master only) ->codacy/tag_version. - Poll the PR's real CI checks until they all pass — local validation is NOT the finish line. After every push, run
gh pr checks <pr-url>and keep re-polling (short sleep while any check ispending) until all checks finish. If a check fails, fetch its actual log (the CircleCI job log — don't guess), find the true root cause, fix it, push again (never--no-verify, never force-push), and re-poll. Repeat until every check is green. This repo has direct history of a version bump that looked fine in isolation but caused a real regression only caught downstream (the PMD 7 bump merged, then had to be reverted for producing duplicated violations) — treat any test or behavior change surfaced by CI as a real signal to investigate, not noise to suppress. Only stop iterating when every check passes, or you hit a genuine product/infra decision that needs a human — in which case explain it in the PR rather than guessing.
| Symptom | Likely cause | Fix |
|---|---|---|
scalafmt::test fails in CI/locally |
Generated or hand-edited Scala/Java file not formatted | Run sbt scalafmt then re-run the check command |
sbt fails to resolve a pmd-* module for the new version |
Module renamed/removed/not yet released for that PMD line (seen with pmd-vm on the PMD 7 attempt) |
Check PMD's Maven Central listing for that release; comment out or adjust the dependency as needed, matching the shape of commit 98efa78 |
pattern/json DockerTest fails |
Rule renamed/removed/added upstream between PMD versions | Re-run DocGenerator; confirm the change matches PMD's release notes |
multiple DockerTest fails, especially around duplicate/overlapping violations |
Renderer/engine behavior regression on major PMD bumps (this is exactly what caused the PMD 7 revert) | Do not just patch the fixture — verify the underlying violation output is actually correct before updating expectations |
CI codacy/publish_docker/tag_version don't run on your branch |
Expected — gated to default branch (master) only |
Nothing to fix |
- Version bump(s) reflected in all files that encode them (
build.sbt,.circleci/config.yml, andproject/build.properties/dockerBaseImageif actually needed). docs/patterns.json,docs/description/*, andRuleSets.scalaregenerated viaDocGeneratorand committed, with fixture inconsistencies underdocs/tests//docs/multiple-tests/resolved.- Local
scalafmt/compile/docker build commands pass. codacy-plugins-test(single and multiple-tests) pass locally against the freshly built image.- After pushing and opening/updating the PR, every CI check on it is green. Poll
gh pr checks <pr-url>and iterate on any failure (fetch the real CI log, fix, push, re-poll) until all pass — a passing local build is not sufficient, and this repo has a concrete precedent (the PMD 7 revert) of a merged bump turning out to be wrong in practice.
Codacy is an Automated Code Review Tool that monitors your technical debt, helps you improve your code quality, teaches best practices to your developers, and helps you save time in Code Reviews.
- Identify new Static Analysis issues
- Commit and Pull Request Analysis with GitHub, BitBucket/Stash, GitLab (and also direct git repositories)
- Auto-comments on Commits and Pull Requests
- Integrations with Slack, HipChat, Jira, YouTrack
- Track issues in Code Style, Security, Error Proneness, Performance, Unused Code and other categories
Codacy also helps keep track of Code Coverage, Code Duplication, and Code Complexity.
Codacy supports PHP, Python, Ruby, Java, JavaScript, and Scala, among others.
Codacy is free for Open Source projects.