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, 云基础设施, 云计算, 单页应用部署, 可重用工作流, 开发运维, 持续集成与部署, 版本管理, 特权提升, 自动化部署, 自动笔记, 规则引擎, 跨组织共享, 部署自动化, 静态站点部署