PR로부터 브랜치 보호하기
이번에 과제를 내주고 깃허브로 제출하는 형식의 스터디를 진행하며 여러 사람들이 사용하는 레포지토리를 관리하게 되었습니다. 함께 코딩을 해서 하나의 프로젝트를 만드는 것이 아니라, 원본 형상은 유지하되 과제 결과물만 확인해야하기 때문에 과제 안내 내용과 초기 설정이 담겨있는 main 브랜치는 최대한 보존할 필요가 있었습니다.
제 경우에는 다행히 별도의 브랜치로 제출하도록 안내를 해서 main 브랜치가 수정되는 일은 없었습니다. 그러나 코드 리뷰를 진행하려 했던 의도와는 다르게 구성원들이 Pull Request와 동시에 각자의 브랜치에 Merge를 진행해서 생각했던 리뷰 과정을 진행하지는 못한 문제가 생기게 되었습니다. 지켜야 할 건 main 브랜치 뿐만이 아니었던 것입니다.
사실 이런 부분들이야 제가 정확히 안내를 했다면 일어나지 않았을 수도 있었겠지만, 그럼에도 항상 만일의 상황을 대비해 문제가 발생하지 않도록 하는 안전 장치는 꼭 필요합니다.
이때, Github에서 제공하는 Branch Protection Rule을 이용하면 이런 문제를 해결할 수 있습니다.
Branch Protection Rule
이전부터 깃허브를 사용하시던 분이라면, 얼마 전부터 아래 사진과 같은 낯선 알림창 하나를 발견하셨을겁니다.
main(master) 브랜치가 보호되고 있지 않다는 내용인데, Protect this branch 버튼을 눌러 브랜치 보호 규칙을 바로 설정해 줄 수 있습니다.
(저처럼) 무료 플랜 사용자는 공개된 레포지토리에서만 보호 규칙을 설정해 줄 수 있고, 개인 레포지토리에서도 적용해주려면 Pro 플랜을 사용하셔야 합니다.
무료 플랜 이용자더라도 공개된 레포지토리라면 걱정없이 사용하실 수 있으니 우선 어떻게 써야하는지 알아봅시다.
규칙 적용 범위 설정
Branch name pattern을 통해 아래의 규칙들이 어떤 브랜치에 영향을 주게 될지 설정합니다. 특정한 브랜치 이름을 적게되면 해당 브랜치에만 적용이 되고, 와일드카드 ( * ) 를 이용하면 조건을 만족하는 모든 브랜치에 공통적으로 적용하게 됩니다.
아래 예시처럼 응용해서 사용하시면 됩니다.
main
- main 브랜치에만 적용
feat/*
- feat/1, feat/login 등 'feat/' 으로 시작하는 모든 브랜치에 적용
*
- 모든 브랜치에 적용
세부 규칙 설정
크게 8개의 규칙이 있고, 각 규칙마다 세부적인 부분들을 설정해 줄 수 있습니다.
1. Require a pull request before merging
merge를 위해서는 pull request를 강제하는 옵션입니다. 해당 브랜치에 수정 내역을 반영하려면 일반적인 푸시가 아닌 반드시 PR을 올리는 작업이 선행되어야 합니다. 보호가 필요한 브랜치라면 대부분의 경우 사용하게 될 속성입니다.
세부적으로 코드 리뷰가 필요한지, 필요하다면 최소 몇 명의 리뷰가 있어야 하는지, 리뷰 작업 중 변동 내역이 있다면 기존의 승인을 취소할지에 대한 여부 등을 정할 수 있습니다.
2. Require status checks to pass before merging
merge 전에 상태 체크를 먼저 진행합니다. 테스트 코드등을 미리 돌려 문자 그대로 PR의 상태를 확인할 수 있습니다. 상태 체크의 경우 Github Action을 통해서 가능합니다. Github Action Workflow를 구성하는 자세한 방법은 PR시 미리보기 구현하기 (Github Actions) 포스팅을 참고해주세요.
3. Require conversation resolution before merging
merge 전에 PR에 남겨진 코멘트(conversation)를 모두 확인해야 합니다. 남겨진 모든 코멘트에 답을 달아주어야 머지가 되는 옵션으로 코드 리뷰를 꼼꼼하게 진행할때 사용하기 좋습니다.
4. Require signed commits
서명된 커밋만 푸시될 수 있도록 하는 규칙입니다. verify 마크가 찍힌 커밋들만 푸시가 가능한데, 믿을 수 있는 출처에서부터 생산된 커밋이라고 생각하시면 될 것 같습니다. 서명된 커밋에 대한 정보는 이곳에서 확인하실 수 있습니다.
5. Require linear history
선형적인 히스토리 관리를 위해 일반적인 머지를 막고, 스쿼시나 리베이스를 통한 머지만 하도록 허용합니다. 여러 갈래로 뻗어진 브랜치는 문제가 발생했을때 히스토리를 추적하고 이전으로 되돌리기가 어렵기 때문에, 브랜치 모양을 단순하게 관리하고 싶을때 사용하면 좋은 옵션입니다.
6. Require deployments to succeed before merging
머지되기 전 반드시 배포에 성공해야만 머지가 가능하도록 하는 옵션입니다. 해당 레포지토리에 세팅 된 환경 중 배포 성공을 확인할 대상을 선택할 수 있습니다.
7. Lock branch
누구도 브랜치에 푸시할 수 없도록 read-only로 만듭니다.
8. Do not allow bypassing the above settings
관리자 권한을 가진 유저들도 해당 설정을 지키지 않으면 머지할 수 없도록 막습니다. 이 옵션을 체크하지 않으면 관리자 권한이 있는 유저는 경고를 무시하고 머지할 수 있습니다.
실제로 적용하기
제가 필요한건 과제 제출과 스터디를 위한 레포지토리이므로, 코드 리뷰를 받지 않으면 머지할 수 없는 세팅이었습니다. 아래처럼 전체 브랜치에 코드 리뷰 필수 옵션을 주었습니다. 또한 레포지토리가 동아리 조직 아래에 있었기 때문에 모두가 관리자 권한을 가지고 있더라도 규칙을 무시할 수 없도록 옵션을 설정했습니다.
Branch name pattern : *
Protect matching branches
- ✅ Require a pull request before merging
- ✅ Require approvals (required a number of approval before merging: 1)
- ✅ Require status checks to pass before merging
- ✅ Require branches to be up to date before merging
- ✅ Do not allow bypassing the above settings
브랜치 보호 규칙을 적용하고 실제 PR을 확인해보니 절차를 지키지 않은 접근 방식을 막을 수 있었습니다. 아래 오른쪽 사진처럼 코드 리뷰가 남겨진 PR에만 Merge pull request 버튼이 활성화 된 모습입니다.
브랜치 설정과 같은 개발 외적인 옵션들은 일찍부터 관리하는 것이 중요합니다. 다소 귀찮더라도 문제가 일어나기 전에 설정하여 예상치 못한 사고를 미연에 방지하면 좋겠습니다.
감사합니다.