틔움랩

Github action을 통한 Spring CI/CD 설정

한뜨응규 2025. 1. 25. 12:04
반응형

프로젝트를 시작할 때마다, 가장 먼저하는 CI/CD 설정이다.

기존에는 대부분 Jenkins를 통해 CI/CD 설정을 했었지만, 이번 프로젝트는 별도의 서버를 구성할 여유가 없어 Github에서 제공하는 Github action을 통해 설정을 해보려고 한다.

 

우선 Github의 리포지토리에서 actions 탭을 클릭한다.

그러면 이런 식으로 페이지가 나올텐데, 여기에 gradle을 검색한다.

 

그리고 이 action을 configure해준다.

 

이거 클릭하면 코드의 .github 폴더에 yml 파일이 생길텐데, 해당 파일을 수정해주면 된다.

 

크게 build와 deploy로 나뉜다.

build는 Gradle을 바탕으로 spring을 빌드하는 부분이고, deploy는 빌드된 jar파일을 서버로 전송하여 배포하는 부분이다.

 

name: CI/CD for develop branch

on:
  push:
    branches: [ "develop" ]
  pull_request:
    branches: [ "develop" ]
  workflow_dispatch:
    

jobs:
  build:

    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
    - uses: actions/checkout@v4
    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin'
    - name: Setup Gradle
      uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582

    - name: Grant execute permission for gradlew
      run: chmod +x ./gradlew
      working-directory: ./WAS

    - name: Build with Gradle Wrapper
      run: ./gradlew build
      working-directory: ./WAS
      
    - name: Scp to EC2
      uses: appleboy/scp-action@master
      with:
        host: ${{ secrets.SERVER_IP }}
        username: ${{secrets.SSH_USER}}
        key: ${{secrets.SSH_PRIVATE_KEY}}
        source: |
          WAS/build/libs/{빌드된 파일 이름}.war
        target: was/
      
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.5.4
        with:
          ssh-private-key: ${{secrets.SSH_PRIVATE_KEY}}
          
      - name: Deploy Docker Container
        run: |
          ssh -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SERVER_IP}} << 'EOF'
          cd was
          docker stop {컨테이너 이름} && docker rm {컨테이너 이름} && docker rmi {이미지 이름}:latest
          docker build -t {이미지 이름} .
          docker-compose up -d
          EOF

 

우선 작성한 파일은 다음과 같다.

 

step에서 하나씩 뜯어보도록 하자.

  • build
    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin'
    - name: Setup Gradle
      uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582

이 부분은 자바와 gradle을 준비하는 부분이다.

큰 이상이 없다면 아마 고정적으로 사용할 것 같다.

 

    - name: Grant execute permission for gradlew
      run: chmod +x ./gradlew
      working-directory: ./WAS

    - name: Build with Gradle Wrapper
      run: ./gradlew build
      working-directory: ./WAS

이 부분은 빌드하는 부분이다.

gradlew에 실행 권한을 부여하고, ./gradlew build를 통해 스프링부트를 빌드한다.

만약 테스트와 관련된 명령어가 있다면, 이곳에 추가하면 된다.

 

아래를 보면 working-directory가 설정되어 있는 것을 볼 수 있는데, 만약 빌드하는 폴더가 루트 폴더가 아니라면 해당 명령어를 통해 폴더를 지정해주어야 한다.

 

    - name: Scp to EC2
      uses: appleboy/scp-action@master
      with:
        host: ${{ secrets.SERVER_IP }}
        username: ${{secrets.SSH_USER}}
        key: ${{secrets.SSH_PRIVATE_KEY}}
        source: |
          WAS/build/libs/{빌드된 파일}.war
        target: was/

이제 빌드된 jar(war) 파일을 서버로 전송하는 부분이다.

당연히 서버의 ip, 사용자 이름, pem 키가 필요하다.

이런 부분은 yml 파일에 작성할 수 없기 때문에, 해당 Repository의 설정에 환경변수로 추가해주도록 하자.

 

pem키를 환경변수로 추가할 때는 위, 아래 boundary까지 그냥 추가해주면 된다.

source는 빌드된 파일(결과물)이고, target은 해당 서버에서 어떤 폴더에 저장할 것인지를 적어주면 된다.

 

이렇게 작성하면 빌드 후, 파일이 서버에 저장되게 된다.

그럼 이제 해당 파일을 통해 배포를 설정해주어야 한다.

 

 

  • deploy

해당 jar 파일을 docker container를 통해 실행해보자.

 

    needs: build

needs에 build를 추가해서, 해당 작업이 build 이후에 이루어질 수 있도록 해준다.

 

 

      - name: Setup SSH
        uses: webfactory/ssh-agent@v0.5.4
        with:
          ssh-private-key: ${{secrets.SSH_PRIVATE_KEY}}

서버에서 사용할 pem키를 등록해준다.

 

      - name: Deploy Docker Container
        run: |
          ssh -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SERVER_IP}} << 'EOF'
          cd was
          docker stop {컨테이너 이름} && docker rm {컨테이너 이름} && docker rmi {이미지 이름}:latest
          docker build -t {이미지 이름} .
          docker-compose up -d
          EOF

 

그리고는 이제 원격 서버에 접속해 해당 파일을 바탕으로 도커를 빌드한다.

원격 서버에서 추가적으로 실행하고 싶은 부분이 있다면, 저 안에 추가해주면 된다.

 

이제 작성이 모두 완료되었으니, 실행해보도록 하자.

위의 on에 workflow_dispatch:를 지정해주면 직접 실행 할 수도 있다.

 

 

이렇게 초록색으로 체크표시가 된다면 성공한 것이다.

서버에서도 배포가 완료된 것을 확인 할 수 있었다.