Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,35 @@ jobs:
type=raw,value=edge,enable=${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
type=raw,value=latest,enable=${{ github.event_name != 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/v') }}

# Pull requests only: keep the Dockerfile's `--mount=type=cache` dirs
# (cargo registry, /app/target) between pushes of the same PR. On a hosted
# runner those mounts start empty and are never part of the exported layer
# cache, so the cargo-chef cook layer caches nothing and every PR push
# rebuilt all dependencies plus the app in release. The cache is restored
# from actions/cache, injected into BuildKit here, and extracted again
# after the build. The Dockerfile, the image, the target and every
# push / tag / release / dispatch path are unchanged. A PR's cache is
# private to that PR (and main), so the first push of a PR is still cold.
- name: Restore cargo build mounts (pull requests)
if: github.event_name == 'pull_request'
id: cargo_mounts
uses: actions/cache@v4
with:
path: docker-cache-mounts
# One entry per commit, restored from the newest earlier one: a run
# whose layers were all cached from main compiles nothing and would
# otherwise freeze an empty cache under a fixed key.
key: docker-pr-cargo-mounts-${{ github.sha }}
restore-keys: docker-pr-cargo-mounts-

- name: Inject cargo build mounts into BuildKit (pull requests)
if: github.event_name == 'pull_request'
uses: reproducible-containers/buildkit-cache-dance@1b8ab18fbda5ad3646e3fcc9ed9dd41ce2f297b4 # v3.3.2
with:
dockerfile: Dockerfile
cache-dir: docker-cache-mounts
skip-extraction: ${{ steps.cargo_mounts.outputs.cache-hit }}

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
Expand Down
62 changes: 58 additions & 4 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,13 @@ jobs:
run: cargo build -p tinycloud-sdk-wasm -p tinycloud-verifier-wasm --target wasm32-unknown-unknown

test:
name: test (workspace, PostgreSQL-backed)
name: test (workspace, PostgreSQL-backed, ${{ matrix.group }})
runs-on: ubuntu-latest
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
group: [unit, integration-a-o, integration-rest, duckdb]
services:
postgres:
image: postgres:16-alpine
Expand Down Expand Up @@ -136,7 +140,11 @@ jobs:
- name: Cache Rust dependencies
uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6
with:
shared-key: rust-1.97.1-test-default-duckdb
# The three default-feature legs share the cache the single job used
# (warm on every PR); the DuckDB leg has its own, because the bundled
# DuckDB build is the 12 minute one and must never be lost to another
# leg winning the save race.
shared-key: ${{ matrix.group == 'duckdb' && 'rust-1.97.1-test-duckdb' || 'rust-1.97.1-test-default-duckdb' }}
workspaces: . -> target
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Assert PostgreSQL is reachable
Expand All @@ -149,6 +157,7 @@ jobs:
sudo -n iptables -w -L OUTPUT -n >/dev/null

- name: Assert the PostgreSQL regressions still exist
if: matrix.group == 'integration-a-o'
run: |
set -euo pipefail
# `|| true` so a zero match reaches the explicit check below rather
Expand All @@ -164,20 +173,47 @@ jobs:
# The five postgres_* regressions run as part of this suite, against the
# service container above. tinycloud-core's other ~300 tests — which no CI
# job had ever executed — run here too.
- name: Run the workspace test suite
#
# The old step ran `cargo test --workspace`. That is exactly the four steps
# below, which partition cargo's own default targets (lib unit tests, bin
# unit tests, integration tests, doc tests) while keeping `--workspace` so
# feature unification and the built artifacts are identical:
# unit --lib
# integration-a-o --bins, --test '[a-o]*', then --doc
# integration-rest --test '[!a-o]*' (the complement of [a-o]*, so any
# new integration test lands in exactly one leg)
- name: Run the workspace unit tests
if: matrix.group == 'unit'
timeout-minutes: 25
run: cargo test --workspace --lib

- name: Run the workspace bin and integration tests (a-o)
if: matrix.group == 'integration-a-o'
timeout-minutes: 25
run: cargo test --workspace --bins --test '[a-o]*'

- name: Run the workspace doc tests
if: matrix.group == 'integration-a-o'
timeout-minutes: 25
run: cargo test --workspace --doc

- name: Run the workspace integration tests (everything outside a-o)
if: matrix.group == 'integration-rest'
timeout-minutes: 25
run: cargo test --workspace
run: cargo test --workspace --test '[!a-o]*'

# The workspace suite does not enable tinycloud-core's DuckDB feature.
# Run its unit tests with that feature so SQL/DuckDB identity parity is
# checked in CI as well as through the excluded W5 wire-test crate.
# A cold bundled DuckDB build took 11m52s before tests began in PR #473;
# the prior 15m cap stopped it after 1,082 passing core tests, during integration tests.
- name: Run DuckDB-enabled core tests
if: matrix.group == 'duckdb'
timeout-minutes: 20
run: cargo test -p tinycloud-core --features duckdb

- name: Run DuckDB policy and request telemetry through node binaries
if: matrix.group == 'duckdb'
timeout-minutes: 15
run: cargo test -p tinycloud-node --features duckdb --test request_telemetry_authenticated --test duckdb_diagnostics_policy --test duckdb_offline_policy --test space_size_restart

Expand All @@ -190,6 +226,24 @@ jobs:
run: |
psql "${TINYCLOUD_TEST_POSTGRES_URL}" -c "SELECT pid, datname, state, wait_event_type, wait_event, left(query, 200) AS query, pg_blocking_pids(pid) AS blocked_by FROM pg_stat_activity WHERE pid <> pg_backend_pid() ORDER BY pid;" || true

# The test job above is a matrix so its groups run in parallel (it used to be
# one serial job, ~26 min). This job keeps the old check name as the single
# verdict: it fails unless every leg succeeded, so nothing that looks for the
# old name can go green on a partial run.
test-gate:
name: test (workspace, PostgreSQL-backed)
needs: [test]
if: always()
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Require every test leg to have succeeded
env:
TEST_RESULT: ${{ needs.test.result }}
run: |
echo "test matrix result: ${TEST_RESULT}"
[ "${TEST_RESULT}" = "success" ]

clippy:
name: clippy (workspace)
runs-on: ubuntu-latest
Expand Down
Loading