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
85 changes: 76 additions & 9 deletions .github/workflows/container.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,61 @@ env:

jobs:
test:
# Builds the container image and runs E2E tests against it before any publish step.
# "release" here is the Containerfile stage name (Cargo release profile: opt-level 3, fat LTO).
#
# Unit tests run inside the Containerfile build itself (via `cargo nextest run` in the `test`
# stage, using `rust:slim-trixie` as the tester base image). Note: this environment differs
# from the production runtime (`distroless/cc-debian13`); the unit tests do not prove the
# binary works in distroless — that is covered by the E2E steps below. The in-container
# unit tests validate the compiled binary in the build pipeline before it enters the runtime
# stage, and share the same Debian trixie glibc as the production image. See ADR
# 20260603000000_keep_unit_tests_inside_container_build.md.
#
# Cache flow: the `build` step writes the BuildKit layer cache to the `container-release`
# GHA scope (mode=max, all intermediate layers). The publish_development and publish_release
# jobs read from this scope first, so they get a cache hit and avoid a full rebuild when
# running on the same commit. The cache is written during `docker build`, before the E2E
# steps below, so it is available to publish jobs even if E2E tests fail (though in that
# case the publish jobs are blocked anyway by the `needs: test` dependency chain).
#
# When this workflow runs (push to develop/main/releases, PR targeting develop/main),
# the docker-e2e job in testing.yaml is skipped to avoid running the same E2E suite twice.
# For feature branch pushes where this workflow does not trigger, testing.yaml provides
# equivalent coverage. See issue #1854.
name: Test (Docker)
runs-on: ubuntu-latest
timeout-minutes: 90

strategy:
matrix:
target: [debug, release]
target: [release]

steps:
- id: checkout
name: Checkout Repository
uses: actions/checkout@v6

- id: setup
name: Setup Toolchain
- id: setup-buildx
name: Setup Buildx
uses: docker/setup-buildx-action@v4

- id: setup-toolchain
name: Setup Toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable

- id: cache
name: Enable Job Cache
uses: Swatinem/rust-cache@v2

- id: fetch
name: Download Dependencies
run: cargo fetch --verbose

- id: build
name: Build
name: Build Tracker Image
uses: docker/build-push-action@v7
with:
file: ./Containerfile
Expand All @@ -52,9 +89,24 @@ jobs:
cache-from: type=gha,scope=container-${{ matrix.target }}
cache-to: type=gha,scope=container-${{ matrix.target }},mode=max

- id: inspect
name: Inspect
run: docker image inspect torrust-tracker:local
- id: run-tracker-e2e-tests
name: Run E2E Tests
run: >-
cargo run -p torrust-tracker-e2e-tools --bin e2e_tests_runner
-- --config-toml-path "./share/default/config/tracker.e2e.container.sqlite3.toml"
--tracker-image "torrust-tracker:local" --skip-build

- id: run-qbittorrent-e2e-test-sqlite3
name: Run qBittorrent E2E Test (SQLite)
run: cargo run -p torrust-tracker-e2e-tools --bin qbittorrent_e2e_runner -- --tracker-image "torrust-tracker:local" --skip-build --db-driver sqlite3 --timeout-seconds 600

- id: run-qbittorrent-e2e-test-mysql
name: Run qBittorrent E2E Test (MySQL)
run: cargo run -p torrust-tracker-e2e-tools --bin qbittorrent_e2e_runner -- --tracker-image "torrust-tracker:local" --skip-build --db-driver mysql --timeout-seconds 600

- id: run-qbittorrent-e2e-test-postgresql
name: Run qBittorrent E2E Test (PostgreSQL)
run: cargo run -p torrust-tracker-e2e-tools --bin qbittorrent_e2e_runner -- --tracker-image "torrust-tracker:local" --skip-build --db-driver postgresql --timeout-seconds 600

context:
name: Context
Expand Down Expand Up @@ -109,6 +161,12 @@ jobs:
fi

