UNPKG

bktide

Version:

Command-line interface for Buildkite CI/CD workflows with rich shell completions (Fish, Bash, Zsh) and Alfred workflow integration for macOS power users

186 lines 6.48 kB
import { BaseBuildDetailFormatter } from './Formatter.js'; export class JsonFormatter extends BaseBuildDetailFormatter { name = 'json'; formatBuildDetail(buildData, options) { if (options?.hasError || !buildData) { return JSON.stringify({ error: true, errorType: options?.errorType || 'unknown', message: options?.errorMessage || 'An error occurred' }, null, 2); } const build = buildData.build; // Transform based on options let output = { id: build.id, number: build.number, state: build.state, branch: build.branch, message: build.message, commit: build.commit, url: build.url, createdAt: build.createdAt, startedAt: build.startedAt, finishedAt: build.finishedAt }; // Add creator info if (build.createdBy) { output.createdBy = { name: build.createdBy.name, email: build.createdBy.email }; } // Add organization and pipeline if (build.organization) { output.organization = { id: build.organization.id, name: build.organization.name, slug: build.organization.slug }; } if (build.pipeline) { output.pipeline = { id: build.pipeline.id, name: build.pipeline.name, slug: build.pipeline.slug }; } // Add jobs if requested or failed if (options?.jobs || options?.failed || options?.full) { const jobs = build.jobs?.edges || []; if (options?.failed) { // Filter to only failed jobs (both hard and soft failures) output.jobs = jobs .filter((j) => { const exitCode = j.node.exitStatus !== null ? parseInt(j.node.exitStatus, 10) : null; return j.node.state === 'FAILED' || (exitCode !== null && exitCode !== 0); }) .map((j) => this.formatJob(j.node)); } else { output.jobs = jobs.map((j) => this.formatJob(j.node)); } // Add job statistics output.job_stats = this.calculateJobStats(jobs.map((j) => j.node)); } // Add annotations if requested if (options?.annotations || options?.annotationsFull || options?.full) { const annotations = build.annotations?.edges || []; output.annotations = annotations.map((a) => ({ id: a.node.id, style: a.node.style, context: a.node.context, body: options?.annotationsFull ? a.node.body?.html : undefined, createdAt: a.node.createdAt, updatedAt: a.node.updatedAt })); } // Add extra details if full if (options?.full) { if (build.pullRequest) { output.pullRequest = { id: build.pullRequest.id, number: build.pullRequest.number, repository: build.pullRequest.repository }; } if (build.triggeredFrom) { output.triggeredFrom = { id: build.triggeredFrom.id, number: build.triggeredFrom.number, url: build.triggeredFrom.url, pipeline: build.triggeredFrom.pipeline }; } if (build.blockedState) { output.blockedState = build.blockedState; } } return JSON.stringify(output, null, 2); } formatJob(job) { const formatted = { id: job.id, uuid: job.uuid, label: job.label, state: job.state, exitStatus: job.exitStatus, passed: job.passed, soft_failed: job.softFailed, startedAt: job.startedAt, finishedAt: job.finishedAt }; if (job.command) { formatted.command = job.command; } if (job.agent) { formatted.agent = { id: job.agent.id, name: job.agent.name, hostname: job.agent.hostname }; } if (job.retried !== undefined) { formatted.retried = job.retried; } return formatted; } calculateJobStats(jobs) { const stats = { total: jobs.length, passed: 0, failed: 0, soft_failed: 0, running: 0, blocked: 0, skipped: 0 }; for (const job of jobs) { const state = job.state?.toUpperCase(); if (job.exitStatus !== null && job.exitStatus !== undefined) { const exitCode = parseInt(job.exitStatus, 10); if (exitCode === 0) { stats.passed++; } else { if (job.softFailed === true) { stats.soft_failed++; } else { stats.failed++; } } } else if (state === 'RUNNING') { stats.running++; } else if (state === 'BLOCKED') { stats.blocked++; } else if (state === 'SKIPPED' || state === 'BROKEN' || state === 'CANCELED') { stats.skipped++; } else if (state === 'PASSED' || job.passed === true) { stats.passed++; } else if (state === 'FAILED' || job.passed === false) { if (job.softFailed === true) { stats.soft_failed++; } else { stats.failed++; } } } return stats; } formatError(action, error) { return JSON.stringify({ error: true, action, message: error instanceof Error ? error.message : String(error), timestamp: new Date().toISOString() }, null, 2); } } //# sourceMappingURL=JsonFormatter.js.map