name: Integration Tests with Docker Mixnet
on:
pull_request:
branches: [ main, master, update_python_pigeonhole ]
jobs:
test-integration-docker:
permissions:
contents: read
packages: write
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout thinclient repository
uses: actions/checkout@v4
with:
path: thinclient
- name: Checkout katzenpost repository
uses: actions/checkout@v4
with:
repository: katzenpost/katzenpost
ref: d5a6349a34c4a2d4bca587f4be86ce92f2873b12 path: katzenpost
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Cache Docker layers
uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Configure podman socket
run: |
systemctl --user start podman.socket
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Set up Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
- name: Install thinclient dependencies
run: |
cd thinclient
python -m pip install --upgrade pip
pip install -e '.[test]'
- name: Log in to GitHub Container Registry
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
echo "${{ secrets.GITHUB_TOKEN }}" | podman login ghcr.io -u "${{ github.actor }}" --password-stdin || true
- name: Build and start the mixnet
run: |
cd katzenpost/docker && make start wait
- name: Brief pause to ensure mixnet is fully ready
run: sleep 30
- name: Detect pigeonhole-cp-relevant changes
id: smoke_filter
uses: dorny/paths-filter@v3
with:
working-directory: thinclient
filters: |
smoke:
- 'src/bin/**'
- 'src/persistent/**'
- 'src/pigeonhole.rs'
- 'src/core.rs'
- 'tests/smoke_pigeonhole_cp.rs'
- 'Cargo.toml'
- 'Cargo.lock'
- name: Run Python and Rust integration tests in parallel
id: parallel-tests
timeout-minutes: 60
run: |
cd thinclient
# Run Python tests in background.
python -m pytest tests/ \
-vvv -s --tb=short --timeout=1200 -n 3 \
--durations=25 \
> /tmp/python-test-output.txt 2>&1 &
PYTHON_PID=$!
# Run Rust tests in background
cargo test --test '*' -- --nocapture --test-threads=3 \
> /tmp/rust-test-output.txt 2>&1 &
RUST_PID=$!
# Wait for both and capture exit codes
PYTHON_RC=0
RUST_RC=0
wait $PYTHON_PID || PYTHON_RC=$?
wait $RUST_PID || RUST_RC=$?
# Print outputs
echo "=== Python test output ==="
cat /tmp/python-test-output.txt
echo ""
echo "=== Rust test output ==="
cat /tmp/rust-test-output.txt
echo ""
# Report results
echo "Python tests exit code: $PYTHON_RC"
echo "Rust tests exit code: $RUST_RC"
# Fail if either failed
if [ $PYTHON_RC -ne 0 ] || [ $RUST_RC -ne 0 ]; then
exit 1
fi
- name: Run pigeonhole-cp smoke test
if: steps.smoke_filter.outputs.smoke == 'true'
timeout-minutes: 10
run: |
cd thinclient
cargo test --features cli --test smoke_pigeonhole_cp -- --nocapture
- name: Capture kpclientd container logs
if: always()
run: |
if [ ! -d katzenpost/docker/voting_mixnet ]; then
echo "voting_mixnet directory absent; the mixnet never started, nothing to capture"
exit 0
fi
cd katzenpost/docker/voting_mixnet
DOCKER_HOST="unix://$XDG_RUNTIME_DIR/podman/podman.sock" \
podman compose logs --no-color --no-log-prefix kpclientd \
> kpclientd.log 2>&1 || true
- name: Stop the mixnet
if: always()
run: |
cd katzenpost/docker && make stop
- name: Upload testnet state
uses: actions/upload-artifact@v4
if: always()
with:
name: mixnet-${{ github.run_id }}-${{ github.job }}
path: |
katzenpost/docker/voting_mixnet/*/*.log
katzenpost/docker/voting_mixnet/kpclientd.log
katzenpost/docker/voting_mixnet/servicenode*/courier/*.log