| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- Android WebView
- Android 12 대응
- Kotlin FCM
- Android Jetpack
- 66챌린지
- 안드로이드
- 알고리즘 자바
- 습관만들기
- Kotlin
- DataBinding
- 프로그래머스 알고리즘
- 안드로이드 갤러리 접근
- Android ProgressBar
- android recyclerview
- Android 12
- OkHttp Interceptor
- 카카오 알고리즘
- 코틀린 코루틴
- 안드로이드 카카오 로그인
- MVP Architecture
- WebView
- Android Interceptor
- scope function
- Android
- Java
- 영어공부
- Android ViewPager2
- Android Navigation
- coroutine
- 영어독립365
- Today
- Total
주맨의 개발노트
[CD] Release Drafter로 릴리즈 노트 자동화 본문
프로젝트에는 이미 CI가 갖춰져 있었습니다. PR이 develop 브랜치에 병합되면 빌드와 테스트가 자동으로 실행되는 환경이었습니다.
다음 단계는 CD였습니다. Firebase App Distribution으로 앱 빌드를 자동 배포하는 파이프라인을 준비하면서, 자연스럽게 릴리즈 노트를 어떻게 만들 것인지가 문제로 올라왔습니다.
배포 자체는 자동화하는데, 매번 릴리즈 노트만 사람이 손으로 정리해야 한다면 자동화 흐름이 어색해집니다. 특히 저희 프로젝트는 PR 라벨을 이미 비교적 일관되게 붙이고 있었기 때문에, 이 라벨을 기준으로 변경사항을 자동 분류할 수 있지 않을까 생각했습니다.
그 과정에서 GitHub Actions 마켓플레이스의 오픈소스 액션인 release-drafter/release-drafter를 적용해봤습니다. 이 글은 CD를 본격적으로 붙이기 전에, 릴리즈 노트 자동화를 먼저 준비한 경험을 정리한 글입니다.
왜 릴리즈 노트 자동화가 필요했나
Firebase App Distribution은 앱을 배포할 때 릴리즈 노트를 함께 전달할 수 있습니다. QA를 진행하는 입장에서는 이번 빌드에 어떤 변경이 들어갔는지 바로 확인할 수 있기 때문에 중요한 정보입니다.
문제는 이 릴리즈 노트를 수동으로 만들 때 발생합니다. 배포 직전에 지난 PR 목록을 열어보고, 어떤 기능이 추가됐는지, 어떤 버그가 수정됐는지, 내부 작업은 어디까지 포함할지 다시 정리해야 합니다.
배포 시점마다 병합된 PR을 다시 확인하고 릴리즈 노트를 작성해야 합니다. PR이 많아질수록 누락과 중복이 생기기 쉽습니다.
PR이 병합될 때마다 Draft Release에 변경사항을 쌓아둡니다. 배포 시점에는 이미 정리된 내용을 가져오면 됩니다.
릴리즈 노트 자동화는 단순히 글을 대신 써주는 기능이 아니었습니다. PR을 만들 때 붙인 라벨과 배포 시점의 커뮤니케이션을 연결하는 작은 파이프라인에 가까웠습니다.
GitHub Release와 Draft Release
Release Drafter를 이해하려면 먼저 GitHub Release와 Draft Release를 구분할 필요가 있습니다.
GitHub Release는 특정 태그와 설명을 묶어서 공개하는 GitHub의 기능입니다. 예를 들어 v1.2.0이라는 태그에 어떤 기능이 추가됐고 어떤 문제가 수정됐는지 기록할 수 있습니다.
Release에는 크게 두 가지 상태가 있습니다.
| 상태 | 의미 | 사용 시점 |
|---|---|---|
| Draft | 아직 공개되지 않은 릴리즈 초안입니다. | 변경사항을 미리 쌓고 검토할 때 사용합니다. |
| Published | 외부에 공개된 릴리즈입니다. | 실제 릴리즈 시점에 공개합니다. |
중요한 점은 Draft Release가 공개 결과물이 아니라는 것입니다. 당장 릴리즈하지 않더라도 변경사항을 미리 쌓아둘 수 있고, 릴리즈 타이밍이 왔을 때 내용을 확인한 뒤 Publish할 수 있습니다.
Release Drafter는 이 Draft Release를 PR 병합 시점마다 자동으로 생성하거나 업데이트해주는 역할을 합니다.
Release Drafter의 동작 방식
Release Drafter는 GitHub Actions 위에서 실행됩니다. PR이 특정 브랜치에 병합되면 마지막으로 공개된 Release 이후의 PR을 확인하고, 라벨을 기준으로 변경사항을 분류한 뒤 Draft Release를 갱신합니다.
feat, fix, design 같은 라벨을 붙입니다.develop 브랜치에 병합됩니다.여기서 핵심은 Release Drafter가 커밋 메시지를 해석하는 도구가 아니라는 점입니다. 제가 구성한 방식에서는 PR 라벨이 분류 기준이 됩니다. 따라서 라벨 컨벤션이 곧 릴리즈 노트 컨벤션이 됩니다.
설정에 필요한 파일은 두 개
Release Drafter를 적용하기 위해 필요한 파일은 두 개였습니다. 하나는 언제 액션을 실행할지 정하는 GitHub Actions 워크플로우이고, 다른 하나는 릴리즈 노트를 어떤 형식으로 만들지 정하는 설정 파일입니다.
| 파일 | 역할 |
|---|---|
.github/workflows/release-drafter.yml |
Release Drafter를 언제 실행할지 정의합니다. |
.github/release-drafter.yml |
라벨 분류, 버전 계산, 릴리즈 노트 템플릿을 정의합니다. |
워크플로우 파일
먼저 GitHub Actions 워크플로우를 추가했습니다. develop 브랜치에 push가 발생했을 때 실행되도록 했고, 필요할 때 수동으로 실행할 수 있도록 workflow_dispatch도 함께 열어두었습니다.
name: Release Drafter
on:
push:
branches:
- develop
workflow_dispatch:
jobs:
update_release_draft:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: read
steps:
- uses: release-drafter/release-drafter@v7
with:
config-name: release-drafter.yml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR 병합은 결국 대상 브랜치에 새로운 커밋이 들어오는 일이기 때문에 push 트리거를 사용했습니다. 저희 프로젝트에서는 develop 브랜치를 기준으로 다음 배포 후보를 만들고 있었기 때문에 해당 브랜치만 대상으로 잡았습니다.
이 워크플로우에는 actions/checkout이 없습니다. Release Drafter는 저장소 코드를 읽어서 빌드하는 액션이 아니라, GitHub API를 통해 PR과 라벨을 조회하고 Release를 수정하는 액션이기 때문입니다.
권한은 최소한으로 열었습니다. Draft Release를 생성하고 수정하려면 contents: write가 필요하고, 병합된 PR의 라벨을 읽으려면 pull-requests: read가 필요합니다.
Release Drafter 설정 파일
다음은 실제 릴리즈 노트 형식을 정의하는 설정 파일입니다. 라벨을 어떤 카테고리로 묶을지, 어떤 라벨이 버전을 올릴지, PR 한 줄을 어떤 형식으로 표시할지를 여기서 정합니다.
name-template: 'v$RESOLVED_VERSION'
tag-template: 'v$RESOLVED_VERSION'
categories:
- title: '새 기능'
labels:
- 'feat'
- 'feature'
- title: '버그 수정'
labels:
- 'fix'
- 'bug'
- title: '디자인 변경'
labels:
- 'design'
- 'ui'
- title: '내부 작업'
labels:
- 'chore'
- 'refactor'
- 'ci'
- 'test'
- 'docs'
exclude-labels:
- 'skip-changelog'
version-resolver:
major:
labels:
- 'breaking-change'
minor:
labels:
- 'feat'
- 'feature'
default: patch
change-template: "- $TITLE @$AUTHOR (#$NUMBER)"
change-title-escapes: '\<*_&'
no-changes-template: '변경사항 없음'
template: |
## 변경사항
$CHANGES
설정 키가 많아 보이지만, 실제로 중요한 축은 세 가지였습니다. 라벨을 릴리즈 노트 섹션으로 묶는 것, 라벨을 기준으로 버전을 계산하는 것, PR 한 줄의 출력 형식을 정하는 것입니다.
categories
PR 라벨을 기준으로 변경사항을 섹션별로 묶습니다. feat 라벨은 새 기능, fix 라벨은 버그 수정처럼 분류됩니다.
version-resolver
라벨을 보고 다음 버전이 major, minor, patch 중 어디로 올라갈지 계산합니다. 여러 라벨이 섞이면 더 큰 변경 단위가 선택됩니다.
change-template와 template
릴리즈 노트 전체 형식과 PR 한 줄의 출력 형식을 정합니다. PR 제목, 작성자, 번호를 변수로 치환할 수 있습니다.
PR 라벨이 릴리즈 노트의 기준이 된다
Release Drafter는 라벨을 기반으로 동작합니다. 그래서 액션 설정만큼이나 중요한 것이 팀의 라벨 컨벤션입니다.
제가 진행한 프로젝트에서는 다음과 같은 기준으로 라벨을 사용했습니다.
| 라벨 | 용도 | 버전 영향 |
|---|---|---|
skip-changelog |
릴리즈 노트에서 제외합니다. | 없음 |
feat, feature |
새 기능을 추가한 PR입니다. | minor |
fix, bug |
버그를 수정한 PR입니다. | patch |
design, ui |
UI 또는 디자인 변경입니다. | patch |
chore, refactor, ci, test, docs |
내부 작업 또는 유지보수성 개선입니다. | patch |
breaking-change |
하위 호환이 깨지는 변경입니다. | major |
라벨이 없는 PR은 어느 카테고리에도 들어가지 않을 수 있습니다. 즉, Release Drafter를 도입했다는 사실만으로 릴리즈 노트 품질이 자동으로 좋아지지는 않습니다.
PR을 만들고 리뷰하는 과정에서 라벨을 제대로 붙이는 습관이 같이 필요합니다. 자동화 도구는 팀의 습관을 대체한다기보다, 이미 정해둔 습관을 배포 흐름까지 이어주는 역할에 가깝습니다.
결과물은 어떻게 보이나
위 설정이 적용되면 Release Drafter는 Draft Release 본문을 다음과 같은 형태로 만들어줍니다. PR이 병합될 때마다 해당 내용이 다시 계산되어 업데이트됩니다.
## 변경사항
### 새 기능
- 위시리스트 생성 기능 추가 @Jooman-Lee (#38)
### 버그 수정
- 로그인 크래시 수정 @Jooman-Lee (#41)
### 내부 작업
- CI Node.js 업그레이드 @Jooman-Lee (#39)
이 단계에서는 아직 실제 CD가 완성된 것은 아닙니다. 하지만 배포 시점에 사용할 릴리즈 노트가 GitHub Draft Release에 계속 누적되는 기반은 만들어졌습니다.
이후 CD 파이프라인에서 이 Draft Release의 내용을 읽어 Firebase App Distribution의 릴리즈 노트로 전달하면, PR 병합부터 QA 배포 노트까지 자연스럽게 이어지는 흐름을 만들 수 있습니다.
도입하면서 좋았던 점
가장 좋았던 점은 릴리즈 노트를 배포 직전에 몰아서 작성하지 않아도 된다는 점이었습니다. PR이 병합될 때마다 변경사항이 Draft Release에 반영되기 때문에, 배포 시점에는 이미 누적된 내용을 확인하면 됩니다.
또한 릴리즈 노트가 PR 라벨을 기준으로 분류되기 때문에 팀이 어떤 종류의 변경을 하고 있는지도 더 잘 드러났습니다. 새 기능, 버그 수정, 내부 작업이 한 곳에 섞이지 않고 섹션별로 나뉘어 보이는 것만으로도 확인 비용이 줄었습니다.
Release Drafter의 가장 큰 장점은 릴리즈 노트를 "배포 직전의 별도 작업"이 아니라 "PR 병합 과정의 결과물"로 바꿔준다는 점이었습니다.
CD를 도입하기 전 단계에서 이 기반을 먼저 만들어둔 것도 좋았습니다. 배포 자동화를 붙인 뒤 릴리즈 노트 문제를 다시 고민하는 것보다, 릴리즈 노트가 쌓이는 구조를 먼저 만들어두는 편이 이후 파이프라인을 설계하기 쉬웠습니다.
아쉬웠던 점
아쉬운 점도 있었습니다. 가장 불편했던 부분은 설정 파일의 오류를 로컬에서 바로 확인하기 어렵다는 점이었습니다.
Release Drafter는 GitHub Actions 위에서 실행되기 때문에 설정 파일을 잘못 작성했는지 확인하려면 실제 워크플로우를 실행해봐야 했습니다. 설정을 조금 바꾸고, 머지한 뒤, Action 로그에서 config 파싱 에러를 확인하는 흐름은 빠르게 피드백을 받기 어렵습니다.
Release Drafter에는 dry-run 옵션이 있습니다. Draft Release를 실제로 수정하지 않고 로그만 확인할 수 있다는 점은 도움이 됩니다. 하지만 이 역시 GitHub Actions에서 실행해야 한다는 전제는 같습니다.
설정 파일 오류를 로컬에서 바로 확인하기 어려웠습니다. 작은 설정 변경도 Actions 실행 로그를 확인해야 했습니다.
workflow_dispatch와 dry-run을 활용하면 실제 Draft Release 수정 없이 설정 결과를 확인할 수 있습니다.
또 하나는 라벨 의존성입니다. Release Drafter는 라벨을 보고 분류할 뿐입니다. 팀원 중 한 명이라도 라벨을 빠뜨리면 해당 PR은 기대한 섹션에 들어가지 않습니다.
그래서 Release Drafter만 도입하고 끝내기보다, PR 템플릿이나 리뷰 체크 과정에서 라벨을 확인하는 습관을 함께 만드는 것이 필요하다고 느꼈습니다.
정리하며
Release Drafter는 거창한 CD 도구는 아닙니다. 빌드를 만들거나 앱을 배포해주지는 않습니다. 대신 배포 자동화에서 자주 비어 있는 한 부분, 릴리즈 노트 생성을 안정적으로 채워줍니다.
저에게는 CD를 도입하기 전에 적용해보기 좋은 자동화였습니다. PR 라벨이라는 이미 존재하던 팀의 작업 흔적을 Draft Release로 연결해주었고, 이후 Firebase App Distribution 배포 노트로 확장할 수 있는 기반을 만들 수 있었습니다.
다만 자동화의 품질은 결국 라벨 컨벤션에 달려 있었습니다. 도구는 라벨을 읽고 정리해줄 뿐이고, 어떤 라벨을 붙일지 결정하고 꾸준히 지키는 것은 팀의 몫이었습니다.
- Release Drafter는 PR 병합 시점마다 GitHub Draft Release를 자동으로 생성하거나 업데이트합니다.
- 릴리즈 노트 기준은 PR 라벨입니다. 라벨 컨벤션이 곧 릴리즈 노트 컨벤션이 됩니다.
- 설정 파일은 두 개입니다. 워크플로우 파일은 실행 시점을, 설정 파일은 분류와 출력 형식을 담당합니다.
- CD 전 단계에서도 유용합니다. 배포 자동화를 붙이기 전에 릴리즈 노트가 누적되는 기반을 만들 수 있습니다.
- 도구보다 습관이 중요합니다. 라벨을 빠뜨리면 자동화된 릴리즈 노트도 누락될 수 있습니다.
'Git' 카테고리의 다른 글
| [Git] git stash란 (0) | 2022.10.17 |
|---|