릴리스는 지루하게 느껴져서는 안 됩니다.
@nyaomaru/changelog-bot
🤖 Git 히스토리와 릴리스 노트를 다듬어진 변경 로그 항목(그리고 선택적 PR)으로 한 번에 만들어줍니다. CI에 넣거나, 로컬에서 실행하거나, 릴리스 담당자에게 전달하세요. 어느 쪽이든 깔끔한 변경 로그와 복사-붙여넣기 피로감 제로를 경험할 수 있습니다.
자동 스토리텔링: 커밋 히스토리, PR 제목, 그리고 릴리스 노트를 결합하여 사람이 읽을 수 있는 변경 로그 섹션을 생성합니다.LLM 기능 (선택 사항): OpenAI 또는 Anthropic에 연결하여 어조를 고려한 요약을 만들거나, API 키 없이도 강력한 휴리스틱 폴백(heuristic fallback)에 의존할 수 있습니다.PR 준비 출력: 업데이트된 변경 로그가 포함된 풀 리퀘스트를 열고, 비교 링크와 릴리스 노트까지 미리 연결할 수 있습니다.안전한 기본값: 중복 버전을 감지하고, 비교 링크를 최신 상태로 유지하며, AI 서비스에 문제가 생겨도 릴리스 실패를 막아줍니다.CI 네이티브: GitHub Action, 재사용 가능한 워크플로우(reusable workflow), 또는 일반 CLI로 작동합니다. 불안정한 스크립팅이 필요 없습니다.
중요
이 프로젝트는 현재 초기 단계(v0.0.x)에 있습니다.
v1.0.0까지는 인터페이스와 동작 방식이 예고 없이 변경될 수 있습니다.
만약 프로덕션 워크플로우에 통합할 계획이라면, 예상치 못한 호환성 문제(breaking changes)를 피하기 위해 정확한 버전을 고정(pin)해 주십시오.
지금 바로 게시된 CLI를 실행하세요. 로컬 도구 준비가 필요 없습니다.
pnpm dlx @nyaomaru/changelog-bot --help
항상 사용하고 싶다면? 개발 의존성으로 추가한 후 스크립트에서 호출하거나 (pnpm exec을 통해 직접 호출할 수도 있습니다):
pnpm add -D @nyaomaru/changelog-bot
pnpm exec changelog-bot --help
CI에서 사용하려면? 드롭인 워크플로우 예제를 위해 GitHub Actions 통합 섹션으로 이동하세요.
| 옵션 | 설명 | 기본값 |
|---|
--repo-path | 저장소 루트 경로 | . |
--config | JSON 설정 파일 경로 | 존재 시 changelog-bot.config.json |
--changelog-path | CHANGELOG 파일 경로 | CHANGELOG.md |
--base-branch | PR의 기본 브랜치 | main |
--provider | LLM 제공업체 (openai, anthropic, gemini, 또는 xai) | openai |
--release-tag | 릴리스를 생성할 Git 참조 (태그 또는 HEAD) | 최신 태그 또는 HEAD |
--release-name | 버전의 표시 이름 (v 제외) | 태그에서 파생 |
--release-body | 추가 릴리스 노트 본문 | "" |
--language | 생성된 CHANGELOG 산문의 언어 | en |
--instructions | 추가적인 CHANGELOG 작성/그룹화 지침 | 설정 안 함 (unset) |
--instructions-file | 추가 지침이 담긴 파일 경로 | 설정 안 함 (unset) |
--dry-run | 업데이트된 CHANGELOG를 stdout에 출력하고 파일을 쓰지 않음 | false |
--dry-run-json-report | dry-run 제공업체 진단 결과를 JSON으로 출력 | false |
--fail-on-llm-error | 제공업체 호출 실패 시 폴백하는 대신 실패함 | false |
--require-provider | 선택된 제공업체의 API 키가 누락되면 실패함 | false |
--no-ai | 모든 제공업체 호출을 건너뛰고 결정론적 출력을 사용함 | false |
--why | PR 설명에서 짧은 WHY 메모를 추출함 | false |
--why-engine | WHY 엔진 (llm 또는 실험적인 jev) | llm |
--why-max-prs | WHY 추출을 위해 검사할 최대 PR 수 | 30 |
--why-max-chars-per-pr | PR당 전송되는 최대 후보 문자 수 | 800 |
--why-confidence | 최소 WHY 신뢰도 (low, medium, high) | medium |
--why-label | WHY 메모 앞에 렌더링되는 레이블 | Why |
pnpm dlx @nyaomaru/changelog-bot \
--release-tag HEAD \
--release-name 0.1.0-dev \
...
dry-run은 생성된 CHANGELOG 이전에 제공업체 진단 결과를 출력하여 LLM 요청이 사용되었는지 또는 실행이 폴백했는지 확인할 수 있게 합니다. --dry-run-json-report를 추가하면 해당 진단 블록을 provider, model과 함께 JSON으로 출력할 수 있습니다.
, aiUsed
,
fallbackReasons
,
그리고 프롬프트 커스터마이징 진단 항목.
pnpm dlx @nyaomaru/changelog-bot \
--release-tag vx.y.z \
--release-name x.y.z \
...
선택된 제공업체(provider)의 API 키가 설정되어 있지 않으면, CLI는 모델 호출을 건너뛰고 git 로그에서 휴리스틱 섹션을 생성하거나 (제공되는 경우 GitHub Release Notes를 사용합니다). PR 본문에는 폴백 이유(fallback reason)가 포함된 메모가 들어가므로, 모두가 해당 실행이 결정론적(deterministic)이었음을 알게 됩니다. 키가 누락되었을 때 실패하려면 --require-provider를 사용하고, 제공업체 API/스키마 오류 시 실패하려면 --fail-on-llm-error를 사용하거나, 의도적으로 제공업체 호출을 건너뛰려면 --no-ai를 사용하세요.
# env에 AI 키가 없음
pnpm dlx @nyaomaru/changelog-bot --release-tag HEAD --release-name 1.2.3
예시 PR 본문 접미사:
Note: Generated without LLM. Reason: Missing API key for provider: openai.
WHY 추출 기능은 기본적으로 비활성화되어 있습니다. 왜냐하면 PR 설명을 읽고 추가적인 제공업체 호출을 수행하기 때문입니다. 각 높은 신호(high-signal)의 변경 로그 항목에 변경 이유가 담긴 짧은 설명이 포함되기를 원할 때 이를 활성화하세요:
pnpm dlx @nyaomaru/changelog-bot \
--release-tag HEAD \
--release-name 1.2.3 \
...
WHY 노트는 Added, Changed, Fixed, 그리고 Breaking 항목에 대해서만 고려됩니다. 유지보수(Maintenance), 의존성(dependency), 문서(docs), 및 작업(chore) 항목은 건너뜁니다. PR 설명이 이유를 명확하게 설명하지 않거나, 로컬 신뢰 점수(local trust score)와 제공업체 확신도(provider confidence)가 일치하지 않으면, changelog-bot은 해당 항목에 대해 WHY 노트를 작성하지 않습니다. --fail-on-llm-error를 사용하면 제공업체 오류가 실행을 실패하게 하지만, 그렇지 않은 경우에도 주요 변경 로그는 계속 진행되며 진단 이유와 함께 WHY 추출 기능이 건너뛰어집니다.
사전 처리기(preprocessor)는 영어, 스페인어, 프랑스어, 독일어, 포르투갈어, 이탈리아어, 네덜란드어, 일본어, 중국어, 한국어, 그리고 러시아어의 일반적인 이유/맥락 섹션 제목을 인식합니다. 이것은 하드한 언어 제한이 아닌 제목 별칭 목록입니다: 다른 언어로 된 간결한 PR 설명도 여전히 제공업체의 판단에 도달할 수 있으며, 누락되거나 불분명한 증거는 추측되기보다는 여전히 생략됩니다. Description
섹션은 또한 그 산문이 이유를 명시적으로 표시하는 경우, 예를 들어 WHY:,
, because`,
, 또는 in order to로 인해 WHY 증거(evidence)를 제공할 수도 있습니다.
Jev는 옵트인 방식의 WHY 전용 엔진입니다. 이는 --provider 값이 아니며 변경 로그 자체를 생성하지 않습니다. Jev는 공급된 PR 설명 후보 각각이 이유를 명시적으로 진술하는지, 그리고 그 이유가 변경 로그 변경에 적용되는지를 독립적으로 평가한 다음, 이를 의역(paraphrasing)하지 않고 가장 강력하게 수용된 출처 텍스트를 렌더링합니다. 이로써 Jev의 비생성형 API에도 불구하고 WHY 노트는 증거 기반을 유지할 수 있습니다.
export TYPESAFE_API_KEY=ts-xxxx
pnpm dlx @nyaomaru/changelog-bot \
--release-tag HEAD \
...
TYPESAFE_MODEL은 기본값인 jev-latest를 선택적으로 재정의합니다. 이 엔진은 TypeSafe의 재시도 가능한 429 및 529 응답을 로컬 지수 백오프(exponential backoff)로 처리하며, 최대 30초까지 서버 재시도 힌트를 준수합니다. 또한 각 요청은 30초 후에 시간 초과됩니다.
--no-ai는 여전히 이 실험적 경로를 비활성화하며, TypeSafe 자격 증명이 누락되면 진단 이유와 함께 WHY 추출을 건너뜁니다.
복합 액션(composite Action)은 why-engine: jev를 수용하고; 재사용 가능한 워크플로우(reusable workflow)는 why_engine: jev를 수용합니다. 각각의 액션 단계 환경 또는 재사용 가능한 워크플로우 시크릿을 통해 TYPESAFE_API_KEY를 전달해야 합니다.
Jev는 명시적 근거 확률과 변경 관련성 확률이 모두 최소 0.50일 때만 후보를 수용합니다. 이는 두 확률 중 낮은 값을 0.50에서 low, 0.60에서 medium(기본값), 그리고 0.80에서 high로 매핑합니다. 이러한 실험적 임계값은 평가 코퍼스(evaluation corpus)가 커짐에 따라 변경될 수 있습니다.
pnpm eval:why
labeled WHY 코퍼스를 Jev와 기존 LLM 제공업체에 실행하고, 그 결과를 정밀도(precision), 재현율(recall), F1 점수, 출처-후보 보존 여부(source-candidate preservation), 사례별 선택 사항, 지연 시간(latency), 실패 횟수, 그리고 API가 보고한 토큰 사용량을 JSON 형식으로 출력합니다.
보존 측정 항목 (Preservation measures)
엔진이 원본 후보를 그대로 반환했는지 여부를 확인하는 것으로, Jev에 대한 진단 지표일 뿐 LLM이 생성한 의역(paraphrases)과의 품질 비교는 아닙니다. TYPESAFE_API_KEY와 선택된 제공업체 키를 설정하고, WHY_EVALUATION_PROVIDER 옵션으로 openai, anthropic, 또는 gemini 중 하나를 선택할 수 있으며 기본값은 openai입니다.
토큰 사용량은 각 제공업체의 현재 청구 요율과 비용 비교를 지원합니다. 러너는 모델 가격과 계정 계약이 다를 수 있으므로 통화 환산(currency)을 의도적으로 추정하지 않습니다.
Jev의 경우, 보고서에 Brier 점수, 레이블링된 긍정 및 부정 후보의 평균 확률, 그리고 실험적인 0.50, 0.60, 0.80 임계값에서의 정밀도/재현율/F1 트레이드오프가 포함됩니다. 한 사례는 각각이 유효한 출처 증거일 경우 둘 이상의 후보를 허용으로 레이블링할 수 있습니다.
해당 코퍼스는 리포지토리 PR 자료와 경계 고정값(boundary fixtures)을 포함하며, 명시적이지만 관련 없는 근거(rationale)도 포함합니다. 이는 임계값 및 관련성 변경 사항을 안내하기 위한 것이며, 어느 엔진이 프로덕션 준비가 되었음을 주장하는 것은 아닙니다.
export OPENAI_MODEL=gpt-4o-mini
export OPENAI_API_KEY=sk-xxxx
pnpm dlx @nyaomaru/changelog-bot --release-tag HEAD --release-name 1.0.0 --dry-run
pnpm dlx @nyaomaru/changelog-bot \
--release-tag HEAD \
--release-name 1.0.0 \
...
사용자 지정 지침(Custom instructions)은 누적 적용됩니다: 이 봇은 여전히 JSON 스키마, 중복 제거(deduplication), 그리고 사실성 규칙을 강제합니다.
지침 파일은 UTF-8로 읽힙니다. 인라인 지침과 파일 지침은 빈 줄로 결합된 후, 16,000자로 제한됩니다. 비어 있거나 읽을 수 없는 지침 파일은 무시됩니다. 건식 실행(Dry-run) 진단 보고서는 프롬프트 사용자 정의가 요청되었는지, 해결되었는지, 실제로 적용되었는지를 보고합니다. 사용자 정의는 제공업체 전체 생성에만 영향을 미치며, --no-ai, 누락된 제공업체 키 또는 제공업체 생성 폴백(fallback)의 경우, 사용자 지정 지침을 적용하지 않고 결정론적인 릴리스 노트/폴백 출력이 생성됩니다.
CLI에서 실행하는 디렉토리에 changelog-bot.config.json 파일을 만드세요:
{
"provider": "gemini",
"language": "nl",
...
}
그런 다음 정상적으로 실행하세요:
pnpm dlx @nyaomaru/changelog-bot --release-tag HEAD --release-name 1.0.0
CLI 플래그가 설정 파일 값을 재정의합니다. 다른 파일을 사용하려면:
pnpm dlx @nyaomaru/changelog-bot --config .github/changelog-bot.json --dry-run
설정 파일은 CLI 옵션과 일치하는 카멜케이스(camelCase) 키를 사용합니다:
repoPath, changelogPath, baseBranch, provider, releaseTag, releaseName, releaseBody, language, instructions, instructionsFile, dryRun, dryRunJsonReport, failOnLlmError, requireProvider, noAi, why, whyEngine, whyMaxPrs, whyMaxCharsPerPr, whyConfidence, 그리고 whyLabel.
알 수 없는 키는 거부되므로 오타가 발생하면 즉시 실패합니다.
클론된 환경에서 작업하는 경우? 종속성을 설치하고 CLI를 직접 실행하려면 로컬 개발 설정(Local development setup)의 단계를 따르세요.
필요한 만큼 자체 키와 토큰을 가져오세요. changelog-bot은 실제로 사용하는 것만 요청합니다.
- 환경 변수:
GITHUB_TOKEN(PR 생성에 필요하며, --dry-run에는 필요하지 않음)
- 또는 GitHub App 인증 (브랜딩 및 최소 권한 원칙에 권장):
CHANGELOG_BOT_APP_ID와 CHANGELOG_BOT_APP_PRIVATE_KEY (필수)
CHANGELOG_BOT_APP_INSTALLATION_ID (선택; 리포지토리별 자동 감지)
CHANGELOG_BOT_API_BASE (선택; GHES, 예: https://ghe.example.com/api/v3)
OPENAI_API_KEY
(optional)ANTHROPIC_API_KEY
(optional)GEMINI_API_KEY
(optional)TYPESAFE_API_KEY
(optional; required only with--why-engine jev
)
REPO_FULL_NAME
(optional,owner/repo
; used for link resolution)OPENAI_MODEL
(optional; defaults togpt-4o-mini
)ANTHROPIC_MODEL
(optional; defaults toclaude-3-5-sonnet-20240620
)GEMINI_MODEL
(optional; defaults togemini-3.5-flash
)TYPESAFE_MODEL
(optional; defaults tojev-latest
)
기본적으로, changelog-bot은 하드 실패보다 완성된 변경 로그를 선호합니다. CI에서 결정론적 대체 출력을 생성하는 대신 실패해야 하는 경우 아래의 엄격 플래그(strict flags)를 사용하세요.
| 조건 | 기본 동작 (Default behavior) | 엄격 동작 (Strict behavior) |
|---|---|
--no-ai가 설정됨 | 제공자 생성, 제목 분류 및 WHY 추출을 건너뜁니다. GitHub Release Notes 또는 휴리스틱 출력을 사용합니다. | --require-provider와 결합할 수 없습니다. |
| 선택된 제공자 키가 누락됨 | GitHub Release Notes 또는 휴리스틱 출력으로 계속 진행됩니다. | --require-provider는 생성 전에 실패합니다. |
| 제공자 생성에 실패함 | 입력이 잘린(truncated) 상태로 한 번 재시도한 후, 휴리스틱 출력으로 계속 진행됩니다. | --fail-on-llm-error는 실행을 실패하게 합니다. |
| ... | v1에서는 실패 모드가 없습니다. |
AI가 변경 로그 생성에 사용되지 않을 때, PR 본문에는 “LLM 없이 생성됨. 이유: … (Generated without LLM. Reason: …)”이라고 주석이 달립니다. 제목 분류는 제공자가 사용 가능한 경우 해당 제공자를 사용하며; 키가 없는 경우, 제목은 결정론적 로컬 카테고리로 대체됩니다.
코드 64와 65는 일반적인 POSIX sysexits 관례(EX_USAGE, EX_DATAERR)를 따릅니다. 코드 66과 67은 changelog-bot 전용 제공자 및 스키마 실패를 위해 동일한 예약 범위에 유지됩니다. 코드 1