Develop a SonarQube step with redline checks

更新时间:
复制 MD 格式

This tutorial demonstrates how to use the latest version of Flow-CLI to develop a custom scanning step with redline checks, using a SonarQube scanning service as an example.

Prerequisites

Develop the step locally

Clone the RedlineSonar sample code from https://atomgit.com/flow-step-custom/RedlineSonar:

git clone https://atomgit.com/flow-step-custom/RedlineSonar.git

The directory structure of the sample code is as follows:

.
├── README.md     # Step description
├── package.json  # TypeScript project manifest
├── src           # Backend execution logic for the step
│   ├── index.ts
│   └── params.ts
├── step.yaml     # YAML file for the step's UI definition
├── tsconfig.eslint.json
└── tsconfig.json

Step UI in step.yaml

The step.yaml file defines the step's UI and the input parameters required for its execution. The following table describes the main parameters in this file.

Parameter

Description

id

A unique identifier for the step. This ID must be globally unique. If you plan to publish the step to your enterprise, change the ID to a unique value before publishing.

name

The name of the step.

items

Defines the input fields and UI elements for the step. For details, refer to the Step Language YAML Description.

redline

Redline information.

datamap

The type enumeration field defines the comparison operator: LE: less than or equal to the threshold; GE: greater than or equal to the threshold; EQ: equal to the threshold.

The key field specifies the metric for the redline check.

This step defines the following form fields as input parameters:

  • SonarQube server address

  • SonarQube token

  • SonarQube project key

  • Redline information

---
apiVersion: v2
kind: DefaultJob
id: RedlineSonar
name: RedlineSonar
description: flow redline check with sonar
helpUrl: https://atomgit.com/flow-step-custom/RedlineSonar
execution:
  executor: node
  main: dist/index.js
items:
  - label: SonarQube server address
    name: STEP_SONAR_HOST
    type: input
  - label: SonarQube token
    name: STEP_SONAR_TOKEN
    type: password
    rules:
      - require: false
  - label: SonarQube project key
    name: STEP_SONAR_PROJECT_KEY
    type: input
  - label: Redline information
    name: CHECK_REDLINES
    type: addable_group
    rules:
      - require: false
    add_button:
      type: icon
      icon: plus
      text: Add redline
      tip:
        icon: question-circle
        description: The task will fail if a redline check fails.
    template:
      items:
        - name: redline
          label: Redline
          position: flat
          type: custom_redline_dropdown
          datamap: '[{"key": "Bugs","type": "LE"},{"key": "Vulnerabilities","type": "LE"},{"key": "Smells","type": "LE"},{"key": "Coverage","type": "GE"}]'
          rules:
            - require: false

The keys for redline information are defined as follows. Pre-defined keys support localized descriptions, while custom keys are displayed as is.

Key (case-insensitive)

Description

passedrate

Test pass rate

total

Total issues

blocker

Blocker issues

high

High issues

medium

Medium issues

critical

Critical issues

major

Major issues

violation

Violation issues

information

Information issues

warning

Warning issues

error

Error issues

linecoveragerate

Line coverage

branchcoveragerate

Branch coverage

methodcoveragerate

Method coverage

classcoveragerate

Class coverage

instructioncoveragerate

Instruction coverage

Backend logic in src/index.ts

The src/index.ts file contains the backend logic for the step. The main logic includes the following actions:

  1. Output basic information and validate the step's input parameters.

  2. Call the SonarQube API to get the metric data for the specified project. The STEP_SONAR_TOKEN is required for private projects.

  3. Format the data returned from SonarQube into redline data.

  4. Call the SDK to perform redline checks and record the report link.

async function runStep(): Promise<void> {
  const params = getParams()
  // Output basic information and validate input parameters
  logAndValidParams(params);

  // Call the SonarQube API to get metric data for the specified project
  const metrics = await requestSonarMetrics(`${params.sonarHost}/api/measures/search`, params.sonarToken, {
    projectKeys: `${params.sonarProjectKey}`,
    metricKeys: 'alert_status,bugs,reliability_rating,vulnerabilities,security_rating,code_smells,sqale_rating,duplicated_lines_density,coverage,ncloc,ncloc_language_distribution'
  })
  step.infoCyan(`Sonar Metrics: ${JSON.stringify(metrics)}`)

  const bugs = Number(metrics['bugs'])
  const vulnerabilities = Number(metrics['vulnerabilities'])
  const smells = Number(metrics['code_smells'])
  const coverage = Number(metrics['coverage'])

  // Prepare the redline data
  const readlineResults = [] as RedlineResult[]
  const bugsRR = generateRedlineResult("Bugs", "Bugs", bugs, redline.Error);
  readlineResults.push(bugsRR)

  const vulnerabilitiesRR = generateRedlineResult("Vulnerabilities", "Vulnerabilities", vulnerabilities, redline.Error);
  readlineResults.push(vulnerabilitiesRR)

  const smellsRR = generateRedlineResult("Smells", "Code Smells", smells, redline.Error);
  readlineResults.push(smellsRR)

  const coverageRR = generateRedlineResult("Coverage", "Coverage", coverage, redline.Warning);
  readlineResults.push(coverageRR)

  // Call the SDK to perform the redline check and record the report link
  const redlineInfo = {} as RedlineInfo
  redlineInfo.title = 'Redline Sonar'
  redlineInfo.reportUrl = `${params.sonarHost}/component_measures?id=${params.sonarProjectKey}`
  redlineInfo.readlineResults = readlineResults
  const checkResult = step.redline.redlineCheck(redlineInfo, process.env['CHECK_REDLINES'])
  if (!checkResult){
      step.error('Redline check failed')
      process.exit(-1)
  }
}

