Tests
Retrieve and build the charts before running anything:
task retrieve-charts
task build_chart
export HELM_CHARTS=$(pwd)/charts
export CHART_VERSION=$(head -n1 CHART_VERSIONS)Tiers
| Tier | Where | Run it with | Needs |
|---|---|---|---|
| Unit, Ginkgo | controllers/, helm/, pkg/, api/, internal/controller/gitlabcore/ | task unit-tests | the charts |
| Unit, testify | the rest of internal/ | task unit-tests, task bridge-unit-tests | nothing |
| Controller, envtest | controllers/, pkg/support/kube, internal/controller/gitlabcore | task slow-unit-tests | KUBEBUILDER_ASSETS, the charts |
| End-to-end, in-process | internal/**/e2e_test.go | task e2e-tests | a cluster, the v2alpha1 definitions |
| End-to-end, black-box | test/e2e/ | task e2e-suite | a cluster, a built -bridge image |
Run one package with task unit-tests TEST_PKGS="./controllers/gitlab/...", and one
test with SKIP_ENVTEST=yes go run github.com/onsi/ginkgo/v2/ginkgo --focus "...".
Unattended upgrades
Two tests follow an instance through unattended upgrades. They cover the same journey at different depths.
The envtest journey, internal/controller/gitlabcore/unattended_upgrade_envtest_test.go,
runs the reconciler against a real API server and a chart repository the test controls.
It needs two bundled chart versions one minor apart, and repackages them as the new
releases the repository publishes. envtest runs no controllers, so a fake kubelet
completes the Jobs and rolls the workloads out. Everything else is real: the render,
the server-side apply, the preflight dry run, and the hooks. It covers these cases:
- Static, then Patch, then a new patch that the instance upgrades to and settles on.
- A Latest target held while an upgrade runs, and the newer patch it moves to afterward.
- The hooks of the new chart running on an unattended upgrade.
- A candidate that fails its preflight, and the fixed release that replaces it.
- A refused downgrade.
Run it on its own:
KUBEBUILDER_ASSETS=$(./setup-envtest use -p path) SKIP_ENVTEST=no \
go run github.com/onsi/ginkgo/v2/ginkgo --focus "unattended upgrades" ./internal/controller/gitlabcore/The black-box upgrades suite in test/e2e/suite/upgrades runs the same journey
against a real GitLab. From the install on, it requests the sign-in page through the
Gateway and HTTPRoute every 2 seconds, and fails for any request that is not served, so
it asserts that the upgrades cause no downtime. For its requirements, see
test/e2e/README.md.
Why the black-box suites deploy an image
The v2alpha1 reconcilers are gated twice: the bridge build tag keeps them out of
the default build, and ENABLE_BRIDGE keeps them off at runtime even in the tagged
build. Their RBAC is not in deploy/chart either — it is
config/rbac/v2alpha1_manager_role.yaml, applied by task install_v2alpha1_crds.
A test that constructs a reconciler in its own process uses none of the three. It
runs under the ambient kubeconfig of whoever ran it, which is usually an
administrator, so it passes just as happily against an image built from the wrong
Dockerfile, a release installed with the bridge off, or a manager that may not write
the status of what it reconciles. test/e2e deploys the image and drives it through
the API server so that all three have to be right, and it fails with a different
message for each. See test/e2e/README.md.
The in-process tests under internal/ are still worth having: they are far faster,
and they can reach a reconciler directly. They are the tier below, not the same one.
Why test/e2e carries no build tag
The in-process end-to-end tests live in the same package as the code they test, so a
//go:build e2e tag is the only thing that keeps them out of task unit-tests.
test/e2e is a directory of its own, so it needs no tag: TestE2E skips unless
E2E=true, and unit-tests excludes the package by name.
That is deliberate rather than incidental. A tagged file is invisible to gopls unless
every editor sets its build flags, and invisible to golangci-lint unless the tag is
on its command line, so tagged code rots quietly. Untagged, go build ./...,
go vet ./... and the default lint run all cover the harness.