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
8 changes: 6 additions & 2 deletions .claude/rules/ci-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
paths:
- ".github/**"
- ".bun-version"
- "scripts/smoke-cli.sh"
- "release-please-config.json"
- ".release-please-manifest.json"
- "CHANGELOG.md"
Expand All @@ -17,9 +18,12 @@ paths:

## PR 체크 (`.github/workflows/pr-check.yml`)

- 잡 5개(lint — format:check 스텝 포함 · typecheck · test · coverage · e2e)가 `main` 룰셋의 필수 체크다. 잡 이름을 바꾸거나 지우면 룰셋도 같이 고친다 — 룰셋은 이름으로 기다려서, 없어진 이름 때문에 모든 PR이 막힌다. 룰셋: `gh api repos/say8425/diffdeck/rulesets/18998573`.
- 잡 6개(lint — format:check 스텝 포함 · typecheck · test · bun-floor · coverage · e2e)가 `main` 룰셋의 필수 체크다. 잡 이름을 바꾸거나 지우면 룰셋도 같이 고친다 — 룰셋은 이름으로 기다려서, 없어진 이름 때문에 모든 PR이 막힌다. 룰셋: `gh api repos/say8425/diffdeck/rulesets/18998573`.
- 우회자(`bypass_actors`)가 없어 관리자도 빨간 CI로 머지하지 못한다. `strict`(최신 `main` 포함 요구)는 끈다 — 켜면 머지마다 열린 PR의 e2e를 다시 돌려야 한다. flake는 `gh run rerun <id> --failed`로 다시 돌린다.
- 모든 setup-bun 스텝은 `bun-version-file: .bun-version`으로 같은 Bun을 쓴다. 고정하지 않으면 새 Bun이 나올 때마다 PR과 무관하게 결과가 바뀐다 — Bun의 line coverage 집계가 버전마다 달라 coverage 게이트가 갑자기 실패할 수 있다. 올릴 때는 `.bun-version`과 devDep `@types/bun`을 같이 바꾸고, 그 버전으로 `bun run test:coverage`를 로컬에서 먼저 돌린다. 지원 하한은 Bun 1.4다.
- setup-bun 스텝은 `bun-version-file: .bun-version`으로 같은 Bun을 쓴다(`bun-floor`의 두 번째 스텝만 예외). 고정하지 않으면 새 Bun이 나올 때마다 PR과 무관하게 결과가 바뀐다 — Bun의 line coverage 집계가 버전마다 달라 coverage 게이트가 갑자기 실패할 수 있다. 올릴 때는 `.bun-version`과 devDep `@types/bun`을 같이 바꾸고, 그 버전으로 `bun run test:coverage`를 로컬에서 먼저 돌린다.
- 지원 하한은 Bun 1.4.0이다(README·번역 4종·`apps/viewer/README.md`의 요구 사항 줄). `.bun-version`을 올리면 `@types/bun`도 올라가 하한에 없는 API가 타입 검사와 다른 잡을 통과한다. 그래서 `bun-floor` 잡이 고정 Bun으로 설치·빌드한 뒤 `BUN_FLOOR` Bun으로 `scripts/smoke-cli.sh`(빌드된 `dist/cli.js`를 띄워 첫 화면 API를 부른다)와 `bun test`를 돈다. 설치를 하한 Bun으로 하지 않는 것은, 잠금 파일 포맷이 하한을 앞서는 날 하한과 무관하게 빨개지지 않게 하려는 것이다.
- 스모크는 `bun test`보다 먼저 돈다. `cli-smoke.test.ts`가 PATH의 bun(하한)으로 `dist`를 다시 빌드하므로, 순서를 바꾸면 릴리스 번들 대신 하한 Bun이 빌드한 번들을 스모크한다. 같은 이유로 `build.ts`도 하한 Bun에서 돌아야 한다.
- `bun-floor`가 테스트 코드에서만 빨개지면(새 `bun:test` 매처, `bunfig.toml` 키 등) 테스트를 고친다. 사용자는 테스트를 돌리지 않으므로 그 때문에 하한을 올리지 않는다. 하한을 올리면 `BUN_FLOOR`, README 여섯 곳(`apps/viewer/README.md` 포함), 이 줄을 같은 PR에서 바꾼다.
- 모든 잡은 `bun install --frozen-lockfile`로 설치한다. e2e 잡은 Node를 고정하고 `playwright install --with-deps chrome`으로 실제 Chrome을 깐다(`channel: "chrome"`). 실패하면 `apps/viewer/test-results/`를 아티팩트로 올린다.
- e2e는 골라 돌리지 않고 전부 돈다 — 어느 계약이 깨질지 미리 알 수 없다.

Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,35 @@ jobs:
- run: bun install --frozen-lockfile
- run: bun test

