Files
2025-11-30 09:00:26 +08:00

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