Skip to content

Commit 2fde680

Browse files
committed
chore(msrv): bump workspace rust-version from 1.85 to 1.88
- 1.88 is the minimum floor that avoids `cargo update` regressions on the current lockfile (bollard, tonic, testcontainers, serde_with, time, ureq, etc. all require Rust > 1.85; 1.86 and 1.87 still produce downgrades) - Aligns with torrust-index, which also uses rust-version = "1.88" - Stabilised let_chains (RFC 2679) triggered 5 collapsible_if clippy fixes across tracker-core, udp-tracker-server, and src/console - MSRV policy (app tracks latest stable post-extraction; bittorrent-* libraries keep minimum MSRV for external consumer compatibility) documented in AGENTS.md and issue spec torrust#1787
1 parent e3f6658 commit 2fde680

10 files changed

Lines changed: 99 additions & 65 deletions

File tree

.github/skills/dev/maintenance/setup-dev-environment/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ rustup update # Update to latest stable
3131
rustup toolchain install nightly # Required for docs generation
3232
```
3333

34-
The project MSRV is **1.85**. The nightly toolchain is needed only for
34+
The project MSRV is **1.88**. The nightly toolchain is needed only for
3535
`cargo +nightly doc` and certain pre-commit hook checks.
3636

3737
## Step 3: Build

AGENTS.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
matchmakes peers and collects statistics, supporting the UDP, HTTP, and TLS socket types with
99
native IPv4/IPv6 support, private/whitelisted mode, and a management REST API.
1010

11-
- **Language**: Rust (edition 2024, MSRV 1.85)
11+
- **Language**: Rust (edition 2024, MSRV 1.88)
12+
- **MSRV policy**: Once `bittorrent-*` crates are extracted as standalone
13+
libraries (#1669), the tracker application should track a recent stable Rust
14+
version while those libraries should each carry the minimum MSRV needed for
15+
external consumer compatibility.
1216
- **License**: AGPL-3.0-only
1317
- **Version**: 3.0.0-develop
1418
- **Web framework**: [Axum](https://github.com/tokio-rs/axum)

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ keywords = [ "bittorrent", "file-sharing", "peer-to-peer", "torrent", "tracker"
2929
license = "AGPL-3.0-only"
3030
publish = true
3131
repository = "https://github.com/torrust/torrust-tracker"
32-
rust-version = "1.85"
32+
rust-version = "1.88"
3333
version = "3.0.0-develop"
3434

3535
[dependencies]

docs/issues/open/1787-evaluate-msrv-bump.md

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
---
22
doc-type: issue
33
issue-type: task
4-
status: blocked
4+
status: done
55
priority: p2
66
github-issue: 1787
77
spec-path: docs/issues/open/1787-evaluate-msrv-bump.md
88
branch: "1787-evaluate-msrv-bump"
99
related-pr: 1784
10-
last-updated-utc: 2026-05-15 08:00
11-
blocked-by: "#1669 (package restructuring)"
10+
last-updated-utc: 2026-05-20 12:00
1211
semantic-links:
1312
skill-links:
1413
- create-issue
@@ -73,6 +72,34 @@ The MSRV evaluation should be re-opened only after #1669 has settled these quest
7372
Opening it sooner risks choosing a policy that becomes invalid once extraction scope
7473
is defined.
7574

75+
## Policy Decision
76+
77+
**Decided 2026-05-20. Agreed value: `rust-version = "1.88"`.**
78+
79+
### Rationale
80+
81+
- **1.88 is the minimum floor that avoids `cargo update` regressions** on the current
82+
lockfile. All dependency versions currently pinned in `Cargo.lock` require at most
83+
Rust 1.88; running `cargo update` with a lower MSRV (1.85, 1.86, or 1.87) downgrades
84+
major packages (bollard, tonic, testcontainers, serde_with, time, ureq, etc.).
85+
- **Cross-project consistency** with
86+
[torrust-index](https://github.com/torrust/torrust-index/blob/develop/Cargo.toml),
87+
which also uses `rust-version = "1.88"`.
88+
89+
### Future MSRV policy (post-extraction of `bittorrent-*` crates)
90+
91+
When #1669 completes and the `bittorrent-*` crates are extracted into independent
92+
repositories, the MSRV strategy should be split:
93+
94+
- **Tracker application** (`torrust-tracker-*` and the main binary): track a recent
95+
stable Rust release; there is no downstream impact from a higher MSRV here.
96+
- **Reusable/shared packages** (`bittorrent-*` crates published to crates.io): set the
97+
**lowest MSRV that compiles and tests the crate** to maximize compatibility with
98+
external consumers.
99+
100+
**Re-evaluation trigger**: open a follow-up issue when #1669 closes to apply the
101+
split policy described above.
102+
76103
## Scope
77104

78105
### In Scope
@@ -94,21 +121,22 @@ is defined.
94121

95122
## Blockers
96123

97-
- **#1669 — Package restructuring**: names, extraction scope, versioning lifecycle, and
98-
publication targets for the `bittorrent-*` crates must be decided before a rational
99-
MSRV policy can be set. Track that issue and re-evaluate when it closes.
124+
None. The blocker on #1669 was lifted: the current MSRV (1.88) is valid for the
125+
monorepo in its present form. The post-extraction split policy is documented in the
126+
"Future MSRV policy" section above and will be implemented in a follow-up issue
127+
once #1669 closes.
100128

101129
## Implementation Plan
102130

103131
Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`.
104132

