Giter Site home page Giter Site logo

pmd-github-action's Introduction

PMD - source code analyzer

PMD Logo

Join the chat Build Status Maven Central Reproducible Builds Coverage Status Codacy Badge Contributor Covenant Documentation (latest)

PMD is an extensible multilanguage static code analyzer. It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so forth. It's mainly concerned with Java and Apex, but supports 16 other languages. It comes with 400+ built-in rules. It can be extended with custom rules. It uses JavaCC and Antlr to parse source files into abstract syntax trees (AST) and runs rules against them to find violations. Rules can be written in Java or using a XPath query.

Currently, PMD supports Java, JavaScript, Salesforce.com Apex and Visualforce, Kotlin, Swift, Modelica, PLSQL, Apache Velocity, JSP, WSDL, Maven POM, HTML, XML and XSL. Scala is supported, but there are currently no Scala rules available.

Additionally, it includes CPD, the copy-paste-detector. CPD finds duplicated code in Coco, C/C++, C#, Dart, Fortran, Gherkin, Go, Groovy, HTML, Java, JavaScript, JSP, Julia, Kotlin, Lua, Matlab, Modelica, Objective-C, Perl, PHP, PLSQL, Python, Ruby, Salesforce.com Apex and Visualforce, Scala, Swift, T-SQL, Typescript, Apache Velocity, WSDL, XML and XSL.

๐Ÿš€ Installation and Usage

Download the latest binary zip from the releases and extract it somewhere.

Execute bin/pmd check or bin\pmd.bat check.

See also Getting Started

Demo:

This shows how PMD analyses openjdk:

Demo

There are plugins for Maven and Gradle as well as for various IDEs. See Tools / Integrations

โ„น๏ธ How to get support?

๐Ÿค Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Our latest source of PMD can be found on GitHub. Fork us!

The rule designer is developed over at pmd/pmd-designer. Please see its README for developer documentation.

๐Ÿ’ต Financial Contributors

Become a financial contributor and help us sustain our community. Contribute

โœจ Contributors

This project follows the all-contributors specification. Contributions of any kind welcome!

See credits for the complete list.

๐Ÿ“ License

BSD Style

pmd-github-action's People

Contributors

adangel avatar chemmi avatar dependabot[bot] avatar pmd-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

pmd-github-action's Issues

Add releasing documentation

  1. Rename milestone "next" to new version, e.g. "v1.0.1", close it, and create a new "next" milestone
  2. Push a tag with a full semantic version, e.g. "v1.0.1"
  3. Draft a new github release. Make sure to check the checkbox "Publish this Action to the GitHub Marketplace". Copy release notes from CHANGELOG.md. And finally publish the release.
  4. The publish workflow will start and create/update tags "v1" and "v1.0"
  5. Run Regenerate CHANGELOG and dist workflow manually to update CHANGELOG.md
  6. Update starter workflow: https://github.com/actions/starter-workflows/blob/main/code-scanning/pmd.yml
    See older PRs for examples:

Optionally create review comments

With #7 inline annotations are created, but they can't be commented or resolved. The PMD GitHub Action could add comments for each found violation when running on a pull request. This requires to only consider the modified files (#6).
See https://github.com/rody/pmd-review-github-action for the idea.

This should add a new input parameter for the action, which can switch on this feature. When review comments are created, no annotations should be created then.

See also #12 (comment)

Migrate to typescript

The action is now written in plain old javascript. But typescript offers early type checking, so would be beneficial.

At the same time, prettier should be integerated, maybe some vs-code settings (.vscode/settings.json).
When migrating to typescript, the eslint rules also need to be changed.

See https://github.com/actions/typescript-action

Use the checks api

See https://docs.github.com/en/rest/reference/checks

The advantage over the currently implemented build annotations (#7) is, that we can mark the build as failed directly. This would make the extra build step, to make the build fail based on the number of violations (exit 1), superfluous. Then this could be a built-in feature which can be enabled/disabled via a input parameter.

Code scanning doesn't contain all violations from PMD

PMD produces a SARIF file with multiple location entries per result. It appears that on GitHub only the first location is used.

Example file: pmd-report.sarif.txt
In this case, we have in total 24 violations in 6 files. The violations are from one of 9 different rules.
In the end, we don't have 24 alerts but only 9 alerts after uploading. This is also visible in the build log: "num_results_in_sarif":9.

Code scanning alerts: https://github.com/pmd/pmd-github-action-tests/security/code-scanning?query=branch%3Ajava
Test case, see https://github.com/pmd/pmd-github-action-tests/tree/java#code-scanning-alerts

Sarif feature in PMD: https://pmd.github.io/latest/pmd_userdocs_report_formats.html#sarif

Sarif Spec: https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html

3.14.23 results property
... an array of zero or more result objects (ยง3.27) each of which represents a single result detected in the course of the run

Could be interpreted in the way, that since we have 24 violations, each of these violations should be a single result...

3.27.12 locations property
a) A result object SHOULD contain a property named locations whose value is an array of zero or more location objects (ยง3.28) each of which specifies a location where the result occurred.
b) The locations array SHALL NOT contain more than one element unless the condition indicated by the result, if any, can only be corrected by making a change at every location specified in the array.
c) The locations array SHALL NOT be used to specify distinct occurrences of the same result which can be corrected independently.

