# CI/CD Scripts
TypeScript scripts + shell scripts for validation, reporting, versioning, and deployment. 6 GitHub Actions workflows in `.github/workflows/`.
**Parent:** See [root AGENTS.md](../AGENTS.md) for monorepo context.
## STRUCTURE
```
ci/
├── tsconfig.json # ES2022, strict, Node types
├── reporters/
│ ├── types.ts # Core types + artifact I/O (ci/reports/*.json)
│ ├── index.ts # Reporter registry + re-exports
│ ├── npm-release.ts # NPM beta install instructions (priority 10)
│ ├── kumo-docs-preview.ts # Docs preview URL (priority 30)
│ └── visual-regression.ts # Screenshot diff report
├── scripts/
│ ├── validate-kumo-changeset.ts # Pre-push + CI changeset enforcement
│ ├── ensure-changeset-config.ts # Guard: .changeset/config.json exists
│ ├── write-npm-report.ts # Writes ci/reports/npm-release.json
│ ├── write-kumo-docs-report.ts # Writes ci/reports/kumo-docs-preview.json
│ ├── post-pr-report.ts # Aggregates artifacts → GitHub PR comment
│ └── create-release-pr.ts # Creates release PR via GitHub API
├── utils/
│ ├── git-operations.ts # Git ref detection (CI + local), diff, changed files
│ ├── github-api.ts # Octokit wrapper (hardcoded: cloudflare/kumo)
│ └── pr-reporter.ts # Markdown assembly + comment posting
├── visual-regression/
│ └── run-visual-regression.ts # Creates vr-screenshots-{pr}-{runId} branches
└── versioning/
├── version-beta.sh # changeset version + append -beta.<sha> via jq
├── publish-beta.sh # Full pipeline: version → build → publish → verify (45s) → report
├── release-production.sh # Branch → version → build → publish → verify (30s) → push → PR
├── deploy-kumo-docs-preview.sh # Build → wrangler versions upload → preview URL → report
└── deploy-kumo-docs-staging.sh # Build → wrangler deploy --env staging
```
## WHERE TO LOOK
| Task | Location | Notes |
| -------------------- | -------------------------------------------- | ------------------------------------------------------- |
| Changeset validation | `scripts/validate-kumo-changeset.ts` | Used by lefthook pre-push AND CI |
| PR comment system | `reporters/` + `scripts/post-pr-report.ts` | Artifact bus via `ci/reports/*.json` |
| Beta release | `versioning/publish-beta.sh` | Calls version-beta.sh internally |
| Production release | `versioning/release-production.sh` | Creates release branch + PR |
| Git operations | `utils/git-operations.ts` | Dual-mode: GitHub Actions env vars / local `merge-base` |
| Visual regression | `visual-regression/run-visual-regression.ts` | Creates ephemeral branches for screenshot diffs |
## CONVENTIONS
### Artifact Bus Pattern
Jobs communicate via filesystem: each writes JSON to `ci/reports/{id}.json`, final job reads all.
```
publish-beta.sh → write-npm-report.ts → ci/reports/npm-release.json ──┐
├→ post-pr-report.ts → PR comment
deploy-docs-preview.sh → write-kumo-docs-report.ts → ci/reports/kumo-docs-preview.json ─┘
```
- Priority determines display order (lower = higher in comment): npm=10, docs=30
- Reporter returns `null` to skip (e.g., no package version = no npm section)
- `readReportArtifacts()` handles partial failures via `failures` array
### Shell ↔ TypeScript Boundary
- Shell scripts: orchestration (npm auth, git config, sequential builds, wrangler)
- TypeScript: structured operations (report generation, PR creation, GitHub API)
- Data channel: environment variables (`PACKAGE_VERSION`, `KUMO_DOCS_PREVIEW_URL`, `GITHUB_*`)
### Dual-Mode Git Operations
`getGitRefs()` adapts automatically:
- **CI**: Uses `GITHUB_BASE_REF` / `GITHUB_HEAD_REF`
- **Local**: Computes `git merge-base origin/main HEAD`
- Uses `execFileSync` (array args) to prevent shell injection
## GITHUB WORKFLOWS
| Workflow | Trigger | Purpose |
| -------------------- | -------------------------------- | ------------------------------------------------ |
| `release.yml` | push:main | changesets/action (Version PR or publish) |
| `pullrequest.yml` | pull_request, push:opencode/\*\* | Build, lint, typecheck, test |
| `preview.yml` | pull_request, push:opencode/\*\* | pkg-pr-new, docs build/deploy, visual regression |
| `preview-deploy.yml` | workflow_run(Preview) | Fork PR docs deploy (security boundary) |
| `bonk.yml` | issue_comment, pr_review_comment | AI agent (`@ask-bonk`) via CF AI Gateway |
| `reviewer.yml` | pr_review_comment | AI code review (`/review` command) |
## ANTI-PATTERNS
| Pattern | Why | Instead |
| ---------------------------------------- | ---------------------- | -------------------------------------- |
| Reading `process.env.*` directly | Bypasses typed context | Use `buildContextFromEnv()` |
| Adding reporter without registry | Won't be collected | Add to `reporters/index.ts` array |
| Running `release-production.sh` as agent | Sensitive operation | Human-only; use `DRY_RUN=true` to test |
## NOTES
- **Verify-after-publish**: Both beta (45s) and production (30s) scripts sleep then check npm registry. No retry logic.
- **`DRY_RUN=true`**: Production release script gates all destructive operations; logs what would happen
- **Hardcoded repo**: `github-api.ts` uses `owner: "cloudflare", repo: "kumo"`
- **Required secrets**: `NPM_TOKEN`, `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID`, `GITHUB_TOKEN`, `FIGMA_TOKEN` (optional)
- **Visual regression**: Creates ephemeral `vr-screenshots-{pr}-{runId}` branches for diff images
- **Fork PR security**: `preview-deploy.yml` handles fork PRs via `workflow_run` (no secrets in fork context)
- **Composite action**: `.github/actions/install-dependencies/action.yml` installs pnpm 10.22.0, Node 24, with optional filtercloudflare/kumo
Publicmirrored fromhttps://github.com/cloudflare/kumoAvailable
ci/AGENTS.md
107lines · modepreview