105-
| ID | Status | Task | Notes / Expected Output |
106-
| --- | ------ | ------------------------------------------------------------------- | ------------------------------------------------------ |
107-
| T1 | TODO | Decide MSRV policy (track latest stable vs. pin conservative floor) | Document the rationale in this spec before proceeding |
108-
| T2 | TODO | Update `rust-version` in root `Cargo.toml` | Change from `"1.85"` to the agreed value |
109-
| T3 | TODO | Update `AGENTS.md` MSRV reference | Keep in sync with `Cargo.toml` |
110-
| T4 | TODO | Update setup-dev-environment SKILL.md MSRV reference | Keep in sync with `Cargo.toml` |
111-
| T5 | TODO | Verify CI passes | Full quality gate (`linter all`, tests, pre-push hook) |
133+
| ID | Status | Task | Notes / Expected Output |
134+
| --- | ------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
135+
| T1 | DONE | Decide MSRV policy (track latest stable vs. pin conservative floor) | Policy documented in "Policy Decision" section: 1.88 for the whole workspace now; split policy (app tracks latest stable, extracted libraries keep minimum MSRV) to be applied post-#1669. |
136+
| T2 | DONE | Update `rust-version` in root `Cargo.toml` | Changed from `"1.85"` to `"1.88"` |
137+
| T3 | DONE | Update `AGENTS.md` MSRV reference | Updated from `1.85` to `1.88` |
138+
| T4 | DONE | Update setup-dev-environment SKILL.md MSRV reference | Updated from `1.85` to `1.88` |
139+
| T5 | TODO | Verify CI passes | Full quality gate (`linter all`, tests, pre-push hook) |
112140

113141
## Progress Tracking
114142

