line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Dist::Zilla::Role::TravisYML; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:BBYRD'; # AUTHORITY |
4
|
|
|
|
|
|
|
our $VERSION = '1.15'; # VERSION |
5
|
|
|
|
|
|
|
# ABSTRACT: Role for .travis.yml creation |
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
663
|
use v5.10; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
55
|
|
8
|
1
|
|
|
1
|
|
6
|
use Moose::Role; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
9
|
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
5093
|
use MooseX::Has::Sugar; |
|
1
|
|
|
|
|
546
|
|
|
1
|
|
|
|
|
4
|
|
11
|
1
|
|
|
1
|
|
90
|
use MooseX::Types::Moose qw{ ArrayRef Str Bool is_Bool }; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
11
|
|
12
|
|
|
|
|
|
|
|
13
|
1
|
|
|
1
|
|
4946
|
use List::AllUtils qw{ first sum uniq }; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
92
|
|
14
|
1
|
|
|
1
|
|
4
|
use YAML qw{ Dump }; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
49
|
|
15
|
|
|
|
|
|
|
|
16
|
1
|
|
|
1
|
|
2271
|
use Module::CoreList; |
|
1
|
|
|
|
|
35553
|
|
|
1
|
|
|
|
|
13
|
|
17
|
1
|
|
|
1
|
|
656
|
use version 0.77; |
|
1
|
|
|
|
|
31
|
|
|
1
|
|
|
|
|
8
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
requires 'zilla'; |
20
|
|
|
|
|
|
|
requires 'logger'; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
with 'Dist::Zilla::Role::MetaCPANInterfacer'; |
23
|
|
|
|
|
|
|
|
24
|
0
|
|
|
0
|
|
|
sub log { shift->logger->log(@_) } |
25
|
0
|
|
|
0
|
|
|
sub log_debug { shift->logger->log_debug(@_) } |
26
|
0
|
|
|
0
|
|
|
sub log_fatal { shift->logger->log_fatal(@_) } |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
# needs our to pass to mvp_multivalue_args |
29
|
|
|
|
|
|
|
our @phases = qw( |
30
|
|
|
|
|
|
|
before_install |
31
|
|
|
|
|
|
|
install |
32
|
|
|
|
|
|
|
after_install |
33
|
|
|
|
|
|
|
before_script |
34
|
|
|
|
|
|
|
script |
35
|
|
|
|
|
|
|
after_script |
36
|
|
|
|
|
|
|
after_success |
37
|
|
|
|
|
|
|
after_failure |
38
|
|
|
|
|
|
|
after_deploy |
39
|
|
|
|
|
|
|
); |
40
|
|
|
|
|
|
|
my @yml_order = (qw( |
41
|
|
|
|
|
|
|
sudo |
42
|
|
|
|
|
|
|
language |
43
|
|
|
|
|
|
|
perl |
44
|
|
|
|
|
|
|
env |
45
|
|
|
|
|
|
|
matrix |
46
|
|
|
|
|
|
|
branches |
47
|
|
|
|
|
|
|
), @phases, qw( |
48
|
|
|
|
|
|
|
notifications |
49
|
|
|
|
|
|
|
)); |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
### HACK: Need these rw for ChainSmoking ### |
53
|
|
|
|
|
|
|
has $_ => ( rw, isa => ArrayRef[Str], default => sub { [] } ) for ( |
54
|
|
|
|
|
|
|
map { $_, $_.'_dzil', $_.'_build' } |
55
|
|
|
|
|
|
|
map { $_, 'pre_'.$_, 'post_'.$_ } |
56
|
|
|
|
|
|
|
@phases |
57
|
|
|
|
|
|
|
); |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
has dzil_branch => ( rw, isa => Str ); |
60
|
|
|
|
|
|
|
has build_branch => ( rw, isa => Str, default => '/^build\/.*/' ); |
61
|
|
|
|
|
|
|
has notify_email => ( rw, isa => ArrayRef[Str], default => sub { [ 1 ] } ); |
62
|
|
|
|
|
|
|
has notify_irc => ( rw, isa => ArrayRef[Str], default => sub { [ 0 ] } ); |
63
|
|
|
|
|
|
|
has mvdt => ( rw, isa => Bool, default => 0 ); |
64
|
|
|
|
|
|
|
has test_authordeps => ( rw, isa => Bool, default => 0 ); |
65
|
|
|
|
|
|
|
has test_deps => ( rw, isa => Bool, default => 1 ); |
66
|
|
|
|
|
|
|
has support_builddir => ( rw, isa => Bool, default => 0 ); |
67
|
|
|
|
|
|
|
has sudo => ( rw, isa => Bool, default => 0 ); |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
has irc_template => ( rw, isa => ArrayRef[Str], default => sub { [ |
70
|
|
|
|
|
|
|
"%{branch}#%{build_number} by %{author}: %{message} (%{build_url})", |
71
|
|
|
|
|
|
|
] } ); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
has perl_version => ( rw, isa => Str, default => '-blead 5.20 5.18 5.16 5.14 5.12 5.10 -5.8' ); |
74
|
|
|
|
|
|
|
has perl_version_build => ( rw, isa => Str, lazy, default => sub { shift->perl_version } ); |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
has _releases => ( ro, isa => ArrayRef[Str], lazy, default => sub { |
77
|
|
|
|
|
|
|
my $self = shift; |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
# Find the lowest required dependencies and tell Travis-CI to install them |
80
|
|
|
|
|
|
|
my (%releases, %versions); |
81
|
|
|
|
|
|
|
if ($self->mvdt) { |
82
|
|
|
|
|
|
|
my $prereqs = $self->zilla->prereqs; |
83
|
|
|
|
|
|
|
$self->log("Searching for minimum dependency versions"); |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
my $minperl = version->parse( |
86
|
|
|
|
|
|
|
$prereqs->requirements_for('runtime', 'requires')->requirements_for_module('perl') || |
87
|
|
|
|
|
|
|
v5.8.8 # released in 2006... C'mon, people! Don't make me lower this! |
88
|
|
|
|
|
|
|
); |
89
|
|
|
|
|
|
|
foreach my $phase (qw( runtime configure build test )) { |
90
|
|
|
|
|
|
|
$self->logger->set_prefix("{Phase '$phase'} "); |
91
|
|
|
|
|
|
|
my $req = $prereqs->requirements_for($phase, 'requires'); |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
foreach my $module ( sort ($req->required_modules) ) { |
94
|
|
|
|
|
|
|
next if $module eq 'perl'; # obvious |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
my $modver = $req->requirements_for_module($module); |
97
|
|
|
|
|
|
|
my ($distro, $release, $minver) = $self->_mcpan_module_minrelease($module, $modver); |
98
|
|
|
|
|
|
|
next unless $release; |
99
|
|
|
|
|
|
|
my $mod_in_perlver = Module::CoreList->first_release($module, $minver); |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
if ($mod_in_perlver && $minperl >= $mod_in_perlver) { |
102
|
|
|
|
|
|
|
$self->log_debug(['Module %s v%s is already found in core Perl v%s (<= v%s)', $module, $minver, $mod_in_perlver, $minperl]); |
103
|
|
|
|
|
|
|
next; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
# Only install the latest version, in cases of a conflict between phases |
107
|
|
|
|
|
|
|
if (!$versions{$distro} || $minver > $versions{$distro}) { |
108
|
|
|
|
|
|
|
$releases{$distro} = $release; |
109
|
|
|
|
|
|
|
$versions{$distro} = $minver; |
110
|
|
|
|
|
|
|
$self->log_debug(['Found minimum dep version for Module %s as %s', $module, $release]); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
else { |
113
|
|
|
|
|
|
|
$self->log_debug(['Module %s v%s has a higher version due to be installed in %s v%s', $module, $minver, $distro, ''.$versions{$distro}]); |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
$self->logger->clear_prefix; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
return [ map { $releases{$_} } sort keys %releases ]; |
121
|
|
|
|
|
|
|
}); |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub build_travis_yml { |
124
|
0
|
|
|
0
|
|
|
my ($self, $is_build_branch) = @_; |
125
|
|
|
|
|
|
|
|
126
|
0
|
0
|
|
|
|
|
my %travis_yml = ( |
|
|
0
|
|
|
|
|
|
127
|
|
|
|
|
|
|
sudo => $self->sudo ? 'true' : 'false', |
128
|
|
|
|
|
|
|
language => 'perl', |
129
|
|
|
|
|
|
|
matrix => { fast_finish => 'true' }, |
130
|
|
|
|
|
|
|
$self->support_builddir ? ( |
131
|
|
|
|
|
|
|
env => [ 'BUILD=0', 'BUILD=1' ], |
132
|
|
|
|
|
|
|
) : (), |
133
|
|
|
|
|
|
|
); |
134
|
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
my $email = $self->notify_email->[0]; |
136
|
0
|
|
|
|
|
|
my $irc = $self->notify_irc->[0]; |
137
|
0
|
|
|
|
|
|
my $rmeta = $self->zilla->distmeta->{resources}; |
138
|
|
|
|
|
|
|
|
139
|
0
|
|
|
|
|
|
my %notifications; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
# Perl versions |
142
|
0
|
|
|
|
|
|
my (@perls, @perls_allow_failures); |
143
|
0
|
0
|
0
|
|
|
|
if ($self->support_builddir && !$is_build_branch) { # dual DZIL+build YAML |
144
|
0
|
|
|
|
|
|
@perls = uniq map { s/^\-//; $_ } split(/\s+/, $self->perl_version.' '.$self->perl_version_build); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
145
|
0
|
|
|
|
|
|
@perls_allow_failures = ( |
146
|
|
|
|
|
|
|
( |
147
|
0
|
|
|
|
|
|
map { +{ perl => $_, env => 'BUILD=0' } } |
148
|
0
|
|
|
|
|
|
grep { s/^\-// } |
149
|
|
|
|
|
|
|
split(/\s+/, $self->perl_version) |
150
|
|
|
|
|
|
|
), ( |
151
|
0
|
|
|
|
|
|
map { +{ perl => $_, env => 'BUILD=1' } } |
152
|
0
|
|
|
|
|
|
grep { s/^\-// } |
153
|
|
|
|
|
|
|
split(/\s+/, $self->perl_version_build) |
154
|
|
|
|
|
|
|
) |
155
|
|
|
|
|
|
|
); |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
else { |
158
|
0
|
0
|
|
|
|
|
@perls = split(/\s+/, $is_build_branch ? $self->perl_version : $self->perl_version_build); |
159
|
0
|
|
|
|
|
|
@perls_allow_failures = |
160
|
0
|
|
|
|
|
|
map { +{ perl => $_ } } |
161
|
0
|
|
|
|
|
|
grep { s/^\-// } # also strips the dash from @perls |
162
|
|
|
|
|
|
|
@perls |
163
|
|
|
|
|
|
|
; |
164
|
|
|
|
|
|
|
} |
165
|
0
|
|
|
|
|
|
$travis_yml{perl} = \@perls; |
166
|
0
|
0
|
|
|
|
|
$travis_yml{matrix}{allow_failures} = \@perls_allow_failures if @perls_allow_failures; |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
# IRC |
169
|
0
|
0
|
0
|
0
|
|
|
$irc eq "1" and $irc = $self->notify_irc->[0] = $rmeta->{ first { /irc$/i } keys %$rmeta } || "0"; |
|
0
|
|
|
|
|
|
|
170
|
0
|
|
|
|
|
|
s#^irc:|/+##gi for @{$self->notify_irc}; |
|
0
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
|
172
|
0
|
0
|
|
|
|
|
if ($irc) { |
173
|
0
|
|
|
|
|
|
my %irc = ( |
174
|
|
|
|
|
|
|
on_success => 'change', |
175
|
|
|
|
|
|
|
on_failure => 'always', |
176
|
|
|
|
|
|
|
use_notice => 'true', |
177
|
|
|
|
|
|
|
); |
178
|
0
|
|
|
|
|
|
$irc{channels} = [grep { $_ } @{$self->notify_irc}]; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
179
|
0
|
|
|
|
|
|
$irc{template} = [grep { $_ } @{$self->irc_template}]; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
180
|
0
|
|
|
|
|
|
$notifications{irc} = \%irc; |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# Email |
184
|
0
|
0
|
|
|
|
|
$notifications{email} = ($email eq "0") ? "false" : [ grep { $_ } @{$self->notify_email} ] |
|
0
|
0
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
unless ($email eq "1"); |
186
|
|
|
|
|
|
|
|
187
|
0
|
0
|
|
|
|
|
$travis_yml{notifications} = \%notifications if %notifications; |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
### Prior to the custom mangling by the user, establish a default .travis.yml to work from |
190
|
0
|
|
|
|
|
|
my %travis_code = ( |
191
|
|
|
|
|
|
|
common => { # run for both dzil *and* build |
192
|
|
|
|
|
|
|
before_install => [ # install haarg's perl travis helpers |
193
|
|
|
|
|
|
|
'export AUTOMATED_TESTING=1 NONINTERACTIVE_TESTING=1 HARNESS_OPTIONS=j10:c HARNESS_TIMER=1', |
194
|
|
|
|
|
|
|
'git clone git://github.com/haarg/perl-travis-helper', |
195
|
|
|
|
|
|
|
'source perl-travis-helper/init', |
196
|
|
|
|
|
|
|
'build-perl', |
197
|
|
|
|
|
|
|
'perl -V', |
198
|
|
|
|
|
|
|
], |
199
|
|
|
|
|
|
|
}, |
200
|
|
|
|
|
|
|
dzil => {}, |
201
|
|
|
|
|
|
|
build => {}, |
202
|
|
|
|
|
|
|
); |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# needed for MDVT |
205
|
0
|
|
|
|
|
|
my @releases = @{$self->_releases}; |
|
0
|
|
|
|
|
|
|
206
|
0
|
|
|
|
|
|
my @releases_install; |
207
|
0
|
0
|
|
|
|
|
if (@releases) { |
208
|
0
|
|
|
|
|
|
@releases_install = ( |
209
|
|
|
|
|
|
|
# Install the lowest possible required version for the dependencies |
210
|
|
|
|
|
|
|
'export OLD_CPANM_OPT=$PERL_CPANM_OPT', |
211
|
|
|
|
|
|
|
"export PERL_CPANM_OPT='--mirror http://cpan.metacpan.org/ --mirror http://search.cpan.org/CPAN' \$PERL_CPANM_OPT", |
212
|
0
|
|
|
|
|
|
(map { 'cpanm --verbose ' .$_ } @releases), # first pass to force minimum versions |
213
|
0
|
|
|
|
|
|
(map { 'cpanm --verbose --installdeps '.$_ } @releases), # second pass to make sure conflicting deps are handled correctly |
214
|
|
|
|
|
|
|
'export PERL_CPANM_OPT=$OLD_CPANM_OPT', |
215
|
|
|
|
|
|
|
); |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
# DZIL Travis YAML |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# verbosity/testing and parallelized installs don't mix |
221
|
0
|
|
|
|
|
|
my $notest_cmd = 'xargs -n 5 -P 10 cpanm --quiet --notest'; |
222
|
0
|
|
|
|
|
|
my $test_cmd = 'cpanm --verbose'; |
223
|
|
|
|
|
|
|
|
224
|
0
|
|
|
|
|
|
$travis_code{dzil}{before_install} = [ |
225
|
|
|
|
|
|
|
# Fix for https://github.com/travis-ci/travis-cookbooks/issues/159 |
226
|
|
|
|
|
|
|
'git config --global user.name "TravisCI"', |
227
|
|
|
|
|
|
|
'git config --global user.email $HOSTNAME":not-for-mail@travis-ci.org"', |
228
|
|
|
|
|
|
|
]; |
229
|
0
|
0
|
|
|
|
|
$travis_code{dzil}{install} = scalar(@releases) ? \@releases_install : [ |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
230
|
|
|
|
|
|
|
"cpanm --quiet --notest --skip-satisfied Dist::Zilla", # this should already exist anyway... |
231
|
|
|
|
|
|
|
"dzil authordeps --missing | grep -vP '[^\\w:]' | ".($self->test_authordeps ? $test_cmd : $notest_cmd), |
232
|
|
|
|
|
|
|
"dzil listdeps --author --missing | grep -vP '[^\\w:]' | ".($self->test_deps ? $test_cmd : $notest_cmd), |
233
|
|
|
|
|
|
|
]; |
234
|
0
|
|
|
|
|
|
$travis_code{dzil}{script} = [ |
235
|
|
|
|
|
|
|
"dzil smoke --release --author", |
236
|
|
|
|
|
|
|
]; |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
# Build Travis YAML |
239
|
|
|
|
|
|
|
|
240
|
0
|
|
|
|
|
|
$travis_code{build}{before_install} = [ |
241
|
|
|
|
|
|
|
# Prevent any test problems with this file |
242
|
|
|
|
|
|
|
'rm .travis.yml', |
243
|
|
|
|
|
|
|
# Build tests shouldn't be considered "author testing" |
244
|
|
|
|
|
|
|
'export AUTHOR_TESTING=0', |
245
|
|
|
|
|
|
|
]; |
246
|
0
|
0
|
|
|
|
|
$travis_code{build}{install} = scalar(@releases) ? \@releases_install : [ |
|
|
0
|
|
|
|
|
|
247
|
|
|
|
|
|
|
'cpanm --installdeps --verbose '.($self->test_deps ? '' : '--notest').' .', |
248
|
|
|
|
|
|
|
]; |
249
|
|
|
|
|
|
|
|
250
|
0
|
0
|
|
|
|
|
if (my $bbranch = $self->build_branch) { |
251
|
0
|
|
|
|
|
|
$travis_code{build}{branches} = { only => $bbranch }; |
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
### See if any custom code is requested |
255
|
|
|
|
|
|
|
|
256
|
0
|
|
|
|
|
|
foreach my $phase (@phases) { |
257
|
|
|
|
|
|
|
# First, replace any new blocks, then deal with pre/post blocks |
258
|
0
|
|
|
|
|
|
foreach my $ft ('', '_dzil', '_build') { # YML file type; specific wins priority |
259
|
0
|
|
|
|
|
|
my $method = $phase.$ft; |
260
|
0
|
|
|
|
|
|
my $custom_cmds = $self->$method; |
261
|
|
|
|
|
|
|
|
262
|
0
|
0
|
0
|
|
|
|
if ($custom_cmds && @$custom_cmds) { |
263
|
0
|
|
|
|
|
|
foreach my $key ('dzil', 'build') { |
264
|
0
|
0
|
0
|
|
|
|
next unless (!$ft || substr($ft, 1) eq $key); |
265
|
0
|
|
|
|
|
|
$travis_code{$key}{$phase} = [ @$custom_cmds ]; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
} |
269
|
|
|
|
|
|
|
|
270
|
0
|
|
|
|
|
|
foreach my $ft ('', '_dzil', '_build') { |
271
|
0
|
|
|
|
|
|
foreach my $pos (qw(pre post)) { |
272
|
0
|
|
|
|
|
|
my $method = $pos.'_'.$phase.$ft; |
273
|
0
|
|
|
|
|
|
my $custom_cmds = $self->$method; |
274
|
|
|
|
|
|
|
|
275
|
0
|
0
|
0
|
|
|
|
if ($custom_cmds && @$custom_cmds) { |
276
|
0
|
|
|
|
|
|
foreach my $key ('dzil', 'build') { |
277
|
0
|
0
|
0
|
|
|
|
next unless (!$ft || substr($ft, 1) eq $key); |
278
|
0
|
|
0
|
|
|
|
$travis_code{$key}{$phase} //= []; |
279
|
|
|
|
|
|
|
|
280
|
0
|
|
|
|
|
|
$pos eq 'pre' ? |
281
|
0
|
|
|
|
|
|
unshift(@{$travis_code{$key}{$phase}}, @$custom_cmds) : |
282
|
0
|
0
|
|
|
|
|
push (@{$travis_code{$key}{$phase}}, @$custom_cmds) |
283
|
|
|
|
|
|
|
; |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# Insert %travis_code into %travis_yml |
291
|
0
|
0
|
|
|
|
|
unless ($is_build_branch) { |
|
|
0
|
|
|
|
|
|
292
|
|
|
|
|
|
|
# Standard DZIL YAML |
293
|
0
|
0
|
|
|
|
|
unless ($self->support_builddir) { |
294
|
0
|
|
|
|
|
|
%travis_yml = (%travis_yml, %{ $travis_code{dzil} }); |
|
0
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
# Dual DZIL+build YAML |
297
|
|
|
|
|
|
|
else { |
298
|
0
|
|
|
|
|
|
foreach my $phase (@phases) { # skip branches as well |
299
|
0
|
0
|
|
|
|
|
my @common = $travis_code{common}{$phase} ? @{ $travis_code{common} {$phase} } : (); |
|
0
|
|
|
|
|
|
|
300
|
0
|
0
|
|
|
|
|
my @dzil = $travis_code{dzil} {$phase} ? @{ $travis_code{dzil} {$phase} } : (); |
|
0
|
|
|
|
|
|
|
301
|
0
|
0
|
|
|
|
|
my @build = $travis_code{build} {$phase} ? @{ $travis_code{build} {$phase} } : (); |
|
0
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
|
303
|
0
|
0
|
|
|
|
|
if ($phase eq 'before_install') { |
304
|
0
|
|
|
|
|
|
@build = grep { $_ ne 'rm .travis.yml' } @build; # this won't actually exist in .build/testing |
|
0
|
|
|
|
|
|
|
305
|
0
|
|
|
|
|
|
unshift @build, 'cd .build/testing'; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
0
|
0
|
0
|
|
|
|
if (@common || @dzil || @build) { |
|
|
|
0
|
|
|
|
|
309
|
0
|
|
|
|
|
|
$travis_yml{$phase} = [ |
310
|
|
|
|
|
|
|
@common, |
311
|
0
|
|
|
|
|
|
( map { 'if [[ $BUILD == 0 ]]; then '.$_.'; fi' } @dzil ), |
312
|
0
|
|
|
|
|
|
( map { 'if [[ $BUILD == 1 ]]; then '.$_.'; fi' } @build ), |
313
|
|
|
|
|
|
|
]; |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# if the directory doesn't exist, unset $BUILD, so that everything else is a no-op |
317
|
0
|
0
|
|
|
|
|
unshift @{ $travis_yml{$phase} }, 'if [[ $BUILD == 1 && ! -d .build/testing ]]; then unset BUILD; fi' |
|
0
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
if $phase eq 'before_install'; |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# because {build}{script} normally doesn't have any lines, mimic the Travis default |
321
|
0
|
0
|
0
|
|
|
|
if ($phase eq 'script' and not @build) { |
322
|
0
|
|
|
|
|
|
push @{ $travis_yml{$phase} }, ( |
|
0
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
'if [[ $BUILD == 1 && -f Makefile.PL ]]; then perl Makefile.PL && make test; fi', |
324
|
|
|
|
|
|
|
'if [[ $BUILD == 1 && -f Build.PL ]]; then perl Build.PL && ./Build test; fi', |
325
|
|
|
|
|
|
|
'if [[ $BUILD == 1 && ! -f Makefile.PL && ! -f Build.PL ]]; then make test; fi', |
326
|
|
|
|
|
|
|
); |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
# Add 'only' option, if specified |
332
|
0
|
0
|
|
|
|
|
$travis_code{build}{branches} = { only => $self->dzil_branch } if $self->dzil_branch; |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
# Build branch YAML |
335
|
|
|
|
|
|
|
elsif ($self->build_branch) { |
336
|
0
|
|
|
|
|
|
%travis_yml = (%travis_yml, %{ $travis_code{build} }); |
|
0
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
} |
338
|
|
|
|
|
|
|
else { |
339
|
0
|
|
|
|
|
|
return; # no point in staying here... |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
### Dump YML (in order) |
343
|
0
|
|
|
|
|
|
local $YAML::Indent = 3; |
344
|
0
|
|
|
|
|
|
local $YAML::UseHeader = 0; |
345
|
|
|
|
|
|
|
|
346
|
0
|
|
|
|
|
|
my $node = YAML::Bless(\%travis_yml); |
347
|
0
|
|
|
|
|
|
$node->keys([grep { exists $travis_yml{$_} } @yml_order]); |
|
0
|
|
|
|
|
|
|
348
|
0
|
0
|
|
|
|
|
$self->log( "Rebuilding .travis.yml".($is_build_branch ? ' (in build dir)' : '') ); |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
# Add quotes to perl version strings, as Travis tends to remove the zeroes |
351
|
0
|
|
|
|
|
|
my $travis_yml = Dump \%travis_yml; |
352
|
0
|
|
|
|
|
|
$travis_yml =~ s/^(\s+- )(5\.\d+|blead)$/$1'$2'/gm; |
353
|
0
|
|
|
|
|
|
$travis_yml =~ s/^(\s+(?:- )?perl: )(5\.\d+|blead)$/$1'$2'/gm; |
354
|
|
|
|
|
|
|
|
355
|
0
|
|
|
|
|
|
my $file = Path::Class::File->new($self->zilla->built_in, '.travis.yml'); |
356
|
0
|
|
|
|
|
|
$file->spew($travis_yml); |
357
|
0
|
|
|
|
|
|
return $file; |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
sub _as_lucene_query { |
361
|
0
|
|
|
0
|
|
|
my ($self, $ver_str) = @_; |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
# simple versions short-circuits |
364
|
0
|
0
|
|
|
|
|
return () if $ver_str eq '0'; |
365
|
0
|
0
|
|
|
|
|
return ('module.version_numified:['.version->parse($ver_str)->numify.' TO 999999]') |
366
|
|
|
|
|
|
|
unless ($ver_str =~ /[\<\=\>]/); |
367
|
|
|
|
|
|
|
|
368
|
0
|
|
|
|
|
|
my ($min, $max, $is_min_inc, $is_max_inc, @num_conds, @str_conds); |
369
|
0
|
|
|
|
|
|
foreach my $ver_cmp (split(qr{\s*,\s*}, $ver_str)) { |
370
|
0
|
|
|
|
|
|
my ($cmp, $ver) = split(qr{(?<=[\<\=\>])\s*(?=\d)}, $ver_cmp, 2); |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
# Normalize string, but keep originals for alphas |
373
|
0
|
|
|
|
|
|
my $use_num = 1; |
374
|
0
|
|
|
|
|
|
my $orig_ver = $ver; |
375
|
0
|
|
|
|
|
|
$ver = version->parse($ver); |
376
|
0
|
|
|
|
|
|
my $num_ver = $ver->numify; |
377
|
0
|
0
|
|
|
|
|
if ($ver->is_alpha) { |
378
|
0
|
|
|
|
|
|
$ver = $orig_ver; |
379
|
0
|
|
|
|
|
|
$ver =~ s/^v//i; |
380
|
0
|
|
|
|
|
|
$use_num = 0; |
381
|
|
|
|
|
|
|
} |
382
|
0
|
|
|
|
|
|
else { $ver = $num_ver; } |
383
|
|
|
|
|
|
|
|
384
|
0
|
0
|
|
|
|
|
if ($cmp eq '==') { return 'module.version'.($use_num ? '_numified' : '').':'.$ver; } # no need to look at anything else |
|
0
|
0
|
|
|
|
|
|
385
|
0
|
0
|
|
|
|
|
if ($cmp eq '!=') { $use_num ? push(@num_conds, '-'.$ver) : push(@str_conds, '-'.$ver); } |
|
0
|
0
|
|
|
|
|
|
386
|
|
|
|
|
|
|
### XXX: Trying to do range-based searches on strings isn't a good idea, so we always use the number field ### |
387
|
0
|
0
|
|
|
|
|
if ($cmp eq '>=') { ($min, $is_min_inc) = ($num_ver, 1); } |
|
0
|
|
|
|
|
|
|
388
|
0
|
0
|
|
|
|
|
if ($cmp eq '<=') { ($max, $is_max_inc) = ($num_ver, 1); } |
|
0
|
|
|
|
|
|
|
389
|
0
|
0
|
|
|
|
|
if ($cmp eq '>') { ($min, $is_min_inc) = ($num_ver, 0); } |
|
0
|
|
|
|
|
|
|
390
|
0
|
0
|
|
|
|
|
if ($cmp eq '<') { ($max, $is_max_inc) = ($num_ver, 0); } |
|
0
|
|
|
|
|
|
|
391
|
0
|
|
|
|
|
|
else { die 'Unable to parse complex module requirements with operator of '.$cmp.' !'; } |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
# Min/Max parsing |
395
|
0
|
0
|
0
|
|
|
|
if ($min || $max) { |
396
|
0
|
|
0
|
|
|
|
$min ||= 0; |
397
|
0
|
|
0
|
|
|
|
$max ||= 999999; |
398
|
0
|
|
|
|
|
|
my $rng = $min.' TO '.$max; |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
# Figure out the inclusive/exclusive status |
401
|
0
|
|
|
|
|
|
my $inc = $is_min_inc.$is_max_inc; # (this is just easier to deal with as a combined form) |
402
|
0
|
0
|
0
|
|
|
|
unshift @num_conds, '-'.($inc eq '01' ? $min : $max) |
|
|
0
|
|
|
|
|
|
403
|
|
|
|
|
|
|
if ($inc =~ /0/ && $inc =~ /\d\d/); # has mismatch of inc/exc (reverse order due to unshift) |
404
|
0
|
0
|
|
|
|
|
unshift @num_conds, '+'.($inc =~ /1/ ? '['.$rng.']' : '{'.$rng.'}'); # +[{ $min TO $max }] |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
# Create the string |
408
|
0
|
|
|
|
|
|
my @lq; |
409
|
0
|
0
|
|
|
|
|
push @lq, 'module.version_numified:('.join(' ', @num_conds).')' if @num_conds; |
410
|
0
|
0
|
|
|
|
|
push @lq, 'module.version:(' .join(' ', @str_conds).')' if @str_conds; |
411
|
0
|
|
|
|
|
|
return @lq; |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
sub _mcpan_module_minrelease { |
415
|
0
|
|
|
0
|
|
|
my ($self, $module, $ver_str, $try_harder) = @_; |
416
|
|
|
|
|
|
|
|
417
|
0
|
|
|
|
|
|
my @lq = $self->_as_lucene_query($ver_str); |
418
|
0
|
0
|
|
|
|
|
my $maturity_q = ($ver_str =~ /==/) ? undef : 'maturity:released'; # exact version may be a developer one |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
### XXX: This should be replaced with a ->file() method when those |
421
|
|
|
|
|
|
|
### two pull requests of mine are put into CPAN... |
422
|
0
|
|
|
|
|
|
my $q = join(' AND ', 'module.name:"'.$module.'"', $maturity_q, 'module.authorized:true', @lq); |
423
|
0
|
|
|
|
|
|
$self->log_debug("Checking module $module via MetaCPAN"); |
424
|
|
|
|
|
|
|
#$self->log_debug(" [q=$q]"); |
425
|
0
|
0
|
|
|
|
|
my $details = $self->mcpan->fetch("file/_search", |
426
|
|
|
|
|
|
|
q => $q, |
427
|
|
|
|
|
|
|
sort => 'module.version_numified', |
428
|
|
|
|
|
|
|
fields => 'author,release,distribution,module.version,module.name', |
429
|
|
|
|
|
|
|
size => $try_harder ? 20 : 1, |
430
|
|
|
|
|
|
|
); |
431
|
0
|
0
|
0
|
|
|
|
unless ($details && $details->{hits}{total}) { |
432
|
0
|
|
|
|
|
|
$self->log("??? MetaCPAN can't even find a good version for $module!"); |
433
|
0
|
|
|
|
|
|
return undef; |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
### XXX: Figure out better ways to find these modules with multiple package names (ie: Moose::Autobox, EUMM) |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
# Sometimes, MetaCPAN just gets highly confused... |
439
|
0
|
|
|
|
|
|
my @hits = @{ $details->{hits}{hits} }; |
|
0
|
|
|
|
|
|
|
440
|
0
|
|
|
|
|
|
my $hit; |
441
|
0
|
|
|
|
|
|
my $is_bad = 1; |
442
|
0
|
|
0
|
|
|
|
while ($is_bad and @hits) { |
443
|
0
|
|
|
|
|
|
$hit = shift @hits; |
444
|
|
|
|
|
|
|
# (ie: we shouldn't have multiples of modules or versions, and sort should actually have a value) |
445
|
0
|
|
0
|
|
|
|
$is_bad = !$hit->{sort}[0] || ref $hit->{fields}{'module.name'} || ref $hit->{fields}{'module.version'}; |
446
|
|
|
|
|
|
|
}; |
447
|
|
|
|
|
|
|
|
448
|
0
|
0
|
|
|
|
|
if ($is_bad) { |
449
|
0
|
0
|
|
|
|
|
if ($try_harder) { |
450
|
0
|
|
|
|
|
|
$self->log("??? MetaCPAN is highly confused about $module!"); |
451
|
0
|
|
|
|
|
|
return undef; |
452
|
|
|
|
|
|
|
} |
453
|
0
|
|
|
|
|
|
$self->log_debug(" MetaCPAN got confused; trying harder..."); |
454
|
0
|
|
|
|
|
|
return $self->_mcpan_module_minrelease($module, $ver_str, 1) |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
|
457
|
0
|
|
|
|
|
|
$hit = $hit->{fields}; |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
# This will almost always be .tar.gz, but TRIAL versions might have different names, etc. |
460
|
0
|
|
|
|
|
|
my $fields = $self->mcpan->release( |
461
|
|
|
|
|
|
|
search => { |
462
|
|
|
|
|
|
|
q => 'author:'.$hit->{author}.' AND name:"'.$hit->{release}.'"', |
463
|
|
|
|
|
|
|
fields => 'archive,tests', |
464
|
|
|
|
|
|
|
size => 1, |
465
|
|
|
|
|
|
|
}, |
466
|
|
|
|
|
|
|
)->{hits}{hits}[0]{fields}; |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
# Warn about test failures |
469
|
0
|
|
|
|
|
|
my $t = $fields->{tests}; |
470
|
0
|
|
|
|
|
|
my $ttl = sum @$t{qw(pass fail unknown na)}; |
471
|
0
|
0
|
|
|
|
|
unless ($ttl) { |
472
|
0
|
|
|
|
|
|
$self->log(['%s has no CPAN test results! You should consider upgrading the minimum dep version for %s...', $hit->{release}, $module]); |
473
|
|
|
|
|
|
|
} |
474
|
|
|
|
|
|
|
else { |
475
|
0
|
|
|
|
|
|
my $per = $t->{pass} / $ttl * 100; |
476
|
0
|
|
|
|
|
|
my $f_ttl = $ttl - $t->{pass}; |
477
|
|
|
|
|
|
|
|
478
|
0
|
0
|
0
|
|
|
|
if ($per < 70 || $t->{fail} > 20 || $f_ttl > 30) { |
|
|
|
0
|
|
|
|
|
479
|
0
|
|
|
|
|
|
$self->log(['CPAN Test Results for %s:', $hit->{release}]); |
480
|
0
|
|
|
|
|
|
$self->log([' %7s: %4u (%3.1f)', $_, $t->{lc $_}, $t->{lc $_} / $ttl * 100]) for (qw(Pass Fail Unknown NA)); |
481
|
0
|
|
|
|
|
|
$self->log(['You should consider upgrading the minimum dep version for %s...', $module]); |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
|
485
|
0
|
|
|
|
|
|
my $v = $hit->{'module.version'}; |
486
|
0
|
|
0
|
|
|
|
return ($hit->{distribution}, $hit->{author}.'/'.$fields->{archive}, $v && version->parse($v)); |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
42; |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
__END__ |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
=pod |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
=encoding UTF-8 |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
=head1 NAME |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
Dist::Zilla::Role::TravisYML - Role for .travis.yml creation |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
=head1 AVAILABILITY |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
The project homepage is L<https://github.com/SineSwiper/Dist-Zilla-TravisCI>. |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
The latest version of this module is available from the Comprehensive Perl |
506
|
|
|
|
|
|
|
Archive Network (CPAN). Visit L<http://www.perl.com/CPAN/> to find a CPAN |
507
|
|
|
|
|
|
|
site near you, or see L<https://metacpan.org/module/Dist::Zilla::TravisCI/>. |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
=head1 AUTHOR |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
Brendan Byrd <bbyrd@cpan.org> |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
This software is Copyright (c) 2015 by Brendan Byrd. |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
This is free software, licensed under: |
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
The Artistic License 2.0 (GPL Compatible) |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
=cut |