2. 医疗软件开发生命周期与CI/CD映射
医疗软件与普通商业软件最大的区别在于:它的开发过程本身就是受监管对象。IEC 62304 规定软件生命周期过程,ISO 13485 规定质量管理体系,ISO 14971 规定风险管理过程。三者不是三套独立流程,而是同一开发活动的三个观察面——62304 管"软件怎么做",13485 管"组织怎么保证做对",14971 管"风险怎么被识别和控制"。CI/CD 流水线要落地到医疗软件,必须先把这三条约束映射到流水线的每个阶段。
三个标准各自约束什么
IEC 62304 把软件生命周期划分为开发过程(需求分析、架构设计、详细设计、单元实现、集成、系统测试、发布)和维护过程,并按软件安全分级 A/B/C 决定各过程的严格程度。C 级软件(可能导致死亡或严重伤害)要求每个软件单元都有详细设计、单元验证和可追溯性。ISO 13485 从质量体系角度要求:设计输入、设计输出、设计评审、设计验证、设计确认、设计转换、设计变更控制,以及贯穿全程的文件与记录控制。ISO 14971 则要求建立风险管理计划,识别危害、估计风险、评价风险、控制风险,并验证控制措施的有效性,且风险活动必须与开发活动同步进行,而不是发布前补做。
把三者叠加,可以得到一条对 CI/CD 最关键的结论:医疗软件的每一次构建、每一次合并、每一次发布,都必须能回答"它对应哪条需求、覆盖了哪些风险控制、留下了什么记录"。这正是流水线设计的核心约束。
把流水线阶段映射到生命周期
映射的关键不是给每个阶段起个 CI/CD 名字,而是确定每个阶段"必须产出什么证据、由谁自动校验、不通过时怎么办"。
需求与风险分析阶段对应流水线的起点。软件需求规格中的每一条需求都应带有唯一标识(如 SRS-001),并关联到 ISO 14971 风险分析中对应的危害与控制措施。在工程实践中,这通常体现为需求管理工具(如 DOORS、Jama 或 Git 仓库中的需求文件)与代码仓库的关联。流水线在合并请求(MR)阶段即可校验:新增代码是否关联了需求 ID,是否触发了风险评审。若某次提交修改了与高风险控制相关的模块,流水线应自动要求风险负责人审批。
架构与详细设计阶段对应代码仓库中的设计文档与模块划分。IEC 62304 要求 C 级软件的每个软件单元都有详细设计描述。在 CI 中,可以通过架构守护工具(如 ArchUnit、dependency-cruiser)自动检查模块依赖是否符合设计约束,防止架构漂移。安全分级 A/B/C 应记录在软件项清单中,并作为后续测试严格程度的依据。
实现与单元验证阶段是 CI 最核心的部分。每次提交触发构建、静态分析和单元测试。对于 C 级软件,IEC 62304 要求单元验证覆盖所有软件单元,且通常要求分支覆盖率接近 100%。流水线应设置覆盖率门禁:低于阈值直接失败。静态分析工具(如 Coverity、PC-lint、SonarQube)的告警应分级处理,与安全相关的告警必须清零。所有测试结果、覆盖率报告、静态分析报告都应自动归档,形成 ISO 13485 要求的质量记录。
集成与系统测试阶段对应持续交付环节。集成测试验证软件项之间的接口,系统测试验证软件需求是否被满足。这里最关键的是需求追溯矩阵的自动校验:流水线应能生成"需求→测试用例→测试结果"的映射报告,确认每条需求都有对应测试且通过。同时,ISO 14971 要求的风险控制验证也应在此阶段执行——针对每个风险控制措施,确认其对应的测试用例已执行且结果符合预期。
发布与维护阶段对应制品管理与变更控制。发布制品必须带版本号、构建哈希、SBOM(软件物料清单)和数字签名,确保可追溯、不可篡改。ISO 13485 要求设计变更受控,因此任何代码变更都应通过 MR 流程,保留评审记录。缺陷修复同样要走变更控制,并评估是否影响风险分析结论。
质量门禁:让标准变成可执行的检查
标准条文本身不会自动执行,必须转化为流水线中的质量门禁。以下是一组可直接参考的门禁配置示例(参数为示例值,需根据产品安全分级调整):
# 质量门禁示例(C级软件)
stages:
- build
- static_analysis
- unit_test
- integration_test
- system_test
- release
build:
script:
- cmake --build . --config Release
artifacts:
paths: [build/]
static_analysis:
script:
- sonar-scanner -Dsonar.qualitygate.wait=true
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
unit_test:
script:
- ctest --output-on-failure
- gcovr --branches --fail-under-branch 100
coverage: '/TOTAL.*\s+(\d+%)$/'
traceability_check:
script:
- python tools/check_traceability.py \
--requirements docs/SRS.csv \
--tests test/results.xml \
--risk docs/risk_control.csv
allow_failure: false
release:
script:
- sha256sum build/app > build/app.sha256
- cosign sign --key $SIGNING_KEY build/app
rules:
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
其中 traceability_check 是医疗软件特有的门禁:它读取需求清单、测试结果和风险控制清单,校验三者是否完整对应。若某条需求没有测试覆盖,或某个风险控制措施没有验证记录,流水线直接失败。这把 ISO 13485 的追溯要求和 ISO 14971 的风险控制验证变成了自动化检查。
常见误区:把 CI/CD 当作"加速发布"的工具,却忽略了医疗软件中"每次变更都要留下合规证据"的要求。如果流水线只跑测试、不归档记录、不做追溯校验,那么它产出的制品无法通过审核。医疗软件的 CI/CD 首先是一套证据生成与校验系统,其次才是效率工具。
风险活动与开发活动的同步
ISO 14971 强调风险管理不是一次性活动,而是贯穿生命周期的迭代过程。映射到 CI/CD,意味着风险分析文件应随代码一起版本控制,风险控制措施的验证应作为流水线的一部分。当代码变更影响到已识别的风险控制时,流水线应触发风险再评价流程。例如,某次提交修改了报警阈值判断逻辑,而该逻辑对应风险控制措施 RC-012(防止漏报),则流水线应要求更新风险文件并重新验证。
这种同步机制可以通过在代码中嵌入风险控制标识(如注释 @risk-control RC-012)并在 CI 中扫描实现。当包含该标识的文件被修改时,流水线自动标记需要风险评审。这样,ISO 14971 的要求就从纸面流程变成了可执行的工程约束。
总结来看,IEC 62304 提供了生命周期阶段的骨架,ISO 13485 提供了记录与变更控制的规则,ISO 14971 提供了风险驱动的判断依据。CI/CD 流水线的任务,是把这三者转化为每个阶段的自动检查、自动归档和自动阻断。映射做对了,流水线本身就是合规证据的生产线;映射做错了,再快的流水线也无法让医疗软件通过审核。