tinbee/ci-workflows

GitHub: tinbee/ci-workflows

提供可复用的 GitHub Actions 工作流,用于标准化 Node.js 项目的 CI/CD 和静态站点部署到 AWS 及 GitHub Pages。

Stars: 0 | Forks: 0

# ci-工作流 适用于 `tinbee` 及其他仓库的可复用 GitHub Actions 工作流。作为 Action 版本和 CI/CD 步骤结构的唯一真实来源——在此处仅需更新一次 Action 版本,所有消费者在下次运行时便会自动采用最新版本。 公开状态以确保任何组织的仓库均可使用。私有仓库中的可复用工作流只能被同一组织调用;将此公开是跨组织共享的标准模式。 ## 可用工作流 ### 部署-s3-cloudfront.yml 将静态站点部署至 AWS S3 + CloudFront。默认采用 **SPA 模式**(Vite/Astro/Next 风格):两阶段 S3 同步,对带哈希的 `assets/*` 设置 `max-age=31536000, immutable`,其余文件设置 `max-age=0, must-revalidate`,并仅对 `/` 和 `/index.html` 进行针对性 CloudFront 失效处理(带哈希的资产无需失效)。对于根目录提供 HTML/其他文件的传统静态站点(cal 风格),可覆盖这些默认设置。 #### SPA 调用方(推荐 — Vite/Astro/Next) ``` name: Deploy web on: workflow_run: workflows: ["CI"] types: [completed] branches: [main] workflow_dispatch: concurrency: group: deploy-web-${{ github.ref }} cancel-in-progress: true permissions: id-token: write contents: read jobs: deploy: if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' uses: tinbee/ci-workflows/.github/workflows/deploy-s3-cloudfront.yml@v1 with: aws_region: ${{ vars.AWS_REGION }} build_command: | pnpm install --frozen-lockfile --filter @yourapp/web... pnpm --filter @yourapp/web build source_dir: apps/web/dist/ env_json: | { "VITE_API_URL": "${{ vars.VITE_API_URL }}", "VITE_PUBLIC_KEY": "${{ vars.VITE_PUBLIC_KEY }}" } secrets: role_to_assume: ${{ secrets.AWS_CLOUDFRONT_ROLE_TO_ASSUME }} s3_bucket: ${{ secrets.AWS_S3_BUCKET }} cloudfront_distribution: ${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }} ``` #### 传统静态站点调用方(cal 风格 — 根目录提供 `.html`、`.ics` 等文件) ``` jobs: deploy: uses: tinbee/ci-workflows/.github/workflows/deploy-s3-cloudfront.yml@v1 with: aws_region: ${{ vars.AWS_REGION }} source_dir: "." setup_pnpm: false # no package.json cache_control_overrides: "" # disable multi-pass sync default_cache_control: "" # no Cache-Control header invalidation_paths: "/*" # invalidate everything sync_excludes: | .git/* .github/* content_type_fixups: | [{"ext":".ics","content_type":"text/calendar; charset=utf-8","cache_control":"public, max-age=3600"}] secrets: { ... } ``` #### 输入参数 | 输入参数 | 类型 | 默认值 | 说明 | |---|---|---|---| | `node_version` | 字符串 | `"24"` | 传递给 `actions/setup-node`。 | | `build_command` | 字符串 | `""` | 多行 bash 命令;为空则跳过。 | | `source_dir` | 字符串 | `"dist/"` | 需同步至 S3 的目录。 | | `sync_excludes` | 字符串 | `""` | 换行分隔的 `--exclude` 模式(适用于每个同步阶段)。 | | `cache_control_overrides` | 字符串 | `'[{"path_pattern":"assets/*","cache_control":"public, max-age=31536000, immutable"}]'` | JSON 数组格式,用于按模式覆盖 Cache-Control。每个条目作为独立的 `aws s3 sync` 阶段在默认同步前执行。设为 `""` 可完全禁用多阶段同步。 | | `default_cache_control` | 字符串 | `"public, max-age=0, must-revalidate"` | 未被任何覆盖规则匹配的文件的 Cache-Control 值。设为 `""` 可省略该头部(S3 默认行为)。 | | `content_type_fixups` | 字符串 | `""` | JSON 数组格式,用于按扩展名修正 Content-Type。每个条目需包含 `ext`、`content_type`,可选 `cache_control`。在所有同步阶段后执行。 | | `invalidation_paths` | 字符串 | `"/ /index.html"` | 空格分隔的 CloudFront 路径。默认对 SPA 友好。传统静态站点可设为 `"/*"`。 | | `env_json` | 字符串 | `"{}"` | JSON 对象,在构建步骤前导出至 `$GITHUB_ENV`。用于 `VITE_*` / `NEXT_PUBLIC_*` 等构建时配置。 | | `aws_region` | 字符串 | 必填 | 例如 `us-east-1`。通过 `vars.X` 传入或直接硬编码——**切勿**使用 `secrets.X`(`with:` 块禁止使用 secrets 上下文)。 | | `setup_pnpm` | 布尔值 | `true` | 是否设置 pnpm + pnpm 缓存。对于无 `package.json` 或 `packageManager` 字段的消费者,设为 `false`。 | #### 密钥 | 密钥 | 说明 | |---|---| | `role_to_assume` | 用于 OIDC 的 IAM 角色 ARN。该角色必须信任 `token.actions.githubusercontent.com` 以及调用方仓库。 | | `s3_bucket` | 存储桶名称,不含 `s3://` 前缀。 | | `cloudfront_distribution` | Distribution ID。 | #### 验证 所有必需输入/密钥(`aws_region`、`role_to_assume`、`s3_bucket`、`cloudfront_distribution`)在第一步即被检查**是否非空**,之后才进行任何 AWS 调用。`required: true` 仅保证调用方*传入*了值——但不保证其非空——因此缺少 `vars.AWS_REGION`(解析为 `""`)或未设置的密钥会在此处快速失败,并附带明确指明缺失项的 `::error::` 注解,而非在部署过程中出现晦涩错误。可复用工作流是正确性的来源;配置不当的消费者将被精确告知需要修正的内容。 ### node-pnpm-持续集成.yml 基于 pnpm 的 Node 项目 CI 工作流。基本流程为:检出代码 → pnpm → Node(由 `.nvmrc` 驱动)→ 安装依赖,随后执行预设默认步骤(格式化 / Lint / 类型检查 / 构建 / 测试)。每个步骤均可通过将其输入设为 `""` 来跳过。提供预检查插槽(输入 `pre_check_command`)用于需要在类型检查前运行的代码生成(如 Prisma generate、GraphQL codegen)。 #### 调用示例 ``` name: CI on: push: branches: [main] pull_request: workflow_dispatch: concurrency: group: ci-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: ci: uses: tinbee/ci-workflows/.github/workflows/node-pnpm-ci.yml@v1 with: # Opt out of any step by passing "": # test_command: "" pre_check_command: pnpm --filter @yourapp/api db:generate build_command: | pnpm --filter @yourapp/api build pnpm --filter @yourapp/web build test_command: pnpm --filter @yourapp/api test env_json: | { "DATABASE_URL": "postgresql://ci:ci@localhost:5432/ci", "VITE_API_URL": "https://ci.example", "VITE_PUBLIC_KEY": "ci-placeholder" } ``` #### 输入参数 | 输入参数 | 类型 | 默认值 | 说明 | |---|---|---|---| | `node_version_file` | 字符串 | `".nvmrc"` | 与本地开发共享的单一真实来源。设为 `""` 可改为使用字面值 `node_version`。 | | `node_version` | 字符串 | `"24"` | 仅在 `node_version_file` 为空时使用。 | | `install_command` | 字符串 | `"pnpm install --frozen-lockfile"` | 设为空则跳过(少见情况)。 | | `pre_check_command` | 字符串 | `""` | 代码生成 / Schema 生成。在安装后、格式化/Lint/类型检查前运行。 | | `format_check_command` | 字符串 | `"pnpm format:check"` | 设为空则跳过。 | | `lint_command` | 字符串 | `"pnpm lint"` | 设为空则跳过。 | | `typecheck_command` | 字符串 | `"pnpm -r typecheck"` | 设为空则跳过。 | | `build_command` | 字符串 | `"pnpm -r build"` | 设为空则跳过。 | | `test_command` | 字符串 | `"pnpm -r test"` | 设为空则跳过。每次触发均运行,除非被覆盖率运行取代(见下文)。 | | `coverage_command` | 字符串 | `""` | 在推送到默认分支(合并后)时**替代** `test_command` 运行。生成覆盖率报告作为证据(非门控)。设为空则禁用覆盖率运行。调用方必须在 `push` 到默认分支时触发。 | | `coverage_artifact_path` | 字符串 | `""` | 多行 glob 路径,上传为覆盖率构件(例如 `packages/*/coverage`)。设为空则跳过上传。仅在覆盖率运行期间使用。 | | `coverage_artifact_name` | 字符串 | `"coverage"` | 上传的覆盖率构件名称。 | | `coverage_retention_days` | 数字 | `14` | 覆盖率构件的保留天数。 | | `env_json` | 字符串 | `"{}"` | JSON 对象,包含导出至 `$GITHUB_ENV` 的环境变量。 | | `timeout_minutes` | 数字 | `15` | 作业超时时间。 | | `turbo_api` | 字符串 | `""` | Turbo Remote Cache API URL(通常为 `vars.TURBO_API`)。设为空则不使用远程缓存。 | | `turbo_team` | 字符串 | `""` | Turbo Remote Cache 团队标识(通常为 `vars.TURBO_TEAM`)。 | #### 密钥 | 密钥 | 必填 | 说明 | |---|---|---| | `turbo_token` | 否 | Turbo Remote Cache 令牌(`secrets.TURBO_TOKEN`)。省略则不使用远程缓存。必须是密钥——不能通过 `env_json` 传递(它是 `with:` 输入,禁止使用 secrets 上下文)。需与 `turbo_api` + `turbo_team` 输入配对使用。 | 作业始终命名为 `CI`——所需状态检查规则集应引用此名称。 ### 部署-gh-pages.yml 构建静态/SPA 站点并发布至 **GitHub Pages**。包含两个作业:`build`(检出代码 → pnpm/Node → 构建 → 上传 Pages 构件)和 `deploy`(`actions/deploy-pages`)。默认为 pnpm 优先;npm 消费者应设置 `setup_pnpm: false` 并覆盖 `build_command`。 调用方**必须**授予 Pages 权限上限(可复用工作流继承调用方权限),并应设置并发组。 #### 调用示例 ``` name: Deploy to GitHub Pages on: push: branches: ["main"] workflow_dispatch: permissions: contents: read pages: write id-token: write concurrency: group: "pages" cancel-in-progress: false jobs: deploy: if: github.ref == 'refs/heads/main' uses: tinbee/ci-workflows/.github/workflows/deploy-gh-pages.yml@v1 # All defaults suit a pnpm Vite SPA (build → dist/). Override as needed: # with: # setup_pnpm: false # build_command: | # npm ci # npm run build # artifact_path: frontend/dist ``` #### 输入参数 | 输入参数 | 类型 | 默认值 | 说明 | |---|---|---|---| | `node_version` | 字符串 | `"24"` | 传递给 `actions/setup-node`。 | | `setup_pnpm` | 布尔值 | `true` | 设置 pnpm + `cache: pnpm`。npm/yarn 消费者设为 `false`(然后覆盖 `build_command`)。 | | `build_command` | 字符串 | `pnpm install --frozen-lockfile` + `pnpm build` | 多行 bash 命令。npm 消费者需覆盖(例如 `npm ci && npm run build`)。 | | `artifact_path` | 字符串 | `"dist"` | 作为 Pages 构件上传的目录。 | | `env_json` | 字符串 | `"{}"` | JSON 对象,通过 `$GITHUB_ENV` 导出至构建过程(例如 `VITE_*`)。 | 无密钥要求——GitHub Pages 认证使用内置 `GITHUB_TOKEN`,通过调用方授予的 `pages: write` + `id-token: write` 权限实现。如果构建未生成非空的 `artifact_path`,`build` 作业将快速失败。 ## 版本管理 - 浮动主版本标签:`@v1`、`@v2`、... — 消费者固定使用这些标签,自动获取补丁和次要版本更新。 - 完整版本:`@v1.0.0`、`@v1.0.1`、... — 用于固定到特定发布版本。 - 破坏性变更总是会提升主版本号(`@v1` → `@v2`);消费者按自身计划迁移。 ## 添加新工作流 1. 在 `.github/workflows/.yml` 添加工作流,并包含 `on: workflow_call:` 触发器。 2. 在此文档中记录输入参数和密钥。 3. 迁移一个消费者作为验证。 4. 提升版本号(现有主版本下新增工作流用 `v1.x.x`;若改变现有工作流的输入/密钥契约则用 `v2.0.0`)。
标签:Astro, AWS CloudFront, AWS S3, AWS 部署, CI/CD 工作流, GitHub Actions, MITM代理, pnpm, SPA 模式, Vite, 云基础设施, 云计算, 单页应用部署, 可重用工作流, 开发运维, 持续集成与部署, 版本管理, 特权提升, 自动化部署, 自动笔记, 规则引擎, 跨组织共享, 部署自动化, 静态站点部署