File Coverage

blib/lib/Badge/Depot/Plugin/Coverage.pm
Criterion Covered Total %
statement 53 71 74.6
branch 5 18 27.7
condition n/a
subroutine 16 16 100.0
pod 0 4 0.0
total 74 109 67.8


line stmt bran cond sub pod time code
1 1     1   23005 use 5.10.1;
  1         3  
2 1     1   11 use strict;
  1         2  
  1         24  
3 1     1   5 use warnings;
  1         1  
  1         52  
4              
5             package Badge::Depot::Plugin::Coverage;
6              
7 1     1   858 use Moose;
  1         522380  
  1         7  
8 1     1   8619 use namespace::autoclean;
  1         8893  
  1         5  
9 1     1   935 use MooseX::AttributeShortcuts;
  1         2617107  
  1         7  
10 1     1   38005 use Types::Standard qw/Str Bool Num/;
  1         64916  
  1         14  
11 1     1   1792 use Types::URI qw/Uri/;
  1         187806  
  1         16  
12 1     1   1137 use JSON::MaybeXS 'decode_json';
  1         16399  
  1         65  
13 1     1   19 use Path::Tiny;
  1         2  
  1         45  
14 1     1   1425 use DateTime;
  1         96835  
  1         43  
15 1     1   798 use DateTime::Format::RFC3339;
  1         3784  
  1         615  
