PMD for Java
ActionsAbout
Tags
(2)This is a GitHub action to run PMD check on your Java code and report status via reviewdog on pull request.
This version includes major updates and breaking changes:
- PMD 7.20.0: Upgraded from PMD 6.55.0 to 7.20.0
- Java 21: Now using Eclipse Temurin 21 (upgraded from OpenJDK 17)
- Reviewdog v0.21.0: Updated from v0.14.1
- Default Ruleset Change:
category/java/bestpractices.xml(wasrulesets/java/quickstart.xml) - PMD CLI Change: Uses
pmd checkcommand (PMD 7.x syntax)
Migration Required:
- If you explicitly set
rulesets_path, update to PMD 7.x compatible paths (see Migration Guide) - Legacy ruleset paths like
rulesets/java/basic.xmlare no longer supported - Review your custom rulesets for deprecated rules
Version Strategy:
- v1.x branch: Uses PMD 6.x (previous version)
- v0.1.x: Uses PMD 7.x (current)
| Component | Version |
|---|---|
| Java | Eclipse Temurin 21 (LTS) |
| PMD | 7.20.0 |
| Reviewdog | v0.21.0 |
An example of how the reported pmd violations will look like on pull request is shown below (link to PR):
inputs:
github_token:
description: 'GITHUB_TOKEN'
default: '${{ github.token }}'
workdir:
description: 'Working directory relative to the root directory.'
default: '.'
### Flags for reviewdog ###
level:
description: 'Report level for reviewdog [info,warning,error]'
default: 'error'
reporter:
description: 'Reporter of reviewdog command [github-pr-check,github-pr-review].'
default: 'github-pr-check'
filter_mode:
description: |
Filtering mode for the reviewdog command [added,diff_context,file,nofilter].
Default is added.
default: 'added'
fail_level:
description: |
Fail level for reviewdog [none,any,info,warning,error]
Default is `none`.
default: 'none'
tool_name:
description: 'Tool name to use for reviewdog reporter'
default: 'pmd'
reviewdog_flags:
description: 'Additional reviewdog flags'
default: ''
### Flags for PMD ###
src_path:
description: 'Specify the directory where the sources to be analyzed are stored. Default is `src/main/java`.'
default: 'src/main/java'
rulesets_path:
description: 'Specify the path of the PMD rule set. Default is `category/java/bestpractices.xml`.'
default: 'category/java/bestpractices.xml'
pmd_cache:
description: 'Enable PMD incremental analysis with cache file path (e.g., "/tmp/pmd-cache/pmd.cache"). Must be a file path, not a directory. Leave empty to disable.'
default: ''name: pmd
on: [pull_request]
jobs:
pmd_job:
runs-on: ubuntu-latest
name: PMD job
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Run PMD
uses: kemsakurai/action-pmd@v0.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: 'github-pr-review'
tool_name: 'pmd_reviewdog'name: pmd
on: [pull_request]
jobs:
pmd_job:
runs-on: ubuntu-latest
name: PMD job with cache
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Run PMD
uses: kemsakurai/action-pmd@v0.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: 'github-pr-review'
tool_name: 'pmd_reviewdog'
pmd_cache: '/tmp/pmd-cache/pmd.cache' # Enable incremental analysisname: pmd
on: [pull_request]
jobs:
pmd_job:
runs-on: ubuntu-latest
name: PMD job with custom ruleset
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Run PMD
uses: kemsakurai/action-pmd@v0.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: 'github-pr-check'
rulesets_path: 'category/java/errorprone.xml' # Use different built-in rulesetFor comprehensive migration information, please refer to:
-
CLI Command Change
- Old:
pmd -d <dir> -R <ruleset> - New:
pmd check -d <dir> -R <ruleset>
- Old:
-
Ruleset Path Format
- ❌ Removed:
rulesets/java/basic.xml,rulesets/java/quickstart.xml - ✅ Use:
category/java/bestpractices.xml,category/java/errorprone.xml
- ❌ Removed:
-
Deprecated Rules Removed
- Many legacy rules have been removed or replaced
- See Removed Rules List
-
Property Delimiter Change
- Old: Pipe
|separator - New: Comma
,separator
- Old: Pipe
-
Verify Current Ruleset Compatibility
# Test your current ruleset with PMD 7.x docker build --build-arg PMD_VERSION=7.20.0 -t action-pmd:test . docker run -v $(pwd):/workspace action-pmd:test pmd check -d /workspace/src -R category/java/bestpractices.xml
-
Update Workflow Configuration
# Before (v1.x) - uses: kemsakurai/action-pmd@v1 with: rulesets_path: 'rulesets/java/quickstart.xml' # After (v0.1.0) - uses: kemsakurai/action-pmd@v0.1.0 with: rulesets_path: 'category/java/bestpractices.xml' # Updated path
-
Review Custom Rulesets
- Update ruleset references to use
category/prefix - Remove references to deleted rules
- Test thoroughly before deploying
- Update ruleset references to use
PMD 7.x provides category-based rulesets. Here are recommended options:
| Ruleset | Description | Use Case |
|---|---|---|
category/java/bestpractices.xml |
Best practice rules (default) | General code quality |
category/java/errorprone.xml |
Error-prone patterns | Bug prevention |
category/java/codestyle.xml |
Code style conventions | Style enforcement |
category/java/design.xml |
Design principles | Architecture quality |
category/java/performance.xml |
Performance optimizations | Performance-critical code |
category/java/security.xml |
Security vulnerabilities | Security-sensitive applications |
- uses: kemsakurai/action-pmd@v0.1.0
with:
rulesets_path: 'category/java/bestpractices.xml,category/java/errorprone.xml'Create a custom pmd-ruleset.xml in your repository:
<?xml version="1.0"?>
<ruleset name="Custom Ruleset"
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
<description>Custom PMD ruleset for our project</description>
<!-- Include built-in rulesets -->
<rule ref="category/java/bestpractices.xml"/>
<rule ref="category/java/errorprone.xml"/>
<!-- Exclude specific rules -->
<rule ref="category/java/bestpractices.xml">
<exclude name="UnusedPrivateMethod"/>
</rule>
<!-- Customize rule properties -->
<rule ref="category/java/codestyle.xml/LongVariable">
<properties>
<property name="minimum" value="30"/>
</properties>
</rule>
</ruleset>Then use it in your workflow:
- uses: kemsakurai/action-pmd@v0.1.0
with:
rulesets_path: './pmd-ruleset.xml'PMD 7.x supports incremental analysis via the --cache option, which can significantly reduce CI execution time for large codebases.
Enable Cache:
- uses: kemsakurai/action-pmd@v0.1.0
with:
pmd_cache: '/tmp/pmd-cache/pmd.cache'Benefits:
- Analyzes only changed files
- Reduces analysis time by 30-70% for subsequent runs
- Automatically managed by PMD
Best Practices:
- Use a consistent cache path across workflow runs
- Consider using GitHub Actions cache to persist between runs:
- name: Cache PMD results
uses: actions/cache@v3
with:
path: /tmp/pmd-cache
key: pmd-cache-${{ github.sha }}
restore-keys: |
pmd-cache-
- uses: kemsakurai/action-pmd@v0.1.0
with:
pmd_cache: '/tmp/pmd-cache/pmd.cache'Symptom:
Error: Unable to load ruleset: rulesets/java/quickstart.xml
Solution: Update to PMD 7.x category-based paths:
rulesets_path: 'category/java/bestpractices.xml'Symptom:
Error: Rule 'SomeRuleName' not found
Solution: The rule may have been removed in PMD 7.x. Check the removed rules list and find alternatives.
Symptom:
Warning: Failed to create cache directory
Solution: Ensure the cache path is writable. The action automatically sets permissions, but if using a custom path, verify access:
pmd_cache: '/tmp/pmd-cache/pmd.cache' # /tmp is always writableSymptom:
Error: PMD requires Java 8 or later
Solution: This action includes Java 21. If you're building with a different Java version in previous steps, ensure PMD runs in the action's container context.
You can build the Docker image with custom versions of PMD or Reviewdog:
# Build with specific PMD version
docker build --build-arg PMD_VERSION=7.18.0 -t action-pmd:custom .
# Build with specific Reviewdog version
docker build --build-arg REVIEWDOG_VERSION=v0.20.0 -t action-pmd:custom .
# Build with both custom versions
docker build \
--build-arg PMD_VERSION=7.18.0 \
--build-arg REVIEWDOG_VERSION=v0.20.0 \
-t action-pmd:custom .PMD for Java is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.
