Tests

Retrieve and build the charts before running anything:

shell
task retrieve-charts
task build_chart
export HELM_CHARTS=$(pwd)/charts
export CHART_VERSION=$(head -n1 CHART_VERSIONS)

Tiers

TierWhereRun it withNeeds
Unit, Ginkgocontrollers/, helm/, pkg/, api/, internal/controller/gitlabcore/task unit-teststhe charts
Unit, testifythe rest of internal/task unit-tests, task bridge-unit-testsnothing
Controller, envtestcontrollers/, pkg/support/kube, internal/controller/gitlabcoretask slow-unit-testsKUBEBUILDER_ASSETS, the charts
End-to-end, in-processinternal/**/e2e_test.gotask e2e-testsa cluster, the v2alpha1 definitions
End-to-end, black-boxtest/e2e/task e2e-suitea 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:

shell
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.