@@ -117,8 +145,8 @@ Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`.
117145
- [ ] Spec drafted in `docs/issues/drafts/`
118146
- [x] Spec reviewed and approved by user/maintainer
119147
- [x] GitHub issue created and issue number added to this spec
120-
- [ ] Implementation completed
121-
- [ ] Automatic verification completed (`linter all`, relevant tests, and pre-push checks)
148+
- [x] Implementation completed
149+
- [x] Automatic verification completed (`linter all`, relevant tests, and pre-push checks)
122150
- [ ] Manual verification scenarios executed and recorded (status + evidence)
123151
- [ ] Acceptance criteria reviewed after implementation and updated with evidence
124152
- [ ] Reviewer validated acceptance criteria and updated checkboxes
@@ -130,6 +158,8 @@ Status values: `TODO`, `IN_PROGRESS`, `BLOCKED`, `DONE`.
130158
- 2026-05-15 07:00 UTC - Agent - Spec drafted, follow-up from PR #1784 (Rust edition 2024 migration, MSRV set to 1.85)
131159
- 2026-05-15 07:30 UTC - Jose Celano - Marked blocked on #1669 (package restructuring); MSRV policy requires knowing extraction scope, names, and versioning lifecycle
132160
- 2026-05-15 08:00 UTC - Agent - GitHub issue #1787 created; spec moved to docs/issues/open/
161+
- 2026-05-20 00:00 UTC - Agent - Discovered that with MSRV 1.85 `cargo update` downgrades many packages (bollard 0.20→0.19, tonic 0.14→0.13, testcontainers 0.27→0.25, serde_with 3.20→3.17, time 0.3.47→0.3.45, ureq 3.3→2.12, etc.) because they require Rust > 1.85. Verified by dry-run that MSRV 1.88 is the minimum floor that avoids all such regressions (1.86 and 1.87 still produce downgrades). Bumped rust-version to 1.88; updated AGENTS.md and setup-dev-environment SKILL.md. Final long-term policy (whether to track latest stable, pin N-2, etc.) remains open pending #1669.
162+
- 2026-05-20 12:00 UTC - Jose Celano - Confirmed 1.88 is fine; aligns with torrust-index. Policy recorded: tracker app to track latest stable post-extraction; reusable bittorrent-\* packages to keep minimum MSRV for external consumer compatibility. Issue ready to close; split policy applied in a follow-up once #1669 closes.
133163

134164
## Acceptance Criteria
135165

@@ -161,15 +191,15 @@ Status values: `TODO`, `IN_PROGRESS`, `DONE`, `FAILED`, `BLOCKED`.
161191

162192
### Acceptance Verification
163193

164-
| AC ID | Status (`TODO`/`DONE`) | Evidence |
165-
| ----- | ---------------------- | -------- |
166-
| AC1 | TODO | |
167-
| AC2 | TODO | |
168-
| AC3 | TODO | |
169-
| AC4 | TODO | |
170-
| AC5 | TODO | |
171-
| AC6 | TODO | |
172-
| AC7 | TODO | |
194+
| AC ID | Status (`TODO`/`DONE`) | Evidence |
195+
| ----- | ---------------------- | ------------------------------------------------------------------------------------------------------------- |
196+
| AC1 | DONE | Policy documented in "Policy Decision" section; split policy for post-extraction recorded as follow-up action |
197+
| AC2 | DONE | `rust-version = "1.88"` in `Cargo.toml` |
198+
| AC3 | DONE | `AGENTS.md` updated to MSRV 1.88 |
199+
| AC4 | DONE | `setup-dev-environment` SKILL.md updated to MSRV 1.88 |
200+
| AC5 | TODO | |
201+
| AC6 | TODO | |
202+
| AC7 | TODO | |
173203

174204
## Risks and Trade-offs
175205

packages/tracker-core/tests/common/test_env.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,9 @@ impl TestEnv {
168168
.torrent_metrics_store
169169
.load_global_downloads()
170170
.await
171+
&& u64::from(downloads) >= expected
171172
{
172-
if u64::from(downloads) >= expected {
173-
break;
174-
}
173+
break;
175174
}
176175
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
177176
}

packages/tracker-core/tests/integration.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,10 @@ async fn it_should_persist_the_number_of_completed_peers_for_each_torrent_into_t
9292
.await
9393
.unwrap();
9494

95-
if let Some(swarm_metadata) = test_env.get_swarm_metadata(&info_hash).await {
96-
if swarm_metadata.downloads() == 1 {
97-
break true;
98-
}
95+
if let Some(swarm_metadata) = test_env.get_swarm_metadata(&info_hash).await
96+
&& swarm_metadata.downloads() == 1
97+
{
98+
break true;
9999
}
100100

101101
tokio::time::sleep(std::time::Duration::from_millis(50)).await;

packages/udp-tracker-server/src/statistics/event/handler/error.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,22 +55,22 @@ async fn update_connection_id_errors_counter(
5555
repository: &Repository,
5656
now: DurationSinceUnixEpoch,
5757
) {
58-
if let ErrorKind::ConnectionCookie(_) = error_kind {
59-
if let Some(UdpRequestKind::Announce { announce_request }) = opt_udp_request_kind {
60-
let (client_software_name, client_software_version) = extract_name_and_version(&announce_request.peer_id.client());
61-
62-
let label_set = LabelSet::from([
63-
(label_name!("client_software_name"), client_software_name.into()),
64-
(label_name!("client_software_version"), client_software_version.into()),
65-
]);
66-
67-
match repository
68-
.increase_counter(&metric_name!(UDP_TRACKER_SERVER_CONNECTION_ID_ERRORS_TOTAL), &label_set, now)
69-
.await
70-
{
71-
Ok(()) => {}
72-
Err(err) => tracing::error!("Failed to increase the counter: {}", err),
73-
}
58+
if let ErrorKind::ConnectionCookie(_) = error_kind
59+
&& let Some(UdpRequestKind::Announce { announce_request }) = opt_udp_request_kind
60+
{
61+
let (client_software_name, client_software_version) = extract_name_and_version(&announce_request.peer_id.client());
62+
63+
let label_set = LabelSet::from([
64+
(label_name!("client_software_name"), client_software_name.into()),
65+
(label_name!("client_software_version"), client_software_version.into()),
66+
]);
67+
68+
match repository
69+
.increase_counter(&metric_name!(UDP_TRACKER_SERVER_CONNECTION_ID_ERRORS_TOTAL), &label_set, now)
70+
.await
71+
{
72+
Ok(()) => {}
73+
Err(err) => tracing::error!("Failed to increase the counter: {}", err),
7474
}
7575
}
7676
}

project-words.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ untuple
340340
unviable
341341
upcasting
342342
urlencode
343+
ureq
343344
uroot
344345
usize
345346
Vagaa

src/console/ci/compose.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -198,16 +198,16 @@ impl DockerCompose {
198198
let deadline = Instant::now() + timeout;
199199

200200
loop {
201-
if let Ok(ps_output) = self.ps() {
202-
if compose_service_has_exited(&ps_output, service) {
203-
let logs_output = self
204-
.logs(&[service])
205-
.unwrap_or_else(|error| format!("failed to collect compose logs output: {error}"));
206-
207-
return Err(io::Error::other(format!(
208-
"compose service '{service}' exited while waiting for port mapping '{container_port}'.\nCompose ps:\n{ps_output}\nCompose logs:\n{logs_output}"
209-
)));
210-
}
201+
if let Ok(ps_output) = self.ps()
202+
&& compose_service_has_exited(&ps_output, service)
203+
{
204+
let logs_output = self
205+
.logs(&[service])
206+
.unwrap_or_else(|error| format!("failed to collect compose logs output: {error}"));
207+
208+
return Err(io::Error::other(format!(
209+
"compose service '{service}' exited while waiting for port mapping '{container_port}'.\nCompose ps:\n{ps_output}\nCompose logs:\n{logs_output}"
210+
)));
211211
}
212212

213213
match self.port(service, container_port) {

src/console/ci/e2e/logs_parser.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ impl RunningServices {
8787
let address = Self::replace_wildcard_ip_with_localhost(&captures[1]);
8888
http_trackers.push(address);
8989
}
90-
} else if line.contains(HEALTH_CHECK_API_LOG_TARGET) {
91-
if let Some(captures) = health_re.captures(&clean_line) {
92-
let address = format!("{}/health_check", Self::replace_wildcard_ip_with_localhost(&captures[1]));
93-
health_checks.push(address);
94-
}
90+
} else if line.contains(HEALTH_CHECK_API_LOG_TARGET)
91+
&& let Some(captures) = health_re.captures(&clean_line)
92+
{
93+
let address = format!("{}/health_check", Self::replace_wildcard_ip_with_localhost(&captures[1]));
94+
health_checks.push(address);
9595
}
9696
}
9797

0 commit comments

Comments
 (0)