Run tests recursively.
[gitmo/moose-dev-utils.git] / cpan-stable-smolder
1 #!/usr/bin/env perl
2
3 use strict;
4 use warnings;
5 use CPAN;
6 use Cwd;
7 use File::chdir;
8 use IPC::Run3 qw( run3 );
9
10
11 CPAN::HandleConfig->load();
12 CPAN::Shell::setup_output();
13 CPAN::Index->reload();
14
15 local $CPAN::Config->{tar_verbosity} = 'none';
16 local $CPAN::Config->{load_module_verbosity} = 'none';
17
18
19 my $LOGFILE = ( cwd . "/cpan-stable-smolder.log" );
20
21 if ( -f $LOGFILE ) {
22     unlink $LOGFILE;
23 }
24
25 open my $log, '>', $LOGFILE || die "Could not open $LOGFILE because $!";
26
27 my $MODULE_LIST_FILE = ( cwd . '/cpan-stable-modules' );
28
29 my @modules;
30 {
31     open my $fh, $MODULE_LIST_FILE or die "Can't open $MODULE_LIST_FILE: $!";
32     @modules = map { chomp; $_ } <$fh>;
33 }
34
35 test_all_modules(@modules);
36
37 close $log;
38
39 exit;
40
41 sub test_all_modules {
42     my @statuses;
43     my @details;
44
45     foreach my $project (@_) {
46         my $dist = get_distro_from_cpan($project);
47
48         unless ($dist) {
49             print {$log} "UNKNOWN : $project (not on CPAN?)\n";
50             next;
51         }
52
53         my ( $passed, $warned, $output ) = test_module( $dist->dir() );
54
55         my $status = $passed && $warned ? 'WARN' : $passed ? 'PASS' : 'FAIL';
56
57         my $summary = "$status: $project - " . $dist->base_id();
58         print {$log} "$summary\n";
59
60         push @details, [ $project, $output ]
61             if $warned || ! $passed;
62     }
63
64     if (@details) {
65         print {$log} "\n\n";
66
67         for my $detail (@details) {
68             print {$log} q{-} x 50;
69             print {$log} "\n";
70             print {$log} "$detail->[0]\n\n";
71             print {$log} "$detail->[1]\n\n";
72         }
73     }
74 }
75
76 sub get_distro_from_cpan {
77     my $project = shift;
78
79     ( my $module = $project ) =~ s/-/::/g;
80
81     my @mods = CPAN::Shell->expand( 'Module', $module );
82
83     die "Cannot resolve $project to a single module object"
84         if @mods > 1;
85
86     return unless @mods;
87
88     my $dist = $mods[0]->distribution();
89
90     $dist->get();
91
92     return $dist;
93 }
94
95 sub test_module {
96     my $dir = shift;
97
98     local $CWD = $dir;
99
100     local $ENV{PERL_AUTOINSTALL} = '--defaultdeps';
101     if ( -f "Build.PL" ) {
102         return
103             unless _run_commands(
104             [ $^X, 'Build.PL' ],
105             ['./Build'],
106             );
107     }
108     else {
109         return
110             unless _run_commands(
111             [ $^X, 'Makefile.PL' ],
112             ['make'],
113             );
114     }
115
116     return _run_tests();
117 }
118
119 sub _run_commands {
120     for my $cmd (@_) {
121         my $output;
122
123         unless ( run3 $cmd, \undef, \$output, \$output ) {
124             warn "Failed to run @{$cmd}\n";
125             return ( 0, $output );
126         }
127     }
128
129     return 1;
130 }
131
132 sub _run_tests {
133     my $output;
134
135     run3 [ qw( prove -br ) ], undef, \$output, \$output;
136
137     my $passed = $output =~ /Result: PASS/;
138     my $warned = $output =~ /at .+ line \d+/;
139
140     return ( $passed, $warned, $output );
141 }
142