본문으로 건너뛰기

릴리스 자동화

Libre WebUI 릴리스는 저장소 루트에서 릴리스 스크립트로 만듭니다. 스크립트는 이전 버전 태그 이후의 실제 git 기록을 읽고, 패키지 버전을 업데이트하고, 변경 기록을 작성하고, 릴리스 검사를 실행하고, 릴리스 커밋과 버전 태그를 만듭니다. GitHub가 빌드 및 바이너리 게시 원본이며 릴리스 메타데이터와 이름 있는 artifact 링크는 프로젝트의 Forgejo 저장소로 미러링됩니다.

최초 로컬 설정

종속성을 설치하고 저장소 훅을 활성화하세요.

npm install
npm run setup-hooks

훅 설정은 다음을 구성합니다.

  • Conventional Commit 검증용 .githooks/commit-msg
  • 서식 검사용 .githooks/pre-commit
  • 로컬 커밋 메시지 템플릿인 .gitmessage

릴리스 만들기

태그를 지정할 브랜치의 깨끗한 작업 트리에서 릴리스 스크립트를 실행하세요.

# Patch release
npm run release

# Minor release
npm run release:minor

# Major release
npm run release:major

스크립트는 자동으로 다음을 수행합니다.

  1. 작업 트리가 깨끗하고 다음 로컬 태그를 사용할 수 있는지 확인합니다.
  2. 커밋, 파일, 종속성, 로케일 및 미출시 변경 기록의 증거를 수집합니다.
  3. 해당 증거에서 릴리스 노트를 생성합니다.
  4. package.json, 워크스페이스 패키지 파일, package-lock.json, Helm 차트 및 앱 버전, CHANGELOG.md를 업데이트합니다.
  5. 서식, 린트, 빌드, 테스트, 보안 감사 및 npm 게시 dry-run을 포함하는 npm run release:check를 실행합니다.
  6. 모든 검사가 통과한 뒤에만 릴리스를 커밋하고 주석이 있는 버전 태그를 만듭니다.

변경 기록 생성

파일을 변경하지 않고 다음 변경 기록 섹션을 미리 봅니다.

npm run changelog

생성된 섹션으로 CHANGELOG.md를 직접 업데이트합니다.

npm run changelog -- update

기본적으로 변경 기록 생성기는 로컬 Ollama 호환 모델에 다듬어진 초안을 요청한 뒤 수집한 git 증거와 결과를 대조해 검증할 수 있습니다. AI를 사용할 수 없거나 출력이 안전하지 않아 보이면 스크립트는 결정론적 생성기로 대체합니다.

유용한 오버라이드:

CHANGELOG_AI=0 npm run release:minor
CHANGELOG_AI_MODEL=glm-5.2:cloud npm run changelog
OLLAMA_BASE_URL=http://127.0.0.1:11434 npm run release

릴리스 푸시

릴리스 커밋과 주석이 있는 태그가 생성된 뒤 스크립트가 표시한 정확한 브랜치 커밋과 태그만 게시하세요. 프로덕션 브랜치는 태그 자동 포함을 명시적으로 끈 상태에서 Forgejo, GitHub 순으로 푸시합니다.

git -c push.followTags=false push \
https://git.kroonen.ai/libre-webui/libre-webui.git \
HEAD:refs/heads/main
git ls-remote \
https://git.kroonen.ai/libre-webui/libre-webui.git \
refs/heads/main

git -c push.followTags=false push \
https://github.com/libre-webui/libre-webui.git \
HEAD:refs/heads/main
git ls-remote \
https://github.com/libre-webui/libre-webui.git \
refs/heads/main

반환된 두 브랜치 SHA는 의도한 로컬 릴리스 커밋과 같아야 합니다. 태그를 게시하기 전에 정확히 그 커밋에 대한 필수 GitHub 워크플로가 통과할 때까지 기다리세요.

두 서비스 모두에 버전 태그가 아직 없는지 확인한 다음 그 태그 하나를 Forgejo, GitHub 순으로 푸시합니다.

git ls-remote \
https://git.kroonen.ai/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'
git ls-remote \
https://github.com/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'

git -c push.followTags=false push \
https://git.kroonen.ai/libre-webui/libre-webui.git \
refs/tags/vX.Y.Z:refs/tags/vX.Y.Z
git -c push.followTags=false push \
https://github.com/libre-webui/libre-webui.git \
refs/tags/vX.Y.Z:refs/tags/vX.Y.Z

git ls-remote \
https://git.kroonen.ai/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'
git ls-remote \
https://github.com/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'

vX.Y.Z를 릴리스 태그로 바꾸세요. 주석이 있는 태그는 태그 객체 SHA와 peeled 커밋 SHA를 모두 검증합니다. 관련 없는 로컬 태그까지 게시할 수 있는 git push --tags는 절대 사용하지 마세요.

