Fix the ktlint and compat-test failures, and start using the Rust gate
Two more from the step-2 removals: **Two unused Kotlin imports** — `FilterChip` (the Note/List switch) and `Icons.Filled.Create` (the "switch to a note" icon), both orphaned when their callers went. ktlint treats them as errors. **`server_info_tolerates_unknown_and_absent_fields`** pinned `sync_protocol_version: 1` as a literal, so bumping the protocol to v2 made it fail for a reason that has nothing to do with what it tests. It is about unknown FIELDS; the versions now come from `CLIENT_PROTOCOL_VERSION`, like every other test in that file already did. The bigger fix is the habit. `ci-requirements.md` has documented since 2026-08-18 that the operator authorised running fmt/clippy/test against the CI image locally, and I had not been doing it. All three now pass here — 116 tests, clippy clean, fmt clean — and every Rust failure in this milestone so far would have been caught by them in under a minute instead of by CI, several commits downstream. Noted in ci-requirements so the next session doesn't relearn it: a removal is exactly the change that looks too safe to check.
This commit is contained in:
@@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.navigationBarsPadding
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.FilterChip
|
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import androidx.compose.foundation.shape.CircleShape
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.List
|
import androidx.compose.material.icons.automirrored.filled.List
|
||||||
import androidx.compose.material.icons.filled.Close
|
import androidx.compose.material.icons.filled.Close
|
||||||
import androidx.compose.material.icons.filled.Create
|
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
import androidx.compose.material.icons.filled.Notifications
|
import androidx.compose.material.icons.filled.Notifications
|
||||||
import androidx.compose.material3.BottomAppBar
|
import androidx.compose.material3.BottomAppBar
|
||||||
|
|||||||
@@ -305,6 +305,15 @@ matched CI run 3931's byte for byte. Same image, same lockfile, same units.
|
|||||||
take seconds (~30s for clippy). It is gitignored and reaches ~1.4 GB; delete it
|
take seconds (~30s for clippy). It is gitignored and reaches ~1.4 GB; delete it
|
||||||
whenever the space is wanted.
|
whenever the space is wanted.
|
||||||
|
|
||||||
|
**Run these on every Rust-touching push, not just the ones that feel risky.** Four
|
||||||
|
consecutive failures across M13's removals — a private `fn` deleted along with the
|
||||||
|
`pub fn` above it, an orphaned `#[serde]` attribute left where a field was removed,
|
||||||
|
and a test pinning a protocol version literal — were all caught by these three
|
||||||
|
commands in under a minute each, after CI had already found them the slow way. A
|
||||||
|
removal is exactly the kind of change that looks safe and isn't: nothing in the
|
||||||
|
Python or TypeScript lanes compiles Rust, so a break can travel several commits
|
||||||
|
before the first lane that does gets to it.
|
||||||
|
|
||||||
**Don't infer formatting from existing code.** Several lines in `local/store.rs`
|
**Don't infer formatting from existing code.** Several lines in `local/store.rs`
|
||||||
exceed 100 characters and survive only because rustfmt cannot break a string
|
exceed 100 characters and survive only because rustfmt cannot break a string
|
||||||
literal — copying that shape caused one of four consecutive fmt-only CI failures,
|
literal — copying that shape caused one of four consecutive fmt-only CI failures,
|
||||||
|
|||||||
+10
-6
@@ -344,13 +344,17 @@ mod tests {
|
|||||||
fn server_info_tolerates_unknown_and_absent_fields() {
|
fn server_info_tolerates_unknown_and_absent_fields() {
|
||||||
// Forward compatibility: a NEWER server sending fields we've never heard of
|
// Forward compatibility: a NEWER server sending fields we've never heard of
|
||||||
// must not break the handshake.
|
// must not break the handshake.
|
||||||
let info: ServerInfo = serde_json::from_str(
|
// Versions come from the constants, not literals: this test is about unknown
|
||||||
r#"{"site_name":"S","sync_protocol_version":1,
|
// FIELDS, and pinning the numbers made it fail the moment the protocol moved
|
||||||
"min_client_protocol_version":1,
|
// to v2 — for a reason that has nothing to do with what it checks.
|
||||||
|
let body = format!(
|
||||||
|
r#"{{"site_name":"S","sync_protocol_version":{v},
|
||||||
|
"min_client_protocol_version":{v},
|
||||||
"sync_features":["notes","labels","attachments","tombstones","revisions"],
|
"sync_features":["notes","labels","attachments","tombstones","revisions"],
|
||||||
"some_future_field":{"nested":true}}"#,
|
"some_future_field":{{"nested":true}}}}"#,
|
||||||
)
|
v = CLIENT_PROTOCOL_VERSION,
|
||||||
.expect("unknown fields are ignored");
|
);
|
||||||
|
let info: ServerInfo = serde_json::from_str(&body).expect("unknown fields are ignored");
|
||||||
assert_eq!(evaluate(&info), Compatibility::Ok);
|
assert_eq!(evaluate(&info), Compatibility::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user