bktide 1.0.1755559112 → 1.0.1755639164

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.
Files changed (32) hide show
  1. package/README.md +42 -0
  2. package/dist/commands/ShowBuild.js +31 -5
  3. package/dist/commands/ShowBuild.js.map +1 -1
  4. package/dist/formatters/build-detail/PlainTextFormatter.js +533 -180
  5. package/dist/formatters/build-detail/PlainTextFormatter.js.map +1 -1
  6. package/dist/formatters/builds/PlainTextFormatter.js +4 -2
  7. package/dist/formatters/builds/PlainTextFormatter.js.map +1 -1
  8. package/dist/formatters/pipelines/PlainTextFormatter.js +3 -6
  9. package/dist/formatters/pipelines/PlainTextFormatter.js.map +1 -1
  10. package/dist/graphql/fragments/index.js +3 -0
  11. package/dist/graphql/fragments/index.js.map +1 -0
  12. package/dist/graphql/fragments/jobs.js +112 -0
  13. package/dist/graphql/fragments/jobs.js.map +1 -0
  14. package/dist/graphql/queries.js +35 -53
  15. package/dist/graphql/queries.js.map +1 -1
  16. package/dist/index.js +1 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/scripts/extract-data-patterns.js +118 -0
  19. package/dist/scripts/extract-data-patterns.js.map +1 -0
  20. package/dist/services/BuildkiteClient.js +109 -32
  21. package/dist/services/BuildkiteClient.js.map +1 -1
  22. package/dist/services/BuildkiteRestClient.js +8 -7
  23. package/dist/services/BuildkiteRestClient.js.map +1 -1
  24. package/dist/test-helpers/DataProfiler.js +307 -0
  25. package/dist/test-helpers/DataProfiler.js.map +1 -0
  26. package/dist/test-helpers/PatternMockGenerator.js +590 -0
  27. package/dist/test-helpers/PatternMockGenerator.js.map +1 -0
  28. package/dist/ui/theme.js +193 -8
  29. package/dist/ui/theme.js.map +1 -1
  30. package/dist/utils/terminal-links.js +165 -0
  31. package/dist/utils/terminal-links.js.map +1 -0
  32. package/package.json +19 -3
package/README.md CHANGED
@@ -50,10 +50,25 @@ See [Shell Completions Guide](docs/shell-completions.md) for detailed installati
50
50
  - [Development Guide](docs/development.md) - Information about running and developing the CLI
51
51
  - [Authentication](docs/authentication.md) - How to authenticate with Buildkite
52
52
  - [Caching](docs/caching.md) - Information about the CLI's caching system
53
+ - [Testing Guide](docs/testing-guide.md) - Running tests and testing strategy
54
+ - [API Reference](docs/api-reference.md) - Complete command reference
55
+ - [Troubleshooting](docs/troubleshooting.md) - Common issues and solutions
53
56
  - [Alfred Integration (Overview)](docs/alfred.md) - What the Alfred integration does and quick usage
54
57
  - [Alfred Installation](docs/alfred-installation.md) - End-user install, configuration, and troubleshooting
55
58
  - [Alfred Development](docs/alfred-development.md) - Packaging, wrapper behavior, metadata, and workflow wiring
56
59
 
60
+ ## Testing
61
+
62
+ Run the test suite with:
63
+ ```bash
64
+ npm test # Run all tests
65
+ npm run test:watch # Watch mode for development
66
+ npm run test:coverage # Generate coverage report
67
+ npm run test:extract-patterns # Extract patterns from real data (requires token)
68
+ ```
69
+
70
+ See [Testing Guide](docs/testing/README.md) for details on the hybrid testing strategy.
71
+
57
72
  ## Usage
58
73
 
59
74
  ### Show Your Login Information
@@ -141,6 +156,33 @@ bktide annotations https://buildkite.com/gusto/zenpayroll/builds/1287418 --forma
141
156
  bktide annotations gusto/zenpayroll/1287418 --context build-resources --format json
142
157
  ```
143
158
 
159
+ ### Show Build Details
160
+
161
+ View detailed information about a specific build including jobs and annotations.
162
+
163
+ ```bash
164
+ # View build by slug format
165
+ bktide build org/pipeline/123
166
+
167
+ # View build by URL format
168
+ bktide build @https://buildkite.com/org/pipeline/builds/123
169
+ ```
170
+
171
+ Additional options:
172
+ ```bash
173
+ # Fetch all jobs (handles pagination for large builds)
174
+ bktide build org/pipeline/123 --jobs
175
+
176
+ # Show failure details and error summaries
177
+ bktide build org/pipeline/123 --failed
178
+
179
+ # Include full annotation content
180
+ bktide build org/pipeline/123 --annotations
181
+
182
+ # Combine options for comprehensive view
183
+ bktide build org/pipeline/123 --jobs --failed --annotations
184
+ ```
185
+
144
186
  ### Generate Shell Completions
145
187
 
146
188
  ```bash
