integration #33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: integration | |
| # Live-service integration tests for the feature-gated backends (ADR-0006). These run against | |
| # emulators (MinIO/Azurite/fake-gcs/dind/kind) rather than real clouds, and are env-guarded by | |
| # `CAIRN_IT_*` so the default `cargo test` (and the hermetic CI in ci.yml) never touches the network. | |
| # This is the "dedicated, env-guarded integration job" the depth-vs-breadth contract calls for. | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| # Weekly drift check (Mondays 06:00 UTC) so SDK/service changes surface even without a PR. | |
| - cron: "0 6 * * 1" | |
| pull_request: | |
| # Validate the job on changes to the object backend or this workflow itself. | |
| paths: | |
| - "crates/cairn-backend-object/**" | |
| - "crates/cairn-backend-docker/**" | |
| - "crates/cairn-backend-k8s/**" | |
| - "crates/cairn-vault/**" | |
| - ".github/workflows/integration.yml" | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| jobs: | |
| s3-minio: | |
| name: S3 contract (MinIO) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| # Run MinIO ourselves (the official image needs the `server` command, which the GitHub | |
| # `services:` block can't supply). aws-lc/hyper compile under `--features s3` on Linux only. | |
| - name: Start MinIO | |
| run: | | |
| docker run -d --name minio -p 9000:9000 \ | |
| -e MINIO_ROOT_USER=minioadmin -e MINIO_ROOT_PASSWORD=minioadmin \ | |
| minio/minio:latest server /data | |
| - name: Wait for MinIO to be ready | |
| run: | | |
| for i in $(seq 1 30); do | |
| if curl -fsS http://127.0.0.1:9000/minio/health/live >/dev/null; then | |
| echo "MinIO ready"; exit 0 | |
| fi | |
| sleep 2 | |
| done | |
| echo "MinIO did not become ready"; docker logs minio || true; exit 1 | |
| - name: Create the test bucket | |
| env: | |
| AWS_ACCESS_KEY_ID: minioadmin | |
| AWS_SECRET_ACCESS_KEY: minioadmin | |
| AWS_REGION: us-east-1 | |
| # `aws` is preinstalled on ubuntu-latest; `mb` is idempotent enough for a fresh runner. | |
| run: aws --endpoint-url http://127.0.0.1:9000 s3 mb s3://cairn-it || true | |
| - name: Run the S3 round-trip against MinIO | |
| env: | |
| CAIRN_IT_S3: "1" | |
| CAIRN_IT_S3_ENDPOINT: http://127.0.0.1:9000 | |
| CAIRN_IT_S3_BUCKET: cairn-it | |
| CAIRN_IT_S3_ACCESS_KEY: minioadmin | |
| CAIRN_IT_S3_SECRET_KEY: minioadmin | |
| CAIRN_IT_S3_REGION: us-east-1 | |
| run: cargo test -p cairn-backend-object --features s3 --test s3_minio -- --nocapture | |
| azure-azurite: | |
| name: Azure contract (Azurite) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| - name: Start Azurite | |
| # `--skipApiVersionCheck`: the runner's `az` CLI negotiates a very new Storage API version | |
| # that the pinned Azurite image rejects ("API version ... is not supported"); skipping the | |
| # check lets both the `az` container-create step and the SDK round-trip talk to it. (The | |
| # azure_storage 0.21 SDK itself sends an older, supported version.) | |
| # `--loose`: the 0.21 SDK adds `x-ms-range-get-content-crc64` on ranged GETs, which real | |
| # Azure supports but Azurite's strict mode rejects; loose mode accepts the extra header. | |
| run: | | |
| docker run -d --name azurite -p 10000:10000 \ | |
| mcr.microsoft.com/azure-storage/azurite \ | |
| azurite-blob --blobHost 0.0.0.0 --skipApiVersionCheck --loose | |
| - name: Wait for Azurite to be ready | |
| run: | | |
| for i in $(seq 1 30); do | |
| # Any HTTP response (even 400/403) means Azurite is listening; only a refused | |
| # connection is a failure, so check the curl exit code, not the status. | |
| if curl -sS -o /dev/null http://127.0.0.1:10000/devstoreaccount1; then | |
| echo "Azurite ready"; exit 0 | |
| fi | |
| sleep 2 | |
| done | |
| echo "Azurite did not become ready"; docker logs azurite || true; exit 1 | |
| - name: Create the test container | |
| # The Azurite well-known account/key connection string (public, not a secret). | |
| env: | |
| AZ_CS: "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;" | |
| run: az storage container create -n cairn-it --connection-string "$AZ_CS" || true | |
| - name: Run the Azure round-trip against Azurite | |
| env: | |
| CAIRN_IT_AZURE: "1" | |
| CAIRN_IT_AZURE_ACCOUNT: devstoreaccount1 | |
| CAIRN_IT_AZURE_KEY: "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" | |
| CAIRN_IT_AZURE_CONTAINER: cairn-it | |
| CAIRN_IT_AZURE_ENDPOINT: http://127.0.0.1:10000/devstoreaccount1 | |
| run: cargo test -p cairn-backend-object --features azure --test azure_azurite -- --nocapture | |
| docker-dind: | |
| name: Docker contract (dind) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| # GitHub Linux runners have a working Docker daemon, so `connect_local()` talks to it | |
| # directly — no docker-in-docker service needed. The test creates/cleans its own container. | |
| - name: Run the Docker fs round-trip against the runner's daemon | |
| env: | |
| CAIRN_IT_DOCKER: "1" | |
| run: cargo test -p cairn-backend-docker --features docker --test docker_dind -- --nocapture | |
| k8s-kind: | |
| name: K8s contract (kind) | |
| runs-on: ubuntu-latest | |
| # Bound the blast radius if `kind-action` ever stalls bringing up the cluster. | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: Swatinem/rust-cache@v2 | |
| # Spin up a real single-node Kubernetes cluster; the action writes the kubeconfig to the | |
| # default location and sets the current context, which the adapter reads. | |
| - uses: helm/kind-action@v1 | |
| with: | |
| cluster_name: cairn-it | |
| - name: Wait for kube-system to be up | |
| run: kubectl wait --for=condition=Ready pods --all -n kube-system --timeout=150s || kubectl get pods -A | |
| - name: Run the K8s tree round-trip against kind | |
| env: | |
| CAIRN_IT_K8S: "1" | |
| run: cargo test -p cairn-backend-k8s --features k8s --test k8s_kind -- --nocapture |