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
-
You have downloaded and installed the latest version of Flow-CLI. See Download and install Flow-CLI.
-
You have a SonarQube service that is accessible from the public internet, such as https://sonarcloud.io/. If your service is not publicly accessible, you must use a private build agent. For more information, see How to use Alibaba Cloud DevOps pipelines for CI/CD in a private network?
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 The |
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:
-
Output basic information and validate the step's input parameters.
-
Call the SonarQube API to get the metric data for the specified project. The STEP_SONAR_TOKEN is required for private projects.
-
Format the data returned from SonarQube into redline data.
-
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%.