Github Actions로 CI 구축하기 (with env.yml 관리)

meong·2023년 10월 5일
2
post-thumbnail

CI 란?

CI (Continuous Integration, 지속적인 통합)는 소프트웨어 개발에서 개발자들이 코드를 지속적으로 통합하고 자동화된 빌드와 테스트를 통해 소프트웨어 품질을 높이며 버그를 신속하게 발견하고 수정하는 프로세스를 의미한다

CI 구축 목적?

저희 팀은 각 브랜치에서 develop 브랜치로 머지될 때, 자동으로 빌드&테스트를 수행하여
develop 브랜치는 바로 배포해도 문제가 없는 브랜치임을 보장하고자 CI 설정을 해줬습니다!

Github Actions로 CI 구축하기

1. workflow 생성

Repository 페이지 [ Actions ] 탭에서 [ Java with Gradle ]을 선택해줍니다

그러면 [ .github/workflows/ ] 하위에 yml 파일이 하나 생성되며 이 파일에 명령어를 작성해주면 됩니다
(이때 yml 파일 이름은 수정 가능합니다!)

workflow 구조

name: 
on:
jobs:
	steps:

workflow

  • 한개 이상의 job을 실행할 수 있는 자동화된 작업

name

  • workflow의 이름 정의
  • [ Actions ] 탭에 보여지는 이름입니다.

on

  • 해당 workflow를 실행시키는 이벤트(트리거)와 브랜치 정의
  • 이벤트 ex) push, pull request, issue 등

jobs

  • 자동으로 수행할 작업들을 정의
  • 한가지 러너안에서 실행되는 여러가지 step들의 모음
  • 각각의 step들은 일종의 shell script 처럼 실행
  • Step들은 순서에 따라 실행되며 Step 끼리 데이터들을 공유할 수 있음
  • Job은 다른 Job에 의존관계를 가질 수 있으며, 병렬 실행도 가능

workflow 코드

전체적인 흐름을 보면 레포지토리의 최신 코드를 복사해와서 Gradle build를 수행하는 코드이다.

name: Java CI with Gradle PR Test			# workflow의 이름 

on:
  pull_request:								# workflow를 실행시키는 이벤트(트리거)
    branches: [ "develop", "main" ]			# 적용 브랜치 

jobs:
  test:										# job 이름 
    runs-on: ubuntu-latest					# run 할 운영체제 
    steps:
      - name: Checkout						# step 이름
        uses: actions/checkout@v3			# 리포지토리의 최신 소스 코드를 workflow의 작업 디렉토리로 복사
  
      - name: Set up JDK 11
        uses: actions/setup-java@v3 		# java 버전 설정 
        with:
          distribution: 'temurin'
          java-version: '11'
 
      - name: Cache Gradle packages
        uses: actions/cache@v2				# Gradle dependency 캐싱 설정(테스트 속도 향상)
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            ${{ runner.os }}-gradle-
            
      - name: Grant execute permission for gradlew
        run: chmod +x gradlew				# Gradle wrapper 파일 실행 권한 부여
        
      - name: Build with Gradle
        run: ./gradlew build				# Gradle build를 수행

2. Secrets로 env.yml 파일 생성하기

깃허브에 올리지 못하는 Secret key 정보가 있고 env.yml 파일에 환경 변수로 관리한다면
Actions 실행 시 이를 참조하는 코드에서 빌드 오류가 발생한다.

이를 해결하기 위해 Secrets를 활용하여 Actions 실행 시에만 env.yml 파일에 내용이 채워지도록 설정 해줘야한다.

1. Secrets 설정

[ Settings ] - [ Secrets and variables ] - [ Actions ] 로 이동해서 [ new repository secret ] 클릭

Secret 이름을 설정하고
안에 들어갈 데이터를 base64로 인코딩 하여 입력한다
(base64로 인코딩은 필수는 x. 원문 그대로 넣어도 상관은 없음)

⚠️ 주의사항
 Secret은 한 번 설정하면 설정한 내용은 볼 수 없다. 수정이 가능하지만 이전 값은 볼 수 없고 덮어쓰는 방식 ! 
 때문에 로컬에 값을 저장해두어야한다. 

2. Actions 에 코드 추가

