Skip to content
Development

Reading changelogs before bumping three stale dependencies

By Victor Da Luz
rustdependenciesdev-loggreenhouse

The same repo review that found no dependency scanning also flagged three specific dependencies in Greenhouse’s Cargo.toml as stale: serde_yaml 0.9 is archived and unmaintained, rusqlite 0.31 was statically linking a two-year-old bundled SQLite missing that entire window of upstream fixes, and thiserror 1 was a duplicate major version already superseded everywhere else in the dependency tree.

Why this approach

None of these needed a design decision, just verification that the upgrade path was actually safe before touching anything. A version bump on a database driver and a serialization library is exactly the kind of change that looks trivial and occasionally isn’t.

Implementation

Before editing a single line, I grepped every call site of all three crates across the codebase: four serde_yaml:: uses, eight-ish thiserror-derived variants in one error enum, and a dozen-plus rusqlite calls in the database layer (connections, transactions, prepared statements, the params! macro, specific error variants). Then I checked each usage against what actually changed upstream, not just the version number:

  • serde_yaml → yaml_serde 0.10.4: confirmed on crates.io as the YAML organization’s maintained fork, API-identical to serde_yaml (from_str/to_string/Value/Error all match). It’s a Cargo package rename, not a code migration - serde_yaml = { package = "yaml_serde", version = "0.10" } and every existing serde_yaml:: call site in the source keeps compiling unchanged.
  • rusqlite 0.31 → 0.40.1: nine minor versions, bundled SQLite jumping from 3.45.1 to 3.53.2. I pulled the GitHub release notes for every version in between and checked each breaking-change line against what Greenhouse’s db.rs actually touches. The breaking changes clustered around virtual tables, the statement cache, and u64/usize type conversions - none of which this codebase uses (i64 timestamps and UUID-string IDs throughout, no vtab/functions/backup/blob features).
  • thiserror 1 → 2: Tauri’s own dependency tree was already on thiserror 2 for everything except our crate. The 2.0 breaking changes are format-string edge cases (positional argument capture, tuple-index ambiguity) that don’t apply to a plain derived error enum.

Gotcha

None, which was itself the interesting part. Three dependencies, nine minor versions of drift on the worst one, and the actual bump was cargo build succeeding on the first try. The work wasn’t in writing code, it was in reading enough changelog to know in advance that nothing would break - grep the call sites first, then check the exact API surface those call sites touch against the exact list of what changed, instead of bumping the version and finding out from the compiler.

Results

All 95 tests pass, including two that already did a full serialize-write-read-deserialize round trip through the same Config types the yaml_serde swap touches. Clean cargo build, clippy (deny warnings), and fmt check. Cargo.lock confirms the old serde_yaml package is gone entirely and thiserror 1.0.69/2.0.18 now coexist cleanly, since a handful of unrelated transitive deps (GTK/Android bindings pulled in by Tauri’s non-macOS backends) are still pinned to 1.x.

Related reading

Development

Two notes nobody ever saw

Greenhouse saved a capture note and a handoff note faithfully, and showed neither: one had no field in the wire type, the other had a working command nobody called.

Read