ok, a) is what PMD does. All locations where a specific rule was violated.
sentence b) is probably violated: every location must be fixed to in order to correct the result
sentence c) is also violated: PMD only produces distinct results and they usually can be corrected independently.

So, I guess, that's a bug in PMD: pmd/pmd#3768.

Sourcepath is not applied correctly with analyzeModifiedFilesOnly

If you configure sourcePath: 'src/main/java' and you have sources under src/main/java/** and under src/main/java2/** then the sources under java2 are still analyzed. This is unexpected.

Workaround: sourcePath: 'src/main/java/' (with a trailing slash).

Note: this only is occurs when using "analyzeModifiedFilesOnly: true" (default). When all files are analyzed, then sourcePath is considered correctly.

Allow the --force-language PMD CLI option

The PMD CLI has the --force-language options to force a language to be used for all input files, irrespective of file names.

This feature allows us to use GitHub Actions for Salesforce projects.

Getting Warning in Node version only for PMD

Hi,

I have shifted all my Github Action(Pipeline) from 16 to 20 th version for Node, but I am facing warning only for PMD pipeline, Kindly help me to resolve this.

Pipeline code:

# Unique name for this workflow
name: PMD Code Scan

# Definition when the workflow should run
on:
    # The workflow will run whenever an event happens on a pull request
    pull_request:
      # The events are that a PR is opened, or when a commit is pushed
      # to a branch that has an existing pull request
      types: [opened, synchronize]
      # The branches filter allows to specify that this workflow should only
      # run if the branch name is as listed below. This way we prevent this workflow
      # from running when PRs are opened on other branches
      branches: [ environment/*/dev , environment/qa ]
      # We only care about changes to the force-app directory, which is the
      # root directory of the sfdx project. This prevents the job from running
      # when changing non-salesforce files (like this yml file).
      paths:
        - 'force-app/**'
            

# Jobs to be executed when the above conditions are met
jobs:
    # This is the name of the job. You can give it whatever name you want
    Run-PMD-Code-Scan:
        # As mentioned in the blog post, this job runs inside a VM. Here we
        # can specify which OS this VM should run on. 
        # In this case, we are going to run our commands on the latest version
        # of ubuntu
        runs-on: ubuntu-latest
        permissions:
                    contents: read
                    pull-requests: write
                    # required for all workflows
                    security-events: write
                    # only required for workflows in private repositories
                    actions: read
                    
        if: ${{ github.actor != 'dependabot[bot]' }}
        steps:
      
            # Now we install nodejs in the VM, and specify version 14
            - uses: actions/setup-node@v4
              with:
                node-version: '20'

            # The idea is that the VM can access your remote repository
            # because your repository is an sfdx project.
            # This is a default action that allows us to enter the root 
            # directory of the repository

            # Make sure to specify fetch-depth:0. This allows us to
            # access previous commits that have been pushed to the repository.

            # We'll need this later when we try to figure out which metadata has 
            # changed between commits, so that we can only deploy that metadata
            # to the destination org

            - name: 'Checkout source code'
              uses: actions/checkout@v4
              with:
                fetch-depth: 0
            
            # Run PMD Scan
            - name: 'Run PMD Scan'
              uses: pmd/pmd-github-action@v1
              id: pmd
              with: 
                    sourcePath: 'force-app'
                    rulesets: 'ruleset.xml'    
                    analyzeModifiedFilesOnly: true
                    createGitHubAnnotations: true 
                    
            - name: Fail build if there are violations
              if: steps.pmd.outputs.violations != 0
              run: exit 1              

Warning:

Run-PMD-Code-Scan
Node.js 16 actions are deprecated. Please update the following actions to use Node.js 20: pmd/pmd-github-action@v1. For more information see: https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/.

Thanks

[Feature Request] Minimum severity option

Whether it uses a number 1-5 or "Low" "Medium Low" etc, it would be useful because it would let me use a single rules file for my VSCode PMD scanning and GitHub Actions scanning - and only use severity 1 & 2 in my CI workflow.

