This is the duplication docker we use at Codacy to have Flay support. You can also create a docker to integrate the tool and language of your choice! Check the Docs section for more information.
TODO
TODO
This section is written for an AI coding agent (or a human) tasked with updating this repo — most commonly bumping the wrapped Flay version, but also base image / orb / Scala-seed dependency bumps. Follow it top to bottom.
This is a Codacy DUPLICATION engine (not a pattern-based linting engine): a thin Scala wrapper (src/main/scala/codacy/duplication/flay/Flay.scala, built on codacy-duplication-scala-seed) that shells out to Flay, a Ruby duplicate-code detector, and translates its output into Codacy's DuplicationClone/DuplicationCloneFile model (see FlayReport.scala for the JSON shape Flay is expected to emit and Flay.scala for the mapping).
Unlike a typical Codacy tool wrapper, Flay itself is vendored source, not a Ruby gem dependency: the actual tool code lives at src/main/resources/flay/ (bin/flay, lib/flay.rb, lib/flay_erb.rb, lib/flay_task.rb, lib/gauntlet_flay.rb, Rakefile, History.txt, Manifest.txt, README.txt) and is copied verbatim from an upstream Flay release. build.sbt maps these files (plus Gemfile, Gemfile.lock, .ruby-version) into the Docker image, and Common.scala sets ENV FLAY_SOURCE_PATH /opt/codacy/flay. At runtime, Flay.scala runs rake codacy[<dir>] inside that directory (see the :codacy task in the vendored Rakefile), which invokes vendored bin/flay --diff --report and prints a single line of JSON to stdout — that JSON is parsed by FlayReport.scala into Codacy's duplication contract. The Ruby gems in the top-level Gemfile/Gemfile.lock (rake, hoe, sexp_processor, ruby_parser, ruby2ruby, erubis, minitest) are Flay's own runtime dependencies, installed via bundle install in the Docker image — they are not Flay itself.
There is no docs/patterns.json in this repo (confirmed absent) and no rule/pattern list of any kind — duplication tools don't have configurable patterns. The only "docs" config that exists is a small fixture set used by codacy-plugins-test's duplication test mode:
src/main/resources/docs/duplication-tests/contain-results/src/*.rb— sample Ruby source fed to the engine.src/main/resources/docs/duplication-tests/contain-results/results.xml— the expected duplication report for that sample, in thecodacy-plugins-testXML contract (<checkstyle version="4.3"><duplication nrTokens=".." nrLines=".." message="..">...).src/main/resources/docs/duplication-tests/no-results/— same idea, but a sample with no duplicates (results.xmlis an empty<checkstyle>element).
These fixture directories are mapped into the Docker image under /docs (see build.sbt's mappings.in(Universal)), which is where codacy-plugins-test reads them from. There is also src/test/scala/codacy/duplication/flay/FlaySpec.scala, a native specs2 test that runs Flay(...) against src/test/resources/analysis/duplication/ruby/*.rb and asserts the exact DuplicationClones produced.
| File | What it controls | What to check |
|---|---|---|
src/main/resources/flay/lib/flay.rb (VERSION = "...") and the other vendored files under src/main/resources/flay/ |
The actual Flay release bundled and executed by this engine | This is the file that matters most. Replace the vendored files with the contents of the target seattlerb/flay release tag (e.g. from its gem package or GitHub tag), not just the VERSION string — bin/flay, lib/*, Rakefile, History.txt, Manifest.txt, README.txt should all come from the same release. Caution: a prior commit (f5d56f0, "Bump Flay 2.13.3") only updated the test-fixture copy of flay.rb under src/main/resources/docs/duplication-tests/contain-results/src/ and left the real vendored src/main/resources/flay/lib/flay.rb at 2.7.0 — verify which file(s) you're actually changing. |
Gemfile / Gemfile.lock |
Flay's own Ruby dependency versions (sexp_processor, ruby_parser, ruby2ruby, erubis, rake, hoe, minitest) |
Check the target Flay release's own .gemspec/Rakefile dependency declarations for required version ranges, and regenerate Gemfile.lock with bundle install/bundle lock under the matching Ruby version. |
.ruby-version |
Ruby version used to build/run bundle install and by the Alpine apk add ruby* packages in Common.scala |
Bump if the target Flay release needs a newer Ruby, or as part of routine Ruby maintenance. |
project/Dependencies.scala → Codacy.duplicationSeed |
codacy-duplication-scala-seed version (the Codacy engine API contract this wrapper implements) |
Bump to the latest published version; check for breaking API changes in DuplicationTool/DuplicationClone. |
project/Common.scala → dockerBaseImage |
Runtime base image (amazoncorretto:8-alpine3.22-jre) and the apk add package list for Ruby |
Bump the Alpine tag for security patches; keep the apk add ruby package list in sync with what Flay's Rakefile/gems actually need. |
.circleci/config.yml → codacy/base and codacy/plugins-test orbs |
Shared CircleCI steps and codacy-plugins-test runner |
Check the latest published orb versions. |
build.sbt → semanticdbVersion / project/plugins.sbt sbt plugin versions |
Build tooling only, no runtime effect | Bump opportunistically alongside other changes; not required for a pure Flay bump. |
Note: there is no Dockerfile in this repo — the Docker image is built entirely via sbt-native-packager's DockerPlugin, configured in build.sbt and project/Common.scala (dockerCommands, dockerBaseImage, etc.).
- Identify the target Flay version and fetch its source (e.g.
gem fetch flay -v <version>and unpack, or cloneseattlerb/flayat tagv<version>). - Replace the vendored files under
src/main/resources/flay/with the new release'sbin/flay,lib/flay.rb,lib/flay_erb.rb,lib/flay_task.rb,lib/gauntlet_flay.rb,Rakefile,History.txt,Manifest.txt,README.txt. Keep the existing:codacyrake task in theRakefile(it's Codacy-specific, not part of upstream Flay) — merge it into the newRakefilerather than dropping it. - Update
Gemfile/Gemfile.lockto match the new release's dependency constraints, and.ruby-versionif required. Runbundle install(orbundle lock) locally with the target Ruby to regenerateGemfile.lockdeterministically. - Re-run the native test suite:
sbt test(runsFlaySpec). If Flay's clone-detection output format or exact duplicate findings on the fixtures undersrc/test/resources/analysis/duplication/ruby/changed between versions, update the expectedDuplicationClones inFlaySpec.scalato match. - Check the
codacy-plugins-testfixtures: if the new Flay version changes the JSON/duplication output for the sample files undersrc/main/resources/docs/duplication-tests/*/src/, regenerateresults.xmlin each fixture directory (contain-results/results.xml,no-results/results.xml) to match the new expected output. - Build and format:
sbt scalafmtCheck scalafmtSbtCheck scapegoat(same as the CIlintjob), fixing withsbt scalafmt scalafmtSbtwhere needed. - Build the Docker image locally:
sbt "set version in Docker := \"latest\"; docker:publishLocal". - Run
codacy-plugins-testlocally before pushing — clone https://github.com/codacy/codacy-plugins-test and run its duplication-modeDockerTestcommand against your local image tag (mirrors the CIplugins_testjob, which runs withrun_duplication_tests: trueand all other test flagsfalse). - Iterate on failures, re-running only the relevant command after each fix.
- Commit the version bump(s) together with any regenerated fixtures/lockfiles in one change.
- Push and open a PR.
- 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 (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 can differ from your local one, so a clean local run does not guarantee CI passes. Only stop iterating when every check passes, or you hit a genuine product/infra decision that needs a human.
| Symptom | Likely cause | Fix |
|---|---|---|
FlaySpec fails with different clone counts/line numbers than expected |
The new Flay version changed its structural-hash/mass algorithm or output format | Update the expected DuplicationClone list in FlaySpec.scala to the new (correct) output — don't just force the old values. |
plugins_test duplication job fails on contain-results/no-results |
results.xml fixtures are stale relative to the new Flay output |
Regenerate results.xml by running the engine against the fixture src/ files and capturing real output. |
Docker build fails installing gems (bundle install) |
.ruby-version / Alpine apk add ruby* packages out of sync with Gemfile.lock's BUNDLED WITH version |
Align the Ruby/Bundler version across .ruby-version, Gemfile.lock, and the apk add package list in Common.scala. |
| Engine returns "No output" / "Output should contain a single line" errors at runtime | Vendored Rakefile's :codacy task got dropped or altered while updating from upstream, or bin/flay --diff --report no longer emits single-line JSON |
Confirm the :codacy rake task still exists and still runs bin/flay --diff --report per the current Rakefile; check upstream Flay's CLI output changes. |
- The vendored
src/main/resources/flay/files (not just a fixture copy) reflect the target Flay version. Gemfile/Gemfile.lock/.ruby-versionare consistent with the new Flay release's dependencies.sbt test(nativeFlaySpec) passes, with expectations updated if Flay's output changed.sbt scalafmtCheck scalafmtSbtCheck scapegoatpasses.- Docker image builds successfully via
sbt docker:publishLocal. codacy-plugins-testduplication-mode tests pass locally against the freshly built image, withresults.xmlfixtures regenerated if needed.- 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 until all pass.
TODO
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.