CI(Continuous Integration, 지속적인 통합)란, 개발자가 코드 변경 사항을 커밋할 때마다 자동으로 빌드, 테스트 등을 실행하여 코드의 안정성과 통합성을 검증하는 단계 이다.
main 브랜치에서 push 및 main 브랜치로 pr후 개발자가 직접 테스트를 해주어야 하지만, Github action을 사용하면 자동으로 CI를 해줄 수 있다. 실수로 테스트를 놓치거나 할 가능성이 낮아져서 좋다.
이런 이유로 좀 더 테스트를 잘 작성하는 게 중요한 것 같다.
.github/workflow/ci-test.yml
git action에서 CI 자동화를 하려면, 워크플로우를 작성해주어야 한다. 마법처럼 github가 테스트를 해주지는 않고, 적절한 설정이 필요한 것이다. 현재 내 프로젝트 환경에 맞춰서 yml을 작성해준다.
# 워크플로우 이름을 정의합니다.
name: Java CI with Gradle
# 이 워크플로우가 실행될 조건(이벤트)을 설정합니다.
on:
# main 브랜치에 코드가 푸시(push)될 때 실행됩니다.
push:
branches: [ main ]
# main 브랜치를 대상으로 하는 pull request가 생성되거나 업데이트될 때 실행됩니다.
pull_request:
branches: [ main ]
# 실행할 작업(jobs)을 정의합니다.
jobs:
# 'build'라는 이름의 작업(job)을 정의합니다.
build:
# 이 작업은 최신 Ubuntu 환경에서 실행됩니다.
runs-on: ubuntu-latest
# 작업 내에서 순차적으로 실행될 단계(steps)를 나열합니다.
steps:
# 리포지토리를 체크아웃(다운로드)하는 단계입니다.
- name: Checkout repository
uses: actions/checkout@v3 # GitHub에서 제공하는 checkout 액션을 사용해 소스 코드를 가져옵니다.
# JDK 17을 설치하고 설정하는 단계입니다.
- name: Set up JDK 17
uses: actions/setup-java@v3 # GitHub의 setup-java 액션을 사용해 JDK를 설치합니다.
with:
java-version: '17' # 설치할 자바 버전을 17로 지정합니다.
distribution: 'temurin' # Temurin 배포판을 사용하여 JDK를 설치합니다.
# gradlew 스크립트에 실행 권한을 부여하는 단계입니다.
- name: Grant execute permission for gradlew
run: chmod +x gradlew # gradlew 파일에 실행 권한을 추가합니다.
# Gradle 명령어를 실행하여 프로젝트를 빌드하고 테스트를 수행하는 단계입니다.
- name: Build and run tests
run: ./gradlew clean test # gradlew를 통해 클린 빌드 후, 테스트를 실행합니다.
로컬 파일 저장 이슈
빌드에 실패했다. 테스트시 중요한 것은, 임베디드 메모리 DB를 사용하고, 무언가에 의존하지 않는 것이 중요하다. 현재 내가 의존하고 있는 게 뭘까 생각해보니, 파일을 저장하는 서비스에서 로컬에 저장하도록 의존하고 있었다.
appication.properties 파일에 저장해둔 file.dir을 가져다가 서비스 계층에서 사용중이다.
file.dir=/Users/kimcheoljun/weblibrary/file/
public class LocalFileStore implements FileStore {
@Value("${file.dir}")
private String fileDir;
...
@Override
public UploadFile storeFile(MultipartFile multipartFile) {
if (multipartFile.isEmpty()) {
return null;
}
String originalFilename = multipartFile.getOriginalFilename();
String storeFileName = FileStore.createStoreFileName(originalFilename);
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
try {
multipartFile.transferTo(new File(getFullPath(storeFileName)));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
});
return new UploadFile(originalFilename, storeFileName);
}
...
}
test/application.properties에서는 다음과 같이 file.dir을 넣어주었다. 이렇게 넣어 주면 빌드가 성공한다.
file.dir=/tmp/test-storage