Skip to content
Open
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
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ define assert_clean
fi
endef

.PHONY: build build-all-linux build-runway-linux build-submitqueue-gateway-client build-submitqueue-gateway-linux build-submitqueue-gateway-server build-submitqueue-orchestrator-linux build-stovepipe-linux build-stovepipe-linux-debug check-gazelle check-mocks check-tidy clean clean-proto demo-requests deps docs-build docs-serve e2e-test fmt gazelle integration-test integration-test-submitqueue-consumer integration-test-extensions integration-test-submitqueue-gateway integration-test-submitqueue-orchestrator integration-test-submitqueue-validator license-fix lint lint-binary lint-fmt lint-license local-init-runway-queue-schema local-init-stovepipe-schemas local-runway-start local-runway-stop local-submitqueue-stop local-submitqueue-clean local-submitqueue-gateway-start local-submitqueue-gateway-stop local-init-submitqueue-schemas local-submitqueue-logs local-submitqueue-orchestrator-start local-submitqueue-orchestrator-stop local-submitqueue-ps local-submitqueue-restart local-submitqueue-start local-stop local-stovepipe-debug-start local-stovepipe-logs local-stovepipe-start local-stovepipe-stop mocks proto query-deps query-targets run-client-runway run-client-submitqueue-gateway run-client-submitqueue-orchestrator run-client-stovepipe run-queue-admin test test-no-cache test-race tidy tidy-bazel tidy-go web-build web-check web-e2e-test web-image-load web-install web-proto help
.PHONY: build build-all-linux build-runway-linux build-submitqueue-gateway-client build-submitqueue-gateway-linux build-submitqueue-gateway-server build-submitqueue-orchestrator-linux build-stovepipe-linux build-stovepipe-linux-debug build-tangofake-linux check-gazelle check-mocks check-tidy clean clean-proto demo-requests deps docs-build docs-serve e2e-test fmt gazelle integration-test integration-test-submitqueue-consumer integration-test-extensions integration-test-submitqueue-gateway integration-test-submitqueue-orchestrator integration-test-submitqueue-validator license-fix lint lint-binary lint-fmt lint-license local-init-runway-queue-schema local-init-stovepipe-schemas local-runway-start local-runway-stop local-submitqueue-stop local-submitqueue-clean local-submitqueue-gateway-start local-submitqueue-gateway-stop local-init-submitqueue-schemas local-submitqueue-logs local-submitqueue-orchestrator-start local-submitqueue-orchestrator-stop local-submitqueue-ps local-submitqueue-restart local-submitqueue-start local-stop local-stovepipe-debug-start local-stovepipe-logs local-stovepipe-start local-stovepipe-stop mocks proto query-deps query-targets run-client-runway run-client-submitqueue-gateway run-client-submitqueue-orchestrator run-client-stovepipe run-queue-admin test test-no-cache test-race tidy tidy-bazel tidy-go web-build web-check web-e2e-test web-image-load web-install web-proto help


build: ## Build all services and examples
Expand Down Expand Up @@ -224,6 +224,14 @@ build-stovepipe-linux-debug: ## Build Stovepipe Linux debug binary for Docker/de
cp -f bazel-bin/service/stovepipe/server/stovepipe .docker-bin/stovepipe-debug
@echo "Stovepipe Linux debug binary ready at .docker-bin/stovepipe-debug"

build-tangofake-linux: ## Build the fake Tango server's Linux binary for Docker
@echo "Building the fake Tango server Linux binary for Docker..."
@$(BAZEL) build --platforms=@rules_go//go/toolchain:linux_amd64 //service/tangofake/server:server
@mkdir -p .docker-bin
@cp -f bazel-bin/service/tangofake/server/server_/server .docker-bin/tangofake 2>/dev/null || \
cp -f bazel-bin/service/tangofake/server/server .docker-bin/tangofake
@echo "Fake Tango server Linux binary ready at .docker-bin/tangofake"

check-gazelle: ## Check BUILD.bazel files are up to date
@echo "Running Gazelle to check BUILD files..."
@$(BAZEL) run //:gazelle
Expand Down
10 changes: 7 additions & 3 deletions service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Each domain has its own subdirectory with a dedicated README:
- [`submitqueue/`](submitqueue/README.md) — the multi-service SubmitQueue domain (Gateway + Orchestrator).
- [`stovepipe/`](stovepipe/README.md) — the single-service Stovepipe domain (ingest → process → build → buildsignal → record).
- [`runway/`](runway/README.md) — the single-service Runway merge execution service.
- [`tangofake/`](tangofake/README.md) — a fake Tango server for running the Tango conflict analyzer without a build system.

