chore: 코드베이스 초기 설정 - #2
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 46 minutes and 51 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (16)
📝 WalkthroughWalkthroughBun/Biome/TypeScript 설정과 .env 템플릿을 추가하고, Docker PostgreSQL 및 Drizzle 설정을 도입했습니다. Valibot 환경 검증, DatabaseService/Module, 헬스체크 엔드포인트와 테스트, Swagger 문서화, CI 워크플로우 및 관련 스크립트를 포함합니다. 백엔드 초기 설정 및 통합
Sequence Diagram(s) sequenceDiagram
participant Client
participant HealthController
participant HealthCheckService
participant DrizzleHealthIndicator
participant Database
Client->>HealthController: GET /health
HealthController->>HealthCheckService: check()
HealthCheckService->>DrizzleHealthIndicator: pingCheck("database")
DrizzleHealthIndicator->>Database: db.execute("SELECT 1")
alt success
Database-->>DrizzleHealthIndicator: result
DrizzleHealthIndicator-->>HealthCheckService: up
else failure
Database-->>DrizzleHealthIndicator: error
DrizzleHealthIndicator-->>HealthCheckService: down
end
HealthCheckService-->>HealthController: health response
Estimated code review effort 🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
리뷰 개요이 PR은 NestJS 기반 팀 MINO 백엔드 프로젝트의 초기 개발 환경을 완성합니다. Bun 패키지 관리자, Biome 린터, PostgreSQL과 Drizzle ORM을 통합하고, 헬스체크 API와 Swagger 문서화를 추가하여 프로젝트 구동 체계를 확립합니다. 변경 사항백엔드 초기 설정 및 통합
예상 코드 리뷰 난이도🎯 3 (중간) | ⏱️ ~25분 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| @@ -0,0 +1,21 @@ | |||
| services: | |||
| postgres: | |||
| image: postgres:16-alpine | |||
There was a problem hiding this comment.
💬
postgres 18버전이 현재 lts라 사용하게 될 거 같아요!
일단 여기서는 수정하지 마시고, 제가 supabase와 연동하며 docker-compose도 신경써서 다시 올리겠습니다~!
There was a problem hiding this comment.
굿, 컴포즈 제외해서 올릴게용
| }) | ||
| getHealth() { | ||
| return { | ||
| status: "ok", |
There was a problem hiding this comment.
💬
healthcheck에서 서버뿐 아니라 db의 health도 검사하면 어떨까요?
간단하게 'SELECT 1' 같은 쿼리로 검증했던 경험이 있는데,, 그렇다고 repository layer에 SELECT 1하는 쿼리를 만들기도 뭐하고... 참 애매하네요.
기존에 회사에서는 이 문서처럼 작성했던 거 같은데, drizzle에서는 지원 안하는 거 같기도 하네요!
There was a problem hiding this comment.
terminus가 Drizzle을 공식 지원하지 않아서, HealthIndicator를 직접 상속해 SELECT 1 쿼리로 DB 연결 여부를 확인하는 커스텀 인디케이터를 구현했습니다!
| @@ -0,0 +1,21 @@ | |||
| services: | |||
| postgres: | |||
| image: postgres:16-alpine | |||
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| validate: validateEnv, | ||
| }), | ||
| DatabaseModule, | ||
| TerminusModule, |
There was a problem hiding this comment.
TerminusModule이 디폴트로 예외를 로깅하고 있어서
(헬스체크 실패할 때 로깅하는 부분이 따로 안보여서) 안찍는걸 의도할거라면 logger 옵션 꺼줘야할것 같은데요~
아직 논의되지 않은 부분인거 같아서 여기서 다같이 가볍게 얘기하고 넘어가도 좋을 것 같습니다!
There was a problem hiding this comment.
pino 괜찮으면 여기서 로거 끄고 #13 에서 헬스체크 실패시 로깅처리하게끔 해놓을게
로깅 어떻게 해놓을까??
There was a problem hiding this comment.
pino 괜찮으면 여기서 로거 끄고 #13 에서 헬스체크 실패시 로깅처리하게끔 해놓을게
그럼 여기서는 그냥 무시하고 #13에서 작업하면 될 듯~!
근데 헬스체크 실패시에 로깅 다들 하는지도 궁금했어ㅎㅎ
@KKardy @sudosubin
There was a problem hiding this comment.
우리 bun 쓰는 경우에도 vitest 쓰기로 했었나? (단순 기억이 안나서)
저는 다 좋습니다ㅎㅎ~
There was a problem hiding this comment.
난 bun으로 충분하다면 굳이 새로운 걸 도입해야하나? 라는 생각이라 bun 으로 하는 것 찬성! (일단 이 방향으로 푸시는 해놓을게)
| "@types/node": "^25.9.1", | ||
| "typescript": "^5.9.3" | ||
| "drizzle-kit": "^0.31.10", | ||
| "typescript": "^5.9.3", |
There was a problem hiding this comment.
^6.0.0 (6.0.3)으로 업그레이드 반영했습니다.
7.0은 현재 @typescript/native-preview + tsgo 별도 패키지라 nest build(tsc 기반)와 호환이 안 돼서 stable 릴리즈 대기 중이에요.
그 대신 tsgo --noEmit을 타입체크용으로 병행 도입했는데, tsc 대비 ~5.5x 빠릅니다 (2.4s → 0.43s). bun run typecheck로 실행 가능해요.
라고 하는데, 7.0 업그레이드 가능한 부분인가??
| NODE_ENV=development | ||
| PORT=3000 | ||
| DATABASE_URL=postgres://postgres:postgres@localhost:5432/team_mino | ||
| DB_POOL_SIZE=10 |
There was a problem hiding this comment.
디비 풀 기본값은 Supabase 환경 고려해서 수정이 필요할 수도 있는거죠?
There was a problem hiding this comment.
Supabase PgBouncer 사용한다면 풀은 1~2로 줄일게요!
- env.schema: PORT, DB_POOL_SIZE에 v.transform(Number) 추가 → Env 타입 number 추론
- database.service: ConfigService<Env> 제네릭 및 { infer: true } 적용, Number() 수동 변환 제거
- drizzle.health-indicator: deprecated HealthIndicator 클래스 → HealthIndicatorService 방식으로 마이그레이션 (terminus v11)
- main: app.enableShutdownHooks() 추가 (graceful shutdown)
- app.module: biome 설정 기준 2칸 space 들여쓰기 적용
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- typescript ^5.9.3 → ^6.0.0 (6.0.3) - @typescript/native-preview@beta 설치 (tsgo, Go 기반 네이티브 컴파일러) - typecheck(tsgo), typecheck:tsc 스크립트 추가 - tsconfig: baseUrl 제거 → paths로 대체 (TS 7.0 대비) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
bun 내장 테스트 러너로 교체. NestJS DI(decorator metadata) 동작 검증 완료. vitest.config.ts 제거, vitest 패키지 제거. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
src/health/drizzle.health-indicator.ts (1)
18-23: ⚡ Quick win실패 원인을 보존하면 디버깅에 도움이 됩니다.
catch {}가 실제 에러를 삼켜서"Database ping failed"라는 일반 메시지만 남습니다. 원인(예: connection refused, timeout)을 함께 기록/반환하면 운영 시 진단이 쉬워집니다.🔍 에러 상세 보존 예시
- try { - await this.databaseService.db.execute(sql`SELECT 1`); - return indicator.up(); - } catch { - return indicator.down("Database ping failed"); - } + try { + await this.databaseService.db.execute(sql`SELECT 1`); + return indicator.up(); + } catch (error) { + const message = error instanceof Error ? error.message : "unknown error"; + return indicator.down(`Database ping failed: ${message}`); + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/health/drizzle.health-indicator.ts` around lines 18 - 23, The health check currently swallows the real error in the empty catch; change the try/catch to capture the exception (e.g., catch (err)) and include the error details when returning or logging the failure so diagnostics are preserved — for example call indicator.down with the error info or log the error before returning. Update the block around this.databaseService.db.execute(...) so the catch uses the captured error and forwards err.message / String(err) (or the full error object) to indicator.down("Database ping failed: ...") or to your logger; keep the successful path using indicator.up() unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docker-compose.yml`:
- Around line 12-13: Update the docker-compose volume mount for the Postgres
service: replace the current mapping that uses
postgres_data:/var/lib/postgresql/data with the Postgres 18+ recommended mount
target postgres_data:/var/lib/postgresql so the service (the volumes entry
referencing postgres_data and the current /var/lib/postgresql/data path) uses
the new VOLUME path and avoids persistence/upgrade issues with Postgres 18+.
In `@drizzle.config.ts`:
- Around line 3-7: 현재는 process.env.DATABASE_URL을 빈값만 체크하고 있어 오타나 잘못된 URL 형식이
통과됩니다; databaseUrl 변수를 읽은 직후 (databaseUrl / process.env.DATABASE_URL) URL 형식을
검증하도록 추가하세요 — 예를 들어 프로토콜(mysql://, postgres:// 등) 또는 전체 URL 파싱(정규식 또는 URL 생성자)으로
유효성 검사를 하고, 실패하면 기존 throw new Error("DATABASE_URL is required") 대신 또는 함께 명확한 에러
메시지(예: "DATABASE_URL is missing or invalid: <value>")를 던져 즉시 실패하게 만드세요.
In `@package.json`:
- Around line 45-47: package.json에서 devDependencies의 "typescript" (TS6)와
"`@typescript/native-preview`" (TS7 preview) 및 scripts "typecheck" (tsgo) vs
"typecheck:tsc" (tsc) / "build" (nest build)이 서로 다른 컴파일러 라인을 사용해 결과가 불일치할 수
있으므로, 먼저 로컬에서 bun run typecheck (tsgo/TS7 preview)과 bun run typecheck:tsc
(tsc/TS6)을 실행해 에러·진단이 일치하는지 비교하고 bun run build 결과가 어느 쪽과 동일한지 확인하세요; 불일치가 발생하면
CI와 package.json을 단일 컴파일러로 정렬하도록 수정(예: 제거하거나 고정: 삭제 또는 통일된 TypeScript 버전으로
"typescript"만 사용, 또는 모든 스크립트를 tsgo 또는 tsc로 통일)하고
scripts("typecheck","typecheck:tsc","build")를 해당 컴파일러에 맞게 업데이트해 빌드와 타입체크가 같은
컴파일러/버전에서 동작하도록 고정하십시오.
In `@src/config/env.schema.ts`:
- Around line 15-31: The current validateEnv function uses envSchema but lacks
range checks for numeric env vars like PORT and DB_POOL_SIZE, so add explicit
bounds validation to the envSchema (or immediately after parsing in validateEnv)
to reject out-of-range values: enforce PORT to be within a valid TCP port range
(e.g. 1–65535) and DB_POOL_SIZE to be >=1 (and optionally a reasonable max), and
when out-of-range throw the same Error shape with a clear message (consistent
with the existing `${path}: ${issue.message}` format) so validateEnv will fail
fast on invalid boundaries.
In `@src/health/drizzle.health-indicator.spec.ts`:
- Around line 1-5: The test uses the global jest APIs (e.g.,
jest.fn().mockResolvedValue/mockRejectedValue) which Bun's test runner injects
at runtime but TypeScript may not recognize; if you see compile/type errors in
src/health/drizzle.health-indicator.spec.ts, resolve them by either adding an
explicit import like import { jest } from "bun:test" at the top of the spec or
by adding the appropriate type reference (e.g., /// <reference
types="bun-types/test-globals" /> or updating tsconfig types) so TypeScript
knows the jest globals; if there are no type errors, leave the file as-is.
---
Nitpick comments:
In `@src/health/drizzle.health-indicator.ts`:
- Around line 18-23: The health check currently swallows the real error in the
empty catch; change the try/catch to capture the exception (e.g., catch (err))
and include the error details when returning or logging the failure so
diagnostics are preserved — for example call indicator.down with the error info
or log the error before returning. Update the block around
this.databaseService.db.execute(...) so the catch uses the captured error and
forwards err.message / String(err) (or the full error object) to
indicator.down("Database ping failed: ...") or to your logger; keep the
successful path using indicator.up() unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 20904301-466a-46e8-bd1d-9bac022f968a
⛔ Files ignored due to path filters (2)
bun.lockis excluded by!**/*.lockpackage-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (17)
.env.example.gitignoreREADME.mdbiome.jsondocker-compose.ymldrizzle.config.tspackage.jsonsrc/app.module.tssrc/config/env.schema.tssrc/database/database.module.tssrc/database/database.service.tssrc/database/schema/index.tssrc/health/drizzle.health-indicator.spec.tssrc/health/drizzle.health-indicator.tssrc/health/health.controller.tssrc/main.tstsconfig.json
| volumes: | ||
| - postgres_data:/var/lib/postgresql/data |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
postgres 18-alpine docker image does mounting volume at /var/lib/postgresql/data still persist data via compatibility symlink
💡 Result:
No, mounting a volume at /var/lib/postgresql/data does not persist data in the way it did in previous versions for PostgreSQL 18 and newer [1][2]. In PostgreSQL 18+, the official Docker image structure has changed significantly [1][2]: 1. Changed Data Location: The default data directory (PGDATA) is now located at /var/lib/postgresql/18/docker [3][2]. 2. Volume Mount Point: The VOLUME directive in the Dockerfile has been moved from /var/lib/postgresql/data to /var/lib/postgresql [2]. 3. No Compatibility Symlink: While there was an initial attempt to include a compatibility symlink, it was explicitly removed in the Alpine images (and others) to avoid issues [4]. If you attempt to mount a volume at /var/lib/postgresql/data, it will generally be ignored or result in an unused mount point, because the container expects the data to reside within the /var/lib/postgresql directory structure [1][3]. Recommended Configuration: To ensure data persists correctly in PostgreSQL 18+, you should mount your volume at the parent directory: volumes: - my_db_data:/var/lib/postgresql This configuration allows PostgreSQL to place its data in the correct version-specific subdirectory (e.g., /var/lib/postgresql/18/docker), which is essential for proper functionality and future upgrades using tools like pg_upgrade [1][3]. If you persist in using the old mount path, you may encounter silent data loss where the container initializes a new database in an anonymous volume while ignoring your existing data on the host [3].
Citations:
- 1: Fix Alpine missing
/var/lib/postgresql/datamounts docker-library/postgres#1409 - 2: https://github.com/docker-library/postgres/blob/59063d8f/Dockerfile-alpine.template
- 3: PostgreSQL 18: OLD_DATABASES detection fails to find data in /var/lib/postgresql/data/18/docker/ causing silent data loss on container recreation docker-library/postgres#1400
- 4: Remove symlink for PostgreSQL data directory in Alpine images docker-library/postgres#1394
PostgreSQL 18용 볼륨 마운트 경로를 /var/lib/postgresql로 변경 권장
현재 volumes가 postgres_data:/var/lib/postgresql/data로 되어 있는데, Postgres 18+ 공식 이미지의 데이터 디렉터리/VOLUME 기준이 /var/lib/postgresql로 변경되었습니다. 따라서 올드 경로(/var/lib/postgresql/data)를 유지하면 업그레이드/영속성에서 문제가 생길 수 있어, 마운트 지점을 권장 경로로 맞추는 게 안전합니다.
권장 예시
volumes:
- - postgres_data:/var/lib/postgresql/data
+ - postgres_data:/var/lib/postgresql이전 리뷰에서 언급된 대로 compose를(KKardy가) 별도로 정비할 때 함께 반영해 주세요.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| volumes: | |
| - postgres_data:/var/lib/postgresql/data | |
| volumes: | |
| - postgres_data:/var/lib/postgresql |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docker-compose.yml` around lines 12 - 13, Update the docker-compose volume
mount for the Postgres service: replace the current mapping that uses
postgres_data:/var/lib/postgresql/data with the Postgres 18+ recommended mount
target postgres_data:/var/lib/postgresql so the service (the volumes entry
referencing postgres_data and the current /var/lib/postgresql/data path) uses
the new VOLUME path and avoids persistence/upgrade issues with Postgres 18+.
| const databaseUrl = process.env.DATABASE_URL; | ||
|
|
||
| if (!databaseUrl) { | ||
| throw new Error("DATABASE_URL is required"); | ||
| } |
There was a problem hiding this comment.
DATABASE_URL 형식 검증도 같이 해두는 게 안전합니다.
빈 값만 막고 있어서 오타 URL이 들어오면 이후 단계에서 에러가 납니다. 여기서 즉시 검증하면 원인 파악이 쉬워집니다.
수정 예시
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
throw new Error("DATABASE_URL is required");
}
+
+try {
+ new URL(databaseUrl);
+} catch {
+ throw new Error("DATABASE_URL must be a valid URL");
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const databaseUrl = process.env.DATABASE_URL; | |
| if (!databaseUrl) { | |
| throw new Error("DATABASE_URL is required"); | |
| } | |
| const databaseUrl = process.env.DATABASE_URL; | |
| if (!databaseUrl) { | |
| throw new Error("DATABASE_URL is required"); | |
| } | |
| try { | |
| new URL(databaseUrl); | |
| } catch { | |
| throw new Error("DATABASE_URL must be a valid URL"); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@drizzle.config.ts` around lines 3 - 7, 현재는 process.env.DATABASE_URL을 빈값만 체크하고
있어 오타나 잘못된 URL 형식이 통과됩니다; databaseUrl 변수를 읽은 직후 (databaseUrl /
process.env.DATABASE_URL) URL 형식을 검증하도록 추가하세요 — 예를 들어 프로토콜(mysql://, postgres://
등) 또는 전체 URL 파싱(정규식 또는 URL 생성자)으로 유효성 검사를 하고, 실패하면 기존 throw new
Error("DATABASE_URL is required") 대신 또는 함께 명확한 에러 메시지(예: "DATABASE_URL is
missing or invalid: <value>")를 던져 즉시 실패하게 만드세요.
| "@typescript/native-preview": "^7.0.0-dev.20260421.2", | ||
| "drizzle-kit": "^0.31.10", | ||
| "typescript": "^6.0.0" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# TypeScript 설정 검증
echo "=== Running TypeScript compiler (tsc) ==="
bun run typecheck:tsc
echo ""
echo "=== Running tsgo compiler ==="
bun run typecheck
echo ""
echo "=== Running NestJS build ==="
bun run buildRepository: mash-up-kr/Team-MINO-Node
Length of output: 319
🌐 Web query:
TypeScript 6.0.0 compatibility with NestJS 11
💡 Result:
NestJS 11 is compatible with TypeScript 6.0.x in practice, but you should verify via your specific NestJS 11 package versions because NestJS 11’s repo has been pinned to TypeScript 5.9.x at various points. What we can say with sources: 1) TypeScript 6.0.0 was released in March 2026, and it is positioned as the “last release based on the current JavaScript codebase” (i.e., it’s a normal compiler release intended for adoption) [1]. 2) NestJS 11 requires Node.js v20 or higher [2], but those sources do not state any explicit NestJS 11 incompatibility with TypeScript 6.0.0. 3) However, the NestJS repo has been updated to TypeScript 5.9.3 in its dependencies (example commits show TypeScript moving within the 5.9 series) [3], and there is evidence of a pending bump from TypeScript 5.9.3 to 6.0.2 in April 2026 [4]. That strongly suggests the maintainers were still targeting the 5.9.x line during early/mid 2026, and TypeScript 6 adoption was actively being rolled in. Practical recommendation for today (2026-05-29): - If you want the safest “supported by the repo” path, start with TypeScript 5.9.x, aligning with NestJS 11’s visible dependency target (e.g., 5.9.3) [3]. - If you specifically need TypeScript 6.0.0/6.x, it should generally work because NestJS is TypeScript-authored and TypeScript’s 6.0 is a standard compiler release [1], but you may encounter build/tooling issues in your exact stack (SWC/ts-jest/ts-node/eslint plugins, etc.). If you tell me your exact NestJS 11 package set (e.g., @nestjs/core version) and tooling (SWC vs tsc, eslint/ts-jest/ts-node), I can narrow this to a more definitive “yes/no + specific fixes” for your configuration.
Citations:
- 1: https://devblogs.microsoft.com/typescript/announcing-typescript-6-0/
- 2: https://docs.nestjs.com/migration-guide
- 3: nestjs/nest@f7cd33a
- 4: chore(deps-dev): bump typescript from 5.9.3 to 6.0.2 nestjs/nest#16669
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show package.json around the mentioned lines and also scripts/deps
echo "=== package.json (relevant section) ==="
nl -ba package.json | sed -n '1,120p'
echo
echo "=== Extract dependency versions for TypeScript packages ==="
node -e "const p=require('./package.json'); const d=p.dependencies||{}; const dev=p.devDependencies||{}; const all={...d,...dev}; ['typescript','`@typescript/native-preview`','tsgo','drizzle-kit','drizzle-orm'].forEach(k=>{ if(all[k]) console.log(k+':', all[k]); });"
echo
echo "=== package.json scripts (typecheck/build) ==="
node -e "const p=require('./package.json'); const s=p.scripts||{}; Object.keys(s).filter(k=>/typecheck|tsc|tsgo|build/i.test(k)).sort().forEach(k=>console.log(k+':', s[k]));"Repository: mash-up-kr/Team-MINO-Node
Length of output: 170
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== package.json (relevant section) ==="
cat -n package.json | sed -n '1,120p'
echo
echo "=== Extract dependency versions for TypeScript packages ==="
node -e "const p=require('./package.json'); const d=p.dependencies||{}; const dev=p.devDependencies||{}; const all={...d,...dev}; ['typescript','`@typescript/native-preview`','drizzle-kit','drizzle-orm'].forEach(k=>{ if(all[k]) console.log(k+':', all[k]); else console.log(k+': (not found)'); });"
echo
echo "=== package.json scripts (typecheck/build) ==="
node -e "const p=require('./package.json'); const s=p.scripts||{}; Object.keys(s).filter(k=>/typecheck|tsc|tsgo|build/i.test(k)).sort().forEach(k=>console.log(k+':', s[k]));"Repository: mash-up-kr/Team-MINO-Node
Length of output: 2129
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== tsconfig files ==="
fd -t f "tsconfig*.json" . || true
echo
echo "=== nest-cli config files ==="
fd -t f "nest-cli*.json" . || true
fd -t f "nest*.json" . -g "*nest*cli*.json" || true
echo
echo "=== Print nest-cli.json if present ==="
for f in $(fd -t f -g "nest-cli.json" .); do
echo "--- $f ---"
head -n 120 "$f" | cat -n
done || true
echo
echo "=== Print tsconfig.json (or first found) ==="
for f in $(fd -t f -g "tsconfig.json" .); do
echo "--- $f ---"
head -n 160 "$f" | cat -n
done || true
echo
echo "=== Search for tsgo/tsc/nest build related config ==="
rg -n --hidden --glob '!**/node_modules/**' "(tsgo|tsc|typescript|nest build|nest-cli)" package.json tsconfig*.json nest-cli*.json 2>/dev/null || trueRepository: mash-up-kr/Team-MINO-Node
Length of output: 2134
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== tsconfig.build.json ==="
if [ -f tsconfig.build.json ]; then
cat -n tsconfig.build.json
else
echo "tsconfig.build.json not found"
fi
echo
echo "=== Locate tsgo usage/config ==="
rg -n --hidden --glob '!**/node_modules/**' "tsgo" . || true
echo
echo "=== Check whether tsgo is declared in package.json ==="
node -e "const p=require('./package.json'); const all={...(p.dependencies||{}),...(p.devDependencies||{})}; console.log('tsgo:', all.tsgo || '(not declared)');"
echo
echo "=== Quick look at package-lock/pnpm/yarn presence (if any) ==="
ls -la | headRepository: mash-up-kr/Team-MINO-Node
Length of output: 1717
🏁 Script executed:
#!/bin/bash
# TypeScript 설정 검증
echo "=== Running TypeScript compiler (tsc) ==="
bun run typecheck:tsc
echo ""
echo "=== Running tsgo compiler ==="
bun run typecheck
echo ""
echo "=== Running NestJS build ==="
bun run buildRepository: mash-up-kr/Team-MINO-Node
Length of output: 319
🌐 Web query:
tsgo bin @typescript/native-preview which TypeScript version does it use
💡 Result:
The @typescript/native-preview package corresponds to the upcoming TypeScript 7.0 release [1][2]. It provides a native, Go-based implementation of the TypeScript compiler, which is accessed via the tsgo command [3][4][1]. While the package is currently labeled with version numbers such as 7.0.0-dev (or 7.0.0-beta), it represents the development efforts for TypeScript 7 [3][1][2]. This native compiler is intended to eventually replace the existing JavaScript-based TypeScript compiler (historically referred to as "Strada") and be merged into the official TypeScript package [1][5].
Citations:
- 1: https://devblogs.microsoft.com/typescript/announcing-typescript-native-previews/
- 2: https://dev.to/grimicorn/typescript-70-the-go-compiler-that-makes-ts-10x-faster-4al6
- 3: https://registry.npmjs.org/%40typescript%2Fnative-preview
- 4: https://github.com/microsoft/typescript-go
- 5: https://registry.npmjs.org/@typescript/native-preview
🌐 Web query:
NestJS nest build uses which TypeScript version local typescript dependency
💡 Result:
The nest build command uses the TypeScript version installed as a local dependency in your project's node_modules directory [1][2]. When you create a new NestJS project, the Nest CLI automatically adds typescript as a devDependency in your package.json file [1][2]. The nest build command is designed as a wrapper around the standard tsc (TypeScript compiler) or build tools like webpack (in monorepos) [1][2][3]. Because it relies on these locally installed tools, the build process consistently uses the version of TypeScript defined in your project's local dependency tree, ensuring that all environments—such as your local machine, team members' machines, or CI/CD pipelines—utilize the same compiler version [1][2]. If you encounter issues related to compiler features or errors, you should verify the version specified in your project's package.json or lock file, as the CLI will utilize whichever version is resolved by your package manager (e.g., npm, pnpm, or yarn) in the local node_modules [4].
Citations:
- 1: https://github.com/nestjs/docs.nestjs.com/blob/ba85c6a2/content/cli/scripts.md
- 2: https://docs.nestjs.com/cli/scripts
- 3: https://github.com/nestjs/docs.nestjs.com/blob/ba85c6a2/content/cli/overview.md
- 4: Nest build error when upgrading typescript to 4.8.X nestjs/nest-cli#1812
🏁 Script executed:
#!/bin/bash
# TypeScript 설정 검증
echo "=== typecheck:tsc (TS 6.x) ==="
bun run typecheck:tsc
echo "=== typecheck (tsgo / native-preview: TS 7.0 preview) ==="
bun run typecheck
echo "=== nest build (uses local typescript: TS 6.x) ==="
bun run buildRepository: mash-up-kr/Team-MINO-Node
Length of output: 356
typecheck(tsgo/TS7 preview)와 nest build(tsc/TS6)가 서로 다른 컴파일러 버전을 쓰므로 일관성 확인 및 정렬 필요
현재 package.json에서 devDependencies는 typescript: ^6.0.0과 @typescript/native-preview: ^7.0.0-dev.20260421.2를 동시에 사용합니다. 또한 스크립트가 build: nest build이고, typecheck: tsgo --noEmit로 분리돼 있어 nest build는 로컬 typescript(6.x)로 컴파일되며, tsgo는 @typescript/native-preview가 제공하는(= TypeScript 7.0 개발 라인) 네이티브 컴파일러로 타입체크됩니다. 이 조합이면 타입 정의/판정 결과가 달라져 빌드 통과 여부가 불안정해질 수 있습니다(특히 @nestjs/*@^11.1.x, drizzle-orm@^0.45.2 조합).
다음 확인/조치가 필요합니다.
bun run typecheck:tsc(TS 6)와bun run typecheck(tsgo/TS 7 preview)의 에러/진단이 일치하는지 비교bun run build가typecheck/typecheck:tsc결과와 동일한 전제로 돌아가는지 확인- 불일치가 나오면 CI에서 한 가지 컴파일러만 쓰도록 정렬(예: 타입체크를
typecheck:tsc로 단일화하거나, 최소한 TypeScript 버전을 빌드/타입체크에 맞춰 동일 라인으로 고정)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@package.json` around lines 45 - 47, package.json에서 devDependencies의
"typescript" (TS6)와 "`@typescript/native-preview`" (TS7 preview) 및 scripts
"typecheck" (tsgo) vs "typecheck:tsc" (tsc) / "build" (nest build)이 서로 다른 컴파일러
라인을 사용해 결과가 불일치할 수 있으므로, 먼저 로컬에서 bun run typecheck (tsgo/TS7 preview)과 bun run
typecheck:tsc (tsc/TS6)을 실행해 에러·진단이 일치하는지 비교하고 bun run build 결과가 어느 쪽과 동일한지
확인하세요; 불일치가 발생하면 CI와 package.json을 단일 컴파일러로 정렬하도록 수정(예: 제거하거나 고정: 삭제 또는 통일된
TypeScript 버전으로 "typescript"만 사용, 또는 모든 스크립트를 tsgo 또는 tsc로 통일)하고
scripts("typecheck","typecheck:tsc","build")를 해당 컴파일러에 맞게 업데이트해 빌드와 타입체크가 같은
컴파일러/버전에서 동작하도록 고정하십시오.
- env.schema: PORT 범위(1~65535), DB_POOL_SIZE 최솟값(>=1) 검증 추가 - spec: bun:test에서 jest 등 명시적 import로 변경 - tsconfig: bun-types 추가 (bun:test 타입 인식) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chore: GitHub Actions CI 파이프라인 구성
- Express 어댑터 → BunHonoAdapter로 전환 - SwaggerModule.setup (Express 전용) → BunHonoAdapter.setupSwagger로 교체 Hono native route로 /api-docs, /api-docs.json 제공 - LoggerModule (nestjs-pino) + validateEnv + DatabaseModule + TerminusModule 통합 - HttpExceptionFilter, ResponseInterceptor 글로벌 등록 - @nestjs/terminus optional dep (typeorm, mikro-orm, mongoose, sequelize) 번들러 external 목록에 추가 - swagger-ui-express, @nestjs/platform-express 의존성 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- biome.json 스키마 버전 2.4.15 → 2.4.16 업데이트 - import 정리 및 미사용 파라미터 제거 - result["database"] → result.database 리터럴 키 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🍹
|
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/health/drizzle.health-indicator.spec.ts (2)
34-34:⚠️ Potential issue | 🔴 Critical | ⚡ Quick win브래킷 표기법 대신 점 표기법을 사용하세요.
result["database"]는 불필요한 computed 표현식입니다.result.database로 간결하게 작성할 수 있으며, Biome 린터도 이를 권장합니다.🔧 수정 제안
- expect(result["database"].status).toBe("up"); + expect(result.database.status).toBe("up");🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/health/drizzle.health-indicator.spec.ts` at line 34, Replace the computed property access in the test assertion so it uses dot notation; change the assertion that references result["database"].status to use result.database.status inside the test in drizzle.health-indicator.spec.ts (update the expect call that references the result variable).Source: Pipeline failures
53-53:⚠️ Potential issue | 🔴 Critical | ⚡ Quick win브래킷 표기법 대신 점 표기법을 사용하세요.
Line 34와 동일하게
result["database"]를result.database로 변경해 주세요.🔧 수정 제안
- expect(result["database"].status).toBe("down"); + expect(result.database.status).toBe("down");🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/health/drizzle.health-indicator.spec.ts` at line 53, Change the bracket property access to dot notation: replace occurrences of result["database"].status with result.database.status in the test (the expect assertion using result["database"] should use result.database instead) so it matches the style used earlier in the file (see the other assertion that uses result.database).Source: Pipeline failures
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/ci.yml:
- Around line 3-11: The workflow lacks a concurrency policy so multiple runs for
the same PR can run concurrently; add a top-level concurrency block to the
workflow (near the existing on: section) that defines a stable group (e.g.,
using github.ref or github.workflow and github.head_ref) and sets
cancel-in-progress: true to automatically cancel previous runs when a new PR
update triggers the same job (apply this to the CI workflow containing jobs.ci /
name: Lint & Test).
- Around line 1-13: 워크플로우가 기본 GITHUB_TOKEN 권한을 사용하도록 leaving permissions
unspecified — 위험하므로 top-level에 명시적인 permissions: 블록을 추가해 최소 권한 원칙을 적용하세요; 예를 들어
아래에 있는 "name: CI" / job "ci" 워크플로우에 대해 최소 필수 권한만 허용하도록 permissions: contents:
read 및 필요시 actions: read, packages: read 등으로 축소하고 불필요한 write 권한(예: contents:
write, workflows: write)을 제거하세요.
- Around line 14-18: Update the CI workflow to pin the GitHub Actions to
immutable SHAs and disable credential persistence: replace the tag-based
references for actions/checkout and oven-sh/setup-bun (the current uses: entries
for actions/checkout@v4 and oven-sh/setup-bun@v2) with their corresponding full
commit SHAs, and add persist-credentials: false under the actions/checkout step
to prevent token/SSH key persistence; keep the bun-version input for setup-bun
unchanged while switching its uses to the SHA-pinned reference.
In `@src/main.ts`:
- Line 31: Replace direct access to process.env.PORT when calling app.listen
with the ConfigService get method: inject or obtain ConfigService in main (e.g.,
from app.get(ConfigService) inside the bootstrap function), read the port via
configService.get<number>('PORT') (or the typed key used in env.schema.ts) and
pass that value (with fallback 3000) into app.listen; ensure the ConfigService
import and retrieval uses the Nest application instance (app.get(ConfigService))
and that the retrieved value is cast/parsed to Number if necessary.
---
Outside diff comments:
In `@src/health/drizzle.health-indicator.spec.ts`:
- Line 34: Replace the computed property access in the test assertion so it uses
dot notation; change the assertion that references result["database"].status to
use result.database.status inside the test in drizzle.health-indicator.spec.ts
(update the expect call that references the result variable).
- Line 53: Change the bracket property access to dot notation: replace
occurrences of result["database"].status with result.database.status in the test
(the expect assertion using result["database"] should use result.database
instead) so it matches the style used earlier in the file (see the other
assertion that uses result.database).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 2f858447-7779-4429-af5f-f751440a9cda
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock,!bun.lock
📒 Files selected for processing (9)
.github/workflows/ci.yml.gitignorepackage.jsonscripts/build.tssrc/app.module.tssrc/config/env.schema.tssrc/health/drizzle.health-indicator.spec.tssrc/main.tstsconfig.json
| name: CI | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: [main] | ||
|
|
||
| jobs: | ||
| ci: | ||
| name: Lint & Test | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: |
There was a problem hiding this comment.
permissions 미지정으로 GITHUB_TOKEN 권한이 과도할 수 있습니다.
Line 1-13 기준으로 워크플로우에 permissions: 블록이 없어 기본 권한 정책에 의존합니다. 최소권한 원칙에 맞게 명시적으로 축소하세요.
🔧 제안 수정
name: CI
on:
pull_request:
push:
branches: [main]
+permissions:
+ contents: read
+
jobs:
ci:📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| name: CI | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| jobs: | |
| ci: | |
| name: Lint & Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| name: CI | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| jobs: | |
| ci: | |
| name: Lint & Test | |
| runs-on: ubuntu-latest | |
| steps: |
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 1-28: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block
(excessive-permissions)
[warning] 3-6: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting
(concurrency-limits)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/ci.yml around lines 1 - 13, 워크플로우가 기본 GITHUB_TOKEN 권한을
사용하도록 leaving permissions unspecified — 위험하므로 top-level에 명시적인 permissions: 블록을
추가해 최소 권한 원칙을 적용하세요; 예를 들어 아래에 있는 "name: CI" / job "ci" 워크플로우에 대해 최소 필수 권한만
허용하도록 permissions: contents: read 및 필요시 actions: read, packages: read 등으로 축소하고
불필요한 write 권한(예: contents: write, workflows: write)을 제거하세요.
Source: Linters/SAST tools
| on: | ||
| pull_request: | ||
| push: | ||
| branches: [main] | ||
|
|
||
| jobs: | ||
| ci: | ||
| name: Lint & Test | ||
| runs-on: ubuntu-latest |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | ⚡ Quick win
중복 실행 방지를 위한 concurrency 설정을 추가하세요.
Line 3-11 기준으로 PR 업데이트 시 이전 실행을 취소하지 않아 CI 자원 낭비와 결과 지연이 발생할 수 있습니다.
🔧 제안 수정
on:
pull_request:
push:
branches: [main]
+concurrency:
+ group: ci-${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
jobs:
ci:📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| jobs: | |
| ci: | |
| name: Lint & Test | |
| runs-on: ubuntu-latest | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| ci: | |
| name: Lint & Test | |
| runs-on: ubuntu-latest |
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 3-6: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting
(concurrency-limits)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/ci.yml around lines 3 - 11, The workflow lacks a
concurrency policy so multiple runs for the same PR can run concurrently; add a
top-level concurrency block to the workflow (near the existing on: section) that
defines a stable group (e.g., using github.ref or github.workflow and
github.head_ref) and sets cancel-in-progress: true to automatically cancel
previous runs when a new PR update triggers the same job (apply this to the CI
workflow containing jobs.ci / name: Lint & Test).
Source: Linters/SAST tools
| - uses: actions/checkout@v4 | ||
|
|
||
| - uses: oven-sh/setup-bun@v2 | ||
| with: | ||
| bun-version: "1.3.14" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 워크플로우에서 태그 기반 uses, 권한/토큰 설정 누락을 점검합니다.
rg -n '^\s*uses:\s*[^@]+@v[0-9]+' .github/workflows
rg -n 'persist-credentials|^\s*permissions:' .github/workflows/ci.ymlRepository: mash-up-kr/Team-MINO-Node
Length of output: 284
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== ci.yml lines 1-60 ==="
nl -ba .github/workflows/ci.yml | sed -n '1,80p'
echo "=== persist-credentials occurrences ==="
rg -n 'persist-credentials' .github/workflows || true
echo "=== permissions occurrences (ci.yml) ==="
rg -n '^\s*permissions:' .github/workflows/ci.yml || trueRepository: mash-up-kr/Team-MINO-Node
Length of output: 156
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== ci.yml lines 1-60 ==="
nl -ba .github/workflows/ci.yml | sed -n '1,80p'
echo "=== persist-credentials occurrences ==="
rg -n 'persist-credentials' .github/workflows || true
echo "=== permissions occurrences (ci.yml) ==="
rg -n '^\s*permissions:' .github/workflows/ci.yml || trueRepository: mash-up-kr/Team-MINO-Node
Length of output: 156
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== workflow files ==="
find .github/workflows -maxdepth 1 -type f \( -name '*.yml' -o -name '*.yaml' \) -print | sort
echo "=== ci.yml (raw, first 120 lines) ==="
if [ -f .github/workflows/ci.yml ]; then
sed -n '1,120p' .github/workflows/ci.yml
else
echo "Missing: .github/workflows/ci.yml"
fi
echo "=== persist-credentials occurrences ==="
rg -n 'persist-credentials' .github/workflows || true
echo "=== permissions occurrences in ci.yml ==="
if [ -f .github/workflows/ci.yml ]; then
rg -n '^\s*permissions:' .github/workflows/ci.yml || true
fi
echo "=== uses@v in ci.yml ==="
if [ -f .github/workflows/ci.yml ]; then
rg -n '^\s*uses:\s*[^@]+@v[0-9]+' .github/workflows/ci.yml || true
fiRepository: mash-up-kr/Team-MINO-Node
Length of output: 777
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== workflow files ==="
find .github/workflows -maxdepth 1 -type f \( -name '*.yml' -o -name '*.yaml' \) -print | sort
echo "=== ci.yml (raw, first 120 lines) ==="
if [ -f .github/workflows/ci.yml ]; then
sed -n '1,120p' .github/workflows/ci.yml
else
echo "Missing: .github/workflows/ci.yml"
fi
echo "=== persist-credentials occurrences ==="
rg -n 'persist-credentials' .github/workflows || true
echo "=== permissions occurrences in ci.yml ==="
if [ -f .github/workflows/ci.yml ]; then
rg -n '^\s*permissions:' .github/workflows/ci.yml || true
fi
echo "=== uses@v in ci.yml ==="
if [ -f .github/workflows/ci.yml ]; then
rg -n '^\s*uses:\s*[^@]+@v[0-9]+' .github/workflows/ci.yml || true
fiRepository: mash-up-kr/Team-MINO-Node
Length of output: 777
🌐 Web query:
GitHub actions/checkout v4 persist-credentials default value token persisted git config
💡 Result:
In GitHub Actions actions/checkout@v4, the persist-credentials input has a default value of true [1][2][3]. When persist-credentials is set to true (the default), the authentication token or SSH key used for the checkout is automatically persisted in the local git configuration of the repository [3][4]. This functionality allows subsequent steps in your workflow to execute authenticated git commands (such as git push or git pull) without needing to manually configure credentials [3][4]. To maintain security, the action automatically removes this token during the post-job cleanup phase [3][4]. If you wish to opt out of this behavior—for example, if you do not want the token to be available to other steps in your job—you can explicitly set persist-credentials: false in your workflow configuration [3][4].
Citations:
- 1: https://github.com/actions/checkout/blob/v4/action.yml
- 2: https://github.com/actions/checkout/blob/v4.1.1/action.yml
- 3: https://github.com/actions/checkout/blob/v4/README.md
- 4: https://github.com/actions/checkout/?tab=readme-ov-file
CI 워크플로우에서 actions/checkout/setup-bun 액션을 SHA로 고정하고 persist-credentials: false로 토큰 영속화를 막으세요.
File: .github/workflows/ci.yml
Lines: 14-18
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.14"- 현재
@v4/@v2태그 기반이라 공급망 리스크가 남습니다(풀 SHA로 핀ning 필요). actions/checkout의persist-credentials가 지정돼 있지 않아 기본값(true)으로 체크아웃에 사용된 토큰/SSH 키가 작업 중 로컬 git 설정에 영속됩니다. (따라서persist-credentials: false로 명시 비활성화 필요)
🔧 제안 수정
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@<FULL_SHA_FOR_V4>
+ with:
+ persist-credentials: false
- - uses: oven-sh/setup-bun@v2
+ - uses: oven-sh/setup-bun@<FULL_SHA_FOR_V2>
with:
bun-version: "1.3.14"🧰 Tools
🪛 zizmor (1.25.2)
[warning] 14-14: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 14-14: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 16-16: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/ci.yml around lines 14 - 18, Update the CI workflow to pin
the GitHub Actions to immutable SHAs and disable credential persistence: replace
the tag-based references for actions/checkout and oven-sh/setup-bun (the current
uses: entries for actions/checkout@v4 and oven-sh/setup-bun@v2) with their
corresponding full commit SHAs, and add persist-credentials: false under the
actions/checkout step to prevent token/SSH key persistence; keep the bun-version
input for setup-bun unchanged while switching its uses to the SHA-pinned
reference.
Source: Linters/SAST tools
| const document = SwaggerModule.createDocument(app, swaggerConfig); | ||
| adapter.setupSwagger("/api-docs", document as Record<string, unknown>); | ||
|
|
||
| await app.listen(Number(process.env.PORT) || 3000); |
There was a problem hiding this comment.
환경변수를 ConfigService를 통해 접근해야 합니다.
process.env.PORT를 직접 읽는 대신 ConfigService를 사용해야 합니다. 이는 타입 안전성을 보장하고 env.schema.ts의 검증을 활용하며, 프로젝트의 코딩 가이드라인을 준수합니다.
🔧 수정 제안
+ const configService = app.get(ConfigService);
+ const port = configService.get("PORT", 3000, { infer: true });
- await app.listen(Number(process.env.PORT) || 3000);
+ await app.listen(port);코딩 가이드라인에 따르면 "환경변수는 ConfigService를 통해서만 접근"해야 합니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main.ts` at line 31, Replace direct access to process.env.PORT when
calling app.listen with the ConfigService get method: inject or obtain
ConfigService in main (e.g., from app.get(ConfigService) inside the bootstrap
function), read the port via configService.get<number>('PORT') (or the typed key
used in env.schema.ts) and pass that value (with fallback 3000) into app.listen;
ensure the ConfigService import and retrieval uses the Nest application instance
(app.get(ConfigService)) and that the retrieved value is cast/parsed to Number
if necessary.
Source: Coding guidelines
- 테스트 최상단에 더미 DATABASE_URL 설정 (실제 DB 없는 CI 환경 대응) - /health 응답에 503 허용 (DB 연결 불가 시) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ES module import 호이스팅으로 인해 process.env 할당이 너무 늦게 실행됨. 테스트 스크립트에서 DATABASE_URL 기본값을 shell 레벨에서 설정하여 해결. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
📌 Related Issue
close #1
🚀 Description
NestJS 백엔드 프로젝트의 초기 개발 환경을 구성합니다.
✅ Done
.env.example제공DB_POOL_SIZE) 환경변수로 관리/api-docs) 설정GET /health—@nestjs/terminus기반, 서버 + DB 상태 동시 확인📢 Notes
DB_POOL_SIZE기본값은10http://localhost:3000/api-docs에서 확인/health가 HTTP 503을 반환하여 로드밸런서/컨테이너 오케스트레이터가 자동으로 감지 가능Summary by CodeRabbit
릴리스 노트
New Features
Documentation
Tests
Chores