01 场景介绍
Flow-CLI 是云效流水线 Flow 推出的一款命令行工具,帮助用户定制开发自己的流水线步骤或组件,满足自定义步骤逻辑或对接三方自有平台等场景,以扩展流水线能力。
Flow-CLI V2 基于TypeScript 编写步骤逻辑,相较于 Flow-CLI V1 shell 脚本编写方式,V2 版本具备如下优势:
- 基于 TypeScript 编写步骤,步骤代码可测试、质量更稳定。
- 步骤一次开发,可支持多操作系统/架构运行。
- 可复用 @flow-step/step-toolkit sdk 提供的基础能力,步骤开发更快速便捷。示例步骤代码及 SDK 详见:https://atomgit.com/flow-step/step-toolkit/blob/main/examples/README.md
Flow-CLI 使用的典型场景如:自定义开发一个 Sonar 扫描步骤,以在流水中触发 Sonar 扫描,并以扫描结果作为红线卡点,以保证代码质量;对接三方自有审批平台,在发布前进行检查审批,审批通过才允许发布。
接下来,我们就以对接 Sonar 服务为例,手把手教你开发一个带红线功能的 Sonar 扫描步骤。
02 场景示例:开发一个带红线功能 Sonar 扫描步骤
2.1. 前提条件
准备好一个公网可访问的 Sonar 服务。例如 https://sonarcloud.io/(公网不可达的服务需使用私有构建机方案,详见私网环境下如何使用云效流水线进行 CI/CD?[1])
2.2. 下载安装 Flow-CLI 工具
确保本地已经安装 NodeJS,之后在命令提示符中输入以下命令进行 Flow-CLI V2 的安装。
npm i -g @flow-step/flow-cli --registry=https://registry.npmmirror.com flow-cli -h # 输出帮助信息说明安装成功
登录 Flow 企业:
flow-cli login # 登录
flow-cli 将会自动打开浏览器进入 Flow 登录页面,如果已经登录会提示 success,登录成功后命令行会提示选择账号下企业,输入企业对应的数字进入企业。
2.3. 新建并开发步骤
参考 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[2]文件定义了步骤前端描述,用于定义步骤执行所需的输入参数。参数说明如下:
参数 | 参数说明 |
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
步骤后端执行逻辑 src/index.ts
src/index.ts[3]文件定义了步骤后端执行逻辑,主要逻辑说明如下:
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) } }
2.4. 发布步骤
按需修改上述步骤实现代码后,切换到 step.yaml 文件所在目录,执行以下命令发布步骤到企业:
flow-cli step publish
2.5. 流水线使用步骤
步骤发布成功后,进入流水线编辑页面,可以在任务编辑页面,指定容器环境 -> 添加步骤 -> 企业步骤,添加 RedlineSonar 这个步骤。
编辑后保存并运行流水线,查看步骤运行结果和日志:
以上即完成了一个企业自定义步骤的开发,完成了 Sonar 服务的对接。
点击此处查看更多使用说明和场景示例参考。
相关链接:
[1] 私网环境下如何使用云效流水线进行CI/CD?
[2] step.yaml
https://atomgit.com/flow-step-custom/RedlineSonar/blob/master/step.yaml
[3] src/index.ts
https://atomgit.com/flow-step-custom/RedlineSonar/blob/master/src/index.ts