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
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
persist-credentials: false # 배포에 repo 자격증명이 필요 없다 — git config에 남기지 않는다
- uses: actions/setup-node@v4
with:
node-version: 24 # OIDC 요구: node 22.14+ / npm 11.5.1+
node-version: 24 # OIDC 요구: node 22.14+ / npm 11.5.1+ — 올리면 test.yml 매트릭스에도 반영
registry-url: https://registry.npmjs.org
# setup-node가 .npmrc에 남기는 _authToken placeholder가 OIDC 인증과 충돌할 수 있어
# Trusted Publishing을 지원하는 npm으로 고정한다(11.5.1+). id-token 권한이 있는 job이므로
Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: test
# PR 시점에 테스트를 돌린다. npm test 가 릴리스 워크플로(publish.yml)에서만 돌면
# 깨진 테스트가 배포 시점에야 발견된다 — PR 검증이 commitlint 뿐인 공백을 메운다.
on:
pull_request:
types: [opened, reopened, synchronize]
push:
branches: [main] # 각각 green 인 PR 들이 병합되며 생기는 의미 충돌을 잡는다

permissions:
contents: read

# 같은 브랜치에 연속 푸시하면 이전 실행을 취소한다
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [20, 24] # engines 하한(>=20)과 publish.yml 이 배포에 쓰는 24 양쪽에서 검증한다
steps:
- uses: actions/checkout@v4
Comment thread
coderabbitai[bot] marked this conversation as resolved.
with:
persist-credentials: false # 테스트는 repo 자격증명이 필요 없다 — git config 에 남기지 않는다
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: npm
- run: npm ci
# vitest(esbuild)·tsup 어느 쪽도 타입 검사를 하지 않아 여기서만 돈다
- run: npm run typecheck
- run: npm test
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
node_modules/
dist/
*.log
.DS_Store
# 로컬 Claude Code 세션 산출물 — 공개 저장소에 올리지 않는다
.claude/

# 로컬 산출물(세션 의도 기록·작업 노트 등)이 공개 저장소에 새지 않도록 docs/는 기본 차단하고,
# 공개할 문서가 생기면 아래에 예외를 명시해 허용한다 (rutter의 저장소 위생 규약 참조).
Expand Down
6 changes: 4 additions & 2 deletions tests/apply-cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import { parse } from 'yaml'

const FIXTURE_PKG = new URL('./fixtures/rutter-v2', import.meta.url).pathname
const CLI = join(process.cwd(), 'src/cli/index.ts')
// npx 경유가 아니라 로컬 tsx 바이너리를 직접 실행한다 (e2e.test.ts 와 같은 이유)
const TSX = join(process.cwd(), 'node_modules', '.bin', 'tsx')

let env: NodeJS.ProcessEnv
const run = (args: string[], cwd: string) =>
execFileSync('npx', ['tsx', CLI, ...args], { encoding: 'utf8', env, cwd })
execFileSync(TSX, [CLI, ...args], { encoding: 'utf8', env, cwd })
// stdout+stderr 함께 캡처 (경고는 stderr로 나간다)
const runOut = (args: string[], cwd: string): string => {
const r = spawnSync('npx', ['tsx', CLI, ...args], { encoding: 'utf8', env, cwd })
const r = spawnSync(TSX, [CLI, ...args], { encoding: 'utf8', env, cwd })
return (r.stdout ?? '') + (r.stderr ?? '')
}
const runFail = (args: string[], cwd: string): string => {
Expand Down
3 changes: 2 additions & 1 deletion tests/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { mkdtempSync, writeFileSync, mkdirSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'

const CLI = ['npx', 'tsx', 'src/cli/index.ts']
// npx 경유가 아니라 로컬 tsx 바이너리를 직접 실행한다 (e2e.test.ts 와 같은 이유)
const CLI = [join(process.cwd(), 'node_modules', '.bin', 'tsx'), 'src/cli/index.ts']
let env: NodeJS.ProcessEnv

function run(args: string[], cwd?: string): string {
Expand Down
5 changes: 4 additions & 1 deletion tests/e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import { tmpdir } from 'node:os'
import { join } from 'node:path'

let env: NodeJS.ProcessEnv
// npx 경유가 아니라 로컬 tsx 바이너리를 직접 실행한다 — 테스트 cwd 가 임시 디렉토리라
// npx 는 리포의 node_modules 를 보지 못하고 매번 네트워크에서 tsx 를 받아온다(CI 타임아웃 원인).
const TSX = join(process.cwd(), 'node_modules', '.bin', 'tsx')
const run = (args: string[], cwd: string) =>
execFileSync('npx', ['tsx', join(process.cwd(), 'src/cli/index.ts'), ...args], { encoding: 'utf8', env, cwd })
execFileSync(TSX, [join(process.cwd(), 'src/cli/index.ts'), ...args], { encoding: 'utf8', env, cwd })

beforeEach(() => {
env = { ...process.env,
Expand Down
7 changes: 7 additions & 0 deletions tests/fixtures/rutter-v2/docs/conventions/style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# 코드 스타일

## Why

일관된 스타일은 리뷰 비용을 줄인다.

- 커밋 메시지는 한글로 작성한다.
5 changes: 5 additions & 0 deletions tests/fixtures/rutter-v2/docs/maps/projects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 조직 저장소 조망

| 저장소 | 설명 |
|--------|------|
| payment-api | 결제 API |
6 changes: 4 additions & 2 deletions tests/init.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import { tmpdir } from 'node:os'
import { join } from 'node:path'

let env: NodeJS.ProcessEnv
// npx 경유가 아니라 로컬 tsx 바이너리를 직접 실행한다 (e2e.test.ts 와 같은 이유)
const TSX = join(process.cwd(), 'node_modules', '.bin', 'tsx')
const run = (args: string[], cwd: string) =>
execFileSync('npx', ['tsx', join(process.cwd(), 'src/cli/index.ts'), ...args], { encoding: 'utf8', env, cwd })
execFileSync(TSX, [join(process.cwd(), 'src/cli/index.ts'), ...args], { encoding: 'utf8', env, cwd })

function makeRutter(): string {
const r = mkdtempSync(join(tmpdir(), 'rutter-'))
Expand Down Expand Up @@ -52,7 +54,7 @@ describe('pilot init', () => {
// 않았다"는 보안 불변식(성공 로그 없음 + CLAUDE.md 없음 + config 비어있음)만 검증한다.
let stdout = ''
try {
stdout = execFileSync('npx', ['tsx', join(process.cwd(), 'src/cli/index.ts'), 'init'],
stdout = execFileSync(TSX, [join(process.cwd(), 'src/cli/index.ts'), 'init'],
{ encoding: 'utf8', env, cwd: proj, input: 'n\n' })
} catch {
// 실패 자체가 기대되는 경로 — 아래 불변식만 확인한다
Expand Down
Loading