CI 릴리스 경로

v* 태그를 푸시하면 GitHub 릴리스 워크플로가 실행됩니다. 워크플로는 다음을 수행합니다.

  • npm run release:check 실행
  • macOS, Windows 및 Linux용 Electron Artifacts 빌드
  • 일치하는 CHANGELOG.md 섹션에서 GitHub 릴리스 생성
  • 릴리스 레코드와 이름 있는 artifact 링크를 Forgejo로 미러링
  • Docker 이미지 빌드
  • 릴리스 태그와 같은 버전으로 Helm 차트 게시
  • NPM_TOKEN으로 npm 패키지 게시

태그를 지정하기 전에 같은 검사를 로컬에서 실행할 수 있습니다.

npm run release:check

Forgejo 릴리스 미러

미러는 암호화된 GitHub Actions 비밀 FORGEJO_TOKEN으로 저장된 Forgejo 개인 접근 토큰을 사용합니다. 토큰에는 write:repository 범위만 부여하고, 소유자가 libre-webui/libre-webui에 쓸 수 있는지 확인하며, 토큰을 커밋하거나 출력하지 마세요.

미러는 의도적으로 멱등성을 갖습니다. 태그로 릴리스를 조회하고 누락된 릴리스 레코드만 만들며 GitHub 릴리스 메타데이터를 맞추고 이미 존재하는 artifact 링크는 건너뜁니다. 따라서 네트워크나 워크플로 실패 후 다시 시도하면 릴리스나 자산을 중복 생성하지 않고 누락된 작업만 완료됩니다.

Forgejo 릴리스 자산은 해당 공개 GitHub browser_download_url을 가리키는 이름 있는 외부 링크입니다. GitHub가 바이너리 호스트로 유지되는 동안 Forgejo는 수십 GB의 데스크톱 Artifacts를 복제하지 않고도 같은 다운로드 파일 이름을 표시합니다. 소스 아카이브는 각 서비스에서 정확한 태그를 기준으로 독립 생성됩니다.

릴리스 하나 미리 보기 또는 채우기

Forgejo에 쓰지 않고 변경될 내용을 확인합니다.

node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z --dry-run

관리자의 비밀 관리자에서 프로세스 환경으로 FORGEJO_TOKENGITHUB_TOKEN을 불러온 뒤 해당 릴리스를 미러링합니다.

node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z

릴리스를 미러링하기 전에 정확한 태그가 GitHub와 Forgejo에 이미 존재하고 동일한 태그 객체와 peeled 커밋으로 해석되어야 합니다.

모든 릴리스 미리 보기 또는 채우기

모든 GitHub Release를 Forgejo와 대조해 감사합니다.

node scripts/mirror-forgejo-releases.mjs --all --dry-run

누락되었거나 불완전한 모든 Forgejo Release를 채웁니다.

node scripts/mirror-forgejo-releases.mjs --all

정확한 태그 일치와 자산 검색에는 GitHub 익명 API 제한보다 많은 요청이 필요하므로 dry-run을 포함한 --all에는 GITHUB_TOKEN이 필요합니다. --dry-run을 사용하지 않을 때는 FORGEJO_TOKEN도 필요합니다.

--all 경로는 두 API를 모두 페이지로 나누어 가져오며 모든 Git 태그가 아니라 GitHub Release 객체를 대상으로 합니다. 의도적으로 GitHub Release가 없는 태그는 Forgejo에서도 태그로만 남습니다. 채우기 후 dry-run을 다시 실행하면 대기 중인 변경이 없다고 보고해야 합니다.

변경 불가능한 태그 정책

게시된 버전 태그는 변경할 수 없습니다. 태그가 어느 원격에든 존재한 뒤에는 다음을 지키세요.

  • 삭제하지 않습니다.
  • 강제 푸시하지 않습니다.
  • 수정된 커밋으로 이동하지 않습니다.
  • 다른 내용에 같은 시맨틱 버전을 재사용하지 않습니다.

게시된 릴리스 내용이 잘못되었다면 소스와 변경 기록을 수정하고 다음 패치 버전을 게시하세요. 릴리스 페이지나 외부 자산 링크만 누락되었다면 태그를 건드리지 말고 멱등 미러를 다시 실행합니다.

Forgejo v0.8.6 태그는 이중 릴리스 미러링을 도입할 때 명시적으로 승인된 일회성 재정렬을 거쳤습니다. 동일한 소스 트리를 설명하지만 서로 다른 커밋 계보를 따르던 과거 태그 객체 두 개를 수정했습니다. 이 감사된 마이그레이션은 게시 태그를 옮겨도 된다는 선례가 아닙니다.

