개발/devOps

[git hub actions] 간단한 CI/CD pipeline 구축하기

김키쿠 2023. 10. 16. 01:12

최근 프로젝트를 진행하면서 쿠버네티스 환경에 배포할 일이 생겼다. 그래서 이번 김에 프로젝트 릴리즈와 도커 이미지 빌드 및 푸시까지 자동화 하는 CI/CD 파이프라인을 구축하려고 한다.

 

원래는 jenkins를 사용하려고 했는데 서버 만들기도 귀찮고 복잡한 작업이 많아서 git hub actions를 사용해보기로 했다. git hub actions는 jenkins에 비해 서버가 따로 필요 없이 클라우드 위에서 동작하고 레포지토리가 public이면 무료다! 그리고 yaml 파일을 통해 쉽게 환경을 만들 수 있다는 장점이 있다.

 

 

프로젝트 폴더에 .github 디렉토리를 만들고 workflows 디렉토리를 생성해준다. 그 안에 릴리즈를 담당하는 yaml 파일과 docker 작업을 위한 yaml 파일을 작성해주었다.

 

 

먼저 docker 작업을 위한 yaml 파일이다.

name: "[Push] Build dev"

on:
  push:
    branches:
      - main
    paths-ignore:
      - '.github/**'
      - 'src/VERSION'
  workflow_dispatch:

jobs:
  versioning:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.versioning.outputs.VERSION }}
    steps:
      - uses: actions/checkout@v2
      - name: get current date
        run: |
          sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
          echo "TIME=$(date +'%Y%m%d.%H%M%S')" >> $GITHUB_ENV

      - name: set version with current date
        id: versioning
        run: |
          echo "VERSION=$(cat src/VERSION | cut -c 2-).${{ env.TIME }}" >> $GITHUB_OUTPUT
          echo "::set-output name=VERSION::$(cat src/VERSION | cut -c 2-).${{ env.TIME }}"

  docker:
      if: github.repository_owner == 'kiku99'
      needs: versioning
      runs-on: ubuntu-latest
      env:
        VERSION: ${{ needs.versioning.outputs.version }}
      steps:
        - uses: actions/checkout@v2
        - name: get service name
          run: |
            echo "SERVICE=$(echo ${{ github.repository }} | cut -d '/' -f2)" >> $GITHUB_ENV

        - name: Upload docker
          uses: docker/build-push-action@v1
          with:
            path: .
            repository: kiku99/${{ env.SERVICE }}
            username: ${{ secrets.DOCKER_USERNAME }}
            password: ${{ secrets.DOCKER_PASSWORD }}
            tags: ${{ env.VERSION }}

 

yaml 파일을 보면 main branch에 변경이 일어날 때 아래 정의한 job 들이 실행되는 구조를 알 수 있다. job은 2가지로 나뉘는데 버전 작업을 담당하는 versioning과 도커 작업을 담당하는 docker로 나누었다.

 

versiong 과정에서는 프로젝트의 버전과 현재 날짜와 시간을 조합하여 최종 버전을 만들고 github 환경변수에 저장한다.

docker 과정에서는 현재 프로젝트로 도커 이미지를 만들고  버전과 함께 도커 허브에 푸시한다. 여기서 username과 password는 git hub 레포지토리의 설정에서 도커 허브의 계정 정보를 넣어주면 된다.

 

다음은 릴리즈 작업을 위한 yaml 파일이다.

name: "[Dispatch] Release"

on:
  push:
    branches:
      - main

jobs:
  setup-build-deploy:
    name: Setup, Build, and Deploy
    runs-on: ubuntu-latest
    permissions:
      packages: write
      contents: write
      id-token: write

    steps:
    - name: Bump version and push tag
      id: tag_version
      uses: mathieudutour/github-tag-action@v6.1
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}

    - name: Create a GitHub release
      uses: ncipollo/release-action@v1
      with:
        tag: ${{ steps.tag_version.outputs.new_tag }}
        name: Release ${{ steps.tag_version.outputs.new_tag }}
        body: ${{ steps.tag_version.outputs.changelog }}

 

마찬가지로 main branch에서 변경이 일어날 때 job이 실행되도록 설정해주었다. 작업은 태그를 만드는 작업과 릴리즈를 담당한 작업으로 나누었는데, 두 작업 모두 maketplace에 있는 자동화 tool을 사용했다. 그리고 아직 태그와 릴리즈에 대해 익숙하지 않아서 더 세부적인 설정은 하지 않았다.

참고로 github_token은 자동으로 생성되는 토큰이었다. 여기서 좀 헤맴...

 

 

이렇게 yaml 파일을 잘 작성해주면 actions 탭에 이렇게 워크플로우가 생성되어있는 모습을 볼 수 있다. 

 

 

요런식으로 각 워크플로우마다 해당 작업들의 그래프와 실행 여부를 볼 수 있다. docker 작업이 꽤 걸리는걸 볼 수있는데 실제로 이미지 빌드하는데 시간이 걸리긴 한다.

 

 

또 작업을 누르면 이런식으로 작업 내용과 로그를 볼 수 있다. 여러 모로 편리한 기능.

 

이렇게 pipleline을 구축함으로써 다른 브랜치에서 작업을 하다가 릴리즈를 하기 위해 main 브랜치에 병합을 하면, 자동으로 릴리즈와 도커 이미지를 빌드하고 푸시를 하게 된다. 이제부턴 개발에만 집중하면 될 거 같다.