动态临时分支构建的关键在于销毁时机与范围控制:需在ci任务结束前删除远程分支、k8s命名空间或kind集群等全部关联资源,并通过校验确保清理彻底,避免残留占用配额或阻塞后续构建。

动态临时分支构建本身不难,难的是销毁时机和范围控制——只删分支不清理环境,等于没做。
git push 后自动创建临时分支但不保留
Git 本身不支持“临时分支”概念,所谓动态临时分支,本质是 CI 工具在收到 git push 时,用提交 SHA 或 MR ID 构造一个一次性分支名(如 ci-run-abc123),然后基于该分支触发构建。关键在于:这个分支不能被长期保留在远程仓库里。
- GitLab CI 中可通过
variables: CI_COMMIT_TAG或CI_MERGE_REQUEST_IID拼接分支名,配合only: [pushes]+except: [branches]控制触发范围 - GitHub Actions 不建议直接 push 新分支来触发,更稳妥的做法是用
repository_dispatch或workflow_dispatch手动传参,避免污染 refs - 必须在 job 结束前执行
git push origin --delete ci-run-$SHA,且该操作需配置具有write权限的 token,否则权限拒绝
Jenkins Pipeline 中基于分支名动态生成并销毁 K8s 测试环境
当 Jenkins 收到 ci-run- 开头的分支推送,应立即启动 Pod 模板,并在最后一步强制销毁整个命名空间或 label selector 范围内的资源。
- 使用 Kubernetes 插件时,在
podTemplate中通过namespace字段隔离环境,例如设为ci-${env.BRANCH_NAME} - 构建完成后必须执行
kubectl delete namespace ci-${env.BRANCH_NAME},而非仅删 Pod;否则 Service、ConfigMap、PV 等残留资源仍会占用配额 - 若用 Helm 部署测试服务,销毁阶段应调用
helm uninstall --purge ci-${env.BRANCH_NAME}(v2)或helm uninstall ci-${env.BRANCH_NAME} -n ci-${env.BRANCH_NAME}(v3) - 注意:K8s namespace 删除是异步操作,Jenkins job 需加
sh 'until kubectl get ns ci-${env.BRANCH_NAME} > /dev/null 2>&1; do sleep 2; done'等待真正消失,否则下次同名构建可能失败
GitLab CI 中用 cleanup stage 清理容器与集群资源
临时分支构建常伴随临时容器或 kind 集群,这些资源若未在 pipeline 结束时清除,几小时内就会填满磁盘或耗尽 IP。
- 务必定义
cleanupstage 并设置when: always,确保无论test阶段成功或失败都执行 - 对于 Docker 环境,推荐组合命令:
docker system prune -f --filter "until=10m",比单纯docker container prune更彻底 - 对于 kind 集群,销毁命令必须带
--name参数:kind delete cluster --name ci-${CI_COMMIT_SHORT_SHA};不指定 name 会误删默认集群 - 若使用自定义 bridge 网络,需额外执行
docker network prune -f --filter "label=ci-temp",否则网络对象持续存在并阻塞端口复用
最容易被忽略的一点:销毁动作本身可能失败(比如 namespace 正在被 finalizer 卡住、kind 进程僵死),但 CI 日志里往往只显示 “cleanup completed”,实际什么都没删掉。建议在销毁后加一行校验,比如 kubectl get pods -n ci-${env.BRANCH_NAME} | wc -l 输出为 0,否则报错退出。











