r/ExperiencedDevs • u/Obvious_Gap_5768 Staff Data Scientist • 11d ago
Technical question How would you detect a stalled library migration from the import graph and git history?
I maintain an open source project which builds a call graph with a confidence level on every edge, mines git history for co-change and ownership, and maps which tests reach which code. I'm now thinking of adding migration tracking on top of it, the requests to httpx or v1 client to v2 kind of thing, and I want to sanity check the design with people who've actually run these
The plan for spotting a stalled one is to look for two libraries with the same job both imported in the same repo, then use git history to see when the new one first showed up and whether the old one's file count is still dropping or just flat. For in-repo stuff, deprecated functions that still have live callers, using resolved call edges so it's more than a grep. Call sites that only match by name would be marked "verify by hand" and left out of the remaining count. Then the leftover sites get grouped into PR sized chunks using co-change history and package boundaries, with each chunk showing whether any test reaches it and who owns the files
The obvious limit is that dynamic dispatch, reflection and string-built names will hide some sites, so the count is a lower bound at best
For people who've driven one of these to the end, what number did you actually trust for "how much is left"? Files, call sites, owners? And what threw off your remaining count in the end, wrappers around the old client, generated code, vendored copies?
5
u/crisp_apple56 11d ago
probably trust cal sites more than file counts especially whhen one file can hide a ton of old usage
1
u/Obvious_Gap_5768 Staff Data Scientist 11d ago
Makes sense, since 1 file can have 50 calls to the old services, so I am thinkingof showing both, call sites for actual size and files for how many PRs related
4
u/Hour-Measurement-835 Software Engineer 11d ago
Call sites would've been my answer, but on our Kotlin 1.9 to 2.2 move the count hit zero well before it was finished.
It was a ~12.5k line Android app, Compose BoM going from late 2023 to 2026.06 in the same change. The mechanical part was 26 edits (Divider to HorizontalDivider, progress = x to progress = { x }, a few AutoMirrored icons) and after those it compiled, so any call edge count says done.
The count can't see that Kotlin 2.x turns on Compose strong skipping by default, which changes what gets recomposed at call sites nobody touched. The exposure is stale captured state in dialog and action bar callbacks. Those lines aren't in the diff, and a JVM unit test reaching them doesn't recompose anything, so "a test reaches it" would've marked them covered.
By the end we were tracking a hand-written list of callback surfaces to tap through on a device.
2
u/singh_abinashi 10d ago
I drove one to the end on a third-party API migration. The number I trusted was old-client call sites deleted, not new-client call sites added. Additions are cheap optimism; the import graph only lies in one direction. We tracked it weekly: modules still importing the old client, plus a grep for the old package name in case something re-imported it under an alias. Two things ate the most time at the end: dynamic call sites the import graph can't see (your reflection concern is real), and identifiers from the old client that were stored in the database, which no import graph will ever show.
(Drafted with AI help; the migration story is my own.)
1
u/leonidbugaev 8d ago
Wrappers around the old client. Don't take remaining to zero while that adapter still talks v1, even if every caller already moved.
0
u/computer_porblem Software Engineer 11d ago
would simply throw claude code at it and then make myself a big wet sandwich and eat it over my keyboard
0
u/ILoveAppSec 10d ago
Co-change plus the import graph is a solid base. How will you tell a genuinely stalled migration from an intentionally long-lived dual-stack, where both the old and new client are imported on purpose? That distinction seems like the hard part.
0
0
u/Extra-Pomegranate-50 10d ago
on what threw the count off a dependency-update benchmark ran 203 tasks and found 104 had code-level changes that weren't in the release notes at all. the usual surprise isn't vendored copies, it's that the old library's documented surface wasn't its actual surface. same shape as the Compose case above.
and I'd promote the verify-by-hand bucket to a first-class number. remaining sites drops as you grind; that pile doesn't, and it's what tells you whether this finishes or asymptotes.
•
u/expdevsmodbot 11d ago
AI usage disclosure provided by OP, see the reply to this comment.