상황
- CI 작업을 위해서 프로젝트에 github action을 연동하던 중 마주친 에러.
- build 중 테스트가 돌아가면서 에러가 나버린다.
- 프로젝트의 datasource는 RDS mysql database를 연결해둔 상태였다.
발생한 에러
ApplicationTests > contextLoads() FAILED
java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
Caused by: org.springframework.beans.factory.BeanCreationException at AbstractAutowireCapableBeanFactory.java:1804
Caused by: javax.persistence.PersistenceException at AbstractEntityManagerFactoryBean.java:421
Caused by: org.hibernate.exception.JDBCConnectionException at SQLStateConversionDelegate.java:112
Caused by: com.mysql.cj.jdbc.exceptions.CommunicationsException at SQLError.java:174
Caused by: com.mysql.cj.exceptions.CJCommunicationsException at NativeConstructorAccessorImpl.java:-2
Caused by: java.net.SocketTimeoutException at PlainSocketImpl.java:-2
- github action log 전체
에러 코드를 읽어보니, 결국 MySQL 데이터베이스와 연결이 되지 않아서 SocketTimeOut이 발생했다는 것이다.
왜 그럴까.. 하면서 많은 시도를 해봤다.
1. 로컬에서 빌드 => 성공
2. 데이터베이스 연결 확인 => intellj에서 database로 해당 MySQL server 접속 확인
3. ec2에서 RDS 원격 접속 => 접속 성공 확인
4. application.yml의 datasource를 RDS에서 localhost로 변경 => 동일하게 MySQL 문제 발생
5. ec2에서 빌드 => 실패
6. datasource를 h2로 변경 => 빌드 테스트까지 통과!
따라서 로컬에서는 빌드되고, 해당 디비 서버 접속 잘 되는데 왜 github action CI 환경이나 ec2에서만 connectionTimeOut이 날까?? 였다.
그리고 h2로 바꾸니 성공하는 것으로 봐서 무조건 MySQL 문제라고 생각했다.
결론
결론을 말하자면, MySQL Server가 running 상태여야 한다.
하필, 정말 운이 없게도 ec2에서 mysql server error가 나던 상태였고, (그래서 동일한 에러 로그가 떴다)
CI Test 환경에서도 빌드 스크립트에 디비 서버 관련 코드는 없었다. (MySQL setup이 없었다)
따라서 해당 테스트 서버 환경에서 connection error가 난 것이다.
- name: Setup MySQL
uses: samin/mysql-action@v1
with:
character set server: 'utf8'
mysql database: 데이터베이스 이름
mysql user: 자신 id
mysql password: ${{ secrets.MYSQL_PASSWORD }} // github에 secret key 등록
github action 스크립트에 Set Up JDK와 Build with Gradle 사이에 추가시켜줬더니 정상 동작했다.
(빌드되기 전에만 세팅해주면 된다.)
나는 어차피 RDS 서버를 이용하니까 잘 접속만 되면 되지!라고 생각했는데, 테스트할 때 MySQL 서버가 켜져 있어야 테스트가 정상적으로 돌아가는 것 같다.
교훈
- 테스트 시 그냥 h2 데이터베이스 쓰자..