Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b06ee0f
docs(issues): prefix 1525-08 spec with issue number
josecelano May 1, 2026
cd665bf
docs(issues): update 1723-1525-08 spec with user answers and implemen…
josecelano May 1, 2026
a0f9c00
feat(tracker-core): add PostgreSQL database driver
josecelano May 1, 2026
15af1e0
fix(tracker-core): correct postgres key timestamp column
josecelano May 1, 2026
54210f3
ci(testing): add postgres compatibility job
josecelano May 1, 2026
74f5c8a
feat(ci): extend qBittorrent E2E runner with MySQL and PostgreSQL
josecelano May 1, 2026
e0d0a87
fix(tracker-core): wait for single postgres ready log in benchmark ru…
josecelano May 1, 2026
aee2efb
docs(tracker-core): add 2026-05-01 benchmark run with PostgreSQL base…
josecelano May 1, 2026
248df3d
ci(container): isolate compose build paths from storage
josecelano May 1, 2026
b0a654e
chore(repo): remove legacy compose file references
josecelano May 1, 2026
3ef0707
docs(containers): document PostgreSQL runtime configuration
josecelano May 1, 2026
3c9264c
docs(issues): mark task 9 complete in 1723 spec
josecelano May 1, 2026
517b42e
ci(db-compatibility): extract database compatibility workflow
josecelano May 1, 2026
8fb55e9
ci(db-benchmarking): add persistence benchmark smoke workflow
josecelano May 1, 2026
87d458c
docs(readme): add workflow badges for db-compatibility and db-benchma…
josecelano May 1, 2026
661bbd9
ci(os-compatibility): extract build matrix into dedicated workflow
josecelano May 1, 2026
33e5820
ci(testing): collapse matrix jobs into test-nightly and test-stable
josecelano May 1, 2026
40ed669
chore(issues): archive closed issue specs to docs/issues/closed
josecelano May 1, 2026
51998dd
fix(postgres): address Copilot PR review suggestions
josecelano May 1, 2026
245e6a3
ci(testing): collapse stable and nightly into matrix job
josecelano May 1, 2026
735fe19
ci(testing): normalize sqlite qBittorrent e2e invocation
josecelano May 1, 2026
453dd48
ci(testing): split unit checks and merge docker e2e flow
josecelano May 1, 2026
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
75 changes: 40 additions & 35 deletions .github/skills/dev/planning/cleanup-completed-issues/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
---
name: cleanup-completed-issues
description: Guide for cleaning up completed and closed issues in the torrust-tracker project. Covers removing issue documentation files from docs/issues/ and committing the cleanup. Supports single issue cleanup or batch cleanup. Use when cleaning up closed issues, removing issue docs, or maintaining the docs/issues/ folder. Triggers on "cleanup issue", "remove issue", "clean completed issues", "delete closed issue", or "maintain issue docs".
description: Guide for cleaning up completed and closed issues in the torrust-tracker project. Covers moving closed issue documentation files from docs/issues/ to docs/issues/closed/ and eventually deleting them. Supports single issue cleanup or batch cleanup. Use when cleaning up closed issues, archiving issue docs, or maintaining the docs/issues/ folder. Triggers on "cleanup issue", "archive issue", "move closed issue", "clean completed issues", "delete closed issue", or "maintain issue docs".
metadata:
author: torrust
version: "1.0"
version: "1.1"
---

# Cleaning Up Completed Issues

## When to Clean Up
## Two-Stage Lifecycle

- **After PR merge**: Remove the issue file when its PR is merged
- **Batch cleanup**: Periodically clean up multiple closed issues during maintenance
- **Before releases**: Tidy documentation before major releases
Closed issue specs are **not deleted immediately**. They go through a two-stage lifecycle:

## Cleanup Approaches
1. **Stage 1 — Archive**: When an issue is closed, move its spec file from `docs/issues/` to
`docs/issues/closed/`. The file stays here as a reference buffer while adjacent issues are
still in progress.
2. **Stage 2 — Delete**: Once the spec is no longer referenced by active work (typically after
the next one or two related issues are also closed), delete it permanently.

### Option 1: Single Issue Cleanup (Recommended)
See [`docs/issues/closed/README.md`](../../../../docs/issues/closed/README.md) for the purpose
of the buffer folder.