Otherwise, I have to have two separate files, and while I don't change them much, setting properties in both across many projects is time-consuming.

Thank you!

Code scanning doesn't work well with analyzeModifiedFilesOnly

Code scanning seems to require the complete picture of the project. E.g. if a violation is not reported anymore, the code scanning alerts are getting closed.

This should be done:

Action doesn't work under Windows runner

Log output:

Run pmd/pmd-github-action@features/annotation
  with:
    sourcePath: src/main/java
    rulesets: ruleset.xml,category/java/design.xml/AbstractClassWithoutAnyMethod
    version: latest
"C:\Program Files\PowerShell\7\pwsh.exe" -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "$ErrorActionPreference = 'Stop' ; try { Add-Type -AssemblyName System.IO.Compression.ZipFile } catch { } ; try { [System.IO.Compression.ZipFile]::ExtractToDirectory('D:\a\_temp\d900343f-1477-4896-849f-4ad7c682771e', 'D:\a\_temp\31b52bc9-9a59-4858-a700-f782163268ae', $true) } catch { if (($_.Exception.GetType().FullName -eq 'System.Management.Automation.MethodException') -or ($_.Exception.GetType().FullName -eq 'System.Management.Automation.RuntimeException') ){ Expand-Archive -LiteralPath 'D:\a\_temp\d900343f-1477-4896-849f-4ad7c682771e' -DestinationPath 'D:\a\_temp\31b52bc9-9a59-4858-a700-f782163268ae' -Force } else { throw $_ } } ;"
Using PMD 6.41.0 from cached path C:\hostedtoolcache\windows\pmd\6.41.0\x64
Error: Unable to locate executable file: C:\hostedtoolcache\windows\pmd\6.41.0\x64/pmd-bin-6.41.0/bin/run.sh. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.
PMD exited with undefined

PMD detected 0 violations.
Error: File pmd-report.sarif does not exist

Clarify the need for Java

This action calls PMD and PMD requires a Java runtime for execution.
In the README.md the following basic configuration is suggested:

steps:
  - uses: actions/setup-java@v2
    with:
      distribution: 'temurin'
      java-version: '11'
  - uses: pmd/pmd-github-action@v1
    with:
      rulesets: 'ruleset.xml'

However, the "actions/setup-java" step is not really necessary, since Java is one of the pre-installed tools in the runners. See https://github.com/actions/virtual-environments/ and more specifically https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md#java
This is available under all operating systems.

Support reports in other formats

Hello Folks !!

Is there any way to specify the type of report in the action ? per example , can i do this

 - uses: pmd/pmd-github-action@v1
      id: pmd
      with:
        version: '6.40.0'
        sourcePath: 'src/main/java'
        rulesets: 'rulesets/java/quickstart.xml,ruleset.xml'
        reportFile: 'pmd-report.xlst' "Or another report file extension"

Thanks!

"Error: Not Found" if push event's `before` commit is `0000000000000000000000000000000000000000`

Scenario

When configured to run on a push event and the GitHub's context.payload.before commit is 0000000000000000000000000000000000000000 (meaning there was no prior commit) then the action fails with error Error: Not Found.

The error is raised by util.js by determineModifiedFiles(..) function when it invokes octokit.rest.repos.compareCommitsWithBasehead(..)

https://github.com/pmd/pmd-github-action/blob/main/lib/util.js#L143

Config File

# .github/workflows/pmd.yml
name: Run PMD

on:
    push:
        branches:
            - my-branch
        paths:
            - my-folder

jobs:
    build:
        name: Run PMD
        runs-on: self-hosted
        steps:
            - name: Checkout repository
              uses: actions/checkout@v3

            - name: Run Apex Rules
              uses: pmd/pmd-github-action@v1
              with:
                  rulesets: rulesets/PMD/apex-rules-github.xml
                  sourcePath: my-folder
                  analyzeModifiedFilesOnly: true
                  createGitHubAnnotations: true

Expected Result

  • PMD to not perform a diff comparison because there is no prior commit.
  • PMD to identify the list of files included in the commit for the given source path.

Example using Git:

$ git diff-tree --no-commit-id --name-only --diff-filter=AM -r <commit>
index.html
my-folder/some-file.java

Example using Octokit

const response = await octokit.rest.repos.getCommit({
    ...context.repo,
    ref: eventData.after,
});
console.log(response);

---

