Skip to content

Commit bf095ca

Browse files
djuloori27claude
andcommitted
feat(extension): add metadata to Poll method and reorder BuildAction enum
Enhance BuildManager.Poll to return build metadata and reorder BuildAction constants for better semantic ordering. Changes to Poll method: - Add map[string]string return value for build metadata - Document common metadata keys (build_url, commit_sha, duration_ms, etc.) - Update interface signature: Poll(ctx, id) → (BuildStatus, map[string]string, error) - Update mocks and tests to handle metadata return value Changes to BuildAction enum: - Reorder constants: BuildActionApply now comes before BuildActionValidate - Apply is the primary action, validate is secondary - Update all tests and examples to reflect new ordering Documentation updates: - Add Build Metadata section explaining common keys - Update all Poll usage examples to show metadata handling - Update mock examples with metadata assertions - Clarify that metadata keys are implementation-defined The metadata map allows implementations to return provider-specific information (build URLs, commit SHAs, timestamps, etc.) without changing the interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 025cf2a commit bf095ca

6 files changed

Lines changed: 53 additions & 26 deletions

File tree

entity/build.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ type BuildAction string
6060
const (
6161
// BuildActionUnknown is the sentinel value for uninitialized actions.
6262
BuildActionUnknown BuildAction = ""
63-
// BuildActionValidate runs validation/testing on the change without applying it.
64-
BuildActionValidate BuildAction = "validate"
6563
// BuildActionApply applies the change to the target branch.
6664
BuildActionApply BuildAction = "apply"
65+
// BuildActionValidate runs validation/testing on the change without applying it.
66+
BuildActionValidate BuildAction = "validate"
6767
)
6868

6969
// BuildChange represents a code change to be processed by the build system.