## Services

Expand All @@ -16,6 +17,7 @@ Each domain has its own subdirectory with a dedicated README:
| **SubmitQueue Orchestrator** | 8082 | `submitqueue` | `Ping` (+ consumes start, cancel, validate, merge-conflict-check-signal, batch, dependency-analysis, speculate, build, buildsignal, submitqueue-land, merge-signal, conclude, submitqueue-hook, and paired DLQ topics) | MySQL app + queue |
| **Stovepipe** | 8083 | `stovepipe` | `Ping`, `Ingest` (+ consumes process, build, buildsignal, record, stovepipe-hook, and paired DLQ topics) | MySQL storage + queue |
| **Runway** | 8086 | `runway` | `Ping` (+ consumes merge-conflict-check & runway-merge topics) | MySQL queue |
| **Fake Tango** | free port, logged | none | Tango's `GetChangedTargets` | a git repository of `TARGET` files |

Ports above are the `go run` defaults; under Docker Compose each server listens on `:8080` inside its container and is published on a random ephemeral host port. `make local-submitqueue-ps` is the only status target, and it prints the SubmitQueue mappings. `make local-stovepipe-start` and `make local-runway-start` print their ports when those stacks come up.

Expand All @@ -37,9 +39,11 @@ service/
│ ├── docker-compose.debug.yml # Debug variant with delve
│ ├── server/ # Stovepipe gRPC server + Dockerfile + compose
│ └── client/ # Stovepipe ping client
└── runway/
├── server/ # Runway gRPC server + Dockerfile + compose
└── client/ # Runway ping client
├── runway/
│ ├── server/ # Runway gRPC server + Dockerfile + compose
│ └── client/ # Runway ping client
└── tangofake/
└── server/ # Fake Tango gRPC server + Dockerfile + compose
```

## Running
Expand Down
37 changes: 37 additions & 0 deletions service/tangofake/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
load("@rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "go_default_library",
srcs = ["tangofake.go"],
importpath = "github.com/uber/submitqueue/service/tangofake",
visibility = [
"//service/tangofake:__subpackages__",
"//test:__subpackages__",
],
deps = [
"//platform/extension/gitworkspace:go_default_library",
"@com_github_uber_tango//tangopb:go_default_library",
],
)

go_test(
name = "go_default_test",
srcs = ["tangofake_test.go"],
# The pinned git, for building the repositories the tests read.
data = ["@git"],
embed = [":go_default_library"],
env = {
"SUBMITQUEUE_TEST_GIT": "$(location @git//:git)",
},
deps = [
"//platform/extension/gitworkspace/local:go_default_library",
"//platform/git/exectest:go_default_library",
"//submitqueue/extension/conflict/tango:go_default_library",
"//submitqueue/extension/conflict/tango/tangoclient:go_default_library",
"@com_github_stretchr_testify//assert:go_default_library",
"@com_github_stretchr_testify//require:go_default_library",
"@com_github_uber_tango//tangopb:go_default_library",
"@org_uber_go_yarpc//:go_default_library",
"@org_uber_go_yarpc//transport/grpc:go_default_library",
],
)
14 changes: 14 additions & 0 deletions service/tangofake/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Fake Tango server

A runnable stand-in for a Tango server, for running the SubmitQueue Tango conflict analyzer without a build system. It serves Tango's real gRPC protocol and derives the changed targets from `TARGET` files in a git repository, so the analyzer exercises the same client path it uses against a real Tango. The target-file format and how a change maps to targets are described in the package doc of [`tangofake.go`](tangofake.go).

## Running it

It runs as a container like the other services here. Build the Linux binary with `make build-tangofake-linux`, then bring it up with [`server/docker-compose.yml`](server/docker-compose.yml), pointing `SQ_TANGOFAKE_REPO_DIR` at a git repository that holds the `TARGET` files. The server listens on port 8080 in the container.

Outside a container, `bazel run //service/tangofake/server -- -repo <path>` serves the same repository on a free port, which it logs.

## Flags

