[API] 프로젝트 개요가 전체 diff 를 읽던 것을 97MB→20KB 로 · 목록에 커서 페이지네이션 [ #341 ] #504
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| # main 병합이 곧 EC2 배포이므로(deploy-ec2.yml) 검증은 병합 전에 끝나야 한다. | |
| # 이 워크플로가 PR에서 실패하면 병합을 막는 것이 전제다 — GitHub 저장소 설정에서 | |
| # main 보호 규칙에 "Build and test"를 required status check로 걸어야 실제로 막힌다. | |
| # 워크플로 파일만으로는 강제되지 않는다. | |
| # develop 이 dev 서버 배포 트리거이므로(deploy-ec2-dev.yml) develop 으로 들어오는 PR 도 | |
| # 같은 검증을 거쳐야 한다. 빠뜨리면 develop 은 테스트 없이 dev 서버로 나가고, dev 에서 | |
| # 깨진 것이 그대로 main PR 로 올라온다. | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| - develop | |
| push: | |
| branches: | |
| - main | |
| - develop | |
| # PR에 커밋을 연달아 밀면 앞선 실행은 취소한다. 배포와 달리 중간 상태가 남지 않는다. | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| test: | |
| name: Build and test | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| # @SpringBootTest 19종이 실제 MySQL을 요구한다. H2로는 대체할 수 없다 — | |
| # *SchemaTest 들이 information_schema를 직접 조회해 Flyway가 만든 테이블/컬럼을 | |
| # 단언하고, ddl-auto=validate 도 실제 마이그레이션 결과를 검증 대상으로 삼는다. | |
| # 버전은 운영·dev EC2 와 같은 8.0 계열로 맞춘다. 예전에는 mysql:9 였는데, 그러면 | |
| # CI(9) / dev·운영(8.0) / 개발자 로컬(제각각) 이 갈려서 "내 로컬에선 됐는데"가 | |
| # 구조적으로 생긴다. 패치버전까지 고정하지 않는 이유는 Ubuntu 저장소와 Docker Hub 의 | |
| # 패치 릴리스 시점이 다르기 때문 — 맞춰야 하는 것은 8.0 이라는 계열이다. | |
| services: | |
| mysql: | |
| image: mysql:8.0 | |
| env: | |
| MYSQL_ROOT_PASSWORD: root | |
| MYSQL_DATABASE: dvely | |
| MYSQL_USER: dvely | |
| MYSQL_PASSWORD: dvely | |
| # time_zone=SYSTEM 이라 컨테이너 타임존이 곧 NOW()/DEFAULT CURRENT_TIMESTAMP 다. | |
| # 아래 job env 의 TZ 와 같은 값으로 맞춰 둔다. | |
| TZ: Asia/Seoul | |
| ports: | |
| - 3306:3306 | |
| options: >- | |
| --health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -proot" | |
| --health-interval=10s | |
| --health-timeout=5s | |
| --health-retries=12 | |
| env: | |
| # local 프로파일은 gitignore된 application-local.yml을 요구한다. | |
| # dev 프로파일은 datasource를 전부 환경변수에서 읽으므로 CI에서 그대로 쓸 수 있다. | |
| SPRING_PROFILES_ACTIVE: dev | |
| # GitHub 러너는 UTC 다. 아래 DB_URL 이 serverTimezone=Asia/Seoul 로 접속하므로, | |
| # 그대로 두면 Connector/J 가 JVM(UTC)과 그 값 사이에서 시각을 변환해 DB 에는 +9 된 | |
| # 값이 저장된다. 운영·dev·개발자 로컬은 전부 Asia/Seoul 이라 이 변환이 일어나지 | |
| # 않으니, CI 만 다른 표현으로 저장하게 된다. MySQL 8.0 버전을 맞춘 것과 같은 이유로 | |
| # 타임존도 맞춘다. | |
| TZ: Asia/Seoul | |
| # allowPublicKeyRetrieval: MySQL 8.0의 기본 인증 플러그인(caching_sha2_password)이 | |
| # 평문 연결에서 서버 공개키를 요구한다. 빠뜨리면 첫 접속부터 인증 실패로 끝난다. | |
| DB_URL: jdbc:mysql://127.0.0.1:3306/dvely?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul | |
| DB_USERNAME: dvely | |
| DB_PASSWORD: dvely | |
| # 아래는 전부 더미다. 실제 값이 필요한 게 아니라, application.yaml의 플레이스홀더에 | |
| # 기본값이 없어서 비어 있으면 컨텍스트 로딩 자체가 실패하기 때문에 채운다. | |
| # 테스트는 GitHub/AI API를 실제로 호출하지 않는다. | |
| # | |
| # ENCRYPT_SECRET은 AesEncryptor가 SHA-256으로 해싱해 쓰므로 길이 제약이 없다. | |
| # JWT_SECRET은 다르다. jjwt의 Keys.hmacShaKeyFor()가 HS256에 256비트 미만 키를 | |
| # 받으면 WeakKeyException을 던지므로 32바이트 이상이어야 한다. | |
| ENCRYPT_SECRET: ci-dummy-encrypt-secret | |
| JWT_SECRET: ci-dummy-jwt-secret-that-is-at-least-32-bytes-long-for-hs256 | |
| GITHUB_OAUTH_CLIENT_ID: ci-dummy | |
| GITHUB_OAUTH_CLIENT_SECRET: ci-dummy | |
| GITHUB_OAUTH_REDIRECT_URI: http://localhost:8080/api/v1/auth/github/callback | |
| GITHUB_APP_ID: '1' | |
| GITHUB_APP_CLIENT_ID: ci-dummy | |
| GITHUB_APP_CLIENT_SECRET: ci-dummy | |
| GITHUB_APP_INSTALLATION_REDIRECT_URI: http://localhost:8080/api/v1/auth/github/app/callback | |
| # GithubAppClient는 값이 "-----BEGIN"으로 시작하지 않으면 파일 경로로 읽는다. | |
| # 지연 로딩이라 더미 문자열로도 컨텍스트는 뜨지만, 키를 실제로 파싱하는 경로가 | |
| # 테스트에 섞여 들어와도 깨지지 않도록 진짜 RSA 키를 만들어 둔다. | |
| GITHUB_APP_PRIVATE_KEY: ${{ github.workspace }}/ci-github-app.pem | |
| GITHUB_WEBHOOK_SECRET: ci-dummy-webhook-secret | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up JDK 25 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: '25' | |
| - name: Set up Gradle | |
| uses: gradle/actions/setup-gradle@v4 | |
| - name: Generate dummy GitHub App private key | |
| run: openssl genrsa -out "${{ github.workspace }}/ci-github-app.pem" 2048 | |
| - name: Build and test | |
| run: ./gradlew build --no-daemon | |
| # 실패했을 때 어느 테스트가 왜 깨졌는지 보려면 HTML 리포트가 필요하다. | |
| # 로그만으로는 @SpringBootTest 컨텍스트 로딩 실패의 원인 예외를 찾기 어렵다. | |
| - name: Upload test report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-report | |
| path: | | |
| build/reports/tests/test | |
| build/test-results/test | |
| retention-days: 7 | |
| if-no-files-found: ignore |