Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
1c34026
docs(issues): rename 1525-02 spec for issue 1706
josecelano Apr 22, 2026
55ef63a
feat(qbittorrent-e2e): add --keep-containers flag and fix race condit…
josecelano Apr 22, 2026
2885f0b
test(qbittorrent-e2e): verify leecher completion and update troublesh…
josecelano Apr 22, 2026
d154153
fix(qbittorrent-e2e): address PR review feedback
josecelano Apr 22, 2026
24061f5
docs(skills): add PR review thread workflows
josecelano Apr 22, 2026
6f8959d
docs(agents): clarify linter command usage
josecelano Apr 22, 2026
a5f7a23
refactor(qbittorrent-e2e): extract bencode helpers
josecelano Apr 22, 2026
cc6ce0b
refactor(qbittorrent-e2e): extract single-client initialization
josecelano Apr 22, 2026
231b1ee
refactor(qbittorrent-e2e): extract single-client torrent upload
josecelano Apr 22, 2026
abdfc29
refactor(qbittorrent-e2e): extract single-client torrent counting
josecelano Apr 22, 2026
293d591
refactor(qbittorrent-e2e): extract workspace module
josecelano Apr 22, 2026
8e4341d
refactor(qbittorrent-e2e): move upload label context into qbittorrent…
josecelano Apr 22, 2026
55076cd
refactor(qbittorrent-e2e): extract torrent upload value type
josecelano Apr 22, 2026
086aeec
refactor(qbittorrent-e2e): inline torrent upload helper
josecelano Apr 22, 2026
ddd39e0
refactor(qbittorrent-e2e): move torrent count logic into client
josecelano Apr 22, 2026
757009f
refactor(qbittorrent-e2e): replace path and polling literals with con…
josecelano Apr 22, 2026
a84b53a
refactor(qbittorrent-e2e): add aliases for client pair signatures
josecelano Apr 22, 2026
d0ae4a8
refactor(qbittorrent-e2e): normalize runner role and service naming
josecelano Apr 23, 2026
e1a0bfa
refactor(qbittorrent-e2e): extract transfer flow phase from runner
josecelano Apr 23, 2026
0c6f35a
refactor(qbittorrent-e2e): add reusable poller helper
josecelano Apr 23, 2026
b6c2cfb
refactor(qbittorrent-e2e): extract login candidate helper state
josecelano Apr 23, 2026
c061063
refactor(qbittorrent-e2e): pass initial passwords to login candidates
josecelano Apr 23, 2026
ae1e4c0
refactor(qbittorrent-e2e): use named payload and torrent result
josecelano Apr 23, 2026
50a583b
refactor(qbittorrent-e2e): extract torrent artifact builders
josecelano Apr 23, 2026
20936b8
refactor(qbittorrent-e2e): introduce client role enum
josecelano Apr 23, 2026
fba3fb7
refactor(qbittorrent-e2e): group flow helpers in scenario runner
josecelano Apr 23, 2026
873755b
refactor(qbittorrent-e2e): tidy polling docs and hash formatting
josecelano Apr 23, 2026
11f1929
refactor(qbittorrent-e2e): extract client role module
josecelano Apr 23, 2026
689268c
refactor(qbittorrent-e2e): extract poller module
josecelano Apr 23, 2026
33060e0
refactor(ci): move compose port wait into DockerCompose
josecelano Apr 23, 2026
65f66fb
refactor(qbittorrent-e2e): split run() into ARRANGE and ACT phases
josecelano Apr 23, 2026
95e9fde
refactor(qbittorrent-e2e): extract fixture builders into scenario_ste…
josecelano Apr 23, 2026
d35c80d
refactor(qbittorrent-e2e): extract generic torrent submission and pre…
josecelano Apr 23, 2026
940ffa6
refactor(qbittorrent-e2e): extract login readiness step
josecelano Apr 23, 2026
8c6046a
refactor(qbittorrent-e2e): split login step, extract leecher steps, a…
josecelano Apr 23, 2026
65d9a87
refactor(qbittorrent-e2e): remove redundant add_torrent_file_to_leech…
josecelano Apr 23, 2026
008edb4
refactor(qbittorrent-e2e): group scenario steps into fixtures/ and qb…
josecelano Apr 23, 2026
a9923ba
fix(qbittorrent-e2e): replace log-polling password with injected cred…
josecelano Apr 23, 2026
eaa9202
refactor(qbittorrent-e2e): dissolve ScenarioRunner into free functions
josecelano Apr 23, 2026
d60c6a6
refactor(qbittorrent-e2e): extract service-oriented arrange helpers
josecelano Apr 23, 2026
48c200a
refactor(qbittorrent-e2e): move verify_payload_integrity to scenario_…
josecelano Apr 24, 2026
6477efd
refactor(qbittorrent-e2e): fix verify_payload_integrity signature to …
josecelano Apr 24, 2026
6b597da
refactor(qbittorrent-e2e): remove sha1 from verify_payload_integrity
josecelano Apr 24, 2026
6aefb94
refactor(qbittorrent-e2e): extract QbittorrentConfigBuilder from runner
josecelano Apr 24, 2026
9f996e2
refactor(qbittorrent-e2e): unify qBittorrent upload API
josecelano Apr 24, 2026
bd6e466
refactor(qbittorrent-e2e): delegate tracker image build to docker com…
josecelano Apr 24, 2026
6b09d1a
refactor(qbittorrent-e2e): split initialize_client into three focused…
josecelano Apr 24, 2026
9f13354
refactor(qbittorrent-e2e): extract build_api_clients from run_scenario
josecelano Apr 24, 2026
7cba481
docs(qbittorrent-e2e): add module-level doc comment explaining BDD sc…
josecelano Apr 24, 2026
0808f40
refactor(qbittorrent-e2e): extract scenario into dedicated module
josecelano Apr 24, 2026
83e04d5
refactor(qbittorrent-e2e): reorder run fn body into ARRANGE/ACT/ASSERT
josecelano Apr 24, 2026
6e3b9ef
refactor(qbittorrent-e2e): extract compose stack provisioning into co…
josecelano Apr 24, 2026
b5fe409
refactor(qbittorrent-e2e): rename and extract client builder function…
josecelano Apr 24, 2026
847b452
refactor(qbittorrent-e2e): extract workspace setup into workspace_set…
josecelano Apr 24, 2026
d70a251
refactor(qbittorrent-e2e): rename compose_stack and workspace_setup m…
josecelano Apr 24, 2026
4924f0c
docs(qbittorrent-e2e): add workspace layout tree to filesystem_setup …
josecelano Apr 24, 2026
3769e19
refactor(qbittorrent-e2e): introduce TimingConfig to group polling Du…
josecelano Apr 24, 2026
051047a
refactor(qbittorrent-e2e): introduce TrackerFilesystem to group track…
josecelano Apr 24, 2026
23a41cb
refactor(qbittorrent-e2e): introduce SharedFixtures to group shared f…
josecelano Apr 24, 2026
531f496
refactor(qbittorrent-e2e): introduce PeerConfig to group per-peer fields
josecelano Apr 24, 2026
404c316
refactor(qbittorrent-e2e): extract QbittorrentCredentials from PeerCo…
josecelano Apr 24, 2026
3d596b6
refactor(qbittorrent-e2e): extract TorrentFixture from SharedFixtures
josecelano Apr 24, 2026
6acc115
refactor(qbittorrent-e2e): introduce FileName newtype and types module
josecelano Apr 24, 2026
ae8f49a
refactor(qbittorrent-e2e): introduce ContainerPath newtype for contai…
josecelano Apr 24, 2026
a194860
refactor(qbittorrent-e2e): introduce Deadline and PollInterval newtypes
josecelano Apr 24, 2026
5ed2e78
refactor(qbittorrent-e2e): introduce TorrentState enum for TorrentInfo
josecelano Apr 24, 2026
b4b201f
refactor(qbittorrent-e2e): introduce TorrentProgress newtype
josecelano Apr 24, 2026
dc99841
refactor(qbittorrent-e2e): introduce WebUiBaseUrl for validated base URL
josecelano Apr 24, 2026
a799810
refactor(qbittorrent-e2e): introduce ComposeProjectName newtype
josecelano Apr 24, 2026
cf2faf4
refactor(qbittorrent-e2e): introduce TrackerImage and QbittorrentImag…
josecelano Apr 24, 2026
f643b44
refactor(qbittorrent-e2e): introduce TorrentHash newtype for TorrentI…
josecelano Apr 24, 2026
53e4c2c
refactor(qbittorrent-e2e): introduce PayloadSize and PieceLength newt…
josecelano Apr 24, 2026
7f584d4
refactor(qbittorrent): move torrent state into client module
josecelano Apr 27, 2026
d1dd8b0
refactor(qbittorrent): move torrent progress into client module
josecelano Apr 27, 2026
11fb987
refactor(qbittorrent): split types module and add unit tests
josecelano Apr 27, 2026
09c5c33
refactor(qbittorrent-e2e): rename module and split qbittorrent featur…
josecelano Apr 27, 2026
aaa59b0
refactor(qbittorrent-e2e): pass QbittorrentCredentials to login inste…
josecelano Apr 27, 2026
11c2f2c
ci(testing): add qBittorrent E2E job to testing workflow
josecelano Apr 27, 2026
fd26ad5
refactor(qbittorrent-e2e): replace tracker config template arg with T…
josecelano Apr 27, 2026
d636151
refactor(qbittorrent-e2e): introduce TrackerConfig DTO with typed Soc…
josecelano Apr 27, 2026
c641ef9
chore(qbittorrent-e2e): suppress DevSkim DS137138 warning for test an…
josecelano Apr 27, 2026
841453f
test(qbittorrent-e2e): add unit tests for bencode encoder and torrent…
josecelano Apr 27, 2026
48db166
refactor(qbittorrent-e2e): use InfoHash-based torrent presence checks
josecelano Apr 27, 2026
ad5c076
fix(qbittorrent-e2e): use InfoHash to identify torrent in wait_until_…
josecelano Apr 27, 2026
fcff35f
refactor(qbittorrent-e2e): return domain types directly from setup fu…
josecelano Apr 27, 2026
9c11c91
fix(qbittorrent-e2e): disable DHT, LSD, and PeX in qBittorrent config…
josecelano Apr 27, 2026
4f79bc8
feat(qbittorrent-e2e): verify tracker swarm participation via REST AP…
josecelano Apr 27, 2026
a3ccbc5
refactor(ci): use structured tracing fields in qbittorrent e2e runner
josecelano Apr 27, 2026
19e09b7
test(qbittorrent-e2e): cover transfer over HTTP and UDP
josecelano Apr 27, 2026
18073cf
refactor(qbittorrent-e2e): polish docs and staged test/readability im…
josecelano Apr 28, 2026
a823fa0
ci(testing): merge E2E jobs and rename step IDs
josecelano Apr 28, 2026
6de9fbd
fix(qbittorrent-e2e): pre-seed scenario fixtures before compose startup
josecelano Apr 28, 2026
d9fa45c
fix(qbittorrent-e2e): harden FileName validation and fix WebUI/announ…
josecelano Apr 28, 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
91 changes: 91 additions & 0 deletions .github/skills/dev/pr-reviews/fetch-review-threads/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
name: fetch-review-threads
description: Fetch unresolved GitHub pull request review thread IDs for the torrust-tracker project. Use when asked to find open PR review threads, list unresolved review comments, collect thread IDs before resolving suggestions, or inspect Copilot review feedback. Triggers on "fetch review threads", "list unresolved PR comments", "get review thread IDs", or "find open review suggestions".
metadata:
author: torrust
version: "1.0"
---

