Monitoring dependencies on the CPAN
Tags: perl, cpan, dependencies
Published: 2020-10-16 12:10:38

---
title: Monitoring dependencies on the CPAN
published: true
description: A new tool to help monitor how your code's dependencies are changing
tags: perl, cpan, dependencies
---

If you're anything like me you're a lazy bugger and prefer to write as little code as possible, instead relying on libraries that other people have written. This has several advantages: it's less work for you, the code has already been tested (you hope!) and debugged, someone else maintains it for you, and so on. The disadvantage is that those other people might change things, either accidentally or on purpose, and break your code. So if you're going to use other peoples' libraries it's a good idea to know what libraries you're actually using.

Easy to figure out, right? Just remember what you're using!

Oh if only it were that simple. You see, all those other people whose code you're using are just as lazy as you are, and they're all using third parties' libraries, and in turn those are using yet more libraries, and so on. As a [learnèd sage](https://en.wikipedia.org/wiki/Augustus_De_Morgan) once wrote:

> Bigger fleas have littler fleas upon their backs to bite 'em,
> And little fleas have lesser fleas, and so on, ad infinitum.

Many years ago I wrote [a script](https://metacpan.org/source/DCANTRELL/CPAN-FindDependencies-2.49/examples/cpandeps) [^1] which shows the entire dependency tree for a module on the [CPAN](https://www.cpan.org/). Those trees grow surprisingly big surprisingly fast. For one of mine, it has 1 direct dependency, 8 second level dependencies, another 13 at the third level, and so it continues for a grand total of 41 [^2] dependencies.

```
Params::Validate::Dependencies::all_or_none_of (dist: D/DC/DCANTRELL/Params-Validate-Dependencies-all_or_none_of-1.01.tar.gz)
  Params::Validate::Dependencies (dist: D/DC/DCANTRELL/Params-Validate-Dependencies-1.40.tar.gz)
    Clone (dist: A/AT/ATOOMIC/Clone-0.45.tar.gz)
      B::COW (dist: A/AT/ATOOMIC/B-COW-0.004.tar.gz)
    Data::Domain (dist: D/DA/DAMI/Data-Domain-1.07.tar.gz)
      Date::Calc (dist: S/ST/STBEY/Date-Calc-6.4.tar.gz)
        Bit::Vector (dist: S/ST/STBEY/Bit-Vector-7.4.tar.gz)
          Carp::Clan (dist: E/ET/ETHER/Carp-Clan-6.08.tar.gz)
      List::MoreUtils (dist: R/RE/REHSACK/List-MoreUtils-0.428.tar.gz)
        Exporter::Tiny (dist: T/TO/TOBYINK/Exporter-Tiny-1.002002.tar.gz)
        List::MoreUtils::XS (dist: R/RE/REHSACK/List-MoreUtils-XS-0.428.tar.gz)
        Test::LeakTrace (dist: L/LE/LEEJO/Test-LeakTrace-0.16.tar.gz)
      Scalar::Does (dist: T/TO/TOBYINK/Scalar-Does-0.203.tar.gz)
        Test::NoWarnings (dist: A/AD/ADAMK/Test-NoWarnings-1.04.tar.gz)
        Test::Requires (dist: T/TO/TOKUHIROM/Test-Requires-0.11.tar.gz)
        Type::Tiny (dist: T/TO/TOBYINK/Type-Tiny-1.010006.tar.gz)
        URI (dist: O/OA/OALDERS/URI-1.76.tar.gz)
          Test::Needs (dist: H/HA/HAARG/Test-Needs-0.002006.tar.gz)
... and so on
```

But even more important than knowing what's in your dependency tree is knowing when that tree changes, so that you know when you need to re-test your code to make sure no-one else broke it. Well, I've finally gone and [created a tool for that](https://github.com/DrHyde/perlscripts/blob/master/cpandeps-diff), after having it on my to-do list for over a decade (did I mention above that I'm very lazy?).

It maintains a little database in `~/.cpandeps-diff` of what a module's dependencies are, and every time you run it without any arguments it compares the dependencies it already knows about with what's on the CPAN, spitting out a side-by-side diff. Invoke it daily from your `crontab` and you'll get a daily email with any changes.

Start by telling it what modules you want to get reports about:

```
$ cpandeps-diff add CPAN::FindDependencies
$ cpandeps-diff add Sub::WrapPackages
$ cpandeps-diff add Number::Phone
```

Each time it will go away to the CPAN, find what all the dependencies are, and store them in a file in that directory. You will also notice a cache directory, which is used to minimise traffic to the CPAN mirrors.

You can list which modules it knows about, and delete any that you are no longer interested in:

```
$ cpandeps-diff list
CPAN::FindDependencies
Number::Phone
Sub::WrapPackages

$ cpandeps-diff rm Sub::WrapPackages
```

And you can get a report on an individual module:

```
$ cpandeps-diff report Number::Phone
Differences found in dependencies for Number::Phone:
+---+-----------------------------------------------+-----------------------------------------------+
|  3|E/ET/ETHER/Class-Method-Modifiers-2.13.tar.gz  |E/ET/ETHER/Class-Method-Modifiers-2.13.tar.gz  |
|  4|E/ET/ETHER/File-ShareDir-Install-0.13.tar.gz   |E/ET/ETHER/File-ShareDir-Install-0.13.tar.gz   |
|  5|E/ET/ETHER/Try-Tiny-0.30.tar.gz                |E/ET/ETHER/Try-Tiny-0.30.tar.gz                |
*  6|E/EX/EXODIST/Test-Exception-0.42.tar.gz        |E/EX/EXODIST/Test-Exception-0.43.tar.gz        *
|  7|H/HA/HAARG/Moo-2.004000.tar.gz                 |H/HA/HAARG/Moo-2.004000.tar.gz                 |
|  8|H/HA/HAARG/Role-Tiny-2.001004.tar.gz           |H/HA/HAARG/Role-Tiny-2.001004.tar.gz           |
...
```

You can see in that report that a new version of [Test-Exception](https://metacpan.org/pod/Test::Exception) has been released, and so I should make sure that the code which depends on it still works. If it turns out that that broke my code, that's annoying, but at least I found out about the problem before users started reporting bugs.

[^1]: I also created [a website](http://deps.cpantesters.org/?module=XML%3A%3AFeed&perl=5.30&os=any+OS), originally based on largely the same code, which also shows test results for all dependencies and which has bit-rotted and become overloaded to the extent that it is no longer usable. Sorry about that.

[^2]: or if you're using a really old version of perl, and so need upgraded versions of libraries distributed with the interpreter, you can more than double that.