fix(ci): 배포 검증 상태를 격리한다
All checks were successful
ci / build (push) Successful in 33s

This commit is contained in:
Yun Chan 2026-08-24 14:14:29 +09:00
parent 4d813420dc
commit cb3c323c9f
7 changed files with 54 additions and 20 deletions

View file

@ -76,14 +76,15 @@ jobs:
# 설치 -> 실행 -> 제거 왕복
sandbox="$(mktemp -d)"
state_dir="$sandbox/.designpaca-state"
cd "$sandbox"
npm init -y >/dev/null 2>&1
npm i --no-audit --no-fund --silent "$tarball"
npx --no-install designpaca --version
npx --no-install designpaca install --target claude-code --scope project --yes
env DESIGNPACA_STATE_DIR="$state_dir" npx --no-install designpaca --version
env DESIGNPACA_STATE_DIR="$state_dir" npx --no-install designpaca install --target claude-code --scope project --yes
test -f .claude/skills/designpaca/SKILL.md || { echo "설치 후 스킬이 없다" >&2; exit 1; }
npx --no-install designpaca doctor
npx --no-install designpaca uninstall --yes
env DESIGNPACA_STATE_DIR="$state_dir" npx --no-install designpaca doctor
env DESIGNPACA_STATE_DIR="$state_dir" npx --no-install designpaca uninstall --yes
test ! -f .claude/skills/designpaca/SKILL.md || { echo "제거 후에도 파일이 남았다" >&2; exit 1; }
cd / && rm -rf "$sandbox" "$tarball"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Before After
Before After

View file

@ -1,4 +1,4 @@
# E2E 시나리오 게이트 — 2026-08-24 03:41
# E2E 시나리오 게이트 — 2026-08-24 05:13
단언 1805 · 통과 1805 · 실패 0 — **GREEN — 전 단언 통과**

View file

@ -1,16 +1,16 @@
# 검증 리포트 — 2026-08-24 03:41
# 검증 리포트 — 2026-08-24 05:13
게이트: **전 계층 통과 — 배포 가능** · 총 96.1초
게이트: **전 계층 통과 — 배포 가능** · 총 103.0초
| 계층 | 결과 | 항목 | 소요 |
|---|---|---|---|
| L0-정적/stylelint | PASS | PASS — | 1.5s |
| L0-정식/html-validate | PASS | PASS — | 1.5s |
| L0-정적/stylelint | PASS | PASS — | 2.7s |
| L0-정식/html-validate | PASS | PASS — | 2.8s |
| L0-무결성/변수·경로·조판 | PASS | PASS 1 | 0.1s |
| L1-단위/계산로직 | PASS | PASS 41 | 0.0s |
| L2-기능/감사 | PASS | PASS 72 | 9.9s |
| L2-불변식/렌더 | PASS | PASS 10 | 17.2s |
| L3-시각회귀/diff | PASS | PASS 30 | 12.2s |
| L4-WebKit | PASS | PASS 8 | 3.7s |
| L5-탐색/키보드 | PASS | PASS 14 | 6.6s |
| L6-시나리오/E2E | PASS | PASS — | 43.3s |
| L2-기능/감사 | PASS | PASS 72 | 9.8s |
| L2-불변식/렌더 | PASS | PASS 10 | 16.7s |
| L3-시각회귀/diff | PASS | PASS 30 | 18.7s |
| L4-WebKit | PASS | PASS 8 | 3.8s |
| L5-탐색/키보드 | PASS | PASS 14 | 6.0s |
| L6-시나리오/E2E | PASS | PASS — | 42.3s |

View file

@ -1,17 +1,27 @@
import os from "node:os";
import path from "node:path";
/** designpaca 자체 상태 디렉터리 (~/.designpaca) */
export function stateDir(home = os.homedir()): string {
return path.join(home, ".designpaca");
/**
* CI·테스트처럼 실제 사용자 설치 기록과 분리해야 하는 실행은 전용 상태 디렉터리를 쓴다.
* 사용자 설치 경로의 기준 홈은 바꾸지 않고, designpaca 자체 상태만 격리한다.
*/
function isolatedStateDir(): string | undefined {
const dir = process.env["DESIGNPACA_STATE_DIR"]?.trim();
return dir ? path.resolve(dir) : undefined;
}
export function manifestPath(home = os.homedir()): string {
/** designpaca 자체 상태 디렉터리 (~/.designpaca) */
export function stateDir(home?: string): string {
if (home) return path.join(home, ".designpaca");
return isolatedStateDir() ?? path.join(os.homedir(), ".designpaca");
}
export function manifestPath(home?: string): string {
return path.join(stateDir(home), "manifest.json");
}
/** 업데이트 확인 캐시 */
export function updateCachePath(home = os.homedir()): string {
export function updateCachePath(home?: string): string {
return path.join(stateDir(home), "update-check.json");
}

View file

@ -0,0 +1,23 @@
import assert from "node:assert/strict";
import os from "node:os";
import path from "node:path";
import { test } from "node:test";
import { manifestPath, stateDir, updateCachePath } from "../src/paths.ts";
test("DESIGNPACA_STATE_DIR 은 사용자 홈을 바꾸지 않고 상태 파일만 격리한다", () => {
const before = process.env["DESIGNPACA_STATE_DIR"];
const isolated = path.join(os.tmpdir(), "designpaca-isolated-state");
try {
process.env["DESIGNPACA_STATE_DIR"] = isolated;
assert.equal(stateDir(), path.resolve(isolated));
assert.equal(manifestPath(), path.join(path.resolve(isolated), "manifest.json"));
assert.equal(updateCachePath(), path.join(path.resolve(isolated), "update-check.json"));
const explicitHome = path.join(os.tmpdir(), "designpaca-explicit-home");
assert.equal(stateDir(explicitHome), path.join(explicitHome, ".designpaca"));
} finally {
if (before === undefined) delete process.env["DESIGNPACA_STATE_DIR"];
else process.env["DESIGNPACA_STATE_DIR"] = before;
}
});