Add a way to bring up instances on ec2, benchmark them, and get profiles #71
Workflow file for this run
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: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| # wal-rs is a git submodule at walshadow/wal-rs (see .gitmodules); | |
| # the path dep in Cargo.toml points there. Submodule URL is SSH; the | |
| # `Init wal-rs submodule` step in each job feeds a read-only deploy | |
| # key (secrets.WAL_RS_DEPLOY_KEY) via GIT_SSH_COMMAND so the clone | |
| # auths without disturbing the primary checkout's GITHUB_TOKEN path. | |
| # Cancel superseded runs on the same ref. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| name: build + e2e (pg${{ matrix.pg-major }}) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| # walshadow operationally supports PG 16+ (see PLAN.md "Supported | |
| # PostgreSQL versions"). Matrix pins the on-PATH PG binaries to one | |
| # specific major; tests + fixture-capture scripts pick up whichever | |
| # `initdb` / `pg_ctl` / `postgres` lands first. | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| pg-major: [16, 17, 18] | |
| steps: | |
| - name: Checkout walshadow | |
| uses: actions/checkout@v6 | |
| with: | |
| path: walshadow | |
| - name: Init wal-rs submodule | |
| working-directory: walshadow | |
| env: | |
| WAL_RS_DEPLOY_KEY: ${{ secrets.WAL_RS_DEPLOY_KEY }} | |
| run: | | |
| install -d -m 700 ~/.ssh | |
| printf '%s\n' "$WAL_RS_DEPLOY_KEY" > ~/.ssh/wal_rs_deploy | |
| chmod 600 ~/.ssh/wal_rs_deploy | |
| ssh-keyscan -H github.com >> ~/.ssh/known_hosts 2>/dev/null | |
| GIT_SSH_COMMAND='ssh -i ~/.ssh/wal_rs_deploy -o IdentitiesOnly=yes' \ | |
| git submodule update --init --recursive | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy, rustfmt | |
| - name: Cargo cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: walshadow | |
| # Key on PG major so a feature/test-config change for one | |
| # major doesn't poison the others' caches. | |
| key: pg${{ matrix.pg-major }} | |
| - name: Install C deps (lz4 + zstd for clickhouse-c-rs) | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| build-essential liblz4-dev libzstd-dev curl gnupg lsb-release | |
| # The runner's preinstalled postgresql-common ships only one major | |
| # at a time; pull the requested major straight from PGDG so the | |
| # matrix can pin any of 16 / 17 / 18 independently of the runner | |
| # image's choice. `systemctl stop postgresql` parks any auto- | |
| # started instance so tests own the unix-socket dirs cleanly. | |
| - name: Install PostgreSQL ${{ matrix.pg-major }} (PGDG) | |
| run: | | |
| sudo systemctl stop postgresql 2>/dev/null || true | |
| curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \ | |
| | sudo gpg --dearmor -o /usr/share/keyrings/postgres-archive-keyring.gpg | |
| echo "deb [signed-by=/usr/share/keyrings/postgres-archive-keyring.gpg] https://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" \ | |
| | sudo tee /etc/apt/sources.list.d/pgdg.list | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| postgresql-${{ matrix.pg-major }} \ | |
| postgresql-client-${{ matrix.pg-major }} \ | |
| postgresql-server-dev-${{ matrix.pg-major }} | |
| sudo systemctl stop postgresql 2>/dev/null || true | |
| PG_BIN=/usr/lib/postgresql/${{ matrix.pg-major }}/bin | |
| "$PG_BIN/postgres" -V | |
| "$PG_BIN/initdb" --version | |
| echo "$PG_BIN" >> "$GITHUB_PATH" | |
| # Official deb repo gives us both the `clickhouse` multitool (for | |
| # `clickhouse local` tests) and `clickhouse-server` (for the | |
| # readme_quickstart that connects to localhost:9000). | |
| - name: Install ClickHouse (server + client) | |
| run: | | |
| sudo apt-get install -y apt-transport-https ca-certificates | |
| curl -fsSL https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key \ | |
| | sudo gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg | |
| echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg] https://packages.clickhouse.com/deb stable main" \ | |
| | sudo tee /etc/apt/sources.list.d/clickhouse.list | |
| sudo apt-get update | |
| DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y \ | |
| -o Dpkg::Options::="--force-confdef" \ | |
| -o Dpkg::Options::="--force-confold" \ | |
| clickhouse-server clickhouse-client clickhouse-common-static | |
| clickhouse --version | |
| - name: Start ClickHouse server | |
| run: | | |
| sudo service clickhouse-server start | |
| # Wait for native protocol on :9000 (readme_quickstart probes it). | |
| for i in $(seq 1 60); do | |
| if clickhouse-client --query "SELECT 1" >/dev/null 2>&1; then | |
| echo "clickhouse-server up after ${i}s" | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| echo "clickhouse-server failed to come up" >&2 | |
| sudo tail -n 200 /var/log/clickhouse-server/clickhouse-server.err.log || true | |
| exit 1 | |
| # classify / filter / xlog_switch / vacuum_full_pg_depend tests | |
| # silently skip when no fixture bytes are present. Regenerate | |
| # them against the matrix PG major so each job's | |
| # filter_round_trip + classify_fixture + wal_stream_chunk_boundary | |
| # actually runs against that major's WAL layout. | |
| - name: Regenerate WAL fixtures (PG ${{ matrix.pg-major }}) | |
| working-directory: walshadow | |
| env: | |
| WALSHADOW_USE_LOCAL: "1" | |
| run: | | |
| fixtures/wal/classify/capture.sh | |
| fixtures/wal/filter/capture.sh | |
| fixtures/wal/xlog_switch/capture.sh | |
| fixtures/wal/vacuum_full_pg_depend/capture.sh | |
| - name: Build (workspace + tests) | |
| working-directory: walshadow | |
| run: cargo build --workspace --all-targets --locked | |
| # All e2e tests run: shadow_lifecycle, shadow_catalog, catalog_seed, | |
| # wal_stream_e2e (need initdb), classify_fixture + filter_round_trip | |
| # + wal_stream_chunk_boundary (use the freshly regenerated fixtures), | |
| # clickhouse-c-rs clickhouse_local + readme_quickstarts (need | |
| # clickhouse binary + server on :9000). | |
| - name: Test (workspace, single-threaded — each test owns a PG cluster) | |
| working-directory: walshadow | |
| env: | |
| # Tests pick non-overlapping ports but PG cluster startup is heavy; | |
| # avoid thrashing the runner by serializing. | |
| RUST_TEST_THREADS: "1" | |
| # Opts tests with `fx::dump_artifacts` into copying their tempdir | |
| # here on failure. Empty on success; uploaded as a job artifact | |
| # by the next step when present. | |
| WALSHADOW_ARTIFACT_DIR: ${{ github.workspace }}/test-artifacts | |
| run: cargo test --workspace --all-targets --locked -- --nocapture | |
| - name: Upload test artifacts on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: test-artifacts-pg${{ matrix.pg-major }} | |
| path: ${{ github.workspace }}/test-artifacts | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| # walshadow extension is a separate PGXS module (shipped to shadow PG). | |
| # Build it against the matrix PG, install into that major's $libdir / | |
| # share/extension, then run pg_regress under a private --temp-instance | |
| # so we don't need an external server. Covers the C bridge function's | |
| # varlena, fixed-width by-val, by-ref, NULL, and ereport paths. | |
| - name: walshadow extension (build + pg_regress) | |
| working-directory: walshadow/pgext | |
| run: | | |
| PG_BIN=/usr/lib/postgresql/${{ matrix.pg-major }}/bin | |
| PG_CONFIG=$PG_BIN/pg_config | |
| make PG_CONFIG=$PG_CONFIG | |
| sudo make PG_CONFIG=$PG_CONFIG install | |
| PG_REGRESS=/usr/lib/postgresql/${{ matrix.pg-major }}/lib/pgxs/src/test/regress/pg_regress | |
| rm -rf /tmp/walshadow_pgext_tmpinst | |
| "$PG_REGRESS" \ | |
| --inputdir=./ --outputdir=./ \ | |
| --bindir="$PG_BIN" \ | |
| --temp-instance=/tmp/walshadow_pgext_tmpinst \ | |
| --port=54329 \ | |
| walshadow | |
| - name: walshadow extension regression diffs on failure | |
| if: failure() | |
| working-directory: walshadow/pgext | |
| run: | | |
| test -f regression.diffs && cat regression.diffs || true | |
| test -d /tmp/walshadow_pgext_tmpinst/log && \ | |
| sudo tail -n 200 /tmp/walshadow_pgext_tmpinst/log/postmaster.log || true | |
| - name: ClickHouse server logs on failure | |
| if: failure() | |
| run: sudo tail -n 500 /var/log/clickhouse-server/clickhouse-server.err.log || true | |
| # Line-coverage baseline so future work can track movement. Runs the | |
| # full e2e suite under `cargo llvm-cov` against the middle supported | |
| # major (PG 17) — one major is enough for a coverage baseline; the | |
| # matrix above proves cross-version behaviour separately. Uploads | |
| # `lcov.info` + an HTML report as artifacts; summary lands in the | |
| # job log. | |
| coverage: | |
| name: line coverage (pg17) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| steps: | |
| - name: Checkout walshadow | |
| uses: actions/checkout@v6 | |
| with: | |
| path: walshadow | |
| - name: Init wal-rs submodule | |
| working-directory: walshadow | |
| env: | |
| WAL_RS_DEPLOY_KEY: ${{ secrets.WAL_RS_DEPLOY_KEY }} | |
| run: | | |
| install -d -m 700 ~/.ssh | |
| printf '%s\n' "$WAL_RS_DEPLOY_KEY" > ~/.ssh/wal_rs_deploy | |
| chmod 600 ~/.ssh/wal_rs_deploy | |
| ssh-keyscan -H github.com >> ~/.ssh/known_hosts 2>/dev/null | |
| GIT_SSH_COMMAND='ssh -i ~/.ssh/wal_rs_deploy -o IdentitiesOnly=yes' \ | |
| git submodule update --init --recursive | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| # cargo-llvm-cov needs `llvm-profdata` + `llvm-cov` shipped by | |
| # this component. | |
| components: llvm-tools-preview | |
| - name: Install cargo-llvm-cov | |
| uses: taiki-e/install-action@v2 | |
| with: | |
| tool: cargo-llvm-cov | |
| - name: Cargo cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: walshadow | |
| # Instrumented builds differ from the test job's; pin a | |
| # separate cache key so they don't collide. | |
| key: coverage | |
| - name: Install C deps | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| build-essential liblz4-dev libzstd-dev curl gnupg lsb-release | |
| - name: Install PostgreSQL 17 (PGDG) | |
| run: | | |
| sudo systemctl stop postgresql 2>/dev/null || true | |
| curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \ | |
| | sudo gpg --dearmor -o /usr/share/keyrings/postgres-archive-keyring.gpg | |
| echo "deb [signed-by=/usr/share/keyrings/postgres-archive-keyring.gpg] https://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" \ | |
| | sudo tee /etc/apt/sources.list.d/pgdg.list | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| postgresql-17 postgresql-client-17 | |
| sudo systemctl stop postgresql 2>/dev/null || true | |
| echo "/usr/lib/postgresql/17/bin" >> "$GITHUB_PATH" | |
| - name: Install ClickHouse (server + client) | |
| run: | | |
| sudo apt-get install -y apt-transport-https ca-certificates | |
| curl -fsSL https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key \ | |
| | sudo gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg | |
| echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg] https://packages.clickhouse.com/deb stable main" \ | |
| | sudo tee /etc/apt/sources.list.d/clickhouse.list | |
| sudo apt-get update | |
| DEBIAN_FRONTEND=noninteractive sudo -E apt-get install -y \ | |
| -o Dpkg::Options::="--force-confdef" \ | |
| -o Dpkg::Options::="--force-confold" \ | |
| clickhouse-server clickhouse-client clickhouse-common-static | |
| - name: Start ClickHouse server | |
| run: | | |
| sudo service clickhouse-server start | |
| for i in $(seq 1 60); do | |
| if clickhouse-client --query "SELECT 1" >/dev/null 2>&1; then | |
| echo "clickhouse-server up after ${i}s" | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| sudo tail -n 200 /var/log/clickhouse-server/clickhouse-server.err.log || true | |
| exit 1 | |
| - name: Regenerate WAL fixtures (PG 17) | |
| working-directory: walshadow | |
| env: | |
| WALSHADOW_USE_LOCAL: "1" | |
| run: | | |
| fixtures/wal/classify/capture.sh | |
| fixtures/wal/filter/capture.sh | |
| fixtures/wal/xlog_switch/capture.sh | |
| fixtures/wal/vacuum_full_pg_depend/capture.sh | |
| # Single `--no-report` test pass so cargo only instruments & | |
| # executes the suite once; subsequent `report` invocations re-read | |
| # the cached profdata to emit lcov + html + summary. | |
| - name: Run instrumented test suite (cargo llvm-cov) | |
| working-directory: walshadow | |
| env: | |
| RUST_TEST_THREADS: "1" | |
| WALSHADOW_ARTIFACT_DIR: ${{ github.workspace }}/test-artifacts | |
| run: | | |
| cargo llvm-cov clean --workspace | |
| cargo llvm-cov --workspace --all-targets --locked --no-report \ | |
| -- --nocapture | |
| - name: Upload test artifacts on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: test-artifacts-coverage | |
| path: ${{ github.workspace }}/test-artifacts | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| - name: Coverage summary (job log) | |
| working-directory: walshadow | |
| run: cargo llvm-cov report --summary-only | |
| - name: Coverage lcov.info | |
| working-directory: walshadow | |
| run: cargo llvm-cov report --lcov --output-path lcov.info | |
| - name: Coverage HTML | |
| working-directory: walshadow | |
| run: cargo llvm-cov report --html | |
| - name: Upload coverage artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage | |
| path: | | |
| walshadow/lcov.info | |
| walshadow/target/llvm-cov/html | |
| if-no-files-found: error | |
| retention-days: 30 | |
| - name: Fail on any 0%-coverage file | |
| working-directory: walshadow | |
| run: | | |
| zero=$(awk ' | |
| /^SF:/ { f = substr($0, 4) } | |
| /^LF:/ { lf = substr($0, 4) + 0 } | |
| /^LH:/ { | |
| if (substr($0, 4) + 0 == 0 && lf > 0) { | |
| i = index(f, "/src/"); if (i) f = substr(f, i + 1) | |
| print f | |
| } | |
| } | |
| ' lcov.info) | |
| if [ -n "$zero" ]; then | |
| count=$(printf '%s\n' "$zero" | grep -c .) | |
| echo "Files with 0% line coverage (every source file must be exercised by a test):" | |
| printf '%s\n' "$zero" | sed 's/^/ /' | |
| echo "::error::${count} file(s) have 0% line coverage" | |
| exit 1 | |
| fi | |
| echo "OK: all instrumented files have >0% line coverage." | |
| - name: ClickHouse server logs on failure | |
| if: failure() | |
| run: sudo tail -n 500 /var/log/clickhouse-server/clickhouse-server.err.log || true | |
| lint: | |
| name: clippy + fmt | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout walshadow | |
| uses: actions/checkout@v6 | |
| with: | |
| path: walshadow | |
| - name: Init wal-rs submodule | |
| working-directory: walshadow | |
| env: | |
| WAL_RS_DEPLOY_KEY: ${{ secrets.WAL_RS_DEPLOY_KEY }} | |
| run: | | |
| install -d -m 700 ~/.ssh | |
| printf '%s\n' "$WAL_RS_DEPLOY_KEY" > ~/.ssh/wal_rs_deploy | |
| chmod 600 ~/.ssh/wal_rs_deploy | |
| ssh-keyscan -H github.com >> ~/.ssh/known_hosts 2>/dev/null | |
| GIT_SSH_COMMAND='ssh -i ~/.ssh/wal_rs_deploy -o IdentitiesOnly=yes' \ | |
| git submodule update --init --recursive | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy, rustfmt | |
| - name: Cargo cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: walshadow | |
| key: lint | |
| - name: Install C deps | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| build-essential liblz4-dev libzstd-dev | |
| - name: cargo fmt | |
| working-directory: walshadow | |
| run: cargo fmt --all -- --check | |
| - name: cargo clippy | |
| working-directory: walshadow | |
| run: cargo clippy --workspace --all-targets -- -D warnings |