- `-repo` is the path to the git repository holding the `TARGET` files. It is required, and the repository must contain every commit a change URI names.
- `-address` is the gRPC listen address and defaults to `127.0.0.1:0`.
21 changes: 21 additions & 0 deletions service/tangofake/server/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
load("@rules_go//go:def.bzl", "go_binary", "go_library")

go_library(
name = "go_default_library",
srcs = ["main.go"],
importpath = "github.com/uber/submitqueue/service/tangofake/server",
visibility = ["//visibility:private"],
deps = [
"//platform/extension/gitworkspace/local:go_default_library",
"//service/tangofake:go_default_library",
"@com_github_uber_tango//tangopb:go_default_library",
"@org_uber_go_yarpc//:go_default_library",
"@org_uber_go_yarpc//transport/grpc:go_default_library",
],
)

go_binary(
name = "server",
embed = [":go_default_library"],
visibility = ["//visibility:public"],
)
15 changes: 15 additions & 0 deletions service/tangofake/server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM debian:bookworm-slim

# git is a runtime dependency: the fake reads targets out of a repository by
# running it.
RUN apt-get update && apt-get install -y ca-certificates git && rm -rf /var/lib/apt/lists/* \
&& mkdir -p /app && chmod 0755 /app
WORKDIR /app

# Built via: make build-tangofake-linux
COPY .docker-bin/tangofake ./tangofake
RUN chmod 0555 ./tangofake

EXPOSE 8080

CMD ["/app/tangofake"]
21 changes: 21 additions & 0 deletions service/tangofake/server/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Docker Compose for the fake Tango server on its own.
#
# IMPORTANT: Before running compose, build the Linux binary:
# make build-tangofake-linux
#
# Quick start, pointing it at a git repository that holds TARGET files:
# SQ_TANGOFAKE_REPO_DIR=/path/to/repo REPO_ROOT=$PWD \
# docker compose -f service/tangofake/server/docker-compose.yml up --build

services:
tangofake-service:
image: ${SQ_DOCKER_IMAGE_PREFIX:-submitqueue}-tangofake-service:latest
build:
context: ${REPO_ROOT}
dockerfile: service/tangofake/server/Dockerfile
user: "${SQ_CONTAINER_USER:-0:0}"
command: ["/app/tangofake", "-repo", "/var/tangofake/repo", "-address", "0.0.0.0:8080"]
ports:
- "8080" # Random ephemeral port to avoid conflicts
volumes:
- ${SQ_TANGOFAKE_REPO_DIR:?set SQ_TANGOFAKE_REPO_DIR to the repository holding the TARGET files}:/var/tangofake/repo:ro
74 changes: 74 additions & 0 deletions service/tangofake/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// 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.

// Command server serves a Tango server over gRPC that derives changed
// targets from the TARGET files of a git repository (see package tangofake),
// for running the SubmitQueue demo without a build system.
package main

import (
"flag"
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"

"github.com/uber/tango/tangopb"
"go.uber.org/yarpc"
"go.uber.org/yarpc/transport/grpc"

"github.com/uber/submitqueue/platform/extension/gitworkspace/local"
"github.com/uber/submitqueue/service/tangofake"
)

func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}

func run() error {
repo := flag.String("repo", "", "path to the git repository holding the TARGET files")
address := flag.String("address", "127.0.0.1:0", "address to listen on for gRPC; port 0 picks a free port, which is logged")
flag.Parse()
if *repo == "" {
return fmt.Errorf("-repo is required")
}

listener, err := net.Listen("tcp", *address)
if err != nil {
return fmt.Errorf("failed to listen on %s: %w", *address, err)
}

transport := grpc.NewTransport()
dispatcher := yarpc.NewDispatcher(yarpc.Config{
Name: "tango",
Inbounds: yarpc.Inbounds{transport.NewInbound(listener)},
})
dispatcher.Register(tangopb.BuildTangoYARPCProcedures(tangofake.New(tangofake.Params{
Workspaces: local.NewFactory(local.Params{Dir: *repo}),
})))
if err := dispatcher.Start(); err != nil {
return fmt.Errorf("failed to start the server: %w", err)
}
defer func() { _ = dispatcher.Stop() }()

log.Printf("fake tango serving %s on %s", *repo, listener.Addr())
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
<-stop
return nil
}
Loading
Loading