Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Checking if your CPAN distributions need to bump their prereq versions

by stevieb (Abbot)
on Jun 26, 2017 at 17:52 UTC ( #1193614=CUFP: print w/replies, xml ) Need Help??

I've made two 'updates' to this post, but I'm going to let it fly for a bit, then I'm going to come back and edit in my updates into the post itself...

Update: In v0.02, we now skip over prereqs where the version is listed as 0 (zero). This signifies that any version of a prereq is acceptable. To disable this and display all prereqs even if the version is zero, use the ignore_any => 0 parameter. /update

Update2: I've updated the distribution (v0.05) to install a binary, checkdep, so that you don't have to write your own to use the library:

Usage: checkdep PAUSEID [options] -a|--all Work on all dependencies, not just the author's -m|--module String; Work only on a specific distribution. (eg: Moc +k::Sub) -z|--zero Include dependencies listed with a version of zero -h|--help Display this help screen


I've got quite a few CPAN distributions that require one another, and it's gotten to the point that it's very easy to forget to bump prereq versions before uploading a new release to the CPAN.

As a stopgap, I wrote Module::CheckDep::Version (may not be indexed yet). What this module does is using MetaCPAN::Client, fetches all distributions by author, pulls out all prerequisite distributions and the version of it that your distribution has listed, checks if there's a newer version of it, and lists out the ones that need a bump in the prereq's version.

The most basic of runs takes a single parameter, a PAUSE ID (CPAN username), and lists the discrepancies of prereq version mismatches for that author's own prereq distributions *only*. Here's an example of that:

use warnings; use strict; use Module::CheckDep::Version qw(check_deps); check_deps('STEVEB');

Here's the full output of that function call:

RPi-ADC-MCP3008: WiringPi::API: 2.3608 -> 2.3612 RPi::WiringPi::Constant: 0.02 -> 1.00 App-RPi-EnvUI: WiringPi::API: 1.04 -> 2.3612 RPi::DHT11: 1.01 -> 1.02 Logging::Simple: 1.01 -> 1.04 RPi::WiringPi::Constant: 0.02 -> 1.00 Async::Event::Interval: 0.00 -> 0.03 RPi-BMP180: RPi::WiringPi::Constant: 0.02 -> 1.00 WiringPi::API: 2.3608 -> 2.3612 Wrap-Sub: Devel::Examine::Subs: 1.63 -> 1.69 RPi-I2C: WiringPi::API: 2.3609 -> 2.3612 RPi-DigiPot-MCP4XXXX: RPi::WiringPi::Constant: 0.02 -> 1.00 WiringPi::API: 2.3608 -> 2.3612 RPi-WiringPi: RPi::I2C: 2.3602 -> 2.3603 RPi::LCD: 2.3601 -> 2.3603 Devel-Trace-Subs: Mock::Sub: 1.01 -> 1.07 Devel::Examine::Subs: 1.61 -> 1.69 Test-BrewBuild: Plugin::Simple: 0.06 -> 0.07 Logging::Simple: 0.07 -> 1.04 Test::BrewBuild::Plugin::Author: 0.02 -> 0.03 RPi-SPI: WiringPi::API: 2.3608 -> 2.3612 File-Edit-Portable: Mock::Sub: 1.06 -> 1.07 WWW-ProxyChecker: WWW::FreeProxyListsCom: 0.00 -> 1.005 RPi-DAC-MCP4922: WiringPi::API: 2.3608 -> 2.3612 RPi::WiringPi::Constant: 0.02 -> 1.00 RPi-Pin: WiringPi::API: 2.3609 -> 2.3612 Devel-Examine-Subs: Mock::Sub: 1.06 -> 1.07

Using the all => 1 param, we'll check against *all* prereqs, the author's own ones and those of any other author. If it's listed as a dependency, we'll check it:

check_deps('STEVEB', all => 1);

Example (snipped) output:

Devel-Examine-Subs: Test::Trap: 0.00 -> v0.3.2 ExtUtils::MakeMaker: 0.00 -> 7.30 Carp: 0.00 -> 1.38 Data::Dumper: 0.00 -> 2.161 PPI: 0.00 -> 1.236 Mock::Sub: 1.06 -> 1.07 Data::Compare: 0.00 -> 1.25 Geo-Compass-Variation: ExtUtils::MakeMaker: 0.00 -> 7.30 RPi-LCD: ExtUtils::MakeMaker: 6.72 -> 7.30

You can look up only a single distribution instead of listing all of them (this works with all => 1 as well):

check_deps('STEVEB', module => 'RPi::WiringPi');


Pi-WiringPi: RPi::I2C: 2.3602 -> 2.3603 RPi::LCD: 2.3601 -> 2.3603

You can request the data back (a hashref of hashrefs) instead of displaying it to STDOUT:

my $data = check_deps('STEVEB', return => 1);

...and finally, you can send in a code reference to handle the data within the module instead of getting it returned or printed. This sub can do anything you want it to. You get passed a single parameter, a hashref of hashrefs, same as with the return functionality:

check_deps('STEVEB', handler => \&my_handler); sub my_handler { my $data = shift; for my $dist (keys %$data){ for my $dep (keys %{ $data->{$dist} }){ my $dep_ver = $data->{$dist}{$dep}{dep_ver}; my $cur_ver = $data->{$dist}{$dep}{cur_ver}; print "$dist has dep $dep with listed ver $dep_ver " . "and updated ver $cur_ver\n"; } } }

Sample output:

App-RPi-EnvUI has dep Async::Event::Interval with listed ver 0.00 and +updated ver 0.03 Devel-Trace-Subs has dep Devel::Examine::Subs with listed ver 1.61 and + updated ver 1.69 Devel-Trace-Subs has dep Mock::Sub with listed ver 1.01 and updated ve +r 1.07 RPi-WiringPi has dep RPi::LCD with listed ver 2.3601 and updated ver 2 +.3603 RPi-WiringPi has dep RPi::I2C with listed ver 2.3602 and updated ver 2 +.3603

I was going to hook this into an automation script using other tools I have written, but I just don't have the time. Just knowing what needs to be updated is fine for me for now.

Next version will have the ability to optionally skip prereqs that the author has set to 0 (ie. any version is acceptable).

As always, have fun!

Replies are listed 'Best First'.
Re: Checking if your CPAN distributions need to bump their prereq versions
by Tux (Abbot) on Jun 27, 2017 at 06:28 UTC

    potentially useful. Thoughtlessly upping the prereq versions /might/ work for you, but it may also break a lot. Imagine installed Foo::Bar version 1.81, which passes all your tests and everything works smoothly. Then F;;OOBar gets updated to Foo::Bar 2.00 with a complete new API and tons of new shiny features that users have asker for over the last decade (e.g. after someone else took over maintenance and finaly resolved all open RT tickets gathered during that unmaintained decade). Now you required a version 2.00, as it is available, but you never tested all your stuff with that version.

    In an ideal developer world, you'd have a machine that (automatically) installs ever update and then tests all your own (unpublished) modules against those. Only after the tests PASS, you up the prereq version. And if there are circular deps, you'd probably have to go through that cycle a few times.

    Just my 2 for today

    Enjoy, Have FUN! H.Merijn

      Hi Tux,

      Indeed, I do exactly this with my own modules, which is why the default of this software is to show only one's own dependencies.

      I test my modules along with all of their reverse dependencies with another software I wrote, Test::BrewBuild. It has the capabilities built-in to spin up new perlbrew instances for each test, ensure my distributions still pass, then tests any/all distributions on the CPAN that use my distributions as well.

      This ensures that changes I've made don't break anything anywhere else.

        To elaborate...

        cd ~/repos/mock-sub git pull # make changes, perhaps bumping one of my # own prereq versions

        My Test::BrewBuild software does a lot of things, but a basic run is started out of the current working directory, and runs unit tests of itself and optionally as in the case below, runs all the unit tests of all reverse dependencies against the changed version of the distribution I'm planning on uploading to the CPAN against any and/or all installed versions of Perlbrew (and Berrybrew) perls (you can also remove them all and install any number of them from scratch to have a clean slate for every test if you want). I won't bother getting into the network dispatching capabilities, or the automation aspects.

        Here's an example after a random change that clearly broke things for some of the revdeps:

        brewbuild -R reverse dependencies: RPi::DigiPot::MCP4XXXX Devel::Examine::Subs PSGI::Hector App::RPi::EnvUI File::Edit::Portable Devel::Trace::Subs RPi::DigiPot::MCP4XXXX 5.10.1 :: PASS 5.18.4 :: PASS 5.20.3 :: PASS 5.24.1 :: PASS 5.26.0 :: PASS Devel::Examine::Subs 5.10.1 :: PASS 5.18.4 :: PASS 5.20.3 :: PASS 5.24.1 :: PASS 5.26.0 :: FAIL PSGI::Hector 5.10.1 :: PASS 5.18.4 :: PASS 5.20.3 :: PASS 5.24.1 :: PASS 5.26.0 :: FAIL App::RPi::EnvUI 5.10.1 :: FAIL 5.18.4 :: FAIL 5.20.3 :: FAIL 5.24.1 :: FAIL 5.26.0 :: FAIL File::Edit::Portable 5.10.1 :: PASS 5.18.4 :: PASS 5.20.3 :: PASS 5.24.1 :: PASS 5.26.0 :: PASS Devel::Trace::Subs 5.10.1 :: PASS 5.18.4 :: PASS 5.20.3 :: PASS 5.24.1 :: PASS 5.26.0 :: FAIL

        Once all tests pass for all reverse dependencies, it's safe for me to upload the new version to CPAN.

Re: Checking if your CPAN distributions need to bump their prereq versions (no!)
by tye (Sage) on Jun 29, 2017 at 02:12 UTC

    This sounds like an terrible idea! "Prereq" is short for "prerequisite". It is meant to indicate what version is required for your module to function. It is not meant to indicate which version is the hippest, newest bleeding edge in the repo!

    You should specify the oldest possible version of the modules you depend upon. You are supposed to specify the minimal version number, the one that if you can't find one at least that new, then your module can't be installed because it doesn't work with that really old version of the module. A prereq version number does not prevent the installation of a newer version of the module.

    Please stop doing this.

    - tye        

      In fact you should do BOTH! State the minimum required and state the recommended version. The latter should have been thoroughly tested.

      Having a lowest supported and a recommended might have a lot of added value to a module. Say that the newest/hippest module adds a feature that can speed up you code by a factor 10, it is worth supporting that with a fallback to the old code if the newest feature is not available.

      You META.yml might then have a section similar to:

      requires: perl: 5.008001 DBI: 1.628 DBD::File: 0.42 SQL::Statement: 1.405 Text::CSV_XS: 1.01 recommends: DBI: 1.636 DBD::File: 0.44 SQL::Statement: 1.412 Text::CSV_XS: 1.31 configure_requires: ExtUtils::MakeMaker: 0 DBI: 1.628 build_requires: Config: 0 test_requires: Test::Harness: 0 Test::More: 0.90 Encode: 0 Cwd: 0 charnames: 0 test_recommends: Test::More: 1.302085

      Enjoy, Have FUN! H.Merijn

      I will review my observation of all of this. It was supposed to be something that showed with *my* distributions had prereqs of *my* software that were behind.

      I had no idea that it would cause such a furor.

      If my WiringPi::API software had issues, why shouldn't I know which other of my dists have that outdated versions of it?

      It's not like it auto-updates or something.

      This distribution simply *informs* you what is out of date. What's the problem with that?

      I should repeat again that the default shows the author's distributions along with their own software that is out of date. You have to go out of your way to see a full blown list of all prereqs outside of one author's scope.

        If you, the author, actually need to update the prereqs for your own modules with every release because your own modules fail if they try to use slightly old versions of your own modules, then imagine how painful it must be for people other than you that try to use your modules. Every single time you release a module they have to change their code because your modules lack any useful backward compatibility?

        Modules should be modular. That is where the name comes from. Modular code has a defined, narrow interface. Part of the point of the interface being narrow is so that it can also be stable.

        You should endeavor to support your own modules being able to work with older (and newer) versions of your own modules. This exercise will help you to better define and to narrow the interfaces that your modules expose.

        - tye        

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://1193614]
Approved by marto
and the leaves swirl about...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (9)
As of 2017-10-19 07:53 GMT
Find Nodes?
    Voting Booth?
    My fridge is mostly full of:

    Results (252 votes). Check out past polls.