GitHub Action에 대해서는 앞서 어떤 요소들이 있는지 알아봤다.
최종적으로 나 역시 CI / CD를 구축하는 것을 목표로 GitHub Action을 사용하려고 한다.
CI의 베이스가 되는 브랜치 전략으로 Git Flow를 사용하려고 한다.
GitHub Flow 등도 있을 텐데 최초 브랜치 전략을 공부할 때 Git Flow를 알아봤었고 아직까지 많이 사용되는
전략이라서 굳이 다른 방향을 알아보진 않았다.
어떤 방향으로 GitHub Action을 사용할 것인가!
이게 중요할 것 같은데, Git Flow를 이야기하는 이유는 브랜치의 속성에 따라 Action을 설정해줄 생각이다.
내가 사용할 브랜치로
- Main : 프로젝트 | 서비스의 메인 브랜치로 정식 배포가 된 환경의 브랜치다.
- Develop : 개발 환경을 가지고 있는 브랜치다. 해당 브랜치에서 개발자들이 작업을 한다고 생각하면 된다.
- Feat/[작업] : Develop 브랜치를 기준으로 기능 단위로 개발할 때 만들어지는 브랜치이다.
- Release : 정식 배포가 되기 전 사전 배포를 진행해서 테스트를 진행하는 브랜치이다.
- Hotfix: Develop => Feat 단계를 거치지 않고 급하게 작업 후 배포하는 경우 사용되는 브랜치이다.
다음과 같은 용도의 브랜치가 있다.
여기서 GitHub Action을 사용이 사용되는 부분은 다음과 같다.
- Feat 브랜치 병합 : 전날까지 작업해서 Develop 브랜치에 Merge를 자동으로 해주는 Workflow
코드 리뷰를 진행다고 PR을 올린 사람이 수동으로 Merge를 해도 되지만 간혹 리뷰에 답글만 달고 넘어가는 경우가 발생해서 Auto Merge를 지원한다면 다른 사람이 추후 작업에 충돌이 발생하는 문제가 없을 것이라고 생각된다. - PR 검사 : 개발자가 PR을 올릴 때 테스트 코드를 실행시켜서 오류가 발견된다면 PR을 자동으로 닫는 용도의 Workflow
테스트 코드를 작성하고 있을 때도 매번 PR을 올릴 때 테스트 코드를 체크하지 않고 올리는 경우가 있어서 예방하기 위해서 사용한다. - Release 브랜치 병합 및 배포 : 주기적으로 Develop 브랜치의 코드를 Release 브랜치에 Merge 시켜주고 테스트 환경에 자동으로 배포를 진행시켜주는 Workflow
웹의 경우, lighthouse 까지 검사해서 성능을 확인할 수 있는 방향으로 고려할 생각이다. - Main 브랜치 병합 및 배포 : Release 브랜치에 문제가 없는 상태일 때 정식 배포를 진행해주는 Workflow
이번엔 두 번째인 PR 검사를 해주는 GitHub Action을 만드려고 한다.
PR 검사는 간단한 기능이다.
- develop으로 전송할 PR이 올라오면 동작한다.
- PR을 확인하고 test를 돌려서 오류가 있는지 확인한다.
- 오류가 있다면 커밋의 상태를 failure 처리를 하고 PR에 댓글을 달아준다.
name: "project-pull-request-check"
run-name: Project PR Check
on:
pull_request_target:
branches: [develop]
jobs:
merge:
name: "Pull Request Check Test"
runs-on: "ubuntu-latest"
strategy:
matrix:
node-version: ["18.x"]
steps:
- name: "Check for GitHub Token"
run: |
if [ -z "${{ secrets.ACTION_TOKEN }}" ]; then
echo "GitHub token is missing"
exit 1
else
echo "GitHub token is present"
fi
- name: Checkout PR
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Use Node.js ${{ matrix.node-version }} & Caching
uses: actions/setup-node@v4
with:
node-version: ${{matrix.node-version}}
cache: "yarn"
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Install missing babel plugin
run: yarn add @babel/plugin-proposal-private-property-in-object --dev
- name: Run Test
id: test
run: yarn test --detectOpenHandles --passWithNoTests
- name: Test step has failed
if: ${{ failure() && steps.test.conclusion == 'failure' }}
uses: "actions/github-script@v3"
with:
github-token: ${{ secrets.ACTION_TOKEN }}
script: |
await github.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: context.sha,
state: "failure",
context: 'project-pull-request-check',
description: "테스트를 통과하지 못했습니다. 재검토 부탁드립니다."
});
await github.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: "테스트를 통과하지 못했습니다. 재검토 부탁드립니다."
});
on:
pull_request_target:
branches: [develop]
PR이 develop 타겟으로 올라왔을 때 동작하는 이벤트이다.
- name: Checkout PR
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
github action에서 코드를 받아오기 위한 부분이다.
여기서 중요한 부분이 with ~ 아래이다. 해당 설정이 없다면 main 브랜치의 코드를 가지고 오는데, 그렇게 되면 테스트를 실행해도 매번 main 브랜치를 기준으로 실행하기 때문에 PR이 올라온 변경된 코드는 반영이 안된다.
꼭, 올라온 PR을 기준으로 동작하도록 설정하려면 위 코드를 넣어줘야 한다.
- name: Use Node.js ${{ matrix.node-version }} & Caching
uses: actions/setup-node@v4
with:
node-version: ${{matrix.node-version}}
cache: "yarn"
- name: Install dependencies
run: yarn install --frozen-lockfile
패키지를 설치하고 캐싱된 패키지가 있다면 불러오는 코드이다.
github action의 속도를 올려주는 부분이다. 캐싱된 패키지가 있다면 가지고 오는 코드가 with: ~ 부분이다.
with:
node-version: ${{matrix.node-version}}
cache: "yarn"
또한 패키지를 설치하고 해당 패키지를 캐싱하기 위해서 설정 옵션을 추가하는 것이 --frozen-lockfile이다.
캐싱을 할때와 안할때의 차이가 큰데,
캐싱을 했을 때의 Action 초반 부분이다. 캐싱을 하면 10초를 넘어가는 작업이 없다.
하지만 캐싱을 하지 않으면 패키지를 설치할 때 21초가 걸린다.
특별한 패키지를 설치하지 않았는데도 이정도 차이라고 한다면 본격적인 프로젝트를 진행할 때는 속도차이가 훨씬 크기 때문에 캐싱은 가급적이면 하자!
- name: Install missing babel plugin
run: yarn add @babel/plugin-proposal-private-property-in-object --dev
github action에서 해당 플러그인이 설치되지 않은 것으로 확인해서 오류를 나타낸다.
그래서 따로 추가해주었다.
로컬 환경에서는 문제없이 동작하기 때문에 PR 환경에서만 올리기 위해서 github action에만 추가해 주었다.
- name: Run Test
id: test
run: yarn test --passWithNoTests
일반적인 테스트를 실행시켜주는 명령어이다. --passWithNoTests 설정은 그럴일이 거의 없겠지만 테스트 코드가 없는 상태에서 테스트를 실행하면 검사할 테스트가 없다는 오류가 발생한다.
하지만 그럴 수 있기 때문에 해당 옵션을 줘서 검사할 테스트가 없다면 넘어가도록 설정했다.
- name: Test step has failed
if: ${{ failure() && steps.test.conclusion == 'failure' }}
uses: "actions/github-script@v3"
with:
github-token: ${{ secrets.ACTION_TOKEN }}
script: |
await github.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: context.sha,
state: "failure",
context: 'project-pull-request-check',
description: "테스트를 통과하지 못했습니다. 재검토 부탁드립니다."
});
await github.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: "테스트를 통과하지 못했습니다. 재검토 부탁드립니다."
});
테스트가 실패하면 실행되는 부분이다.
if 조건으로 앞선 테스트가 실패한 경우에만 동작하도록 했고, 또 다른 곳에서 실패한다면 동작하지 않게 하기 위해서 steps.test.conclusion 조건을 추가해서 테스트를 실행한 step에서의 실패만 실행되게 했다.
여기서 steps의 test는 앞선 test의 id 값이다.
내부 코드는 action의 목적인 테스트 통과를 못했을 때 commit의 상태를 바꾸고 댓글을 달아주는 명령어다.
'개발정보' 카테고리의 다른 글
GitHub Action Lighthouse (5) | 2024.09.18 |
---|---|
GitHub Action Feature 합치기 (2) | 2024.09.01 |
GitHub Action 알아보기 (2) | 2024.08.28 |
VSCode Git 계정 변경 (0) | 2023.04.13 |
소프트웨어 개발 3대 원칙 - KISS, YAGNI, DRY (0) | 2023.01.26 |