소개
이번 시간에는 깃허브를 제대로 활용할 수 있는, 이슈 & PR 자동화 스크립트를 알려드리고자 합니다.
깃허브를 사용하고 계신 분들은 대부분 아실 개념들일 텐데요, PR이 merge 되면 관련 이슈가 자동으로 닫히도록 하는 것에 중점을 두겠습니다.
Issue
깃허브에서 이슈 (Issue)란, 모든 종류의 문제를 의미합니다. 예시로 Spring AI의 이슈를 보면 아래와 같이 여러 개가 있습니다.
깃허브의 공식 문서에서는 이슈를 다음과 같이 설명하고 있습니다.
GitHub Issue란?
우리 모두는 우리의 작업을 계획하고, 문제를 추적하고, 우리가 구축하는 것들을 논의할 수 있는 방법이 필요합니다. 이 보편적인 질문에 대한 우리의 대답은 깃허브 이슈이며, 그것은 모든 저장소에 내장되어 있습니다. 깃허브의 이슈 추적은 우리가 단순성, 참조 및 우아한 형식에 초점을 맞추고 있기 때문에 독특합니다.
GitHub Issue를 사용하면 GitHub Flavored Markdown으로 아이디어를 표현하고 기여자를 할당 및 언급하며 이모지로 반응하고 첨부 파일 및 비디오로 명확화 하며 커밋, 풀 요청 및 배포와 같은 참조 코드를 사용할 수 있습니다. 작업 목록을 사용하면 큰 문제를 작업으로 나누고 마일스톤과 레이블로 작업을 더 구성하고 관계와 종속성을 추적할 수 있습니다.
우리는 개발자들을 위해 깃허브 이슈를 만들었습니다. 그것은 단순하고, 적응할 수 있으며, 강력합니다.
Pull Request
다음으로는 PR (Pull Request)에 대해 알아보겠습니다.
직역하면 Pull을 요청 (Request)하는 행위입니다. 깃허브에서 Pull이란, 코드를 내려받는 것을 뜻합니다. 로컬 컴퓨터에서 커밋하고 보내는 것을 Push라 하는데, 메인 저장소의 입장에서 나의 로컬 저장소의 변경 내역을 내려받도록 요청하는 것이기 때문에 Pull Request라 합니다.
위 그림에서 브랜치 (branch)가 나오는데요, 브랜치란 협업 과정에서의 충돌을 방지하기 위해 깃허브에서 제공하는 분기점이라고 할 수 있습니다.
왜 Pull Request 요청이 필요할까?
Pull Request 요청 없이, 바로 메인 저장소에 변경 내역이 들어가도록 하면 안 되는 것일까요?
사실 협업하지 않고 혼자 공부하는 경우에는 무조건 Pull Request를 할 필요는 없습니다. 메인 브랜치에 바로 적용되도록 할 수도 있죠.
그러나 협업을 하거나 실제 돌아가는 서비스 (ex: Spring AI 등)에 자신이 작업을 제출할 때는, 자신이 작업한 내역이 제대로 돌아가고 있는지, 기존 파일들과 충돌되지는 않는지, 버그는 없는지, 다른 사람들이 나의 변경 내역을 제대로 이해하고 있는지 등의 과정을 반드시 거쳐야 합니다.
깃허브의 공식 문서에서는 PR을 다음과 같이 설명하고 있습니다.
풀 요청(pull request)은 한 브랜치에서 다른 브랜치로 변경 사항 집합을 병합하는 제안입니다. 풀 요청에서 공동 작업자는 메인 코드베이스에 변경 사항을 통합하기 전에 제안된 변경 사항 집합을 검토하고 논의할 수 있습니다. 풀 요청은 소스 브랜치의 내용과 대상 브랜치의 내용 간의 차이 또는 차이를 표시합니다.
따라서 정리하자면, 어떤 문제가 있었기 때문에 (Issue), 나의 컴퓨터에서 작업을 했고, 이것을 메인에 반영하고 싶다 (Pull Request)고 요청하는 행위가 바로 Issue와 Pull Request라고 할 수 있습니다.
브랜치 병합 전 PR 요청 설정 방법
앞서 메인 브랜치에 반영되기 전에는 PR이 반영되도록 하는 게 좋다고 했습니다. 그러나 보통 브랜치 설정으로 가보면, PR 없이 바로 병합이 가능하도록 되어 있는 경우가 있습니다.
이를 방지하기 위해서 브랜치 보호 전략 (branch protection rules)을 세울 수 있고, 이 과정에서 PR이 필수로 되게끔 설정할 수도 있습니다.
브랜치 보호 전략에 대해서는 해당 글을 작성한 분께서 잘 정리해 놓으셨으니 이곳을 참고해 주시면 될 것 같습니다. 저는 해당 글을 참고하여 아래처럼 설정했습니다.
- merge 전 반드시 Pull Request가 필요하도록 설정하였습니다.
- 승인이 최소 1명 이상 필요하게 설정하였습니다.
- 대화 (conversation)가 모두 해결이 되어야 merge 되도록 설정하였습니다. PR이 올려지면 서로 대화 (코드 리뷰)가 오고 가는데, 이때 협업자들이 변경 요청을 하는 경우가 있습니다. 이러한 것들이 모두 해결되어야 합니다.
- 본 브랜치 보호 전략은 main 브랜치에 적용됩니다.
Pull Request 예시 (Issue 생성 X)
테스트 계정을 만들고, 연습할 수 있는 리포지터리를 만든 뒤 실습을 진행해 봤습니다.
Pull Request 생성
간단한 Pull Request를 보내니 아래와 같이 리뷰어가 필요하다고 나옵니다. (No reviews - at least 1 approving review is required)
Reviewers 텍스트를 누르면, Collaborator 중 리뷰어를 선택할 수 있습니다. 제 본 계정에게 할당하겠습니다.
그럼 이제 위 사진처럼 Pull Request가 오픈됩니다.
- feat/test에서 main으로 요청을 합니다. main 브랜치에 대한 브랜치 보호 전략에 따라, direct merge가 불가능합니다.
- 1명 이상의 승인된 리뷰가 필요합니다.
- 할당된 리뷰어는 메일로 PR 소식을 받게 됩니다.
- 1️⃣: 리뷰를 시작할 수 있습니다.
- 2️⃣: 브랜치 보호 전략의 충족 조건을 무시한 채 바로 merge시킬 수 있습니다. 만약 이것조차 막고 싶다면, 브랜치 보호 전략에서 Do not allow bypassing the above settings를 활성화하면 됩니다.
Pull Request 리뷰
이제 리뷰 과정을 보겠습니다.
- 코드 옆 플러스 버튼을 누르면, 그 위치에서 리뷰를 남길 수 있습니다.
- Add single comment는 단순 댓글을 의미합니다.
- Start a review는 리뷰로 남길만한 내용을 작성할 수 있음을 의미합니다. (general feedback, approve, request changes)
- 우측 Review Changes를 누르면 Comment / Approve / Request changes를 선택할 수 있습니다. 각각 단순 리뷰 / 승인 / 요청 요구로 사용하실 수 있습니다.
여담으로 각 파일에는 이렇게 Viewed 버튼이 있는데, 파일이 매우 많은 경우에는 파일마다 리뷰가 끝난 뒤 Viewed 체크 표시를 해 두면 파일 변경 내역이 접혀서 들어갑니다. 다른 파일들과 헷갈리지 않게 되어 이 점도 유용한 것 같습니다.
리뷰가 완료되면, 아래와 같이 변경이 필요하다고 나옵니다.
Pull Request 리뷰 내용 반영
리뷰 내용에 따라 수정을 하였습니다. 이제 다시 커밋하고 푸시하였습니다.
간혹 변경이 생겼으니 기존 PR을 닫고 새롭게 PR을 열어야 하나? 라는 생각을 하는 분들이 계신데, 개인적으로는 추천드리지 않습니다.
Pull Request는 자신의 작업물이 반영되기를 요구하는 과정이며, 그 과정에서는 코드 리뷰가 들어갑니다.
그러나 수정이 될 때 마다 PR을 닫고 다시 만든다면, 리뷰의 과정이 의미 없어지게 된다고 생각합니다. 생각이 다르거나 잘못된 점을 수정해 나가는 과정에서 오고 가는 대화 (conversation)들이 하나의 PR에 보존되어야, 진정한 의미가 있다고 생각합니다.
이제 리뷰어는 이렇게 변경된 것에 대해서 Approve를 제출하면 됩니다.
그럼 이제 아래처럼 나오게 됩니다.
그런데 아직 merge가 불가능하네요. 이는 모든 conversation이 solve 된 상태여야만 가능하게끔 허용했기 때문입니다. 만약 필요한 최소 Approve만 받은 다음 merge가 가능하게 하고 싶으신 분들은 브랜치 보호 전략에서 Require conversation resolution before merging 옵션을 off 하시면 됩니다. (그게 아닌 분들은 모든 대화 내역에서 Resolve conversation을 하시면 됩니다.)
Pull Request 병합
이제 merge를 할 수 있습니다.
- Create a merge commit: 지금까지 기여자가 작업했던 모든 커밋이 전부 메인 브랜치의 기록에 남게 됩니다. 병합 기록이 생깁니다.
- Squash and merge: 지금까지 기여자가 작업했던 모든 커밋이 하나의 커밋으로 메인 브랜치의 기록에 남게 됩니다.
- Rebase and merge: Create a merge commit과 비슷하지만, 병합 기록이 생기지 않습니다.
자세한 차이점은 이 글을 참고하시면 될 것 같습니다.
개인적으로는 Squash and merge를 선호합니다. 특정 기능을 개발하기 위해서는 많은 커밋이 갈 텐데, 메인 브랜치로 병합하는 순간 그 변경 내역이 전부 각각 들어가게 된다면 어디서부터 어떤 기능을 개발했는지 확인하기 어려울 것이기 때문입니다.
이제 main 브랜치에 병합이 되었습니다. 파란색으로 되어 있는 #1을 누르면, 관련된 Pull Request로 자동 연결됩니다.
이슈 생성 후 Pull Request 생성하기
이제 새롭게 이슈를 생성한 다음 작업하도록 하겠습니다. 앞서 말했듯 Pull Request를 하게 된 이유를 설명하기 위해 이슈를 먼저 만드는 게 좋습니다.
이슈 템플릿 만들기
처음 이슈를 만들려고 하면 마땅히 정해진 템플릿이 없기 때문에, 사람마다 아무렇게나 작성할 확률이 높습니다.
협업을 하고 상대방이 쉽게 이해하기 위해서는 일종의 템플릿이 필요하겠죠. 이슈 템플릿을 세울 수 있는데, 관련 글을 참고하시면 좋을 것 같습니다.
글을 참고하여 아래처럼 작성해 봤습니다.
이슈 템플릿 사용
이제 기여자는 아래와 같은 형식으로 이슈를 생성하게 됩니다.
또한, 리포지터리를 보면 .github/ISSUE_TEMPLATE/이슈템플릿.md로 저장됨을 볼 수 있습니다. 다른 프로젝트들에도 동일하게 작성하고 싶으시다면 이 파일들을 직접 옮겨서 사용하시면 됩니다.
PR 템플릿 만들기
PR에 대해서도 템플릿을 만들 수 있습니다. 해당 글을 참고하여 작성했습니다.
PR 템플릿 사용
이제 기여자는 아래 템플릿처럼 작성하게 됩니다.
#을 누르면 이슈, 템플릿을 선택할 수 있게 됩니다. 관련 이슈이니 #2를 하면 되겠네요.
이제 원래 이슈로 들어가면 관련 PR이 생겼음을 볼 수 있습니다.
PR 연결 후 관련 이슈가 자동으로 닫히게 하기 (핵심)
그러나 만약 PR을 연결한 후 PR이 merge된 다음 자동으로 이슈도 close 되도록 하고 싶다면, 아래 키워드를 작성하면 됩니다. (출처: 깃허브 문서)
정리
처음에는 PR을 병합하면 자동으로 이슈가 닫히도록 하는 것만 작성하려 했는데, 그러기 위해서는 이슈와 PR에 대한 개념도 정리해둬야 할 것 같아 작성해 봤습니다. 그리고 생각보다 간단한 과정으로 이슈를 자동으로 닫히게 할 수 있었네요. 최근 프로젝트에서 자동으로 닫히지 않아서 정리해 본 건데, 빌드 테스트 등의 내용을 담은 스크립트의 오류인 것 같습니다.
스프링 프로젝트 등을 결합하여 내부 테스트를 거치고 다른 과정들을 자동화할 수 있는 것들은 다른 글에서 작성하겠습니다.
Reference
- 실습한 리포지터리
- Github Issues - Github feature
- Github Pull Request - Github docs
- [GitHub] Branch Protection Rule 적용해 브랜치 보호하기
- GitHub 사용법 문의합니다. PR review 시의 "Add single comment"와 "Start a review"의 차이는 무엇인가요?
- How to review and edit a pull request
- [GitHub] Request Changes를 통한 PR 다시 요청하기
- [Git] Merge 이해하기 (Merge / Squash and Merge / Rebase and Merge)
- 깃허브 이슈 템플릿 생성하기
- 좋은 Pull Request를 만드는 방법과 PR Template 구성
- [Project] Github PR->merge 시 issue 자동 close 방법
- Using keywords in issues and pull requests - Github docs
'🚀 팁 (기술 적용 방법 등)' 카테고리의 다른 글
[Spring REST Docs ✍️] 어렵게만 느껴졌던 REST Docs를 적용해보자! (2) (0) | 2024.03.05 |
---|---|
[Spring MVC 🌐] 회원 식별을 해 보자! (2) - 세션 적용 방법 📦 (1) | 2024.02.10 |
[Spring MVC 🌐] 회원 식별을 해 보자! (1) - 쿠키 적용 방법 🍪 (0) | 2024.02.08 |
[Spring REST Docs ✍️] 어렵게만 느껴졌던 REST Docs를 적용해보자! (1) (1) | 2024.02.07 |