bktide 1.0.1755547716 → 1.0.1755559112
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/ShowBuild.js +88 -0
- package/dist/commands/ShowBuild.js.map +1 -0
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/formatters/FormatterFactory.js +4 -0
- package/dist/formatters/FormatterFactory.js.map +1 -1
- package/dist/formatters/build-detail/AlfredFormatter.js +113 -0
- package/dist/formatters/build-detail/AlfredFormatter.js.map +1 -0
- package/dist/formatters/build-detail/Formatter.js +3 -0
- package/dist/formatters/build-detail/Formatter.js.map +1 -0
- package/dist/formatters/build-detail/JsonFormatter.js +132 -0
- package/dist/formatters/build-detail/JsonFormatter.js.map +1 -0
- package/dist/formatters/build-detail/PlainTextFormatter.js +680 -0
- package/dist/formatters/build-detail/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/build-detail/index.js +21 -0
- package/dist/formatters/build-detail/index.js.map +1 -0
- package/dist/graphql/queries.js +181 -0
- package/dist/graphql/queries.js.map +1 -1
- package/dist/index.js +21 -1
- package/dist/index.js.map +1 -1
- package/dist/services/BuildkiteClient.js +61 -1
- package/dist/services/BuildkiteClient.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { BaseCommand } from './BaseCommand.js';
|
|
2
|
+
import { logger } from '../services/logger.js';
|
|
3
|
+
import { parseBuildRef } from '../utils/parseBuildRef.js';
|
|
4
|
+
import { FormatterFactory, FormatterType } from '../formatters/index.js';
|
|
5
|
+
import { Progress } from '../ui/progress.js';
|
|
6
|
+
export class ShowBuild extends BaseCommand {
|
|
7
|
+
static requiresToken = true;
|
|
8
|
+
async execute(options) {
|
|
9
|
+
if (options.debug) {
|
|
10
|
+
logger.debug('Starting ShowBuild command execution', options);
|
|
11
|
+
}
|
|
12
|
+
if (!options.buildArg) {
|
|
13
|
+
logger.error('Build reference is required');
|
|
14
|
+
return 1;
|
|
15
|
+
}
|
|
16
|
+
// Adjust options based on implications
|
|
17
|
+
const adjustedOptions = { ...options };
|
|
18
|
+
if (options.failed) {
|
|
19
|
+
adjustedOptions.jobs = true; // --failed implies --jobs
|
|
20
|
+
}
|
|
21
|
+
if (options.annotationsFull) {
|
|
22
|
+
adjustedOptions.annotations = true; // --annotations-full implies --annotations
|
|
23
|
+
}
|
|
24
|
+
if (options.full) {
|
|
25
|
+
// --full shows everything
|
|
26
|
+
adjustedOptions.jobs = true;
|
|
27
|
+
adjustedOptions.annotations = true;
|
|
28
|
+
}
|
|
29
|
+
// Initialize spinner early
|
|
30
|
+
const format = options.format || 'plain';
|
|
31
|
+
const spinner = Progress.spinner('Fetching build details…', { format });
|
|
32
|
+
try {
|
|
33
|
+
// Ensure the command is initialized
|
|
34
|
+
await this.ensureInitialized();
|
|
35
|
+
// Parse build reference
|
|
36
|
+
const buildRef = parseBuildRef(options.buildArg);
|
|
37
|
+
if (options.debug) {
|
|
38
|
+
logger.debug('Parsed build reference:', buildRef);
|
|
39
|
+
}
|
|
40
|
+
// Construct build slug for GraphQL
|
|
41
|
+
const buildSlug = `${buildRef.org}/${buildRef.pipeline}/${buildRef.number}`;
|
|
42
|
+
// Fetch build data based on what's needed
|
|
43
|
+
const buildData = await this.fetchBuildData(buildSlug, adjustedOptions);
|
|
44
|
+
spinner.stop();
|
|
45
|
+
// Get the appropriate formatter
|
|
46
|
+
const formatter = FormatterFactory.getFormatter(FormatterType.BUILD_DETAIL, options.format || 'plain');
|
|
47
|
+
// Format and output the results
|
|
48
|
+
const output = formatter.formatBuildDetail(buildData, adjustedOptions);
|
|
49
|
+
logger.console(output);
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
spinner.stop();
|
|
54
|
+
logger.error('Failed to fetch build:', error);
|
|
55
|
+
// Handle the error with the formatter
|
|
56
|
+
const formatter = FormatterFactory.getFormatter(FormatterType.BUILD_DETAIL, options.format || 'plain');
|
|
57
|
+
const errorOutput = formatter.formatBuildDetail(null, {
|
|
58
|
+
...adjustedOptions,
|
|
59
|
+
hasError: true,
|
|
60
|
+
errorMessage: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
61
|
+
errorType: 'api',
|
|
62
|
+
});
|
|
63
|
+
logger.console(errorOutput);
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async fetchBuildData(buildSlug, options) {
|
|
68
|
+
// Determine what data we need to fetch based on options
|
|
69
|
+
const needsJobs = options.jobs || options.failed || options.full;
|
|
70
|
+
const needsAnnotations = options.annotations || options.annotationsFull || options.full;
|
|
71
|
+
if (options.debug) {
|
|
72
|
+
logger.debug('Fetching build data', {
|
|
73
|
+
buildSlug,
|
|
74
|
+
needsJobs,
|
|
75
|
+
needsAnnotations,
|
|
76
|
+
full: options.full
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
// Fetch the appropriate level of detail
|
|
80
|
+
if (options.full || needsJobs) {
|
|
81
|
+
return await this.client.getBuildFull(buildSlug);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
return await this.client.getBuildSummary(buildSlug);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=ShowBuild.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShowBuild.js","sourceRoot":"/","sources":["commands/ShowBuild.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseCommand, BaseCommandOptions } from './BaseCommand.js';\nimport { logger } from '../services/logger.js';\nimport { parseBuildRef } from '../utils/parseBuildRef.js';\nimport { FormatterFactory, FormatterType } from '../formatters/index.js';\nimport { Progress } from '../ui/progress.js';\n\nexport interface ShowBuildOptions extends BaseCommandOptions {\n jobs?: boolean;\n failed?: boolean;\n annotations?: boolean;\n annotationsFull?: boolean;\n full?: boolean;\n summary?: boolean;\n buildArg?: string;\n}\n\nexport class ShowBuild extends BaseCommand {\n static requiresToken = true;\n\n async execute(options: ShowBuildOptions): Promise<number> {\n if (options.debug) {\n logger.debug('Starting ShowBuild command execution', options);\n }\n \n if (!options.buildArg) {\n logger.error('Build reference is required');\n return 1;\n }\n \n // Adjust options based on implications\n const adjustedOptions = { ...options };\n if (options.failed) {\n adjustedOptions.jobs = true; // --failed implies --jobs\n }\n if (options.annotationsFull) {\n adjustedOptions.annotations = true; // --annotations-full implies --annotations\n }\n if (options.full) {\n // --full shows everything\n adjustedOptions.jobs = true;\n adjustedOptions.annotations = true;\n }\n \n // Initialize spinner early\n const format = options.format || 'plain';\n const spinner = Progress.spinner('Fetching build details…', { format });\n \n try {\n // Ensure the command is initialized\n await this.ensureInitialized();\n \n // Parse build reference\n const buildRef = parseBuildRef(options.buildArg);\n if (options.debug) {\n logger.debug('Parsed build reference:', buildRef);\n }\n \n // Construct build slug for GraphQL\n const buildSlug = `${buildRef.org}/${buildRef.pipeline}/${buildRef.number}`;\n \n // Fetch build data based on what's needed\n const buildData = await this.fetchBuildData(buildSlug, adjustedOptions);\n spinner.stop();\n \n // Get the appropriate formatter\n const formatter = FormatterFactory.getFormatter(\n FormatterType.BUILD_DETAIL,\n options.format || 'plain'\n ) as any;\n \n // Format and output the results\n const output = formatter.formatBuildDetail(buildData, adjustedOptions);\n \n logger.console(output);\n \n return 0;\n } catch (error) {\n spinner.stop();\n logger.error('Failed to fetch build:', error);\n \n // Handle the error with the formatter\n const formatter = FormatterFactory.getFormatter(\n FormatterType.BUILD_DETAIL,\n options.format || 'plain'\n ) as any;\n \n const errorOutput = formatter.formatBuildDetail(null, {\n ...adjustedOptions,\n hasError: true,\n errorMessage: error instanceof Error ? error.message : 'Unknown error occurred',\n errorType: 'api',\n });\n \n logger.console(errorOutput);\n return 1;\n }\n }\n \n private async fetchBuildData(buildSlug: string, options: ShowBuildOptions): Promise<any> {\n // Determine what data we need to fetch based on options\n const needsJobs = options.jobs || options.failed || options.full;\n const needsAnnotations = options.annotations || options.annotationsFull || options.full;\n \n if (options.debug) {\n logger.debug('Fetching build data', {\n buildSlug,\n needsJobs,\n needsAnnotations,\n full: options.full\n });\n }\n \n // Fetch the appropriate level of detail\n if (options.full || needsJobs) {\n return await this.client.getBuildFull(buildSlug);\n } else {\n return await this.client.getBuildSummary(buildSlug);\n }\n }\n}\n"]}
|
package/dist/commands/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"/","sources":["commands/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC","sourcesContent":["export * from './BaseCommand.js';\nexport * from './ShowViewer.js';\nexport * from './ListOrganizations.js';\nexport * from './ListBuilds.js';\nexport * from './ListPipelines.js';\nexport * from './ManageToken.js';\nexport * from './ListAnnotations.js';\nexport * from './GenerateCompletions.js';"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"/","sources":["commands/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gBAAgB,CAAC","sourcesContent":["export * from './BaseCommand.js';\nexport * from './ShowViewer.js';\nexport * from './ListOrganizations.js';\nexport * from './ListBuilds.js';\nexport * from './ListPipelines.js';\nexport * from './ManageToken.js';\nexport * from './ListAnnotations.js';\nexport * from './GenerateCompletions.js';\nexport * from './ShowBuild.js';"]}
|
|
@@ -5,6 +5,7 @@ import { getOrganizationFormatter } from './organizations/index.js';
|
|
|
5
5
|
import { getErrorFormatter } from './errors/index.js';
|
|
6
6
|
import { getTokenFormatter } from './token/index.js';
|
|
7
7
|
import { getAnnotationFormatter } from './annotations/index.js';
|
|
8
|
+
import { getBuildDetailFormatter } from './build-detail/index.js';
|
|
8
9
|
export var FormatterType;
|
|
9
10
|
(function (FormatterType) {
|
|
10
11
|
FormatterType["PIPELINE"] = "pipeline";
|
|
@@ -14,6 +15,7 @@ export var FormatterType;
|
|
|
14
15
|
FormatterType["ERROR"] = "error";
|
|
15
16
|
FormatterType["TOKEN"] = "token";
|
|
16
17
|
FormatterType["ANNOTATION"] = "annotation";
|
|
18
|
+
FormatterType["BUILD_DETAIL"] = "build-detail";
|
|
17
19
|
})(FormatterType || (FormatterType = {}));
|
|
18
20
|
export class FormatterFactory {
|
|
19
21
|
/**
|
|
@@ -40,6 +42,8 @@ export class FormatterFactory {
|
|
|
40
42
|
return getTokenFormatter(normalizedFormat);
|
|
41
43
|
case FormatterType.ANNOTATION:
|
|
42
44
|
return getAnnotationFormatter(normalizedFormat);
|
|
45
|
+
case FormatterType.BUILD_DETAIL:
|
|
46
|
+
return getBuildDetailFormatter(normalizedFormat);
|
|
43
47
|
default:
|
|
44
48
|
throw new Error(`Unknown formatter type: ${type}`);
|
|
45
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormatterFactory.js","sourceRoot":"/","sources":["formatters/FormatterFactory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"FormatterFactory.js","sourceRoot":"/","sources":["formatters/FormatterFactory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAElE,MAAM,CAAN,IAAY,aASX;AATD,WAAY,aAAa;IACvB,sCAAqB,CAAA;IACrB,gCAAe,CAAA;IACf,kCAAiB,CAAA;IACjB,8CAA6B,CAAA;IAC7B,gCAAe,CAAA;IACf,gCAAe,CAAA;IACf,0CAAyB,CAAA;IACzB,8CAA6B,CAAA;AAC/B,CAAC,EATW,aAAa,KAAb,aAAa,QASxB;AAED,MAAM,OAAO,gBAAgB;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,YAAY,CAAC,IAAmB,EAAE,SAAiB,OAAO;QAC/D,8BAA8B;QAC9B,MAAM,gBAAgB,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;QAErD,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,aAAa,CAAC,QAAQ;gBACzB,OAAO,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;YAChD,KAAK,aAAa,CAAC,KAAK;gBACtB,OAAO,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;YAC7C,KAAK,aAAa,CAAC,MAAM;gBACvB,OAAO,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;YAC9C,KAAK,aAAa,CAAC,YAAY;gBAC7B,OAAO,wBAAwB,CAAC,gBAAgB,CAAC,CAAC;YACpD,KAAK,aAAa,CAAC,KAAK;gBACtB,OAAO,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;YAC7C,KAAK,aAAa,CAAC,KAAK;gBACtB,OAAO,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;YAC7C,KAAK,aAAa,CAAC,UAAU;gBAC3B,OAAO,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;YAClD,KAAK,aAAa,CAAC,YAAY;gBAC7B,OAAO,uBAAuB,CAAC,gBAAgB,CAAQ,CAAC;YAC1D;gBACE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF","sourcesContent":["import { BaseFormatter } from './BaseFormatter.js';\nimport { getPipelineFormatter } from './pipelines/index.js';\nimport { getBuildFormatter } from './builds/index.js';\nimport { getViewerFormatter } from './viewer/index.js';\nimport { getOrganizationFormatter } from './organizations/index.js';\nimport { getErrorFormatter } from './errors/index.js';\nimport { getTokenFormatter } from './token/index.js';\nimport { getAnnotationFormatter } from './annotations/index.js';\nimport { getBuildDetailFormatter } from './build-detail/index.js';\n\nexport enum FormatterType {\n PIPELINE = 'pipeline',\n BUILD = 'build', \n VIEWER = 'viewer',\n ORGANIZATION = 'organization',\n ERROR = 'error',\n TOKEN = 'token',\n ANNOTATION = 'annotation',\n BUILD_DETAIL = 'build-detail'\n}\n\nexport class FormatterFactory {\n /**\n * Get the appropriate formatter based on the type and format\n * @param type The formatter type ('pipeline', 'build', 'viewer', 'organization', 'error', 'token', 'annotation')\n * @param format The format to use ('plain', 'json', 'alfred')\n * @returns The appropriate formatter instance\n */\n static getFormatter(type: FormatterType, format: string = 'plain'): BaseFormatter {\n // Normalize the format string\n const normalizedFormat = format.toLowerCase().trim();\n \n switch (type) {\n case FormatterType.PIPELINE:\n return getPipelineFormatter(normalizedFormat);\n case FormatterType.BUILD:\n return getBuildFormatter(normalizedFormat);\n case FormatterType.VIEWER:\n return getViewerFormatter(normalizedFormat);\n case FormatterType.ORGANIZATION:\n return getOrganizationFormatter(normalizedFormat);\n case FormatterType.ERROR:\n return getErrorFormatter(normalizedFormat);\n case FormatterType.TOKEN:\n return getTokenFormatter(normalizedFormat);\n case FormatterType.ANNOTATION:\n return getAnnotationFormatter(normalizedFormat);\n case FormatterType.BUILD_DETAIL:\n return getBuildDetailFormatter(normalizedFormat) as any;\n default:\n throw new Error(`Unknown formatter type: ${type}`);\n }\n }\n} "]}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { BaseBuildDetailFormatter } from './Formatter.js';
|
|
2
|
+
export class AlfredFormatter extends BaseBuildDetailFormatter {
|
|
3
|
+
name = 'alfred';
|
|
4
|
+
formatBuildDetail(buildData, options) {
|
|
5
|
+
if (options?.hasError || !buildData) {
|
|
6
|
+
return JSON.stringify({
|
|
7
|
+
items: [{
|
|
8
|
+
uid: 'error',
|
|
9
|
+
title: 'Error fetching build',
|
|
10
|
+
subtitle: options?.errorMessage || 'An error occurred',
|
|
11
|
+
valid: false,
|
|
12
|
+
icon: {
|
|
13
|
+
path: './icons/error.png'
|
|
14
|
+
}
|
|
15
|
+
}]
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const build = buildData.build;
|
|
19
|
+
const items = [];
|
|
20
|
+
// Main build item
|
|
21
|
+
const duration = this.formatDuration(build);
|
|
22
|
+
const mainItem = {
|
|
23
|
+
uid: build.id,
|
|
24
|
+
title: `#${build.number}: ${build.message || 'No message'}`,
|
|
25
|
+
subtitle: `${build.state} • ${build.branch} • ${duration}`,
|
|
26
|
+
arg: build.url,
|
|
27
|
+
icon: {
|
|
28
|
+
path: this.getIconPath(build.state)
|
|
29
|
+
},
|
|
30
|
+
mods: {
|
|
31
|
+
cmd: {
|
|
32
|
+
subtitle: 'Open in browser',
|
|
33
|
+
arg: build.url
|
|
34
|
+
},
|
|
35
|
+
alt: {
|
|
36
|
+
subtitle: 'Copy build number',
|
|
37
|
+
arg: build.number.toString()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
items.push(mainItem);
|
|
42
|
+
// Add failed jobs if present
|
|
43
|
+
if (options?.failed || build.state === 'FAILED') {
|
|
44
|
+
const failedJobs = (build.jobs?.edges || [])
|
|
45
|
+
.filter((j) => j.node.state === 'FAILED' || j.node.exitStatus !== 0);
|
|
46
|
+
for (const job of failedJobs) {
|
|
47
|
+
items.push({
|
|
48
|
+
uid: job.node.id,
|
|
49
|
+
title: `❌ ${job.node.label}`,
|
|
50
|
+
subtitle: `Failed with exit code ${job.node.exitStatus || 1}`,
|
|
51
|
+
valid: false,
|
|
52
|
+
icon: {
|
|
53
|
+
path: './icons/failed.png'
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Add annotation summary if present
|
|
59
|
+
if (build.annotations?.edges?.length > 0) {
|
|
60
|
+
const annotationCount = build.annotations.edges.length;
|
|
61
|
+
items.push({
|
|
62
|
+
uid: 'annotations',
|
|
63
|
+
title: `📝 ${annotationCount} annotation${annotationCount > 1 ? 's' : ''}`,
|
|
64
|
+
subtitle: 'View build annotations',
|
|
65
|
+
valid: false,
|
|
66
|
+
icon: {
|
|
67
|
+
path: './icons/annotation.png'
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return JSON.stringify({ items });
|
|
72
|
+
}
|
|
73
|
+
formatDuration(build) {
|
|
74
|
+
if (!build.startedAt) {
|
|
75
|
+
return 'not started';
|
|
76
|
+
}
|
|
77
|
+
const start = new Date(build.startedAt);
|
|
78
|
+
const end = build.finishedAt ? new Date(build.finishedAt) : new Date();
|
|
79
|
+
const durationMs = end.getTime() - start.getTime();
|
|
80
|
+
const minutes = Math.floor(durationMs / 60000);
|
|
81
|
+
const seconds = Math.floor((durationMs % 60000) / 1000);
|
|
82
|
+
if (build.state === 'RUNNING') {
|
|
83
|
+
return `${minutes}m ${seconds}s elapsed`;
|
|
84
|
+
}
|
|
85
|
+
return `${minutes}m ${seconds}s`;
|
|
86
|
+
}
|
|
87
|
+
getIconPath(state) {
|
|
88
|
+
const iconMap = {
|
|
89
|
+
'PASSED': './icons/passed.png',
|
|
90
|
+
'FAILED': './icons/failed.png',
|
|
91
|
+
'RUNNING': './icons/running.png',
|
|
92
|
+
'BLOCKED': './icons/blocked.png',
|
|
93
|
+
'CANCELED': './icons/canceled.png',
|
|
94
|
+
'SCHEDULED': './icons/scheduled.png',
|
|
95
|
+
'SKIPPED': './icons/skipped.png'
|
|
96
|
+
};
|
|
97
|
+
return iconMap[state] || './icons/unknown.png';
|
|
98
|
+
}
|
|
99
|
+
formatError(action, error) {
|
|
100
|
+
return JSON.stringify({
|
|
101
|
+
items: [{
|
|
102
|
+
uid: 'error',
|
|
103
|
+
title: `Error ${action}`,
|
|
104
|
+
subtitle: error instanceof Error ? error.message : String(error),
|
|
105
|
+
valid: false,
|
|
106
|
+
icon: {
|
|
107
|
+
path: './icons/error.png'
|
|
108
|
+
}
|
|
109
|
+
}]
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=AlfredFormatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AlfredFormatter.js","sourceRoot":"/","sources":["formatters/build-detail/AlfredFormatter.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseBuildDetailFormatter, BuildDetail, BuildDetailFormatterOptions } from './Formatter.js';\n\nexport class AlfredFormatter extends BaseBuildDetailFormatter {\n name = 'alfred';\n \n formatBuildDetail(buildData: BuildDetail | null, options?: BuildDetailFormatterOptions): string {\n if (options?.hasError || !buildData) {\n return JSON.stringify({\n items: [{\n uid: 'error',\n title: 'Error fetching build',\n subtitle: options?.errorMessage || 'An error occurred',\n valid: false,\n icon: {\n path: './icons/error.png'\n }\n }]\n });\n }\n \n const build = buildData.build;\n const items: any[] = [];\n \n // Main build item\n const duration = this.formatDuration(build);\n const mainItem = {\n uid: build.id,\n title: `#${build.number}: ${build.message || 'No message'}`,\n subtitle: `${build.state} • ${build.branch} • ${duration}`,\n arg: build.url,\n icon: {\n path: this.getIconPath(build.state)\n },\n mods: {\n cmd: {\n subtitle: 'Open in browser',\n arg: build.url\n },\n alt: {\n subtitle: 'Copy build number',\n arg: build.number.toString()\n }\n }\n };\n \n items.push(mainItem);\n \n // Add failed jobs if present\n if (options?.failed || build.state === 'FAILED') {\n const failedJobs = (build.jobs?.edges || [])\n .filter((j: any) => j.node.state === 'FAILED' || j.node.exitStatus !== 0);\n \n for (const job of failedJobs) {\n items.push({\n uid: job.node.id,\n title: `❌ ${job.node.label}`,\n subtitle: `Failed with exit code ${job.node.exitStatus || 1}`,\n valid: false,\n icon: {\n path: './icons/failed.png'\n }\n });\n }\n }\n \n // Add annotation summary if present\n if (build.annotations?.edges?.length > 0) {\n const annotationCount = build.annotations.edges.length;\n items.push({\n uid: 'annotations',\n title: `📝 ${annotationCount} annotation${annotationCount > 1 ? 's' : ''}`,\n subtitle: 'View build annotations',\n valid: false,\n icon: {\n path: './icons/annotation.png'\n }\n });\n }\n \n return JSON.stringify({ items });\n }\n \n private formatDuration(build: any): string {\n if (!build.startedAt) {\n return 'not started';\n }\n \n const start = new Date(build.startedAt);\n const end = build.finishedAt ? new Date(build.finishedAt) : new Date();\n const durationMs = end.getTime() - start.getTime();\n \n const minutes = Math.floor(durationMs / 60000);\n const seconds = Math.floor((durationMs % 60000) / 1000);\n \n if (build.state === 'RUNNING') {\n return `${minutes}m ${seconds}s elapsed`;\n }\n \n return `${minutes}m ${seconds}s`;\n }\n \n private getIconPath(state: string): string {\n const iconMap: Record<string, string> = {\n 'PASSED': './icons/passed.png',\n 'FAILED': './icons/failed.png',\n 'RUNNING': './icons/running.png',\n 'BLOCKED': './icons/blocked.png',\n 'CANCELED': './icons/canceled.png',\n 'SCHEDULED': './icons/scheduled.png',\n 'SKIPPED': './icons/skipped.png'\n };\n \n return iconMap[state] || './icons/unknown.png';\n }\n \n formatError(action: string, error: any): string {\n return JSON.stringify({\n items: [{\n uid: 'error',\n title: `Error ${action}`,\n subtitle: error instanceof Error ? error.message : String(error),\n valid: false,\n icon: {\n path: './icons/error.png'\n }\n }]\n });\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Formatter.js","sourceRoot":"/","sources":["formatters/build-detail/Formatter.ts"],"names":[],"mappings":"AAcA,MAAM,OAAgB,wBAAwB;CAI7C","sourcesContent":["import { ShowBuildOptions } from '../../commands/ShowBuild.js';\n\nexport interface BuildDetail {\n build: any;\n jobs?: any[];\n annotations?: any[];\n}\n\nexport interface BuildDetailFormatterOptions extends ShowBuildOptions {\n hasError?: boolean;\n errorMessage?: string;\n errorType?: 'access' | 'not_found' | 'api';\n}\n\nexport abstract class BaseBuildDetailFormatter {\n abstract name: string;\n abstract formatBuildDetail(buildData: BuildDetail | null, options?: BuildDetailFormatterOptions): string;\n abstract formatError(action: string, error: any): string;\n}\n"]}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { BaseBuildDetailFormatter } from './Formatter.js';
|
|
2
|
+
export class JsonFormatter extends BaseBuildDetailFormatter {
|
|
3
|
+
name = 'json';
|
|
4
|
+
formatBuildDetail(buildData, options) {
|
|
5
|
+
if (options?.hasError || !buildData) {
|
|
6
|
+
return JSON.stringify({
|
|
7
|
+
error: true,
|
|
8
|
+
errorType: options?.errorType || 'unknown',
|
|
9
|
+
message: options?.errorMessage || 'An error occurred'
|
|
10
|
+
}, null, 2);
|
|
11
|
+
}
|
|
12
|
+
const build = buildData.build;
|
|
13
|
+
// Transform based on options
|
|
14
|
+
let output = {
|
|
15
|
+
id: build.id,
|
|
16
|
+
number: build.number,
|
|
17
|
+
state: build.state,
|
|
18
|
+
branch: build.branch,
|
|
19
|
+
message: build.message,
|
|
20
|
+
commit: build.commit,
|
|
21
|
+
url: build.url,
|
|
22
|
+
createdAt: build.createdAt,
|
|
23
|
+
startedAt: build.startedAt,
|
|
24
|
+
finishedAt: build.finishedAt
|
|
25
|
+
};
|
|
26
|
+
// Add creator info
|
|
27
|
+
if (build.createdBy) {
|
|
28
|
+
output.createdBy = {
|
|
29
|
+
name: build.createdBy.name,
|
|
30
|
+
email: build.createdBy.email
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Add organization and pipeline
|
|
34
|
+
if (build.organization) {
|
|
35
|
+
output.organization = {
|
|
36
|
+
id: build.organization.id,
|
|
37
|
+
name: build.organization.name,
|
|
38
|
+
slug: build.organization.slug
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (build.pipeline) {
|
|
42
|
+
output.pipeline = {
|
|
43
|
+
id: build.pipeline.id,
|
|
44
|
+
name: build.pipeline.name,
|
|
45
|
+
slug: build.pipeline.slug
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// Add jobs if requested or failed
|
|
49
|
+
if (options?.jobs || options?.failed || options?.full) {
|
|
50
|
+
const jobs = build.jobs?.edges || [];
|
|
51
|
+
if (options?.failed) {
|
|
52
|
+
// Filter to only failed jobs
|
|
53
|
+
output.jobs = jobs
|
|
54
|
+
.filter((j) => j.node.state === 'FAILED' || j.node.exitStatus !== 0)
|
|
55
|
+
.map((j) => this.formatJob(j.node));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
output.jobs = jobs.map((j) => this.formatJob(j.node));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Add annotations if requested
|
|
62
|
+
if (options?.annotations || options?.annotationsFull || options?.full) {
|
|
63
|
+
const annotations = build.annotations?.edges || [];
|
|
64
|
+
output.annotations = annotations.map((a) => ({
|
|
65
|
+
id: a.node.id,
|
|
66
|
+
style: a.node.style,
|
|
67
|
+
context: a.node.context,
|
|
68
|
+
body: options?.annotationsFull ? a.node.body?.html : undefined,
|
|
69
|
+
createdAt: a.node.createdAt,
|
|
70
|
+
updatedAt: a.node.updatedAt
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
// Add extra details if full
|
|
74
|
+
if (options?.full) {
|
|
75
|
+
if (build.pullRequest) {
|
|
76
|
+
output.pullRequest = {
|
|
77
|
+
id: build.pullRequest.id,
|
|
78
|
+
number: build.pullRequest.number,
|
|
79
|
+
repository: build.pullRequest.repository
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (build.triggeredFrom) {
|
|
83
|
+
output.triggeredFrom = {
|
|
84
|
+
id: build.triggeredFrom.id,
|
|
85
|
+
number: build.triggeredFrom.number,
|
|
86
|
+
url: build.triggeredFrom.url,
|
|
87
|
+
pipeline: build.triggeredFrom.pipeline
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (build.blockedState) {
|
|
91
|
+
output.blockedState = build.blockedState;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return JSON.stringify(output, null, 2);
|
|
95
|
+
}
|
|
96
|
+
formatJob(job) {
|
|
97
|
+
const formatted = {
|
|
98
|
+
id: job.id,
|
|
99
|
+
uuid: job.uuid,
|
|
100
|
+
label: job.label,
|
|
101
|
+
state: job.state,
|
|
102
|
+
exitStatus: job.exitStatus,
|
|
103
|
+
passed: job.passed,
|
|
104
|
+
soft_failed: job.soft_failed,
|
|
105
|
+
startedAt: job.startedAt,
|
|
106
|
+
finishedAt: job.finishedAt
|
|
107
|
+
};
|
|
108
|
+
if (job.command) {
|
|
109
|
+
formatted.command = job.command;
|
|
110
|
+
}
|
|
111
|
+
if (job.agent) {
|
|
112
|
+
formatted.agent = {
|
|
113
|
+
id: job.agent.id,
|
|
114
|
+
name: job.agent.name,
|
|
115
|
+
hostname: job.agent.hostname
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (job.retried !== undefined) {
|
|
119
|
+
formatted.retried = job.retried;
|
|
120
|
+
}
|
|
121
|
+
return formatted;
|
|
122
|
+
}
|
|
123
|
+
formatError(action, error) {
|
|
124
|
+
return JSON.stringify({
|
|
125
|
+
error: true,
|
|
126
|
+
action,
|
|
127
|
+
message: error instanceof Error ? error.message : String(error),
|
|
128
|
+
timestamp: new Date().toISOString()
|
|
129
|
+
}, null, 2);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=JsonFormatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JsonFormatter.js","sourceRoot":"/","sources":["formatters/build-detail/JsonFormatter.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseBuildDetailFormatter, BuildDetail, BuildDetailFormatterOptions } from './Formatter.js';\n\nexport class JsonFormatter extends BaseBuildDetailFormatter {\n name = 'json';\n \n formatBuildDetail(buildData: BuildDetail | null, options?: BuildDetailFormatterOptions): string {\n if (options?.hasError || !buildData) {\n return JSON.stringify({\n error: true,\n errorType: options?.errorType || 'unknown',\n message: options?.errorMessage || 'An error occurred'\n }, null, 2);\n }\n \n const build = buildData.build;\n \n // Transform based on options\n let output: any = {\n id: build.id,\n number: build.number,\n state: build.state,\n branch: build.branch,\n message: build.message,\n commit: build.commit,\n url: build.url,\n createdAt: build.createdAt,\n startedAt: build.startedAt,\n finishedAt: build.finishedAt\n };\n \n // Add creator info\n if (build.createdBy) {\n output.createdBy = {\n name: build.createdBy.name,\n email: build.createdBy.email\n };\n }\n \n // Add organization and pipeline\n if (build.organization) {\n output.organization = {\n id: build.organization.id,\n name: build.organization.name,\n slug: build.organization.slug\n };\n }\n \n if (build.pipeline) {\n output.pipeline = {\n id: build.pipeline.id,\n name: build.pipeline.name,\n slug: build.pipeline.slug\n };\n }\n \n // Add jobs if requested or failed\n if (options?.jobs || options?.failed || options?.full) {\n const jobs = build.jobs?.edges || [];\n \n if (options?.failed) {\n // Filter to only failed jobs\n output.jobs = jobs\n .filter((j: any) => j.node.state === 'FAILED' || j.node.exitStatus !== 0)\n .map((j: any) => this.formatJob(j.node));\n } else {\n output.jobs = jobs.map((j: any) => this.formatJob(j.node));\n }\n }\n \n // Add annotations if requested\n if (options?.annotations || options?.annotationsFull || options?.full) {\n const annotations = build.annotations?.edges || [];\n output.annotations = annotations.map((a: any) => ({\n id: a.node.id,\n style: a.node.style,\n context: a.node.context,\n body: options?.annotationsFull ? a.node.body?.html : undefined,\n createdAt: a.node.createdAt,\n updatedAt: a.node.updatedAt\n }));\n }\n \n // Add extra details if full\n if (options?.full) {\n if (build.pullRequest) {\n output.pullRequest = {\n id: build.pullRequest.id,\n number: build.pullRequest.number,\n repository: build.pullRequest.repository\n };\n }\n \n if (build.triggeredFrom) {\n output.triggeredFrom = {\n id: build.triggeredFrom.id,\n number: build.triggeredFrom.number,\n url: build.triggeredFrom.url,\n pipeline: build.triggeredFrom.pipeline\n };\n }\n \n if (build.blockedState) {\n output.blockedState = build.blockedState;\n }\n }\n \n return JSON.stringify(output, null, 2);\n }\n \n private formatJob(job: any): any {\n const formatted: any = {\n id: job.id,\n uuid: job.uuid,\n label: job.label,\n state: job.state,\n exitStatus: job.exitStatus,\n passed: job.passed,\n soft_failed: job.soft_failed,\n startedAt: job.startedAt,\n finishedAt: job.finishedAt\n };\n \n if (job.command) {\n formatted.command = job.command;\n }\n \n if (job.agent) {\n formatted.agent = {\n id: job.agent.id,\n name: job.agent.name,\n hostname: job.agent.hostname\n };\n }\n \n if (job.retried !== undefined) {\n formatted.retried = job.retried;\n }\n \n return formatted;\n }\n \n formatError(action: string, error: any): string {\n return JSON.stringify({\n error: true,\n action,\n message: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString()\n }, null, 2);\n }\n}\n"]}
|