프로젝트의 배포를 위해 github action을 이용하여 무중단 배포를 하게되었다
처음에는 백엔드쪽 서버 배포를 위해 다음과 같이 gradle.yml를 작성했다.
name: Java CI with Gradle
on:
push:
branches: [ "dev" ]
pull_request:
branches: [ "dev" ]
permissions:
contents: read
env:
S3_BUCKET_NAME: jungyeon222
RESOURCE_PATH: ./Server/tripAdvisor/tripAdvisor/src/main/resources/application.yml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Set yml file
uses: microsoft/variable-substitution@v1
with:
files: ${{ env.RESOURCE_PATH }}
env:
spring.datasource.url: ${{ secrets.RDS_HOST }}
spring.datasource.username: ${{ secrets.RDS_USERNAME }}
spring.datasource.password: ${{ secrets.RDS_PASSWORD }}
jwt.key: ${{ secrets.JWT_KEY }}
naver.map.client.id: ${{ secrets.NAVER_CLIENT_ID }}
naver.map.client.secret: ${{ secrets.NAVER_CLIENT_SECRET }}
- name: Add permission
run: chmod +x gradlew
working-directory: ./Server/tripAdvisor/tripAdvisor
- name: Build with Gradle
run : ./gradlew clean build --exclude-task test
working-directory: ./Server/tripAdvisor/tripAdvisor
# build한 후 프로젝트를 압축합니다.
- name: Make zip file
run: zip -r ./tripAdvisor.zip .
shell: bash
# Access Key와 Secret Access Key를 통해 권한을 확인합니다.
# 아래 코드에 Access Key와 Secret Key를 직접 작성하지 않습니다.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} # 등록한 Github Secret이 자동으로 불려옵니다.
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # 등록한 Github Secret이 자동으로 불려옵니다.
aws-region: ap-northeast-2
# 압축한 프로젝트를 S3로 전송합니다.
- name: Upload to S3
run: aws s3 cp --region ap-northeast-2 ./tripAdvisor.zip s3://jungyeon222/tripAdvisor.zip
# CodeDeploy에게 배포 명령을 내립니다.
- name: Code Deploy
run: >
aws deploy create-deployment --application-name project034
--deployment-config-name CodeDeployDefault.AllAtOnce
--deployment-group-name project034-group
--s3-location bucket=jungyeon222,bundleType=zip,key=tripAdvisor.zip
- name: Set yml file
uses: microsoft/variable-substitution@v1
with:
files: ${{ env.RESOURCE_PATH }}
env:
spring.datasource.url: ${{ secrets.RDS_HOST }}
spring.datasource.username: ${{ secrets.RDS_USERNAME }}
spring.datasource.password: ${{ secrets.RDS_PASSWORD }}
jwt.key: ${{ secrets.JWT_KEY }}
naver.map.client.id: ${{ secrets.NAVER_CLIENT_ID }}
naver.map.client.secret: ${{ secrets.NAVER_CLIENT_SECRET }}
환경변수 설정을위해 위와 같이 yml file이 어디있는 지 path를 지정해주고, github secret 을 이용해 key설정을 해주었다.
액션결과 성공적으로 S3에 올라간 것을 확인할 수 있었고
codedeploy를 이용한 배포까지 잘되었다.
우리는 s3의 정적 호스팅을 이용한 배포였기 때문에 결국엔 s3의 엔드포인트에서 웹페이지 접속이 되어야 했다.
무슨 이유인지 s3를 통한 접속 시 아래와 같은 페이지를 볼 수 있었다.
보통의 경우 아래쪽의 key : index.html 이아니라 error.html로 나오고, 그것은 앞 글에서 다뤘던 s3의 정적웹사이트 호스팅 설정을 통해서 해결할 수 있는데, 나의 경우는 좀 달랐다.
원인을 찾던 중 수동빌드할때의 과정이 생각나게 되었다.
수동빌드 과정은 서버 배포 과정과 클라이언트 배포 과정으로 나뉜다.
서버배포
- EC2에서 git을 불러온다.
- EC2상에서 수동 build를 진행한다.
- EC2에서 서버를 실행한다.
클라이언트 배포
- 빌드전 의존성 모듈 설치
- 환경변수 설정(.env)
- 터미널 상에서 build(npm run build)
- build 결과물을 s3에 수동으로 업로드
결국 위에 작성했던 gradle.yml 파일을 이용한 배포과정은 클라이언트 배포 과정이 없어서 브라우저에서 렌더링을 못하고 있던 것이었다.
즉, 빌드를 통해 html로 바꿔줘야 UI를 볼 수 있었다.
그런데, 클라이언트 빌드 과정을 github action으로 어떻게 진행해야하는 가...
위의 파일을 보고 조금 힌트를 얻을 수 있었는데,
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
steps에서는 JDK 11 으로 set up을 해준 후 다음 단계들을 진행하기때문에, 클라이언트 빌드를 위해서는 다른 actions를 새로 만들던지, 하나의 gradle.yml파일에 합쳐서 빌드를 하던지 해야 할 것 같았다.
jobs:
build:
runs-on: ubuntu-latest
현재 이 코드는 jobs의 아래에 build라는 이름의 작업을 추가한다는 뜻이다 즉, build1, build2 로 2개를 추가할 수도있다.
build2:
needs: build1
runs-on: ubuntu-latest
name: Java CI with Gradle
on:
push:
branches: [ "dev" ]
pull_request:
branches: [ "dev" ]
permissions:
contents: read
env:
S3_BUCKET_NAME: jungyeon222
RESOURCE_PATH: ./Server/tripAdvisor/tripAdvisor/src/main/resources/application.yml
jobs:
build1:
runs-on: ubuntu-latest
steps:
- name: Checkout source code.
uses: actions/checkout@v2
- name: Install dependencies
run: npm install
working-directory: ./Client
- name: Build
run: npm run build
working-directory: ./Client
env:
REACT_APP_HOST: ${{ secrets.REACT_APP_HOST }}
REACT_APP_KAKAO_MAP_KEY: ${{ secrets.REACT_APP_KAKAO_MAP_KEY }}
REACT_APP_GEOCODER_KEY: ${{ secrets.REACT_APP_GEOCODER_KEY }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} # 등록한 Github Secret이 자동으로 불려옵니다.
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # 등록한 Github Secret이 자동으로 불려옵니다.
aws-region: ap-northeast-2
- name: Upload to S3
run: |
aws s3 sync \
--region ap-northeast-2 \
build s3://jungyeon222 \
--delete
working-directory: ./Client
#----------------------------------------------------------------------------------------
build2:
needs: build1
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Set yml file
uses: microsoft/variable-substitution@v1
with:
files: ${{ env.RESOURCE_PATH }}
env:
spring.datasource.url: ${{ secrets.RDS_HOST }}
spring.datasource.username: ${{ secrets.RDS_USERNAME }}
spring.datasource.password: ${{ secrets.RDS_PASSWORD }}
jwt.key: ${{ secrets.JWT_KEY }}
naver.map.client.id: ${{ secrets.NAVER_CLIENT_ID }}
naver.map.client.secret: ${{ secrets.NAVER_CLIENT_SECRET }}
- name: Add permission
run: chmod +x gradlew
working-directory: ./Server/tripAdvisor/tripAdvisor
- name: Build with Gradle
run : ./gradlew clean build --exclude-task test
working-directory: ./Server/tripAdvisor/tripAdvisor
# build한 후 프로젝트를 압축합니다.
- name: Make zip file
run: zip -r ./tripAdvisor.zip .
shell: bash
# Access Key와 Secret Access Key를 통해 권한을 확인합니다.
# 아래 코드에 Access Key와 Secret Key를 직접 작성하지 않습니다.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} # 등록한 Github Secret이 자동으로 불려옵니다.
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # 등록한 Github Secret이 자동으로 불려옵니다.
aws-region: ap-northeast-2
# 압축한 프로젝트를 S3로 전송합니다.
- name: Upload to S3
run: aws s3 cp --region ap-northeast-2 ./tripAdvisor.zip s3://jungyeon222/tripAdvisor.zip
# CodeDeploy에게 배포 명령을 내립니다.
- name: Code Deploy
run: >
aws deploy create-deployment --application-name project034
--deployment-config-name CodeDeployDefault.AllAtOnce
--deployment-group-name project034-group
--s3-location bucket=jungyeon222,bundleType=zip,key=tripAdvisor.zip
jobs 하위에 build1, build2 로 해서 클라이언트빌드와 서버 빌드를 동시에 작성했고, build2에 build1이 선행되도록 의존성을 추가해주었다.
이렇게하면 github actions 에서 다음과 같이 두 작업이 연결되어서 진행되는것을 볼 수 있다.
또한, s3 버켓에도 서버 zip 파일 외에 클라이언트 빌드 파일이 잘 올라간것을 확인 할 수 있다.
ref :
https://zzsza.github.io/development/2020/06/06/github-action/
https://www.daleseo.com/github-actions-basics/
https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/cli-services-s3-commands.html
https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/sync.html
https://velog.io/@zero-black/github-actions-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%B9%8C%EB%93%9C%ED%95%98%EA%B8%B0