CI/CD Integration
Framedash CLI integrates with any CI/CD system. This guide covers Jenkins and TeamCity with ready-to-use examples.
Prerequisites
Section titled “Prerequisites”- Install the CLI in your CI environment:
npm install -g @framedash/cli- The performance gate examples use
jqandbcfor JSON parsing and threshold checks. Ensure they are available on your CI agent. - Create an API key in Settings > API Keys on the Framedash dashboard.
- Note your Project ID from the project settings page.
Environment Variables
Section titled “Environment Variables”Configure these in your CI system’s secret management:
| Variable | Required | Description |
|---|---|---|
FRAMEDASH_API_KEY | Yes | API key (fd_admin_* for uploads, fd_* for read-only access) |
FRAMEDASH_PROJECT_ID | Yes | Target project UUID |
FRAMEDASH_BASE_URL | No | Custom API host URL (default: https://app.framedash.dev) |
Jenkins
Section titled “Jenkins”Credentials Setup
Section titled “Credentials Setup”Store the API key as a Jenkins credential (Secret text):
- Go to Manage Jenkins > Credentials > System > Global credentials
- Add a Secret text credential with ID
framedash-api-key - Add a Secret text credential with ID
framedash-project-id
Declarative Pipeline
Section titled “Declarative Pipeline”Post-Build Telemetry Check
Section titled “Post-Build Telemetry Check”Verify that the game build is sending telemetry data after an automated test run:
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 ''' } } }}Performance Regression Gate
Section titled “Performance Regression Gate”Fail the build if performance metrics fall below thresholds:
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.' } }}Map Capture Upload
Section titled “Map Capture Upload”Automatically upload map images after level builds:
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 ''' } } }}Content Registry Sync
Section titled “Content Registry Sync”Keep the content registry in sync with your game data:
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 ''' } } }}Shared Library
Section titled “Shared Library”For organizations with multiple game projects, create a Jenkins Shared Library:
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 """ }}Usage in a Jenkinsfile:
@Library('your-shared-lib') _
pipeline { agent any stages { stage('Framedash Report') { steps { framedashReport(days: 7) } } }}TeamCity
Section titled “TeamCity”Parameter Setup
Section titled “Parameter Setup”Add these as Configuration Parameters in your build configuration:
- Go to Build Configuration > Parameters
- Add parameter
env.FRAMEDASH_API_KEY(type: Password, spec:password display='hidden') - Add parameter
env.FRAMEDASH_PROJECT_ID(type: Text)
Or define them at the Project level for shared use across build configurations.
Build Steps
Section titled “Build Steps”Post-Build Telemetry Check
Section titled “Post-Build Telemetry Check”Add a Command Line build step:
Step name: Verify Framedash Telemetry
#!/bin/bashset -euo pipefail
echo "Verifying Framedash authentication..."framedash auth
echo "Project status:"framedash status --format tablePerformance Regression Gate
Section titled “Performance Regression Gate”Add a Command Line build step:
Step name: 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"Map Capture Upload
Section titled “Map Capture Upload”Add a Command Line build step:
Step name: 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 --uploadFunnel Analysis Report
Section titled “Funnel Analysis Report”Add a Command Line build step to track conversion funnels:
#!/bin/bashset -euo pipefail
echo "Funnel analysis (7-day window):"framedash funnel \ --steps "tutorial_start,tutorial_complete,first_purchase" \ --days 7 \ --format tableBuild Configuration Template (Kotlin DSL)
Section titled “Build Configuration Template (Kotlin DSL)”For TeamCity projects using Kotlin DSL:
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() } }})Meta-Runner
Section titled “Meta-Runner”Create a reusable meta-runner for Framedash checks. Save as Framedash_Performance_Gate.xml in your project’s .teamcity/pluginData/metaRunners/ directory:
<?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>Common Patterns
Section titled “Common Patterns”SQL-Based Quality Gates
Section titled “SQL-Based Quality Gates”Use framedash query with SQL files for repeatable checks:
-- 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 jsonOutput Format for Parsing
Section titled “Output Format for Parsing”Use --format json with jq for reliable CI parsing:
# Extract a single valueframedash dashboard --days 1 --format json | jq '.data.kpis.totalEvents'
# Check project statusframedash status --format json | jq '.data.project.name'Use --format table for human-readable build logs:
framedash dashboard --days 7 --format tableframedash retention --days 30 --format tableNightly Performance Report
Section titled “Nightly Performance Report”Schedule a nightly build that generates a performance summary:
#!/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 tableTroubleshooting
Section titled “Troubleshooting”Authentication Errors
Section titled “Authentication Errors”Error: Unauthorized (401)- Verify
FRAMEDASH_API_KEYis set and valid - Run
framedash authto test the key - Admin keys (
fd_admin_*) are required for map uploads
Rate Limiting
Section titled “Rate Limiting”Error: Too Many Requests (429)- The CLI displays the reset time from
X-RateLimit-Reset - Add a retry with backoff in your pipeline script
- Consider upgrading your plan for higher limits
Network / Proxy
Section titled “Network / Proxy”If your CI environment uses a proxy:
export HTTPS_PROXY=http://proxy.example.com:8080framedash authCLI Not Found
Section titled “CLI Not Found”Ensure the CLI is installed in the CI agent’s PATH:
# Verify installationwhich framedash || npm install -g @framedash/cli
# Or use npx without global installnpx @framedash/cli authNext Steps
Section titled “Next Steps”- CLI Reference — Full command documentation
- API Reference — REST API details
- CI Profiling — Automated performance profiling setup