{
  status: 200,
  url: 'https://api.github.com/repos/my-org/my-repo/commits/65a6b28ce342017b77bde00498434386961cdff7',
  headers: {
    ...
  },
  data: {
    sha: '65a6b28ce342017b77bde00498434386961cdff7',
    node_id: 'C_kwDOFndAydoAKDY1YTZiMjhjZTM0MjAxN2I3N2JkZTAwNDk4NDM0Mzg2OTYxY2RmZjc',
    commit: {
      ...
    },
    url: '...',
    html_url: '...',
    comments_url: '...',
    author: {
      ...
    },
    committer: {
      ...
    },
    parents: [ { ... } ],
    stats: { total: 40, additions: 36, deletions: 4 },
    files: [
        {
            sha: '4b38cfc1be0f3290f3340093825b6bbc48fd69b4',
            filename: 'index.html',
            status: 'modified',
            additions: 9,
            deletions: 1,
            changes: 10,
            blob_url: '...',
            raw_url: '...',
            contents_url: '...',
            patch: '...'
        },
        {
            sha: '565abd034c00e10add52d15cfe478f5bee3fe1da',
            filename: 'my-folder/my-file.java',
            status: 'modified',
            additions: 9,
            deletions: 1,
            changes: 10,
            blob_url: '...',
            raw_url: '...',
            contents_url: '...',
            patch: '...'
        }
    ]
  }
}

Actual Result

  • Action fails with the following error
##[debug]finished caching tool
Using PMD 6.49.0 from cached path /home/docker/actions-runner/_work/_tool/pmd/6.49.0/x64
Determining modified files in my-folder...
##[debug]Push on refs/heads/my-branch: 0000000000000000000000000000000000000000...c46068a4fd0827f6c4365d24c02c1bc44707287a
Error: Not Found
##[debug]Node Action run completed with exit code 1

Workaround

  • Push another commit to the branch

Code scanning alert doesn't find file in repository

When uploading the SARIF file to code-ql, the file in the repository is not found:

Preview unavailable

Sorry, we couldn't find this file in the repository.

grafik


Workaround

Add the following step before upload-sarif:

      - name: Relativize SARIF
        shell: bash
        run: |
          jq ".runs[0].results[].locations[].physicalLocation.artifactLocation.uri |= sub(\"${GITHUB_WORKSPACE}/\"; \"\")" pmd-report.sarif > pmd-report2.sarif
          mv -f pmd-report2.sarif pmd-report.sarif

No annotations created under Windows

It seems, that issue #51 reappeared...

Log output:

  src\classes2\AllInOne.cls:2:FieldNamingConventions (Priority: 1):The instance field name 'INSTANCE_FIELD' doesn't match '[a-z][a-zA-Z0-9]*'
  Error: Configurable naming conventions for field declarations. This rule reports variable declarations
  which do not match the regex that applies to their specific kind ---e.g. constants (static final),
  static field, final field. Each regex can be configured through properties.
  
  By default this rule uses the standard Apex naming convention (Camel case).
  
  FieldNamingConventions (Priority: 1, Ruleset: Code Style)
  https://pmd.github.io/pmd-6.55.0/pmd_rules_apex_codestyle.html#fieldnamingconventions

That means, we use backslashes as path separators. That means, in the sarif.json file, there are no valid URIs anymore...

        {
          "ruleId": "FieldNamingConventions",
          "ruleIndex": 0,
          "message": {
            "text": "The instance field name 'INSTANCE_FIELD' doesn't match '[a-z][a-zA-Z0-9]*'"
          },
          "locations": [
            {
              "physicalLocation": {
                "artifactLocation": {
                  "uri": "src\\classes2\\AllInOne.cls"
                },
                "region": {
                  "startLine": 2,
                  "startColumn": 13,
                  "endLine": 2,
                  "endColumn": 26
                }
              }
            }
          ]
        },

I think, these should be forward slashes....

Create inline annotations for found violations

GitHub supports to show annotations on the file tab of a pull request or when viewing a single commit.
This PMD Action should create for each found violation that is in the pmd-report.sarif file such an inline annotation. The rule priorities can be used to map to either a error, warning or notice message.

The result might look like this:

grafik


Implementation notes:

  • With Setting an error message GitHub Actions can create build annotations as errors, warnings or notice.
  • The filename parameter probably needs to be relative to the repository root. With git rev-parse --show-toplevel one can figure out the current root checkout directory (which could be anywhere on the runner) and use that to make the absolute filepath in the sarif report into relative ones.

Support analyzing only modified files

With the new input parameter analyzeModifiedFilesOnly this action now determines the modified files of a push or pull_request and executes PMD only on these files. This new input parameter is enabled by default.