1. Verify the issue is closed on GitHub
2. Remove the issue file from `docs/issues/`
3. Commit and push changes
## When to Archive (Stage 1)

### Option 2: Batch Cleanup
- **After PR merge**: Move the issue file when its PR is merged and the issue is closed.
- **Batch archive**: Periodically move multiple closed issue files during maintenance.
- **Before releases**: Tidy `docs/issues/` before major releases.

1. List all issue files in `docs/issues/`
2. Check status of each issue on GitHub
3. Remove all closed issue files
4. Commit and push with a descriptive message
## When to Delete (Stage 2)

- The spec is no longer referenced by any open issue or active work.
- The related issue series has progressed far enough that the context is no longer needed.

## Step-by-Step Process

Expand All @@ -36,7 +39,7 @@ metadata:
**Single issue:**

```bash
gh issue view {issue-number} --json state --jq .state
gh issue view {issue-number} --repo torrust/torrust-tracker --json state --jq .state
```

Expected: `CLOSED`
Expand All @@ -45,44 +48,46 @@ Expected: `CLOSED`

```bash
for issue in 21 22 23 24; do
state=$(gh issue view "$issue" --json state --jq .state 2>/dev/null || echo "NOT_FOUND")
echo "$issue:$state"
state=$(gh issue view "$issue" --repo torrust/torrust-tracker --json state --jq .state 2>/dev/null || echo "NOT_FOUND")
echo "$issue: $state"
done
```

### Step 2: Remove Issue Documentation File
### Step 2: Move Issue File to `docs/issues/closed/`

```bash
# Single issue
git rm docs/issues/42-add-peer-expiry-grace-period.md
git mv docs/issues/42-add-peer-expiry-grace-period.md docs/issues/closed/

# Batch
git rm docs/issues/21-some-old-issue.md \
docs/issues/22-another-old-issue.md
git mv docs/issues/21-some-old-issue.md \
docs/issues/22-another-old-issue.md \
docs/issues/closed/
```

### Step 3: Commit and Push

```bash
# Single issue
git commit -S -m "chore(issues): remove closed issue #42 documentation"
git commit -S -m "chore(issues): archive closed issue #42 spec to docs/issues/closed"

# Batch
git commit -S -m "chore(issues): remove documentation for closed issues #21, #22, #23"
git commit -S -m "chore(issues): archive closed issue specs #21, #22, #23 to docs/issues/closed"

git push {your-fork-remote} {branch}
```

## Determining If an Issue File Should Stay

Keep issue files when:
### Step 4 (Stage 2): Delete When No Longer Needed

- The issue is still open
- The PR is open (still being worked on)
- The specification is referenced from other active docs
```bash
git rm docs/issues/closed/42-add-peer-expiry-grace-period.md
git commit -S -m "chore(issues): remove closed issue #42 spec (no longer referenced)"
```

Remove issue files when:
## Determining File Placement

- The issue is **closed**
- The implementing PR is **merged**
- The file is no longer referenced by active work
| Condition | Action |
| --------------------------------------- | ----------------------------- |
| Issue still open | Keep in `docs/issues/` |
| Issue closed, related work still active | Move to `docs/issues/closed/` |
| Issue closed, no longer referenced | Delete permanently |
27 changes: 26 additions & 1 deletion .github/workflows/container.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,32 @@ jobs:

- id: compose
name: Compose
run: docker compose build
run: |
QBT_E2E_WORKDIR="${RUNNER_TEMP}/qbt-e2e-compose-build"
mkdir -p "${QBT_E2E_WORKDIR}/tracker-storage"
mkdir -p "${QBT_E2E_WORKDIR}/seeder-config"
mkdir -p "${QBT_E2E_WORKDIR}/seeder-downloads"
mkdir -p "${QBT_E2E_WORKDIR}/leecher-config"
mkdir -p "${QBT_E2E_WORKDIR}/leecher-downloads"
mkdir -p "${QBT_E2E_WORKDIR}/shared"

