feat: .env.example 파일에 CI 환경 설명 추가 및 config.py 수정
This commit is contained in:
55
.cursor/rules/commit-conventional-ko.mdc
Normal file
55
.cursor/rules/commit-conventional-ko.mdc
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
description: 커밋 메시지는 Conventional Commits + 한글 본문
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# 커밋 메시지 (Conventional Commits + 한글)
|
||||||
|
|
||||||
|
## 형식
|
||||||
|
|
||||||
|
- **한 줄:** `<타입>(선택 범위): <한글 설명>`
|
||||||
|
- **타입·콜론·공백 뒤 설명은 반드시 한글**로 작성한다.
|
||||||
|
- 제목은 **50자 전후**, 명령형·현재형으로 짧게 쓴다. (예: "추가함" 대신 "추가")
|
||||||
|
|
||||||
|
## 허용 타입
|
||||||
|
|
||||||
|
| 타입 | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| `feat` | 새 기능 |
|
||||||
|
| `fix` | 버그 수정 |
|
||||||
|
| `docs` | 문서만 변경 |
|
||||||
|
| `style` | 포맷·세미콜론 등, 동작 변화 없음 |
|
||||||
|
| `refactor` | 리팩터링 (기능 변화 없음) |
|
||||||
|
| `test` | 테스트 추가·수정 |
|
||||||
|
| `chore` | 빌드·설정·잡일 |
|
||||||
|
| `perf` | 성능 개선 |
|
||||||
|
| `ci` | CI 설정 |
|
||||||
|
| `build` | 빌드 시스템·의존성 |
|
||||||
|
| `revert` | 되돌리기 |
|
||||||
|
|
||||||
|
## 예시
|
||||||
|
|
||||||
|
```text
|
||||||
|
feat: 로그인 실패 시 텔레그램 알림 전송
|
||||||
|
fix: GAME_COUNT 빈 문자열일 때 기본값 적용
|
||||||
|
refactor: 설정 로드 로직을 config 모듈로 분리
|
||||||
|
docs: README에 NAS 배포 절차 추가
|
||||||
|
test: LottoBuyer 로그인 성공 케이스 mock 테스트
|
||||||
|
chore: requirements.txt 버전 고정
|
||||||
|
ci: Gitea Actions에서 Secret 기반 설정 검증
|
||||||
|
```
|
||||||
|
|
||||||
|
## 범위(선택)
|
||||||
|
|
||||||
|
- 괄호로 모듈을 짧게: `feat(lotto_buyer): 세션 만료 시 재로그인 시도`
|
||||||
|
- 필요할 때만 사용.
|
||||||
|
|
||||||
|
## 본문이 필요할 때
|
||||||
|
|
||||||
|
- 제목 다음 빈 줄 뒤 **본문도 한글**로 상세 설명.
|
||||||
|
- 푸터: `BREAKING CHANGE:` 등은 프로젝트에 필요할 때만 영문 키워드 유지 가능.
|
||||||
|
|
||||||
|
## 금지
|
||||||
|
|
||||||
|
- 타입 없이 자유 문장만 쓰기
|
||||||
|
- 제목 전체를 영어만으로 쓰기 (이 프로젝트 기본은 한글 설명)
|
||||||
55
.cursorRules
Normal file
55
.cursorRules
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
description: 커밋 메시지는 Conventional Commits + 한글 본문
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# 커밋 메시지 (Conventional Commits + 한글)
|
||||||
|
|
||||||
|
## 형식
|
||||||
|
|
||||||
|
- **한 줄:** `<타입>(선택 범위): <한글 설명>`
|
||||||
|
- **타입·콜론·공백 뒤 설명은 반드시 한글**로 작성한다.
|
||||||
|
- 제목은 **50자 전후**, 명령형·현재형으로 짧게 쓴다. (예: "추가함" 대신 "추가")
|
||||||
|
|
||||||
|
## 허용 타입
|
||||||
|
|
||||||
|
| 타입 | 용도 |
|
||||||
|
|------|------|
|
||||||
|
| `feat` | 새 기능 |
|
||||||
|
| `fix` | 버그 수정 |
|
||||||
|
| `docs` | 문서만 변경 |
|
||||||
|
| `style` | 포맷·세미콜론 등, 동작 변화 없음 |
|
||||||
|
| `refactor` | 리팩터링 (기능 변화 없음) |
|
||||||
|
| `test` | 테스트 추가·수정 |
|
||||||
|
| `chore` | 빌드·설정·잡일 |
|
||||||
|
| `perf` | 성능 개선 |
|
||||||
|
| `ci` | CI 설정 |
|
||||||
|
| `build` | 빌드 시스템·의존성 |
|
||||||
|
| `revert` | 되돌리기 |
|
||||||
|
|
||||||
|
## 예시
|
||||||
|
|
||||||
|
```text
|
||||||
|
feat: 로그인 실패 시 텔레그램 알림 전송
|
||||||
|
fix: GAME_COUNT 빈 문자열일 때 기본값 적용
|
||||||
|
refactor: 설정 로드 로직을 config 모듈로 분리
|
||||||
|
docs: README에 NAS 배포 절차 추가
|
||||||
|
test: LottoBuyer 로그인 성공 케이스 mock 테스트
|
||||||
|
chore: requirements.txt 버전 고정
|
||||||
|
ci: Gitea Actions에서 Secret 기반 설정 검증
|
||||||
|
```
|
||||||
|
|
||||||
|
## 범위(선택)
|
||||||
|
|
||||||
|
- 괄호로 모듈을 짧게: `feat(lotto_buyer): 세션 만료 시 재로그인 시도`
|
||||||
|
- 필요할 때만 사용.
|
||||||
|
|
||||||
|
## 본문이 필요할 때
|
||||||
|
|
||||||
|
- 제목 다음 빈 줄 뒤 **본문도 한글**로 상세 설명.
|
||||||
|
- 푸터: `BREAKING CHANGE:` 등은 프로젝트에 필요할 때만 영문 키워드 유지 가능.
|
||||||
|
|
||||||
|
## 금지
|
||||||
|
|
||||||
|
- 타입 없이 자유 문장만 쓰기
|
||||||
|
- 제목 전체를 영어만으로 쓰기 (이 프로젝트 기본은 한글 설명)
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# 로컬: 이 파일을 .env 로 복사 후 값 입력
|
||||||
|
# Gitea Actions: 동일 변수명을 리포지토리 Secret 으로 등록 (CI=true 일 때 .env 는 읽지 않음)
|
||||||
|
|
||||||
# 동행복권 계정 정보 (필수)
|
# 동행복권 계정 정보 (필수)
|
||||||
LOTTO_USERNAME=your_dhlottery_id
|
LOTTO_USERNAME=your_dhlottery_id
|
||||||
LOTTO_PASSWORD=your_dhlottery_password
|
LOTTO_PASSWORD=your_dhlottery_password
|
||||||
|
|||||||
40
.gitea/workflows/ci.yml
Normal file
40
.gitea/workflows/ci.yml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Gitea Actions: 리포지토리 설정 → Actions → Secrets 에 동일 이름 등록
|
||||||
|
# 로컬은 프로젝트 루트 .env, CI 는 아래 secrets.* 가 환경변수로 주입됨
|
||||||
|
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
|
||||||
|
- name: 의존성 설치
|
||||||
|
run: pip install -r requirements.txt
|
||||||
|
|
||||||
|
- name: 단위 테스트
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
run: PYTHONPATH=src python -m unittest discover -s tests -v
|
||||||
|
|
||||||
|
# PR 은 fork 등에서 Secret 이 없을 수 있어 push 일 때만 검증
|
||||||
|
- name: Secret 기반 설정 로드 검증
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
LOTTO_USERNAME: ${{ secrets.LOTTO_USERNAME }}
|
||||||
|
LOTTO_PASSWORD: ${{ secrets.LOTTO_PASSWORD }}
|
||||||
|
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
|
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||||
|
run: PYTHONPATH=src python -c "from config import load_config; load_config(); print('config: OK')"
|
||||||
@@ -12,7 +12,15 @@ class Config:
|
|||||||
TELEGRAM_CHAT_ID: str
|
TELEGRAM_CHAT_ID: str
|
||||||
|
|
||||||
|
|
||||||
|
def _is_ci_environment() -> bool:
|
||||||
|
v = os.environ.get("CI", "").strip().lower()
|
||||||
|
return v in ("true", "1", "yes")
|
||||||
|
|
||||||
|
|
||||||
def _load_dotenv_if_present() -> None:
|
def _load_dotenv_if_present() -> None:
|
||||||
|
# Gitea Actions 등 CI: Secret으로 주입된 os.environ만 사용 (.env 미로드)
|
||||||
|
if _is_ci_environment():
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
@@ -25,7 +33,8 @@ def _load_dotenv_if_present() -> None:
|
|||||||
def load_config() -> Config:
|
def load_config() -> Config:
|
||||||
_load_dotenv_if_present()
|
_load_dotenv_if_present()
|
||||||
|
|
||||||
game_count = int(os.environ.get("GAME_COUNT", "5"))
|
raw_gc = os.environ.get("GAME_COUNT", "5").strip()
|
||||||
|
game_count = int(raw_gc if raw_gc else "5")
|
||||||
if not 1 <= game_count <= 5:
|
if not 1 <= game_count <= 5:
|
||||||
raise ValueError(f"GAME_COUNT는 1~5 사이여야 합니다. 현재값: {game_count}")
|
raise ValueError(f"GAME_COUNT는 1~5 사이여야 합니다. 현재값: {game_count}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user