publish_development:
# Publishes a Docker Hub image tagged with the branch name (e.g. "develop").
# "Development" here means "built from a development branch, not a versioned release" —
# it is not the Cargo dev profile. Both publish jobs always use `target: release`
# (the optimized Containerfile stage) because Docker Hub images must be production-grade
# binaries regardless of whether they originate from develop or a release branch.
# The Cargo release profile (opt-level 3, fat LTO) applies in both cases.
name: Publish (Development)
environment: dockerhub-torrust
needs: context
Expand Down Expand Up @@ -148,7 +206,12 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
target: release
cache-from: type=gha,scope=container-publish-dev
# Read from the test job's cache first (container-release scope) so that when
# the test and publish jobs run on the same commit the publish step gets a
# cache hit and avoids a full rebuild. Falls back to the publish-specific scope.
cache-from: |
type=gha,scope=container-release
type=gha,scope=container-publish-dev
cache-to: type=gha,scope=container-publish-dev,mode=max

publish_release:
Expand Down Expand Up @@ -194,5 +257,9 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
target: release
cache-from: type=gha,scope=container-publish-release
# Read from the test job's cache first (container-release scope) for the same
# reason as publish_development above.
cache-from: |
type=gha,scope=container-release
type=gha,scope=container-publish-release
cache-to: type=gha,scope=container-publish-release,mode=max
13 changes: 7 additions & 6 deletions .github/workflows/db-benchmarking.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
name: Database Benchmarking

# Path policy: run this workflow only for persistence-relevant changes.
# Scoped intentionally to tracker-core — the benchmarks exercise the
# persistence layer directly. General compile/cross-package regressions
# are covered by the Testing workflow.
# Scoped to tracker-core (persistence layer) and persistence-benchmark (runner).
# General compile/cross-package regressions are covered by the Testing workflow.
# See .github/workflows/docs-lint.yaml for the lightweight docs-only workflow.
on:
push:
paths:
- "packages/tracker-core/**"
- "packages/persistence-benchmark/**"
- ".github/workflows/db-benchmarking.yaml"
pull_request:
paths:
- "packages/tracker-core/**"
- "packages/persistence-benchmark/**"
- ".github/workflows/db-benchmarking.yaml"

env:
Expand Down Expand Up @@ -40,7 +41,7 @@ jobs:

- id: benchmark
name: Run Persistence Benchmark (SQLite3)
run: cargo run -p torrust-tracker-core --bin persistence_benchmark_runner -- --driver sqlite3 --ops 10
run: cargo run -p torrust-tracker-persistence-benchmark --bin persistence_benchmark_runner -- --driver sqlite3 --ops 10

persistence-benchmark-mysql:
name: Persistence Benchmark MySQL
Expand All @@ -63,7 +64,7 @@ jobs:

- id: benchmark
name: Run Persistence Benchmark (MySQL)
run: cargo run -p torrust-tracker-core --bin persistence_benchmark_runner -- --driver mysql --db-version 8.4 --ops 10
run: cargo run -p torrust-tracker-persistence-benchmark --bin persistence_benchmark_runner -- --driver mysql --db-version 8.4 --ops 10

persistence-benchmark-postgresql:
name: Persistence Benchmark PostgreSQL
Expand All @@ -86,4 +87,4 @@ jobs:

- id: benchmark
name: Run Persistence Benchmark (PostgreSQL)
run: cargo run -p torrust-tracker-core --bin persistence_benchmark_runner -- --driver postgresql --db-version 17 --ops 10
run: cargo run -p torrust-tracker-persistence-benchmark --bin persistence_benchmark_runner -- --driver postgresql --db-version 17 --ops 10
12 changes: 12 additions & 0 deletions .github/workflows/testing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,21 @@ jobs:
run: cargo test --tests --benches --examples --workspace --all-targets --all-features

docker-e2e:
# Skip this job when container.yaml is also running for the same event — it builds
# the same image and runs the same E2E tests. container.yaml triggers on pushes to
# develop/main/releases and on PRs targeting develop/main.
# For feature branch pushes and PRs targeting other branches, container.yaml does not
# run, so this job provides the only E2E coverage. See issue #1854.
name: Docker E2E
runs-on: ubuntu-latest
timeout-minutes: 90
if: >-
!(github.event_name == 'pull_request' &&
(github.base_ref == 'develop' || github.base_ref == 'main')) &&
!(github.event_name == 'push' &&
(github.ref == 'refs/heads/develop' ||
github.ref == 'refs/heads/main' ||
startsWith(github.ref, 'refs/heads/releases/')))

