Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
# alpha pre-push hook — enforce local-first (docs/CI.md).
# OPT-IN, not installed by default. Enable once with:
# git config core.hooksPath .githooks
# Disable with: git config --unset core.hooksPath
# Bypass a single push: git push --no-verify
exec bash "$(git rev-parse --show-toplevel)/scripts/alpha-check.sh"
4 changes: 4 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@
```
bun install
bun --cwd packages/ui-mac run dev # electron 解析失败时加 ELECTRON_EXEC_PATH(见 ALPHA.md)
bash scripts/alpha-check.sh # push 前自检:北极星守卫 + typecheck + 单测(与 alpha-ci 1:1)
```

## CI(规范见 `docs/CI.md`)
**本地先跑,CI 兜底**。push 前必过 `scripts/alpha-check.sh`。GitHub 上只有 `alpha-ci`(三关,required)+ `sync-upstream` 两个 workflow active;继承的 ~26 个上游 workflow 已禁用(要 Blacksmith runner,本 fork 没有 → 永久 queued,即"CI 卡"真因)。排查手册见 `docs/CI.md` §5。
73 changes: 73 additions & 0 deletions docs/CI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# CI 规范(alpha-code)

> 一句话:**本地先跑,CI 兜底**。CI 不是你第一次看到失败的地方——它是 merge 前的强制关卡。
> 权威触发定义在 `.github/workflows/alpha-ci.yml`;北极星守卫语义见 ADR-004,fork 纪律见 ADR-005。

## 0. TL;DR — push 前一条命令

```bash
bash scripts/alpha-check.sh
```

绿了再 push。它跑的就是 `alpha-ci` 的三关(北极星守卫 / typecheck / 单测),本地几秒出结果,和 CI 1:1 一致。

## 1. 为什么 local-first(优先本地跑)

- **快**:本地三关秒级;CI 往返一轮 = 排队 + 起机 + 装依赖 + 跑,分钟级。
- **省往返**:把 CI 当"第一次跑"= 每个错都要等一轮红了才知道 → 慢、烦、还堵别人的队。
- **CI 的真正职责**是①**强制门禁**(branch protection:不绿不让 merge,挡手滑)②**中立环境兜底**(抓"在我机器上是好的"那类环境差异)——不是给你当调试台用的。
- 所以顺序永远是:**本地 `alpha-check` 绿 → push → CI 复核 → merge**。

## 2. 三关是什么(与 `alpha-ci` 1:1)

| 关 | 本地命令 | CI job | 失败含义 |
|---|---|---|---|
| **北极星守卫**(零改上游) | `scripts/alpha-check.sh` 内含;等价 `git diff --diff-filter=DMR --name-only origin/dev...HEAD -- <上游7包>` 必须空 | `north-star guard (zero upstream edits)` | 改了上游文件 → 下次 fork-sync 冲突,破北极星 |
| **typecheck**(两个 alpha 包) | `bun --cwd packages/ext run typecheck` + `bun --cwd packages/ui-mac run typecheck` | `typecheck (alpha packages)` | 类型不过 |
| **单元测试**(ui-mac) | `bun --cwd packages/ui-mac test` | `unit tests (ui-mac)` | 安全路径守卫等回归 |

- **上游 7 包** = `packages/{opencode,core,server,app,ui,tui,sdk}`(见 alpha-ci.yml `env.UPSTREAM_PATHS`)。
- **bun 版本钉 `1.3.14`**(与 CI 一致,根 `package.json` 的 `packageManager`)。本机版本不同先对齐。
- 根 `bun test` 被故意禁用(`do not run tests from root`)——测试按包跑,别在根跑。

## 3. GitHub 上只跑两个 workflow(其余上游的已禁用)

本仓是 opencode 的 fork,继承了 ~26 个上游 workflow。它们要上游订阅的 **Blacksmith 自建 runner**(如 `runs-on: blacksmith-4vcpu-ubuntu-2404`),本 fork 没有这种机器 → 一触发就永久 `queued` 挂死。**这是历史上"CI 一直卡 / 连不通"的真因**(不是 API、不是限流、不是 alpha-ci)。

2026-07-03 已 `gh workflow disable` 全部上游 workflow,**只保留**:

| workflow | 作用 | 触发 |
|---|---|---|
| **`alpha-ci`** | 本仓 CI(上面三关) | `push` / `pull_request` → `alpha`;也可 `workflow_dispatch` |
| **`sync-upstream`** | 每日上游 `dev → merge alpha` 同步 | 定时 + 手动 |

- **required check 只有 `alpha-ci` 的三个 job**;其它 workflow 一律**不影响 merge**(PR 上若看到别的 check = 历史残留,忽略)。
- **不要盲目 `gh workflow enable`** 上游那些——除非你真给 fork 接了对应 runner。要恢复某个:`gh workflow enable <name>.yml`(可逆,文件没删)。

