1. 개요

이전 글에서는 테스트 코드를 작성해 Unit단위의 테스트를 진행하고, 확인하는 과정을 거쳤습니다.

하지만 만들어두고 활용하지 않으면 의미가 없죠. 아무래도 매 작업마다 테스트를 실행하기 위해 명령어를 치고 결과를 확인하는 것은 번거롭고 귀찮기 때문입니다.

저는 개발 브랜치에 PR을 요청 했을때 자동으로 작성된 테스트코드를 돌리고, 정상적으로 돌아간다면 merge가 가능하도록 처리하고 싶었습니다.

의도치 않게 기존 코드를 수정하고 유지보수를 진행해도 이미 작성된 테스트코드를 통해 최소한의 기능동작이 돌아간다는게 보장이 된다면 개발의 안정성과 실수를 줄일 수 있을 것 같았어요.

이 글에서는 CI/CD의 개념부터 시작해서, GitHub Actions를 통해 CI/CD 파이프라인을 어떻게 구축하는지 내용을 정리하고자 합니다.

2. CI/CD

CI/CD는 지속적 통합(Continuous Integration, CI)과 지속적 배포(Continuous Deployment, CD)의 약자입니다. 사실 많이 들어봤는데 개념적으로 접하니까 어색하네요.


CI는 개발 중인 코드를 공유 코드 저장소에 지속적으로 통합하는 과정을 의미합니다.

이러한 과정은 팀원들이 자신들의 변경사항을 즉시 공유하도록 독려하여, 버그를 빠르게 찾고 고칠 수 있도록 합니다. 이는 코드 베이스를 최신 상태로 유지하고, 프로젝트의 안정성을 높이는 데에 중요한 역할을 합니다.

CD는 CI의 다음 단계로, 개발된 코드를 실제 사용자에게 배포하는 과정을 자동화하는 것을 의미합니다. 이를 통해 개발 팀은 빠르게 피드백을 얻고, 프로덕트의 품질 개선을 위한 사이클을 짧게 가져갈 수 있습니다.

즉 위에서 언급한 “귀찮고 번거로운 작업들”을 자동화 하고 통합하여 개발프로세스의 안정성과 속도를 높일 수 있는거죠.


CI/CD 도구로는 Jenkins, Travis CI, GitLab CI/CD, GitHub Actions 등 다양한 도구가 있지만 아래 장점을 고려해 Github Action을 사용하였습니다.

  1. 설치의 간결함: GitHub Actions는 GitHub에 내장되어 있기 때문에, 별도의 서버 설치나 구성이 필요 없음

  2. 통합성 : GitHub 저장소와의 자연스러운 통합과 코드 저장소와 CI/CD 파이프라인이 같은 위치에 있으므로 일관성 유지가 용이

  3. 사용 편의성: YAML 형식의 워크플로우 파일을 통해 CI/CD 프로세스를 명확하게 정의하고 관리 가능

  4. 가격 : public 경우 무료..! 출처

3. Github Action

GitHub Actions는 GitHub에서 직접 제공하는 CI/CD 도구입니다. 이 도구를 사용하면 소프트웨어 개발 워크플로우를 자동화할 수 있으며, 코드를 푸시하거나 풀 리퀘스트를 생성할 때 특정 작업을 자동으로 실행할 수 있습니다.

예를 들어, 테스트를 실행하거나 애플리케이션을 빌드하고 배포하는 등의 작업을 자동화할 수 있습니다.

3.1 구성요소

GitHub Actions의 워크플로우는 워크플로우 파일 내에 정의되며, 이 파일은 .github/workflows 디렉토리에 위치합니다. 워크플로우 파일은 YAML 형식으로 작성되며, 언제 어떤 작업을 실행할지를 정의합니다.


크게 워크플로우는 일반적으로 세 가지 구성 요소로 구분할 수 있으며 내용은 아래와 같습니다.

트리거(trigger): 워크플로우가 언제 실행될지를 결정합니다. 트리거는 GitHub 이벤트 (예: 푸시, 풀 리퀘스트, 이슈 생성 등) 또는 일정에 의해 설정될 수 있습니다.

작업(job): 각 워크플로우는 하나 이상의 작업으로 구성되며, 이는 워크플로우가 실제로 무엇을 수행할지를 정의합니다. 각 작업은 독립적으로 실행되며, 다른 작업과의 상호 작용은 제한적입니다.

단계(step): 각 작업은 여러 단계로 구성됩니다. 단계는 실제로 실행되는 명령어 또는 액션을 정의합니다.


[참고]