Publish the step

After modifying the step's implementation code as needed, navigate to the directory that contains the step.yaml file and run the following command to publish the step to your enterprise:

flow-cli step publish

Use the step in a pipeline

After the step is published successfully, go to the pipeline editing page. On the task editing page, you can add the RedlineSonar step by selecting Specify container environment > Add step > Enterprise step.

In the configuration panel of the RedlineSonar step, fill in the Sonar Server Address (such as https://sonarcloud.io), Sonar Token, and Sonar Project Key as needed, and in the Redline Information section, configure validation items (such as Coverage greater than or equal to 15).

After editing, save and run the pipeline. You can then view the step's execution results and logs:

The pipeline run results page displays the execution status of each step in a horizontal node flow. The SonarRedline step failed and is highlighted in red because the redline check failed, which caused the entire run to fail. The step shows the actual metrics for the redline check: 0 bugs, 27 vulnerabilities, 38 code smells, and 11.5% coverage.

2024-12-04 04:15:46 [INFO] Sonar Metrics: {"alert_status":"ERROR","bugs":"0","vulnerabilities":"27","code_smells":"38","coverage":"11.5","reliability_rating":"1.0","security_rating":"1.0"}
2024-12-04 04:15:46 [INFO] STAT_URL_REPORT=https://sonarcloud.io/component_measures?id=cccfeng_sonar-java-test
2024-12-04 04:15:46 [INFO] STAT_NAME_Bugs=Bugs
2024-12-04 04:15:46 [INFO] STAT_VALUE_Bugs=0
2024-12-04 04:15:46 [INFO] REDLINE_ITEM_LINE
{"key":"Bugs","threshold":100,"checkVal":0,"type":"LE","checked":true,"checkResult":true}
2024-12-04 04:15:46 [INFO] STAT_NAME_Vulnerabilities=Vulnerabilities
2024-12-04 04:15:46 [INFO] STAT_VALUE_Vulnerabilities=27
2024-12-04 04:15:46 [INFO] REDLINE_ITEM_LINE
{"key":"Vulnerabilities","threshold":25,"checkVal":27,"type":"LE","checked":true,"checkResult":false}
2024-12-04 04:15:46 [INFO] STAT_NAME_Smells=Code Smells
2024-12-04 04:15:46 [INFO] STAT_VALUE_Smells=38
2024-12-04 04:15:46 [INFO] REDLINE_ITEM_LINE
{"key":"Smells","threshold":35,"checkVal":38,"type":"LE","checked":true,"checkResult":false}
2024-12-04 04:15:46 [INFO] STAT_NAME_Coverage=Coverage
2024-12-04 04:15:46 [INFO] STAT_VALUE_Coverage=11.5
2024-12-04 04:15:46 [INFO] REDLINE_ITEM_LINE
{"key":"Coverage","threshold":10,"checkVal":11.5,"type":"GE","checked":true,"checkResult":true}
2024-12-04 04:15:46 [ERROR] Redline check failed

Advanced usage

In a pipeline, we recommend combining atomic steps to support complex use cases. For example, the RedlineSonar step is only responsible for reading metric data for a specific projectKey from SonarQube. To implement a SonarQube check for a Maven project, you can combine steps.

We recommend that you add the Configure MavenSettings file, Install Java, Execute command, and RedlineSonar steps in sequence in a container environment such as build-steps/alinux3.

Use the Run Command step to build the Maven project and invoke the SonarQube scanner plugin to perform the scan:

# Build with Maven
mvn -B clean package -Dmaven.test.skip=true -Dautoconfig.skip

# Run SonarQube scan by using the Maven SonarQube plugin
mvn verify -Dmaven.test.failure.ignore=true org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.token=<your personal access token> -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=<your organization key> -Dsonar.projectKey=<your project key>

The following is an example of the result:

The run result card shows that the Java Build + RedlineSonar step succeeded in 1 minute and 15 seconds, with details available through the Report and Log links. The bottom of the card summarizes the core quality metrics from the Sonar scan: 0 bugs, 0 vulnerabilities, 3 code smells, and 7.4% coverage.

[INFO] SCM Publisher 2/2 source files have been analyzed (done) | time=153ms
[INFO] CPD Executor 2 files had no CPD blocks
[INFO] CPD Executor Calculating CPD for 1 file
[INFO] CPD Executor CPD calculation finished (done) | time=5ms
[INFO] Analysis report generated in 159ms, dir size=287 KB
[INFO] Analysis report compressed in 19ms, zip size=63 KB
[INFO] Analysis report uploaded in 515ms
[INFO] ANALYSIS SUCCESSFUL, you can find the results at: https://sonarcloud.io/dashboard?id=cccfeng_sonar-java-test
[INFO] Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report
[INFO] More about the report processing at https://sonarcloud.io/api/ce/task?id=AZOQ-dopFA2SZIKknz46
[INFO] Sensor cache published successfully
[INFO] Analysis total time: 25.078 s
[INFO] SonarScanner Engine completed successfully
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 57.651 s
[INFO] Finished at: 2024-12-04T17:21:55+08:00
[INFO] Final Memory: 30M/134M
[INFO] ------------------------------------------------------------------------
2024-12-04 17:21:55 [SUCCESS] run step successfully!

Click **Report** to view the details of the SonarQube scan results:

After you switch to the Measures tab on the Sonar report page, the Overall Code section in the left pane displays a summary of project metrics: Debt Ratio 0.0%, Rating A, Code Smells 3, and Debt 25 min. The right pane shows the distribution of Code Smells in the src directory and the pom.xml file.

In the Overall Code area of the same Measures view, Coverage is 7.4%.