研发协作
设计、加固或排查 CI/CD 流水线时:用多阶段安全门禁…
在需要用 GitHub Actions/GitLab CI/Jenkins 搭建或优化 CI/CD 流水线、加入安全门禁、加速构建或实现安全部署时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
设计、加固或排查 CI/CD 流水线时:特定
解决思路
- 动手前先做规划:列出必须的安全扫描(SAST/SCA/容器),规划 job 依赖与可并行项,标记缓存点,检索组织内已有可复用 workflow,确认凭证策略优先用 OIDC 而非静态密钥。
- 先写流水线测试再实现:新建 .github/workflows/test-pipeline.yml,用 actionlint 校验 workflow 语法,用 grep 断言 ci-cd.yml 中存在 outputs:、deploy 的 needs 包含 security、存在顶层 permissions: 块;每次改动流水线后重跑这些测试。
- 先写最小可跑通的流水线让这些测试通过,再逐步加入缓存、矩阵、签名等能力,每加一项都重跑测试确认合规。
- 本地与远程验证:跑 actionlint;用 act -n 干跑;用 gh workflow run test-pipeline.yml 运行测试流水线;用 gh api repos/{owner}/{repo}/actions/permissions 核对权限。
- 依赖缓存:用 actions/cache 缓存 ~/.npm,key 用 ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} 并配置 restore-keys,安装依赖用 npm ci 而不是 npm install。
- 构建产物缓存实现增量构建:用 actions/cache 缓存 dist、.next/cache、node_modules/.cache,key 用 ${{ runner.os }}-build-${{ hashFiles('src/**') }}。
- Docker 层缓存:docker/build-push-action 配置 cache-from: type=gha 与 cache-to: type=gha,mode=max。
- 并行化 job:lint、test、security 之间不设 needs 让它们并行,只有 build 用 needs: [lint, test, security] 等待全部完成。
- 产物只上传构建输出:upload-artifact 用 path: dist/、retention-days: 7、compression-level: 9,不要上传整个仓库或 node_modules。
- 条件触发:用 dorny/paths-filter 检测 frontend/backend/shared-lib 等变更,后续 job 用 if: needs.detect-changes.outputs.<x> == 'true' 才执行;触发器也可用 on.push.paths 按目录过滤。
- 每个 workflow 显式声明最小 permissions(如 contents: read、security-events: write、id-token: write),绝不依赖默认的 write 权限。
- 第三方 action 固定到 commit SHA(如 actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11),禁止使用 @main 或 @latest。
- 用 OIDC/Workload Identity 替代静态凭证:aws-actions/configure-aws-credentials 配 role-to-assume 与 aws-region,并给 workflow 加 id-token: write;登录镜像仓库用 GITHUB_TOKEN。
- 密钥使用安全:需要输出时先用 echo "::add-mask::${{ secrets.X }}" 掩码,绝不直接 echo 密钥值。
- 密钥作用域隔离:production 使用 environment: production 的环境级 secret;部署 job 加 if: github.event_name == 'push',避免 fork PR 拿到密钥。
- 安全门禁:每个 PR 跑 SAST(semgrep-action 配 config: p/security-audit、CodeQL、SonarQube)、SCA(dependency-review-action 配 fail-on-severity: high、Snyk、Dependabot),并让 deploy job 的 needs 依赖这些安全 job,使其失败即阻塞部署。
- 镜像扫描:构建后用 aquasecurity/trivy-action 以 format: 'sarif'、severity: 'CRITICAL,HIGH' 扫描 image-ref,再用 codeql-action/upload-sarif 上报 GitHub Security。
- 在 pre-commit hook 中集成 Gitleaks/TruffleHog 做 secrets 扫描,发现即让流程失败。
- 产物签名:用 sigstore/cosign-installer 安装后执行 cosign sign --yes <image>@<digest>,签名 job 需 permissions: packages: write 与 id-token: write。
- 生成 provenance 与 SBOM:build-push-action 设置 provenance: true、sbom: true,部署前验证签名与来源。
- 按阶段顺序组织流水线:code-quality → dependency-check → build → container → sign → deploy-staging → deploy-production,阶段间用 needs 建立依赖。
- 抽可复用 workflow:新建 .github/workflows/reusable-service-build.yml,用 on.workflow_call 定义 inputs(service-name、node-version、run-e2e-tests)与 secrets,各服务用 uses: ./.github/workflows/reusable-service-build.yml 调用,避免重复配置。
- 矩阵测试:用 matrix 组合 os 与 node-version,用 exclude 排除不需要的组合,设 fail-fast: false 让其他组合继续跑,codecov 上传时用 flags 区分矩阵。
- 跨阶段产物流转:build 阶段 upload-artifact 上传 dist,container 阶段用 download-artifact 取回 dist 再构建镜像,避免重复构建。
- 部署到环境:用 kubectl set image 更新镜像,再用 kubectl rollout status deployment/myapp --namespace=staging --timeout=5m 等待完成,随后跑 smoke test(npm run test:smoke -- --env=staging)。
- 生产用 ArgoCD 部署:argocd app set myapp --parameter image.tag=<sha>、argocd app sync myapp --prune、argocd app wait myapp --health --timeout 600。
- 生产部署用 workflow_dispatch 手动触发 + environment 审批:先校验输入版本格式(^v[0-9]+\.[0-9]+\.[0-9]+$),部署后执行 rollout status、用 curl -f https://<env>.example.com/health 做健康检查,并发送 Slack 通知。
- 选择并实现部署策略:蓝绿(零停机)、金丝雀(渐进切流量)、滚动更新+健康检查、GitOps(ArgoCD/Flux),并实现失败自动回滚。
- 环境隔离:按环境使用不同配置,如 kubectl apply -f k8s/overlays/${{ inputs.environment }},不要把 DATABASE_URL 等值硬编码在 workflow 中,改用 secrets。
- 给 job 设置 timeout-minutes(如 30,大项目 120),避免默认 360 分钟无限等待。
- 健康检查用重试循环:curl -f https://api.example.com/health 成功即退出,失败 sleep 10 重试最多 30 次,全部失败则 exit 1。
- 错误显式处理:需要容忍失败的步骤加 id 与 continue-on-error: true,再用 if: steps.tests.outcome == 'failure' 明确处理(如 gh issue create 建 issue 或发告警),不要静默忽略。
- 自托管 runner:runs-on: [self-hosted, linux, x64, high-memory],开始时用 docker system prune -af 与 rm -rf node_modules dist 清理工作区,构建时用 docker build --cache-from ghcr.io/${{ github.repository }}:buildcache --build-arg BUILDKIT_INLINE_CACHE=1,在容器内跑测试,最后用 if: always() 清理镜像。
- 配置分支保护规则与 required status checks、必需 review,限制可合并的人与条件。
- 建立可观测性:各阶段结构化日志、跟踪构建时长/成功率/MTTR/部署频率、失败告警、构建性能 dashboard、审计记录并对接 SIEM 与事件管理。
- 按 OWASP CI/CD Top 10 逐条落地:流控(分支保护+必需 review+状态检查)、身份(OIDC+最小权限+短时 token)、依赖链(SCA+版本固定+SBOM)、防投毒(build 与 deploy 分离、校验输入)、PBAC(环境保护+人工审批)、凭证卫生(secrets 扫描+轮换+Vault)、加固 runner 与网络隔离、policy as code 合规门禁、产物完整性(签名+校验 provenance)、日志审计接入 SIEM。
- 提交前做完整检查:跑 actionlint、用 act 本地干跑、确认密钥已掩码、确认分支保护与必需状态检查、复核权限最小、先在 staging 验证、更新 runbook 与 README 文档、配置失败告警。
适用边界 · 注意事项
- 示例与做法深度绑定 GitHub Actions(GitLab CI、Jenkins 只作为能力范围提及),在非 GitHub Actions 平台上需逐项替换为对应实现。
- 无法修改 .github/workflows、无法配置分支保护/环境保护规则,或无法在云侧建立 OIDC 信任时,OIDC 与安全门禁方案落不了地。
- 只有单个小仓库、没有 Kubernetes/常驻部署环境时,引入 ArgoCD、Cosign 签名、SBOM、自托管 runner 等整套多阶段流水线属于过度工程。