From a399104236c99d5653bbe27d456562c6501c73b3 Mon Sep 17 00:00:00 2001 From: manjari Date: Thu, 1 Oct 2026 23:07:29 +0000 Subject: [PATCH 1/3] feat(platform): Add gitworkspace extension for pluggable git command execution --- platform/extension/gitworkspace/BUILD.bazel | 8 ++ .../extension/gitworkspace/gitworkspace.go | 64 +++++++++++ .../extension/gitworkspace/mock/BUILD.bazel | 12 ++ .../gitworkspace/mock/gitworkspace_mock.go | 103 ++++++++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 platform/extension/gitworkspace/BUILD.bazel create mode 100644 platform/extension/gitworkspace/gitworkspace.go create mode 100644 platform/extension/gitworkspace/mock/BUILD.bazel create mode 100644 platform/extension/gitworkspace/mock/gitworkspace_mock.go diff --git a/platform/extension/gitworkspace/BUILD.bazel b/platform/extension/gitworkspace/BUILD.bazel new file mode 100644 index 00000000..c68827bd --- /dev/null +++ b/platform/extension/gitworkspace/BUILD.bazel @@ -0,0 +1,8 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["gitworkspace.go"], + importpath = "github.com/uber/submitqueue/platform/extension/gitworkspace", + visibility = ["//visibility:public"], +) diff --git a/platform/extension/gitworkspace/gitworkspace.go b/platform/extension/gitworkspace/gitworkspace.go new file mode 100644 index 00000000..c9c22dfd --- /dev/null +++ b/platform/extension/gitworkspace/gitworkspace.go @@ -0,0 +1,64 @@ +// Copyright (c) 2026 Uber Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package gitworkspace defines the pluggable interface for executing git +// commands in a stateful workspace. The OSS implementation runs commands as +// local subprocesses; alternative deployments wrap their backend's exec API +// in the same contract. +package gitworkspace + +//go:generate mockgen -source=gitworkspace.go -destination=mock/gitworkspace_mock.go -package=mock + +import "context" + +// Command is one command to execute in a git workspace. +type Command struct { + // Alias identifies this command's Output in the response. + Alias string + // Bin is the executable name. + Bin string + // Args are the command-line arguments. + Args []string + // Stdin is optional standard input. + Stdin string +} + +// Output is the result of one executed command. +type Output struct { + // Alias matches the Command that produced this output. + Alias string + // ExitCode is the process exit code (0 = success, -1 = skipped). + ExitCode int32 + // Stdout is the captured standard output. + Stdout string + // Stderr is the captured standard error. + Stderr string +} + +// Workspace is a stateful git environment where command batches execute +// sequentially. Commands within one Exec call run in order; a non-zero +// exit code skips the remaining commands in that batch. State persists +// across Exec calls on the same Workspace. +type Workspace interface { + // Exec sends a batch of commands and returns their outputs. + Exec(commands []Command) ([]Output, error) + // Close releases the workspace and its resources. + Close() error +} + +// Factory creates Workspace instances bound to a repository. +type Factory interface { + // For returns a Workspace for the given repository. + For(ctx context.Context, repo string) (Workspace, error) +} diff --git a/platform/extension/gitworkspace/mock/BUILD.bazel b/platform/extension/gitworkspace/mock/BUILD.bazel new file mode 100644 index 00000000..63947216 --- /dev/null +++ b/platform/extension/gitworkspace/mock/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["gitworkspace_mock.go"], + importpath = "github.com/uber/submitqueue/platform/extension/gitworkspace/mock", + visibility = ["//visibility:public"], + deps = [ + "//platform/extension/gitworkspace:go_default_library", + "@com_github_golang_mock//gomock:go_default_library", + ], +) diff --git a/platform/extension/gitworkspace/mock/gitworkspace_mock.go b/platform/extension/gitworkspace/mock/gitworkspace_mock.go new file mode 100644 index 00000000..03626bf7 --- /dev/null +++ b/platform/extension/gitworkspace/mock/gitworkspace_mock.go @@ -0,0 +1,103 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: gitworkspace.go + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + gitworkspace "github.com/uber/submitqueue/platform/extension/gitworkspace" +) + +// MockWorkspace is a mock of Workspace interface. +type MockWorkspace struct { + ctrl *gomock.Controller + recorder *MockWorkspaceMockRecorder +} + +// MockWorkspaceMockRecorder is the mock recorder for MockWorkspace. +type MockWorkspaceMockRecorder struct { + mock *MockWorkspace +} + +// NewMockWorkspace creates a new mock instance. +func NewMockWorkspace(ctrl *gomock.Controller) *MockWorkspace { + mock := &MockWorkspace{ctrl: ctrl} + mock.recorder = &MockWorkspaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockWorkspace) EXPECT() *MockWorkspaceMockRecorder { + return m.recorder +} + +// Close mocks base method. +func (m *MockWorkspace) Close() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Close") + ret0, _ := ret[0].(error) + return ret0 +} + +// Close indicates an expected call of Close. +func (mr *MockWorkspaceMockRecorder) Close() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockWorkspace)(nil).Close)) +} + +// Exec mocks base method. +func (m *MockWorkspace) Exec(commands []gitworkspace.Command) ([]gitworkspace.Output, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Exec", commands) + ret0, _ := ret[0].([]gitworkspace.Output) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Exec indicates an expected call of Exec. +func (mr *MockWorkspaceMockRecorder) Exec(commands interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exec", reflect.TypeOf((*MockWorkspace)(nil).Exec), commands) +} + +// MockFactory is a mock of Factory interface. +type MockFactory struct { + ctrl *gomock.Controller + recorder *MockFactoryMockRecorder +} + +// MockFactoryMockRecorder is the mock recorder for MockFactory. +type MockFactoryMockRecorder struct { + mock *MockFactory +} + +// NewMockFactory creates a new mock instance. +func NewMockFactory(ctrl *gomock.Controller) *MockFactory { + mock := &MockFactory{ctrl: ctrl} + mock.recorder = &MockFactoryMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockFactory) EXPECT() *MockFactoryMockRecorder { + return m.recorder +} + +// For mocks base method. +func (m *MockFactory) For(ctx context.Context, repo string) (gitworkspace.Workspace, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "For", ctx, repo) + ret0, _ := ret[0].(gitworkspace.Workspace) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// For indicates an expected call of For. +func (mr *MockFactoryMockRecorder) For(ctx, repo interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "For", reflect.TypeOf((*MockFactory)(nil).For), ctx, repo) +} From 06f706cefd2bc6d35ac868a39224a7eb4c35055f Mon Sep 17 00:00:00 2001 From: manjari Date: Thu, 1 Oct 2026 23:25:17 +0000 Subject: [PATCH 2/3] fix(platform): use go.uber.org/mock import in gitworkspace mock --- platform/extension/gitworkspace/mock/BUILD.bazel | 2 +- platform/extension/gitworkspace/mock/gitworkspace_mock.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/extension/gitworkspace/mock/BUILD.bazel b/platform/extension/gitworkspace/mock/BUILD.bazel index 63947216..5d768ea4 100644 --- a/platform/extension/gitworkspace/mock/BUILD.bazel +++ b/platform/extension/gitworkspace/mock/BUILD.bazel @@ -7,6 +7,6 @@ go_library( visibility = ["//visibility:public"], deps = [ "//platform/extension/gitworkspace:go_default_library", - "@com_github_golang_mock//gomock:go_default_library", + "@org_uber_go_mock//gomock:go_default_library", ], ) diff --git a/platform/extension/gitworkspace/mock/gitworkspace_mock.go b/platform/extension/gitworkspace/mock/gitworkspace_mock.go index 03626bf7..b7a0f2fb 100644 --- a/platform/extension/gitworkspace/mock/gitworkspace_mock.go +++ b/platform/extension/gitworkspace/mock/gitworkspace_mock.go @@ -8,7 +8,7 @@ import ( context "context" reflect "reflect" - gomock "github.com/golang/mock/gomock" + gomock "go.uber.org/mock/gomock" gitworkspace "github.com/uber/submitqueue/platform/extension/gitworkspace" ) From a0ca51084eb8f49815a6fcbf33a1168fb8b86b60 Mon Sep 17 00:00:00 2001 From: manjari Date: Thu, 1 Oct 2026 23:32:25 +0000 Subject: [PATCH 3/3] fix(platform): format gitworkspace mock imports --- platform/extension/gitworkspace/mock/gitworkspace_mock.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/extension/gitworkspace/mock/gitworkspace_mock.go b/platform/extension/gitworkspace/mock/gitworkspace_mock.go index b7a0f2fb..c2617943 100644 --- a/platform/extension/gitworkspace/mock/gitworkspace_mock.go +++ b/platform/extension/gitworkspace/mock/gitworkspace_mock.go @@ -8,8 +8,8 @@ import ( context "context" reflect "reflect" - gomock "go.uber.org/mock/gomock" gitworkspace "github.com/uber/submitqueue/platform/extension/gitworkspace" + gomock "go.uber.org/mock/gomock" ) // MockWorkspace is a mock of Workspace interface.