iampopye/devops-workflows

GitHub: iampopye/devops-workflows

一套生产级的可复用 GitHub Actions 工作流,用于快速搭建安全、规范的 DevOps CI/CD 流水线。

Stars: 0 | Forks: 0

# devops-workflows [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/iampopye/devops-workflows/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![欢迎 PR](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) 大多数 CI/CD 教程向你展示的只是玩具般的 pipeline。而大多数真实的 pipeline 都是从同事那里抄来的,同事又是从 Stack Overflow 抄来的。这个仓库介于两者之间:提供完整、可用的工作流,你今天就可以在自己的仓库中调用它们,并且附有注释解释做出每个决定的*原因*——而不仅仅是说明 YAML 是做什么的。 这里的每一个工作流都是一个 **reusable workflow**。你不需要 fork 这个仓库,也不需要把 150 行代码粘贴到你的项目中。你只需写六行代码说“运行那个工作流”,就能获得整个 pipeline。 ## 快速开始 在**你的**仓库中创建 `.github/workflows/ci.yml` 并粘贴以下内容: ``` name: CI on: pull_request: push: branches: [main] permissions: {} jobs: security: uses: iampopye/devops-workflows/.github/workflows/security/reusable-security-scanning.yml@v1 permissions: contents: read security-events: write actions: read with: language: go # or python, javascript-typescript, java-kotlin, ... ``` 推送它。在下一次 pull request 时,你将获得静态分析 (CodeQL)、依赖项和文件系统漏洞扫描 (Trivy),以及跨整个 git 历史的机密扫描 (Gitleaks)——结果会显示在你仓库的 **Security** 标签页中。 这就是全部的设置。你可以根据需要从[目录](#workflow-catalog)中添加更多任务。 ## 工作流目录 | 工作流 | 功能说明 | 参考 | |---|---|---| | **安全扫描** | CodeQL SAST、Trivy 文件系统扫描、Gitleaks 机密检测、可选的 OWASP ZAP DAST | [详情](#security-scanning) · [源码](.github/workflows/security/reusable-security-scanning.yml) | | **Terraform 基础设施** | `fmt` → `init` → `validate` → `plan`,可选的门控 `apply`,完整的 plan 作为 PR 评论发布 | [详情](#terraform-infrastructure) · [源码](.github/workflows/terraform/reusable-terraform-infra.yml) | | **Docker 构建并推送** | Buildx、多架构构建、语义化标签、SBOM + 来源证明、Trivy 镜像扫描 | [详情](#docker-build-and-push) · [源码](.github/workflows/docker/reusable-docker-build.yml) | | **Kubernetes 部署** | 服务端 dry-run 验证、apply、等待 rollout、凭据清理 | [详情](#kubernetes-deploy) · [源码](.github/workflows/kubernetes/reusable-kubernetes-deploy.yml) | | **合规性验证** | Trivy IaC 配置错误扫描 + OPA 策略即代码测试、证据摘要 | [详情](#compliance-validation) · [源码](.github/workflows/observability/reusable-compliance-validation.yml) | | **AI PR 审查** *(可选)* | 在 pull request 上发布建议性的 AI 生成审查评论 | [详情](#ai-pr-review-optional) · [源码](.github/workflows/ai/reusable-ai-pr-review.yml) | | **AI 故障分析** *(可选)* | 总结近期失败的工作流运行,并创建一个包含分析结果的 issue | [详情](#ai-incident-analysis-optional) · [源码](.github/workflows/ai/reusable-ai-incident-analysis.yml) | 可复制即用的调用工作流位于 [`examples/`](examples/) 目录中。 ## 为什么这些工作流与众不同 互联网上有成千上万的 GitHub Actions 代码片段。以下是这个合集所做的,而大多数其他合集没有做到的地方。 ### 1. 每个第三方 action 都被锁定到了 commit SHA 查看本仓库中的任何一个 action 引用,你都会看到类似这样的内容: ``` uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 ``` 而不是更常见的 `uses: aquasecurity/trivy-action@v0.36.0`。 **简而言之,为什么这很重要:** 像 `v1` 这样的 Git tag 只是一个指向某个 commit 的标签,拥有该 action 仓库的人可以随时移动这个标签。如果他们将 `v1` 移动到指向恶意代码——或者有人窃取了他们的账户并替他们这样做——那么你的 pipeline 下次运行时,该新代码将**在你的 job 中执行,并拥有访问你的 secrets 的权限**。你的 registry 密码。你的云凭据。你的 `GITHUB_TOKEN`。你从未批准该更改,且你仓库中的任何内容都没有改变。 40 个字符的 commit SHA 是无法移动的。它永远只标识一个 commit。锁定到 SHA 意味着今天运行的代码就是你审查过的代码,直到你主动更新它。 这就是人们所说的 **supply chain security**(供应链安全):你不仅要信任自己的代码,还要信任你的构建引入的所有内容。末尾的 `# v0.36.0` 注释保持了人类可读性,并且 [Dependabot](.github/dependabot.yml) 每周会一起更新 SHA 和注释——因此 **SHA 锁定并不意味着会过时**。 `actions/*` 和 `github/*` 下的 Actions 是 GitHub 第一方的,并使用主版本号标签,这是 [GitHub 自己的官方文档指南](https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions)。 ### 2. 默认最小权限 每个工作流都以以下内容开始: ``` permissions: {} ``` 这意味着“此工作流的 token 什么都做不了”,然后每个 job 只重新获得它实际需要的权限。与此相比,常见的替代方案是——根本没有 `permissions:` 块——在这种情况下,job 会静默继承仓库的默认权限,通常是对所有内容的读取*和写入*权限。如果改用工作流级别的授权,文件中的每个 job 都将获得所有权限的并集,包括那些只需要 `contents: read` 的 job。 关键不在于偏执。关键在于,当出现问题时,损害范围会受到你所授予的权限的限制。 ### 3. 仓库会 lint 其自身的工作流 一系列从不进行自身验证的“最佳实践”工作流,只不过是一堆未经验证的 YAML。这里的每个 pull request 都会运行 [`ci.yml`](.github/workflows/ci.yml),它会: - 对所有工作流和示例运行 **actionlint**(加上对每个 `run:` 块的 shellcheck),并且 - 运行一个 **自定义锁定检查器**,如果任何第三方 action 没有被 SHA 锁定,则会导致构建失败。 此 README 中的规则是由机器执行的,而不是靠良好的意愿。 ### 4. AI 工作流是可选的且与供应商无关 有两个工作流使用了语言模型。**此仓库中的其他任何内容都不依赖于它们**——删除 `ai/` 文件夹,其他一切仍能正常工作。 它们也不局限于某个供应商。`model` 输入是**必需的且没有默认值**,因此使用此仓库并不意味着隐含了任何提供商。内置预设涵盖了 `anthropic`、`openai`、`groq`、`openrouter`、`together`、`mistral` 和 `deepseek`;`openai_compatible` 加上 `api_url` 涵盖了任何兼容 OpenAI 的接口,包括完全通过 Ollama、vLLM、llama.cpp、LM Studio 或 Azure OpenAI 运行在你自己硬件上的模型。 这两个工作流都是明确作为建议性的。它们都不阻塞合并,也都不能取代人工审查员。 ### 5. 发现并修复了真实的 bug 这些工作流是从早期的草稿重写而来的。有三个真正被破坏并值得理解的地方,因为同样的错误无处不在: - **Terraform PR 评论过去只能说“成功”。** `plan` 步骤没有配置 `continue-on-error`,因此失败的 plan 会在评论步骤运行之前中止 job。人们曾经看到的唯一评论都是绿色的。修复方法是让 plan 步骤完成,捕获其真实的退出码,报告结果,并在随后的单独步骤中再判定失败。 - **一个 Trivy 扫描结果曾经会导致完全跳过机密扫描。** Trivy 以非零的 `exit-code` 运行,因此单个依赖项 CVE 就会导致该步骤失败——并且它之后的每个步骤都会失败,包括 SARIF 上传和 Gitleaks。一个常规的过期库可能会悄无声息地隐藏泄漏的凭据。修复方法是以 `exit-code: 0` 进行扫描,并将通过/失败的决定放在最后专门的门控步骤中。 - **AI PR 审查的步骤输出过去可能会被 PR 内容伪造。** Diff 使用 `EOF` heredoc 分隔符写入 `$GITHUB_OUTPUT`。任何包含字面量为 `EOF` 这一行的 pull request 都会提前结束该块,其后的所有内容都会被解析为新的步骤输出——攻击者控制的数据变成了 workflow 变量。(步骤输出还有 1 MB 的上限。)修复方法是将 diff 写入一个普通文件。 ## 新手 DevOps 工程师的学习路径 如果你刚接触 CI/CD 并想真正理解它而不是仅仅复制粘贴,请按此顺序进行。每一个都建立在前一个的基础之上。 **1. 从安全扫描开始。** 它不需要云账户、不需要 registry、也不需要 cluster——只需要你的源代码。将其添加到你已有的仓库中,看着 Security 标签页被填满。从头到尾阅读 [`reusable-security-scanning.yml`](.github/workflows/security/reusable-security-scanning.yml);这是了解 jobs、permissions 和 SARIF 上传如何结合在一起的最佳入门。这就是 **DevSecOps** 中的 "Sec":在每次更改时自动运行的安全检查,而不是一年一次在审计中运行。 **2. 然后是 Docker。** 使用你自己的 Dockerfile 构建镜像,设置 `push: false` 且不需要任何 secrets。一旦成功,开启 `push: true` 推送到 GitHub Container Registry。在此过程中,你将接触到镜像标签策略、多架构构建以及 SBOM/provenance 证明——即说明镜像内部有什么以及它是如何构建的元数据。 **3. 然后是 Terraform。** 设置 `apply: false`,针对真实(较小)的基础设施运行它,并在你的 pull request 上阅读 plan 评论。`plan` 是只读且安全的。只有在你对阅读 plan 感到舒适之后,才应该设置 `apply: true`,并且只能在具有保护规则的 GitHub environment 背后进行。 **4. 然后是 Kubernetes。** 从 `dry_run: true` 开始,它可以在不更改任何内容的情况下针对真实的 API server 验证你的 manifests。当它持续通过时,在非生产 namespace 上设置 `dry_run: false`。注意 rollout 等待——这是“API server 接受了我的 YAML”和“我的应用程序实际正在运行”之间的区别。 **5. 最后,进行合规性验证和可选的 AI 工作流。** 到目前为止,你将了解 IaC 配置错误扫描在抱怨什么,以及为什么值得编写 OPA 策略。 在进行这些操作时,请阅读工作流文件中的注释。它们解释了其背后的理由,而这是能够应用到你的下一份工作中的部分。 ## 工作流参考 以下所有示例均引用 `@v1`。将你的调用方锁定到发布标签而不是 `@main`,意味着此处的上游更改在你主动选择之前无法更改你的 pipeline。 ### 安全扫描 `.github/workflows/security/reusable-security-scanning.yml` 三个 job:**CodeQL SAST**、**Trivy 文件系统扫描 + Gitleaks 机密扫描**,以及一个可选的 **OWASP ZAP 基准 DAST** 扫描(仅当你提供目标 URL 时运行)。 **输入** | 名称 | 类型 | 默认值 | 描述 | |---|---|---|---| | `language` | string | `go` | CodeQL 的主要语言。可选值之一:`go`, `javascript-typescript`, `python`, `java-kotlin`, `ruby`, `csharp`, `c-cpp`, `swift`, `rust`, `actions`。 | | `run_codeql` | boolean | `true` | 运行 CodeQL SAST job。对于 CodeQL 不支持的语言,请设置为 `false`。 | | `trivy_severity` | string | `CRITICAL,HIGH` | 要报告的以逗号分隔的严重级别。 | | `fail_on_findings` | boolean | `true` | 当 Trivy 发现达到或超过 `trivy_severity` 的问题时,判定 job 失败。 | | `zap_target_url` | string | `""` | 用于基准 DAST 扫描的目标 URL。留空则完全跳过 DAST job。 | **Secrets** | 名称 | 必需 | 描述 | |---|---|---| | `github_token` | 否 | 传递给 Gitleaks 的 token。如果省略,则回退到 job 内置的 `github.token`。 | **调用者必须授予的权限** `contents: read`, `security-events: write`, `actions: read` —— 另外,如果你使用 ZAP DAST job,还需要 `issues: write`。 **用法** ``` jobs: security: uses: iampopye/devops-workflows/.github/workflows/security/reusable-security-scanning.yml@v1 permissions: contents: read security-events: write actions: read issues: write # only needed for the ZAP job with: language: python trivy_severity: CRITICAL,HIGH fail_on_findings: true zap_target_url: https://staging.example.com ``` 注意: - checkout 使用 `fetch-depth: 0`,因为 Gitleaks 会扫描 commit *历史记录*。提交后又被删除的 secret 仍然存在于你的历史记录中,并且已经泄漏。 - Trivy 故意使用 `exit-code: 0` 进行扫描,因此扫描结果不会导致跳过 SARIF 上传或 secret 扫描。通过/失败的决定在最后专门的门控步骤中做出。 - ZAP 基准模式是被动的——它会抓取目标并报告其看到的内容,而不会攻击。**只能将其指向你被授权测试的系统。** ### Terraform 基础设施 `.github/workflows/terraform/reusable-terraform-infra.yml` 运行 `fmt -check` → `init` → `validate` → `plan`,将完整的 plan 作为可折叠的 pull request 评论发布,并可选择性地应用已保存的 plan 文件。 **输入** | 名称 | 类型 | 默认值 | 描述 | |---|---|---|---| | `working_directory` | string | `terraform` | 包含你的 Terraform 文件的目录。 | | `terraform_version` | string | `1.14.3` | 要安装的 Terraform 版本。 | | `apply` | boolean | `false` | 在 plan 成功后执行 apply。 | | `environment` | string | `nonprod` | GitHub environment 名称。使用其保护规则来门控 `apply`。 | **Secrets** | 名称 | 必需 | 描述 | |---|---|---| | `tf_api_token` | 否 | Terraform Cloud / Enterprise API token,将写入 CLI 凭据配置中。 | **调用者必须授予的权限** `contents: read`、`id-token: write`(用于与 AWS/GCP/Azure 进行 OIDC 联合)、`pull-requests: write`(用于发布 plan 评论)。 **用法** ``` jobs: terraform-plan: uses: iampopye/devops-workflows/.github/workflows/terraform/reusable-terraform-infra.yml@v1 permissions: contents: read id-token: write pull-requests: write with: working_directory: infra/prod terraform_version: 1.14.3 environment: production apply: ${{ github.ref == 'refs/heads/main' }} ``` 注意: - `apply` 是针对在同一 job 中较早生成的**已保存 plan 文件**运行 `terraform apply`,而不是新的 plan。你审查过的内容就是将被应用的内容。 - 使用具有必需审查者的 [GitHub environment](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments) 来门控真实的 apply。工作流为你提供了钩子;你来配置规则。 - 优先使用 OIDC 联合,而不是存储为仓库 secrets 的长期云密钥。这就是为什么 `id-token: write` 包含在权限集中的原因。 - Plan 评论被截断为 60,000 个字符(GitHub 将评论正文限制为 65,536 个字符)。保留**尾部**,因为资源摘要和任何错误消息都位于此处。 ### Docker 构建并推送 `.github/workflows/docker/reusable-docker-build.yml` 带有 GitHub Actions 层缓存、语义化标签派生、SBOM 和来源证明以及可选 Trivy 镜像扫描的 Buildx 构建。 **输入** | 名称 | 类型 | 默认值 | 描述 | |---|---|---|---| | `image_name` | string | **必需** | 没有标签的完整镜像名称,例如 `ghcr.io/owner/app`。 | | `context` | string | `.` | 构建 context 路径。 | | `dockerfile` | string | `./Dockerfile` | Dockerfile 的路径。 | | `platforms` | string | `linux/amd64` | 以逗号分隔的目标平台,例如 `linux/amd64,linux/arm64`。 | | `push` | boolean | `false` | 构建成功后推送到 registry。 | | `scan_image` | boolean | `true` | 对构建的镜像运行 Trivy 漏洞扫描。 | | `scan_severity` | string | `CRITICAL,HIGH` | 导致镜像扫描失败的严重级别。 | **Secrets** | 名称 | 必需 | 描述 | |---|---|---| | `registry` | 否 | Registry 主机。默认为 `ghcr.io`。 | | `registry_username` | 否 | 默认为 `github.actor`。 | | `registry_password` | 否 | 默认为 job 的 `github.token`,这对于 GHCR 来说足够了。 | **输出** | 名称 | 描述 | |---|---| | `digest` | 构建镜像的不可变 digest。 | | `tags` | 应用于镜像的以换行符分隔的标签列表。 | **调用者必须授予的权限** `contents: read`、`packages: write`、`id-token: write`(签署来源证明必需)。 **用法** ``` jobs: docker-build: uses: iampopye/devops-workflows/.github/workflows/docker/reusable-docker-build.yml@v1 permissions: contents: read packages: write id-token: write with: image_name: ghcr.io/${{ github.repository }} platforms: linux/amd64,linux/arm64 push: ${{ github.ref == 'refs/heads/main' }} ``` 注意: - 标签是自动派生的:分支名称、PR ref、来自 git 标签的 semver、长 commit SHA,以及 `latest`(**仅在默认分支上**)。将每个功能分支都标记为 `latest` 就是半成品构建最终进入生产环境的原因。 - `sbom: true` 和 `provenance: mode=max` 将供应链元数据附加到镜像:里面有什么,以及它是如何构建的。 - 当 `push: false` 并且针对单个平台时,镜像将被加载到本地 Docker daemon 中,以便扫描程序有内容可读。多平台构建无法在本地加载——如果你想在多架构构建中扫描镜像,请推送它或设置 `scan_image: false`。 ### Kubernetes 部署 `.github/workflows/kubernetes/reusable-kubernetes-deploy.yml` 针对实时的 API server 验证 manifests,选择性地 apply 它们,等待 rollout 真正变为 ready 状态,并始终在最后删除 kubeconfig。 **输入** | 名称 | 类型 | 默认值 | 描述 | |---|---|---|---| | `namespace` | string | `default` | 目标 namespace。 | | `manifests_path` | string | `k8s/` | Manifests 的路径(文件或目录)。 | | `kubectl_version` | string | `v1.34.1` | 要安装的 kubectl 版本。 | | `dry_run` | boolean | `true` | 仅验证。设置为 `false` 以实际 apply。 | | `environment` | string | `""` | GitHub environment 名称。使用其保护规则来门控部署。 | | `rollout_timeout` | string | `5m` | 等待工作负载变为 ready 的时间。 | **Secrets** | 名称 | 必需 | 描述 | |---|---|---| | `kubeconfig` | **是** | Base64 编码的 kubeconfig。使用 `base64 -w0 < ~/.kube/config` 生成。 | **调用者必须授予的权限** `contents: read`。 **用法** ``` jobs: deploy: needs: [docker-build, security] if: github.ref == 'refs/heads/main' uses: iampopye/devops-workflows/.github/workflows/kubernetes/reusable-kubernetes-deploy.yml@v1 permissions: contents: read with: namespace: production manifests_path: k8s/ environment: production dry_run: false rollout_timeout: 10m secrets: kubeconfig: ${{ secrets.KUBECONFIG_B64 }} ``` 注意: - 验证使用 `--dry-run=server`,它将 manifests 发送到真实的 API server 进行准入和 schema 检查。这能捕获客户端检查永远无法捕获的问题。 - 之所以存在 rollout 等待,是因为 `kubectl apply` 返回 `0` 仅表示 API server *接受了*该对象。如果不等待,卡在 `CrashLoopBackOff` 的 pod 仍然会报告绿色的 pipeline。 - Kubeconfig 使用 `umask 077` 写入,因此它绝不会出现短暂的全局可读状态,并在 `if: always()` 步骤中被删除,因此它不会在失败的运行后残留。 - **优先使用 OIDC 联合到你的 cluster,而不是 base64 kubeconfig secret。** Kubeconfig 是长期的,难以轮换,并且通常权限过大。此工作流支持它是因为许多 cluster 仍然需要它——将其视为备用方案,而不是目标。 ### 合规性验证 `.github/workflows/observability/reusable-compliance-validation.yml` Trivy IaC 配置错误扫描,加上 Open Policy Agent 策略即代码测试,并将摘要表写入 job 摘要中。 **输入** | 名称 | 类型 | 默认值 | 描述 | |---|---|---|---| | `policy_path` | string | `policy/` | 包含 OPA Rego 策略的目录。如果目录缺失或不包含 `.rego` 文件,则跳过并给出警告。 | | `trivy_severity` | string | `CRITICAL,HIGH` | 要报告的严重级别。 | | `fail_on_findings` | boolean | `true` | 发现配置错误时判定 job 失败。 | **Secrets**: 无。 **调用者必须授予的权限** `contents: read`、`security-events: write`。 **用法** ``` jobs: compliance: uses: iampopye/devops-workflows/.github/workflows/observability/reusable-compliance-validation.yml@v1 permissions: contents: read security-events: write with: policy_path: policy/ fail_on_findings: true ``` ### AI PR 审查(可选) `.github/workflows/ai/reusable-ai-pr-review.yml` 将 pull request diff 发送给你选择的模型,并将响应作为 PR 评论发布。仅在 `pull_request` 事件上运行。仅供参考——它不会门控合并,并且失败的模型 endpoint 会产生警告,而不是失败的检查。 **输入** | 名称 | 类型 | 默认值 | 描述 | |---|---|---|---| | `provider` | string | **必需** | `anthropic`, `openai`, `groq`, `openrouter`, `together`, `mistral`, `deepseek`, `openai_compatible` 之一。 | | `model` | string | **必需** | 模型标识符。无默认值,因此不预设任何供应商。 | | `api_url` | string | `""` | 完整的 chat/completions endpoint。对于 `openai_compatible` 是必需的;对于任何其他提供商,这将覆盖内置的 URL。 | | `system_prompt` | string | DevSecOps 审查者角色 | 审查者角色的系统 prompt。 | | `max_diff_bytes` | number | `60000` | 发送前将 diff 截断为这么多字节。 | | `max_tokens` | number | `2000` | 模型响应中的最大 token 数。 | **Secrets** | 名称 | 必需 | 描述 | |---|---|---| | `ai_api_key` | 否 | 所选提供商的 API key。对于不需要身份验证的本地 endpoint,请省略。 | **调用者必须授予的权限** `contents: read`、`pull-requests: write`。 **用法** ``` jobs: review: uses: iampopye/devops-workflows/.github/workflows/ai/reusable-ai-pr-review.yml@v1 permissions: contents: read pull-requests: write with: provider: groq model: llama-3.3-70b-versatile # check your provider's current model list secrets: ai_api_key: ${{ secrets.GROQ_API_KEY }} ``` 完全自托管,不涉及任何第三方(需要能够访问你的 endpoint 的 runner): ``` with: provider: openai_compatible api_url: http://ollama.internal:11434/v1/chat/completions model: qwen2.5-coder:32b ``` 有关每个提供商的准备好的、可直接取消注释代码块,请参见 [`examples/ai-pr-review.yml`](examples/ai-pr-review.yml)。 ### AI 故障分析(可选) `.github/workflows/ai/reusable-ai-incident-analysis.yml` 收集你仓库近期失败的工作流运行,询问模型可能的原因、影响范围、缓解措施和预防步骤,然后打开一个包含结果的 GitHub issue。通常按计划或通过 `workflow_dispatch` 运行,而不是在每次 push 时运行。 **输入** | 名称 | 类型 | 默认值 | 描述 | |---|---|---|---| | `provider` | string | **必需** | 与 PR 审查工作流相同的提供商列表。 | | `model` | string | **必需** | 模型标识符。无默认值。 | | `api_url` | string | `""` | 完整的 endpoint URL。对于 `openai_compatible` 是必需的。 | | `incident_context` | string | `""` | 为模型提供额外的 context(近期的部署、已知问题)。 | | `lookback_runs` | number | `10` | 要分析的近期失败运行次数。 | | `max_tokens` | number | `2000` | 模型响应中的最大 token 数。 | | `dry_run` | boolean | `false` | 将分析结果写入 job 摘要而不是打开 issue。 | **Secrets** | 名称 | 必需 | 描述 | |---|---|---| | `ai_api_key` | 否 | 所选提供商的 API key。 | **调用者必须授予的权限** `actions: read`、`contents: read`、`issues: write`。 **用法** ``` name: Nightly incident analysis on: schedule: - cron: "0 6 * * *" workflow_dispatch: permissions: {} jobs: analyse: uses: iampopye/devops-workflows/.github/workflows/ai/reusable-ai-incident-analysis.yml@v1 permissions: actions: read contents: read issues: write with: provider: anthropic model: claude-opus-5 # check your provider's current model list lookback_runs: 20 dry_run: true # start here; flip to false once you trust the output secrets: ai_api_key: ${{ secrets.ANTHROPIC_API_KEY }} ``` 从 `dry_run: true` 开始。它会写入 job 摘要而不是提交 issue,因此你可以在它开始创建工单之前判断其输出质量。 ## 要求与假设 - **GitHub 托管的 `ubuntu-latest` runner。** 每个工作流都假设使用 Linux。`jq`、`curl`、`git` 和 `shellcheck` 已在此预装。 - **公开仓库,或 GitHub Advanced Security。** CodeQL 分析和到 Security 标签页的 SARIF 上传在公开仓库上是免费的;在私有仓库上,它们需要 GitHub Advanced Security。 - **可重用工作流权限模型。** 调用 job 必须授予每个工作流列出的权限。被调用的工作流可以缩小它们,但绝不能扩大它们。 - **锁定到发布标签。** 将这些工作流引用为 `@v1`,而不是 `@main`,这样上游的更改就无法在你未选择的情况下更改你的 pipeline。这与 SHA 锁定的理由相同,只是高了一个层级。 - **云凭据。** Terraform 工作流请求 `id-token: write`,以便你可以使用 OIDC 联合。在 AWS/GCP/Azure 中配置信任关系由你自己完成。 - **Gitleaks 许可。** `gitleaks/gitleaks-action` 对于个人账户和公开仓库是免费的;组织可能需要 `GITLEAKS_LICENSE`。在全组织范围推出之前,请检查该 action 自己的 README。 - **第三方服务账户**仅在你实际启用的功能时才需要:Terraform Cloud(`tf_api_token`)、container registry(对于 GHCR 默认使用内置 token)、Kubernetes cluster 或 AI 提供商。 ## 示例 [`examples/`](examples/) 目录包含完整的调用工作流,你可以直接将它们复制到你的 `.github/workflows/` 中——包括用于带有 SonarQube 的 Go 测试、Cucumber/Godog BDD 测试、k6 负载测试和 OWASP ZAP 扫描的独立 pipeline。请参见 [`examples/README.md`](examples/README.md)。 ## 贡献 欢迎贡献和提问。请阅读 [CONTRIBUTING.md](CONTRIBUTING.md) 了解内部规则——SHA 锁定的 actions、默认 `permissions: {}`、actionlint 必须通过、每个输入都要有文档记录。 如果你是 DevOps 新手并且觉得这里的某些内容不合常理,**那就是一个文档 bug,报告它会有所帮助**。请创建一个 issue 或发起讨论。 ## 维护者 **Karan Garg** — 高级顾问 高级 DevOps 与多云基础设施 · 高级 DevSecOps 与合规领导力 (CISO) · 数据工程与分析 · AI/GenAI 与机器学习工程 · 架构设计 · 跨团队交付 这个仓库的存在,是因为教程 pipeline 和你可以真正放在生产环境面前的 pipeline 之间的差距,比大多数学习材料所承认的要大。这里的一切都是为了让人阅读而编写的,而不仅仅是为了运行——注释解释了其背后的理由,包括促使做出每个决定的错误。 - **GitHub** — [@iampopye](https://github.com/iampopye) - **LinkedIn** — [karan-garg-tech](https://www.linkedin.com/in/karan-garg-tech/) - **X** — [@mrtechgarg](https://x.com/mrtechgarg) 欢迎在 [讨论区](https://github.com/iampopye/devops-workflows/discussions) 提出关于此仓库中任何内容的问题。如果某个工作流对你来说不合理,那值得告诉我——这通常意味着文档有问题,而不是你的问题。 ## 许可证 MIT — 详见 [LICENSE](LICENSE)。复制这些工作流,修改它们,在工作中使用它们。不胜感激你的注明,但非必须。
标签:DevSecOps, GitHub Actions, 上游代理, 子域名突变, 安全扫描, 时序注入, 网络调试, 自动化, 自动笔记, 请求拦截