This is the docker engine we use at Codacy to have PHPMD support. You can also create a docker to integrate the tool and language of your choice! See the codacy-engine-scala-seed repository for more information.
You can create the docker by doing:
docker build -t codacy-phpmd-base .
sbt docker:publishLocal
The docker is ran with the following command:
docker run -it -v $srcDir:/src <DOCKER_NAME>:<DOCKER_VERSION>
The documentation is updated manually by checking the official documentation rules in the PHPMD repository.
- Install composer - (It will create the composer.phar file):
curl -sS https://getcomposer.org/installer | php
- Update phpmd version on composer.json:
"require": {
"phpmd/phpmd": "x.xx.x"
}
- Run the update command to get the latest versions of the dependencies and to update the composer.lock file:
php composer.phar update
Note: If you receive a message like this:
Could not fetch <URL package>, please review your configured GitHub OAuth token or enter a new one to access private repos" Create a new token here: https://github.com/settings/tokens/new?scopes=&description=Composer to retrieve a token.
create the token and paste it to proceed.
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 PHPMD version, but also base image / orb bumps. Follow it top to bottom.
This is a Codacy engine: a thin Scala wrapper (src/main/scala/codacy/phpmd/PhpMd.scala, built on codacy-engine-scala-seed, invoked via com.codacy.tools.scala.seed.DockerEngine) that packages PHPMD — a PHP static analysis/mess-detection tool — as a Docker image Codacy's platform can run against a customer's PHP source code. PHPMD itself is a PHP/Composer package, not something built from this repo's Scala source: it is pulled in as a vendor/ dependency via composer.json/composer.lock and installed inside the Dockerfile's builder stage, then copied (vendor/) into the final image alongside the compiled Scala bin/codacy-phpmd launcher.
docs/ holds Codacy's "pattern" configuration for this tool:
docs/patterns.json— the list of PHPMD rules ("patterns"), their metadata, and a top-level"version"field recording which PHPMD release the pattern list corresponds to. Hand-maintained, not auto-generated — there is no DocGenerator script in this repo.docs/description/description.json+docs/description/*.md— human-readable titles/descriptions per pattern, also hand-maintained.docs/tests/*anddocs/multiple-tests/*— PHP fixtures used bycodacy-plugins-testto validate real output.docs/tool-description.md— short blurb about the tool.
Per the repo's own "Update Documentation" section above, docs/patterns.json and docs/description/* are updated manually by diffing against the official rule docs in phpmd/phpmd — there is no generator command to run.
| File | What it controls | What to check |
|---|---|---|
composer.json → require.phpmd/phpmd |
Which PHPMD release is installed into the Docker image | Bump to the target version string (e.g. "2.15.0"). |
composer.lock |
Locked resolution of phpmd/phpmd and its transitive PHP deps (pdepend/pdepend, symfony/*, etc.) |
Do not hand-edit — regenerate with composer update after changing composer.json (see step 3). |
docs/patterns.json → top-level "version" |
Records which PHPMD version the pattern list documents | Bump manually to match composer.json; add/remove/rename any patterns changed upstream. |
.circleci/config.yml → codacy/base orb |
Shared CircleCI steps (checkout, versioning, sbt build/test, docker build/publish, tagging) | Check the latest published orb version if asked to bump it; not required for a pure PHPMD bump. |
.circleci/config.yml → codacy/plugins-test orb |
Runs codacy-plugins-test in CI after the image is built |
Same as above. |
Dockerfile → base image (alpine:3.20) and openjdk8-jre |
OS/runtime the packaged PHP CLI + Scala JVM launcher run on | Only bump if asked explicitly, or if the target PHPMD version raises PHP/extension requirements — check PHPMD's release notes for its required PHP version and Alpine's php package version. |
build.sbt → codacy-engine-scala-seed dependency |
Codacy's engine SDK | Not tied to PHPMD bumps; check Maven Central only if asked to update it separately. |
- Bump
composer.json: setrequire.phpmd/phpmdto the target version. - Regenerate
composer.lock. You need PHP + Composer available locally (or use the Dockerfile'sbuilderstage). The repo's own instructions:If Composer fails to fetch a package with a GitHub OAuth/rate-limit error, create a token at https://github.com/settings/tokens/new and supply it when prompted.curl -sS https://getcomposer.org/installer | php php composer.phar update - Update
docs/patterns.json— bump the top-level"version"field to match, and manually reconcile the pattern list against the changelog/rule docs at https://github.com/phpmd/phpmd for the target version (added/removed/renamed rules). Updatedocs/description/*similarly if descriptions changed. - Compile and test the Scala wrapper:
sbt "scalafmtCheckAll; scalafmtSbtCheck; test; stage". - Build the Docker image:
docker build -t codacy-phpmd .(this re-runscomposer install --no-scriptsinside thebuilderstage, so it will fail fast ifcomposer.lockis inconsistent withcomposer.json). - Run
codacy-plugins-testlocally before pushing — clone https://github.com/codacy/codacy-plugins-test and run it (this repo's CI runs it withrun_multiple_tests: true, i.e. both the single-filedocs/tests/*fixtures and thedocs/multiple-tests/*scenarios) against your local image tag. - Iterate on failures, re-running only the relevant test command after each fix.
- Commit the version bump(s) together with
composer.lockand anydocs/changes in one change. - Push and open a PR. CI (
.circleci/config.yml) runscodacy/checkout_and_version→codacy/sbt(scalafmt checks,test,stage,docker build,docker save) →codacy_plugins_test/run(run_multiple_tests: true) →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 (CircleCI API/UI for the failing job — 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. The CI environment's toolchain (PHP version, Composer version, Alpine package versions) can differ subtly from a local machine, so a clean local build does not guarantee CI passes. 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 |
|---|---|---|
composer update fails with a GitHub rate-limit/OAuth error |
Unauthenticated Composer hitting GitHub API limits when resolving dist zips |
Generate a token at https://github.com/settings/tokens/new and provide it to Composer when prompted |
docker build fails in the builder stage on composer install |
composer.lock out of sync with composer.json (e.g. hand-edited version without regenerating the lock file) |
Regenerate composer.lock via composer update rather than editing it directly |
pattern/json plugins-test checks fail |
A PHPMD rule was renamed/added/removed upstream between versions | Manually reconcile docs/patterns.json (and docs/description/*) against https://github.com/phpmd/phpmd's docs/changelog for the target version |
multiple plugins-test checks fail on a specific fixture |
Expected output in docs/multiple-tests/* stale for the new tool behavior |
Update the expected results to match the new (verified correct) output |
composer.jsonbumped andcomposer.lockregenerated to match (not hand-edited).docs/patterns.jsonversion field and pattern list reconciled with the target PHPMD release;docs/description/*updated if descriptions changed.- Local
sbtbuild/format/test commands pass. - Docker image builds successfully (this also validates the Composer install).
codacy-plugins-test(single and multiple test modes) 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, because the CI toolchain can differ from your local one (see step 10).
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.