Instead of analyze all files under "sourcePath", only the files that have been touched in a pull request or push will be analyzed. This makes the analysis faster and helps especially bigger projects which gradually want to introduce PMD. This helps in enforcing that no new code violation is introduced.

Depending on the analyzed language, the results might be less accurate results. At the moment, this is not a problem, as PMD mostly analyzes each file individually, but that might change in the future.

If the change is very big, not all files might be analyzed. Currently the maximum number of modified files is 300.

Note: the touched files are analyzed completely and all found violations within these files are reported - regardless whether the specific lines have been modified or not.


For bigger projects or projects, which gradually want to introduce PMD, it would be beneficial if only the currently modified files would be analyzed. This helps in enforcing that no new code violation is introduced.

Maybe a new input parameter needs to be introduced, similar like pmd-analyser-action's analyze-all-code.

Running the action in this mode, we would probably ignore the sourcePath input parameter and only look at the github event's compare payload: For pull requests we could look at the diff_url or patch_url. For pushes we might be able to use the "compare" url. The REST API also has a way to compare two commits. For pull requests there is list-pull-requests-files.
If the files can be determined by calling the GitHub API, then there is no full checkout needed (fetch-depth).

Instead of providing the sourcePath to PMD (-d cli option), the --file-list option needs to be used, generating a comma-delimited file list on the fly.

A simple solution for the first version could be: let PMD analyze all files and just filter the found violations.

Currently the action doesn't use an API token. This probably should be changed, if the patches/diffs are retrieved by the API calls. Then @actions-github. In theory, the default token should be available via the github-context. Since we only need read-only access, that should be sufficient. Then no extra configuration is required. At least we can provide a reasonable default value. The default value can be provided like the "checkout" action does it: https://github.com/actions/checkout/blob/230611dbd0eb52da1e1f4f7bc8bb0c3a339fc8b7/action.yml#L12-L24

Which mode is active (analyzing all files or only modified files) should be logged in the build log, e.g. "Running PMD on path xyz" or "Running PMD on x files".

PMD version 6.46.0 run check on "Unchanged files with check annotations"

Hello,

As PMD introduced ver 6.46.0 on May 28, GitHub action started to target also "Unchanged files with check annotations" which are not part of the PR.

We are forced to rollback to ver 6.45.0 because this behavior was blocking our deployment.

Is this an expected thing in 6.46? And is there a way to skip the "Unchanged files with check annotations" check from the violations property of the action output and use the ver 6.46, or this is a bug?

Thank you.

Can't run action on GHES

I have seen the similar problem that was already raised but quite unsure if those are identical so that is why i wanted to report it.
Im receiving the error below.
Screenshot 2023-03-15 at 10 17 13
And here is the my action YML. Please advise.

# Unique name for this workflow
name: Pre-Release PR
# Definition when the workflow should run
on:
  workflow_dispatch:
  pull_request:
    types: [opened, edited, synchronize, reopened]
permissions:
  pull-requests: write
jobs:
  pmd-run:
    runs-on: catalyst
    steps:
      # Now we install nodejs in the VM, and specify version 14
      - uses: actions/setup-node@v3
        with:
          node-version: "14"
      # Install java as it is required for the next step
      - uses: actions/setup-java@v3
        with:
          distribution: "temurin"
          java-version: "8"
      # Checkout the source code
      - name: "Checkout source code"
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
      # Run PMD scan
      - name: "Run PMD scan"
        uses: pmd/[email protected]
        id: pmd
        with:
          sourcePath: "force-app"
          rulesets: "ruleset.xml"
          analyzeModifiedFilesOnly:
          createGitHubAnnotations: true

      # Check for PMD violations
      - name: "Check for PMD violations"
        if: steps.pmd.outputs.violations != 0
        run: exit 1

No annotations created under Windows

If the action is executed under Windows, then no code annotations are created. This is probably because of platform specific file paths (e.g. src/main/java vs. src\main\java) and github can't map this to the files.

Support equivalent of failurePriority

You can configure a specific priority for each rule in your own ruleset (https://pmd.github.io/latest/pmd_userdocs_configuring_rules.html#message-and-priority-overriding).

The maven-pmd-plugin supports the parameter failurePriority which can used to fail the build only for "high priority" violations. The lower priority violations are still reported, though.

Currently the action only provides the number of found violations regardless of the priority. So you can only fail the build if any violation is found. This probably has to be tackled together with #30 .

Release summary for v1.0.0

First release of the official GitHub Action for PMD.

This action runs PMD static code analysis checks.

It can execute PMD with your own ruleset against your project. It creates a SARIF report which is uploaded as a build artifact. Furthermore the build can be failed based on the number of violations.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.