배경
열린채로 시간이 지난 이슈나 PR이 꽤 많이 쌓이고 있어요.
또 오랫동안 활동이 없는 브랜치 또한 많이 쌓여있어요.
아마도 Draft PR을 위해 만든 브랜치나, 병합 후에 삭제하지 않은 브랜치가 하나씩 쌓이다보니 많아진 것 같아요. 예전에 까비 팀을 담당해주셨었던 멘토분도 걱정을 가지고 이슈를 남겨주셨었네요..!
꼭 까비에서뿐만 아니라 다른 프로젝트를 진행할 때도 이런 부분은 신경쓰기가 참 어려운 것 같아요.
오래된 이슈/PR 청소기
GitHub Actions에서 공식적으로 제공하는 actions/stale은 오랜 시간 동안 활동이 없는 이슈와 PR을 자동으로 정리해주는 훌륭한 Action 라이브러리입니다.
name: Close Stale Issues/PRs
permissions:
issues: write
pull-requests: write
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *" # Every day at 00:00 UTC
env:
OPERATIONS_PER_RUN: 128
DAYS_BEFORE_ISSUE_STALE: 30
DAYS_BEFORE_ISSUE_CLOSE: 3
DAYS_BEFORE_PR_STALE: 30
DAYS_BEFORE_PR_CLOSE: 3
jobs:
close-stale-issues-and-prs:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v5
with:
operations-per-run: ${{ env.OPERATIONS_PER_RUN }}
days-before-issue-stale: ${{ env.DAYS_BEFORE_ISSUE_STALE }}
days-before-issue-close: ${{ env.DAYS_BEFORE_ISSUE_CLOSE }}
exempt-issue-labels: "no stale"
stale-issue-label: "stale"
stale-issue-message: >
해당 이슈는 지난 ${{ env.DAYS_BEFORE_ISSUE_STALE }}일 동안 활동이 없어서 "stale" 상태로 표시되었어요.
${{ env.DAYS_BEFORE_ISSUE_CLOSE }}일 이내에 "no stale"으로 태그가 지정되거나 다른 활동이 발생하지 않으면 자동으로 닫힐 예정입니다.
close-issue-message: >
해당 이슈는 "stale" 상태로 표시된 후 ${{ env.DAYS_BEFORE_ISSUE_CLOSE }}일 동안 활동이 없어서 자동으로 닫혔어요.
remove-issue-stale-when-updated: true
days-before-pr-stale: ${{ env.DAYS_BEFORE_PR_STALE }}
days-before-pr-close: ${{ env.DAYS_BEFORE_PR_CLOSE }}
exempt-pr-labels: "no stale"
stale-pr-label: "stale"
stale-pr-message: >
해당 PR은 지난 ${{ env.DAYS_BEFORE_PR_STALE }}일 동안 활동이 없어서 "stale" 상태로 표시되었어요.
${{ env.DAYS_BEFORE_PR_CLOSE }}일 이내에 "no stale"으로 태그가 지정되거나 다른 활동이 발생하지 않으면 자동으로 닫힐 예정입니다.
해당 PR이 "stale" 상태로 표시되지 않기를 원하면 이 PR에 코멘트를 남겨주세요.
close-pr-message: >
해당 PR은 "stale" 상태로 표시된 후 ${{ env.DAYS_BEFORE_PR_CLOSE }}일 동안 활동이 없어서 자동으로 닫혔어요.
remove-pr-stale-when-updated: true
repo-token: ${{ secrets.GITHUB_TOKEN }}
YAML
복사
이렇게 워크플로우에서 해당 라이브러리를 불러와 원하는 설정대로 사용해보도록 할게요!
해당 라이브러리를 원활하게 사용하려면 Issue와 PR에 붙일 태그를 미리 만들어주어야 해요.
1.
환경 변수 설정:
•
OPERATIONS_PER_RUN: 실행당 최대 작업 수를 정의합니다.
•
DAYS_BEFORE_ISSUE_STALE 및 DAYS_BEFORE_PR_STALE: 이슈와 PR이 활동 없이 'stale' 상태로 표시되기까지의 일수를 설정합니다.
•
DAYS_BEFORE_ISSUE_CLOSE 및 DAYS_BEFORE_PR_CLOSE: 'stale' 상태의 이슈와 PR이 자동으로 닫히기까지의 일수를 설정합니다.
2.
Stale 액션 설정:
•
stale-issue-label 및 stale-pr-label: 이슈와 PR이 stale 상태일 때 적용할 라벨을 지정합니다.
•
exempt-issue-labels 및 exempt-pr-labels: stale 처리에서 제외될 이슈와 PR의 라벨을 정의합니다. 이 라벨이 붙은 이슈나 PR은 자동으로 닫히지 않습니다.
3.
메시지 옵션:
•
stale-issue-message 및 stale-pr-message: 이슈와 PR이 stale 상태로 전환될 때 보여줄 메시지를 설정합니다.
•
close-issue-message 및 close-pr-message: stale 상태의 이슈와 PR이 닫힐 때 보여줄 메시지를 설정합니다.
4.
동적 업데이트 처리:
•
remove-issue-stale-when-updated 및 remove-pr-stale-when-updated: 이슈나 PR에 새로운 활동(업데이트나 댓글)이 발생하면 자동으로 'stale' 라벨을 제거합니다. 이는 커뮤니티의 의견이나 수정을 적극적으로 반영하여 이슈나 PR을 열린 상태로 유지하는 데 도움을 줍니다.
5.
자동 실행 스케줄:
•
cron: "0 0 * * *": 이 설정은 워크플로우가 매일 00:00 UTC에 자동으로 실행되도록 합니다.
30일 동안 활동이 없는 이슈나 PR은 stale 라벨이 붙고, stale 라벨이 붙은지 3일이 지나면 자동으로 Close 돼요.
만약 중요한 이슈나 PR이라 닫히지 않도록 하고 싶다면코멘트를 남기는 등 활동을 하거나 no stale이라는 라벨을 붙이면 됩니다!
까비는 이슈나 PR 관련해서 이벤트가 발생하면 자동으로 디스코드로 알림이 가도록 설정되어 있기 때문에 팀원들도 쉽게 비활성 여부를 파악할 수 있을 것이라고 생각해요.
이렇게 워크플로우가 실행되면, 오래된 이슈와 PR에 stale 라벨이 붙는 것을 확인할 수 있었어요.
깃허브에 등록한 디스코드 webhook을 통해 알림이 올 줄 알았는데, 담당자에게 메일이 오도록 설정되어 있나보네요. 메일이 가도록만 설정해도 충분할 것 같네요!
다른 상세 옵션에 대한 설명은 공식 레포지토리에서 확인하실 수 있어요!
오래된 브랜치 청소기
오래된 브랜치 역시 자동으로 삭제해주는 워크플로우도 추가해보려고 해요.
그 전에 중요한 브랜치인, dev와 main은 삭제되지 않도록 브랜치 보호 규칙을 확인했어요.
중요 브랜치 삭제 방지
브랜치 보호 규칙을 생성하게 되면, 강제 푸쉬와 브랜치 삭제는 기본으로 disabled로 설정돼요.
main 브랜치는 여기에 추가로 PR을 통해서만 커밋할 수 있도록 규칙을 추가했어요.
dev는 상황에 따라 직접 푸쉬하는 경우도 있어, 직접 푸쉬를 허용했어요.
병합된 브랜치 자동 삭제
merge된 브랜치를 자동으로 지우는 것은 깃허브에서 자체적으로 제공해주어 허용하는 것으로 설정을 변경했어요.
오래된 브랜치 청소
이제 오래된 브랜치를 자동으로 삭제하는 워크플로우를 적용해보려고 해요!
그런데 github에서 action/stale 처럼 공식적으로 제공되는 라이브러리는 따로 존재하지 않았어요.
그래서 마켓플레이스에서 찾아보니 공신력있어보이는 라이브러리가 딱히 보이지는 않았어요…
무엇보다도 action/stale 처럼 stale 상태로 만들어 경고를 한 번 주고, 그 다음에 지워지는 기능을 원하기도 하였고, action이 트리거된 후의 결과를 디스코드로 알려주는 것을 원하기도 해서 해당 라이브러리를 사용하기보다는 이참에 직접 입맛에 맞도록 커스텀 action 라이브러리를 제작해보기로 했어요..!
해당 라이브러리를 만드는 과정은 다른 포스트에서 알아보도록 하고, 바로 해당 action이 적용된 코드 예시를 살펴볼게요!
name: Cleaning Up Stale Branches
permissions:
contents: write
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *" # Every day at 00:00 UTC (KST 09:00)
env:
DAYS_BEFORE_STALE: 30
DAYS_BEFORE_DELETE: 7
jobs:
cleanup-stale-branches:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Cleaning up Stale Branches
uses: sichoi42/cleanup-stale-branch@v1
id: stale
with:
days-before-stale: ${{ env.DAYS_BEFORE_STALE }}
days-before-delete: ${{ env.DAYS_BEFORE_DELETE }}
ignoring-branches: "main,dev,onboard,nestJS"
ignore-branches-pattern: "release/*"
# FIXME: Set dry-run to false when you are ready to delete branches
dry-run: true
use-webhook: true
webhook-url: ${{ secrets.DISCORD_GITHUB_WEBHOOK_URL }}
webhook-type: "discord"
stale-branch-message: >
This branch is considered stale because ${{ env.DAYS_BEFORE_STALE }} days have passed since the last commit.
If you still need this branch, please push a new commit to keep it alive.
If not, this branch will be deleted in ${{ env.DAYS_BEFORE_DELETE }} days.
delete-branch-message: >
This branch was deleted because ${{ env.DAYS_BEFORE_DELETE }} days have passed since the last commit.
- name: Print outputs
run: echo ${{ format('{0},{1}', toJSON(steps.stale.outputs.staled-branches), toJSON(steps.stale.outputs.deleted-branches)) }}
YAML
복사
1.
환경 변수 설정:
•
DAYS_BEFORE_STALE 및 DAYS_BEFORE_DELETE: 브랜치가 마지막 커밋 이후 'stale' 상태로 표시되기까지의 일수와, 'stale' 상태의 브랜치가 자동으로 삭제되기까지의 일수를 설정합니다.
2.
Stale 브랜치 처리 액션 설정:
•
ignoring-branches 및 ignore-branches-pattern: stale 처리에서 제외될 브랜치의 이름과 패턴을 정의합니다. 이 브랜치 이름이나 패턴에 해당하는 브랜치는 자동으로 삭제되지 않습니다.
3.
메시지 옵션:
•
stale-branch-message 및 delete-branch-message: 브랜치가 stale 상태로 전환될 때와 삭제될 때 보여줄 메시지를 설정합니다.
4.
웹훅 사용:
•
webhook-url 및 webhook-type: 이벤트 발생 시 통지를 받을 웹훅의 URL과 유형을 설정합니다. 이 설정을 통해 지정된 웹훅 URL로 브랜치의 상태 변화에 대한 알림을 Discord 등의 서비스로 전송할 수 있습니다. (use-webhook인 경우에만 사용됩니다.)
5.
자동 실행 스케줄:
•
cron: "0 0 * * *": 이 설정은 워크플로우가 매일 00:00 UTC에 자동으로 실행되도록 합니다. 이를 통해 일정한 주기로 브랜치 상태를 검사하고, 필요에 따라 처리를 수행합니다.
30일 동안 커밋이 없는 브랜치는 stale로 판단하고, stale 상태에서 7일이 경과하면 해당 브랜치를 삭제해요.
use-webhook을 true로 지정한 경우, 입력한 webhook-url로 stale로 판단된 브랜치와 삭제된 브랜치 목록들을 알림을 보내주어요.
안쓰는 오래된 레포지토리에서 충분히 테스트를 거친 후, dry-run 모드로 바로 까비 레포지토리에도 적용해보았는데, 이렇게 stale한 브랜치와 삭제된 브랜치 목록을 정상적으로 받아볼 수 있었네요!
결론
이번 포스트를 통해 GitHub Actions를 통해 오래된 이슈, PR, 그리고 브랜치들을 자동으로 관리하는 방법을 살펴보았어요.
미미해 보일 수 있는 작업들도, 빈번하게 반복될 경우 자동화의 좋은 대상이 됩니다. 까비 팀에서 직면한 오래된 이슈, PR, 그리고 브랜치가 쌓이는 문제는 많은 개발 팀이 경험하는 공통적인 고민이죠.
이러한 문제들을 자동으로 관리하도록 설정하는 것은 장기적으로 팀의 개발 생산성을 높이고 리소스 관리를 효율화하는데 큰 도움을 준다고 생각합니다!