File Coverage

blib/lib/App/test/travis.pm
Criterion Covered Total %
statement 84 95 88.4
branch 11 20 55.0
condition 7 14 50.0
subroutine 17 19 89.4
pod 0 4 0.0
total 119 152 78.2


line stmt bran cond sub pod time code
1             package App::test::travis;
2 1     1   38290 use 5.10.0;
  1         3  
  1         37  
3 1     1   4 use strict;
  1         2  
  1         28  
4 1     1   5 use warnings;
  1         5  
  1         23  
5              
6 1     1   832 use version; our $VERSION = version->declare("v0.9.7");
  1         2246  
  1         6  
7              
8 1     1   1072 use encoding::warnings 'FATAL';
  1         647  
  1         5  
9 1     1   15736 use Fatal qw(open close);
  1         18119  
  1         8  
10              
11 1     1   4157 use File::Temp qw(tempdir);
  1         35490  
  1         50  
12 1     1   1488 use Config qw(%Config);
  1         2  
  1         12  
13 1     1   44 use File::Spec ();
  1         2  
  1         8  
14 1     1   1223 use Getopt::Long qw(GetOptionsFromArray :config posix_default no_ignore_case bundling auto_version);
  1         11668  
  1         7  
15 1     1   2021 use autouse 'Pod::Usage' => qw(pod2usage);
  1         696  
  1         5  
16 1     1   159 use autouse 'Pod::Find' => qw(pod_where);
  1         1  
  1         6  
17 1     1   935 use YAML ();
  1         8758  
  1         103  
