Initial commit

This commit is contained in:
2026-10-26 12:28:48 +09:00
commit 18f10cece4
269 changed files with 33654 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
# ==========================================
# Gitea Actions 러너 설정
#
# 사용법: cp .env.example .env 후 토큰을 채운다.
# ⚠️ .env 는 커밋되지 않는다 (루트 .gitignore). 토큰을 이 예시 파일에 적지 말 것.
# ==========================================
# Gitea 인스턴스 주소 (끝에 / 없이)
GITEA_INSTANCE_URL=https://git.wandergo.net
# 등록 토큰 — 저장소 Settings → Actions → Runners → Create new Runner 에서 발급
# (여러 저장소에서 공용으로 쓰려면 관리자 화면의 인스턴스 레벨 토큰을 사용)
GITEA_RUNNER_REGISTRATION_TOKEN=
# 러너 식별 이름 — 여러 대를 띄운다면 구분되게 짓는다
RUNNER_NAME=gitea-runner
# 라벨: <워크플로의 runs-on>:docker://<잡을 실행할 이미지>
# ci.yml 이 ubuntu-latest 를 쓰므로 그대로 두면 된다.
RUNNER_LABELS=ubuntu-latest:docker://gitea/runner-images:ubuntu-latest
+103
View File
@@ -0,0 +1,103 @@
# CI 러너 설정
`.github/workflows/ci.yml` 을 실제로 실행하는 Gitea Actions 러너 설정입니다.
**러너가 없으면 워크플로는 "Waiting for a runner" 상태로 대기만 합니다.**
## 어디에 띄울 것인가
| 위치 | 장점 | 단점 |
| --- | --- | --- |
| **Gitea 서버** (권장) | 항상 켜져 있어 CI 가 늘 동작 | 서버에 Docker 필요 |
| 개발 PC | 바로 시작 가능 | PC 가 꺼지면 CI 도 멈춤 |
CI 의 목적이 "내가 없어도 검사되는 것"이므로 서버 쪽을 권장합니다.
## 설치
```bash
# 1) 저장소 Settings → Actions → Runners → Create new Runner 에서 토큰 발급
# 2) 설정 파일 준비
cd ci
cp .env.example .env # 편집기로 열어 GITEA_RUNNER_REGISTRATION_TOKEN 채우기
# 3) 기동
docker compose -f docker-compose.runner.yml --env-file .env up -d
# 4) 등록 확인
docker compose -f docker-compose.runner.yml --env-file .env logs -f runner
# "Runner registered successfully" 가 보이면 성공
```
저장소 **Settings → Actions → Runners** 에서 러너가 **Idle** 로 표시되면 준비 완료입니다.
이후 푸시하면 Actions 탭에서 실행이 시작됩니다.
## 잘 안 될 때
| 증상 | 원인 | 해결 |
| --- | --- | --- |
| 잡이 계속 대기 중 | 라벨 불일치 | `RUNNER_LABELS` 의 `ubuntu-latest` 가 워크플로 `runs-on` 과 같은지 확인 |
| `uses:` 액션 다운로드 실패 | 서버에서 github.com 접근 불가 | 방화벽 확인. 폐쇄망이면 액션 미러 필요 |
| 등록 실패 (401/404) | 토큰 만료·오타, URL 끝 `/` | 토큰 재발급, `GITEA_INSTANCE_URL` 확인 |
| 잡 시작 직후 실패 | 도커 소켓 마운트 누락 | `/var/run/docker.sock` 마운트 확인 (Windows 는 `//var/run/docker.sock`) |
| **모든 스텝이 한꺼번에 실패**(checkout 포함) | 서비스 컨테이너가 뜨지 못함 | 아래 "서비스 컨테이너" 참고 |
## 서비스 컨테이너 주의 (GitHub Actions 와 다른 점)
Gitea 러너는 잡을 **컨테이너로** 실행하고 서비스와 같은 네트워크에 붙인다.
GitHub Actions 는 잡이 VM 위에서 직접 돌기 때문에 관례가 다르다.
| | GitHub Actions | Gitea act_runner |
| --- | --- | --- |
| 서비스 접근 주소 | `localhost` + `ports` 매핑 | **서비스 이름** (`postgres:5432`) |
| `ports:` 필요 여부 | 필요 | **불필요 — 오히려 해롭다** |
`ports: - 5432:5432` 를 두면 호스트 포트를 점유하려 하는데,
개발 DB 가 이미 그 포트를 쓰고 있으면 **잡이 시작조차 못 하고 모든 스텝이 failure 로 표시된다.**
(스텝이 실패한 게 아니라 잡 준비 단계에서 죽은 것이다)
`ci.yml` 의 backend 잡은 이 규칙에 맞춰 `ports` 없이 `DB_HOST: postgres` 를 쓴다.
## 리소스 참고
워크플로는 두 개로 나뉘어 있습니다.
**`ci.yml`** — 모든 푸시·PR 에서 실행
- `backend` — postgres 서비스 컨테이너를 띄워 단위 테스트와 e2e 를 실행
- `frontend` — lint·type-check·테스트
- `error-codes-sync` — 에러 코드 생성 파일 드리프트 검사
**`ci-flutter.yml`** — **기본적으로 돌지 않는다**
Flutter 는 SDK 다운로드로 매 실행 수 분이 걸리는데, backend/frontend 만 고친 커밋에서는
검사할 것이 없다. 그래서 다음 경우에만 실행된다.
- `flutter/` 아래 파일이 바뀐 푸시·PR — **실제로 Flutter 를 쓰기 시작하면 자동으로 동작한다**
- Actions 탭의 **Run workflow** 버튼으로 수동 실행
모바일 앱을 쓰지 않는 프로젝트라면 `ci-flutter.yml` 을 지우면 된다.
> 러너는 기본적으로 잡을 **하나씩** 처리한다. 전체 시간을 줄이려면 러너를 여러 개 띄우거나
> `act_runner` 설정에서 동시 실행 수를 늘린다.
## 잡이 멈출 때
컨테이너 환경에서 잡이 간헐적으로 멈추는 경우가 있다 (CPU 0%, 네트워크 정지 상태로 진행 없음).
러너가 하나뿐이면 **멈춘 잡 하나가 이후 모든 잡을 굶긴다.**
그래서 모든 잡에 `timeout-minutes` 를 둔다. 상한에 걸리면 강제 종료되고 다음 잡으로 넘어간다.
새 잡을 추가할 때도 반드시 상한을 지정할 것.
멈춘 잡을 즉시 해제하려면 해당 컨테이너를 중지하면 된다 (러너가 실패로 처리하고 다음 잡을 집는다).
```bash
docker ps --format "{{.Names}}" | grep GITEA-ACTIONS # 실행 중인 잡 컨테이너
docker stop <컨테이너명>
```
## 주의
- **토큰은 `ci/.env` 에만** 둡니다. 이 파일은 루트 `.gitignore` 로 커밋되지 않습니다.
- `runner-data/` 에 등록 정보가 저장됩니다. 지우면 토큰으로 재등록해야 합니다.
- 러너는 도커 소켓에 접근하므로 **호스트에 대한 사실상의 관리자 권한**을 갖습니다.
신뢰할 수 있는 저장소의 워크플로만 실행되도록 하세요 (공개 저장소의 PR 실행 정책 확인).
+26
View File
@@ -0,0 +1,26 @@
# Gitea Actions 러너 — CI 를 실제로 실행하는 주체
#
# 이 파일은 애플리케이션 스택(루트 docker-compose.yml)과 **생명주기가 다르다.**
# 앱은 개발할 때만 띄우지만 러너는 항상 켜져 있어야 CI 가 동작한다.
#
# 사용법은 ci/README.md 참조.
services:
runner:
image: gitea/act_runner:latest
container_name: ${RUNNER_NAME:-gitea-runner}
restart: always
environment:
GITEA_INSTANCE_URL: ${GITEA_INSTANCE_URL}
# ⚠️ 등록 토큰 — ci/.env 에만 두고 절대 커밋하지 않는다
GITEA_RUNNER_REGISTRATION_TOKEN: ${GITEA_RUNNER_REGISTRATION_TOKEN}
GITEA_RUNNER_NAME: ${RUNNER_NAME:-gitea-runner}
# ⚠️ 워크플로의 runs-on 과 일치해야 잡을 집는다.
# .github/workflows/ci.yml 은 모든 잡이 ubuntu-latest 다.
GITEA_RUNNER_LABELS: ${RUNNER_LABELS:-ubuntu-latest:docker://gitea/runner-images:ubuntu-latest}
volumes:
# 잡을 컨테이너로 띄우므로 도커 소켓이 필요하다.
# (Windows Docker Desktop 에서 Git Bash 를 쓰면 경로 변환 때문에 //var/run/... 로 적어야 할 수 있다)
- /var/run/docker.sock:/var/run/docker.sock
# 등록 정보를 보존한다 — 지우면 토큰으로 재등록해야 한다
- ./runner-data:/data