diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3783e9ac..f7d2aacd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,8 +16,6 @@ on: env: # Common versions - GO_VERSION: '1.26.8' - GOLANGCI_VERSION: 'v2.10.1' DOCKER_BUILDX_VERSION: 'v0.23.0' # Common users. We can't run a step 'if secrets.AWS_USR != ""' but we can run @@ -27,9 +25,13 @@ env: XPKG_ACCESS_ID: ${{ secrets.XPKG_ACCESS_ID }} AWS_USR: ${{ secrets.AWS_USR }} + # Keep temp files off the size-capped tmpfs /tmp of ubuntu-26.04 runners. + TMPDIR: /home/runner/work/_temp + GOTMPDIR: /home/runner/work/_temp + jobs: detect-noop: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 outputs: noop: ${{ steps.noop.outputs.should_skip }} steps: @@ -44,7 +46,7 @@ jobs: lint: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 needs: detect-noop if: needs.detect-noop.outputs.noop != 'true' @@ -57,7 +59,7 @@ jobs: - name: Setup Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: ${{ env.GO_VERSION }} + go-version-file: go.mod - name: Find the Go Build Cache id: go @@ -80,15 +82,19 @@ jobs: - name: Download Go Modules run: make modules.download modules.check + - name: Detect golangci-lint version + id: golangci + run: echo "version=v$(awk '/^GOLANGCILINT_VERSION/{print $3}' Makefile)" | tee -a "$GITHUB_OUTPUT" + # We could run 'make lint' but we prefer this action because it leaves # 'annotations' (i.e. it comments on PRs to point out linter violations). - name: Lint uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0 with: - version: ${{ env.GOLANGCI_VERSION }} + version: ${{ steps.golangci.outputs.version }} check-diff: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 needs: detect-noop if: needs.detect-noop.outputs.noop != 'true' @@ -101,7 +107,7 @@ jobs: - name: Setup Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: ${{ env.GO_VERSION }} + go-version-file: go.mod - name: Find the Go Build Cache id: go @@ -135,7 +141,7 @@ jobs: run: git diff unit-tests: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 needs: detect-noop if: needs.detect-noop.outputs.noop != 'true' permissions: @@ -154,7 +160,7 @@ jobs: - name: Setup Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: ${{ env.GO_VERSION }} + go-version-file: go.mod - name: Find the Go Build Cache id: go @@ -188,7 +194,7 @@ jobs: files: _output/tests/linux_amd64/coverage.txt e2e-tests: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 needs: detect-noop if: needs.detect-noop.outputs.noop != 'true' @@ -214,7 +220,7 @@ jobs: - name: Setup Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: ${{ env.GO_VERSION }} + go-version-file: go.mod - name: Find the Go Build Cache id: go @@ -248,7 +254,7 @@ jobs: run: make e2e USE_HELM=true POSTGRES_VERSION=${{ inputs.postgres_version || '18' }} publish-artifacts: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 needs: detect-noop if: needs.detect-noop.outputs.noop != 'true' @@ -282,7 +288,7 @@ jobs: - name: Setup Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: ${{ env.GO_VERSION }} + go-version-file: go.mod - name: Find the Go Build Cache id: go diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index af09e8b5..977cb845 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -9,7 +9,7 @@ on: jobs: detect-noop: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 outputs: noop: ${{ steps.noop.outputs.should_skip }} steps: @@ -23,7 +23,7 @@ jobs: concurrent_skipping: false analyze: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 needs: detect-noop if: needs.detect-noop.outputs.noop != 'true' diff --git a/.github/workflows/publish-provider-package.yml b/.github/workflows/publish-provider-package.yml index 2e7b6849..4649b4a3 100644 --- a/.github/workflows/publish-provider-package.yml +++ b/.github/workflows/publish-provider-package.yml @@ -7,18 +7,28 @@ on: description: "Version string to use while publishing the package (e.g. v1.0.0-alpha.1)" default: "" required: false - go-version: - description: "Go version to use if building needs to be done" - default: "1.26.8" - required: false jobs: + get-go-version: + runs-on: ubuntu-latest + outputs: + go-version: ${{ steps.extract-version.outputs.version }} + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Extract Go version from go.mod + id: extract-version + run: | + GO_VERSION=$(grep '^go ' go.mod | awk '{print $2}') + echo "version=${GO_VERSION}" | tee -a $GITHUB_OUTPUT + publish-provider-package: + needs: get-go-version uses: crossplane-contrib/provider-workflows/.github/workflows/publish-provider-non-family.yml@d736839d853a03083eb1aac9af4825f11321c88c with: repository: provider-sql version: ${{ github.event.inputs.version }} - go-version: ${{ github.event.inputs.go-version }} + go-version: ${{ needs.get-go-version.outputs.go-version }} cleanup-disk: true secrets: GHCR_PAT: ${{ secrets.GITHUB_TOKEN }} @@ -27,7 +37,7 @@ jobs: add-extensions: needs: publish-provider-package - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index c61733a7..eb8b79ff 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -12,7 +12,7 @@ on: jobs: create-tag: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 steps: - name: Checkout diff --git a/Makefile b/Makefile index 31517508..7735a178 100644 --- a/Makefile +++ b/Makefile @@ -87,6 +87,10 @@ e2e.run: test-integration CROSSPLANE_HELM_CHANNEL ?= stable CROSSPLANE_HELM_CHART_VERSION ?= POSTGRES_VERSION ?= 18 +# DB selects the integration test suite: all, mysql, postgresql or mssql. +DB ?= all +# skipcleanup=true keeps the kind cluster and provider after the run; the next run reuses them. +skipcleanup ?= false # Run integration tests. test-integration: $(KIND) $(KUBECTL) $(CROSSPLANE_CLI) $(HELM) @@ -95,6 +99,8 @@ test-integration: $(KIND) $(KUBECTL) $(CROSSPLANE_CLI) $(HELM) CROSSPLANE_HELM_CHANNEL=${CROSSPLANE_HELM_CHANNEL} \ CROSSPLANE_HELM_CHART_VERSION=${CROSSPLANE_HELM_CHART_VERSION} \ POSTGRES_VERSION=${POSTGRES_VERSION} \ + DB=${DB} \ + skipcleanup=${skipcleanup} \ $(ROOT_DIR)/cluster/local/integration_tests.sh || $(FAIL) @$(OK) integration tests passed diff --git a/README.md b/README.md index 174e38a5..459a7314 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,37 @@ Check the example: 5. Run `make reviewable` to run code generation, linters, and tests. 6. Commit, push, and PR. +## Integration tests + +Integration tests run against a local [kind](https://kind.sigs.k8s.io) cluster +with Crossplane, the provider, and the database servers deployed in it. + +```console +make build +make e2e # or: make test-integration +``` + +Options (pass as `make` variables, e.g. `make e2e DB=postgresql`): + +| Variable | Default | Description | +|---|---|---| +| `DB` | `all` | Database suite to run: `all`, `mysql`, `postgresql` or `mssql`. | +| `skipcleanup` | `false` | `true` keeps the kind cluster and the provider after the run. The next run reuses the cluster (skips cluster and Crossplane setup) and redeploys the provider. | +| `QUICK_TEST` | unset | `true` stops after the provider is healthy, without running database tests. | +| `POSTGRES_VERSION` | `18` | PostgreSQL server image version. | +| `MSSQL_IMAGE` | `mcr.microsoft.com/mssql/server:2019-CU32-ubuntu-20.04` | MSSQL server image. | +| `KIND_NODE_IMAGE_TAG` | see `Makefile` | kind node image tag (Kubernetes version). | +| `K8S_CLUSTER` | `-inttests` | kind cluster name. | +| `CROSSPLANE_HELM_CHANNEL` | `stable` | Crossplane Helm chart channel. | +| `CROSSPLANE_HELM_CHART_VERSION` | latest in channel | Crossplane Helm chart version. | + +A preserved cluster can hold leftover database resources from a failed run. +If the next run fails on them, delete the cluster: + +```console +kind delete cluster --name +``` + ## Developing locally **Pre-requisite:** A Kubernetes cluster with Crossplane installed diff --git a/build b/build index 65819b05..6a16dad3 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit 65819b05239a0b22f1a98c3698a14acd22bc3cc0 +Subproject commit 6a16dad359dfc2a2509e61d1c2a604b837363f33 diff --git a/cluster/local/integration_tests.sh b/cluster/local/integration_tests.sh index 903eb896..b2ff336a 100755 --- a/cluster/local/integration_tests.sh +++ b/cluster/local/integration_tests.sh @@ -81,8 +81,10 @@ if [ $? -ne 0 ]; then fi integration_tests_end() { - echo_step "--- CLEAN-UP ---" - cleanup_provider + if [ "$skipcleanup" != true ]; then + echo_step "--- CLEAN-UP ---" + cleanup_provider + fi echo_success " All integration tests succeeded!" } @@ -404,8 +406,25 @@ cleanup_test_resources() { "${KUBECTL}" delete secret example-pw } -setup_cluster -setup_crossplane +# DB selects which database suite to run: all (default), mysql, postgresql or mssql. +DB="${DB:-all}" +case "${DB}" in + all|mysql|postgresql|mssql) ;; + *) echo_error "Invalid DB='${DB}'. Expected one of: all, mysql, postgresql, mssql." ;; +esac + +db_selected() { + [[ "${DB}" == "all" || "${DB}" == "$1" ]] +} + +# reuse a cluster kept by a previous run with skipcleanup=true +if "${KIND}" get clusters | grep -qx "${K8S_CLUSTER}"; then + echo_step "reusing existing k8s cluster ${K8S_CLUSTER}" + "${KIND}" export kubeconfig --name="${K8S_CLUSTER}" +else + setup_cluster + setup_crossplane +fi setup_provider if [ "${QUICK_TEST:-}" == "true" ]; then @@ -451,14 +470,20 @@ run_test() { echo_step "--- TESTING $testmain DONE IN ${duration}s ---" } -TLS=true API_TYPE="namespaced" run_test integration_tests_mariadb -TLS=false API_TYPE="cluster" run_test integration_tests_mariadb +if db_selected mysql; then + TLS=true API_TYPE="namespaced" run_test integration_tests_mariadb + TLS=false API_TYPE="cluster" run_test integration_tests_mariadb +fi -TLS=false API_TYPE="cluster" run_test integration_tests_postgres -TLS=false API_TYPE="namespaced" run_test integration_tests_postgres +if db_selected postgresql; then + TLS=false API_TYPE="cluster" run_test integration_tests_postgres + TLS=false API_TYPE="namespaced" run_test integration_tests_postgres +fi # no TLS=false variant - MSSQL uses built-in encryption -TLS=true API_TYPE="cluster" run_test integration_tests_mssql -TLS=true API_TYPE="namespaced" run_test integration_tests_mssql +if db_selected mssql; then + TLS=true API_TYPE="cluster" run_test integration_tests_mssql + TLS=true API_TYPE="namespaced" run_test integration_tests_mssql +fi integration_tests_end