Running PMD in GitLab CI Script doesn't work unless echo command is added after the script runs

708 views Asked by At

This is an interesting issue. I have a GitLab project, and I've created a .gitlab-ci.yml to run a PMD that will scan my code after every commit. The ci.yml file looks like this:

image: "node:latest"

stages:
  - preliminary-testing

apex-code-scan:
  stage: preliminary-testing
  allow_failure: false
  script:
    - install_java
    - install_pmd
  artifacts:
    paths:
      - pmd-reports/

####################################################
# Helper Methods
####################################################

.sfdx_helpers: &sfdx_helpers |

  function install_java() {
    local JAVA_VERSION=11
    local JAVA_INSTALLATION=openjdk-$JAVA_VERSION-jdk
    echo "Installing ${JAVA_INSTALLATION}"
    apt update && apt -y install $JAVA_INSTALLATION
  }

  function install_pmd() {
    local PMD_VERSION=6.52.0
    local RULESET_PATH=ruleset.xml
    local OUTPUT_DIRECTORY=pmd-reports
    local SOURCE_DIRECTORY=force-app
    local URL=https://github.com/pmd/pmd/releases/download/pmd_releases%2F$PMD_VERSION/pmd-bin-$PMD_VERSION.zip
    
    # Here I would download and unzip the PMD source code. But for now I have the PMD source already in my project for testing purposes

    # apt update && apt -y install unzip
    # wget $URL
    # unzip -o pmd-bin-$PMD_VERSION.zip
    # rm pmd-bin-$PMD_VERSION.zip
    echo "Installed PMD!"

    mkdir -p $OUTPUT_DIRECTORY
    echo "Going to run PMD!"
    ls
    echo "Start"
    pmd-bin-$PMD_VERSION/bin/run.sh pmd -d $SOURCE_DIRECTORY -R $RULESET_PATH -f xslt -P xsltFilename=pmd_report.xsl -r $OUTPUT_DIRECTORY/pmd-apex.html
    echo "Done"
    rm -r pmd-bin-$PMD_VERSION
    echo "Remove pmd"
  }

before_script:
  - *sfdx_helpers

When I try to run this pipeline, it will fail after starting the PMD: enter image description here

However, if I make a small change to the PMD's .sh file and add an echo command at the very end. Then the pipeline succeeds:

PMD /bin/run.sh before (doesn't work):

...
java ${HEAPSIZE} ${PMD_JAVA_OPTS} $(jre_specific_vm_options) -cp "${classpath}" "${CLASSNAME}" "$@"

PMD /bin/run.sh after (does work):

...
java ${HEAPSIZE} ${PMD_JAVA_OPTS} $(jre_specific_vm_options) -cp "${classpath}" "${CLASSNAME}" "$@"
echo "Done1" // This is the last line in the file

enter image description here

I don't have the slightest idea why this is the case. Does anyone know why adding this echo command at the end of the .sh file would cause the pipeline to succeed? I could keep it as is with the echo command, but I would like to understand why it is behaving this way. I don't want to be that guy that just leaves a comment saying Hey don't touch this line of code, I don't know why, but without it the whole thing fails. Thank you!

2

There are 2 answers

0
adangel On BEST ANSWER

PMD exits with a specific exit code depending whether it found some violations or not, see https://pmd.github.io/latest/pmd_userdocs_cli_reference.html#exit-status

I guess, your PMD run finds some violations, and PMD exits with exit code 4 - which is not a success exit code.

In general, this is used to make the CI build fail, in case any PMD violations are present - forcing to fix the violations before you get a green build.

If that is not what you want, e.g. you only want to report the violations but not fail the build, then you need to add the following command line option:

--fail-on-violation false

Then PMD will exit with exit code 0, even when there are violations.

0
Tyler Edwards On

So it appears that the java command that the PMD runs for some reason returns a non-zero exit code (even though the script is successful). Because I was adding an echo command at the end of that bash script, the last line in the script returned a success exit code, which is why the GitLab CI pipeline succeeded when the echo command was there.

In order to work around the non-zero exit code being returned by the java PMD command, I have changed this line in my .gitlab-ci.yml file to catch the non-zero exit code and proceed.

function install_pmd() {
// ... For brevity I'm just including the line that was changed in this method
pmd-bin-$PMD_VERSION/bin/run.sh pmd -d $SOURCE_DIRECTORY -R $RULESET_PATH -f xslt -P xsltFilename=pmd_report.xsl -r $OUTPUT_DIRECTORY/pmd-apex.html || echo "PMD Returned Exit Code"
// ...
}