CI/CD 시간을 줄여보자(Github Actions)

고승원·2023년 3월 30일
0

TIL

목록 보기
12/24

서론

새로운 pr을 생성하고, 머지할때 두근대는 마음으로 성공 여부를 기다린다.

프로젝트 배포 자동화를 Git Actions을 이용하고 있는데, 5분 가까운 시간이 소요된다는건 오래걸린다 생각이 들어 ci/cd 스크립트를 수정해서 시간을 줄여보도록 한다.

스크립트

CI

기존

name: CI

on:
  pull_request:
    branches:
      - develop

jobs:
  build:
    runs-on: ubuntu-22.04

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'

      #CI
      - name: Generate environment file
        run: |
          mkdir -p env
          echo "${{secrets.DOCKER_COMPOSE_ENV}}" >> env/docker-compose.env
          echo "${{secrets.LOCAL_SPRING_ENV}}" >> env/spring.env
          echo "${{secrets.AWS_ENV}}" >> env/aws.env
          echo "${{secrets.JWT_ENV}}" >> env/jwt.env
          echo "${{secrets.OAUTH2_ENV}}" >> env/oauth2.env
          echo "${{secrets.TEST_DB_ENV}}" >> env/test-db.env
      - name: Run docker-compose
        uses: isbang/compose-action@v1.4.1
        with:
          compose-file: "./docker/docker-compose.yml"

      - name: Get execution permission to gradlew
        run: chmod +x ./gradlew

      - name: Build with Gradle
        run: ./gradlew clean build

기존의 ci 방식을 살펴보면 secrets를 env파일로 변환 후 도커컴포즈 환경에서 빌드하는 방식이다.

시간을 줄일 방법은 그래들 캐싱과 빌드과정 간소화이다.

그래들 캐싱

- name: Caching gradle
  uses: actions/cache@v3
  with:
  	path: |
    	~/.gradle/caches
        ~/.gradle/wrapper
    key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
    restore-keys: |
    	${{ runner.os }}-gradle-

그래들 또는 프로퍼티가 변경되는경우 path 하위 폴더를 캐싱한다.
그렇지 않은 경우 캐시된 그래들을 사용한다.

캐시 빌드과정 간소화

	- name: Test with Gradle
      run: ./gradlew test

빌드는 테스트, 컴파일, jar파일 생성 세가지로 나뉘는데 ci에서는 테스트만 실행하도록 변경했다.
하단에 수정했습니다.

결과

기존에 4분 20초대의 CI 소요 시간이

1분 30초대로 상당히 단축되었다!!

cd

기존

name: CD

on:
  push:
    branches:
      - develop

jobs:
  build:
    runs-on: ubuntu-22.04

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Generate environment file
        run: |
          mkdir -p env
          echo "${{secrets.DOCKER_COMPOSE_ENV}}" >> env/docker-compose.env
          echo "${{secrets.DEV_SPRING_ENV}}" >> env/spring.env
          echo "${{secrets.AWS_ENV}}" >> env/aws.env
          echo "${{secrets.JWT_ENV}}" >> env/jwt.env
          echo "${{secrets.DEV_OAUTH2_ENV}}" >> env/oauth2.env
          echo "${{secrets.TEST_DB_ENV}}" >> env/test-db.env
      - name: Run docker-compose
        uses: isbang/compose-action@v1.4.1
        with:
          compose-file: "./docker/docker-compose.yml"

      - name: Get execution permission to gradlew
        run: chmod +x ./gradlew

      - name: Build with Gradle
        run: ./gradlew clean build

      - name: Make zip file
        run: zip -qq -r ./$GITHUB_SHA.zip .
        shell: bash

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

      - name: Upload to AWS S3
        run: aws s3 cp --region ap-northeast-2 $GITHUB_SHA.zip s3://${{secrets.AWS_S3_BUCKET_NAME}}/$GITHUB_SHA.zip

      - name: Code Deploy
        run: |
          aws deploy create-deployment \
          --application-name ${{ secrets.CODE_DEPLOY_APPLICATION_NAME }} \
          --deployment-config-name CodeDeployDefault.AllAtOnce \
          --deployment-group-name ${{ secrets.CODE_DEPLOY_DEPLOYMENT_GROUP_DEV }} \
          --s3-location bucket=${{secrets.AWS_S3_BUCKET_NAME}},bundleType=zip,key=$GITHUB_SHA.zip

cd는 ci와 다르게 restDocs를 사용하기 때문에 그래들 캐싱만 적용했다.

마무리

평소에 사용하던 스크립트가 정말 필요한 것인지 한번 더 검토해볼 필요가 있다. 필요하지 않은 과정을 수행하고 있는지, 필요한 과정이 누락되었는지 한번 더 면밀히 살펴보는 시간을 가져보자.


추가

ci과정에서 테스트만 수행하도록 사용했었다. 하지만, ci시에 빌드를 한다면 테스트 단계에서 코드를 실행하기 전에 컴파일 및 패키징 오류 등을 미리 잡아낼 수 있다. 빌드 단계를 건너뛰고 테스트만 진행하면 이러한 오류를 발견할 수 없고, 테스트 실패로 인해 불필요한 디버깅 시간을 허비할 수 있다.

이와 같은 이유로 다시 ci에서 build하도록 변경했다.

결론적으로 ci, cd 모두 build를 하고 있다. 두 번의 빌드는 효율적이지 않다 생각하는데, 그렇다고 ci에서 항상 jar파일을 업로드하면 s3가 부담을 가지는데 좋은 방법이 없을까 생각이 든다.

profile
봄은 영어로 스프링

0개의 댓글