Skip to content

Commit fae9097

Browse files
authored
feat(stovepipe): define the repair executor extension (#929)
## Why? Add a RepairExecutor contract. For now, we have a Submit method, but this contract could expand to include other functionality such as inspecting the status of a submitted request. Internally, we'll use this to submit a fix when detected. ## What? - Add `fixer.RepairExecutor.Submit(context.Context, entity.OpenIssue) (string, error)`. - Add queue configuration, the factory interface, generated GoMock mocks, and Bazel targets. - Document that a nonempty attempt ID means submission was accepted. Errors may follow acceptance, so callers must avoid automatic resubmission. Follow-up layers will add first-failure selection, submission/history handling, and build-analysis trigger wiring. ## Test Plan - Regenerate mocks and Bazel files with `make mocks gazelle`. - Run `make fmt lint check-tidy check-gazelle`. - Compile `//stovepipe/extension/fixer:go_default_library` and `//stovepipe/extension/fixer/mock:go_default_library`. ## Revert Plan Revert this change.
1 parent 6f66ecf commit fae9097

6 files changed

Lines changed: 174 additions & 0 deletions

File tree

‎Makefile‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ GO_GENERATE_PACKAGES := \
629629
./stovepipe/core/requestlog/... \
630630
./stovepipe/extension/buildissue/... \
631631
./stovepipe/extension/buildrunner/... \
632+
./stovepipe/extension/fixer/... \
632633
./stovepipe/extension/projectstatus/... \
633634
./stovepipe/extension/queueconfig/... \
634635
./stovepipe/extension/sourcecontrol/... \
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
load("@rules_go//go:def.bzl", "go_library")
2+
3+
go_library(
4+
name = "go_default_library",
5+
srcs = ["fixer.go"],
6+
importpath = "github.com/uber/submitqueue/stovepipe/extension/fixer",
7+
visibility = ["//visibility:public"],
8+
deps = ["//stovepipe/entity:go_default_library"],
9+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Repair execution
2+
3+
[`RepairExecutor`](fixer.go) submits repair work for one [`OpenIssue`](../../entity/open_issue.go). The executor can invoke an in-process implementation or wrap an external provider.
4+
5+
`Submit` returns promptly with a nonempty opaque provider attempt ID on acceptance, or an error. Acceptance does not establish recovery.
6+
7+
An error, including a timeout or cancellation, can occur after the provider accepted the work, so it must not cause an automatic resubmission. Implementations return plain dependency errors and must support concurrent calls.
8+
9+
`Factory.For` resolves an executor bound to `Config.QueueName`. Generated mocks are available in [`mock`](mock/fixer_mock.go).

‎stovepipe/extension/fixer/fixer.go‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) 2026 Uber Technologies, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Package fixer defines repair submission for an open issue.
16+
package fixer
17+
18+
//go:generate mockgen -source=fixer.go -destination=mock/fixer_mock.go -package=mock
19+
20+
import (
21+
"context"
22+
23+
"github.com/uber/submitqueue/stovepipe/entity"
24+
)
25+
26+
// RepairExecutor submits repair work for one open issue within a configured queue.
27+
// Implementations must be concurrency-safe and return promptly after submission.
28+
type RepairExecutor interface {
29+
// Submit returns a nonempty opaque provider attempt ID on acceptance.
30+
// Acceptance does not establish recovery.
31+
// Repeated calls may start additional attempts. A plain error can follow acceptance,
32+
// including on context cancellation; callers must not automatically repeat Submit.
33+
Submit(context.Context, entity.OpenIssue) (string, error)
34+
}
35+
36+
// Config identifies the queue whose repair executor is requested.
37+
type Config struct {
38+
// QueueName identifies the validation queue.
39+
QueueName string
40+
}
41+
42+
// Factory resolves queue-bound executors; routing belongs to service wiring.
43+
type Factory interface {
44+
For(Config) (RepairExecutor, error)
45+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
load("@rules_go//go:def.bzl", "go_library")
2+
3+
go_library(
4+
name = "go_default_library",
5+
srcs = ["fixer_mock.go"],
6+
importpath = "github.com/uber/submitqueue/stovepipe/extension/fixer/mock",
7+
visibility = ["//visibility:public"],
8+
deps = [
9+
"//stovepipe/entity:go_default_library",
10+
"//stovepipe/extension/fixer:go_default_library",
11+
"@org_uber_go_mock//gomock:go_default_library",
12+
],
13+
)

‎stovepipe/extension/fixer/mock/fixer_mock.go‎

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

0 commit comments

Comments
 (0)