# 다른 잡은 .bun-version으로 돈다. 사용자는 지원 하한까지의 어느 Bun으로든 배포물을
# 돌리므로, 릴리스와 같은 Bun으로 빌드한 dist/cli.js와 테스트 스위트를 하한 Bun에서
# 돌린다(ci-release.md).
bun-floor:
runs-on: ubuntu-latest
timeout-minutes: 10
env:
BUN_FLOOR: 1.4.0
steps:
- uses: actions/checkout@v7
# 두 setup-bun이 같은 경로에 깔린다. 캐시를 켜면 이 스텝의 post가 하한 바이너리를
# 고정 버전 키로 저장할 수 있다.
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: .bun-version
no-cache: true
- run: bun install --frozen-lockfile
- run: bun run build
working-directory: apps/viewer
- uses: oven-sh/setup-bun@v2
with:
bun-version: ${{ env.BUN_FLOOR }}
- name: Check the floor Bun is on PATH
run: test "$(bun --version)" = "$BUN_FLOOR"
# bun test보다 먼저 돈다. cli-smoke.test.ts가 PATH의 bun으로 dist를 다시 빌드한다.
- name: Smoke the release bundle
run: scripts/smoke-cli.sh
- run: bun test

coverage:
runs-on: ubuntu-latest
steps:
Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
- `apps/viewer/` — 배포되는 유일한 패키지 `@say8425/diffdeck`: `server/`(데이터 API) · `browser/`(뷰어, `main.ts`가 배선) · `index.html` · `cli.ts` + `cli/` · `build.ts` · `fonts/` · `__tests__/` · `e2e/`
- `apps/preview/` — PR 프리뷰 Cloudflare Worker와 녹화기. 배포 패키지가 아니다.
- `skills/diffdeck/SKILL.md` — 배포되는 에이전트 스킬. `build.ts`가 `dist/skills/`로 복사한다. 플러그인 매니페스트는 `.claude-plugin/`·`.codex-plugin/`·`.agents/plugins/`에 있다.
- `scripts/` — 소스맵 복원 도구, css-inline Bun 플러그인, 렌더 패리티 하니스(`scripts/parity/`)
- `scripts/` — 소스맵 복원 도구, css-inline Bun 플러그인, 렌더 패리티 하니스(`scripts/parity/`), 배포 번들 스모크(`smoke-cli.sh`)
- `docs/` — README 번역 4종과 스크린샷. `docs/superpowers/`는 gitignore된 로컬 계획 문서다.

## 명령
Expand All @@ -26,7 +26,7 @@ cd apps/viewer && bun run build && bun run start # 뷰어를 직접 띄워 본

## 작업 규칙

- `main`에 직접 push하지 않는다. 브랜치 → PR → 사람이 리뷰·머지한다. 필수 체크 5개(lint·typecheck·test·coverage·e2e)가 초록이어야 머지된다.
- `main`에 직접 push하지 않는다. 브랜치 → PR → 사람이 리뷰·머지한다. 필수 체크 6개(lint·typecheck·test·bun-floor·coverage·e2e)가 초록이어야 머지된다.
- 커밋 메시지는 Conventional Commits다. release-please가 이것으로 버전·CHANGELOG·릴리스를 만든다(`feat`→minor, `fix`→patch, `!`·`BREAKING CHANGE`→major, `docs`·`chore`·`test`·`ci` 등은 릴리스 없음).
- `packages/*`에서는 import 경로와 재구성 타입만 고친다. 렌더·로직 변경은 합의된 예외일 때만 한다(`vendored-packages.md`). CodeView 엔진은 재작성하지 않는다.
- 외부 의존성은 정확한 버전으로 핀한다(`^`·`~` 금지).
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Or install it globally to get the `diffdeck` command:
bun install -g @say8425/diffdeck
```

Requires [Bun](https://bun.sh) and `git` on your `PATH`. [`gh`](https://cli.github.com) is optional: with it, diffdeck uses your pull requests to pick the comparison base and to show PR badges.
Requires [Bun](https://bun.sh) 1.4 or later and `git` on your `PATH`. [`gh`](https://cli.github.com) is optional: with it, diffdeck uses your pull requests to pick the comparison base and to show PR badges.

## CLI

Expand Down
2 changes: 2 additions & 0 deletions apps/viewer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ with syntax highlighting, a file tree, and inline image diffs.
bunx @say8425/diffdeck
```