## 4. 提交纪律

1. push 前 `bash scripts/alpha-check.sh` **必须绿**。
2. 需要新增能力 → 走 alpha 自有文件(`packages/ext`、`packages/ui-mac`)或接缝(tool/plugin/MCP/sidecar,ADR-002/005),**绝不改上游 7 包**(改了北极星守卫本地就红)。
3. 短命 `feat/*` / `fix/*` 分支 → PR → squash 合回 `alpha` → **合后即删分支**(ADR-005)。
4. 想把 local-first 变**强制** → 装 §6 的 pre-push 钩子。

## 5. CI 卡住了怎么办(排查手册)

1. **先分清谁卡**:`gh run list` 看是哪个 workflow。`alpha-ci` 卡 = 真问题;别的 = 已禁用的僵尸,忽略/取消。
2. **queued(排队) vs in_progress(在跑但慢)**:
- 一直 `queued` = 等 runner(无匹配 runner / Actions 额度耗尽 / 并发上限);
- `in_progress` 慢 = job 本身慢(装依赖 / 测试)——那才是 REQ-009 缓存优化的场景。
3. **命令**:`gh run cancel <id>` 取消 · `gh run watch <id>` 盯 · `gh run rerun <id>` 重跑 · `gh run list --workflow=alpha-ci.yml` 只看本仓 CI。
4. **别被堵**:本地三关已绿 = 代码没问题;required 只有 alpha-ci 三个。真急可 `gh pr merge --admin` 绕过(慎用,别养成习惯)。

## 6. (可选)pre-push 钩子 —— 把 local-first 变强制

默认**不装**(不打断急活)。想要强约束:

```bash
git config core.hooksPath .githooks # 一次性开启;仓库已带 .githooks/pre-push
# 关闭: git config --unset core.hooksPath
# 单次绕过: git push --no-verify
```

开启后每次 `git push` 会先跑 `scripts/alpha-check.sh`,不绿不让推。
52 changes: 52 additions & 0 deletions scripts/alpha-check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# alpha-check — run the exact gates alpha-ci enforces, LOCALLY, before you push.
#
# Standard: local-first (see docs/CI.md). CI is the enforcing backstop, not the place
# you first discover a failure. This mirrors alpha-ci's three jobs 1:1 and runs in seconds.
#
# bash scripts/alpha-check.sh
#
# Exit 0 = safe to push (CI will mirror this). Non-zero = fix before pushing.
set -uo pipefail
cd "$(git rev-parse --show-toplevel)"

# Keep in lockstep with .github/workflows/alpha-ci.yml (env.UPSTREAM_PATHS) and ADR-004.
UPSTREAM_PATHS="packages/opencode packages/core packages/server packages/app packages/ui packages/tui packages/sdk"
fail=0

echo "▶ [1/3] north-star guard (zero upstream edits)"
git fetch --no-tags origin dev --quiet 2>/dev/null || echo " (warn: could not fetch origin/dev — comparing against last-known origin/dev)"
# committed delta (mirrors CI) ∪ working-tree edits (earlier local feedback)
committed="$(git diff --diff-filter=DMR --name-only origin/dev...HEAD -- $UPSTREAM_PATHS 2>/dev/null || true)"
worktree="$(git diff --diff-filter=DMR --name-only HEAD -- $UPSTREAM_PATHS 2>/dev/null || true)"
changed="$(printf '%s\n%s\n' "$committed" "$worktree" | sed '/^$/d' | sort -u)"
if [ -n "$changed" ]; then
echo " ✗ upstream files modified/deleted/renamed (fork-sync would conflict):"
echo "$changed" | sed 's/^/ /'
echo " → revert; extend via alpha files (packages/ext, packages/ui-mac) or seams (ADR-002/005)."
fail=1
else
echo " ✓ zero upstream package edits"
fi

echo "▶ [2/3] typecheck (alpha packages: ext + ui-mac)"
if bun --cwd packages/ext run typecheck && bun --cwd packages/ui-mac run typecheck; then
echo " ✓ typecheck"
else
echo " ✗ typecheck failed"; fail=1
fi

echo "▶ [3/3] unit tests (ui-mac)"
if bun --cwd packages/ui-mac test; then
echo " ✓ tests"
else
echo " ✗ tests failed"; fail=1
fi

echo
if [ "$fail" -eq 0 ]; then
echo "✅ all local gates green — safe to push (alpha-ci will mirror this in ~40s)."
else
echo "❌ local gates failed — fix before pushing (alpha-ci would fail the same way)."
fi
exit $fail
Loading