273 lines
6.8 KiB
Markdown
273 lines
6.8 KiB
Markdown
# Buildkite URL Parsing Reference
|
|
|
|
This document explains Buildkite URL formats and how to extract information from them.
|
|
|
|
## URL Formats
|
|
|
|
Buildkite uses several URL patterns for builds and jobs:
|
|
|
|
### Build URL (Most Common)
|
|
|
|
```
|
|
https://buildkite.com/{org}/{pipeline}/builds/{number}
|
|
```
|
|
|
|
Example:
|
|
|
|
```
|
|
https://buildkite.com/gusto/payroll-building-blocks/builds/29627
|
|
```
|
|
|
|
Extracting:
|
|
|
|
- `org`: "gusto"
|
|
- `pipeline`: "payroll-building-blocks"
|
|
- `number`: "29627"
|
|
|
|
### Step/Job URL (From Build Page)
|
|
|
|
```
|
|
https://buildkite.com/{org}/{pipeline}/builds/{number}/steps/{view}?sid={step-id}
|
|
```
|
|
|
|
Example:
|
|
|
|
```
|
|
https://buildkite.com/gusto/payroll-building-blocks/builds/29627/steps/canvas?sid=019a5f23-8109-4656-a033-bd62a82ca239
|
|
```
|
|
|
|
Extracting:
|
|
|
|
- `org`: "gusto"
|
|
- `pipeline`: "payroll-building-blocks"
|
|
- `number`: "29627"
|
|
- `view`: "canvas" (UI view type)
|
|
- `sid`: "019a5f23-8109-4656-a033-bd62a82ca239" (step ID)
|
|
|
|
**IMPORTANT**: The `sid` (step ID) is NOT the same as job UUID. See "Step IDs vs Job UUIDs" below.
|
|
|
|
### Job Detail URL
|
|
|
|
```
|
|
https://buildkite.com/{org}/{pipeline}/builds/{number}/jobs/{job-uuid}
|
|
```
|
|
|
|
Example:
|
|
|
|
```
|
|
https://buildkite.com/gusto/payroll-building-blocks/builds/29627/jobs/019a5f20-2d30-4c67-9edd-87fb92e1f487
|
|
```
|
|
|
|
Extracting:
|
|
|
|
- `org`: "gusto"
|
|
- `pipeline`: "payroll-building-blocks"
|
|
- `number`: "29627"
|
|
- `job-uuid`: "019a5f20-2d30-4c67-9edd-87fb92e1f487"
|
|
|
|
**NOTE**: This format contains the actual job UUID needed for log retrieval.
|
|
|
|
## Step IDs vs Job UUIDs
|
|
|
|
**Critical distinction**: Buildkite has two types of identifiers that are easily confused.
|
|
|
|
### Step IDs
|
|
|
|
- **Source**: Query parameter `sid` in step URLs
|
|
- **Format**: ULID format (e.g., `019a5f23-8109-4656-a033-bd62a82ca239`)
|
|
- **Purpose**: Frontend UI routing
|
|
- **Use**: Navigating to specific steps in web UI
|
|
- **API Usage**: ❌ NOT accepted by MCP tools
|
|
|
|
### Job UUIDs
|
|
|
|
- **Source**: `uuid` field in API responses
|
|
- **Format**: ULID format (e.g., `019a5f20-2d30-4c67-9edd-87fb92e1f487`)
|
|
- **Purpose**: Backend job identification
|
|
- **Use**: API calls to get logs, job details, etc.
|
|
- **API Usage**: ✅ Required by MCP `get_logs` tool
|
|
|
|
### Why the Confusion?
|
|
|
|
Both use ULID format (starts with `019a5f...`), but:
|
|
|
|
- Step IDs come from URLs → Web UI routing
|
|
- Job UUIDs come from API responses → Backend identification
|
|
|
|
**You cannot use a step ID for log retrieval.** Always get job UUID from `buildkite:get_build` API.
|
|
|
|
## Resolving Step ID to Job UUID
|
|
|
|
When given a step URL with `sid` parameter:
|
|
|
|
**Step 1: Extract build identifiers**
|
|
|
|
```javascript
|
|
// From: https://buildkite.com/gusto/payroll-building-blocks/builds/29627/steps/canvas?sid=019a5f23...
|
|
const org = 'gusto';
|
|
const pipeline = 'payroll-building-blocks';
|
|
const build = '29627';
|
|
// Ignore the sid parameter
|
|
```
|
|
|
|
**Step 2: Get job details from API**
|
|
|
|
```javascript
|
|
mcp__MCPProxy__call_tool('buildkite:get_build', {
|
|
org_slug: org,
|
|
pipeline_slug: pipeline,
|
|
build_number: build,
|
|
detail_level: 'detailed',
|
|
job_state: 'failed', // If investigating failures
|
|
});
|
|
```
|
|
|
|
**Step 3: Match job by properties**
|
|
|
|
The API response includes all jobs. Match by:
|
|
|
|
- `label` field (e.g., "ste rspec", "Rubocop")
|
|
- `state` field (e.g., "failed")
|
|
- `type` field (e.g., "script")
|
|
- `step_key` field if available
|
|
|
|
**Step 4: Extract job UUID**
|
|
|
|
```javascript
|
|
// From API response
|
|
const job = response.jobs.find(
|
|
(j) => j.label === 'ste rspec' && j.state === 'failed'
|
|
);
|
|
const jobUuid = job.uuid; // e.g., "019a5f20-2d30-4c67-9edd-87fb92e1f487"
|
|
```
|
|
|
|
**Step 5: Use job UUID for logs**
|
|
|
|
```javascript
|
|
mcp__MCPProxy__call_tool('buildkite:get_logs', {
|
|
org_slug: org,
|
|
pipeline_slug: pipeline,
|
|
build_number: build,
|
|
job_id: jobUuid, // NOT the step ID from URL
|
|
});
|
|
```
|
|
|
|
## Parsing Logic
|
|
|
|
### Simple Regex Approach
|
|
|
|
```javascript
|
|
function parseBuildkiteUrl(url) {
|
|
// Match build URL pattern
|
|
const buildMatch = url.match(
|
|
/buildkite\.com\/([^/]+)\/([^/]+)\/builds\/(\d+)/
|
|
);
|
|
|
|
if (!buildMatch) {
|
|
throw new Error('Invalid Buildkite URL');
|
|
}
|
|
|
|
return {
|
|
org: buildMatch[1],
|
|
pipeline: buildMatch[2],
|
|
buildNumber: buildMatch[3],
|
|
};
|
|
}
|
|
|
|
// Usage
|
|
const info = parseBuildkiteUrl(
|
|
'https://buildkite.com/gusto/payroll-building-blocks/builds/29627'
|
|
);
|
|
// => { org: "gusto", pipeline: "payroll-building-blocks", buildNumber: "29627" }
|
|
```
|
|
|
|
### Extracting Step ID (If Needed)
|
|
|
|
```javascript
|
|
function parseStepUrl(url) {
|
|
const base = parseBuildkiteUrl(url);
|
|
|
|
// Extract step ID from query parameter
|
|
const sidMatch = url.match(/[?&]sid=([^&]+)/);
|
|
|
|
return {
|
|
...base,
|
|
stepId: sidMatch ? sidMatch[1] : null,
|
|
};
|
|
}
|
|
|
|
// Usage
|
|
const info = parseStepUrl(
|
|
'https://buildkite.com/gusto/payroll-building-blocks/builds/29627/steps/canvas?sid=019a5f23...'
|
|
);
|
|
// => { org: "gusto", pipeline: "payroll-building-blocks", buildNumber: "29627", stepId: "019a5f23..." }
|
|
```
|
|
|
|
**Remember**: The `stepId` is useful for debugging but cannot be used for API calls. Always fetch job UUID from the API.
|
|
|
|
## Common URL Patterns in Practice
|
|
|
|
### Pattern 1: User Shares Failing Build URL
|
|
|
|
**URL**: `https://buildkite.com/org/pipeline/builds/123`
|
|
|
|
**Workflow**:
|
|
|
|
1. Extract org/pipeline/build
|
|
2. Call `get_build` with `detail_level: "summary"`
|
|
3. Check build state
|
|
4. If failed, call `get_build` with `detail_level: "detailed"` and `job_state: "failed"`
|
|
5. Get logs for each failed job
|
|
|
|
### Pattern 2: User Shares Step URL (Clicked on Specific Job)
|
|
|
|
**URL**: `https://buildkite.com/org/pipeline/builds/123/steps/canvas?sid=019a5f23...`
|
|
|
|
**Workflow**:
|
|
|
|
1. Extract org/pipeline/build (ignore `sid`)
|
|
2. Call `get_build` with `detail_level: "detailed"`
|
|
3. Find job matching user's intent (often the failed one)
|
|
4. Extract job UUID
|
|
5. Get logs for that job
|
|
|
|
The `sid` hints at which job the user was looking at, but you must resolve it via the API.
|
|
|
|
### Pattern 3: User Provides Job UUID Directly
|
|
|
|
**URL**: `https://buildkite.com/org/pipeline/builds/123/jobs/019a5f20-...`
|
|
|
|
**Workflow**:
|
|
|
|
1. Extract org/pipeline/build/job-uuid
|
|
2. Call `get_logs` directly with the job UUID
|
|
3. No resolution needed - this is the actual job UUID
|
|
|
|
This is the ideal format but least common in practice.
|
|
|
|
## Edge Cases
|
|
|
|
### Multiple Jobs with Same Label
|
|
|
|
Some pipelines parallelize jobs:
|
|
|
|
- "rspec (1/10)"
|
|
- "rspec (2/10)"
|
|
- "rspec (3/10)"
|
|
|
|
When resolving, match the full label string including the partition number.
|
|
|
|
### Dynamic Pipeline Steps
|
|
|
|
Some pipelines generate steps dynamically. The step structure may not be predictable from the URL alone. Always query the API to see actual job structure.
|
|
|
|
### Retried Jobs
|
|
|
|
When jobs are retried, multiple job UUIDs exist for the same step. The API returns the most recent attempt. Check `retries_count` and `retry_source` fields if investigating retry behavior.
|
|
|
|
## See Also
|
|
|
|
- [SKILL.md](../SKILL.md) - Main skill documentation
|
|
- [tool-capabilities.md](tool-capabilities.md) - Tool limitations and capabilities
|
|
- [troubleshooting.md](troubleshooting.md) - Common errors
|