2、DevOps基础:CI/CD流水线概念、版本控制(Git),自动化构建与部署
好,咱们进入正题。这一章聊的是DevOps最核心的骨架——CI/CD流水线。说白了,就是让代码从你本地跑到生产环境的那条路。我见过太多团队,代码写得很漂亮,但上线全靠手搓,结果每次发布都像在拆弹。嗯,咱们今天就把这条路铺平。
2.1 CI/CD流水线:从代码到交付的自动化高速公路
先说说CI/CD到底是什么。CI,持续集成,意思是开发人员频繁地把代码合并到主干,每次合并都自动跑构建和测试。CD,持续交付/持续部署,意思是每次通过测试的代码,都能自动部署到目标环境。
我个人习惯把流水线想象成一条传送带。你放上去一个代码提交,传送带自动帮你编译、测试、打包、部署。中间任何一环出问题,传送带就停下来报警。我在项目中遇到过最典型的场景:一个团队每天手动部署,上线前发现少了个配置文件,结果回滚花了两个小时。后来上了流水线,这种低级错误再也没出现过。
核心要点:CI/CD不是工具,是流程。工具只是帮你把流程自动化。
2.2 版本控制(Git):一切自动化的基石
没有版本控制,CI/CD就是空中楼阁。Git是目前的事实标准,没有之一。你想想看,如果代码都靠U盘拷贝,那还谈什么自动化?
2.4.1 Git工作流:选对姿势很重要
我见过最混乱的Git用法,就是所有人都在master上直接提交。那场面,简直像菜市场。我个人推荐两种主流工作流:
- GitFlow:适合有固定发布周期的项目。有master、develop、feature、release、hotfix分支,结构清晰但稍显复杂。
- Trunk-Based Development:适合追求快速迭代的团队。所有人在主干上开发,通过特性开关控制功能发布。我在做硬件在环测试时,经常用这种方式,因为测试环境需要快速同步最新代码。
我的建议:如果你的团队小于10人,用Trunk-Based Development就够了。分支太多反而增加管理成本。
2.4.2 提交规范:让流水线读懂你的意图
为什么提交规范重要?因为CI/CD流水线需要根据提交信息决定触发什么操作。比如,提交信息里带[skip ci],流水线就不跑。我曾经见过一个团队,提交信息全是"fix bug"、"update",结果想回滚都找不到对应版本。
推荐使用Conventional Commits规范:
feat: 添加硬件在环测试接口
fix: 修复GPIO读取超时问题
docs: 更新API文档
chore: 升级依赖库版本
这样流水线就能根据前缀自动判断:feat触发完整测试,docs只触发文档构建,效率高很多。
2.3 自动化构建:把代码变成可运行的产物
构建,就是把源代码变成可执行文件、镜像或者部署包。在硬件在环测试场景里,构建尤其重要,因为你可能需要交叉编译——在x86机器上编译出ARM架构的程序。
2.3.1 构建工具选型
| 语言/场景 | 推荐工具 | 我的经验 |
|---|---|---|
| Java | Maven / Gradle | Maven稳定,Gradle灵活 |
| Python | Poetry / Pipenv | Poetry的依赖解析更靠谱 |
| C/C++(嵌入式) | CMake + Make | 交叉编译必须用CMake |
| 容器化 | Docker | 硬件在环测试强烈推荐 |
避坑指南:我曾经在构建脚本里写死了绝对路径,结果换到CI服务器上全崩了。记住,所有路径都要用相对路径或者环境变量。
2.3.2 构建脚本示例
一个典型的Docker构建脚本,用于硬件在环测试环境:
# Dockerfile
FROM ubuntu:22.04 AS builder
WORKDIR /app
COPY . .
RUN apt-get update && apt-get install -y gcc-arm-none-eabi cmake
RUN cmake -B build -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
RUN cmake --build build
FROM ubuntu:22.04 AS runtime
COPY --from=builder /app/build/firmware.bin /firmware/
CMD ["/firmware/firmware.bin"]
这个例子展示了多阶段构建。第一阶段编译,第二阶段只放产物。这样最终镜像小很多,部署也快。
2.4 自动化部署:把产物送到该去的地方
部署,就是把构建好的产物放到目标环境里运行。对于硬件在环测试,目标环境可能是真实的硬件设备,也可能是仿真器。
2.4.1 部署策略
- 蓝绿部署:同时维护两套环境,切换流量。适合不能中断的服务。
- 滚动更新:逐个替换实例。适合集群部署。
- 金丝雀发布:先让一小部分用户用新版本,没问题再全量。我在项目中用这个策略测试固件更新,先刷一台设备,观察半小时再刷全部。
2.4.2 部署到硬件设备
硬件在环测试的部署和普通软件不一样。你不能直接SSH上去装包,通常需要通过特定接口刷写固件。举个例子:
# 部署脚本示例
#!/bin/bash
# 通过JTAG接口刷写固件到STM32设备
openocd -f interface/stlink.cfg \
-f target/stm32f4x.cfg \
-c "program build/firmware.hex verify reset exit"
嗯,这里要注意,刷写固件前一定要确认设备连接正常。我曾经因为USB线接触不良,刷写到一半断连,设备直接变砖。后来我加了前置检查:
# 检查设备是否在线
if ! openocd -f interface/stlink.cfg -c "init; exit" 2>/dev/null; then
echo "设备未连接,请检查JTAG线缆"
exit 1
fi
关键原则:自动化部署要幂等。也就是说,不管跑多少次,结果都一样。如果部署到一半失败了,重跑一次应该能恢复。
2.5 完整的CI/CD流水线示例
最后,咱们看一个完整的流水线配置。以GitLab CI为例:
stages:
- build
- test
- deploy
build-job:
stage: build
script:
- cmake -B build -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
- cmake --build build
artifacts:
paths:
- build/firmware.bin
test-job:
stage: test
script:
- python3 run_hil_tests.py --firmware build/firmware.bin
dependencies:
- build-job
deploy-job:
stage: deploy
script:
- ./flash_device.sh build/firmware.bin
dependencies:
- build-job
only:
- master
这个流水线做了三件事:构建固件、在硬件在环平台上跑测试、通过测试后部署到设备。注意,只有master分支的提交才会触发部署,这是为了防止把开发中的代码刷到生产设备上。
好了,这一章的内容就这些。记住,CI/CD流水线不是一蹴而就的,需要根据团队和项目的实际情况不断调整。下一章咱们聊聊硬件在环测试平台的具体搭建,到时候会用到今天讲的这些自动化知识。