18              
19             my $path_sep = $Config{path_sep};
20              
21             my %tab = (
22             c => {
23             script => './configure && make && make test',
24             },
25             cpp => {
26             script => './configure && make && make test',
27             },
28             clojure => {
29             script => 'lein test',
30             },
31             erlang => {
32             install => 'rebar get-deps',
33             script => 'rebar compile && rebar skip_deps=true eunit',
34             },
35             go => {
36             install => 'go get -d -v ./... && go build -v ./...',
37             script => 'make',
38             },
39             groovy => {
40             install => 'gradle assemble',
41             script => 'gradle check',
42             },
43             haskell => {
44             install => 'cabal install --only-dependencies --enable-tests',
45             script => 'cabal configure --enable-tests && cabal build && cabal test',
46             },
47             java => {
48             install => 'mvn install -DskipTests=true',
49             script => 'mvn test',
50             },
51              
52             node_js => {
53             setup => sub {
54             my($config, $tempdir, $cb) = @_;
55             local $ENV{PATH} = join $path_sep, "node_modules/.bin", $ENV{PATH};
56             $cb->();
57             },
58             install => 'npm install',
59             script => 'npm test',
60             },
61              
62             perl => {
63             setup => sub {
64             my($config, $tempdir, $cb) = @_;
65             local $ENV{PERL_CPANM_OPT} = "-l$tempdir --verbose";
66             local $ENV{PERL5OPT} = "-Mlib=$tempdir/lib/perl5";
67             local $ENV{PATH} = join $path_sep, "$tempdir/bin", $ENV{PATH};
68              
69             $cb->();
70             },
71             install => 'cpanm --installdeps --notest .',
72             script => 'cpanm --test-only .',
73             },
74              
75             php => {
76             script => 'phpunit',
77             },
78              
79             python => {
80             install => 'pip install -r requirements.txt --use-mirrors',
81             },
82              
83             ruby => {
84             install => 'bundle install',
85             script => 'bundle exec rake',
86             },
87              
88             scala => {
89             script => 'sbt test',
90             },
91             );
92              
93             sub run {
94 2     2 0 828 my($class, @args) = @_;
95              
96 2         11 my $start = time();
97              
98 2         5 my $DRY_RUN;
99             my $HELP;
100              
101 2 50       16 GetOptionsFromArray(\@args,
102             '--dry-run' => \$DRY_RUN,
103             '--help' => \$HELP,
104             ) or return help(1);
105 2 50       692 return help(0) if $HELP;
106              
107 2         5 my($travis_yml) = @args;
108 2   50     7 $travis_yml //= '.travis.yml';
109              
110 2         11 my $config = YAML::LoadFile($travis_yml);
111              
112 2   50     49510 my $language = lc($config->{language} // 'ruby');
113              
114 2 50       15 my $behavior = $tab{$language} or die "no behavior defined for $language\n";
115              
116 2         76 close STDIN;
117 2         130 open STDIN, '<', File::Spec->devnull;
118              
119 2 50 33     191 if ($ENV{TRAVIS} && $ENV{CI}) {
120 0         0 say '# skip because TRAVIS and CI are already set';
121 0         0 return;
122             }
123 2         113 say "# running $travis_yml";
124              
125             # Travis CI Environment Variables
126             # http://about.travis-ci.org/docs/user/osx-ci-environment/
127 2         22 local $ENV{CI} = 'true';
128 2         11 local $ENV{TRAVIS} = 'true';
129              
130 2         14 my $tempdir = tempdir('.travis-run-XXXXXXX', CLEANUP => 1);
131             my $setup = $behavior->{setup} // sub {
132 0     0   0 my($config, $tempdir, $cb) = @_;
133 0         0 $cb->();
134 2   50     955 };
135              
136 2         8 for my $mode(qw(before_install install script)) {
137 6   66     30 $config->{$mode} //= $behavior->{$mode};
138             }
139              
140             $setup->($config, $tempdir, sub {
141 2   50 2   9 my $versions = $config->{$language} // []; # TODO
142              
143             # http://about.travis-ci.org/docs/user/build-configuration/#Build-Lifecycle
144 2         8 run_commands($config, $DRY_RUN, 'before_install');
145 2         5 run_commands($config, $DRY_RUN, 'install');
146 2         5 run_commands($config, $DRY_RUN, 'before_script');
147 2         5 eval {
148 2         4 run_commands($config, $DRY_RUN, 'script');
149             };
150 2 50       8 if (! $@) {
151 2         5 run_commands($config, $DRY_RUN, 'after_success');
152             }
153             else {
154 0         0 run_commands($config, $DRY_RUN, 'after_failure');
155             }
156 2         5 run_commands($config, $DRY_RUN, 'after_script');
157              
158 2         248 say '# finished: ', scalar localtime;
159              
160 2         7 my $duration = (time() - $start);
161 2 50       6 if ($duration > 60) {
162 0         0 say sprintf '# duration: %d min %d sec', int($duration / 60), $duration % 60;
163             }
164             else {
165 2         28 say sprintf '# duration: %d sec', $duration;
166             }
167 2         20 });
168 2         49 return 0;
169             }
170              
171             sub run_commands {
172 12     12 0 17 my($config, $dry_run, $mode) = @_;
173 12 100       58 return unless defined $config->{$mode};
174 6         38 say "# $mode";
175 3         9 my @cmds = ref($config->{$mode}) eq 'ARRAY'
176 6 100       31 ? @{$config->{$mode}}
177             : ($config->{$mode});
178 6         11 for my $cmd(@cmds) {
179 7         15 xsystem($dry_run, $cmd);
180             }
181             }
182              
183             sub xsystem {
184 7     7 0 11 my($dry_run, @command) = @_;
185              
186 7         39 say "\$ @command";
187 7 50       33 unless($dry_run) {
188 0 0         system(@command) == 0 or die "failed to call `@command`";
189             }
190             }
191              
192             sub help {
193 0     0 0   my($exit_status) = @_;
194 0           my $pod_file = pod_where({ -inc => 1 }, __PACKAGE__);
195 0           pod2usage(
196             -exitval => 'noexit',
197             -input => $pod_file,
198             );
199 0           return $exit_status;
200             }
201             1;
202             __END__