# GitHub Actions

GitHub Actions 工作流创建、安全加固与版本管理，适用于 CI/CD 流水线。

- 涵盖工作流文件编写（`.yml`）、通过 `gh release view` 更新 Action 版本，以及密钥管理、脚本注入防护等安全最佳实践
- 明确禁止反模式：使用过时的 Action 版本、硬编码敏感凭证、输入值注入漏洞、误用 `pull_request_target` 事件、重复配置已预装工具
- 推荐最小权限原则、对不可信第三方 Action 使用 SHA 哈希固定（SHA pinning），以及通过环境变量隔离敏感数据
- 包含常用触发事件（`push`、`pull_request`、`schedule`、`workflow_dispatch`、`release`）和典型 CI/CD 场景所需的权限范围

> ⚠️ 提示：涉及 GitHub Actions 工作流执行与结果查看、Issue/PR 管理等 `gh` CLI 操作，请一并加载 `github` 技能参考。

## 反模式警示（Anti-patterns）

### 1. 使用过时的 Action 版本

```yaml
# ❌ 过due 版本 —— 最常见错误
uses: actions/checkout@v4 # 当前最新主版本为 v6 时

# ✅ 使用最新主版本（先用 gh release view 确认）
uses: actions/checkout@v6
```

确保获得最新版本带来的性能优化与安全补丁。

版本查询命令：

```bash
gh release view --repo {owner}/{repo} --json tagName --jq '.tagName'

# 示例
gh release view --repo actions/checkout --json tagName --jq '.tagName'
gh release view --repo oven-sh/setup-bun --json tagName --jq '.tagName'
```

> 💡 提示：在安全敏感环境或使用低信任度第三方 Action 时，建议采用 [SHA 固定](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-third-party-actions)（如 `@a1b2c3...`）。

### 2. 硬编码敏感信息

```yaml
# ❌ 危险：明文硬编码
env:
  API_KEY: "sk-1234567890"
  DATABASE_PASSWORD: "mypassword123"

# ✅ 安全：使用 secrets
env:
  API_KEY: ${{ secrets.API_KEY }}
  DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
```

密码、API Key 等敏感信息一旦泄露，将直接导致安全事件。所有高敏感数据必须存储于仓库或组织级 Secrets 中，并通过 `${{ secrets.XXX }}` 引用。

> 🔗 参考：[Using secrets in GitHub Actions](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions)

### 3. 输入值注入漏洞（Script Injection）

```yaml
# ❌ 危险：直接拼接 github.event 字段（易受注入）
run: echo "${{ github.event.issue.title }}"
run: gh issue comment ${{ github.event.issue.number }} --body "${{ github.event.comment.body }}"

# ✅ 安全：通过环境变量传递，避免 shell 解析风险
env:
  ISSUE_TITLE: ${{ github.event.issue.title }}
  COMMENT_BODY: ${{ github.event.comment.body }}
run: |
  echo "$ISSUE_TITLE"
  gh issue comment ${{ github.event.issue.number }} --body "$COMMENT_BODY"
```

恶意用户可能在 Issue 标题或 Comment 内注入任意 shell 命令。应始终避免将未过滤的事件字段直接用于 `run` 行。

> 🔗 参考：[Understanding the risk of script injections](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#understanding-the-risk-of-script-injections)

### 4. 误用 `pull_request_target` 事件

```yaml
# ⚠️ 高危：在可信上下文中执行 fork 的代码
on: pull_request_target
steps:
  - uses: actions/checkout@v{N}
    with:
      ref: ${{ github.event.pull_request.head.sha }} # ❌ 极度危险！
```

`pull_request_target` 允许 fork 发起的 PR 访问仓库 Secrets，若同时检出其代码，可能导致恶意逻辑执行。

> 🔗 参考：[Events that trigger workflows: `pull_request_target`](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target)

### 5. 对已预装工具重复配置

```yaml
# ❌ 冗余：Node.js、npm、npx 等已预装，无需 setup
steps:
  - uses: actions/setup-node@v{N}
  - run: npx some-command

# ✅ 直接使用
steps:
  - run: npx some-command
  - run: python script.py
  - run: docker build .
```

重复安装会延长流水线耗时，并产生不必要的网络请求。

✅ **已预装工具**（Ubuntu/macOS/Windows runner）：
`Node.js`, `npm`, `npx`, `Python`, `pip`, `Ruby`, `gem`, `Go`, `Docker`, `git`, `gh`, `curl`, `wget`, `jq`, `yq`

❌ **需手动安装的常见工具**：
`Bun`, `Deno`, `Rust`, `Zig`, `pnpm`, `Poetry`, `Ruff`

🔍 查看完整预装清单：
- Ubuntu：[Ubuntu2404-Readme.md](https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md)
- macOS：[macos-15-Readme.md](https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md)
- Windows：[Windows2022-Readme.md](https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md)

## 最佳实践（Best Practices）

### 最小权限原则（Principle of Least Privilege）

权限应在尽可能细粒度的层级声明（`workflow` > `job` > `step`），范围越窄越安全：

```yaml
# ✅ 推荐：在 job 级别声明仅需权限
jobs:
  build:
    permissions:
      contents: read # 仅读取代码所需
```

> 🔗 参考：[Modifying the permissions for the GITHUB_TOKEN](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token)

## 推荐工作流结构

```yaml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
      # 版本请先用 gh release view 确认
      - uses: actions/checkout@v{N}

      - name: Setup Bun
        uses: oven-sh/setup-bun@v{N}
```

## 常用触发事件

```yaml
on:
  push: # 推送代码时
    branches: [main]
  pull_request: # 创建或更新 PR 时
    branches: [main]
  workflow_dispatch: # 手动触发
  schedule: # 定时触发
    - cron: "0 0 * * 1" # 每周一 00:00 UTC
  release: # 发布新版本时
    types: [published]
  workflow_call: # 被其他工作流调用时
```

## 常用权限配置

```yaml
permissions:
  contents: read        # CI 构建/测试、代码检出
  contents: write       # 提交/推送代码
  pull-requests: write  # PR 评论机器人
  issues: write         # Issue 评论
  packages: write       # 发布包（需配合 contents: write）
  id-token: write       # OIDC 云身份认证（需配合 contents: read）
```

## 常用 Action 列表

```yaml
# 版本请统一通过 gh release view --repo {owner}/{repo} --json tagName --jq '.tagName' 查询
steps:
  - uses: actions/cache@v{N}                # 依赖缓存
  - uses: actions/checkout@v{N}             # 代码检出
  - uses: actions/download-artifact@v{N}    # 下载产物
  - uses: actions/upload-artifact@v{N}       # 上传产物
  - uses: oven-sh/setup-bun@v{N}            # 安装 Bun
```