name: CI
'on':
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-test:
name: Linux Build and Test (${{ matrix.privilege }})
runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || 'ubicloud-standard-4' }}
timeout-minutes: 66
strategy:
fail-fast: false
matrix:
privilege: [unprivileged, root]
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
BUILD_PROFILE: debug
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
MERMAN_CLI_VERSION: '0.7.0'
WHITAKER_INSTALLER_VERSION: '0.2.6'
RUN_RUST_CARGO_WAIT_TIMEOUT: '1800'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
fetch-depth: 0
persist-credentials: false
- name: Setup Rust
uses: leynos/shared-actions/.github/actions/setup-rust@074f7d8ba75a6e5d18532b72cbe38fccbda4e9c6
- name: Install mdtablefix
if: ${{ matrix.privilege == 'unprivileged' }}
uses: leynos/shared-actions/.github/actions/install-mdtablefix@774cc5a01e457714aede66e14a97b3e257812fc2
with:
version: "0.6.0"
- name: Format
if: ${{ matrix.privilege == 'unprivileged' }}
run: make check-fmt
- name: Markdown lint
if: ${{ matrix.privilege == 'unprivileged' }}
uses: DavidAnson/markdownlint-cli2-action@21c1be1b93ad9ed58fa840aacc3f279cde2a72ff
with:
globs: '**/*.md'
- name: Setup uv
if: ${{ matrix.privilege == 'unprivileged' }}
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990
with:
enable-cache: false
- name: Enforce en-GB-oxendict spelling
if: ${{ matrix.privilege == 'unprivileged' }}
run: make spelling
- name: Release tooling tests
if: ${{ matrix.privilege == 'unprivileged' }}
run: make test-scripts
- name: Install interrogate
if: ${{ matrix.privilege == 'unprivileged' }}
run: uv tool install interrogate==1.7.0
- name: Install Whitaker Dylint suite
if: ${{ matrix.privilege == 'unprivileged' }}
uses: leynos/shared-actions/.github/actions/install-whitaker@e041cb75c35c3524201a32d5e57c87408fbd5874
with:
installer-version: ${{ env.WHITAKER_INSTALLER_VERSION }}
- name: Lint
if: ${{ matrix.privilege == 'unprivileged' }}
run: make lint
- name: Set up isolated Rust for Merman
if: ${{ matrix.privilege == 'unprivileged' }}
run: rustup toolchain install 1.95.0 --profile minimal
- name: Cache Merman
if: ${{ matrix.privilege == 'unprivileged' }}
id: cache-merman
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: ~/.cargo/bin/merman-cli
key: merman-cli-${{ runner.os }}-${{ runner.arch }}-${{ env.MERMAN_CLI_VERSION }}
- name: Install Mermaid validation tools
if: ${{ matrix.privilege == 'unprivileged' }}
run: |
uv tool install nixie-cli==1.1.0
if [[ "${{ steps.cache-merman.outputs.cache-hit }}" != 'true' ]]; then
cargo +1.95.0 install merman-cli --version "=${MERMAN_CLI_VERSION}" --locked
fi
- name: Validate Mermaid diagrams
if: ${{ matrix.privilege == 'unprivileged' }}
run: make nixie
- name: Install cargo-nextest
run: cargo binstall -y cargo-nextest@0.9.122
- name: Test with all features (unprivileged)
if: ${{ matrix.privilege == 'unprivileged' }}
run: >-
RUSTFLAGS="-D warnings"
cargo nextest run --all-targets --all-features
- name: Run Loom model tests (unprivileged)
if: ${{ matrix.privilege == 'unprivileged' }}
timeout-minutes: 10
run: make test-loom
- name: Test and Measure Coverage (unprivileged)
if: ${{ matrix.privilege == 'unprivileged' }}
uses: leynos/shared-actions/.github/actions/generate-coverage@d4d248bbbecdcf7b4f5bc79ffd4d6caee370bd79
with:
output-path: lcov.info
format: lcov
features: dev-worker
with-default-features: "false"
with-ratchet: 'true'
publish-artefact: 'false'
- name: Install cargo-nextest and test (root)
if: ${{ matrix.privilege == 'root' }}
run: |
# Worker binary path - staging logic will copy it to /tmp for nobody access
export PG_EMBEDDED_WORKER="$PWD/target/debug/pg_worker"
run_as_root() {
: "${RUSTUP_HOME:=$HOME/.rustup}"
: "${CARGO_HOME:=$HOME/.cargo}"
sudo -E env \
HOME="$HOME" \
RUSTUP_HOME="$RUSTUP_HOME" \
CARGO_HOME="$CARGO_HOME" \
GITHUB_TOKEN="$GITHUB_TOKEN" \
PG_EMBEDDED_WORKER="$PG_EMBEDDED_WORKER" \
PATH="$CARGO_HOME/bin:$PATH" \
"$@"
}
run_as_root make test
msrv:
name: Build at the declared rust-version
runs-on: ${{ github.event.pull_request.head.repo.fork && 'ubuntu-latest' || 'ubicloud-standard-4' }}
timeout-minutes: 30
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- name: Setup Rust
uses: leynos/shared-actions/.github/actions/setup-rust@074f7d8ba75a6e5d18532b72cbe38fccbda4e9c6
- name: Setup uv
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990
with:
enable-cache: false
- name: Build at the declared rust-version
run: make msrv
cross-platform-tests:
name: Test (${{ matrix.target }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- runner: macos-latest
target: aarch64-apple-darwin
- runner: windows-latest
target: x86_64-pc-windows-msvc
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PG_BINARY_CACHE_DIR: ${{ github.workspace }}/.postgres-binary-cache
PG_TEST_BACKEND: postgresql_embedded
PG_VERSION_REQ: "=17.4.0"
RUSTFLAGS: -D warnings
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- name: Setup Rust
uses: leynos/shared-actions/.github/actions/setup-rust@074f7d8ba75a6e5d18532b72cbe38fccbda4e9c6
- name: Restore PostgreSQL binary cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: ${{ env.PG_BINARY_CACHE_DIR }}
key: pg-embedded-postgresql-${{ env.PG_VERSION_REQ }}-${{ runner.os }}-${{ runner.arch }}
- name: Install cargo-nextest
shell: bash
run: cargo binstall -y cargo-nextest@0.9.122
- name: Build binaries
shell: bash
run: >-
cargo build
--no-default-features
--features cluster-unit-tests,async-api
--bins
- name: Run CLI version smoke test
shell: bash
env:
RUNNER_OS: ${{ runner.os }}
run: |
set -euo pipefail
binary=target/debug/pg_embedded_setup_unpriv
if [[ "$RUNNER_OS" == "Windows" ]]; then
binary="${binary}.exe"
fi
"$binary" --version
- name: Test unprivileged surface
shell: bash
run: >-
cargo nextest run
--all-targets
--no-default-features
--features cluster-unit-tests,async-api
binstall-packaging:
name: Binstall (${{ matrix.target }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-24.04
target: x86_64-unknown-linux-gnu
- runner: macos-latest
target: aarch64-apple-darwin
- runner: windows-latest
target: x86_64-pc-windows-msvc
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
RELEASE_PORT: "8765"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- name: Setup Rust
uses: leynos/shared-actions/.github/actions/setup-rust@074f7d8ba75a6e5d18532b72cbe38fccbda4e9c6
- name: Setup uv
uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990
with:
enable-cache: false
- name: Build cargo-binstall archive
shell: bash
env:
TARGET: ${{ matrix.target }}
run: >-
uv run --script scripts/release_archive.py
"$TARGET"
- name: Verify archive checksum sidecar
shell: bash
working-directory: dist
run: |
set -euo pipefail
# Arrays are avoided: expanding an empty array under `set -u`
# fails on the Bash 3.2 that macOS runners provide.
shopt -s nullglob
verified=0
for sidecar in *.tgz.sha256; do
if command -v sha256sum >/dev/null 2>&1; then
sha256sum --check --strict "$sidecar"
else
shasum --algorithm 256 --check --strict "$sidecar"
fi
verified=$((verified + 1))
done
if [ "$verified" -eq 0 ]; then
echo "release_archive.py wrote no .sha256 sidecar" >&2
exit 1
fi
- name: Start local HTTPS archive server
id: archive-server
uses: ./.github/actions/setup-local-https-server
with:
port: ${{ env.RELEASE_PORT }}
cert-dir: ${{ runner.temp }}/binstall-cert
serve-dir: dist
- name: Install from local cargo-binstall archive
shell: bash
env:
ROOT_CERTIFICATE: ${{ steps.archive-server.outputs.ca-certificate }}
RUNNER_OS: ${{ runner.os }}
SERVER_PID: ${{ steps.archive-server.outputs.server-pid }}
TARGET: ${{ matrix.target }}
run: |
set -euo pipefail
trap 'kill "$SERVER_PID" 2>/dev/null || true' EXIT
install_dir="$PWD/.binstall-bin"
rm -rf "$install_dir"
mkdir -p "$install_dir"
cargo binstall -y \
--manifest-path Cargo.toml \
--targets "$TARGET" \
--strategies crate-meta-data \
--pkg-url "https://127.0.0.1:${RELEASE_PORT}/{ name }-{ target }-v{ version }{ archive-suffix }" \
--root-certificates "$ROOT_CERTIFICATE" \
--install-path "$install_dir" \
--force \
pg-embed-setup-unpriv
binary_ext=""
if [[ "$RUNNER_OS" == "Windows" ]]; then
binary_ext=".exe"
fi
test -f "$install_dir/pg_embedded_setup_unpriv${binary_ext}"
test -f "$install_dir/pg_worker${binary_ext}"
"$install_dir/pg_embedded_setup_unpriv${binary_ext}" --version