CI/CD 통합
Framedash CLI는 모든 CI/CD 시스템과 통합할 수 있습니다. 이 가이드에서는 Jenkins와 TeamCity의 바로 사용 가능한 예시를 다룹니다.
사전 요구 사항
섹션 제목: “사전 요구 사항”- CI 환경에 CLI를 설치합니다:
npm install -g @framedash/cli- 성능 게이트 예시에서는
jq와bc를 사용합니다. CI 에이전트에 설치되어 있는지 확인합니다. - Framedash 대시보드의 설정 > API 키에서 API 키를 생성합니다.
- 프로젝트 설정 페이지에서 프로젝트 ID를 확인합니다.
환경 변수
섹션 제목: “환경 변수”CI 시스템의 시크릿 관리에서 다음을 설정합니다:
| 변수 | 필수 | 설명 |
|---|---|---|
FRAMEDASH_API_KEY | 예 | API 키 (업로드: fd_admin_*, 읽기 전용: fd_*) |
FRAMEDASH_PROJECT_ID | 예 | 대상 프로젝트 UUID |
FRAMEDASH_BASE_URL | 아니오 | 커스텀 API 호스트 URL (기본값: https://app.framedash.dev) |
Jenkins
섹션 제목: “Jenkins”자격 증명 설정
섹션 제목: “자격 증명 설정”API 키를 Jenkins 자격 증명(Secret text)으로 저장합니다:
- Jenkins 관리 > Credentials > System > Global credentials로 이동합니다
- ID
framedash-api-key로 Secret text 자격 증명을 추가합니다 - ID
framedash-project-id로 Secret text 자격 증명을 추가합니다
선언적 파이프라인
섹션 제목: “선언적 파이프라인”빌드 후 텔레메트리 확인
섹션 제목: “빌드 후 텔레메트리 확인”자동 테스트 실행 후 게임 빌드가 텔레메트리 데이터를 전송하고 있는지 확인합니다:
pipeline { agent any
environment { FRAMEDASH_API_KEY = credentials('framedash-api-key') FRAMEDASH_PROJECT_ID = credentials('framedash-project-id') }
stages { stage('Build') { steps { sh 'your-game-build-command' } }
stage('Automated Test') { steps { sh 'your-automated-test-command' } }
stage('Verify Telemetry') { steps { sh ''' framedash auth framedash status --format json > status.json echo "Project status:" framedash status --format table ''' } } }}성능 리그레션 게이트
섹션 제목: “성능 리그레션 게이트”성능 메트릭이 임계값 이하로 떨어지면 빌드를 실패시킵니다:
pipeline { agent any
environment { FRAMEDASH_API_KEY = credentials('framedash-api-key') FRAMEDASH_PROJECT_ID = credentials('framedash-project-id') }
stages { stage('Build & Test') { steps { sh 'your-game-build-and-test-command' } }
stage('Performance Gate') { steps { sh ''' RESULT=$(framedash query \ "SELECT avg(fps) as avg_fps, \ avg(frame_time_ms) as avg_frame_time \ FROM events \ WHERE event_name = 'performance_sample' \ AND timestamp > now() - INTERVAL 1 HOUR" \ --format json)
AVG_FPS=$(echo "$RESULT" | jq -r '.data[0].avg_fps // 0')
echo "Average FPS: $AVG_FPS"
if [ "$(echo "$AVG_FPS < 30" | bc -l)" -eq 1 ]; then echo "FAILED: FPS below 30 threshold ($AVG_FPS)" exit 1 fi
echo "PASSED: FPS meets threshold" ''' } } }
post { failure { echo 'Performance regression detected. Check the Framedash dashboard for details.' } }}맵 캡처 업로드
섹션 제목: “맵 캡처 업로드”레벨 빌드 후 맵 이미지를 자동으로 업로드합니다:
pipeline { agent any
environment { FRAMEDASH_API_KEY = credentials('framedash-api-key') FRAMEDASH_PROJECT_ID = credentials('framedash-project-id') }
stages { stage('Build Level') { steps { sh 'your-level-build-command' } }
stage('Capture Maps') { steps { sh 'your-map-capture-command --output-dir ./map_captures' } }
stage('Upload Maps') { steps { sh ''' framedash map-capture \ --input-dir ./map_captures \ --upload ''' } } }}콘텐츠 레지스트리 동기화
섹션 제목: “콘텐츠 레지스트리 동기화”게임 데이터와 콘텐츠 레지스트리를 동기화합니다:
pipeline { agent any
environment { FRAMEDASH_API_KEY = credentials('framedash-api-key') FRAMEDASH_PROJECT_ID = credentials('framedash-project-id') }
stages { stage('Sync Content') { steps { sh ''' framedash content import ./game-content.json echo "Content registry updated" framedash content list --format table ''' } } }}공유 라이브러리
섹션 제목: “공유 라이브러리”여러 게임 프로젝트를 가진 조직에서는 Jenkins 공유 라이브러리를 생성할 수 있습니다:
def call(Map config = [:]) { def queryDays = config.get('days', 7)
withCredentials([ string(credentialsId: config.apiKeyCredentialId ?: 'framedash-api-key', variable: 'FRAMEDASH_API_KEY'), string(credentialsId: config.projectIdCredentialId ?: 'framedash-project-id', variable: 'FRAMEDASH_PROJECT_ID') ]) { sh """ echo "Framedash dashboard (${queryDays}-day summary):" framedash dashboard --days ${queryDays} --format table """ }}Jenkinsfile에서의 사용:
@Library('your-shared-lib') _
pipeline { agent any stages { stage('Framedash Report') { steps { framedashReport(days: 7) } } }}TeamCity
섹션 제목: “TeamCity”파라미터 설정
섹션 제목: “파라미터 설정”빌드 구성에 Configuration Parameters로 추가합니다:
- Build Configuration > Parameters로 이동합니다
- 파라미터
env.FRAMEDASH_API_KEY를 추가합니다 (타입: Password, spec:password display='hidden') - 파라미터
env.FRAMEDASH_PROJECT_ID를 추가합니다 (타입: Text)
또는 프로젝트 레벨에서 정의하여 빌드 구성 간에 공유할 수 있습니다.
빌드 스텝
섹션 제목: “빌드 스텝”빌드 후 텔레메트리 확인
섹션 제목: “빌드 후 텔레메트리 확인”Command Line 빌드 스텝을 추가합니다:
스텝 이름: Verify Framedash Telemetry
#!/bin/bashset -euo pipefail
echo "Verifying Framedash authentication..."framedash auth
echo "Project status:"framedash status --format table성능 리그레션 게이트
섹션 제목: “성능 리그레션 게이트”Command Line 빌드 스텝을 추가합니다:
스텝 이름: Framedash Performance Gate
#!/bin/bashset -euo pipefail
echo "Querying performance metrics..."RESULT=$(framedash query \ "SELECT avg(fps) as avg_fps, \ avg(frame_time_ms) as avg_frame_time \ FROM events \ WHERE event_name = 'performance_sample' \ AND timestamp > now() - INTERVAL 1 HOUR" \ --format json)
AVG_FPS=$(echo "$RESULT" | jq -r '.data[0].avg_fps // 0')
echo "Average FPS: $AVG_FPS"
if [ "$(echo "$AVG_FPS < 30" | bc -l)" -eq 1 ]; then echo "##teamcity[buildProblem description='FPS below threshold: $AVG_FPS']" exit 1fi
echo "##teamcity[buildStatisticValue key='framedash.avgFps' value='$AVG_FPS']"echo "Performance gate passed"맵 캡처 업로드
섹션 제목: “맵 캡처 업로드”Command Line 빌드 스텝을 추가합니다:
스텝 이름: Upload Map Captures
#!/bin/bashset -euo pipefail
echo "Validating map captures..."framedash map-capture --input-dir ./map_captures --dry-run
echo "Uploading map captures..."framedash map-capture --input-dir ./map_captures --upload퍼널 분석 리포트
섹션 제목: “퍼널 분석 리포트”전환 퍼널을 추적하는 Command Line 빌드 스텝을 추가합니다:
#!/bin/bashset -euo pipefail
echo "Funnel analysis (7-day window):"framedash funnel \ --steps "tutorial_start,tutorial_complete,first_purchase" \ --days 7 \ --format table빌드 구성 템플릿 (Kotlin DSL)
섹션 제목: “빌드 구성 템플릿 (Kotlin DSL)”Kotlin DSL을 사용하는 TeamCity 프로젝트용:
import jetbrains.buildServer.configs.kotlin.*import jetbrains.buildServer.configs.kotlin.buildSteps.script
object FramedashPerformanceGate : BuildType({ name = "Framedash Performance Gate"
params { password("env.FRAMEDASH_API_KEY", "", display = ParameterDisplay.HIDDEN) text("env.FRAMEDASH_PROJECT_ID", "") text("framedash.minFps", "30", label = "Minimum FPS Threshold") }
steps { script { name = "Install Framedash CLI" scriptContent = "npm install -g @framedash/cli" } script { name = "Performance Gate" scriptContent = """ #!/bin/bash set -euo pipefail
MIN_FPS=%framedash.minFps%
RESULT=${'$'}(framedash query \ "SELECT avg(fps) as avg_fps FROM events \ WHERE event_name = 'performance_sample' \ AND timestamp > now() - INTERVAL 1 HOUR" \ --format json)
AVG_FPS=${'$'}(echo "${'$'}RESULT" | jq -r '.data[0].avg_fps // 0')
echo "Average FPS: ${'$'}AVG_FPS (threshold: ${'$'}MIN_FPS)"
if [ "${'$'}(echo "${'$'}AVG_FPS < ${'$'}MIN_FPS" | bc -l)" -eq 1 ]; then echo "##teamcity[buildProblem description='FPS below threshold']" exit 1 fi
echo "##teamcity[buildStatisticValue key='framedash.avgFps' value='${'$'}AVG_FPS']" """.trimIndent() } }})메타 러너
섹션 제목: “메타 러너”재사용 가능한 메타 러너를 생성합니다. 프로젝트의 .teamcity/pluginData/metaRunners/ 디렉토리에 Framedash_Performance_Gate.xml로 저장합니다:
<?xml version="1.0" encoding="UTF-8"?><meta-runner name="Framedash Performance Gate"> <description>Check game performance metrics via Framedash CLI</description> <settings> <parameters> <param name="framedash.minFps" value="30" spec="text description='Minimum acceptable FPS' label='Min FPS'" /> <param name="framedash.queryDays" value="7" spec="text description='Number of days to query' label='Query Days'" /> </parameters> <build-runners> <runner name="Framedash Performance Gate" type="simpleRunner"> <parameters> <param name="script.content"><![CDATA[#!/bin/bashset -euo pipefail
framedash auth
MIN_FPS=%framedash.minFps%
RESULT=$(framedash query \ "SELECT avg(fps) as avg_fps FROM events \ WHERE event_name = 'performance_sample' \ AND timestamp > now() - INTERVAL %framedash.queryDays% DAY" \ --format json)
AVG_FPS=$(echo "$RESULT" | jq -r '.data[0].avg_fps // 0')
echo "Average FPS: $AVG_FPS (threshold: $MIN_FPS)"
if [ "$(echo "$AVG_FPS < $MIN_FPS" | bc -l)" -eq 1 ]; then echo "##teamcity[buildProblem description='FPS below threshold: $AVG_FPS < $MIN_FPS']" exit 1fi
echo "##teamcity[buildStatisticValue key='framedash.avgFps' value='$AVG_FPS']"echo "Performance gate passed"]]></param> <param name="teamcity.step.mode" value="default" /> <param name="use.custom.script" value="true" /> </parameters> </runner> </build-runners> </settings></meta-runner>공통 패턴
섹션 제목: “공통 패턴”SQL 기반 품질 게이트
섹션 제목: “SQL 기반 품질 게이트”framedash query와 SQL 파일로 반복 가능한 검사를 실행합니다:
-- checks/fps-threshold.sqlSELECT avg(fps) as avg_fps, min(fps) as min_fps, quantile(0.05)(fps) as p5_fpsFROM eventsWHERE event_name = 'performance_sample' AND timestamp > now() - INTERVAL 1 DAYframedash query --file checks/fps-threshold.sql --format json출력 형식 활용
섹션 제목: “출력 형식 활용”CI에서의 파싱에는 --format json과 jq를 사용합니다:
# 단일 값 추출framedash dashboard --days 1 --format json | jq '.data.kpis.totalEvents'
# 프로젝트 상태 확인framedash status --format json | jq '.data.project.name'빌드 로그의 가독성에는 --format table을 사용합니다:
framedash dashboard --days 7 --format tableframedash retention --days 30 --format table나이틀리 성능 리포트
섹션 제목: “나이틀리 성능 리포트”성능 요약을 생성하는 나이틀리 빌드를 스케줄링합니다:
#!/bin/bashset -euo pipefail
echo "=== Framedash Nightly Report ==="echo ""echo "--- Project Status ---"framedash status --format tableecho ""echo "--- 7-Day Dashboard ---"framedash dashboard --days 7 --format tableecho ""echo "--- Player Retention ---"framedash retention --days 30 --format tableecho ""echo "--- Alert Rules ---"framedash alerts list --format table문제 해결
섹션 제목: “문제 해결”인증 오류
섹션 제목: “인증 오류”Error: Unauthorized (401)FRAMEDASH_API_KEY가 설정되어 있고 유효한지 확인합니다framedash auth로 키를 테스트합니다- 맵 업로드에는 관리자 키(
fd_admin_*)가 필요합니다
요청 제한
섹션 제목: “요청 제한”Error: Too Many Requests (429)- CLI는
X-RateLimit-Reset의 리셋 시간을 표시합니다 - 파이프라인 스크립트에 백오프 재시도를 추가합니다
- 더 높은 제한이 필요하면 플랜 업그레이드를 고려합니다
네트워크 / 프록시
섹션 제목: “네트워크 / 프록시”CI 환경에서 프록시를 사용하는 경우:
export HTTPS_PROXY=http://proxy.example.com:8080framedash authCLI를 찾을 수 없음
섹션 제목: “CLI를 찾을 수 없음”CLI가 CI 에이전트의 PATH에 설치되어 있는지 확인합니다:
# 설치 확인which framedash || npm install -g @framedash/cli
# 글로벌 설치 없이 npx 사용npx @framedash/cli auth