16             with 'Badge::Depot';
17              
18             our $VERSION = '0.0100'; # VERSION
19             # ABSTRACT: Code coverage plugin for Badge::Depot
20              
21             has coverage => (
22             is => 'ro',
23             isa => Num,
24             required => 0,
25             predicate => 1,
26             );
27             has custom_image_url => (
28             is => 'ro',
29             isa => Uri,
30             coerce => 1,
31             default => 'https://img.shields.io/badge/%s-%s-%s.svg',
32             );
33             has text => (
34             is => 'ro',
35             isa => Str,
36             default => 'coverage',
37             );
38             has max_age => (
39             is => 'ro',
40             isa => 'Int',
41             default => '60',
42             documentation => q{Include coverage badge if the latest cover run was done less than 'max_age' minutes ago},
43             );
44              
45              
46             sub BUILD {
47 2     2 0 4 my $self = shift;
48              
49 2         7 my $coverage = $self->determine_coverage;
50 2 100       9 if($coverage == -1) {
51 1         4 $self->log('! Could not determine coverage, skips Coverage badge');
52 1         42 return;
53             }
54              
55 1         22 $coverage = sprintf '%.1f', $coverage;
56 1         5 my $color = $self->determine_color($coverage);
57 1         61 $self->image_url(sprintf $self->custom_image_url, $self->text, $coverage.'%', $color);
58 1         242 $self->image_alt(sprintf '%s %s', $self->text, $coverage.'%');
59 1         15 $self->log("Adds coverage badge ($coverage%)");
60             }
61              
62              
63             sub determine_coverage {
64 2     2 0 3 my $self = shift;
65 2 50       95 return $self->coverage if $self->has_coverage;
66              
67 0         0 my $log_file = path(qw/. .coverhistory.json/);
68              
69 0 0       0 if(!$log_file->exists) {
70 0         0 $self->log('! Could not find cover history file (.coverhistory.json), no coverage to add');
71 0         0 return -1;
72             }
73              
74 0         0 my $history = decode_json($log_file->slurp);
75              
76 0 0       0 if(!scalar @$history) {
77 0         0 $self->log('! No coverage history in .coverhistory.json, nothing to add');
78 0         0 return -1;
79             }
80              
81 0         0 my $summary = $history->[-1];
82 0         0 my $created_at = DateTime::Format::RFC3339->parse_datetime($summary->{'created_at'});
83 0         0 my $since = DateTime->now - $created_at;
84              
85 0         0 my $minutes = $since->years * 1440 * 365
86             + $since->months * 1440 * 30
87             + $since->days * 1440
88             + $since->hours * 60
89             + $since->minutes
90             + $since->seconds / 60;
91              
92 0 0       0 if($minutes > $self->max_age) {
93 0         0 $self->log("! Latest coverage was run @{[ sprintf '%.1f', $minutes ]} minutes ago, maximum allowed age is @{[ $self->max_age ]} minutes, wont add coverage");
  0         0  
  0         0  
94 0         0 return -1;
95             }
96 0         0 return $summary->{'total'};
97             }
98             sub determine_color {
99 1     1 0 7 my $self = shift;
100 1         3 my $coverage = shift;
101              
102 1 0       14 return $coverage < 75 ? 'red'
    0          
    50          
    50          
103             : $coverage < 90 ? 'orange'
104             : $coverage < 100 ? 'yellow'
105             : $coverage == 100 ? 'brightgreen'
106             : 'blue'
107             ;
108             }
109             sub log {
110 2     2 0 4 my $self = shift;
111 2         4 my $text = shift;
112              
113 2         89 say "[Badge/Coverage] $text";
114              
115             };
116              
117             __PACKAGE__->meta->make_immutable;
118              
119             1;
120              
121             __END__
122              
123             =pod
124              
125             =encoding UTF-8
126              
127             =head1 NAME
128              
129             Badge::Depot::Plugin::Coverage - Code coverage plugin for Badge::Depot
130              
131              
132              
133             =begin HTML
134              
135             <p><img src="https://img.shields.io/badge/perl-5.10.1+-brightgreen.svg" alt="Requires Perl 5.10.1+" /> <a href="https://travis-ci.org/Csson/p5-Badge-Depot-Plugin-Coverage"><img src="https://api.travis-ci.org/Csson/p5-Badge-Depot-Plugin-Coverage.svg?branch=master" alt="Travis status" /></a></p>
136              
137             =end HTML
138              
139              
140             =begin markdown
141              
142             ![Requires Perl 5.10.1+](https://img.shields.io/badge/perl-5.10.1+-brightgreen.svg) [![Travis status](https://api.travis-ci.org/Csson/p5-Badge-Depot-Plugin-Coverage.svg?branch=master)](https://travis-ci.org/Csson/p5-Badge-Depot-Plugin-Coverage)
143              
144             =end markdown
145              
146             =head1 VERSION
147              
148             Version 0.0100, released 2016-01-19.
149              
150             =head1 SYNOPSIS
151              
152             Used standalone:
153              
154             use Badge::Depot::Plugin::Coverage;
155              
156             my $badge = Badge::Depot::Plugin::Coverage->new(coverage => 87);
157              
158             print $badge->to_html;
159              
160             Used together with L<Pod::Weaver::Section::Badges>, in weaver.ini:
161              
162             [Badges]
163             ; other settings
164             badge = Coverage
165              
166             =head1 DESCRIPTION
167              
168             This L<Badge::Depot> badge is meant to be used together with L<Dist::Zilla::App::Command::coverh> (or standalone, as per the synopsis) and creates a coverage badge:
169              
170             =for HTML <p><img src="https://img.shields.io/badge/coverage-87%-orange.svg" /></p>
171              
172             =for markdown ![Coverage 87%](https://img.shields.io/badge/coverage-87%-orange.svg)
173              
174             =head1 ATTRIBUTES
175              
176             =head2 coverage
177              
178             Set the code coverage percentage manually. Should only be used when L<Dist::Zilla::App::Command::coverh> is B<not> used.
179              
180             =head2 custom_image_url
181              
182             Default: C<https://img.shields.io/badge/%s-%s-%s.svg>
183              
184             Override the default image url. It is expected to have three C<sprintf> placeholders: Text, coverage percentage and color.
185              
186             =head2 max_age
187              
188             Default: C<60>
189              
190             When used together with L<Dist::Zilla::App::Command::coverh>, only include the badge if the latest coverage run was less than C<max_age> minutes ago.
191              
192             =head2 text
193              
194             Default: C<coverage>
195              
196             Set a different badge text.
197              
198             =head1 SEE ALSO
199              
200             =over 4
201              
202             =item *
203              
204             L<Badge::Depot>
205              
206             =item *
207              
208             L<Task::Badge::Depot>
209              
210             =back
211              
212             =head1 SOURCE
213              
214             L<https://github.com/Csson/p5-Badge-Depot-Plugin-Coverage>
215              
216             =head1 HOMEPAGE
217              
218             L<https://metacpan.org/release/Badge-Depot-Plugin-Coverage>
219              
220             =head1 AUTHOR
221              
222             Erik Carlsson <info@code301.com>
223              
224             =head1 COPYRIGHT AND LICENSE
225              
226             This software is copyright (c) 2016 by Erik Carlsson.
227              
228             This is free software; you can redistribute it and/or modify it under
229             the same terms as the Perl 5 programming language system itself.
230              
231             =cut