# Fetching PR Review Threads

Use this skill before resolving review feedback. Its purpose is to collect the unresolved
review thread IDs and enough context to decide whether each thread should stay open or be closed.

## Preferred Sources

Use one of these approaches:

1. Active pull request tools when they are available in the environment.
2. GitHub CLI GraphQL when you need a terminal-based fallback.

Prefer the active PR tools first because they provide thread metadata together with file paths,
resolution state, and comments.

## What to Collect

For each unresolved thread, capture:

- thread ID
- file path
- `isResolved`
- `canResolve`
- comment author
- comment body

Only unresolved threads should be considered for follow-up work.

## Active PR Tool Workflow

1. Read the active PR.
2. Inspect the `reviewThreads` array.
3. Filter to threads where `isResolved == false`.
4. Group them by file if you plan to address them in code.

## GitHub CLI GraphQL Fallback

Use GitHub CLI if you need to retrieve threads directly from the terminal.

```bash
gh api graphql \
-F owner=torrust \
-F repo=torrust-tracker \
-F pullNumber=1707 \
-f query='query($owner: String!, $repo: String!, $pullNumber: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $pullNumber) {
reviewThreads(first: 100) {
nodes {
id
isResolved
isOutdated
comments(first: 20) {
nodes {
author {
login
}
body
path
}
}
}
}
}
}
}'
```

