- src/dist 산출물 분리 원칙 정리(.gitignore, .gitattributes) - 루트 및 주요 폴더(config/scripts/prompts/tests/src, 런타임 폴더 5종)에 안내용 README.md 추가 - CHANGELOG.md, LICENSE, docs/ops/05-release-and-versioning.md 추가 - docs/README.md 문서 지도 갱신
4.9 KiB
05. 릴리스와 버전 관리
이 문서는 버전 번호·git 태그·릴리스 절차의 정본이다. "몇 버전을 언제 어떻게 배포하는가"는 여기서 결정한다. 배포판을 실제로 만드는 절차(원드라이브 zip 등 수동 전달)의 실측 로그는
docs/HANDOFF.md에 있다.
1. 버전 번호 — Semantic Versioning
pyproject.toml의 [project].version이 유일한 버전 정본이다. 형식은 MAJOR.MINOR.PATCH.
| 자리 | 올리는 경우 |
|---|---|
MAJOR |
설정 파일 스키마·CLI 인자·DB 스키마 등 하위 호환을 깨는 변경 |
MINOR |
하위 호환을 유지하며 기능을 추가(새 시트, 새 알림 채널, 새 CLI 서브커맨드 등) |
PATCH |
버그 수정, 문서 정리, 리팩터링 등 사용자에게 보이는 동작 변화가 없는 변경 |
0.y.z 동안은(1.0.0 이전) 아직 안정 API 이전이므로 MINOR도 하위 호환을 깰 수 있다.
2. 릴리스 절차
1. CHANGELOG.md의 [Unreleased] 섹션을 확정 버전으로 승격
- 헤더를 `## [X.Y.Z] - YYYY-MM-DD`로 바꾼다
- 문서 하단 비교 링크(compare/... , releases/tag/...)를 갱신한다
2. pyproject.toml의 version = "X.Y.Z" 를 갱신
3. 필수 smoke 실행 (AGENTS.md §3)
.\.venv\Scripts\python.exe -m compileall -q src tests
.\.venv\Scripts\python.exe -m dmf_crawler --help
.\.venv\Scripts\python.exe -m dmf_crawler doctor --json
.\.venv\Scripts\python.exe -m pytest tests -q
4. (선택) 배포용 빌드 산출물 생성 — §3 참고
5. 커밋: "release: vX.Y.Z"
6. 태그: git tag -a vX.Y.Z -m "vX.Y.Z"
7. 푸시: git push origin main --follow-tags
8. git.chanpaca.net 웹에서 Releases → 해당 태그로 릴리스 노트 작성
(본문은 CHANGELOG.md의 해당 버전 섹션을 그대로 옮긴다)
태그 이름은 항상 v 접두어를 붙인다(v0.1.0, v1.2.0). pyproject.toml의 버전 문자열에는
v를 붙이지 않는다.
3. 빌드 산출물 (dist/) — src/와의 구분
이 저장소는 소스와 빌드 산출물을 엄격히 분리한다.
| 디렉터리 | 내용 | git 추적 여부 |
|---|---|---|
src/dmf_crawler/ |
사람이 직접 편집하는 유일한 소스. 여기가 정본이다 | 추적함 |
dist/ |
python -m build 등이 만들어내는 sdist(.tar.gz)·wheel(.whl) |
추적 안 함(.gitignore) |
build/ |
setuptools가 빌드 중 쓰는 임시 작업 디렉터리 | 추적 안 함 |
*.egg-info/ |
패키지 메타데이터 캐시 | 추적 안 함 |
dist/는 항상 src/에서 재생성 가능해야 한다. dist/ 안의 파일을 손으로 고쳐서는 안 된다
(고칠 게 있으면 src/를 고치고 다시 빌드한다). 그래서 저장소에 커밋하지 않는다 — 커밋하면
"소스와 다른 빌드 산출물이 정본 행세를 하는" 사고가 난다.
빌드 확인 절차:
.\.venv\Scripts\python.exe -m pip install --upgrade build
.\.venv\Scripts\python.exe -m build # dist/dmf_crawler-X.Y.Z-py3-none-any.whl + .tar.gz 생성
.\.venv\Scripts\python.exe -m pip install --force-reinstall dist\dmf_crawler-*.whl
.\.venv\Scripts\python.exe -m dmf_crawler --help
이 프로그램은 PyPI에 올리지 않는다(pyproject.toml의 Private :: Do Not Upload 분류자).
dist/의 wheel은 다른 PC에 수동 배포할 때만 쓴다. 일반 사용자 배포는 bootstrap.cmd +
저장소 zip 방식을 쓴다(§4).
4. 최종 사용자 배포판 (zip)
이 프로그램은 개발자가 아닌 사용자가 쓴다(AGENTS.md, README.md 참고). PyPI/wheel 설치가
아니라 저장소를 그대로 zip으로 압축해 전달하는 방식을 쓴다. 실제 배포 사례와 포함/제외
감사 체크리스트는 docs/HANDOFF.md의 "릴리즈 배포본 생성 완료" 절을 참고한다.
핵심 원칙만 요약한다:
- 포함:
bootstrap.cmd,README.md,LICENSE,pyproject.toml,src/,config/,scripts/,prompts/,docs/(필요한 만큼). - 제외:
.venv/,data/,logs/,reports/,backup/,state/,tests/,__pycache__/,*.pyc,*.lnk,config.local.toml,service_key*,*oauth-token*. - 압축 해제 후
bootstrap.cmd가 정상 동작하는지 새 폴더에서 재현 검증한다.
5. 원격 저장소
정본 원격은 git.chanpaca.net(공개 저장소, Forgejo)이다.
git remote -v
# origin ssh://git@git.chanpaca.net:2222/yunchan/DMF_Crawler.git
이 저장소는 **공개(public)**다. 그래서 커밋 전 다음을 반드시 확인한다(AGENTS.md §6와 동일):
- API 키·OAuth 토큰·웹훅 URL·비밀번호가 코드·설정·로그·문서 어디에도 평문으로 없는가
config/config.local.toml,*.sqlite3,data/,logs/,reports/,backup/,state/가.gitignore로 실제로 제외되는가 (git status로 커밋 전 매번 확인)- 실제 수집 데이터(엑셀·DB)가 우연히 스테이징되지 않았는가