Helm 버전 정책

Helm 차트 version, 차트 appVersion, 루트 패키지 버전 및 릴리스 태그는 의도적으로 같은 시맨틱 버전을 사용합니다. 릴리스 스크립트가 함께 올리고 CI는 불일치를 거부합니다.

차트는 변경 불가능한 v* 릴리스 태그에서만 게시됩니다. 기존 차트 버전에 수정된 차트 내용을 게시하지 마세요. 차트 변경은 다음 애플리케이션 릴리스를 거쳐 새 버전을 받아야 합니다.

차트 버전 0.14.1은 해당 릴리스가 시맨틱 Docker 태그보다 앞서 나왔기 때문에 일회성 다이제스트 오버라이드를 포함합니다. 다이제스트는 검증된 다중 아키텍처 0.14.1 이미지를 식별합니다. 릴리스 스크립트는 다음 릴리스를 만들 때 이 오버라이드를 지우며, 이후 기본 이미지는 차트 appVersion으로 해석됩니다.

Docker 워크플로는 동일한 v* 릴리스 태그에서 해당 시맨틱 버전 태그를 GHCR과 Docker Hub에 게시합니다. Helm 게시 작업은 일치하는 공개 Docker Hub 이미지를 최대 20분 기다리고, 기본 이미지가 누락된 차트를 게시하는 대신 실패합니다. 번들 Ollama 이미지는 계속 독립적으로 설정할 수 있으며 기본값은 업스트림 latest 태그입니다.

Conventional Commits

커밋 메시지는 Conventional Commit 형식을 사용해야 합니다.

<type>[optional scope]: <description>

일반적인 유형:

  • feat: 사용자 대상 기능
  • fix: 버그 수정
  • docs: 문서 업데이트
  • refactor: 내부 코드 구조 변경
  • perf: 성능 개선
  • test: 테스트 범위
  • chore: 유지 관리, 릴리스 또는 빌드 작업

호환성을 깨뜨리는 변경에는 !를 사용합니다.

git commit -m "feat!: remove deprecated endpoint"
git commit -m "fix(auth)!: change token validation"

문제 해결

작업 디렉터리가 깨끗하지 않음

릴리스 전에 로컬 변경 사항을 커밋하거나 stash하세요.

git status --short
git add .
git commit -m "fix: resolve pending changes"

릴리스할 변경 사항이 없음

이전 태그 이후의 커밋을 확인합니다.

git log $(git describe --tags --abbrev=0)..HEAD --oneline

변경 기록을 직접 편집해야 함

CHANGELOG.md를 편집한 다음 태그를 게시하기 전에 수정 사항을 커밋하세요.

git add CHANGELOG.md
git commit -m "docs: refine changelog"

로컬 릴리스 커밋 롤백

릴리스 커밋과 태그가 모두 아직 푸시되지 않았다면 다음을 실행합니다.

git tag -d v0.12.0
git reset --soft HEAD~1

어느 원격에든 태그가 이미 있다면 삭제하거나 교체하지 마세요. main에서 문제를 수정하고 다음 패치 릴리스를 만든 뒤 전체 게이트를 통해 새 변경 불가능한 태그를 게시하세요.

Forgejo 미러가 불완전함

먼저 양쪽 원격의 태그 객체와 peeled 커밋 SHA가 일치하는지 확인합니다. 그런 다음 해당 릴리스를 미리 보고 다시 시도하세요.

node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z --dry-run
node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z

권한 부여 실패는 FORGEJO_TOKEN이 없거나 만료되었거나, 저장소 접근 권한이 없는 사용자가 소유하거나, write:repository 범위가 없다는 뜻입니다. 누락되었거나 다른 원격 태그는 별도로 조사해야 합니다. 릴리스 미러는 Git 태그를 만들거나 옮기지 않습니다.

관리자 파일

  • .gitmessage - 커밋 메시지 템플릿
  • .githooks/commit-msg - Conventional Commit 검증
  • .githooks/pre-commit - 서식 사전 검사
  • scripts/release.js - 릴리스 오케스트레이션
  • scripts/mirror-forgejo-releases.mjs - 멱등 Forgejo 릴리스 미러 및 채우기
  • scripts/generate-changelog.js - 변경 기록 미리 보기/업데이트 명령
  • scripts/lib/releaseNotes.js - 증거 수집 및 변경 기록 생성
  • .github/workflows/release.yml - 태그 기반 CI 릴리스 워크플로
  • .github/workflows/helm-publish.yml - Helm 검증 및 태그 게시

Conventional Commits에 대한 자세한 내용은 https://www.conventionalcommits.org/ 에서 확인하세요.