Then filter for unresolved threads.

## Practical Guidance

- Do not guess thread IDs.
- Do not resolve a thread immediately after fetching it. First confirm the fix exists.
- If a thread is outdated but unresolved, still read it before deciding what to do.
- If there are more than 100 threads, paginate instead of assuming the first page is complete.

## Completion Checklist

- [ ] Unresolved thread IDs were collected from the current PR state
- [ ] Each thread has enough context for triage
- [ ] Already resolved threads were excluded from action items
- [ ] The result is ready to hand off to a fix or resolution workflow
77 changes: 77 additions & 0 deletions .github/skills/dev/pr-reviews/resolve-review-threads/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
name: resolve-review-threads
description: Resolve addressed GitHub pull request review threads for the torrust-tracker project. Use when asked to mark PR suggestions as resolved, resolve review comments, close addressed review threads, or clear Copilot review feedback after fixes are pushed. Triggers on "resolve PR threads", "mark suggestions as resolved", "resolve review comments", or "close addressed review threads".
metadata:
author: torrust
version: "1.0"
---

# Resolving PR Review Threads

Use this skill after the requested code or documentation changes are already implemented,
validated, committed, and pushed.

## Preconditions

- The feedback has actually been addressed in the branch.
- Validation has been run for the touched scope (`linter all`, tests, or a targeted executable check).
- You have the target PR number and unresolved review thread IDs.

