들어가며
안녕하세요. 요즘에 플러피(fluffy)라는 온라인 시험 문제 제작 및 관리 서비스를 개발하고 있습니다. 이 프로젝트에서는 main, dev, feat, fix 브랜치를 사용하는 git flow를 사용하고 있습니다. dev로의 pull request는 squash merge로만 허용하고 있고, main으로의 pull request는 rebase merge로만 허용하고 있습니다. 또한 main, dev으로 force 푸쉬하는 것을 금지하고, github actions를 통해 테스트를 자동화하고 있습니다.
이렇게 까다롭게 규칙을 정한 이유는 프로젝트를 안전하게 관리하기 위해서입니다. 하지만 이런 규칙을 정하고 관리하는 것은 쉽지 않습니다. 특히, 프로젝트에 참여하는 사람이 많아지거나, 프로젝트의 규모가 커지면서 규칙을 지키지 않는 사람이 생기기 마련입니다. 이런 문제를 해결하기 위해 Github Branch Rulesets를 사용할 수 있습니다. 이번 글에서는 Github Rulesets 중 하나인 Branch Rulesets를 사용하는 방법을 알아보겠습니다.
Rulesets란?
깃허브 공식 문서에 따르면 Rulesets는 사용자가 레포지토리에서 브랜치 및 태그와 상호 작용하는 방법을 제어하는데 도움을 준다고 합니다. 예를 들어, 특정 CI가 통과되어야만 dev 브랜치로 merge가 가능하도록 설정할 수 있습니다. 레포지토리 당 최대 75개의 규칙을 만들 수 있으며, 특정 사용자가 규칙을 우회할 수 있도록 허용할 수 있습니다.
Branch Rulesets 알아보기
먼저, Branch Rulesets를 알아보고, 제가 플러피 프로젝트에서 사용하고 있는 규칙을 소개하겠습니다.
Branch Rulesets는 해당 레포지토리에서 Settings로 이동한 후 Rules의 Rulesets로 들어가서 New ruleset 버튼을 누르고, New branch ruleset을 클릭하시면 됩니다. 글로는 이해하기가 어려우니 이미지로 보여드리겠습니다. 또는 공식 문서를 보셔도 됩니다.
주의할 점으로, Ruleset을 생성하기 위해서는 레포지토리의 관리자 권한이 있어야 합니다.
Branch Ruleset을 생성한 후 Branchs에서 각 브랜치에 적용된 규칙들을 볼 수 있습니다.
Branch Ruleset 생성에 대한 옵션은 굉장히 많습니다. 이 옵션들을 위에서 아래로 내려가면서 알아보겠습니다.
Ruleset Name과 Enforcement status
Ruleset Name은 단순히 규칙 모음의 이름입니다. Enforcement status에는 Active와 Disdabled가 있습니다. 이 옵션을 통해 Ruleset을 활성화, 비활성화 시킬 수 있습니다.
Bypass list
Bypass list는 이 규칙을 우회할 수 있는 사용자나 팀을 지정할 수 있는 리스트입니다. 아래 예시에서는 Vercel에 대해서 지정되어 있습니다. 항상 허용할지, Pull Request 시에만 허용할지에 대한 옵션을 선택할 수 있습니다.
Targets
Target branches에서는 이 규칙을 적용할 브랜치들을 선택할 수 있습니다. 아래 예시에서는 dev 브랜치가 지정되어 있습니다. "release/**/*", "users/**/*"와 같이 패턴으로 포함시킬 수도 있고, 제외시킬 수도 있습니다.
Rules - 1
이 부분에서는 각 브랜치에 적용시킬 규칙을 선택할 수 있습니다. Rules는 옵션이 많기 때문에 나눠서 설명하겠습니다.
Restrict creations (생성 제한)
이 규칙은 특정 브랜치 또는 태그에 대해 우회 권한이 있는 사용자만 새로운 참조(ref)를 생성할 수 있도록 제한합니다. 예를 들어, feat/* 패턴에 대해서 이 옵션이 지정되어 있을 경우, 우회 권한을 가진 사용자만이 feat/#12, feat/#15 등을 생성할 수 있습니다.
Restrict updates (업데이트 제한)
이 규칙은 우회 권한이 있는 사용자만 해당 브랜치 또는 태그의 내용을 업데이트할 수 있도록 제한합니다.
Restrict deletions (삭제 제한)
이 규칙은 우회 권한이 있는 사용자만 특정 브랜치 또는 태그를 삭제할 수 있도록 제한합니다.
Require linear history (선형 히스토리 요구)
이 규칙은 병합 커밋이 해당 브랜치에 푸시되는 것을 방지하여, 커밋 히스토리가 직선적으로 유지되도록 합니다. 예를 들어, merge, rebase merge, squash merge 중 merge를 사용할 수 없습니다. 엄격한 선형 커밋 기록을 사용하면 팀이 변경 내용을 보다 쉽게 되돌릴 수 있습니다.
Rules - 2
Require deployments to succeed(병합 전 배포 성공 필요)
분기를 병합하기 전에 변경 내용을 특정 환경에 성공적으로 배포하도록 요구할 수 있습니다. 위 예시에서 Production에 대해서 지정되어 있습니다. 이 경우 Production 환경에 성공적으로 배포되어야만 해당 브랜치에 푸시할 수 있습니다.
Require signed commits(서명된 커밋 필요)
이 규칙을 활성화하면 해당 브랜치에 푸시되는 모든 커밋은 반드시 서명되어야 하며, 서명되지 않은 커밋은 거부됩니다. 아래의 이미지에서 오른쪽을 보시면 'Verified'라고 적힌 초록 글씨가 있습니다. 이게 서명된 커밋입니다.
Rules - 3 (중요 🌟)
Require a pull request before merging(병합 전 끌어오기 요청 필요)
이 옵션을 선택할 경우 모든 커밋은 대상 브랜치가 아닌 브랜치에서 이루어지고, 병합되기 전에 Pull Request를 통해 제출되어야 합니다. 위에서 아래로 옵션들을 한 번 알아보겠습니다.
- Require approvals는 Pull Request가 병합되기 전에 필요한 승인 리뷰 수를 설정할 수 있습니다. 예를 들어, 팀원 중 적어도 2명이 코드 리뷰에서 approve를 해야 병합할 수 있음을 의미합니다. 이를 통해 코드의 신뢰도를 높일 수 있습니다.
- Dismiss stale pull request approvals when new commits are pushed는 최신 커밋이 푸시되면, 이전 리뷰에 대한 승인 상태를 무효화합니다. 코드 변경이 있을 경우 항상 최신 상태에 대한 리뷰를 요구하여, 누락된 검토를 방지합니다.
- Require review from Code Owners는 Code Owner(코드 소유자 정보)에게 승인을 받아야함을 의미합니다. 코드 소유자가 직접 검토하여 코드 품질과 일관성을 유지합니다.
- Require approval of the most recent reviewable push는 푸시한 사람 외의 누군가의 승인을 받아야 합니다. 푸시한 사람이 아닌 다른 개발자가 코드를 검토하도록 강제하여, 객관적인 리뷰를 보장합니다.
- Require conversation resolution before merging는 Pull Request 내의 모든 코드 관련 대화는 병합되기 전에 해결되어야 합니다. 모든 의견이나 질문이 해결된 상태에서 코드가 병합되도록 하여, 불확실성을 줄입니다.
- Request pull request review from CopilotPreview는 Copilot 코드 리뷰에 대해 접근할 수 있는 경우 자동으로 리뷰 요청을 합니다.
- Allowed merge methods는 Pull Request 시 Merge, Rebase, Squash 중 허용된 병합 방법들을 설정할 수 있습니다.
Require status check to pass(병합 전 상태 검사 통과 요구하기)
Require status checks to pass는 특정 상태가 통과되어야만 브랜치가 업데이트될 수 있도록 설정합니다. 예를 들어, CI/CD 파이프라인에서의 테스트 결과가 통과해야만 다음 단계로 진행될 수 있습니다. 코드가 특정 기준을 충족해야만 업데이트되므로, 안정성과 품질을 높일 수 있습니다.
- Require branches to be up to date before merging는 Pull Request가 병합되기 전에 해당 브랜치가 최신 코드로 업데이트되어야 한다는 조건을 설정합니다. 여러 개발자가 같은 코드베이스에서 작업하는 경우, 최신 변경 사항을 반영하지 않으면 병합 시 충돌이 발생할 수 있습니다. 예를 들어, A 개발자가 dev 브랜치에서 작업을 하고, B 개발자가 main 브랜치에서 작업을 한 후, A 개발자가 dev 브랜치에서 main 브랜치로 PR을 보내면 충돌이 발생할 수 있습니다. 이런 경우, A 개발자는 dev 브랜치를 main 브랜치로부터 최신으로 업데이트해야 합니다.
- Do not require status checks on creation는 상태 검사가 통과하지 않더라도 새로운 브랜치를 생성할 수 있게 합니다. 이는 새로운 브랜치를 생성할 때 불필요한 제한을 받지 않게 하기 위함입니다.
- Status checks that are required는 특정 상태 검사를 설정하여, 해당 검사가 반드시 통과해야만 다음 단계로 진행할 수 있음을 명시합니다. Github Actions, cloudtype, Vercel 등의 소스를 이용할 수 있고, Github Actions의 경우 Workflow에서 특정 Job 이름을 통해 특정 상태 검사를 지정할 수 있습니다. 위의 예시의 경우 Server CI라는 Job Name을 지정하여, Server CI가 통과해야만 Pull Request에서 Merge할 수 있습니다.
Rules - 4
Block force pushes(강제 푸시 차단)
사용자가 대상 분기 또는 태그에 강제로 푸시하는 것을 방지할 수 있습니다. 강제 커밋을 할 경우 특정 커밋이 삭제될 수도 있고, 병합 충돌 또는 손상된 끌어오기 요청으로 이어질 수 있습니다. 이러한 문제들을 막기 위해 이 규칙은 기본적으로 사용하도록 설정되어 있습니다.
Require code scanning results(code scanning 병합 보호 설정)
특정 브랜치나 태그가 업데이트되기 전에 코드 스캔 도구가 검사 결과를 제공해야 한다는 조건을 설정하는 기능입니다. 이 규칙을 활성화하면, 코드 변경 사항에 대한 보안 및 품질 검사를 자동으로 수행할 수 있습니다.
플러피에서 사용하는 규칙들
플러피는 아직 개발 단계이기도 하고, 1인 개발이기 때문에 많은 규칙은 오히려 자유로운 개발을 방해할 것 같아서 기본적인 것들만 지정했습니다. protect-main, protect-dev라는 규칙이 있습니다. 이 2개의 규칙은 각각 main, dev에 대한 규칙 모음입니다. main 병합은 Rebase, dev로의 병합은 Squash로 설정한 것 외에 나머지 옵션은 비슷합니다.
- Restrict deletions
- Require a pull request before merging
- Require status checks to pass
- Require branches to be up to date before merging
- github actions "Build" Job을 통과해야만 Merge 가능
- Block force pushes
마치며
새롭게 프로젝트를 진행하시는 분들이나 이미 팀원들과 프로젝트를 진행하시는 분들 모두 Branch Rulesets를 적용하고, 프로젝트를 안전하게 관리해보세요!
참고
'협업' 카테고리의 다른 글
Git Submodule(서브모듈)을 통해서 Spring 설정(yml) 관리하기 (1) | 2025.01.05 |
---|