GitHub Actions는 기본적으로 .github/workflows 디렉토리에서 워크플로우를 찾으며 이 디렉토리는 워크플로우를 실행할 브랜치에 존재해야 합니다.

예를 들어, develop 브랜치에 대한 이벤트가 워크플로우를 트리거하는 경우, .github/workflows 디렉토리와 그 안의 워크플로우 파일들은 develop 브랜치에 존재해야 합니다.

이는 GitHub Actions가 브랜치별로 독립적으로 워크플로우를 관리하므로, 각 브랜치에서 어떤 워크플로우를 실행할지 결정할 수 있기때문입니다.

(저는 잘 모르고 개발브랜치에 hotfix로 처리하면서 실수했었습니다ㅜㅜ)

3.2 test 실습

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# .github/workflows/test.yml
# 워크 플로우의 이름 설정
name: TEST

# 워크 플로우의 트리거 설정 (develop브랜치에 대한 push,pr에 대해 처리한다)
on:
  push:
    branches: [develop]
  pull_request:
    branches: [develop]

# 워크 플로우에서 실행될 작업 정의
jobs:
  build:
    name: jest test
    # 작업을 실행할 운영체제 설정
    runs-on: ubuntu-latest

    # 병렬 실행 전략 설정 (Node사용)
    strategy:
      matrix:
        node-version: [16.x]

    steps:
      # 각 단계 설정
      - uses: actions/checkout@v2
      - name: Use Node.js $
        uses: actions/setup-node@v2
        with:
          node-version: $
      - run: yarn install
      - run: yarn test

이 워크플로우가 실행되면, GitHub Actions는 가장 최신 버전의 Ubuntu에서 Node.js를 설정하고, 의존성을 설치한 다음 테스트를 실행합니다. 모든 단계가 성공적으로 완료되면, 워크플로우는 성공으로 마무리됩니다.

이제 테스트를 진행해볼까요?

우선 레포의 Actions탭으로 이동하면 아래와 같이 워크플로우가 생성되어있음을 확인할 수 있습니다.

image

단 위의 워크 플로우 자체는 “실패 시 merge 금지” 의 동작을 의미하지 않습니다.

별도의 설정이 필요하며 설정 순서는 다음과 같습니다

  1. 해당 레포의 Settings페이지로 이동

  2. Branch 클릭

    image

  3. Add branch protection rule 클릭

    image

  4. Branch name pattern에 적용할 브랜치명 작성

  5. Require status checks to pass before merging 체크

  6. Require branches to be up to date before merging 체크 및 생성한 워크플로우 선택

    image


이제 임의로 브랜치를 만들어 테스트에 실패하도록 가정하고, develop브랜치에 PR을 요청하면 다음과 같이 테스트 실패 결과가 화면에 나타나며 merge할 수 없도록 되어있습니다.

image

그리고 의도적으로 틀린 부분을 다시 고치고 push하면 설정된 트리거에 의해 다시 워크플로우가 실행되면서 정상적으로 merge버튼이 활성화 되어 의도한 동작이 잘 돌아가는것을 확인할 수 있었습니다 🙌

image

3.3 시크릿 키 관리

배포와 관련된 설정등 때로는 환경변수를 별도로 분리해야할 때가 있습니다.

이때는 아래와 같이 사용합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
name: DEPLOY
on:
  push:
    branches:
      - master
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2

      - name: Build and Deploy
        run: |
          yarn install
          yarn build
          yarn ci-deploy

      - name: Invalidate CloudFront cache
        run: |
          aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*"

위의 코드는 master브랜치에 push가 되면 aws에 배포하는 워크플로우 내용이며 AWS와 CloudFront에 접근하기 위한 인증정보를 별도의 시크릿키로 분리하고 관리하고 있습니다.

이러한 시크릿 설정은 다음과 같은 단계를 따릅니다


  1. GitHub의 프로젝트 페이지로 이동합니다. 그리고 상단 메뉴에서 “Settings”를 클릭합니다.

  2. Settings 페이지 내의 사이드바에서 “Secrets”를 선택합니다.

  3. 이어서 “New repository secret” 버튼을 클릭합니다.

    image

  4. 새로운 창에서 시크릿의 이름을 입력하고, 값(value) 필드에 시크릿 값을 입력합니다.

    image

    • 이때 대문자와 밑줄만을 사용해야 합니다

이러한 설정을 마치면 워크 플로우 파일에서 secrets.MY_SECRET 등으로 접근해서 사용할 수 있습니다.

참고 자료

https://satisfactoryplace.tistory.com/361

https://docs.github.com/ko/actions

댓글남기기