Qodana, GitLab and Discord

Automated Qodana reports with GitLabs CI/CD? Yes please! Webhook notifications in your Discord server? GIMME GIMME GIMME!

Short, sweet and to the point. This short article gives you an example configuration for a Qodana-job in GitLabs CI/CD infrastructure, what you need to do in order to integrate it into your pipelines, and an example on what the finished product will look like.

The juicy stuff, the details, the how and the shiny, in a neatly packed post.

1. The juicy stuff:

Below is a GitLab CI/CD job definition of Qodana, which when run, will generate a Qodana report and expose it in any open merge request related to it. In addition to that, it will also post a message to a Discord server via a webhook URL defined in $QODANA_WEBHOOK_URL, notifiying anyone reading it about the availability of a new Qodana report, with a neat clickable link directly to said report.

Sounds sweet, right?

variables:
  QODANA_REMOTE_URL: git@$CI_SERVER_HOST:$CI_PROJECT_PATH.git
  QODANA_BRANCH: $CI_COMMIT_BRANCH
  QODANA_REPO_URL: $CI_PROJECT_URL
  QODANA_JOB_URL: $CI_JOB_URL

Qodana:
  image:
    name: jetbrains/qodana-jvm-community:2022.2
    entrypoint: [""]
  allow_failure: true
  script:
    - qodana --cache-dir=qodana/cache --save-report --results-dir=$CI_PROJECT_DIR/qodana --report-dir=$CI_PROJECT_DIR/qodana/report
  after_script:
    - wget -O discord.sh https://raw.githubusercontent.com/ChaoticWeg/discord.sh/master/discord.sh
    - apt-get update
    - apt-get install -y --no-install-recommends jq curl
    - chmod a+x discord.sh
    - ./discord.sh
      --webhook-url="$QODANA_WEBHOOK_URL"
      --username "$CI_PROJECT_TITLE"
      --avatar "https://discord.com/assets/f9bb9c4af2b9c32a2c5ee0014661546d.png"
      --text "New Qodana report available for pipeline ID ${CI_PIPELINE_ID}, commit ${CI_COMMIT_SHORT_SHA}, branch ${CI_COMMIT_REF_NAME}."
      --title "New ${CI_PROJECT_TITLE} Qodana Report"
      --description "New Qodana report available for pipeline ID ${CI_PIPELINE_ID}, commit ${CI_COMMIT_SHORT_SHA}, branch ${CI_COMMIT_REF_NAME}."
      --color "0xC0FFEE"
      --url "${CI_PROJECT_URL}/-/jobs/${CI_JOB_ID}/artifacts/file/qodana/report/index.html"
  artifacts:
    paths:
      - qodana
    expose_as: 'Qodana report'
  cache:
    - key:
        files:
          - qodana.yml
      paths:
        - qodana
      policy: pull-push

2. The details:

If you want to make use of the above configuration, you need a couple of things:

  • Discord webhook URL: The webhook URL specifies to which Discord server and which channel on that server the message, linking to the Qodana report, will be posted in. If you have a Discord server available to you on which you are either an admin, or the owner, or have a similar role with similar privileges, you can acquire such a webhook URL by:
    1. Hitting Edit Channel on the desired channel
    2. Switch to the Integrations tab
    3. Clicking New Webhook
    3.1 Configuring the look of the new webhook to your liking, i.e. name, icon, or changing the channel it is attached to
    4. Click Copy Webhook URL and store it somewhere safe. We will need it later.
  • FQDN of your GitLab instance: This will most likely be gitlab.com for most people. If you are running a self-hosted instance of GitLab, then you need the corresponding FQDN of your GitLab instance, i.e. mygitlab.mydomain.com.
    • This is optional! If you do not want to restrict the platform this job runs on, you can simply delete the two rules-lines at the bottom of the example above.
  • Avatar picture for your webhook: The example above would use Discords own logo, similar to the default logo of any new webhook. You should replace it with a URL to a logo which you want to use.
  • Variables: These variables are responsible for allowing the fancy opening of a problem in your local IDE. They are requried when running Qodana in GitLabs CI/CD system, as per QD-3373

3. The how:

Remember I said we will need the Discord webhook URL later? It’s now later.

  1. In your GitLab repository, head on to Settings -> CI/CD -> Variables and add a new variable to your CI/CD configuration for your project.
  2. Set the key-field to $QODANA_WEBHOOK_URL and the value-field to the webhook URL you saved earlier.
    1. Make sure the Mask variable checkbox is ticked! Otherwise the used webhook URL will be available in clear text in the logs of any Qodana Expose job run, thus allowing anyone to use it however they want!
  3. Head on to CI/CD -> Editor and add the Qodana Expose job from above to your pipeline.
    1. Make sure you add the Documentation-stage, or remove it from the job-definition, when adding said job to your pipeline. Otherwise your configuration will throw errors.
    2. Replace YOUR_GITLAB_FQDN, in the rules-section of the job-definition, with your the appropriate FQDN of the GitLab-instance you are using, if you haven’t already.
    3. Replace the URL in the avatar-parameter in the call of the Discord-script with a link to your own avatar, if you haven’t already, or leave it be in case you want to actually use the Discord logo.

And that’s pretty much it. When GitLab doesn’t complain about an invalid GitLab CI configuration, you can safely commit your changes. Depending on your CI configuration, this may trigger a new run of your pipeline and even trigger a run of your newly added Qodana Expose job.

4. The shiny:

If everything went smoothly, you will now receive Discord messages which contain a direct link to the newly generated Qodana Report and also receive entries in your Merge Request, which had a run of the Qodana Expose job, in which you can also inspect the available Qodana report.

Here are some examples from my setup for ServerPackCreator:

And that’s it! We’re done! You can now enjoy your Qodana reports which may or may not lead you into despair as you discover that your project has a great many things to fix/repair/change, or not.

Last but not least:

If you want to go further, you can configure Qodana to your liking and further fine-tune your reports. For more information about that, go ahead and give the documentation a read!