export QBT_E2E_TRACKER_IMAGE=torrust-tracker:local
export QBT_E2E_QBITTORRENT_IMAGE=ghcr.io/linuxserver/qbittorrent:latest
export QBT_E2E_TRACKER_CONFIG_PATH=./share/default/config/tracker.container.sqlite3.toml
export QBT_E2E_TRACKER_STORAGE_PATH="${QBT_E2E_WORKDIR}/tracker-storage"
export QBT_E2E_TRACKER_HTTP_TRACKER_PORT=7070
export QBT_E2E_TRACKER_UDP_PORT=6969
export QBT_E2E_TRACKER_HTTP_API_PORT=1212
export QBT_E2E_TRACKER_HEALTH_CHECK_API_PORT=1313
export QBT_E2E_SEEDER_CONFIG_PATH="${QBT_E2E_WORKDIR}/seeder-config"
export QBT_E2E_SEEDER_DOWNLOADS_PATH="${QBT_E2E_WORKDIR}/seeder-downloads"
export QBT_E2E_LEECHER_CONFIG_PATH="${QBT_E2E_WORKDIR}/leecher-config"
export QBT_E2E_LEECHER_DOWNLOADS_PATH="${QBT_E2E_WORKDIR}/leecher-downloads"
export QBT_E2E_SHARED_PATH="${QBT_E2E_WORKDIR}/shared"

docker compose -f compose.qbittorrent-e2e.sqlite3.yaml build
docker compose -f compose.qbittorrent-e2e.mysql.yaml build
docker compose -f compose.qbittorrent-e2e.postgresql.yaml build

context:
name: Context
Expand Down
78 changes: 78 additions & 0 deletions .github/workflows/db-benchmarking.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Database Benchmarking

on:
push:
pull_request:

env:
CARGO_TERM_COLOR: always

jobs:
persistence-benchmark-sqlite3:
name: Persistence Benchmark SQLite3
runs-on: ubuntu-latest

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

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

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

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

persistence-benchmark-mysql:
name: Persistence Benchmark MySQL
runs-on: ubuntu-latest

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

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

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

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

persistence-benchmark-postgresql:
name: Persistence Benchmark PostgreSQL
runs-on: ubuntu-latest

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

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

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

- id: benchmark
name: Run Persistence Benchmark (PostgreSQL)
run: cargo run -p bittorrent-tracker-core --bin persistence_benchmark_runner -- --driver postgresql --db-version 17 --ops 10
69 changes: 69 additions & 0 deletions .github/workflows/db-compatibility.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Database Compatibility

on:
push:
pull_request:

env:
CARGO_TERM_COLOR: always

jobs:
database-compatibility-mysql:
name: Database Compatibility MySQL (${{ matrix.mysql-version }})
runs-on: ubuntu-latest

strategy:
matrix:
mysql-version: ["8.0", "8.4"]

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

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

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

- id: database
name: Run Database Compatibility Test
env:
TORRUST_TRACKER_CORE_RUN_MYSQL_DRIVER_TEST: "true"
TORRUST_TRACKER_CORE_MYSQL_DRIVER_IMAGE_TAG: ${{ matrix.mysql-version }}
run: cargo test -p bittorrent-tracker-core --features db-compatibility-tests run_mysql_driver_tests -- --nocapture

database-compatibility-postgres:
name: Database Compatibility PostgreSQL (${{ matrix.postgres-version }})
runs-on: ubuntu-latest

strategy:
matrix:
postgres-version: ["14", "15", "16", "17"]

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

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

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

- id: database
name: Run Database Compatibility Test
env:
TORRUST_TRACKER_CORE_RUN_POSTGRES_DRIVER_TEST: "true"
TORRUST_TRACKER_CORE_POSTGRES_DRIVER_IMAGE_TAG: ${{ matrix.postgres-version }}
run: cargo test -p bittorrent-tracker-core --features db-compatibility-tests run_postgres_driver_tests -- --nocapture
31 changes: 31 additions & 0 deletions .github/workflows/os-compatibility.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: OS Compatibility

on:
push:
pull_request:

env:
CARGO_TERM_COLOR: always

jobs:
build:
name: Build on ${{ matrix.os }} (${{ matrix.toolchain }})
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
toolchain: [nightly, stable]

steps:
- name: Checkout code
uses: actions/checkout@v6

- id: setup
name: Setup Toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.toolchain }}

- name: Build project
run: cargo build --verbose
Loading