entity/build_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,6 @@ func TestBuildChange_Creation(t *testing.T) {
5353
wantID string
5454
wantAction BuildAction
5555
}{
56-
{
57-
name: "validate action",
58-
change: BuildChange{
59-
ChangeID: "D12345",
60-
Action: BuildActionValidate,
61-
},
62-
wantID: "D12345",
63-
wantAction: BuildActionValidate,
64-
},
6556
{
6657
name: "apply action",
6758
change: BuildChange{
@@ -71,6 +62,15 @@ func TestBuildChange_Creation(t *testing.T) {
7162
wantID: "PR-42",
7263
wantAction: BuildActionApply,
7364
},
65+
{
66+
name: "validate action",
67+
change: BuildChange{
68+
ChangeID: "D12345",
69+
Action: BuildActionValidate,
70+
},
71+
wantID: "D12345",
72+
wantAction: BuildActionValidate,
73+
},
7474
{
7575
name: "unknown action",
7676
change: BuildChange{

extension/build/README.md

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type BuildManager interface {
2222
) (string, error)
2323

2424
// Poll retrieves the current status of a build from the CI provider
25-
Poll(ctx context.Context, id string) (entity.BuildStatus, error)
25+
Poll(ctx context.Context, id string) (entity.BuildStatus, map[string]string, error)
2626

2727
// CancelBuild requests cancellation of a build (asynchronous operation)
2828
CancelBuild(ctx context.Context, id string) error
@@ -60,8 +60,8 @@ type BuildAction string
6060

6161
const (
6262
BuildActionUnknown BuildAction = "" // Sentinel value
63-
BuildActionValidate BuildAction = "validate" // Run validation/testing without applying
6463
BuildActionApply BuildAction = "apply" // Apply the change to the target branch
64+
BuildActionValidate BuildAction = "validate" // Run validation/testing without applying
6565
)
6666
```
6767

@@ -105,6 +105,20 @@ func (s BuildStatus) IsTerminal() bool
105105

106106
**Build Lifecycle**: `accepted` → `passed`/`failed`/`cancelled`
107107

108+
### Build Metadata
109+
110+
The `Poll` method returns a `map[string]string` containing additional metadata about the build. The specific keys and values are implementation-defined, but common examples include:
111+
112+
**Common metadata keys:**
113+
- `build_url` - Direct link to the build in the CI provider's UI
114+
- `commit_sha` - Git commit SHA being tested
115+
- `duration_ms` - Build duration in milliseconds
116+
- `started_at` - Build start timestamp
117+
- `finished_at` - Build completion timestamp
118+
- `error_message` - Error details for failed builds
119+
120+
Implementations may include additional provider-specific metadata. Consumers should handle missing keys gracefully.
121+
108122
## Error Handling
109123

110124
The extension defines sentinel errors following the SubmitQueue pattern:
@@ -119,7 +133,7 @@ Each error has helper functions:
119133
120134
Example:
121135
```go
122-
status, err := buildMgr.Poll(ctx, buildID)
136+
status, metadata, err := buildMgr.Poll(ctx, buildID)
123137
if build.IsBuildNotFound(err) {
124138
// Handle missing build
125139
}
@@ -132,8 +146,8 @@ if build.IsBuildNotFound(err) {
132146
```go
133147
// 1. Schedule a build with changes
134148
changes := []entity.BuildChange{
135-
{ChangeID: "D12345", Action: entity.BuildActionValidate},
136-
{ChangeID: "D12346", Action: entity.BuildActionApply},
149+
{ChangeID: "D12345", Action: entity.BuildActionApply},
150+
{ChangeID: "D12346", Action: entity.BuildActionValidate},
137151
}
138152

139153
buildID, err := buildMgr.Schedule(ctx, "my-queue", changes)
@@ -142,11 +156,15 @@ if err != nil {
142156
}
143157

144158
// 2. Poll for build status
145-
status, err := buildMgr.Poll(ctx, buildID)
159+
status, metadata, err := buildMgr.Poll(ctx, buildID)
146160
if err != nil {
147161
// Handle error
148162
}
149163

164+
// Access build metadata
165+
buildURL := metadata["build_url"]
166+
commitSHA := metadata["commit_sha"]
167+
150168
// 3. Check if build is done
151169
if status.IsTerminal() {
152170
// Build finished: status is passed, failed, or cancelled
@@ -246,7 +264,7 @@ To add support for a new CI provider:
246264

247265
5. **Implement Schedule method**:
248266
- Look up job name from queue config using `queueName` parameter
249-
- Handle both `BuildActionValidate` and `BuildActionApply` actions
267+
- Handle both `BuildActionApply` and `BuildActionValidate` actions
250268
- Create appropriate builds/jobs for each change
251269
- Return unique build ID
252270

extension/build/build_manager.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ type BuildManager interface {
4444
//
4545
// Returns:
4646
// - BuildStatus: Current state of the build
47+
// - map[string]string: Additional metadata about the build (e.g., build URL, commit SHA, duration)
4748
// - error: ErrBuildNotFound if the build doesn't exist
48-
Poll(ctx context.Context, id string) (entity.BuildStatus, error)
49+
Poll(ctx context.Context, id string) (entity.BuildStatus, map[string]string, error)
4950

5051
// CancelBuild requests cancellation of a build.
5152
//

extension/build/mock/build_manager.go

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extension/build/mock/build_manager_test.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ func TestMockBuildManager_Compilation(t *testing.T) {
2323

2424
queueName := "test-queue"
2525
changes := []entity.BuildChange{
26-
{ChangeID: "D12345", Action: entity.BuildActionValidate},
27-
{ChangeID: "D12346", Action: entity.BuildActionApply},
26+
{ChangeID: "D12345", Action: entity.BuildActionApply},
27+
{ChangeID: "D12346", Action: entity.BuildActionValidate},
2828
}
2929

3030
buildID, err := mockBuildMgr.Schedule(
@@ -39,15 +39,22 @@ func TestMockBuildManager_Compilation(t *testing.T) {
3939
}
4040

4141
// Test Poll
42+
expectedMetadata := map[string]string{
43+
"build_url": "https://ci.example.com/builds/123",
44+
"commit_sha": "abc123",
45+
}
4246
mockBuildMgr.EXPECT().
4347
Poll(gomock.Any(), gomock.Any()).
44-
Return(entity.BuildStatusPassed, nil)
48+
Return(entity.BuildStatusPassed, expectedMetadata, nil)
4549

46-
status, err := mockBuildMgr.Poll(context.Background(), buildID)
50+
status, metadata, err := mockBuildMgr.Poll(context.Background(), buildID)
4751
if err != nil {
4852
t.Fatalf("unexpected error: %v", err)
4953
}
5054
if status != entity.BuildStatusPassed {
5155
t.Fatalf("expected %v, got %v", entity.BuildStatusPassed, status)
5256
}
57+
if metadata["build_url"] != expectedMetadata["build_url"] {
58+
t.Fatalf("expected metadata %v, got %v", expectedMetadata, metadata)
59+
}
5360
}

0 commit comments

Comments
 (0)