
이번 팀프로젝트에서는 CI를 맡아서 진행하게 되었습니다.
서비스 배포는 예정이 없었기 때문에 Jenkins와 Github Actions 중 Github Actions를 채택했습니다.
그러나 현재 PR이 올라오는 족족 모든 CI가 실패하는 문제가 있어 이를 해결하려 합니다.
ci.yamlname: ci pipelines
on:
pull_request:
branches:
- dev
push:
branches: [ dev ]
jobs:
all:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Cache Gradle packages
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Grant
run: chmod +x ./gradlew
- name: Create application-build.yaml from secret
run: |
mkdir -p ./src/main/resources/yml
echo "${{ secrets.APPLICATION_BUILD_YAML }}" > ./src/main/resources/yml/application-build.yaml
- name: Build with Gradle
run: ./gradlew build -x test
- name: Run tests
env:
SLACKBOT_TOKEN: ${{ secrets.SLACKBOT_TOKEN }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
S3_PUBLIC: ${{ secrets.S3_PUBLIC }}
S3_SECRET: ${{ secrets.S3_SECRET }}
S3_REGION: ${{ secrets.S3_REGION }}
run: ./gradlew test -Dspring.profiles.active=build
- name: Notify on success
if: success()
run: echo "All tests passed!"
- name: Notify on failure
if: failure()
run: echo "Some tests failed!"
테스트가 모두 성공하는지를 확인하기 위해서는 application-dev.yaml 대신에 다른 파일을 읽어야 합니다.
그렇기 때문에 application-buil.yaml이라는 파일을 생성했습니다.
Actions secrets에 APPLICATION_BUILD_YAML를 두고, 그 값을 읽어와서 CI Action이 돌아가게 구성했습니다.
APPLICATION_BUILD_YAML의 값은 아래와 같습니다.
APPLICATION_BUILD_YAMLspring:
datasource:
url: jdbc:h2:mem:test
username: sa
password:
driverClassName: org.h2.Driver
h2:
console:
enabled: true
config:
import: optional:file:.env[.properties]
data:
redis:
host: localhost
port: 6379
jpa:
hibernate:
ddl-auto: create-drop
properties:
hibernate:
auto_quote_keyword: true
highlight_sql: true
show_sql: true
format_sql: true
database-platform: org.hibernate.dialect.H2Dialect
servlet:
multipart:
max-file-size: 5MB
max-request-size: 5MB
enabled: true
cloud:
aws:
s3:
bucket: ${S3_BUCKET}
credentials:
accessKey: ${S3_PUBLIC}
secretKey: ${S3_SECRET}
region:
static: ${S3_REGION}
stack:
auto: false
slackBotToken: ${SLACKBOT_TOKEN}
그러나 이 구성으로 CI가 돌아가면 아래처럼 모두 실패하게 됩니다.

확인해보니 실제 프로젝트 내에서 JWT Secret Key의 환경변수명은 JWT_SECRET_KEY인데 ci.yaml이나 Actions secrets에서는 JWT_SECRET와 같이 작성되어 있어 JWT Secret Key의 환경변수가 들어오지 않아 생기는 문제였습니다.
아래와 같이 실제 프로젝트와 ci.yaml, Actions secrets의 환경변수명을 모두 똑같이 맞춰주었습니다.
ci.yamlname: ci pipelines
# dev 브랜치로 pull request 요청이 들어오거나
# dev 브랜치에 코드가 푸시되면 실행
on:
pull_request:
branches:
- dev
push:
branches: [ dev ]
jobs:
all:
runs-on: ubuntu-latest
services:
# Redis 추가 (테스트를 위해)
redis:
image: redis:6.2
ports:
- 6379:6379
options: >-
--health-cmd="redis-cli ping"
--health-interval=10s
--health-timeout=5s
--health-retries=5
steps:
# 현재 리포지토리의 소스를 가져옴
- name: Checkout code
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
# gradle 캐시를 설정 (CI 속도 향상을 위해)
- name: Cache Gradle packages
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
# gradlew 파일에 실행 권한을 부여
- name: Grant execute permission for Gradlew
run: chmod +x ./gradlew
# gradle 빌드 실행 (테스트 제외)
- name: Build with Gradle
run: ./gradlew build -x test
# H2 DB를 통해 테스트 실행 (application-test.yaml로)
- name: Run tests with H2 DB
env:
spring_profiles_active: test
REDIS_HOST: ${{ secrets.REDIS_HOST }}
REDIS_PORT: ${{ secrets.REDIS_PORT }}
JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
S3_PUBLIC: ${{ secrets.S3_PUBLIC }}
S3_SECRET: ${{ secrets.S3_SECRET }}
S3_REGION: ${{ secrets.S3_REGION }}
SLACKBOT_TOKEN: ${{ secrets.SLACKBOT_TOKEN }}
LOGSTASH_HOST: ${{ secrets.LOGSTASH_HOST }}
LOGSTASH_PORT: ${{ secrets.LOGSTASH_PORT }}
run: ./gradlew test -Dspring.profiles.active=test
- name: Notify on success
if: success()
run: echo "All tests passed!"
- name: Notify on failure
if: failure()
run: echo "Some tests failed!"