@@ -21,10 +21,14 @@ export class ShowBuild extends BaseCommand {
21
21
  if (options.annotationsFull) {
22
22
  adjustedOptions.annotations = true; // --annotations-full implies --annotations
23
23
  }
24
+ if (options.allJobs) {
25
+ adjustedOptions.jobs = true; // --all-jobs implies --jobs
26
+ }
24
27
  if (options.full) {
25
28
  // --full shows everything
26
29
  adjustedOptions.jobs = true;
27
30
  adjustedOptions.annotations = true;
31
+ adjustedOptions.allJobs = true; // --full shows all jobs
28
32
  }
29
33
  // Initialize spinner early
30
34
  const format = options.format || 'plain';
@@ -66,21 +70,43 @@ export class ShowBuild extends BaseCommand {
66
70
  }
67
71
  async fetchBuildData(buildSlug, options) {
68
72
  // Determine what data we need to fetch based on options
69
- const needsJobs = options.jobs || options.failed || options.full;
73
+ const needsAllJobs = options.jobs || options.failed || options.full;
70
74
  const needsAnnotations = options.annotations || options.annotationsFull || options.full;
71
75
  if (options.debug) {
72
76
  logger.debug('Fetching build data', {
73
77
  buildSlug,
74
- needsJobs,
78
+ needsAllJobs,
75
79
  needsAnnotations,
76
80
  full: options.full
77
81
  });
78
82
  }
79
- // Fetch the appropriate level of detail
80
- if (options.full || needsJobs) {
81
- return await this.client.getBuildFull(buildSlug);
83
+ // Use the new pagination-aware method when we need all jobs
84
+ if (needsAllJobs) {
85
+ // Show progress when fetching many jobs (only in plain format)
86
+ const progressCallback = options.format === 'plain' || !options.format
87
+ ? (fetched, total) => {
88
+ const totalStr = total ? `/${total}` : '';
89
+ process.stderr.write(`\rFetching jobs: ${fetched}${totalStr}...`);
90
+ }
91
+ : undefined;
92
+ const buildData = await this.client.getBuildSummaryWithAllJobs(buildSlug, {
93
+ fetchAllJobs: true,
94
+ onProgress: progressCallback
95
+ });
96
+ // Clear the progress line
97
+ if (progressCallback) {
98
+ process.stderr.write('\r\x1b[K'); // Clear the line
99
+ }
100
+ // If we need full details (like command text), fetch that separately
101
+ if (options.full) {
102
+ // For now, getBuildFull still provides more detailed fields
103
+ // In the future, we could enhance the pagination query to include these
104
+ return await this.client.getBuildFull(buildSlug);
105
+ }
106
+ return buildData;
82
107
  }
83
108
  else {
109
+ // Just get the summary with first 100 jobs
84
110
  return await this.client.getBuildSummary(buildSlug);
85
111
  }
86
112
  }
@@ -1 +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"]}
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 allJobs?: 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.allJobs) {\n adjustedOptions.jobs = true; // --all-jobs implies --jobs\n }\n if (options.full) {\n // --full shows everything\n adjustedOptions.jobs = true;\n adjustedOptions.annotations = true;\n adjustedOptions.allJobs = true; // --full shows all jobs\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 needsAllJobs = 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 needsAllJobs,\n needsAnnotations,\n full: options.full\n });\n }\n \n // Use the new pagination-aware method when we need all jobs\n if (needsAllJobs) {\n // Show progress when fetching many jobs (only in plain format)\n const progressCallback = options.format === 'plain' || !options.format\n ? (fetched: number, total?: number) => {\n const totalStr = total ? `/${total}` : '';\n process.stderr.write(`\\rFetching jobs: ${fetched}${totalStr}...`);\n }\n : undefined;\n \n const buildData = await this.client.getBuildSummaryWithAllJobs(buildSlug, {\n fetchAllJobs: true,\n onProgress: progressCallback\n });\n \n // Clear the progress line\n if (progressCallback) {\n process.stderr.write('\\r\\x1b[K'); // Clear the line\n }\n \n // If we need full details (like command text), fetch that separately\n if (options.full) {\n // For now, getBuildFull still provides more detailed fields\n // In the future, we could enhance the pagination query to include these\n return await this.client.getBuildFull(buildSlug);\n }\n \n return buildData;\n } else {\n // Just get the summary with first 100 jobs\n return await this.client.getBuildSummary(buildSlug);\n }\n }\n}\n"]}