Test suite for the BlanketOps Environments API surface. Exercises every custom
resource across all four domains — environments, events, networks,
sources — against shared fixtures, fake controllers, and the gRPC contract.
This repository contains no production code . It exists to answer one question continuously: does an implementation of the Environments API behave the way the contract says it must?
| Repository | Role |
|---|---|
blanketops-environments-contract |
Proto definitions — the contract under test |
blanketops-environments-controller |
Reference implementation the fakes mirror |
blanketops-environments-tests |
This repo— fixtures, fakes, conformance suites |
The pipeline chain the resources participate in:
GitRepository → GitHubEvent → Build → SupplyChain → Package → Deployment
tests/
├── data/ Canonical test fixtures — one file per CR, one package per domain
├── fake/ Fake domain controllers + behavioural suites (Ginkgo/Gomega)
└── grpc/ gRPC service conformance tests against the contract
Constructor functions producing valid, canonical instances of every CR. These are the single source of truth for "what a well-formed resource looks like" — fakes and gRPC suites both consume them. Every fixture carries the required BlanketOps labels:
environments.blanketops.dev/name
environments.blanketops.dev/type
environments.blanketops.dev/api-version
environments.blanketops.dev/contract-version
When the contract changes shape, fixtures change first; failures ripple outward from here by design.
Deterministic fake controllers per domain, exercised by suite_test.go files.
These encode the behavioural contract — phase transitions, status writes,
ownership semantics — without requiring a cluster. A fake that drifts from the
reference controller is a bug in one of the two; the suite is how you find out
which.
tests/fake/observers is a variant of this: instead of a domain reconciler
(via a fake domain injected into the real registry/engine), it drives the
observer reconcilers directly — the side-channel layer under
environments-controller/internal/controller/observers that watches non-
BlanketOps infrastructure (Shipwright BuildRun, Argo Events Sensor) and
reflects real-world outcomes back onto the owning CR (GitHubEvent→Build
trigger mirroring, retry bookkeeping, success/failure conditions). Reaching
these reconcilers from here required adding public pkg/controller/observers/*
aliases in environments-controller (same pattern as the domain reconcilers'
own pkg/controller/{environments,events,networks,sources} aliases) — they
previously lived only under internal/, unreachable from any external module.
This suite additionally needs the Shipwright BuildRun and Argo Events
Sensor CRDs registered on the target cluster (not their controllers — same
"drive fake objects directly" approach as everywhere else in this repo).
One test file per service (BuildService, DeploymentService,
GitRepositoryService, …) validating the generated gRPC surface: request and
response shapes, CRUD + domain-specific RPCs, watch-stream semantics. Tests
not yet implemented are stubbed with t.Skip() — a skip is a TODO, not a
pass.
# everything
make test
# one layer
go test ./tests/fake/...
go test ./tests/grpc/...
# one domain
go test ./tests/fake/environments/...
# verbose Ginkgo output
go test ./tests/fake/... -vRequires Go (version per go.mod). No cluster, no external services — the
suite is fully self-contained and deterministic.
The workflows run on the repository's self-hosted runner (runs-on: self-hosted), on pull requests and on pushes to test and master:
| Workflow | Check | What it runs |
|---|---|---|
Lint (lint.yml) |
golangci-lint | The runner image's golangci-lint over the whole module |
Data Tests (test.yml) |
Fixtures and conformance (tests/data) | make test: the fixture builders and engine conformance tests, no cluster |
Suite Tests (run-tests.yml) |
fake and gRPC suites (envtest) | tests/fake and tests/grpc against an envtest API server with the CRDs from environments-install; JUnit and Allure reports as artifacts, and a results table in the job summary |
Each test file has a tracking issue, [test] <path under tests/> (e.g.
[test] fake/networks/route_test), labelled test-tracking and its layer.
A test file is a *_test.go file under tests/ (tests/data excluded)
that declares Go test functions or top-level Ginkgo containers. Suite Tests
runs test-helper (blanketops/environments-bots) as the BlanketOps
Environments Tests App (blanketops-environments-tests[bot]; secrets
TESTS_APP_ID and TESTS_APP_PRIVATE_KEY, falling back to the job's
GITHUB_TOKEN where they are not available): before the tests, test-helper sync opens issues for new test files, including those a pull request adds,
and puts them on project 1 in Test; after them, test-helper report comments every file's results on its issue (each test's result
and time, failure and skip output, a link to the run). Neither step can fail
the job.
- Fixtures are canonical. Never hand-roll a resource inside a test;
consume
tests/dataand mutate only the field under test. - One domain, one package. A new CR gets a fixture file, a fake, a suite registration, and a gRPC test file — all four, in the same change.
- Skips are visible debt.
t.Skip()marks unimplemented conformance, and CI reports skips distinctly from passes. - Determinism is non-negotiable. No sleeps, no wall-clock assertions, no network. If a test needs ordering, it asserts on observed state.
- Fixture constructors in
tests/data/<domain>/ - Fake controller + behaviours in
tests/fake/<domain>/with asuite_test.go - gRPC conformance in
tests/grpc/<resource>_grpc_test.go - Wire into
make test(automatic via./tests/...globbing)
See LICENSE.