문제 상황: 나의 코드외의 팀원분의 코드들을 직접 병합하고 테스트하기가 번거로워졌음
-> 팀원분께서도 병합을 하시게하되 테스트를 자동화 할 수 있게해보자는 생각
-> CI(지속적인 통합)을 구현하자
라는 생각으로 CI를 구축해보기로 했다.
CI/CD에 구축에 이용툴이 주로 젠킨스와 깃액션으로 나뉘는데
나는 깃액션을 사용하기로 했다. 이유는
현재 프로젝트는 각 도메인별 브랜치가 있고 도메인별 기능 개발, 테스트가 끝나면 develop 브랜치에 병합후 테스트 -> main에 병합후 배포하는 과정으로 구현이 된 상태이다.
내가 생각한 CI는 Develop 브랜치에 병합을 시도할 때 빌드, 테스트를 수행하고 통과한다면 병합을 시켜주는 구조로 Develop에서 테스트를 마치고 main에서는 배포에만 신경 쓸 수 있는 환경이다.
develop에서 CI를 먼저 구현해야 하니 develop 브랜치에
.github/workflows 디렉토리를 생성해준다.
디렉토리를 생성하였으면 workflows 디렉토리에 깃액션에서 이용할 yml 설정 파일을 작성해준다.
name: Java CI with Gradle
on:
push:
branches: [ develop ]
pull_request:
branches: [ develop ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
env :
rds_end_point : ${{secrets.RDS_END_POINT}}
rds_secret_key : ${{secrets.RDS_SECRET_KEY}}
rds_user_name : ${{secrets.RDS_USER_NAME}}
storage_access_key : ${{secrets.STORAGE_ACCESS_KEY}}
storage_name : ${{secrets.STORAGE_NAME}}
storage_secret_key : ${{secrets.STORAGE_SECRET_KEY}}
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew clean build
제일 위부터 설명을하면
1. gradle을 이용한 ci
2. develop에서 push, pr 요청시 동작
3. ubuntu 최신버전에서 빌드(EC2와 같은 환경으로 선택함)
4. 환경변수 설정
5. 브랜치로 체크아웃
6. gradlew 실행 권한 부여
7. 빌드 -> 이전의 빌드 내용들을 모두 지우고 빌드
application.yml에 있는 민감한 정보들은 모두 환경변수로 대체되어 있으므로 로컬외의 환경에서는 환경변수를 따로 설정을 해주어야 정상적으로 빌드가 된다.
레포지토리의 설정에 들어가서 다음의 탭으로 들어가면 된다
settings의 경우 최초에는 레포지토리 생성자, 나머지 멤버는 권한 설정으로 이용이 가능하게 만들수 있다. 생성자라면 보안 걱정없이 변수들을 설정 해주면된다.
위에서 작성한 내용들은 빌드 테스트를 해주는것이고 해당 테스트의 통과여부에 따라 병합의 여부를 결정해주는 설정이 필요하다.
다시 settings로 들어가서 이번엔 branches 탭에서 require status checks to pass before murging에 체크를 해준뒤 깃액션의 빌드를 통과하면 병합이 가능하도록 설정값을 넣어주었다.
이제 develop에서 push, pr 명령이 실행되면 다음과 같이 actions에서
yml에 설정해놨던 과정들이 실행이 된다.
MovieVer2ApplicationTests > contextLoads() FAILED
java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:98
Caused by: org.springframework.beans.factory.BeanCreationException at AbstractAutowireCapableBeanFactory.java:1804
Caused by: org.hibernate.service.spi.ServiceException at AbstractServiceRegistryImpl.java:284
Caused by: org.hibernate.HibernateException at DialectFactoryImpl.java:100
통합 테스트중 발생한 에러로 DB 연결에 문제가 있음을 보여주는 에러 코드
로컬에서는 문제가 없었기에 제일 유력한 원인으로 환경변수를 예상했고
역시 깃액션 환경에서는 별도의 환경변수 설정이 없기에 발생한게 문제였다.
먼저 깃액션에 secrets 변수들을 추가해주었고
jobs:
build:
runs-on: ubuntu-latest
env :
rds_end_point : ${{secrets.RDS_END_POINT}}
rds_secret_key : ${{secrets.RDS_SECRET_KEY}}
rds_user_name : ${{secrets.RDS_USER_NAME}}
storage_access_key : ${{secrets.STORAGE_ACCESS_KEY}}
storage_name : ${{secrets.STORAGE_NAME}}
storage_secret_key : ${{secrets.STORAGE_SECRET_KEY}}
workflows의 파일안에 위의 코드를 추가해 환경 변수 설정을 해주고
secret의 환경변수들과 맵핑을 시켜주어 해결하였다.
실제 기업에서는 CI를 어떻게 구현하는지 매우 궁금하다
너무 간단하게 내가 생각하는 CI를 구현하게 되어서 불안한 마음이 있어 더 궁금한 것 같다. 레퍼런스들을 많이 보고 있지만 최근 트렌드에 맞는 정답이 뭔지가 궁금하다
다음은 CD를 만들 예정인데 CD까지 만든다면 문제점들이 보이게 될까? 하는 생각도 든다
어서 CD도 구현하며 더 공부를 해봐야겠다.