⚠️ 주의사항
 이 방식은 Secrets에 저장된 값을 빈 env.yml 파일에 echo로 copy 해주는 방식이다.
 따라서 빈 env.yml 파일이 깃허브 레포지토리에 존재해야한다!

Actions workflow에서 Secrets에 저장한 변수는 secrets.변수명 으로 참조한다.

 # 환경 변수 설정
 - name: Copy Secret To application module
   env:
   	 OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }}				# secrets 값
     OCCUPY_SECRET_DIR: ./application/src/main/resources 		# 레포지토리 내 빈 env.yml의 위치 (main)
     OCCUPY_SECRET_TEST_DIR: ./application/src/test/resources	# 레포지토리 내 빈 env.yml의 위치 (test)
     OCCUPY_SECRET_DIR_FILE_NAME: env.yml						# 파일 이름
     
   # base64 디코딩하여 파일에 secrets 값 복사 
   run: echo $OCCUPY_SECRET | base64 --decode > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME && 	
        echo $OCCUPY_SECRET | base64 --decode > $OCCUPY_SECRET_TEST_DIR/$OCCUPY_SECRET_DIR_FILE_NAME
             

해당 코드를 Checkout 과 Build with Gradle 사이에 작성한다.

최종 코드

name: Java CI with Gradle PR Test			

on:
  pull_request:								
    branches: [ "develop", "main" ]			

jobs:
  test:										
    runs-on: ubuntu-latest					
    steps:
      - name: Checkout						
        uses: actions/checkout@v3			
  
      - name: Set up JDK 11
        uses: actions/setup-java@v3 		
        with:
          distribution: 'temurin'
          java-version: '11'
          
     # 환경 변수 설정
     - name: Copy Secret To application module
       env:
         OCCUPY_SECRET: ${{ secrets.OCCUPY_SECRET }}				
         OCCUPY_SECRET_DIR: ./application/src/main/resources 		
         OCCUPY_SECRET_TEST_DIR: ./application/src/test/resources	
         OCCUPY_SECRET_DIR_FILE_NAME: env.yml						
       run: echo $OCCUPY_SECRET | base64 --decode > $OCCUPY_SECRET_DIR/$OCCUPY_SECRET_DIR_FILE_NAME && 	
            echo $OCCUPY_SECRET | base64 --decode > $OCCUPY_SECRET_TEST_DIR/$OCCUPY_SECRET_DIR_FILE_NAME
 
 	  # Gradle dependency 캐싱 설정(테스트 속도 향상)
      - name: Cache Gradle packages
        uses: actions/cache@v2				
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            ${{ runner.os }}-gradle-
            
      # Gradle wrapper 파일 실행 권한 부여
      - name: Grant execute permission for gradlew
        run: chmod +x gradlew	
        
      # Gradle build를 수행
      - name: Build with Gradle
        run: ./gradlew build				

3. Branch protection rule 설정

마지막으로, PR을 생성했을 때 Actions test를 통과 해야지만 merge가 가능하도록 설정을 해준다
[ Settings ]-[ Branches ]에서 [ Add rule ] 또는 [ 기존 rule Edit ] 선택

[ Require status checks to pass before merging ] 부분을 모두 체크하고
workflow jobs 를 지정해준다

지정 후 PR을 날려보면 Actions 테스트가 돌아가고 verified 가 뜨면
하단에 All checks have passed 로 바뀌면서 머지 버튼이 활성화 된다
(아래 사진은 Actions는 통과했는데 review가 없어서 아직 머지 버튼이 비활성화인 것)

회고

다른 사람의 코드 로직 하나하나 살펴볼 수 없고, pr을 올리는 과정에서 충돌이 날 수 도 있는데
이를 직접 실행 해서 빌드가 되는지 확인하는 것은 상당히 번거롭다.

이러한 번거로운 작업을 자동으로 해주는 것이 Actions라고 보면 된다.

Actions CI 를 도입하고 나서 개선된 점(편리한 점)을 보면
1. develop 브랜치를 pull 받고 실행 시켰을 때 오류가 나지 않는다.
2. 배포를 위해 빌드를 했을 때 오류가 나지 않는다.

특히 배포 과정에서 빌드 에러가 날 때가 가장 힘빠지고 답답했는데
CI 설정 이후로는 겪지 않아서 너무 만족스러웠다!

10페이지가 넘도록 고생해준 Actions 👍

profile
새싹 개발자

0개의 댓글