Skip to content

ci(delta-sync): raise password-only fixture timeout 15m -> 25m #69

ci(delta-sync): raise password-only fixture timeout 15m -> 25m

ci(delta-sync): raise password-only fixture timeout 15m -> 25m #69

name: Delta Sync Integration
# Validates the rsync-over-SSH stack end-to-end against a local docker
# fixture. Cheap to run, scoped to paths that actually affect the feature
# so unrelated PRs don't pay for it.
on:
push:
branches: [main]
paths:
- 'src-tauri/src/lib.rs'
- 'src-tauri/src/settings.rs'
- 'src-tauri/src/ssh_exec.rs'
- 'src-tauri/src/rsync_output.rs'
- 'src-tauri/src/rsync_over_ssh.rs'
- 'src-tauri/src/delta_transport.rs'
- 'src-tauri/src/delta_sync_rsync.rs'
- 'src-tauri/src/providers/sftp.rs'
- 'src-tauri/Cargo.lock'
- 'src-tauri/tests/fixtures/sftp-rsync/**'
- 'src-tauri/tests/integration_delta_sync.rs'
- '.github/workflows/delta-sync-integration.yml'
pull_request:
branches: [main]
paths:
- 'src-tauri/src/lib.rs'
- 'src-tauri/src/settings.rs'
- 'src-tauri/src/ssh_exec.rs'
- 'src-tauri/src/rsync_output.rs'
- 'src-tauri/src/rsync_over_ssh.rs'
- 'src-tauri/src/delta_transport.rs'
- 'src-tauri/src/delta_sync_rsync.rs'
- 'src-tauri/src/providers/sftp.rs'
- 'src-tauri/Cargo.lock'
- 'src-tauri/tests/fixtures/sftp-rsync/**'
- 'src-tauri/tests/integration_delta_sync.rs'
- '.github/workflows/delta-sync-integration.yml'
workflow_dispatch:
permissions:
contents: read
jobs:
integration:
name: SFTP rsync fixture + live test (key-auth)
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
toolchain: stable
- name: Rust cache
uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2
with:
workspaces: './src-tauri -> target'
- name: Install system dependencies
run: |
sudo apt-get update
# rsync + ssh client for the host side of the integration test.
# Webkit/GTK stack is needed because compiling the aeroftp
# library pulls Tauri deps even when we only run one test binary.
sudo apt-get install -y \
rsync \
openssh-client \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev
- name: Generate fixture SSH key
working-directory: src-tauri/tests/fixtures/sftp-rsync
run: bash setup.sh
- name: Build & start docker fixture
working-directory: src-tauri/tests/fixtures/sftp-rsync
run: docker compose up -d --build
- name: Wait for fixture SSH
run: |
for i in $(seq 1 20); do
if ssh -i src-tauri/tests/fixtures/sftp-rsync/ssh_key \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o BatchMode=yes \
-o ConnectTimeout=2 \
-p 2222 testuser@127.0.0.1 'true' 2>/dev/null; then
echo "Fixture SSH ready after $((i * 2))s"
exit 0
fi
echo "Waiting for fixture SSH... ($i/20)"
sleep 2
done
echo "Fixture did not come up within 40s; dumping logs" >&2
docker logs aeroftp-delta-sync-fixture >&2 || true
exit 1
- name: "Unit tests: delta-sync modules"
working-directory: src-tauri
run: |
cargo test --lib --no-fail-fast -- \
rsync_output:: \
rsync_over_ssh:: \
ssh_exec:: \
delta_transport:: \
delta_sync_rsync::
- name: "Integration test: delta sync over SSH"
working-directory: src-tauri
run: cargo test --test integration_delta_sync -- --ignored --nocapture
- name: Dump fixture logs on failure
if: failure()
working-directory: src-tauri/tests/fixtures/sftp-rsync
run: |
docker logs aeroftp-delta-sync-fixture || true
docker compose ps
- name: Teardown fixture
if: always()
working-directory: src-tauri/tests/fixtures/sftp-rsync
run: docker compose down -v
fallback-fixture:
# PR-T02: covers the silent-fallback branch when the SFTP session
# is password-only (delta path returns `None`, classic upload takes
# over) and the offline hard-rejection contract. Runs in parallel
# with the key-auth integration job so a regression in either lane
# blocks the PR independently.
name: SFTP password-only fixture + fallback contract
runs-on: ubuntu-latest
# Cold-cache PRs (Cargo.lock churn from deps bumps) compile the full
# workspace + Tauri + aeroftp lib before the test binary links. The
# sibling key-auth job needs ~11min on a warm shared cache; this lane
# uses an isolated shared-key so the first cache miss can take 18-22
# minutes. 25min gives enough headroom without parking PRs forever.
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
toolchain: stable
- name: Rust cache
uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2
with:
workspaces: './src-tauri -> target'
shared-key: delta-sync-fallback
- name: Install system dependencies
# sshpass needed to poll the password-auth fixture readiness
# (the integration test itself uses russh via SftpProvider -
# sshpass is just a scripting convenience).
run: |
sudo apt-get update
sudo apt-get install -y \
rsync \
openssh-client \
sshpass \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev
- name: Build & start password-auth docker fixture
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v3
with:
timeout_minutes: 5
max_attempts: 2
retry_wait_seconds: 10
command: |
cd src-tauri/tests/fixtures/sftp-rsync
docker compose -f docker-compose.password.yml up -d --build
- name: Wait for password fixture SSH
run: |
for i in $(seq 1 20); do
if sshpass -p testpass ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o BatchMode=no \
-o PreferredAuthentications=password \
-o PubkeyAuthentication=no \
-o ConnectTimeout=2 \
-p 2223 testuser@127.0.0.1 'true' 2>/dev/null; then
echo "Password fixture SSH ready after $((i * 2))s"
exit 0
fi
echo "Waiting for password fixture SSH... ($i/20)"
sleep 2
done
echo "Password fixture did not come up within 40s; dumping logs" >&2
docker logs aeroftp-delta-sync-fixture-password >&2 || true
exit 1
- name: Offline hard-rejection contract
working-directory: src-tauri
# Non-ignored offline pins: no fixture needed but we run them
# here too so a change that breaks the string contract without
# touching the key-auth lane's paths is still caught.
run: |
cargo test --test integration_delta_sync -- \
hard_rejection_string_contract_is_pinned_offline \
hard_error_branch_runs_before_classic_fallback_in_bivio \
--nocapture
- name: "Fallback integration test: password-only fixture"
working-directory: src-tauri
run: |
cargo test --test integration_delta_sync -- \
--ignored \
product_path_falls_through_silently_when_session_not_eligible \
--nocapture
- name: Dump fixture logs on failure
if: failure()
working-directory: src-tauri/tests/fixtures/sftp-rsync
run: |
docker logs aeroftp-delta-sync-fixture-password || true
docker compose -f docker-compose.password.yml ps
- name: Teardown fixture
if: always()
working-directory: src-tauri/tests/fixtures/sftp-rsync
run: docker compose -f docker-compose.password.yml down -v
windows-native:
# PR-T11: validate the cross-OS surgical gate on Windows.
# Since v3.6.1 `aerorsync` is in the default feature set,
# so the "default features" matrix entry is the same as
# "--features aerorsync". The two meaningful matrix entries
# are now:
# - default (native prototype on): the shipping configuration
# - `--no-default-features`: the classic-only fallback path; on
# Windows this must compile to a `delta_transport() -> None`
# surface so the consumer drops silently to plain SFTP.
# No live fixture on Windows: the CI image cannot reach a Linux rsync
# server and the native prototype's live probe is covered by the
# aerorsync-protocol.yml lane against the Linux fixture.
name: Windows cross-OS build + native unit tests
runs-on: windows-latest
# `windows-latest` is slower than ubuntu-latest by ~2x for MSVC
# link steps on the large lib target; the single-config run used
# to fit in 20 min but the v3.6.1 default-feature change doubled
# the amount of code the test binary pulls in. 40 min is the new
# comfortable ceiling; will be tightened again after pipeline
# caching stabilises across a few more runs.
timeout-minutes: 40
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Install Rust (stable, msvc)
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
toolchain: stable
targets: x86_64-pc-windows-msvc
- name: Rust cache
uses: swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2
with:
workspaces: './src-tauri -> target'
shared-key: delta-sync-windows
# Compile-surface gate for the classic-only fallback path:
# `--no-default-features` turns `aerorsync` off, and on
# Windows the binary-rsync transport is also gated out. The only
# thing that should survive on this path is
# `SftpProvider::delta_transport() -> None`, which the consumer
# treats as "drop to plain SFTP silently". Regression here means
# the surgical `#[cfg(unix)]` gate has leaked a Unix-only symbol
# back into the cross-OS surface.
- name: cargo check (--no-default-features, classic-only fallback)
working-directory: src-tauri
run: cargo check --locked --no-default-features
# Compile-surface gate for the shipping configuration (default
# features, which include `aerorsync`). This confirms
# the native rsync driver, the type layer
# (`RsyncCapability`/`RsyncConfig`/`RsyncError`/`RsyncStats`),
# the cross-platform adapter, and `SftpProvider::delta_transport()`
# all build cleanly under MSVC with the feature on.
- name: "cargo check (default features: shipping configuration)"
working-directory: src-tauri
run: cargo check --locked --all-targets
# Note on the test binary: a full `cargo test --lib` on Windows
# requires the whole lib-test link closure, which pulls in
# `whisper-rs-sys` (STT for Linux/Windows, excluded on macOS).
# `whisper-rs-sys` link-time symbols against the MSVC import
# library stubs (`__imp_rand`, `__imp__aligned_malloc`,
# `__imp_expm1f`, `__imp_fmaxf`, `__imp_erff`, etc.) do not
# resolve cleanly in the `cargo test` profile today (a known
# issue with the vendored ggml sources' CRT import descriptors
# under recent MSVC toolchains). The cross-platform unit tests
# we actually care about for PR-T11 (delta_sync_rsync
# eligibility probes, rsync_output parsing, native prototype
# encoders, ndx round-trips) are executed by the
# aerorsync-protocol.yml lane and by the Linux integration
# job above. Adding a Windows-side test runner is tracked as a
# follow-up to harden whisper-rs-sys MSVC linkage separately
# from the release gate.