From be473078cc66be680206580d142ea8d50bd22f40 Mon Sep 17 00:00:00 2001 From: ttipo Date: Wed, 28 Oct 2026 22:28:12 +0900 Subject: [PATCH] =?UTF-8?q?docs(rules):=20CI=20=EB=9F=AC=EB=84=88=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=C2=B7=20CPU=20=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=ED=95=9C=EB=8F=84=20=EA=B7=9C=EC=B9=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docker 스킬에 러너의 compose 프로젝트 이름(RUNNER_NAME)과 이미지 판을, testing 규칙에 CPU 시간 한도는 지금 값의 10배쯤 둔다는 것을 적는다(CPU 시간도 부하에서 는다). Co-Authored-By: Claude Opus 5.5 --- .claude/rules/testing.md | 2 ++ .claude/skills/docker/SKILL.md | 3 +++ 2 files changed, 5 insertions(+) diff --git a/.claude/rules/testing.md b/.claude/rules/testing.md index dd685b7..802cf6e 100644 --- a/.claude/rules/testing.md +++ b/.claude/rules/testing.md @@ -14,6 +14,8 @@ description: 세 스택 공통 테스트 규칙 — 테스트 위치/네이밍, - **공유 계약은 반드시 테스트한다** — 아래 "계약 테스트" 절 참조. - **테스트는 결정적(deterministic)** 으로 — 외부 네트워크/시간/랜덤에 의존하지 않도록 모킹한다. - 성능 단언("입력이 커져도 오래 걸리지 않는다")은 **벽시계가 아니라 계산량**으로 잰다 — 프로세스 CPU 시간이나 비용 수치. + CPU 시간 한도는 **지금 값의 10배쯤** 둔다 — CPU 시간도 부하에서 는다(2026-10-28: CI 와 같은 Linux 컨테이너에서 메모리가 모자라고 테스트가 함께 돌 때 + 평소의 4~7배 — 여유가 3~6배뿐이던 한도 두 곳이 CI 를 실패시켰다). 막으려는 옛 경로(제곱 등)는 그 한도를 확실히 넘어야 한다 — 둘 사이가 좁으면 입력을 키운다. 벽시계는 다른 작업이 CPU 를 나눠 쓰면 몇 배로 늘어 CI 에서 흔들린다 (2026-10-27: 혼자 0.8초인 정화가 부하에서 9초). 비동기 결과를 기다릴 때도 고정 대기(`setTimeout(20)`) 대신 조건이 될 때까지 짧게 다시 보고 넉넉한 기한을 둔다. - **커밋 전 실행** — 변경 영역의 테스트가 통과해야 한다. ([[checklist]]) diff --git a/.claude/skills/docker/SKILL.md b/.claude/skills/docker/SKILL.md index d444d65..5446603 100644 --- a/.claude/skills/docker/SKILL.md +++ b/.claude/skills/docker/SKILL.md @@ -242,6 +242,8 @@ docker compose -f docker-compose.runner.yml --env-file .env up -d ``` - 러너가 없으면 워크플로는 **"Waiting for a runner"** 로 대기만 한다. +- compose 프로젝트 이름은 `RUNNER_NAME` 이다(`name:`) — 폴더 이름 `ci` 로 두면 같은 템플릿을 쓰는 다른 프로젝트의 러너와 겹쳐 `up` 이 그쪽 컨테이너를 다시 만든다. + 같은 PC 에 러너가 여럿이면 `RUNNER_NAME` 을 겹치지 않게 짓는다(이 저장소는 `arasystem-runner`). - `RUNNER_LABELS` 의 라벨이 워크플로의 `runs-on` 과 **일치해야** 잡을 집는다. - 러너는 도커 소켓에 접근하므로 사실상 호스트 관리자 권한을 갖는다 — 신뢰할 수 있는 워크플로만 실행되게 한다. - `ci.yml` 의 **infra 잡**(compose `config -q` · `docker build --check` · nginx 단계 `nginx -t`)은 잡 컨테이너 안에서 docker 를 쓴다. @@ -318,6 +320,7 @@ node --env-file=.env.development mail/scripts/setup.mjs | nginx (운영 frontend) | `nginxinc/nginx-unprivileged:1.30.6-alpine3.24` | `frontend/Dockerfile` 의 `FROM … AS nginx-config`, 이 문서. 1.29.3 아래로 내리지 않는다 (`add_header_inherit`) | | Stalwart (mail) | `stalwartlabs/stalwart:v0.16.27` | 루트 `.env.development.example`·`.env.production.example` 의 `MAIL_IMAGE`(각자의 로컬 `.env.*` 도), `mail/README.md` 머리말, 이 문서. `mail/scripts/setup.mjs` 는 0.16 의 관리 API·bootstrap 동작에 맞춰져 있다 — 마이너(0.17 등)를 올리면 개발에서 setup 처음 설치·재실행과 웹메일을 다시 확인한다 | | Mailpit (개발) | `axllent/mailpit:v1.32.0` | `.env.development.example` 의 `MAILPIT_IMAGE` | + | CI 러너 | `gitea/act_runner:0.6.1` | `ci/docker-compose.runner.yml`. 잡 이미지(`RUNNER_LABELS` 의 `gitea/runner-images:ubuntu-latest`)는 각자의 `ci/.env` 값이라 아직 떠 있는 태그다 | - **갱신 규칙**(공통): 일반 패치는 **배포 후 2주가 지나면** 올린다 (공급망 위험 — 갓 나온 버전을 피한다). **보안 릴리스는 CI 가 통과하는 대로** 올린다. 새 태그가 있는지와 digest 는 `docker buildx imagetools inspect <이미지>:<태그>` 로 확인한다 (2026-10-27: Stalwart `v0.16`·`v0.16.27`, nginx `stable-alpine`·`1.30.6-alpine3.24` 가 각각 같은 digest).