Skip to content

Commit a1abecd

Browse files
committed
Add tag display in build details: fetch tags for commit SHA, show in build detail overlay
1 parent fc59dd0 commit a1abecd

5 files changed

Lines changed: 103 additions & 8 deletions

File tree

README.md

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -247,16 +247,76 @@ internal/
247247
- **Log fetching**: `?content=true` with raw text fallback + `Accept: text/plain`; script steps only
248248
- **Step types handled**: `script` (logs), `waiter` (hidden), `trigger`/`deploy` (metadata only)
249249
250-
## CI Pipeline
250+
## Dynamic Build Details (Tertiary Validation)
251251
252-
The project uses Buildkite for its own CI (`.buildkite/pipeline.yml`):
252+
builddeck enriches build details and artifacts with data from dedicated pipeline steps — not from Buildkite itself. These are **tertiary validations**: Buildkite doesn't validate them; our dedicated steps do.
253253
254-
1. **Lint & test** — `golangci-lint`, `go vet`, `go test`, `gosec`, `govulncheck`
255-
2. **Build** — `go build ./cmd/builddeck`
256-
3. **Checksum** — downloads binary, runs `sha256sum`, uploads `builddeck.sha256`
257-
4. **Release** — on tag push: builds multi-arch, creates GitHub Release, uploads binaries
254+
### Git Tag from Tag Step
258255
259-
Pipeline reads from default branch — changes must be on `main` before PR builds pass.
256+
The **Tag step** (`:bookmark: Tag`) in the pipeline:
257+
1. Runs after all validation passes
258+
2. Analyzes conventional commits since last tag
259+
3. Creates/pushes semver tag (e.g., `v0.1.1`)
260+
3. builddeck queries Buildkite API for tags on the build's commit SHA
261+
4. Displays the tag in build details under the commit hash
262+
263+
This is **not** Buildkite-managed — it's our step creating the tag, our TUI discovering it.
264+
265+
### Artifact Checksum from Checksum Step
266+
267+
The **Checksum step** (`:lock: Checksum`) in the pipeline:
268+
1. Downloads the binary artifact
269+
2. Runs `sha256sum` → produces `builddeck.sha256`
270+
3. Uploads `.sha256` as companion artifact
271+
4. builddeck detects `.sha256` artifacts, fetches them, parses the hash
272+
5. Displays checksum inline next to matching artifact
273+
274+
This is **tertiary validation** — Buildkite doesn't compute or verify checksums; our dedicated step and TUI do.
275+
276+
### Contract for Pipeline Authors
277+
278+
To enable these features, add these steps to your pipeline:
279+
280+
```yaml
281+
steps:
282+
# ... your validation steps ...
283+
284+
- label: ":bookmark: Tag"
285+
key: tag
286+
depends_on:
287+
- test
288+
- lint
289+
# ... all validation steps ...
290+
command: |
291+
# Auto-tag based on conventional commits
292+
VERSION=$(determine_version_from_commits)
293+
git tag -a "$VERSION" -m "Release $VERSION"
294+
git push origin "$VERSION"
295+
296+
- label: ":golang: Build and Release"
297+
key: build
298+
depends_on: tag
299+
command: |
300+
# Build binary
301+
# Query GitHub for tag on this commit SHA
302+
VERSION=$(gh api repos/:owner/:repo/git/refs/tags --jq '.[] | select(.object.sha == "'$BUILDKITE_COMMIT'") | .ref' | sed 's|refs/tags/||')
303+
go build -ldflags="-X main.version=$VERSION" ...
304+
305+
- label: ":lock: Checksum"
306+
key: checksum
307+
depends_on: build
308+
command: |
309+
buildkite-agent artifact download builddeck /tmp/
310+
sha256sum /tmp/builddeck | tee builddeck.sha256
311+
buildkite-agent artifact upload builddeck.sha256
312+
```
313+
314+
The **Tag** step runs after all validation (fan-in), creates the tag.
315+
The **Checksum** step runs after build, creates `.sha256` companion artifact.
316+
317+
builddeck automatically:
318+
- Queries tags for each build's commit SHA → shows in build details
319+
- Detects `.sha256` companion artifacts → shows checksum on artifacts
260320

261321
## Planned Next Features
262322

internal/buildkite/client.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,3 +419,22 @@ func ParseAgentQueue(agent Agent) string {
419419
}
420420
return "default"
421421
}
422+
423+
// GetTagsForCommit fetches tags pointing to a specific commit SHA
424+
func (c *Client) GetTagsForCommit(ctx context.Context, orgSlug, pipelineSlug, commitSHA string) ([]Tag, error) {
425+
path := fmt.Sprintf("/organizations/%s/pipelines/%s/builds/%s/tags", orgSlug, pipelineSlug, commitSHA)
426+
resp, err := c.get(ctx, path, nil)
427+
if err != nil {
428+
return nil, fmt.Errorf("getting tags for commit %s: %w", commitSHA, err)
429+
}
430+
var tags []Tag
431+
if err := json.Unmarshal(resp.Body, &tags); err != nil {
432+
return nil, fmt.Errorf("decoding tags for commit %s: %w", commitSHA, err)
433+
}
434+
return tags, nil
435+
}
436+
437+
// ListTagsForCommit fetches tags for a commit (alias for GetTagsForCommit)
438+
func (c *Client) ListTagsForCommit(ctx context.Context, orgSlug, pipelineSlug, commitSHA string) ([]Tag, error) {
439+
return c.GetTagsForCommit(ctx, orgSlug, pipelineSlug, commitSHA)
440+
}

internal/buildkite/types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,8 @@ type EmojiEntry struct {
108108
Name string `json:"name"`
109109
URL string `json:"url"`
110110
}
111+
112+
type Tag struct {
113+
Name string `json:"name"`
114+
Commit string `json:"commit"`
115+
}

internal/tui/model.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,15 @@ func loadBuildsCmd(client *buildkite.Client, orgSlug, pipelineSlug string) tea.C
275275
func loadBuildDetailCmd(client *buildkite.Client, orgSlug, pipelineSlug string, buildID string, buildNumber int) tea.Cmd {
276276
return func() tea.Msg {
277277
build, err := client.GetBuild(context.Background(), orgSlug, pipelineSlug, buildNumber)
278-
return buildDetailMsg{buildID: buildID, build: build, err: err}
278+
if err != nil {
279+
return buildDetailMsg{buildID: buildID, build: build, err: err}
280+
}
281+
// Fetch tags for this build's commit
282+
tags, _ := client.ListTagsForCommit(context.Background(), orgSlug, pipelineSlug, build.Commit)
283+
if len(tags) > 0 {
284+
build.Tag = tags[0].Name // Use first (most recent) tag
285+
}
286+
return buildDetailMsg{buildID: buildID, build: build, err: nil}
279287
}
280288
}
281289

internal/tui/views.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,9 @@ func (m Model) statsOverlay(base string) string {
11251125
b.WriteString(fmt.Sprintf(" State: %s\n", bd.State))
11261126
b.WriteString(fmt.Sprintf(" Branch: %s\n", bd.Branch))
11271127
b.WriteString(fmt.Sprintf(" Commit: %s\n", shortSHA(bd.Commit)))
1128+
if bd.Tag != "" {
1129+
b.WriteString(fmt.Sprintf(" Tag: %s\n", bd.Tag))
1130+
}
11281131
msg := renderEmoji(strings.SplitN(bd.Message, "\n", 2)[0])
11291132
b.WriteString(fmt.Sprintf(" Message: %s\n", msg))
11301133
if bd.Creator != nil {

0 commit comments

Comments
 (0)