场景示例-开发一个带红线卡点的SonarQube扫描步骤

更新时间:
复制 MD 格式

本文将以对接 SonarQube 扫描服务为例,介绍如何使用新版 Flow-CLI 工具定制开发一个带红线卡点的扫描步骤。

前提条件

本地开发步骤

参考 RedlineSonar 示例代码 https://atomgit.com/flow-step-custom/RedlineSonar ,本地拉取示例代码:

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

示例代码目录结构如下:

.
├── README.md     # 步骤说明
├── package.json  # typescript 工程包声明
├── src           # 步骤后端执行逻辑
│   ├── index.ts
│   └── params.ts
├── step.yaml     # 步骤前端展示描述信息 yaml
├── tsconfig.eslint.json
└── tsconfig.json

步骤前端展示 step.yaml

step.yaml 文件定义了步骤前端描述,用于定义步骤执行所需的输入参数。参数说明如下:

参数

参数说明

id

步骤唯一标识,全局唯一。(如需发布步骤到企业,请修改 id 为唯一标识后发布)

name

用于定义步骤名称。

items

步骤语言描述,请参考步骤语言YAML描述。

redline

红线信息。

datamap

type 枚举字段 LE: 实际值小于等于期望值;GE: 实际值大于等于期望值;EQ 实际值等于期望值

key 红线待校验字段。

本步骤定义以下几个表单,作为步骤执行参数输入:

  • Sonar服务器地址

  • Sonar Token

  • Sonar Project Key

  • 红线信息

---
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: Sonar服务器地址
    name: STEP_SONAR_HOST
    type: input
  - label: Sonar Token
    name: STEP_SONAR_TOKEN
    type: password
    rules:
      - require: false
  - label: Sonar Project Key
    name: STEP_SONAR_PROJECT_KEY
    type: input
  - label: 红线信息
    name: CHECK_REDLINES
    type: addable_group
    rules:
      - require: false
    add_button:
      type: icon
      icon: plus
      text: 增加红线
      tip:
        icon: question-circle
        description: 红线校验失败任务将失败
    template:
      items:
        - name: redline
          label: 红线
          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

红线信息key定义如下,以下预置 key 支持显示中文描述,自定义key则直接显示key:

key(不区分大小写)

中文描述

passedrate

测试通过率

total

Total 问题数

blocker

Blocker 问题数

high

High 问题数

medium

Medium 问题数

critical

Critical 问题数

major

Major 问题数

violation

Violation 问题数

information

Information 问题数

warning

Warning 问题数

error

Error 问题数

linecoveragerate

行覆盖率

branchcoveragerate

分支覆盖率

methodcoveragerate

方法覆盖率

classcoveragerate

类覆盖率

instructioncoveragerate

指令覆盖率

步骤后端执行逻辑 src/index.ts

src/index.ts 文件定义了步骤后端执行逻辑,主要逻辑说明如下:

  1. 输出基础信息和检验步骤入参

  2. 调用 sonar api 获取指定项目的指标数据(私有项目需要指定 STEP_SONAR_TOKEN)

  3. 将 sonar 返回数据格式化为红线数据

  4. 调用 sdk 进行红线检验和记录报告链接信息

async function runStep(): Promise<void> {
  const params = getParams()
  // 输出基础信息和检验入参
  logAndValidParams(params);

  // 调用 sonar api 获取指定项目的指标数据
  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'])

  // 准备红线数据
  const readlineResults = [] as RedlineResult[]
  const bugsRR = generateRedlineResult("Bugs", "缺陷", bugs, redline.Error);
  readlineResults.push(bugsRR)

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

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

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

  // 调用 sdk 进行红线检验和记录报告链接信息
  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)
  }
}

发布步骤

按需修改上述步骤实现代码后,切换到 step.yaml 文件所在目录,执行以下命令发布步骤到企业:

flow-cli step publish

流水线使用步骤并运行

步骤发布成功后,进入流水线编辑页面,可以在任务编辑页面,指定容器环境 -> 添加步骤 -> 企业步骤,添加 RedlineSonar 这个步骤。

在 RedlineSonar 步骤的配置面板中,按需填写 Sonar服务器地址(如 https://sonarcloud.io)、Sonar TokenSonar Project Key,并在 红线信息 中配置校验项(如 Coverage 大于等于 15)。

编辑后保存并运行流水线,查看步骤运行结果和日志:

流水线运行结果页面以横向节点流形式展示各步骤的执行状态。其中 SonarRedline 节点因 红线未通过 而标红失败,从而导致整体运行失败,节点中可看到红线校验项的实际指标:缺陷 0、漏洞 27、坏味道 38、覆盖率 11.5。

2024-12-04 04:15:46 [INFO] Sonar Metrics: {"alert_status":"ERROR","bugs":"0","code_smells":"30","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=缺陷
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=漏洞
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=坏味道
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=覆盖率
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 [SUCCESS] run step successfully!

高级用法

在流水线中,推荐使用原子的步骤进行组合支持复杂的使用场景。例如以上的 RedlineSonar 步骤只负责从 sonar 读取某个 projectKey 的 metric 数据,对于 mvn 工程的 sonar 卡点可采取步骤组合如下。

推荐在容器环境(如 build-steps/alinux3)中依次添加 配置 MavenSettings 文件安装 Java执行命令RedlineSonar 四个步骤组合使用。

其中执行命令对 mvn 工程进行构建和调用 sonar 插件进行扫描:

# mvn 构建
mvn -B clean package -Dmaven.test.skip=true -Dautoconfig.skip

# 通过 mvn sonar 插件执行 sonar 扫描
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>

运行效果如下:

运行结果卡片显示 Java 构建 + RedlineSonar 步骤执行成功,耗时 1 分 15 秒,可通过 报告日志 链接进入详情;卡片底部汇总展示 Sonar 扫描的核心质量指标:缺陷 0、漏洞 0、坏味道 3、覆盖率 7.4%。

[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!

点击「报告」查看sonar扫描结果详情如下:

Sonar 报告页面切换到 Measures 标签后,左栏 Overall Code 区域汇总展示项目度量:Debt Ratio 0.0%、Rating A、Code Smells 3、Debt 25min;右栏可进一步查看 Code Smells 在 src 目录和 pom.xml 文件中的分布。

在同一 Measures 视图的 Overall Code 区域,Coverage(覆盖率)显示为 7.4%。