Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions service/submitqueue/demo/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
load("@rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "go_default_library",
srcs = [
"demo.go",
"run.go",
"workload.go",
],
importpath = "github.com/uber/submitqueue/service/submitqueue/demo",
visibility = ["//visibility:public"],
deps = [
"//api/base/mergestrategy/protopb:go_default_library",
"//api/submitqueue/gateway/protopb:go_default_library",
"//submitqueue/client:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_x_sync//errgroup:go_default_library",
],
)

go_test(
name = "go_default_test",
srcs = [
"run_test.go",
"workload_test.go",
],
embed = [":go_default_library"],
deps = [
"//api/base/mergestrategy/protopb:go_default_library",
"//api/submitqueue/gateway/protopb:go_default_library",
"@com_github_stretchr_testify//assert:go_default_library",
"@com_github_stretchr_testify//require:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
],
)
17 changes: 17 additions & 0 deletions service/submitqueue/demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Demo workload runner

This package is the reusable part of the SubmitQueue demo. The OSS command in the sibling `requests` package and internal commands import `github.com/uber/submitqueue/service/submitqueue/demo`; deployment configuration, authentication, source construction, and connection ownership remain with those commands.

`Run` generates changes through a supplied source. `RunExisting` takes revisions already resolved by the caller and never invokes the source. Both return known changes, accepted request identifiers, and the last observed request histories, including on partial failure. A request identifier is opaque and must always be used with its queue.

Independent changes are created and submitted with bounded concurrency. Each can enter the queue as soon as it is ready. Burst mode prepares every change before submitting any request. Stacked mode creates a chain sequentially, prepares its members, and submits their ordered URIs as one request.

Sources own their base branch or snapshot. A stack link receives the preceding change's branch and head; a source must honor that parent or fail rather than silently retargeting it. The OSS providers retain their frozen-base behavior. A remote source that resolves a branch at creation time can use a moving base without promising identical commit ancestry across independent changes.

Readiness is optional and only runs when submission is enabled. A command can wait for real approvals or checks without baking that policy into the workload generator. Existing-change stack validation is the caller's responsibility.

The runner owns polling and interactive terminal cleanup. It waits for recorded histories rather than sampling only current status, preserving fast transitions and build metadata. Monitoring failures are not request failures: permanent errors stop the local watch without cancelling creation or submission and without inventing a terminal server state, and temporary failures retain the last known status and history.

Mutating source and submission calls are never retried automatically. A failing sibling stops new work from starting and cancels readiness waits, but never cancels a source or submission call already in flight. A timeout may hide a successful remote operation; inspect the reported artifacts before retrying. Stopping the command does not cancel submitted work, close PRs, or delete branches.

Workload layout is deterministic for a supplied `RunID`; an empty identifier receives a timestamp and random suffix so simultaneous runs do not collide. File/folder controls and the existing OSS command flags and Make targets are unchanged.
139 changes: 139 additions & 0 deletions service/submitqueue/demo/demo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// 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 demo generates and submits workloads with injected change sources
// and gateway transports. Deployment configuration and credentials belong to
// the calling command.
package demo

import (
"context"

mergestrategypb "github.com/uber/submitqueue/api/base/mergestrategy/protopb"
pb "github.com/uber/submitqueue/api/submitqueue/gateway/protopb"
)

// Options controls a workload, independently of its provider and transport.
type Options struct {
// Count is the number of changes to generate.
Count int
// Folders is the shard count; zero selects a reproducible count for the run.
Folders int
// Files is the minimum number of files per generated change.
Files int
// Concurrency bounds independent creation, readiness and submission.
Concurrency int
// Stacked submits an ordered chain as one request.
Stacked bool
// Burst prepares all independent changes before submitting any.
Burst bool
// Prefix is the generated branch namespace.
Prefix string
// RunID identifies a workload; empty generates a unique identifier.
RunID string
// Land enables submission; false only creates changes.
Land bool
// Watch waits for terminal request histories when Land is true.
Watch bool
// Queue is the exact queue accepting the requests.
Queue string
// Strategy is the wire strategy used for every submitted URI.
Strategy mergestrategypb.Strategy
}

// File is one generated file and its source-specific commit description.
type File struct {
// Path is relative to the repository root.
Path string
// Body is the complete file content.
Body string
// Message is the description when a provider commits files individually.
Message string
}

// Change is a head-pinned revision, or an attempted branch returned on failure.
type Change struct {
// Branch is the source branch.
Branch string
// HeadSHA is the full revision identifier, empty for an unconfirmed artifact.
HeadSHA string
// URI is the head-pinned identifier, empty for an unconfirmed artifact.
URI string
// Label identifies the change in terminal output.
Label string
// URL is an optional browser link.
URL string
}

// ChangeSpec describes a new change. Sources own their configured base.
type ChangeSpec struct {
// Branch is the branch to create.
Branch string
// Title describes the change.
Title string
// Files contains generated contents.
Files []File
// Parent identifies the preceding change when HasParent is true.
Parent Change
// HasParent distinguishes a stack link from a change on the source's base.
HasParent bool
// Note reports progress and may be called concurrently.
Note func(string, ...any)
}

// Source creates independent changes concurrently and stack links sequentially.
type Source interface {
Open(context.Context, ChangeSpec) (Change, error)
}

// Gateway is the transport-independent submission and history contract.
type Gateway interface {
Land(ctx context.Context, queue string, uris []string, strategy mergestrategypb.Strategy) (requestID string, err error)
History(ctx context.Context, queue, requestID string) ([]*pb.HistoryEvent, error)
}

// Readiness waits for an exact revision to be eligible for submission.
type Readiness interface {
Wait(context.Context, Change) error
}

// Dependencies supplies provider, transport and readiness integration.
type Dependencies struct {
// Source is required for generation, unused by RunExisting.
Source Source
// Gateway is required when Land is enabled.
Gateway Gateway
// Readiness is optional; nil means no preparation is required.
Readiness Readiness
}

// RequestResult records one accepted request and its observed history.
type RequestResult struct {
// Changes is the ordered set submitted in this request.
Changes []Change
// ID is opaque and only meaningful together with the run's queue.
ID string
// Status is the last observed server status, not a local monitoring verdict.
Status string
// History is the last successful history read.
History []*pb.HistoryEvent
}

// RunResult preserves known artifacts, including after a partially failed run.
type RunResult struct {
// Changes contains known artifacts in input order, including unconfirmed branches.
Changes []Change
// Requests contains accepted requests in workload order.
Requests []RequestResult
}
5 changes: 1 addition & 4 deletions service/submitqueue/demo/requests/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ go_library(
importpath = "github.com/uber/submitqueue/service/submitqueue/demo/requests",
visibility = ["//visibility:private"],
deps = [
"//api/base/mergestrategy/protopb:go_default_library",
"//platform/base/change/git:go_default_library",
"//platform/base/change/github:go_default_library",
"//platform/git/exec:go_default_library",
"//service/submitqueue/demo:go_default_library",
"//submitqueue/client:go_default_library",
"@org_golang_x_sync//errgroup:go_default_library",
],
)

Expand Down Expand Up @@ -45,11 +44,9 @@ go_test(
"SUBMITQUEUE_TEST_GIT": "$(location @git//:git)",
},
deps = [
"//api/base/mergestrategy/protopb:go_default_library",
"//platform/base/change/git:go_default_library",
"//platform/git/exec:go_default_library",
"//platform/git/exectest:go_default_library",
"//submitqueue/client:go_default_library",
"@com_github_stretchr_testify//assert:go_default_library",
"@com_github_stretchr_testify//require:go_default_library",
],
Expand Down
Loading
Loading