bktide 0.0.1
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/README.md +145 -0
- package/WORKFLOW_README.md +65 -0
- package/bin/alfred-entrypoint +54 -0
- package/dist/commands/BaseCommand.js +159 -0
- package/dist/commands/BaseCommand.js.map +1 -0
- package/dist/commands/BaseCommandHandler.js +80 -0
- package/dist/commands/BaseCommandHandler.js.map +1 -0
- package/dist/commands/BuildCommandHandler.js +28 -0
- package/dist/commands/BuildCommandHandler.js.map +1 -0
- package/dist/commands/HelloCommandHandler.js +6 -0
- package/dist/commands/HelloCommandHandler.js.map +1 -0
- package/dist/commands/ListAnnotations.js +60 -0
- package/dist/commands/ListAnnotations.js.map +1 -0
- package/dist/commands/ListBuilds.js +137 -0
- package/dist/commands/ListBuilds.js.map +1 -0
- package/dist/commands/ListOrganizations.js +27 -0
- package/dist/commands/ListOrganizations.js.map +1 -0
- package/dist/commands/ListPipelines.js +114 -0
- package/dist/commands/ListPipelines.js.map +1 -0
- package/dist/commands/ManageToken.js +180 -0
- package/dist/commands/ManageToken.js.map +1 -0
- package/dist/commands/OrganizationCommandHandler.js +53 -0
- package/dist/commands/OrganizationCommandHandler.js.map +1 -0
- package/dist/commands/PipelineCommandHandler.js +142 -0
- package/dist/commands/PipelineCommandHandler.js.map +1 -0
- package/dist/commands/ShowViewer.js +26 -0
- package/dist/commands/ShowViewer.js.map +1 -0
- package/dist/commands/UserBuildsCommandHandler.js +61 -0
- package/dist/commands/UserBuildsCommandHandler.js.map +1 -0
- package/dist/commands/ViewerBuildsCommandHandler.js +176 -0
- package/dist/commands/ViewerBuildsCommandHandler.js.map +1 -0
- package/dist/commands/ViewerCommandHandler.js +46 -0
- package/dist/commands/ViewerCommandHandler.js.map +1 -0
- package/dist/commands/index.js +8 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/formatters/BaseFormatter.js +14 -0
- package/dist/formatters/BaseFormatter.js.map +1 -0
- package/dist/formatters/FormatterFactory.js +48 -0
- package/dist/formatters/FormatterFactory.js.map +1 -0
- package/dist/formatters/annotations/Formatter.js +10 -0
- package/dist/formatters/annotations/Formatter.js.map +1 -0
- package/dist/formatters/annotations/JsonFormatter.js +20 -0
- package/dist/formatters/annotations/JsonFormatter.js.map +1 -0
- package/dist/formatters/annotations/PlainTextFormatter.js +35 -0
- package/dist/formatters/annotations/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/annotations/index.js +23 -0
- package/dist/formatters/annotations/index.js.map +1 -0
- package/dist/formatters/builds/AlfredFormatter.js +135 -0
- package/dist/formatters/builds/AlfredFormatter.js.map +1 -0
- package/dist/formatters/builds/Formatter.js +10 -0
- package/dist/formatters/builds/Formatter.js.map +1 -0
- package/dist/formatters/builds/JsonFormatter.js +44 -0
- package/dist/formatters/builds/JsonFormatter.js.map +1 -0
- package/dist/formatters/builds/PlainTextFormatter.js +113 -0
- package/dist/formatters/builds/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/builds/index.js +26 -0
- package/dist/formatters/builds/index.js.map +1 -0
- package/dist/formatters/errors/AlfredFormatter.js +110 -0
- package/dist/formatters/errors/AlfredFormatter.js.map +1 -0
- package/dist/formatters/errors/Formatter.js +98 -0
- package/dist/formatters/errors/Formatter.js.map +1 -0
- package/dist/formatters/errors/JsonFormatter.js +63 -0
- package/dist/formatters/errors/JsonFormatter.js.map +1 -0
- package/dist/formatters/errors/PlainTextFormatter.js +52 -0
- package/dist/formatters/errors/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/errors/index.js +26 -0
- package/dist/formatters/errors/index.js.map +1 -0
- package/dist/formatters/index.js +9 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/formatters/organizations/Formatter.js +10 -0
- package/dist/formatters/organizations/Formatter.js.map +1 -0
- package/dist/formatters/organizations/JsonFormatter.js +16 -0
- package/dist/formatters/organizations/JsonFormatter.js.map +1 -0
- package/dist/formatters/organizations/PlainTextFormatter.js +15 -0
- package/dist/formatters/organizations/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/organizations/index.js +21 -0
- package/dist/formatters/organizations/index.js.map +1 -0
- package/dist/formatters/pipelines/AlfredFormatter.js +42 -0
- package/dist/formatters/pipelines/AlfredFormatter.js.map +1 -0
- package/dist/formatters/pipelines/Formatter.js +10 -0
- package/dist/formatters/pipelines/Formatter.js.map +1 -0
- package/dist/formatters/pipelines/JsonFormatter.js +13 -0
- package/dist/formatters/pipelines/JsonFormatter.js.map +1 -0
- package/dist/formatters/pipelines/PlainTextFormatter.js +47 -0
- package/dist/formatters/pipelines/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/pipelines/index.js +28 -0
- package/dist/formatters/pipelines/index.js.map +1 -0
- package/dist/formatters/token/AlfredFormatter.js +191 -0
- package/dist/formatters/token/AlfredFormatter.js.map +1 -0
- package/dist/formatters/token/Formatter.js +13 -0
- package/dist/formatters/token/Formatter.js.map +1 -0
- package/dist/formatters/token/JsonFormatter.js +211 -0
- package/dist/formatters/token/JsonFormatter.js.map +1 -0
- package/dist/formatters/token/PlainTextFormatter.js +184 -0
- package/dist/formatters/token/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/token/index.js +26 -0
- package/dist/formatters/token/index.js.map +1 -0
- package/dist/formatters/viewer/Formatter.js +10 -0
- package/dist/formatters/viewer/Formatter.js.map +1 -0
- package/dist/formatters/viewer/JsonFormatter.js +20 -0
- package/dist/formatters/viewer/JsonFormatter.js.map +1 -0
- package/dist/formatters/viewer/PlainTextFormatter.js +20 -0
- package/dist/formatters/viewer/PlainTextFormatter.js.map +1 -0
- package/dist/formatters/viewer/index.js +21 -0
- package/dist/formatters/viewer/index.js.map +1 -0
- package/dist/graphql/generated/fragment-masking.js +17 -0
- package/dist/graphql/generated/fragment-masking.js.map +1 -0
- package/dist/graphql/generated/gql.js +13 -0
- package/dist/graphql/generated/gql.js.map +1 -0
- package/dist/graphql/generated/graphql.js +852 -0
- package/dist/graphql/generated/graphql.js.map +1 -0
- package/dist/graphql/generated/index.js +3 -0
- package/dist/graphql/generated/index.js.map +1 -0
- package/dist/graphql/generated/sdk.js +872 -0
- package/dist/graphql/generated/sdk.js.map +1 -0
- package/dist/graphql/queries.js +138 -0
- package/dist/graphql/queries.js.map +1 -0
- package/dist/index.js +271 -0
- package/dist/index.js.map +1 -0
- package/dist/services/BuildkiteClient.js +520 -0
- package/dist/services/BuildkiteClient.js.map +1 -0
- package/dist/services/BuildkiteRestClient.js +244 -0
- package/dist/services/BuildkiteRestClient.js.map +1 -0
- package/dist/services/CacheManager.js +221 -0
- package/dist/services/CacheManager.js.map +1 -0
- package/dist/services/CredentialManager.js +158 -0
- package/dist/services/CredentialManager.js.map +1 -0
- package/dist/services/EnhancedBuildkiteClient.js +297 -0
- package/dist/services/EnhancedBuildkiteClient.js.map +1 -0
- package/dist/services/logger.js +107 -0
- package/dist/services/logger.js.map +1 -0
- package/dist/types/buildkite.js +5 -0
- package/dist/types/buildkite.js.map +1 -0
- package/dist/types/credentials.js +2 -0
- package/dist/types/credentials.js.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/cli-error-handler.js +172 -0
- package/dist/utils/cli-error-handler.js.map +1 -0
- package/dist/utils/errorUtils.js +59 -0
- package/dist/utils/errorUtils.js.map +1 -0
- package/dist/utils/parseBuildRef.js +31 -0
- package/dist/utils/parseBuildRef.js.map +1 -0
- package/dist/utils/textFormatter.js +53 -0
- package/dist/utils/textFormatter.js.map +1 -0
- package/dist/utils/xdgPaths.js +95 -0
- package/dist/utils/xdgPaths.js.map +1 -0
- package/env.example +66 -0
- package/icons/README.md +68 -0
- package/icons/blocked.png +0 -0
- package/icons/buildkite.png +0 -0
- package/icons/failed.png +0 -0
- package/icons/failing.png +0 -0
- package/icons/passed.png +0 -0
- package/icons/running.png +0 -0
- package/icons/scheduled.png +0 -0
- package/icons/skipped.png +0 -0
- package/icons/unknown.png +0 -0
- package/info.plist +734 -0
- package/package.json +87 -0
package/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# bktide
|
|
2
|
+
|
|
3
|
+
A command-line tool for interacting with Buildkite's GraphQL API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g bktide
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Documentation
|
|
12
|
+
|
|
13
|
+
- [Development Guide](docs/development.md) - Information about running and developing the CLI
|
|
14
|
+
- [Authentication](docs/authentication.md) - How to authenticate with Buildkite
|
|
15
|
+
- [Caching](docs/caching.md) - Information about the CLI's caching system
|
|
16
|
+
- [Alfred Integration (Overview)](docs/alfred.md) - What the Alfred integration does and quick usage
|
|
17
|
+
- [Alfred Installation](docs/alfred-installation.md) - End-user install, configuration, and troubleshooting
|
|
18
|
+
- [Alfred Development](docs/alfred-development.md) - Packaging, wrapper behavior, metadata, and workflow wiring
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Show Your Login Information
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm run dev -- viewer
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### List Your Organizations
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm run dev -- orgs
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### List Pipelines in an Organization
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm run dev -- pipelines
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Additional options:
|
|
41
|
+
```bash
|
|
42
|
+
# Filter by organization
|
|
43
|
+
npm run dev -- pipelines --org your-org-slug
|
|
44
|
+
|
|
45
|
+
# Limit the number of results
|
|
46
|
+
npm run dev -- pipelines --count 20
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### List Your Builds
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm run dev -- builds
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Additional options:
|
|
56
|
+
```bash
|
|
57
|
+
# Filter by organization
|
|
58
|
+
npm run dev -- builds --org your-org-slug
|
|
59
|
+
|
|
60
|
+
# Filter by pipeline
|
|
61
|
+
npm run dev -- builds --pipeline pipeline-slug
|
|
62
|
+
|
|
63
|
+
# Filter by branch
|
|
64
|
+
npm run dev -- builds --branch main
|
|
65
|
+
|
|
66
|
+
# Filter by state
|
|
67
|
+
npm run dev -- builds --state passed
|
|
68
|
+
|
|
69
|
+
# Pagination
|
|
70
|
+
npm run dev -- builds --count 20 --page 2
|
|
71
|
+
|
|
72
|
+
# Output in JSON format
|
|
73
|
+
npm run dev -- builds --json
|
|
74
|
+
|
|
75
|
+
# Output in Alfred-compatible JSON format
|
|
76
|
+
npm run dev -- builds --alfred
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Show Build Annotations
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm run dev -- annotations <build>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The build reference can be specified in two formats:
|
|
86
|
+
- **Slug format**: `org/pipeline/number` (e.g., `gusto/zenpayroll/1287418`)
|
|
87
|
+
- **URL format**: `@https://buildkite.com/org/pipeline/builds/number` or `https://buildkite.com/org/pipeline/builds/number`
|
|
88
|
+
|
|
89
|
+
Additional options:
|
|
90
|
+
```bash
|
|
91
|
+
# Filter by context
|
|
92
|
+
npm run dev -- annotations gusto/zenpayroll/1287418 --context rspec
|
|
93
|
+
|
|
94
|
+
# Output in JSON format
|
|
95
|
+
npm run dev -- annotations gusto/zenpayroll/1287418 --format json
|
|
96
|
+
|
|
97
|
+
# Output in plain text format (default)
|
|
98
|
+
npm run dev -- annotations https://buildkite.com/gusto/zenpayroll/builds/1287418 --format plain
|
|
99
|
+
|
|
100
|
+
# Combine filtering and formatting
|
|
101
|
+
npm run dev -- annotations gusto/zenpayroll/1287418 --context build-resources --format json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## API Token
|
|
105
|
+
|
|
106
|
+
You'll need a Buildkite API token with GraphQL scopes. Create one at:
|
|
107
|
+
https://buildkite.com/user/api-access-tokens
|
|
108
|
+
|
|
109
|
+
# Logging System
|
|
110
|
+
|
|
111
|
+
The CLI uses a structured logging system based on Pino. This provides several benefits:
|
|
112
|
+
|
|
113
|
+
- Different log levels (trace, debug, info, warn, error, fatal)
|
|
114
|
+
- JSON logs saved to disk (in `log/cli.log`)
|
|
115
|
+
- Pretty-printed logs to the console
|
|
116
|
+
- Performance measurements
|
|
117
|
+
|
|
118
|
+
## Log Level Configuration
|
|
119
|
+
|
|
120
|
+
You can configure the log level with the `--log-level` option:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
bktide orgs --log-level=debug # Show debug messages
|
|
124
|
+
bktide builds --log-level=trace # Show all messages including trace
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Available log levels (from most to least verbose):
|
|
128
|
+
- trace: Very detailed tracing for debugging
|
|
129
|
+
- debug: Detailed information for developers
|
|
130
|
+
- info: General information (default)
|
|
131
|
+
- warn: Warning conditions
|
|
132
|
+
- error: Error conditions
|
|
133
|
+
- fatal: Severe errors causing termination
|
|
134
|
+
|
|
135
|
+
## Log Files
|
|
136
|
+
|
|
137
|
+
All logs are written to `log/cli.log` in JSON format, which can be processed with tools like jq:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# View recent errors
|
|
141
|
+
cat log/cli.log | grep -v '"level":30' | jq
|
|
142
|
+
|
|
143
|
+
# Analyze performance
|
|
144
|
+
cat log/cli.log | jq 'select(.duration != null) | {msg, duration}'
|
|
145
|
+
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# bktide Alfred Workflow
|
|
2
|
+
|
|
3
|
+
A powerful Alfred workflow for interacting with Buildkite builds, pipelines, and organizations.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
1. **Install Node.js 18+** (required)
|
|
8
|
+
- Download from [nodejs.org](https://nodejs.org/) or install via Homebrew: `brew install node`
|
|
9
|
+
|
|
10
|
+
2. **Set up your Buildkite token**
|
|
11
|
+
- Open Alfred: `bktide token store`
|
|
12
|
+
- Enter your Buildkite API token
|
|
13
|
+
|
|
14
|
+
3. **Start using the workflow**
|
|
15
|
+
- `bktide viewer` - Show your user info
|
|
16
|
+
- `bktide orgs` - List organizations
|
|
17
|
+
- `bktide pipelines` - List pipelines
|
|
18
|
+
- `bktide builds` - List recent builds
|
|
19
|
+
|
|
20
|
+
## Commands
|
|
21
|
+
|
|
22
|
+
| Command | Description |
|
|
23
|
+
|---------|-------------|
|
|
24
|
+
| `bktide viewer` | Show your Buildkite user information |
|
|
25
|
+
| `bktide orgs` | List your accessible organizations |
|
|
26
|
+
| `bktide pipelines [org]` | List pipelines, optionally filtered by org |
|
|
27
|
+
| `bktide builds [filter]` | List recent builds with optional filtering |
|
|
28
|
+
| `bktide annotations <build-ref>` | Show annotations for a specific build |
|
|
29
|
+
|
|
30
|
+
## Configuration
|
|
31
|
+
|
|
32
|
+
If Node.js is not in your PATH, create `~/.config/bktide/env`:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# For Homebrew on Apple Silicon
|
|
36
|
+
export PATH="/opt/homebrew/bin:$PATH"
|
|
37
|
+
NODE_BIN=/opt/homebrew/bin/node
|
|
38
|
+
|
|
39
|
+
# For Homebrew on Intel
|
|
40
|
+
export PATH="/usr/local/bin:$PATH"
|
|
41
|
+
NODE_BIN=/usr/local/bin/node
|
|
42
|
+
|
|
43
|
+
# For nvm
|
|
44
|
+
NODE_BIN=/Users/username/.nvm/versions/node/v18.17.0/bin/node
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
See `env.example` in this workflow for more configuration options.
|
|
48
|
+
|
|
49
|
+
## Troubleshooting
|
|
50
|
+
|
|
51
|
+
**"node: command not found"**
|
|
52
|
+
- Install Node.js or configure the path in `~/.config/bktide/env`
|
|
53
|
+
|
|
54
|
+
**"Authentication failed"**
|
|
55
|
+
- Run `bktide token store` to set up your Buildkite API token
|
|
56
|
+
|
|
57
|
+
**Workflow is slow**
|
|
58
|
+
- Clear cache: `rm -rf ~/.cache/bktide`
|
|
59
|
+
- Check logs: `~/.local/state/bktide/logs/alfred.log`
|
|
60
|
+
|
|
61
|
+
## Support
|
|
62
|
+
|
|
63
|
+
- Full documentation: See included `docs/alfred-installation.md`
|
|
64
|
+
- Issues: [GitHub Issues](https://github.com/yourusername/bktide/issues)
|
|
65
|
+
- Logs: `~/.local/state/bktide/logs/alfred.log`
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
set -x
|
|
5
|
+
|
|
6
|
+
workflow_dir="$(dirname "$0")/.."
|
|
7
|
+
cd "$workflow_dir"
|
|
8
|
+
|
|
9
|
+
# Prefer Alfred's cache directory for logs; fall back to XDG if unavailable
|
|
10
|
+
if [[ -n "$alfred_workflow_cache" ]]; then
|
|
11
|
+
log_file="$alfred_workflow_cache/alfred.log"
|
|
12
|
+
else
|
|
13
|
+
log_file="$HOME/.local/state/bktide/logs/alfred.log"
|
|
14
|
+
fi
|
|
15
|
+
mkdir -p "$(dirname "$log_file")"
|
|
16
|
+
|
|
17
|
+
# Optionally source user-provided environment to customize PATH, NODE_BIN, etc.
|
|
18
|
+
xdg_config_home="${XDG_CONFIG_HOME:-$HOME/.config}"
|
|
19
|
+
user_env_file="$xdg_config_home/bktide/env"
|
|
20
|
+
workflow_env_file="$workflow_dir/.env"
|
|
21
|
+
|
|
22
|
+
if [[ -f "$user_env_file" ]]; then
|
|
23
|
+
# Export variables defined in the file
|
|
24
|
+
set -a
|
|
25
|
+
# shellcheck disable=SC1090
|
|
26
|
+
source "$user_env_file"
|
|
27
|
+
set +a
|
|
28
|
+
elif [[ -f "$workflow_env_file" ]]; then
|
|
29
|
+
set -a
|
|
30
|
+
# shellcheck disable=SC1090
|
|
31
|
+
source "$workflow_env_file"
|
|
32
|
+
set +a
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
command="$1"
|
|
36
|
+
shift
|
|
37
|
+
|
|
38
|
+
if [[ -z "$command" ]]; then
|
|
39
|
+
echo "Usage: $0 <command> [filter]"
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
if [[ -z "$NODE_BIN" ]]; then
|
|
44
|
+
export NODE_BIN=node
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# Enable CLI debug mode if user config sets DEBUG=true/1 (compatible with macOS bash 3.2)
|
|
48
|
+
extra_flags=()
|
|
49
|
+
if [[ "$DEBUG" == "true" || "$DEBUG" == "TRUE" || "$DEBUG" == "True" || "$DEBUG" == "1" ]]; then
|
|
50
|
+
extra_flags+=("--debug")
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
echo "Running command: $NODE_BIN $workflow_dir/dist/index.js $command" "$@" >> "$log_file"
|
|
54
|
+
"$NODE_BIN" "$workflow_dir/dist/index.js" "$command" --format alfred "${extra_flags[@]}" "$@" 2>&1 | tee -a "$log_file"
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { BuildkiteClient } from '../services/BuildkiteClient.js';
|
|
2
|
+
import { BuildkiteRestClient } from '../services/BuildkiteRestClient.js';
|
|
3
|
+
import { FormatterFactory } from '../formatters/index.js';
|
|
4
|
+
import { logger } from '../services/logger.js';
|
|
5
|
+
import { CredentialManager } from '../services/CredentialManager.js';
|
|
6
|
+
export class BaseCommand {
|
|
7
|
+
token;
|
|
8
|
+
requiresToken = true;
|
|
9
|
+
_client;
|
|
10
|
+
_restClient;
|
|
11
|
+
_restClientOptions;
|
|
12
|
+
options;
|
|
13
|
+
initialized = false;
|
|
14
|
+
static credentialManager = new CredentialManager();
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.options = options || {};
|
|
17
|
+
this.token = this.options.token;
|
|
18
|
+
if (this.options.debug) {
|
|
19
|
+
// Include token length (not the actual token) for debugging auth issues
|
|
20
|
+
// Debug mode is already handled here by logger.debug use
|
|
21
|
+
logger.debug('BaseCommandHandler options:', {
|
|
22
|
+
...options,
|
|
23
|
+
token: this.token ? `${this.token.substring(0, 4)}...${this.token.substring(this.token.length - 4)} (${this.token.length} chars)` : 'Not provided'
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
get client() {
|
|
28
|
+
if (this._client) {
|
|
29
|
+
return this._client;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
if (this.token) {
|
|
33
|
+
this._client = new BuildkiteClient(this.token, this.options);
|
|
34
|
+
return this._client;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
throw new Error('No token provided');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
get restClient() {
|
|
42
|
+
if (this._restClient) {
|
|
43
|
+
return this._restClient;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
if (this.token) {
|
|
47
|
+
this._restClient = new BuildkiteRestClient(this.token, this.options);
|
|
48
|
+
return this._restClient;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
throw new Error('No token provided');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
get restClientOptions() {
|
|
56
|
+
if (this._restClientOptions) {
|
|
57
|
+
return this._restClientOptions;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Configure REST client with the same caching options
|
|
61
|
+
const restClientOptions = {
|
|
62
|
+
debug: this.options?.debug,
|
|
63
|
+
caching: !this.options?.noCache,
|
|
64
|
+
};
|
|
65
|
+
// If a specific cache TTL is provided, apply it to REST client
|
|
66
|
+
if (this.options?.cacheTTL) {
|
|
67
|
+
restClientOptions.cacheTTLs = {
|
|
68
|
+
default: this.options.cacheTTL,
|
|
69
|
+
builds: this.options.cacheTTL,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return restClientOptions;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
static get requiresToken() {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
async ensureInitialized() {
|
|
79
|
+
// No additional initialization needed
|
|
80
|
+
return Promise.resolve();
|
|
81
|
+
}
|
|
82
|
+
handleError(error, debug = false) {
|
|
83
|
+
// Only log the error message and stack trace
|
|
84
|
+
if (error instanceof Error) {
|
|
85
|
+
logger.error(error, 'Error occurred');
|
|
86
|
+
// If it's a GraphQL error or API error, show more details
|
|
87
|
+
const apiError = error;
|
|
88
|
+
if (apiError.response?.errors) {
|
|
89
|
+
apiError.response.errors.forEach((gqlError, index) => {
|
|
90
|
+
logger.error({ path: gqlError.path }, `GraphQL Error ${index + 1}: ${gqlError.message}`);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// Show request details if available and in debug mode
|
|
94
|
+
if (debug && apiError.request) {
|
|
95
|
+
logger.debug({
|
|
96
|
+
url: apiError.request.url,
|
|
97
|
+
method: apiError.request.method
|
|
98
|
+
}, 'Request Details');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (typeof error === 'object') {
|
|
102
|
+
logger.error({ error }, 'Unknown error occurred');
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
logger.error({ error }, 'Unknown error occurred');
|
|
106
|
+
}
|
|
107
|
+
if (debug) {
|
|
108
|
+
logger.debug({
|
|
109
|
+
timestamp: new Date().toISOString(),
|
|
110
|
+
nodeVersion: process.version,
|
|
111
|
+
platform: `${process.platform} (${process.arch})`
|
|
112
|
+
}, 'Debug Information');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Static helper to get token from options, keyring, or environment
|
|
116
|
+
static async getToken(options) {
|
|
117
|
+
// First check if token is provided directly in options
|
|
118
|
+
if (options.token) {
|
|
119
|
+
return options.token;
|
|
120
|
+
}
|
|
121
|
+
// Next try to get token from keyring
|
|
122
|
+
try {
|
|
123
|
+
const storedToken = await this.credentialManager.getToken();
|
|
124
|
+
if (storedToken) {
|
|
125
|
+
logger.debug('Using token from system keychain');
|
|
126
|
+
return storedToken;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
logger.debug('Error retrieving token from keychain', error);
|
|
131
|
+
}
|
|
132
|
+
// Finally fall back to environment variable
|
|
133
|
+
const envToken = process.env.BK_TOKEN;
|
|
134
|
+
if (envToken) {
|
|
135
|
+
return envToken;
|
|
136
|
+
}
|
|
137
|
+
if (options.requiresToken) {
|
|
138
|
+
throw new Error('API token required. Set via --token, BK_TOKEN environment variable, or store it using --save-token.');
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get the appropriate formatter based on command-specific type and format option
|
|
146
|
+
* @param type The formatter type ('pipeline', 'build', 'viewer')
|
|
147
|
+
* @param options Command options that may include a format
|
|
148
|
+
* @returns The appropriate formatter
|
|
149
|
+
*/
|
|
150
|
+
getFormatter(type, options) {
|
|
151
|
+
// Format precedence: command line option > constructor option > default
|
|
152
|
+
const format = options.format || this.options.format || 'plain';
|
|
153
|
+
if (options.debug) {
|
|
154
|
+
logger.debug(`Using ${format} formatter for ${type}`);
|
|
155
|
+
}
|
|
156
|
+
return FormatterFactory.getFormatter(type, format);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=BaseCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseCommand.js","sourceRoot":"/","sources":["commands/BaseCommand.ts"],"names":[],"mappings":"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","sourcesContent":["import { BuildkiteClient } from '../services/BuildkiteClient.js';\nimport { BuildkiteRestClient, BuildkiteRestClientOptions } from '../services/BuildkiteRestClient.js';\nimport { FormatterFactory, FormatterType } from '../formatters/index.js';\nimport { logger } from '../services/logger.js';\nimport { CredentialManager } from '../services/CredentialManager.js';\n\nexport interface BaseCommandOptions {\n cacheTTL?: number;\n clearCache?: boolean;\n debug?: boolean;\n filter?: string;\n format?: string;\n noCache?: boolean;\n token?: string;\n}\n\n// Extended Error interface for API and GraphQL errors\ninterface ApiError extends Error {\n response?: {\n errors?: Array<{\n message: string;\n path?: string[];\n locations?: Array<{line: number; column: number}>;\n }>;\n };\n request?: {\n url?: string;\n method?: string;\n };\n}\n\nexport abstract class BaseCommand {\n protected token: string | undefined;\n protected requiresToken: boolean = true;\n private _client: BuildkiteClient | undefined;\n private _restClient: BuildkiteRestClient | undefined;\n private _restClientOptions: BuildkiteRestClientOptions | undefined;\n \n protected options: Partial<BaseCommandOptions>;\n protected initialized: boolean = false;\n protected static credentialManager = new CredentialManager();\n\n constructor(options?: Partial<BaseCommandOptions>) {\n this.options = options || {};\n this.token = this.options.token;\n \n if (this.options.debug) {\n // Include token length (not the actual token) for debugging auth issues\n // Debug mode is already handled here by logger.debug use\n logger.debug('BaseCommandHandler options:', {\n ...options,\n token: this.token ? `${this.token.substring(0, 4)}...${this.token.substring(this.token.length - 4)} (${this.token.length} chars)` : 'Not provided'\n });\n }\n }\n\n get client(): BuildkiteClient {\n if (this._client) {\n return this._client;\n } else {\n if (this.token) {\n this._client = new BuildkiteClient(this.token, this.options);\n return this._client;\n } else {\n throw new Error('No token provided');\n }\n }\n }\n\n get restClient(): BuildkiteRestClient {\n if (this._restClient) {\n return this._restClient;\n } else {\n if (this.token) {\n this._restClient = new BuildkiteRestClient(this.token, this.options);\n return this._restClient;\n } else {\n throw new Error('No token provided');\n }\n }\n }\n\n get restClientOptions(): BuildkiteRestClientOptions {\n if (this._restClientOptions) {\n return this._restClientOptions;\n } else {\n // Configure REST client with the same caching options\n const restClientOptions: BuildkiteRestClientOptions = {\n debug: this.options?.debug,\n caching: !this.options?.noCache,\n };\n \n // If a specific cache TTL is provided, apply it to REST client\n if (this.options?.cacheTTL) {\n restClientOptions.cacheTTLs = {\n default: this.options.cacheTTL,\n builds: this.options.cacheTTL,\n };\n }\n return restClientOptions;\n }\n }\n\n static get requiresToken(): boolean {\n return true;\n }\n \n protected async ensureInitialized(): Promise<void> {\n // No additional initialization needed\n return Promise.resolve();\n }\n\n protected handleError(error: any, debug: boolean = false): void {\n // Only log the error message and stack trace\n if (error instanceof Error) {\n logger.error(error, 'Error occurred');\n \n // If it's a GraphQL error or API error, show more details\n const apiError = error as ApiError;\n if (apiError.response?.errors) {\n apiError.response.errors.forEach((gqlError, index) => {\n logger.error({ path: gqlError.path }, `GraphQL Error ${index + 1}: ${gqlError.message}`);\n });\n }\n \n // Show request details if available and in debug mode\n if (debug && apiError.request) {\n logger.debug({ \n url: apiError.request.url,\n method: apiError.request.method \n }, 'Request Details');\n }\n } else if (typeof error === 'object') {\n logger.error({ error }, 'Unknown error occurred');\n } else {\n logger.error({ error }, 'Unknown error occurred');\n }\n \n if (debug) {\n logger.debug({ \n timestamp: new Date().toISOString(),\n nodeVersion: process.version,\n platform: `${process.platform} (${process.arch})`\n }, 'Debug Information');\n }\n }\n\n // Static helper to get token from options, keyring, or environment\n static async getToken(options: any): Promise<string | undefined> {\n // First check if token is provided directly in options\n if (options.token) {\n return options.token;\n }\n \n // Next try to get token from keyring\n try {\n const storedToken = await this.credentialManager.getToken();\n if (storedToken) {\n logger.debug('Using token from system keychain');\n return storedToken;\n }\n } catch (error) {\n logger.debug('Error retrieving token from keychain', error);\n }\n \n // Finally fall back to environment variable\n const envToken = process.env.BK_TOKEN;\n if (envToken) {\n return envToken;\n }\n \n if (options.requiresToken) {\n throw new Error('API token required. Set via --token, BK_TOKEN environment variable, or store it using --save-token.');\n } else {\n return\n }\n }\n\n /**\n * Get the appropriate formatter based on command-specific type and format option\n * @param type The formatter type ('pipeline', 'build', 'viewer')\n * @param options Command options that may include a format\n * @returns The appropriate formatter\n */\n protected getFormatter(type: FormatterType, options: BaseCommandOptions) {\n // Format precedence: command line option > constructor option > default\n const format = options.format || this.options.format || 'plain';\n if (options.debug) {\n logger.debug(`Using ${format} formatter for ${type}`);\n }\n return FormatterFactory.getFormatter(type, format);\n }\n\n /**\n * Execute the command with the given options\n * @param options Command options\n * @returns A promise that resolves to an exit code (0 for success, non-zero for errors)\n */\n abstract execute(options: BaseCommandOptions): Promise<number>;\n}"]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { BuildkiteClient } from '../services/BuildkiteClient.js';
|
|
11
|
+
export class BaseCommandHandler {
|
|
12
|
+
constructor(token, options) {
|
|
13
|
+
this.initialized = false;
|
|
14
|
+
this.token = token;
|
|
15
|
+
this.options = options || {};
|
|
16
|
+
if (options === null || options === void 0 ? void 0 : options.debug) {
|
|
17
|
+
console.log('Debug: BaseCommandHandler options:', JSON.stringify(options));
|
|
18
|
+
}
|
|
19
|
+
this.client = new BuildkiteClient(token);
|
|
20
|
+
this.initialized = true; // Client is initialized in constructor
|
|
21
|
+
}
|
|
22
|
+
ensureInitialized() {
|
|
23
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
// No additional initialization needed
|
|
25
|
+
return Promise.resolve();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
handleError(error, debug = false) {
|
|
29
|
+
var _a;
|
|
30
|
+
console.error('\x1b[31m%s\x1b[0m', '🔥 Error Details:');
|
|
31
|
+
if (error instanceof Error) {
|
|
32
|
+
console.error('\x1b[31m%s\x1b[0m', `Message: ${error.message}`);
|
|
33
|
+
// Always print the stack trace for proper debugging
|
|
34
|
+
if (error.stack) {
|
|
35
|
+
console.error('\x1b[33m%s\x1b[0m', 'Stack Trace:');
|
|
36
|
+
console.error('\x1b[33m%s\x1b[0m', error.stack);
|
|
37
|
+
}
|
|
38
|
+
// If it's a GraphQL error or API error, show more details
|
|
39
|
+
const apiError = error;
|
|
40
|
+
if ((_a = apiError.response) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
41
|
+
console.error('\x1b[33m%s\x1b[0m', 'GraphQL Errors:');
|
|
42
|
+
apiError.response.errors.forEach((gqlError, index) => {
|
|
43
|
+
console.error(` Error ${index + 1}: ${gqlError.message}`);
|
|
44
|
+
if (gqlError.path)
|
|
45
|
+
console.error(` Path: ${gqlError.path.join('.')}`);
|
|
46
|
+
if (gqlError.locations)
|
|
47
|
+
console.error(` Locations: ${JSON.stringify(gqlError.locations)}`);
|
|
48
|
+
console.error('');
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// Show request details if available and in debug mode
|
|
52
|
+
if (debug && apiError.request) {
|
|
53
|
+
console.error('\x1b[36m%s\x1b[0m', 'Request Details:');
|
|
54
|
+
console.error(` URL: ${apiError.request.url || 'N/A'}`);
|
|
55
|
+
console.error(` Method: ${apiError.request.method || 'N/A'}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else if (typeof error === 'object') {
|
|
59
|
+
console.error('\x1b[31m%s\x1b[0m', JSON.stringify(error, null, 2));
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.error('\x1b[31m%s\x1b[0m', 'An unknown error occurred:', error);
|
|
63
|
+
}
|
|
64
|
+
if (debug) {
|
|
65
|
+
console.error('\x1b[36m%s\x1b[0m', '\nDebug Information:');
|
|
66
|
+
console.error('\x1b[36m%s\x1b[0m', `⏰ Timestamp: ${new Date().toISOString()}`);
|
|
67
|
+
console.error('\x1b[36m%s\x1b[0m', `🔧 Node Version: ${process.version}`);
|
|
68
|
+
console.error('\x1b[36m%s\x1b[0m', `💻 Platform: ${process.platform} (${process.arch})`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Static helper to get token from options or environment
|
|
72
|
+
static getToken(options) {
|
|
73
|
+
const token = options.token || process.env.BK_TOKEN;
|
|
74
|
+
if (!token) {
|
|
75
|
+
throw new Error('API token required. Set via --token or BK_TOKEN environment variable.');
|
|
76
|
+
}
|
|
77
|
+
return token;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=BaseCommandHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseCommandHandler.js","sourceRoot":"/","sources":["commands/BaseCommandHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { BuildkiteClient } from '../services/BuildkiteClient.js';\n\nexport interface BaseCommandOptions {\n cacheTTL?: number;\n clearCache?: boolean;\n debug?: boolean;\n filter?: string;\n format?: string;\n noCache?: boolean;\n token?: string;\n}\n\n// Extended Error interface for API and GraphQL errors\ninterface ApiError extends Error {\n response?: {\n errors?: Array<{\n message: string;\n path?: string[];\n locations?: Array<{line: number; column: number}>;\n }>;\n };\n request?: {\n url?: string;\n method?: string;\n };\n}\n\nexport abstract class BaseCommandHandler {\n protected token: string;\n protected client: BuildkiteClient;\n protected options: Partial<BaseCommandOptions>;\n protected initialized: boolean = false;\n\n constructor(token: string, options?: Partial<BaseCommandOptions>) {\n this.token = token;\n this.options = options || {};\n if (options?.debug) {\n console.log('Debug: BaseCommandHandler options:', JSON.stringify(options));\n }\n this.client = new BuildkiteClient(token);\n this.initialized = true; // Client is initialized in constructor\n }\n\n protected async ensureInitialized(): Promise<void> {\n // No additional initialization needed\n return Promise.resolve();\n }\n\n protected handleError(error: any, debug: boolean = false): void {\n console.error('\\x1b[31m%s\\x1b[0m', '🔥 Error Details:');\n \n if (error instanceof Error) {\n console.error('\\x1b[31m%s\\x1b[0m', `Message: ${error.message}`);\n \n // Always print the stack trace for proper debugging\n if (error.stack) {\n console.error('\\x1b[33m%s\\x1b[0m', 'Stack Trace:');\n console.error('\\x1b[33m%s\\x1b[0m', error.stack);\n }\n \n // If it's a GraphQL error or API error, show more details\n const apiError = error as ApiError;\n if (apiError.response?.errors) {\n console.error('\\x1b[33m%s\\x1b[0m', 'GraphQL Errors:');\n apiError.response.errors.forEach((gqlError, index) => {\n console.error(` Error ${index + 1}: ${gqlError.message}`);\n if (gqlError.path) console.error(` Path: ${gqlError.path.join('.')}`);\n if (gqlError.locations) console.error(` Locations: ${JSON.stringify(gqlError.locations)}`);\n console.error('');\n });\n }\n \n // Show request details if available and in debug mode\n if (debug && apiError.request) {\n console.error('\\x1b[36m%s\\x1b[0m', 'Request Details:');\n console.error(` URL: ${apiError.request.url || 'N/A'}`);\n console.error(` Method: ${apiError.request.method || 'N/A'}`);\n }\n } else if (typeof error === 'object') {\n console.error('\\x1b[31m%s\\x1b[0m', JSON.stringify(error, null, 2));\n } else {\n console.error('\\x1b[31m%s\\x1b[0m', 'An unknown error occurred:', error);\n }\n \n if (debug) {\n console.error('\\x1b[36m%s\\x1b[0m', '\\nDebug Information:');\n console.error('\\x1b[36m%s\\x1b[0m', `⏰ Timestamp: ${new Date().toISOString()}`);\n console.error('\\x1b[36m%s\\x1b[0m', `🔧 Node Version: ${process.version}`);\n console.error('\\x1b[36m%s\\x1b[0m', `💻 Platform: ${process.platform} (${process.arch})`);\n }\n }\n\n // Static helper to get token from options or environment\n static getToken(options: any): string {\n const token = options.token || process.env.BK_TOKEN;\n if (!token) {\n throw new Error('API token required. Set via --token or BK_TOKEN environment variable.');\n }\n return token;\n }\n} "]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { BaseCommandHandler } from './BaseCommandHandler.js';
|
|
11
|
+
export class BuildCommandHandler extends BaseCommandHandler {
|
|
12
|
+
triggerBuild(options) {
|
|
13
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
14
|
+
try {
|
|
15
|
+
// Currently just logging, but would implement the actual API call
|
|
16
|
+
console.log('Triggering build with options:', options);
|
|
17
|
+
// Implementation would go here
|
|
18
|
+
// TODO: Implement build triggering logic using the Buildkite API
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
console.error('Error triggering build:');
|
|
22
|
+
this.handleError(error, options.debug);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=BuildCommandHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BuildCommandHandler.js","sourceRoot":"","sources":["../../src/commands/BuildCommandHandler.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAW7D,MAAM,OAAO,mBAAoB,SAAQ,kBAAkB;IACnD,YAAY,CAAC,OAAqB;;YACtC,IAAI,CAAC;gBACH,kEAAkE;gBAClE,OAAO,CAAC,GAAG,CAAC,gCAAgC,EAAE,OAAO,CAAC,CAAC;gBAEvD,+BAA+B;gBAC/B,iEAAiE;YAEnE,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;gBACzC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;gBACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;KAAA;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HelloCommandHandler.js","sourceRoot":"","sources":["../../src/commands/HelloCommandHandler.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,mBAAmB;IAC9B,OAAO;QACL,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACpC,CAAC;CACF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
export class ListAnnotations extends BaseCommand {
|
|
6
|
+
static requiresToken = true;
|
|
7
|
+
async execute(options) {
|
|
8
|
+
if (options.debug) {
|
|
9
|
+
logger.debug('Starting ListAnnotations command execution');
|
|
10
|
+
}
|
|
11
|
+
if (!options.buildArg) {
|
|
12
|
+
logger.error('Build reference is required');
|
|
13
|
+
return 1;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
// Ensure the command is initialized
|
|
17
|
+
await this.ensureInitialized();
|
|
18
|
+
const buildRef = parseBuildRef(options.buildArg);
|
|
19
|
+
if (options.debug) {
|
|
20
|
+
logger.debug('Parsed build reference:', buildRef);
|
|
21
|
+
}
|
|
22
|
+
// Fetch annotations from the GraphQL API
|
|
23
|
+
const buildSlug = `${buildRef.org}/${buildRef.pipeline}/${buildRef.number}`;
|
|
24
|
+
const result = await this.client.getBuildAnnotations(buildSlug);
|
|
25
|
+
// Extract annotations from the GraphQL response
|
|
26
|
+
let annotations = result.build?.annotations?.edges?.map((edge) => edge.node) || [];
|
|
27
|
+
// Filter by context if specified
|
|
28
|
+
if (options.context) {
|
|
29
|
+
const contextFilter = options.context.toLowerCase();
|
|
30
|
+
annotations = annotations.filter(annotation => annotation.context.toLowerCase() === contextFilter);
|
|
31
|
+
if (options.debug) {
|
|
32
|
+
logger.debug(`Filtered annotations by context '${options.context}': ${annotations.length} found`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Get the appropriate formatter
|
|
36
|
+
const formatter = FormatterFactory.getFormatter(FormatterType.ANNOTATION, options.format || 'plain'); // Cast to any since FormatterFactory returns BaseFormatter
|
|
37
|
+
// Format and output the results
|
|
38
|
+
const output = formatter.formatAnnotations(annotations, {
|
|
39
|
+
debug: options.debug,
|
|
40
|
+
contextFilter: options.context
|
|
41
|
+
});
|
|
42
|
+
logger.console(output);
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
logger.error('Failed to fetch annotations:', error);
|
|
47
|
+
// Handle the error with the formatter
|
|
48
|
+
const formatter = FormatterFactory.getFormatter(FormatterType.ANNOTATION, options.format || 'plain'); // Cast to any since FormatterFactory returns BaseFormatter
|
|
49
|
+
const errorOutput = formatter.formatAnnotations([], {
|
|
50
|
+
hasError: true,
|
|
51
|
+
errorMessage: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
52
|
+
errorType: 'api',
|
|
53
|
+
debug: options.debug
|
|
54
|
+
});
|
|
55
|
+
logger.console(errorOutput);
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=ListAnnotations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListAnnotations.js","sourceRoot":"/","sources":["commands/ListAnnotations.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseCommand } from './BaseCommand.js';\nimport { logger } from '../services/logger.js';\nimport { parseBuildRef } from '../utils/parseBuildRef.js';\nimport { FormatterFactory, FormatterType } from '../formatters/index.js';\nimport { Annotation } from '../types/index.js';\n\nexport class ListAnnotations extends BaseCommand {\n static requiresToken = true;\n\n async execute(options: any): Promise<number> {\n if (options.debug) {\n logger.debug('Starting ListAnnotations command execution');\n }\n \n \n if (!options.buildArg) {\n logger.error('Build reference is required');\n return 1;\n }\n \n try {\n // Ensure the command is initialized\n await this.ensureInitialized();\n \n const buildRef = parseBuildRef(options.buildArg);\n if (options.debug) {\n logger.debug('Parsed build reference:', buildRef);\n }\n \n // Fetch annotations from the GraphQL API\n const buildSlug = `${buildRef.org}/${buildRef.pipeline}/${buildRef.number}`;\n const result = await this.client.getBuildAnnotations(buildSlug);\n \n // Extract annotations from the GraphQL response\n let annotations: Annotation[] = result.build?.annotations?.edges?.map((edge: any) => edge.node) || [];\n \n // Filter by context if specified\n if (options.context) {\n const contextFilter = options.context.toLowerCase();\n annotations = annotations.filter(annotation => \n annotation.context.toLowerCase() === contextFilter\n );\n \n if (options.debug) {\n logger.debug(`Filtered annotations by context '${options.context}': ${annotations.length} found`);\n }\n }\n \n // Get the appropriate formatter\n const formatter = FormatterFactory.getFormatter(\n FormatterType.ANNOTATION,\n options.format || 'plain'\n ) as any; // Cast to any since FormatterFactory returns BaseFormatter\n \n // Format and output the results\n const output = formatter.formatAnnotations(annotations, {\n debug: options.debug,\n contextFilter: options.context\n });\n \n logger.console(output);\n \n return 0;\n } catch (error) {\n logger.error('Failed to fetch annotations:', error);\n \n // Handle the error with the formatter\n const formatter = FormatterFactory.getFormatter(\n FormatterType.ANNOTATION,\n options.format || 'plain'\n ) as any; // Cast to any since FormatterFactory returns BaseFormatter\n \n const errorOutput = formatter.formatAnnotations([], {\n hasError: true,\n errorMessage: error instanceof Error ? error.message : 'Unknown error occurred',\n errorType: 'api',\n debug: options.debug\n });\n \n logger.console(errorOutput);\n return 1;\n }\n }\n}\n"]}
|