Requires [Bun](https://bun.sh) 1.4 or later and `git`.

Run it from inside a git repository. It starts a local server on
`127.0.0.1:49573` (override with `--port`) and opens the viewer in your
default browser.
Expand Down
2 changes: 1 addition & 1 deletion docs/README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ O instálalo globalmente para obtener el comando `diffdeck`:
bun install -g @say8425/diffdeck
```

Requiere [Bun](https://bun.sh) y `git` en tu `PATH`. [`gh`](https://cli.github.com) es opcional: con él, diffdeck usa tus pull requests para elegir la base de comparación y mostrar insignias de PR.
Requiere [Bun](https://bun.sh) 1.4 o posterior y `git` en tu `PATH`. [`gh`](https://cli.github.com) es opcional: con él, diffdeck usa tus pull requests para elegir la base de comparación y mostrar insignias de PR.

## CLI

Expand Down
2 changes: 1 addition & 1 deletion docs/README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ bunx @say8425/diffdeck
bun install -g @say8425/diffdeck
```

[Bun](https://bun.sh) と、`PATH` 上の `git` が必要です。[`gh`](https://cli.github.com) は任意です — あればプルリクエストをもとに比較ベースを選び、PR バッジを表示します。
[Bun](https://bun.sh) 1.4 以降と、`PATH` 上の `git` が必要です。[`gh`](https://cli.github.com) は任意です — あればプルリクエストをもとに比較ベースを選び、PR バッジを表示します。

## CLI

Expand Down
2 changes: 1 addition & 1 deletion docs/README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ bunx @say8425/diffdeck
bun install -g @say8425/diffdeck
```

[Bun](https://bun.sh)과, `PATH`에 `git`이 있어야 합니다. [`gh`](https://cli.github.com)는 선택 사항입니다 — 있으면 풀 리퀘스트를 보고 비교 기준을 고르고 PR 배지를 보여줍니다.
[Bun](https://bun.sh) 1.4 이상과, `PATH`에 `git`이 있어야 합니다. [`gh`](https://cli.github.com)는 선택 사항입니다 — 있으면 풀 리퀘스트를 보고 비교 기준을 고르고 PR 배지를 보여줍니다.

## CLI

Expand Down
2 changes: 1 addition & 1 deletion docs/README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ bunx @say8425/diffdeck
bun install -g @say8425/diffdeck
```

需要 [Bun](https://bun.sh),且 `PATH` 中需包含 `git`。[`gh`](https://cli.github.com) 为可选项:有了它,diffdeck 会根据拉取请求选择对比基准,并显示 PR 徽章。
需要 [Bun](https://bun.sh) 1.4 或更高版本,且 `PATH` 中需包含 `git`。[`gh`](https://cli.github.com) 为可选项:有了它,diffdeck 会根据拉取请求选择对比基准,并显示 PR 徽章。

## CLI

Expand Down
52 changes: 52 additions & 0 deletions scripts/smoke-cli.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# 빌드된 dist/cli.js를 PATH의 bun으로 띄워 첫 화면 API가 답하는지 본다. CI는 지원 하한
# Bun으로 이것을 돈다(ci-release.md).
set -euo pipefail

cli="$(cd "$(dirname "$0")/.." && pwd)/apps/viewer/dist/cli.js"
[ -f "$cli" ] || { echo "missing $cli (run: cd apps/viewer && bun run build)" >&2; exit 1; }

work="$(mktemp -d)"
pid=""
trap '[ -n "$pid" ] && kill "$pid" 2>/dev/null; rm -rf "$work"' EXIT

# 원격을 두지 않는다. 원격이 있으면 base 해석이 `gh pr view`로 GitHub를 찾는다(e2e.md).
repo="$work/repo"
git init -q "$repo"
printf 'one\n' >"$repo/a.txt"
git -C "$repo" add a.txt
git -C "$repo" -c user.email=smoke@example.com -c user.name=smoke -c commit.gpgsign=false \
commit -q -m init
printf 'two\n' >"$repo/a.txt"

echo "bun $(bun --version)"
bun "$cli" --version

(cd "$repo" && XDG_CACHE_HOME="$work/cache" exec bun "$cli" --no-open --port 0) \
>"$work/out" 2>"$work/err" &
pid=$!

url=""
for _ in $(seq 1 100); do
url="$(grep -oE 'http://127\.0\.0\.1:[0-9]+/\?[^[:space:]]+' "$work/out" | head -n 1 || true)"
[ -n "$url" ] && break
kill -0 "$pid" 2>/dev/null || break
sleep 0.2
done
if [ -z "$url" ]; then
echo "CLI did not print a viewer URL" >&2
cat "$work/out" "$work/err" >&2
exit 1
fi

origin="${url%%/\?*}"
query="${url#*\?}"
get() { curl -fsS --max-time 30 "$@"; }
get -o /dev/null "$origin/api/ping?$query"
get -o /dev/null "$origin/api/summary?$query"
diff="$(get "$origin/api/diff?$query")"
grep -q '"a.txt"' <<<"$diff" || { echo "/api/diff has no a.txt: $diff" >&2; exit 1; }
get -o /dev/null "$url"
get -o /dev/null "$origin/main.js"
get -o /dev/null "$origin/worker.js"
echo "smoke ok"
Loading