134. •Create an EC2 image
•Put perlbrew on it
•Install every Perl locally
135. •Create an EC2 image
•Put perlbrew on it
•Install every Perl locally
•Boot an instance for every
uploaded distribution
136. •Create an EC2 image
•Put perlbrew on it
•Install every Perl locally
•Boot an instance for every
uploaded distribution
•Install needed dependencies
for the distribution
137. •Create an EC2 image
•Put perlbrew on it
•Install every Perl locally
•Boot an instance for every
uploaded distribution
•Install needed dependencies
for the distribution
•Run the tests and report the
results
138. •Create an EC2 image
•Put perlbrew on it
•Install every Perl locally
•Boot an instance for every
uploaded distribution
•Install needed dependencies
for the distribution
•Run the tests and report the
results
•Shut down the instance
151. App::cpanminus
That means the same cpanm can be run by any perl
perlbrew switch master
curl -L http://cpanmin.us/ | perl - App::cpanminus
ln -s ~/perl5/perlbrew/perls/master/bin/cpanm ./cpanm
~/perl5/perlbrew/perls/perl-5.8.9/bin/perl cpanm
~/perl5/perlbrew/perls/perl-5.10.1/bin/perl cpanm
~/perl5/perlbrew/perls/perl-5.12.5/bin/perl cpanm
~/perl5/perlbrew/perls/perl-5.14.4/bin/perl cpanm
~/perl5/perlbrew/perls/perl-5.16.3/bin/perl cpanm
~/perl5/perlbrew/perls/perl-5.18.0/bin/perl cpanm
~/perl5/perlbrew/perls/perl-5.19.0/bin/perl cpanm
154. •Use perlbrew to install a "master" perl
•Use it again to install "virgin" perls of every
major version
155. •Use perlbrew to install a "master" perl
•Use it again to install "virgin" perls of every
major version
•Use the master perl to install everything
from CPAN that makes CPANci work
156. •Use perlbrew to install a "master" perl
•Use it again to install "virgin" perls of every
major version
•Use the master perl to install everything
from CPAN that makes CPANci work
•For each distribution, create a temp
directory
157. •Use perlbrew to install a "master" perl
•Use it again to install "virgin" perls of every
major version
•Use the master perl to install everything
from CPAN that makes CPANci work
•For each distribution, create a temp
directory
•Tell cpanminus to install dependencies
there, as if for local::lib
158. •Use perlbrew to install a "master" perl
•Use it again to install "virgin" perls of every
major version
•Use the master perl to install everything
from CPAN that makes CPANci work
•For each distribution, create a temp
directory
•Tell cpanminus to install dependencies
there, as if for local::lib
•Run tests and report results
159. •Use perlbrew to install a "master" perl
•Use it again to install "virgin" perls of every
major version
•Use the master perl to install everything
from CPAN that makes CPANci work
•For each distribution, create a temp
directory
•Tell cpanminus to install dependencies
there, as if for local::lib
•Run tests and report results
•Delete temp directory, leaving each perl
untouched!
160. What does that look like?
The "fetcher" grabs the latest distribution URLs from
MetaCPAN's RSS feed.
my $xml = XML::LibXML->load_xml(
string => $self->ua->get( $self->rss_base )->decoded_content
);
my @dists = map {
my $u = URI->new( $_->getAttribute( 'rdf:resource' ) );
$u->host( 'api.metacpan.org' );
$u->path( 'v0' . $u->path );
$u;
} $xml->findnodes( '//rdf:li' );
161. What does that look like?
The "fetcher" grabs the latest distribution URLs from
MetaCPAN's RSS feed.
my $xml = XML::LibXML->load_xml(
string => $self->ua->get( $self->rss_base )->decoded_content
);
my @dists = map {
my $u = URI->new( $_->getAttribute( 'rdf:resource' ) );
$u->host( 'api.metacpan.org' );
$u->path( 'v0' . $u->path );
$u;
} $xml->findnodes( '//rdf:li' );
162. What does that look like?
The "fetcher" grabs the latest distribution URLs from
MetaCPAN's RSS feed.
my $xml = XML::LibXML->load_xml(
string => $self->ua->get( $self->rss_base )->decoded_content
);
my @dists = map {
my $u = URI->new( $_->getAttribute( 'rdf:resource' ) );
$u->host( 'api.metacpan.org' );
$u->path( 'v0' . $u->path );
$u;
} $xml->findnodes( '//rdf:li' );
163. What does that look like?
The "fetcher" grabs the latest distribution URLs from
MetaCPAN's RSS feed.
my $xml = XML::LibXML->load_xml(
string => $self->ua->get( $self->rss_base )->decoded_content
);
my @dists = map {
my $u = URI->new( $_->getAttribute( 'rdf:resource' ) );
$u->host( 'api.metacpan.org' );
$u->path( 'v0' . $u->path );
$u;
} $xml->findnodes( '//rdf:li' );
164. What does that look like?
We retrieve the distribution metadata from
the MetaCPAN JSON API and save it to
MongoDB.
foreach my $dist( @dists ) {
my $fetched_data = decode_json
$self->ua->get( $dist )->decoded_content;
my %ins = ( _id => 'cpan/' . $name,
fetched => DateTime->now,
meta => $fetched_data );
$coll->insert( %ins );
}
165. What does that look like?
We retrieve the distribution metadata from
the MetaCPAN JSON API and save it to
MongoDB.
foreach my $dist( @dists ) {
my $fetched_data = decode_json
$self->ua->get( $dist )->decoded_content;
my %ins = ( _id => 'cpan/' . $name,
fetched => DateTime->now,
meta => $fetched_data );
$coll->insert( %ins );
}
166. What does that look like?
We retrieve the distribution metadata from
the MetaCPAN JSON API and save it to
MongoDB.
foreach my $dist( @dists ) {
my $fetched_data = decode_json
$self->ua->get( $dist )->decoded_content;
my %ins = ( _id => 'cpan/' . $name,
fetched => DateTime->now,
meta => $fetched_data );
$coll->insert( %ins );
}
167. What does that look like?
We retrieve the distribution metadata from
the MetaCPAN JSON API and save it to
MongoDB.
foreach my $dist( @dists ) {
my $fetched_data = decode_json
$self->ua->get( $dist )->decoded_content;
my %ins = ( _id => 'cpan/' . $name,
fetched => DateTime->now,
meta => $fetched_data );
$coll->insert( %ins );
}
168. What does that look like?
We retrieve the distribution metadata from
the MetaCPAN JSON API and save it to
MongoDB.
foreach my $dist( @dists ) {
my $fetched_data = decode_json
$self->ua->get( $dist )->decoded_content;
my %ins = ( _id => 'cpan/' . $name,
fetched => DateTime->now,
meta => $fetched_data );
$coll->insert( %ins );
}
169. What does that look like?
We extract the archive in a specific "work" directory
for each perl.
Then use a temp directory for building and installing
dependencies.
foreach my $perl ( @{ $self->perls } ) {
my $workdir = catdir $self->home, 'work', $perl, $dist;
chdir $workdir;
}
170. What does that look like?
We extract the archive in a specific "work" directory
for each perl.
Then use a temp directory for building and installing
dependencies.
foreach my $perl ( @{ $self->perls } ) {
my $workdir = catdir $self->home, 'work', $perl, $dist;
chdir $workdir;
}
171. What does that look like?
We extract the archive in a specific "work" directory
for each perl.
Then use a temp directory for building and installing
dependencies.
foreach my $perl ( @{ $self->perls } ) {
my $workdir = catdir $self->home, 'work', $perl, $dist;
chdir $workdir;
}
172. What does that look like?
We extract the archive in a specific "work" directory
for each perl.
Then use a temp directory for building and installing
dependencies.
foreach my $perl ( @{ $self->perls } ) {
my $workdir = catdir $self->home, 'work', $perl, $dist;
chdir $workdir;
}
173. What does that look like?
Use a specific perl binary to run cpanm and
install dependencies, with no tests, to the temp
directory.
Then we parse the cpanm log on stderr
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $pid = open3 $wtr, $rdr, $err, $plbin, $self->cpanm,
'--installdeps', '--notest', '-L', $dist_tmp, '.';
my $results = $self->_read_cpanm_deps_log( $err );
174. What does that look like?
Use a specific perl binary to run cpanm and
install dependencies, with no tests, to the temp
directory.
Then we parse the cpanm log on stderr
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $pid = open3 $wtr, $rdr, $err, $plbin, $self->cpanm,
'--installdeps', '--notest', '-L', $dist_tmp, '.';
my $results = $self->_read_cpanm_deps_log( $err );
175. What does that look like?
Use a specific perl binary to run cpanm and
install dependencies, with no tests, to the temp
directory.
Then we parse the cpanm log on stderr
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $pid = open3 $wtr, $rdr, $err, $plbin, $self->cpanm,
'--installdeps', '--notest', '-L', $dist_tmp, '.';
my $results = $self->_read_cpanm_deps_log( $err );
176. What does that look like?
Use a specific perl binary to run cpanm and
install dependencies, with no tests, to the temp
directory.
Then we parse the cpanm log on stderr
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $pid = open3 $wtr, $rdr, $err, $plbin, $self->cpanm,
'--installdeps', '--notest', '-L', $dist_tmp, '.';
my $results = $self->_read_cpanm_deps_log( $err );
177. What does that look like?
Use a specific perl binary to run cpanm and
install dependencies, with no tests, to the temp
directory.
Then we parse the cpanm log on stderr
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $pid = open3 $wtr, $rdr, $err, $plbin, $self->cpanm,
'--installdeps', '--notest', '-L', $dist_tmp, '.';
my $results = $self->_read_cpanm_deps_log( $err );
178. What does that look like?
Use a specific perl binary to run cpanm and
install dependencies, with no tests, to the temp
directory.
Then we parse the cpanm log on stderr
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $pid = open3 $wtr, $rdr, $err, $plbin, $self->cpanm,
'--installdeps', '--notest', '-L', $dist_tmp, '.';
my $results = $self->_read_cpanm_deps_log( $err );
180. What does that look like?
Use a specific perl to run each test file,
save the TAP output and any errors, and
use the exit status to determine if it passed.
foreach my $test( @tests ) {
my @test_results;
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $idir = catdir $dist_tmp, 'lib', 'perl5';
my $pid = open3 $wtr, $rdr, $plbin, '-I', $idir, $test;
my ( $tap_out, $errors );
{ local $/;
$tap_out = readline $rdr; $errors = readline $err;
}
waitpid $pid, 0;
my $passed = ( ( $? >> 8 ) == 0 ) true : false );
}
181. What does that look like?
Use a specific perl to run each test file,
save the TAP output and any errors, and
use the exit status to determine if it passed.
foreach my $test( @tests ) {
my @test_results;
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $idir = catdir $dist_tmp, 'lib', 'perl5';
my $pid = open3 $wtr, $rdr, $plbin, '-I', $idir, $test;
my ( $tap_out, $errors );
{ local $/;
$tap_out = readline $rdr; $errors = readline $err;
}
waitpid $pid, 0;
my $passed = ( ( $? >> 8 ) == 0 ) true : false );
}
182. What does that look like?
Use a specific perl to run each test file,
save the TAP output and any errors, and
use the exit status to determine if it passed.
foreach my $test( @tests ) {
my @test_results;
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $idir = catdir $dist_tmp, 'lib', 'perl5';
my $pid = open3 $wtr, $rdr, $plbin, '-I', $idir, $test;
my ( $tap_out, $errors );
{ local $/;
$tap_out = readline $rdr; $errors = readline $err;
}
waitpid $pid, 0;
my $passed = ( ( $? >> 8 ) == 0 ) true : false );
}
183. What does that look like?
Use a specific perl to run each test file,
save the TAP output and any errors, and
use the exit status to determine if it passed.
foreach my $test( @tests ) {
my @test_results;
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $idir = catdir $dist_tmp, 'lib', 'perl5';
my $pid = open3 $wtr, $rdr, $plbin, '-I', $idir, $test;
my ( $tap_out, $errors );
{ local $/;
$tap_out = readline $rdr; $errors = readline $err;
}
waitpid $pid, 0;
my $passed = ( ( $? >> 8 ) == 0 ) true : false );
}
184. What does that look like?
Use a specific perl to run each test file,
save the TAP output and any errors, and
use the exit status to determine if it passed.
foreach my $test( @tests ) {
my @test_results;
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $idir = catdir $dist_tmp, 'lib', 'perl5';
my $pid = open3 $wtr, $rdr, $plbin, '-I', $idir, $test;
my ( $tap_out, $errors );
{ local $/;
$tap_out = readline $rdr; $errors = readline $err;
}
waitpid $pid, 0;
my $passed = ( ( $? >> 8 ) == 0 ) true : false );
}
185. What does that look like?
Use a specific perl to run each test file,
save the TAP output and any errors, and
use the exit status to determine if it passed.
foreach my $test( @tests ) {
my @test_results;
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $idir = catdir $dist_tmp, 'lib', 'perl5';
my $pid = open3 $wtr, $rdr, $plbin, '-I', $idir, $test;
my ( $tap_out, $errors );
{ local $/;
$tap_out = readline $rdr; $errors = readline $err;
}
waitpid $pid, 0;
my $passed = ( ( $? >> 8 ) == 0 ) true : false );
}
186. What does that look like?
Use a specific perl to run each test file,
save the TAP output and any errors, and
use the exit status to determine if it passed.
foreach my $test( @tests ) {
my @test_results;
my $plbin = catfile $self->pldir, $perl, 'bin', 'perl';
my $idir = catdir $dist_tmp, 'lib', 'perl5';
my $pid = open3 $wtr, $rdr, $plbin, '-I', $idir, $test;
my ( $tap_out, $errors );
{ local $/;
$tap_out = readline $rdr; $errors = readline $err;
}
waitpid $pid, 0;
my $passed = ( ( $? >> 8 ) == 0 ) true : false );
}
187. What does that look like?
Parse the TAP output of each test into a
structure which can be saved in MongoDB
eval {
my $parser = TAP::Parser->new( { source => $tap_out } );
while( my $result = $parser->next ) {
push @test_results,
{ text => $result->as_string,
ok => ( $result_is_ok ? true : false ),
type => $result->type,
$result->type eq 'test' ?
( number => $result->number,
desc => ( $result->description =~ s/^- //r )
) : ( ),
};
}
};
188. What does that look like?
Parse the TAP output of each test into a
structure which can be saved in MongoDB
eval {
my $parser = TAP::Parser->new( { source => $tap_out } );
while( my $result = $parser->next ) {
push @test_results,
{ text => $result->as_string,
ok => ( $result_is_ok ? true : false ),
type => $result->type,
$result->type eq 'test' ?
( number => $result->number,
desc => ( $result->description =~ s/^- //r )
) : ( ),
};
}
};
189. What does that look like?
Parse the TAP output of each test into a
structure which can be saved in MongoDB
eval {
my $parser = TAP::Parser->new( { source => $tap_out } );
while( my $result = $parser->next ) {
push @test_results,
{ text => $result->as_string,
ok => ( $result_is_ok ? true : false ),
type => $result->type,
$result->type eq 'test' ?
( number => $result->number,
desc => ( $result->description =~ s/^- //r )
) : ( ),
};
}
};
190. What does that look like?
Parse the TAP output of each test into a
structure which can be saved in MongoDB
eval {
my $parser = TAP::Parser->new( { source => $tap_out } );
while( my $result = $parser->next ) {
push @test_results,
{ text => $result->as_string,
ok => ( $result_is_ok ? true : false ),
type => $result->type,
$result->type eq 'test' ?
( number => $result->number,
desc => ( $result->description =~ s/^- //r )
) : ( ),
};
}
};
191. What does that look like?
Parse the TAP output of each test into a
structure which can be saved in MongoDB
eval {
my $parser = TAP::Parser->new( { source => $tap_out } );
while( my $result = $parser->next ) {
push @test_results,
{ text => $result->as_string,
ok => ( $result_is_ok ? true : false ),
type => $result->type,
$result->type eq 'test' ?
( number => $result->number,
desc => ( $result->description =~ s/^- //r )
) : ( ),
};
}
};
192. What does that look like?
Parse the TAP output of each test into a
structure which can be saved in MongoDB
eval {
my $parser = TAP::Parser->new( { source => $tap_out } );
while( my $result = $parser->next ) {
push @test_results,
{ text => $result->as_string,
ok => ( $result_is_ok ? true : false ),
type => $result->type,
$result->type eq 'test' ?
( number => $result->number,
desc => ( $result->description =~ s/^- //r )
) : ( ),
};
}
};
193. What does that look like?
Parse the TAP output of each test into a
structure which can be saved in MongoDB
eval {
my $parser = TAP::Parser->new( { source => $tap_out } );
while( my $result = $parser->next ) {
push @test_results,
{ text => $result->as_string,
ok => ( $result_is_ok ? true : false ),
type => $result->type,
$result->type eq 'test' ?
( number => $result->number,
desc => ( $result->description =~ s/^- //r )
) : ( ),
};
}
};
194. What does that look like?
Parse the TAP output of each test into a
structure which can be saved in MongoDB
eval {
my $parser = TAP::Parser->new( { source => $tap_out } );
while( my $result = $parser->next ) {
push @test_results,
{ text => $result->as_string,
ok => ( $result_is_ok ? true : false ),
type => $result->type,
$result->type eq 'test' ?
( number => $result->number,
desc => ( $result->description =~ s/^- //r )
) : ( ),
};
}
};
195. What does that look like?
Parse the TAP output of each test into a
structure which can be saved in MongoDB
eval {
my $parser = TAP::Parser->new( { source => $tap_out } );
while( my $result = $parser->next ) {
push @test_results,
{ text => $result->as_string,
ok => ( $result_is_ok ? true : false ),
type => $result->type,
$result->type eq 'test' ?
( number => $result->number,
desc => ( $result->description =~ s/^- //r )
) : ( ),
};
}
};
196. What does that look like?
Parse the TAP output of each test into a
structure which can be saved in MongoDB
eval {
my $parser = TAP::Parser->new( { source => $tap_out } );
while( my $result = $parser->next ) {
push @test_results,
{ text => $result->as_string,
ok => ( $result_is_ok ? true : false ),
type => $result->type,
$result->type eq 'test' ?
( number => $result->number,
desc => ( $result->description =~ s/^- //r )
) : ( ),
};
}
};
197. What does that look like?
Parse the TAP output of each test into a
structure which can be saved in MongoDB
eval {
my $parser = TAP::Parser->new( { source => $tap_out } );
while( my $result = $parser->next ) {
push @test_results,
{ text => $result->as_string,
ok => ( $result_is_ok ? true : false ),
type => $result->type,
$result->type eq 'test' ?
( number => $result->number,
desc => ( $result->description =~ s/^- //r )
) : ( ),
};
}
};