Do not resolve a thread just because a suggestion exists. Resolve it only when the underlying
concern is fixed or intentionally declined with a clear reason.

## Workflow

1. Read the active PR and collect unresolved review threads.
2. Group threads by file and confirm each one is truly addressed.
3. Implement and validate any missing fixes before resolving anything.
4. Resolve the addressed threads.
5. Re-check the PR state if needed.

## Preferred Resolution Path

If PR tools are available, first gather thread IDs from the active pull request metadata.

- Use the active PR tools to identify unresolved `reviewThreads`.
- Resolve only threads where `isResolved == false` and the fix is already on the branch.

## GitHub CLI GraphQL Command

Use GitHub CLI GraphQL when you need to resolve a thread directly from the terminal:

```bash
gh api graphql \
-F threadId=THREAD_ID \
-f query='mutation($threadId: ID!) { resolveReviewThread(input: { threadId: $threadId }) { thread { isResolved } } }'
```

Successful output should report `isResolved: true`.

## Batch Pattern

For multiple threads, resolve them one by one and check each result:

```bash
for thread_id in \
THREAD_ID_1 \
THREAD_ID_2
do
gh api graphql \
-F threadId="$thread_id" \
-f query='mutation($threadId: ID!) { resolveReviewThread(input: { threadId: $threadId }) { thread { isResolved } } }'
done
```

## Notes

- Thread IDs are GraphQL node IDs, not PR numbers or comment IDs.
- This resolves the review thread, not the entire review.
- If a thread should remain open, leave it open and explain why.
- If you do not know the thread IDs yet, query the active PR first instead of guessing.

## Completion Checklist

- [ ] All targeted threads were verified against the current branch state
- [ ] Validation passed before resolution
- [ ] Each resolved mutation returned `isResolved: true`
- [ ] Any intentionally unresolved feedback is documented with reasoning
14 changes: 10 additions & 4 deletions .github/workflows/testing.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -168,27 +168,33 @@ jobs:
name: E2E
runs-on: ubuntu-latest
needs: database-compatibility
timeout-minutes: 45

strategy:
matrix:
toolchain: [nightly, stable]

steps:
- id: setup
- id: setup-e2e-toolchain
name: Setup Toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.toolchain }}
components: llvm-tools-preview

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

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

- id: test
- id: run-tracker-e2e-tests
name: Run E2E Tests
run: cargo run --bin e2e_tests_runner -- --config-toml-path "./share/default/config/tracker.e2e.container.sqlite3.toml"

- id: run-qbittorrent-e2e-test
if: matrix.toolchain == 'stable'
name: Run qBittorrent E2E Test
run: cargo run --bin qbittorrent_e2e_runner -- --compose-file ./compose.qbittorrent-e2e.yaml --timeout-seconds 600
Comment thread
josecelano marked this conversation as resolved.
13 changes: 13 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,19 @@ See [docs/benchmarking.md](docs/benchmarking.md) and [docs/profiling.md](docs/pr
The project uses the `linter` binary from
[torrust/torrust-linting](https://github.com/torrust/torrust-linting).

Agent reminder:

- When asked to lint, prefer loading the `run-linters` skill at
`.github/skills/dev/git-workflow/run-linters/SKILL.md`.
- Start with `linter all`.
- To lint only markdown files, run `linter markdown`.
- To isolate a failing tool, run the individual linters directly:
`linter markdown`, `linter yaml`, `linter toml`, `linter cspell`, `linter clippy`,
`linter rustfmt`, `linter shellcheck`.
- If `linter all` fails or appears inconclusive, use the individual commands above before editing
files so the failing linter is explicit.
- Treat `linter all` passing with exit code `0` as the required pre-commit gate.

```sh
# Install the linter binary
cargo install --locked --git https://github.com/torrust/torrust-linting --bin linter
Expand Down
Loading