steps:
- id: checkout
Expand Down
28 changes: 26 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ torrust-tracker-test-helpers = { version = "3.0.0-develop", path = "packages/tes
members = [
"console/tracker-client",
"contrib/dev-tools/analysis/workspace-coupling",
"packages/e2e-tools",
"packages/net-primitives",
"packages/persistence-benchmark",
"packages/torrent-repository-benchmarking",
]

Expand Down
58 changes: 43 additions & 15 deletions Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,23 @@ WORKDIR /build/src
COPY Cargo.toml Cargo.lock ./
COPY console/tracker-client/Cargo.toml console/tracker-client/
COPY contrib/bencode/Cargo.toml contrib/bencode/
# workspace-coupling and torrust-tracker-torrent-repository-benchmarking are
# excluded from cargo nextest archive (see Cook and Build stages below), but
# their Cargo.toml manifests and stub source files must still be present here
# The following packages are excluded from cargo nextest archive (see Cook and
# Build stages below) because they are not part of the production tracker service
# and do not need to be tested inside the container image:
# - workspace-coupling (analysis/coupling tool, no production value)
# - torrust-tracker-torrent-repository-benchmarking (benchmarking only)
# - torrust-tracker-client (CLI dev tools: tracker_client, tracker_checker, etc.)
# - torrust-tracker-contrib-bencode (contrib utility; its own tests/bins are not needed in the container)
# - torrust-tracker-e2e-tools (E2E runners + profiling tool, GHA host-only)
Comment thread
josecelano marked this conversation as resolved.
# - torrust-tracker-persistence-benchmark (persistence layer dev benchmarking tool)
# Their Cargo.toml manifests and stub source files must still be present here
# because `cargo chef prepare` uses `cargo metadata` internally to enumerate
# all workspace members, and `cargo metadata` aborts if any member's manifest
# or declared target file is missing. `cargo chef prepare` has no `--exclude`
# flag (only `--bin`), so these stubs cannot be omitted from the recipe stage.
COPY contrib/dev-tools/analysis/workspace-coupling/Cargo.toml contrib/dev-tools/analysis/workspace-coupling/
COPY packages/e2e-tools/Cargo.toml packages/e2e-tools/
COPY packages/persistence-benchmark/Cargo.toml packages/persistence-benchmark/
COPY packages/axum-health-check-api-server/Cargo.toml packages/axum-health-check-api-server/
COPY packages/axum-http-server/Cargo.toml packages/axum-http-server/
COPY packages/axum-rest-api-server/Cargo.toml packages/axum-rest-api-server/
Expand Down Expand Up @@ -104,6 +113,8 @@ COPY packages/udp-tracker-core/Cargo.toml packages/udp-tracker-core/
# stub lines below AND the Cargo.toml COPY line in the manifest-only block above.
RUN mkdir -p \
src/bin \
packages/e2e-tools/src/bin \
packages/persistence-benchmark/src/bin \
contrib/bencode/src \
contrib/bencode/benches \
contrib/dev-tools/analysis/workspace-coupling/src \
Expand Down Expand Up @@ -133,7 +144,6 @@ RUN mkdir -p \
packages/torrent-repository-benchmarking/benches \
packages/tracker-client/src \
packages/tracker-core/src \
packages/tracker-core/src/bin \
packages/udp-protocol/src \
packages/udp-server/src \
packages/udp-server/examples \
Expand All @@ -142,10 +152,11 @@ RUN mkdir -p \
&& touch \
src/lib.rs \
src/main.rs \
src/bin/e2e_tests_runner.rs \
src/bin/http_health_check.rs \
src/bin/profiling.rs \
src/bin/qbittorrent_e2e_runner.rs \
packages/e2e-tools/src/bin/e2e_tests_runner.rs \
packages/e2e-tools/src/bin/profiling.rs \
packages/e2e-tools/src/bin/qbittorrent_e2e_runner.rs \
packages/persistence-benchmark/src/bin/persistence_benchmark_runner.rs \
contrib/bencode/src/lib.rs \
contrib/bencode/benches/bencode_benchmark.rs \
contrib/dev-tools/analysis/workspace-coupling/src/main.rs \
Expand Down Expand Up @@ -179,7 +190,6 @@ RUN mkdir -p \
packages/torrent-repository-benchmarking/benches/repository_benchmark.rs \
packages/tracker-client/src/lib.rs \
packages/tracker-core/src/lib.rs \
packages/tracker-core/src/bin/persistence_benchmark_runner.rs \
packages/udp-protocol/src/lib.rs \
packages/udp-server/src/lib.rs \
packages/udp-server/examples/udp_only_public_tracker.rs \
Expand All @@ -193,20 +203,26 @@ FROM chef AS dependencies_debug
WORKDIR /build/src
COPY --from=recipe /build/recipe.json /build/recipe.json
# Note: `cargo chef cook` does not support `--exclude` (the cargo-chef CLI only
# exposes `--workspace` and `--package`, not `--exclude`). The two irrelevant
# workspace members (workspace-coupling and torrust-tracker-torrent-repository-
# benchmarking) are therefore still compiled as part of the cook skeleton
# (their Cargo.toml manifests are in the recipe, so cargo-chef cooks them).
# The build-time savings come from the archive/build stages: `cargo nextest
# archive` below is passed `--exclude` so those packages are not compiled from
# real source in the final archive. See Cook (release) and Build stages.
# exposes `--workspace` and `--package`, not `--exclude`). The excluded workspace
# members (workspace-coupling, torrust-tracker-torrent-repository-benchmarking,
# torrust-tracker-client, torrust-tracker-contrib-bencode,
# torrust-tracker-e2e-tools, torrust-tracker-persistence-benchmark) are therefore
# still compiled as part of the cook skeleton (their Cargo.toml manifests are in
# the recipe, so cargo-chef cooks them). The build-time savings come from the
# archive/build stages: `cargo nextest archive` below is passed `--exclude` so
# those packages are not compiled from real source in the final archive. See Cook
# (release) and Build stages.
RUN cargo chef cook --tests --workspace --all-features --recipe-path /build/recipe.json
# Pre-link warm-up: Create and discard a nextest archive to warm up the linker
# before final compilation. This improves incremental build cache efficiency
# by pre-faulting the linker phases, avoiding redundant linking work in later stages.
RUN cargo nextest archive --tests --workspace --all-features \
--exclude workspace-coupling \
--exclude torrust-tracker-torrent-repository-benchmarking \
--exclude torrust-tracker-client \
--exclude torrust-tracker-contrib-bencode \
--exclude torrust-tracker-e2e-tools \
--exclude torrust-tracker-persistence-benchmark \
--archive-file /build/temp.tar.zst && rm -f /build/temp.tar.zst

## Cook (release)
Expand All @@ -221,6 +237,10 @@ RUN cargo chef cook --tests --workspace --all-features --recipe-path /build/reci
RUN cargo nextest archive --tests --workspace --all-features \
--exclude workspace-coupling \
--exclude torrust-tracker-torrent-repository-benchmarking \
--exclude torrust-tracker-client \
--exclude torrust-tracker-contrib-bencode \
--exclude torrust-tracker-e2e-tools \
--exclude torrust-tracker-persistence-benchmark \
--archive-file /build/temp.tar.zst --release && rm -f /build/temp.tar.zst


Expand All @@ -231,6 +251,10 @@ COPY . /build/src
RUN cargo nextest archive --tests --workspace --all-features \
--exclude workspace-coupling \
--exclude torrust-tracker-torrent-repository-benchmarking \
--exclude torrust-tracker-client \
--exclude torrust-tracker-contrib-bencode \
--exclude torrust-tracker-e2e-tools \
--exclude torrust-tracker-persistence-benchmark \
--archive-file /build/torrust-tracker-debug.tar.zst

## Build Archive (release)
Expand All @@ -240,6 +264,10 @@ COPY . /build/src
RUN cargo nextest archive --tests --workspace --all-features \
--exclude workspace-coupling \
--exclude torrust-tracker-torrent-repository-benchmarking \
--exclude torrust-tracker-client \
--exclude torrust-tracker-contrib-bencode \
--exclude torrust-tracker-e2e-tools \
--exclude torrust-tracker-persistence-benchmark \
--archive-file /build/torrust-tracker.tar.zst --release


Expand Down
Loading
Loading