text:
Once you have the pipeline for building a package, it's time to distribute the freshly built package to the machines where it's going to be installed on.
I've previously explained the nuts and bolts of getting a Debian package into a repository managed by aptly so it's time to automate that.
We are going to need a separate repository for each environment we want to deploy to (or maybe group of environments; it might be OK and even desirable to share a repository between various testing environments that can be used in parallel, for example for security, performance and functional testing).
At some point in the future, when a new version of the operating system is released, we'll also need to build packages for another major version, so for example for Debian
stretch instead of
jessie. So it's best to plan for that case. Based on these assumptions, the path to each repository will be
For the sake of simplicity, I'm going to assume a single host on which both testing and production repositories will be hosted on from separate directories. If you need those repos on separate servers, it's easy to reverse that decision (or make a different one in the first place).
To easy the transportation and management of the repository, a GoCD agent should be running on the repo server. It can copy the packages from the GoCD server's artifact repository with built-in commands.
It would be possible to manually initialize each repository, and only automate the process of adding a package. But since it's not hard to do, taking the opposite route of creating automatically on the fly is more reliable. The next time you need a new environment or need to support a new distribution you will benefit from this decision.
So here is a small Perl program that, given an environment, distribution and a package file name, creates the aptly repo if it doesn't exist yet, writes the config file for the repo, and adds the package.
use strict;
use warnings;
use 5.014;
use JSON qw(encode_json);
use File::Path qw(mkpath);
use autodie;
unless ( @ARGV == 3) {
die "Usage: $0 <environment> <distribution> <.deb file>\n";
my ( $env, $distribution, $package ) = @ARGV;
my $base_path = "$ENV{HOME}/aptly";
my $repo_path = "$base_path/$env/$distribution";
my $config_file = "$base_path/$env-$distribution.conf";
my @aptly_cmd = ("aptly", "-config=$config_file");
sub init_config {
mkpath $base_path;
open my $CONF, '>:encoding(UTF-8)', $config_file;
say $CONF encode_json( {
rootDir => $repo_path,
architectures => [qw( i386 amd64 all )],
close $CONF;
sub init_repo {
return if -d "$repo_path/db";
mkpath $repo_path;
system @aptly_cmd, "repo", "create", "-distribution=$distribution", "myrepo";
system @aptly_cmd, "publish", "repo", "myrepo";
sub add_package {
system @aptly_cmd, "repo", "add", "myrepo", $package;
system @aptly_cmd, "publish", "update", $distribution;
As always, I've developed and tested this script interactively, and only started to plug it into the automated pipeline once I was confident that it did what I wanted.
And as all software, it's meant to be under version control, so it's now part of the deployment-utils git repo.
Before GoCD can upload the debian packages into a repository, the go agent needs to have a GPG key that's not protected by a password. You can either log into the
go system user account and create it there with
gpg --gen-key, or copy an existing
.gnupg directory over to
~go (don't forget to adjust the ownership of the directory and the files in there).
The first stage of the pipeline builds the Debian package, and records the resulting file as an artifact. The upload step needs to retrieve this artifact with a
fetchartifact task. This is the config for the second stage, to be inserted directly after the first one:
<stage name="upload-testing">
<job name="upload-testing">
<fetchartifact pipeline="" stage="build" job="build-deb" srcdir="package-info">
<runif status="passed" />
<exec command="/bin/bash">
<arg>deployment-utils/add-package testing jessie package-info_*.deb</arg>
Note that
testing here refers to the name of the environment (which you can chose freely, as long as you are consistent), not the testing distribution of the Debian project.
There is a
aptly resource, which you must assign to the agent running on the repo server. If you want separate servers for testing and production repositories, you'd come up with a more specific resource name here (for example `aptly-testing^) and a separate one for the production repository.
To make the repository reachable from other servers, it needs to be exposed to the network. The most convenient way is over HTTP. Since only static files need to be served (and a directory index), pretty much any web server will do.
An example config for lighttpd:
dir-listing.encoding = "utf-8"
server.dir-listing = "enable"
alias.url = (
"/debian/testing/jessie/" => "/var/go/aptly/testing/jessie/public/",
"/debian/production/jessie/" => "/var/go/aptly/production/jessie/public/",
# more repos here
And for the Apache HTTP server, once you've configured a virtual host:
Options +Indexes
Alias /debian/testing/jessie/ /var/go/aptly/testing/jessie/public/
Alias /debian/production/jessie/ /var/go/aptly/production/jessie/public/
# more repos here
With theses steps done, there is automatic building and upload of packages in place. Since client machines can pull from that repository at will, we can tick off the distribution of packages to the client machines.
I'm writing a book on automating deployments. If this topic interests you, please sign up for the Automating Deployments newsletter. It will keep you informed about automating and continuous deployments. It also helps me to gauge interest in this project, and your feedback can shape the course it takes.
I spent last weekend editing a few photographs from a short trip to Bahrain, in between that i was working on a perl library for the Mondo API. The thread the connects these two things is something i've mentioned before1: credit/debit card fees.
I did my best to avoid using a credit/debit card whilst in Bahrain simply because, over the past few years, i've become acutely aware of the cost of doing so. Not specifically Bahrain, just anywhere beyond the United Kingdom. Of course i could get myself a Swiss issued card, but i'd be in exactly the same situation2. Fees for using cards are the norm, not the exception.
If you do a bit of research you will not find a card that doesn't have some catch, be those foreign transaction fees, conversion fees, yearly/monthly service fees, a minimum spend/transactions per month, having to open another account with the bank, cash withdrawal fees. The list goes on and on and it is, frankly, ridiculous. Card issuers lure you in with "bonus" features and reward schemes like air miles, points, cash back, zero percentage on balance transfers for x months, and so on. But what about those who don't want any of this, who just want a replacement for cash without any of the mess3?
A Cashless Society?
In the end i had to use my card to pay for the hotel, grab something to eat at the airport, and to withdraw some cash:
That's a total of £14.17 collected by my card issuer for doing nothing. FA fees4, before they even charge me interest for using the credit card. Now, i could have exchanged some currency for Bahraini dinar before i went but i would have been fleeced on the exchange rate and had to pay a commission fee, if i could find a bureau de change that had the currency available. I'd probably have ended up with some foreign currency left over when i got back, another cost.
When i moved abroad i decided to keep my UK accounts open, they're useful to have in one case (a UK credit card) and essential in another (NI contributions from my current account). As i still use the credit card i've ended up paying approximately £400 on non-sterling + cash fees over the past three years. The majority are the non-sterling transaction fees, they're typically small charges, but they add up1.
Keep in mind that i'm not running around paying for everything with a card because i have some aversion to cash. The credit/debit cards only get used when i generally can't use cash. Buying something online, paying those road tolls in France, settling a hotel bill? All card payments.
Card payments are convenient, but as long as it costs me they're never going to replace cash. Cash costs me nothing. Yeah yeah carrying cash is a risk, the fee merchants pay on their handling of cards are passed on to cash payments, blah blah blah. Look, as long as i am faced with the choice of paying €10 and it costing me €10 or paying €10 and it costing me €10 + a transaction fee + a crappy exchange rate + interest, i am always going to take the first option where possible. As long as this is the case your dream of a cashless society is stuck somewhere in a pipe.
It's not only the fees, the majority of banking systems are antiquated. Paying by card means not just getting the aforementioned fees but having to wait up to three days to find out exactly what those fees were. And they're antiquated on the frontend just as much as the backend, the phrase "banking API" could almost be considered an oxymoron.
A Modern Bank
With the arrival of my Mondo card all the above issues are no more. Take a look at the following image:
That's the withdrawal of cash from an ATM in Villars. The transaction appeared on the feed in the app within moments, giving me the approximate exchange rate. There was no "cash fee" and the exchange rate was accurate to that found on xe.com within a few pence. The exchange rate used was corrected a couple of days later, again accurate to the actual rate within a few pence.
The same transaction on my Lloyds issued card would have:
So a transaction that would have cost me in the region of £3.50 on my old card actually cost me £0.15, and that £0.15 is down to the fluctuation of exchange rates between markets. Oh and you'll notice i could take a photo and attach it to the transaction, and it's correctly geo-tagged.
And it gets better:
The Mondo API allows me to access my data through a JSON API. I can push items to my feed, download transactional data, all sorts of ideas and uses cases can be built on top of the API. There are already many apps, libraries, and integrations available. The perl client library i've released is just one of them.
Out With The Old
Of course Mondo still have some work to do. They don't offer the same products as traditional banks, but that's not what they're aiming for. Their card is a pre-paid debit card, not offering the same protections as a credit card. However they are headed in the right direction, they're getting rid of all those FA fees that for too long have been a barrier to actually achieving a cashless society. Or at least they're offering a product that makes others look extremely unattractive.
My Lloyds card will remain with me whilst Mondo is still in its early stages, but it will see very little use from now on. In with the new.
I'll let you guess what that stands for. ↩
While I have hung out on the fringes of the p5p and toolchain communities for a few years now, my largest "qualifying" contribution has been Alien::Base, which has largely been handed off to Graham Ollis (plicease). Therefore I was a little surprised but very honored to be invited to the 2016 Perl QA Hackathon held in Rugby, England.
Overall it was an incredible experience. Day after day the energy in the room was palpable. Everyone was creating and improving the code that we would all get to use one way or the other. People hacking on PAUSE and MetaCPAN and CPANTesters, on ExtUtils::MakeMaker, on Test2 and Test::More.
Someone would encounter a bug and someone across the room would know the fix. Another person would accidentally trigger a problem elsewhere in the toolchain but the person with the keys would be two seats away ready to help. Having so much talent in one place like this is invaluable.
I actually felt quite a bit of pressure (only self imposed) to contribute as much as I could. But this is a good thing, it keeps you going and striving for more.
I am certainly most well known in the Perl community for my advocacy of Mojolicious as well as being part of its core development team. As part of this advocacy I have also built and/or advocated for some of its relevant modules. Two of these, Test::Mojo::Role::Phantom (my own) and Minion (Mojolicious' lead dev Sebastien Riedel's) also factor into my work at QAH.
Because of my work on Test::Mojo::Role::Phantom I became aware of the Test2 effort very early on. As Chad Granum (Exodist) has continued to improve Test2, I have sought to advocate for him and for the project. My thoughts on Test2 that were originally meant for this article became too large and really diverged from a QAH recap; so I have extracted that into its own blog post. In that article you will see that there was an effort to compile the list of all modules that had been impacted by Test::Builder-on-Test2, even if only that they needed to be upgraded. My small actual contribution to the Test2 effort at QAH was to help Chad compile this list and help in implementing the list as a pseudo-test during installation.
I like to think that my non-code contributions are exemplified in that post. I have and will continue to spread the word of how useful Test2 is and dispell concerns surrounding it. If you have any questions, please feel free to ask (though perhaps commenting on that post is more directed).
The aforementioned Alien::Base is a subclass of Module::Build and as such I have had some experience inside its internals. I took a brief hack at an MB refactor of my own but the mechanism was very flawed and I have abandoneded it. Since then I have taken an interest in Module::Build::Tiny and its authoring tool App::ModuleBuildTiny. These tools of Leon Timmermans' (leont) construction are very minimalistic but still very capable for small/common distributions. I have tried to encourage Leon to make it more usable by the general public and contributed some small ideas to it. To that end, I had hoped to spend some of my time working on these tools with him at the QAH.
As it was we didn't do too much. A patch I had expected to help shepherd in turns out to already have been merged. That left discussion of his new modules which unlike Module::Build::Tiny aren't so … tiny. Leon has modules already essentially in alpha stage which would represent an actual successor to Module::Build. A pure-perl build framework (not relying on make) but architected with both module installers (users) and extension authors in mind. Now after sitting with him, seeing what they are capable of, learning something about the architecture and discussing the future plans, I'm really excited to help him make this project a reality. Hopefully sooner than later.
One table I didn't expect to spend so much time at was the MetaCPAN table. I heard relatively early on in the event that MetaCPAN was moving a lot of its indexing load to a job queue. Not just any job queue, Minion, the Mojolicious spin-off project. I volunteered my services immediately.
But it is more than just being able to help with minion integrations. The hardest part of helping out is knowing how to get started, especially in a system like this where there are several related services. While the guys were working to upgrade their Elasticsearch backend the graciously took the time to help me install and learn their vagrant development stack. (It really is quite easy once you know the layout, if you are interested in helping ping me or them in #metacpan.) Once I had that running I started to get other ideas of ways I could help since they had their work cut out for them!
The one task I took through to completion was related to Neil Bowers' work on "River of CPAN" statistics. If A requires B and B requires C then C has two downstream dependencies. With the total number of downstream dependencies known one can start to get a picture of level of care that a module requires. Any breakage in a module with large numbers of downstream dependencies is a big deal since so much code is affected. The River of CPAN analogy (explained futher here and here) places modules along a river, the distance upstream is quantified partially by this total number of downstreams. Any pollution which enters the river up near the top of the river pollutes proportionally more of the river than were it to enter farther downstream.
Many authors are unaware of their modules position on the river and it can take a lot of effort to know. Lets say you were the author of C in the above example. Currently it is easy to see that your module has one reverse dependency but unless you drill down you might now see that A is in your river path too. Even worse is when a new module begins to depend (even indirectly) on yours, it brings in all of those modules that depend on it. In this way an author have one of his modules move rapidly upstream and completely without his knowledge.
To support several of his projects (including the Pull Request Challenge) Neil determines the aggregate number of downstream dependencies for each module on CPAN. If MetaCPAN can show statistics like this is can help an author gauge the impact of future changes to a given modules. It was discussed that in order to help an author be aware of the their module's position on the river he could share that information on MetaCPAN.
While he works on an webservice that MetaCPAN can use to fetch this data, I took his expected format and built tool for MetaCPAN to use to fetch and insert that data. Once back home I hope to continue by adding display of the information to the MetaCPAN front-end as well as helping to do the service integration once Neil is ready.
There are several other items upon which I hope to help MetaCPAN, including injecting reindexing jobs into minion when CPAN reindexes a distribution for example. Also as fellow Chicago.pm member Doug Bell (preaction) is beginning to take over for Barbie at CPANTesters our Chicago.pm meeting "office hours" can be used to continue the integration of those services as well.
Of course there is huge value to getting p5p and toolchain people into one room together purely for the efficiency of it. Bugs that pop up in one corner of the room can often be diagnosed or fixed by people across the room, even if they occur in other modules. That said, I think for myself this QAH was most valuable for me to be able to learn how to contribute to other projects from the authors themselves.
At my day job I love to pair with my coworkers; at the same desk if possible, on video/screenshare if not. IRC is great but to really iterate with someone, whether learning or fixing bugs or planning for the future, I find it is easier if you can talk to the other person or people. To hear their voice, to see how they go about their coding, is invaluable and an incredible foothold, especially when ramping up on something new. To those people, especially Chad, Leon, Olaf and Mickey, thank you so much for letting me sit next to you and learn from you.
I had plenty of opportunities to chat with so many great people! Over food or drinks or strawberries or laptops; thank you to everyone who indulged me in conversation.
Of course I want to thank Neil, JJ, Barbie and anyone else who had a hand in organizing this event. It is spectacular and though I'm sure it took huge amounts of effort you made it look effortless.
I would be remiss without thanking Rik Signes for his term as Pumpking! He has done an excellent job in what must be an incredibly trying job. I also want to extend congratuations to our new Pumpking Sawyer! I wish you best of luck and if I may be of any help I hope that you will please ask early and often (to borrow phrase from my native Chicago).
Most importantly I want to thank the sponsors. Without their support, no matter how much we would all want to gather to work together we could never afford the travel, accomodations, or venue to do so. These companies show their love for open source and Perl not just with their words but with their budgets and that is greatly appreciated. Thank you, thank you, thank you!
Their contribution made possible this event which produces such incredible results for the Perl community.
I also want to thank my employer ServerCentral for giving me the time and support to attend!
This post covers the previous two weeks of my Perl 6 grant work. Last time I wrote here, I plotted changes to call frames in MoarVM. Or, as the wonderful Perl Weekly put it, provided way too much information about call frames. :-)
That there is so much to say about call frames reflects their rather central role. They play a big part in supporting numerous language features (function calls, recursion, closures, continuations, dynamic variables, and pseudo-packages like
OUTER and
CALLER). The garbage collector scans them to find live objects. Both the interpreter and JIT compiler have to relate to them in various ways. The dynamic optimizer performs transforms over them when doing OSR (On Stack Replacement) and uninlining (the deoptimization that enables us to speculatively perform inlining optimizations).
All of which makes a major refactor of call frames a rather scary prospect. While they have picked up additional bits of state as MoarVM has evolved, they have been reference counted since, well, the day I first implemented call frames, which means "before MoarVM could even run any code". Being reference counted, rather than handled by the garbage collector, gave them a property that is easy to rely on, and rather less easy to discover reliance on: that they never move over their lifetime.
Wait, what, move? Why would they even move?
Here's a little Perl 6 program to illustrate. It declares a class, makes an instance of it, prints its memory address, does a load of further, throwaway, memory allocations, and then again prints the address of the object instance we made.
class A { }
my $obj = A.new;
say $obj.WHERE;
A.new for ^10000;
say $obj.WHERE;
When I ran this locally just now, I got:
If you get the same number twice, just make the
10000 something bigger. What's interesting to note here is that an object's location in memory can change over time. This is a consequence of MoarVM's garbage collector, which is both generational and manages its young generation using semi-space copying. (This is nothing special to MoarVM; many modern VMs do it.)
Being able to move objects relies on being able to find and update all of the references to them. And, since MoarVM is written in C, that includes those references on the C stack. Consider this bit of code, which is the (general, unoptimized) path for boxing strings:
MVMObject * MVM_repr_box_str(MVMThreadContext *tc, MVMObject *type, MVMString *val) {
MVMObject *res;
MVMROOT(tc, val, {
res = MVM_repr_alloc_init(tc, type);
MVM_repr_set_str(tc, res, val);
return res;
It receives
val, which is a string to box. Note that strings are garbage-collectable objects in MoarVM, and so may move. It then allocates a box of the specified
type (for example, Perl 6's
Str), and puts the string inside of it. Since
MVM_repr_alloc_init allocates an object, it may trigger garbage collection. And that in turn may move the object pointed to by
val – meaning that the
val pointer needs updating. The
MVMROOT macro is used in order to add the memory address of
val on the C stack to the set of roots that the GC considers and updates, thus ensuring that even if the allocation of the box triggers garbage collection, this code won't end up with an old
val pointer.
Last time, I discussed how reference counting could be eliminated in favor of a "linear" call stack for frames that don't escape (that is, become heap referenced), and promoting those that do escape to being garbage collected. As an intermediate step there, I've been working to make all frames GC-managed. This means that frames can move, and that they are part of the generational scheme. Therefore, every piece of code that both holds a reference to a frame and takes a code path that can allocate would need updating with
MVMROOT. Further, all assignments of frames into other objects, and other objects into frames, would need write barriers (aside from the working area, which is handled specially).
In part, this just needs a lot of care. Going through the places frames show up, updating things as needed, and so forth. But even then, would that really be enough to be confident things weren't broken? After all, my refactor was changing the rules for one of the most important data structures in the VM.
Of course, building NQP and Rakudo and passing the spectest suite is one good way to exercise MoarVM after the changes. Doing this showed up some issues, which I fixed. But even that doesn't offer a huge amount of confidence. A simple script, or a short test, might trigger no garbage collections at all, or just the odd one. And the collections are highly likely to be triggered on the most common code paths in the VM.
When faced with something scary, a surprisingly good approach is to tackle it by doing it really often. For example, are software releases scary? If yes, then do time-based releases every month, and with time they'll become automatic and boring enough not to be scary. Is deploying changes to a production system scary? If yes, then adopt continuous delivery, deploying lots of times in a day and with easy rollback if things don't go well.
Garbage collection is pretty scary. I mean, we take this world of objects the program has created, move them around, throw a bunch of them out, and then have the program continue running as if nothing happened. So…let's try doing it really often!
This is exactly what GC torture testing involves.
--- a/src/gc/collect.h
+++ b/src/gc/collect.h
@@ -1,7 +1,7 @@
/* How big is the nursery area? Note that since it's semi-space copying, we
* actually have double this amount allocated. Also it is per thread. (In
* the future, we'll make this adaptive rather than a constant.) */
-#define MVM_NURSERY_SIZE 4194304
+#define MVM_NURSERY_SIZE 13000
Rather than doing a collection every 4MB worth of allocations, let's do one every 13KB worth of allocations! That's around 320 times more often. Combined with a few debugging checks enabled, to catch references to objects that are out of date, bugs resulting from missing
MVMROOTs and write barriers can be driven out of their hiding places into the light of day.
It's a rather effective technique. It's also a very time-consuming one. The NQP and Rakudo builds easily take an hour between them, and running spectest this way takes over 12 hours. It's cheap compared to shipping a MoarVM with new and nasty bugs that waste a bunch of people's time, of course!
It's been a while since we did such a torture test. I've decided we should do them more often. It found issues. So far, from the spectest run torture test results, I've fixed 9 bugs (I didn't go back and count those discovered while building NQP and Rakudo). What's interesting is that of the 9, only 3 of them were clearly attributable to my refactors, one was potentially related to them, and 5 were bugs that must have been around a good while. One of the bugs that did relate to the frames changes caused deadlocks in multi-threaded code quite reliably under torture testing, but would have likely caused them very rarely under normal use (and so been extremely frustrating to reproduce and track down if it made it into the wild). 2 of the fixed non-frame bugs exclusively affected multi-threaded programs and would have doomed them. One was in the
CUnion representation, and probably was the cause of some previously unresolved occasional failures of the NativeCall union tests.
By this point, I'm reasonably confident that regressions due to the first step of the frame changes have been shaken out. The GC torture testing has, however, shed light on some other issues that will want addressing in the near future.
I intend to put those aside for a little while, and complete the frame changes, introducing the linear stack. Compared with the first step, this feels like a lower risk change, in that mistakes should be a lot easier and cheaper to detect. I'd like to try and land this in the next week or so, in order that it can get some real-world testing before it makes it into a MoarVM and Rakudo release.
Once that's out the way, I'll be returning to other issues turned up in GC torture testing. I'd also like to look into a way to be able to run it automatically and regularly (once a week, perhaps). It's a good bit too intensive to be able to farm it out to Travis. The sensible solution is probably to do it in the cloud, on some elastic compute thing where it just uses a machine once a week for a day or so. The silly but fun way is to build a Raspberry Pi cluster on my desk, and hack up something to distribute the tests across them. :-)
|CPAN module
|send cpanm output to CPAN Testers
|Database independent interface for Perl
|Sugar for your favorite ORM, DBIx::Class
|Data type related to database tables, spreadsheets, CSV/TSV files, HTML table displays, etc.
|Code coverage metrics for Perl
|distribution builder; installer not included!
|weave your Pod together from configuration and Dist::Zilla
|Create a module Makefile
|Why should Node.js have all the fun?
|A comprehensive, DWIM-featured client to the MetaCPAN API
|Build and install Perl modules
|Mojolicious ♥ PostgreSQL
|Real-time web framework
|weave together a Pod document from an outline
|Turnkey ajaxy webapps
|Serious testing for serious Perl
|High resolution alarm, sleep, gettimeofday, interval timers
In a future post I will recount the details of my delightful experience at the 2016 Perl QA Hackathon. Since this is my first post since that time I do want to tip my hat to the great sponsors of the event and to my own employer ServerCentral without whom I would not have been able to attend. I will thank them in more detail in that post.
Before I get to that however, I want to post a reflection on one discussion that is and has been weighing on my mind since then. That topic is the upcoming release of Test2, which I consider to be a very important step forward for Perl's testing architecture.
While I didn't spend the majority of my time at the QA Hackathon thinking about Test2, I think it probably is the most important part of the event to discuss. Test2 is a major project to rewrite the guts of the venerable Perl testing library Test::Builder. Most users are blissfully unaware of Test::Builder, they use Test::More instead, but Test::More uses Test::Builder as do almost all (let's say all) test modules.
Test::Builder draws its interface from the Test Anything Protocol (TAP). The protocol is seemingly very simple; print the number of tests you expect to run, then print 'ok 1' to say the first test passes and so on. I can report three passing tests by printing
ok 1
ok 2
ok 3
But most test authors don't print their test results, they use a function like
Test::More::ok to print the test result. They use something like
plan or
done_testing to manage the number of tests they expect. This is because it is annoying to have to keep track of the current test number, especially once you start sharing testing code.
Test::Builder, the Test::More guts, keeps an internal record of the number of tests that have been run, so that you don't have to. While this seems useful it sows the seeds of problems that we are finally starting to understand. Test::Builder's internal state is fundamentally important to the running of the test. This very quickly leads to the realization that all the test modules have to play nicely with Test::Builder or the count skews and your tests won't report correctly and your test runner will see a failure.
Our problem now is that Test::Builder is showing its age. People want to write tests in different and more expressive ways. They want to use subtests (groups of tests that count together), they want to output other formats than just TAP, they want to test their test modules, they want their harness (runner) output to be pretty. Test::Builder can't really support these things well, but that doesn't meant that people haven't gotten those features by hook or by crook.
Most readers will be aware that I am a core developer of Mojolicious and author of many related CPAN modules. Test::Mojo::Role::Phantom (I'll refer to it as ::Phantom for brevity) is a module which combines Test::Mojo and the headless Javascript interpreter Phantom.js to greatly simplify testing of a web application's dynamic (content). Note that via Test::Mojo::Role::PSGI these other test modules can be used to test Catalyst, Dancer, or any other PSGI-compliant application.
When it starts, it spins up a Mojolicious service on a random local port (possibly shimmed to host a PSGI app). It then forks a phantom Javascript interpreter; the child's STDOUT is a pipe pointed back at the parent. Via this pipe the javascript can send back a JSON structure representing command to be executed back in the parent. These commands are intended to run various test functions in the parent as they come in. You might say
perl('Test::More::is', some_selected_text, 'expected result', 'discription')
Which back in the Perl process is executed as
This mechanism works very well. While not a replacement for more dedicated front-end testing tools, helps authors who wouldn't otherwise write any front-end tests to be able to start. But ::Phantom has some problems that I cannot directly solve.
The test script itself might only make one call to
$t->phantom_ok($url, $js) but the execution of the phantom interpreter might execute several tests. In this scenario the call to
phantom_ok is logically equivalent to a subtest and so it wraps the fork and subsequent listen/interpret-cycle in a subtest. However if the test fails, the failure is reported as eminating from inside
phantom_ok. This problem alone wouldn't be tremendously difficult to fix, you could simply tell Test::Builder to report test failures from a higher stack frame by doing the usual trick of
local $Test::Builder::Level = $Test::Builder::Level + 1;
For ::Phantom however this will not help. The reason is that since the parent still has to serve the page to the client and then the parent has to listen for calls from the child's handle, it has to perform the test inside of an IO loop. Those of you familiar with IO loops can now see the problem. Now when the test is executed the original caller's stack frame isn't one level above the current one. In fact the original caller isn't (really) in the call stack at all (and certainly isn't a predictable number of frames above it.
This means that Test::Build's interface for this task is too limiting. Now up until Chad Granam started working on Test2 the next step would be to hack Test::Builder in one of several nasty ways. In fact many many test modules on CPAN have already done this because they had no other choice. These hacks range from mild to horrendous and can even lead to test modules which conflict with each other in strange ways or break unexpectedly when Test::More is updated seemingly innocuously.
Actually this stretches the truth; Test::More really isn't ever updated because in practice too much breaks when that is attempted. Test::More is actually more like completely stuck, frozen by the hacks that people have perpetuated around it.
I am lucky though because Chad has been working on a replacement, Test2. You see Chad (and many others before him) have noticed this problem of people hacking Test::More and wanted a solution. Test2 has been specially (and painstakingly) written to provide public api mechanisms to replace as many of the hacks that were seen on CPAN as possible. The only reason those hacks existed was because there was no approved way to do what test modules authors needed.
In my case Test2 provides a mechanism to capture a context object from which the test successes and failures are emitted. When you think about it this is the much more natural way to tell the testing singleton what is desired. Rather than
sub my_cool_test_ok {
... # arbitrary depth of calls ...
# count the number of intervening stack frames $n
local $Test::Builder::Level = $Test::Builder::Level + $n
You can simply do
use Test2::API 'context';
sub my_cool_test_ok {
my $ctx = context();
... # arbitrary depth of calls ...
and the tests will be reported correctly.
My situation isn't uncommon. I want to use Test::Builder in a way that wasn't originally envisioned.
Test2 contains many such fixes for many abuse patterns, both common and uncommon. In fact the reason it has taken so long is that over the YEARS that this has been in development Chad has continued to find modules that did stranger and stranger things to Test::Builder and then found ways to support them! The Test::Builder interface doesn't change when Test2 replaces its guts. This includes things that were never intended to be public interface but have defacto become public api over the course of all of this hacking.
There were a few cases that modules on CPAN could not be supported but most of those have now been updated to use supportable apis in Test::Builder. This leaves only a very small handful of only the most unsupportable ones. Once Test::Builder-on-Test2 hits CPAN nearly everyone will upgrade transparently thanks to this herculean effort. Not all of that praise goes to Chad as many others have submitted reports and offered suggestions and yes even held him back at times. The final product is a stunning level of backwards support that is worthy of the Perl language's commitment to this goal.
Here you have seen my argument for Test2 as the successor to Test::Builder from the perspective of having a more useful public api. It is important to note that this wasn't the original motivation.
Test2 brings one other huge benefit, an event system! When you run
ok using Test2 you don't just print 'ok $n' anymore, you emit a passing test event. For most users this will simply be consumed by a TAP emitter and it will print 'ok $n', but this isn't all you can do.
When testing Test:: modules written with Test2 no longer have to parse the TAP stream to see if they pass their own tests. Test2's robust system of events can be watched and then compared as data structure streams. I can write tests for ::Phantom without ever having to regexp on TAP output!
We can finally test our testers!
Not only that but those event streams don't need to emit TAP at all! Users desirous of xUnit, TeamCity or other formats no longer need to parse the output and re-emit what they need. Simply attach emitters for the preferred output and Test2 does what you need!
The first response of anyone new to the situation is to ask "well can't the test script author or at least the module author choose to opt-in rather than replace the guts transparently?" Remember up at the top of the discussion that there is this central point of knowledge of the state of the test run?
Any Test:: module can practically only target one authority, whether it be Test::Builder or Test2. Sure some module authors could provide one version of a module for each, but that places a burden on them and a cognitive load on the consumer to pick all their test modules from one pool or the other. In practice this will not occur, the inertia behind Test::Builder is too great. Test::Builder is the existing authority and it must remain as a least a view into the state of test progress for all existing tests.
This means that we are left with a question of can one authority delegate to the other? Test::Builder is too limited in its scope to continue to improve marginally, let alone be the substructure of its own replacement, it simply doesn't have the capacity; Test2-on-Test::Builder isn't possible.
No, from those axioms we can see that for Test2 to gain any adoption, it must replace Test::Builder in holding the authority and provide a new Test::Builder as the interface to older tests. Which leads us back to opt-in. If users have to opt-in, then tests written with and for Test2 cannot communicate with older tests, leading inevitably back to the first case of a forked ecosystem.
Now there is no gaurantee of perfection, but if you had been following this process you wouldn't doubt the lengths to which compatibility has motivated it. I know I would have quit long long ago had it been me! At this point, most of the detractors have been converted and the few holdouts seem to mostly have the fear of the unknown for effects on the DarkPAN. Fair enough; this represents a judgement call. Perfect backwards compatibility by atrophy versus progress with some small risk almost entirely mitigated at incredible effort.
I know where I stand on that call.
The discussions around the Test::Builder-on-Test2 centered around end-user notification. It seems that most if not all of the technical discussion has wrapped up and the code has been well reviewed.
To help the users of the few affected modules, it was decided to list ALL of the known broken modules (even those that are now fixed by upgrading from CPAN) in a documeent. This document (part of the Test2 distribtion) will tell those few affected users what they should do if they experience trouble. Further, when installing Test::Builder-on-Test2 the user will be notified if they have any existing modules which need upgrade or even replacement. Remember though, this list is very very small.
The benefits of Test2 are huge. Let's see it make this final step and become the new backbone of Perl's great testing infrastructure.
This year I discussed less and got more focussed on one thing, namely PAUSE, thanks to the kisses of the muse we got flooded with, that is Kenichi, Neil, Matt, Peter and me. Thanks to that, PAUSE is, I daresay, in a better shape than ever before and definitely on a good track towards the future.
Here's a short run down on my activities at the QAH in Rugby:
Fixed a bug discovered by Leo Lapworth in
rrr synchronization: it turned out that a crontab item got mangled recently.
Joined the Test2 discussion.
Set up a smoker run for 5.18.4 with the Test-Simple releases 1.302014_001..7.
Finished the pre-Hackathon activities on getting the Perl Authors Upload Server (PAUSE) to work with two separate puppet instances, one for the system operation team, and one the application (together with Robert Spier).
Added sysv startup gears for the new plack-driven PAUSE server and fine-tuning configuration (together with Slaven Rezić and Kenichi Ishigaki).
Continued the year-long activities on transforming the database of PAUSE to work without the
mods table and cleaning up inconsistencies (together with Neil Bowers).
Helped out with my admin privileges on PAUSE to fix an upload glitch during Dist-Zilla-6 developer release.
Reviewed pull requests on https://github.com/andk/pause/pulls that had accumulated over the year and applied: 210, 206, 214, 216, 209, 215, 219, 207, 220, 190, 168, 172, 133, 137, 208, 212, 211, 217, and 221 (together with Kenichi Ishigaki); special thanks go to the contributors pjlsergeant, wolfsage, mohawk2, rjbs, dagolden, neilb, charsbar who generated the pull requests.
Consultation with Breno G. de Oliveira about cpanminus reporter.
Consultation with Colin Newell, Ricardo Signes, and Karen Etheridge about how to retain sane upload-permissions for collaborating groups of users.
Consultation with Joel Berger on a potential Mojolicious cookbook article about when and when not to use
Thank you to the sponsors, FastMail, ActiveState, ZipRecruiter, Strato, SureVoIP, CV-Library, OpusVL, thinkproject!, MongoDB, Infinity, Dreamhost, Campus Explorer, Perl 6, Perl Careers, Evozon, Booking, Eligo, Oetiker+Partner, CAPSiDE, Perl Services, Procura, Constructor.io, Robbie Bow, Ron Savage, Charlie Gonzalez, Justin Cook, many of us would not have been able to come and stay for four days without their help. Thanks to Neil and Barbie and JJ for setting all this up and managing everything so nicely and smoothly. Thanks to Wendy for keeping us sugared and vitamined and fed and hugged and hugged and hugged.
If you use Perl and MongoDB, I need your help. Every year, we put out a survey to developers to find out what languages they use, what features they need, what problems they have, and so on.
We have very few Perl responses. ☹
Be an ally! Take the MongoDB Developer Experience Survey.
Thank you to all the people who sponsored the Perl QAH hackathon and all those that provided their time. It was a very productive environment for a lot of projects.
I worked on 2 primary things relating to PAUSE permissions. PAUSE (indexing) itself and a new module for testing that permissions are consistent named
The permissions of distributions on CPAN are generally something you don't think about until you become a co-maintainer of a distribution and you see red on
search.cpan.org or
metacpan.org. Then you discover that there is a system by which each module in your distribution is effectively owned by somebody, and that some others might also have been granted permission to upload a file.
Let's take
Test::DBIx::Class as an example. I'm a co-maintainer, and JJNAPIORK is the owner. There is also another Co-Maintainer.
Using the script from
Test::PAUSE::ConsistentPermissions I can look at the permissions currently assigned.
$ pause-check-distro-perms Test-DBIx-Class Test::DBIx::Class Distribution: Test-DBIx-Class Module: Test::DBIx::Class Owner: JJNAPIORK Comaint: NEWELLC, PHAYLON
When I upload a new release of Test::DBIx::Class to PAUSE any new modules added will be given to me. So I will be owner and no-one will be Comaint. I then need to grant PHAYLON comaint (which I can do as owner), and then pass ownership back to JJNAPIORK.
There is an alternative mechanism involving a bit of metadata named 'x_authority'. With that we could ensure that JJNAPIORK retains ownership of all the modules within the distribution. The downside of that is that while I would also gain comaint on those new modules as the uploader, PHAYLON would not. Since I wasn't the owner either, I wouldn't be able to assign him Comaint, and I would have to ask JJNAPIORK to do that instead.
I believe there were historically alternative methods for managing this, but PAUSE has been through some rationalisation and simplification of some features and those features don't exist anymore.
I came to this hackathon wanting to work on this problem having encountered Karen Etheridge (ETHER)'s prototype
Dist::Zilla::Plugin::AuthorityFromModule which suggested a potential solution.
We had a meeting with the interested parties at the hackathon about how we could deal with this scenario better. Ricardo Signes (RJBS) suggested that we could make use of the fact that there is a designated 'main module' for permissions. We could use that for the defaults. This is one step better than the previously suggested solution as it makes use of some of the previous rationalisation of PAUSE permissions and won't require authors to provide extra metadata. This should mean that permissions are much more likely to just work out of the box.
With that potential solution suggested RJBS gave me some assistance to get working on the PAUSE indexer. I started with adding tests, then wrote the code.
The change made so far is very minimal, only affecting the indexing of new packages. No changes have been made to the user interface, or the complex permissions you can currently end up with. The pull request is here – https://github.com/andk/pause/pull/222. Note that it also benefits from Peter Sergeant (Perl Careers)'s work to hook the PAUSE tests into Travis giving it a green tick indicating the tests passed.
The other thing I worked on was
Test::PAUSE::ConsistentPermissions to allow us to check that a distribution has consistent permissions. I created a script for checking a distro on PAUSE (not too dissimilar to Neil Bowers
App::PAUSE::CheckPerms module) and a test function for using a distro's release tests. This is a bit like
Test::PAUSE::Permissions, but rather than check whether you have permission to upload the distribution, it checks whether the permissions are consistent. These two properties don't necessarily coincide.
During the event I was also able to create a couple of minor pull requests.
Here's the obligatory thank you to the full list of sponsors. Thank you all.
The sponsors for the Perl QA Hackathon 2016,
We made some very good progress on MetaCPAN at this year's QA Hackathon in Rugby. The whole post can be found here.
I've long said that the Perl QA Hackathon is my favorite professional event of the year. It's better than any conference, where there are some good talks and some bad talks, and some nice socializing. At the Perl QA Hackathon, stuff gets done. I usually leave feeling like a champ, and that was generally the case this time, too.
I flew over with Matt Horsfall, and the trip was fine. We got to the hotel in the early afternoon, settled in, played some chess (stalemate) and then got dinner with the folks there so far. I was delighted to get a (totally adequate) steal and ale pie. Why can't I find these in Philly? No idea.
The next day, we got down to business quickly. We started, as usual, with about thirty seconds of introduction from each person, and then we shut up and got to work. This year, we had most of a small hotel entirely to ourselves. This gave us a dining room, a small banquet hall, a meeting room, and a bar. I spent most of my time in the banquet hall, near the window. It seemed like the easiest place to work. Although there were many good things about the hotel, the chairs were not one of them! Still, it worked out just fine.
The MetaCPAN crew were in the dining room, a few people stayed at the bar seating most of the time, and the board room got used by various meetings, most of which I attended.
The view over my shoulder most of the time, though, was this:
Philippe wasn't always there with that camera, though. Just most of the time.
I think my work falls into three categories: Dist::Zilla work, meeting work, and pairing work.
Two big releases of Dist::Zilla came out of the QAH. One was v5.047 (and the two preceeding it), which closed about 40 issues and pull requests. Some of those just needed application, but others needed tests, or rework, or review, or whatever. Amusingly enough, other people at the QAH were working on Dist::Zilla issues, so as I tried to close out the obvious branches, more easy-to-merge branches kept popping up!
Eventually I got down to things that I didn't think I could handle and moved on to my next big Dist::Zilla task for the day: version six!
My goal with Dist::Zilla has been to have a new major version every year or two, breaking backward compatibility if needed, to fix things that seemed worth fixing. I've been very clear that while I value backcompat quite a lot in most software, Dist::Zilla will remain something of a wild west, where I will consider nothing sacred, if it gets me a big win. The biggest change for v6 was replacing Dist::Zilla's use of Path::Class with Path::Tiny. This was not a huge win, except insofar as it lets me focus on knowing and using a single API. It's also a bit faster, although it's hard to notice that under Dist::Zilla's lumbering pace.
Karen Etheridge and I puzzled over some encoding issues, specifically around PPI. The PPI plugin had changed, about two years ago, to passing octets rather than characters to PPI, and we weren't sure why. Karen was convinced that PPI did better with characters, but I had seen it hit a fatal bug that using octets avoided. Eventually, with the help of
git blame and IRC logs, we determined that the problem was... a byte order mark. Worse yet, a BOM on UTF-8!
When parsing a string, PPI does in fact expect characters, but does not expect that the first one might be
U+FEFF, the space character used at offset 0 in files to indicate the UTF encoding type. Perl's UTF-16 encoding layers will notice and use the BOM, but the UTF-8 layer will not, because a BOM on a UTF-8 file is a bad idea. Rather than try to do anything incredibly clever, I did something quite crude: I strip off leading
U+FEFF when reading UTF-8 files and, sometimes, strings. Although this isn't always correct, I feel pretty confident that anybody who has put a literal
ZERO WIDTH NO-BREAK SPACE in their code is going to deserve whatever they get.
With that done, a bunch of encoding issues go away and you can once again use Dist::Zilla on code like:
my $π = 22 / 7;
This also led to some fixes for Unicode text in
__DATA__ sections. As with the Path::Tiny change, a number of downstream plugins were affected in one way or another, and I did my best to mitigate the damage. In most cases, anything broken was only working accidentally before.
Dist::Zilla v6.003 is currently in trial on CPAN, and a few more releases with a few more changes will happen before v6 is stable.
Oh, and it requires perl v5.14.0 now. That's perl from about five years ago.
I was in a number of meetings, but I'm only going to mention one: the Test2 meeting. We wanted to discuss the way forward for Test2 and Test::Builder. I think this needs an entire post of its own, which I'll try to get to soon. In short, the majority view in the room was that we should merge Test2 into Test-Simple and carry on. I am looking forward to this upgrade.
Other meetings included:
A bit more about that last one: I wrote Software-License, and I feel I've done as much work on it as I care to, at least in the large. Now it gets a steady trickle of issues, and I'm not excited to keep doing it all myself. I recruited some helpers, but mostly nothing has come of it. I tried to rally the troops a bit to encourage more regular review just leading to each person giving a +1 or -1 on each pull request. Otherwise, Software-License is likely to languish.
I really enjoy being "free floating helper guy" at QAH. It's something I've done a lot ever since Oslo. What I mean is this: I look around for people who look frustrated and say, "Hey, how's it going?" Then they say what's up, and we talk about the issue. Sometimes, they just need to say things out loud, and I'm their rubber duck. Other times, we have a real discussion about the problem, do a bit of pair programming, debate the benefits of different options, or whatever. Even when I'm not really involved in the part of the toolchain being worked on, I feel like I have been able to contribute a lot this way, and I know it makes me more valuable to the group in general, because it leaves me with more of an understanding of more parts of the system.
This time, I was involved in review, pairing, or discussion on:
...and probably other things I've already forgotten.
A few weeks ago, I announced that I'm retiring a pumpking after a good four and a half years on the job. On the second night of the hackathon, the day ended with a few people saying some very nice things about me and giving me both a lovely "Silver Camel" award and also a staggering collection of bottles of booze. I had to borrow some extra luggage to bring it all home. (Also, a plush camel, a very nice hardbound notebook, and a book on cocktails!) I was asked to say something, and tried my best to sound at least slightly articulate.
Meanwhile, there was a lot of discussion going on — a bit at the QAH but more via email — about who would be taking over. In the end, Sawyer X agreed to take on the job. The reaction from the group, when this was announced, was strong and positive, except possibly from Sawyer himself, as he quickly fled the room, presumably to consider his grave mistake. He did not, however, recant.
I didn't want to spend too much time on perl v5.24.0 at the QAH, but I did spend a bit, rolling out RC2 after discussing Configure updates with Tux and (newly-minted Configure expert) Aaron Crane. I'm hoping that we'll have v5.24.0 final in about a week.
I'm definitely looking forward to next year's QAH, wherever it may be. This year, I had hoped to do some significant refactoring of the internals of PAUSE, but as the QAH approached, I realized that this was a task I'd need to plan ahead for. I'm hoping that between now and QAH 2017, I can develop a plan to rework the guts to make them easier to unit test and then to re-use.
The QAH is a really special event, in that most of the attendees are brought to it on the sponsor's dime. It's not a conference or a fun code jam, but a summit paid for by people and corporations who know they'll benefit from it. There's a list of all the sponsors on the event page, including, but not limited to:
Check out the full list, and raise a glass to them!
schmorp recently complained about a maintainer fail in Math::BigFloat, and since this is not an isolated incident of the last years, I try to give a summary of all the maintainer fails of important modules lately, as I happen to fix them privately.
These are all doomed modules, as p5p refuses to take bug and security reports, and most of them are not maintained and fixed and improved in cperl only.
Maintained by p5p, responsible:
regression in blsflt (left shift) and refusal to fix it, lack of understanding of float math.
fixed in cperl only. in cperl we also heavily modernized all the bigint/bignum/bigrat/Big::* modules to use typed signatures.
there were several podcheck fails, which were promptly fixed. so they do react fast, their only problem is the lack of understanding.
maintained by p5p, responsible: nobody
missing features, grave security problems with bless and tie, other security problems on 64bit with overlarge hashes and names. fixed in cperl only.
tonyc recently replied to a similar but limited bugreport with a partial fix, which doesn't really help.
unmaintained by p5p, responsible: nobody, previously smpeters
p5p took it over from him, while smpeters refactored the test suite for a while. many bug reports and patches still sitting in the cpan queue, no idea about the p5p queue, because they blocked me there.
development stalled, so I added most needed features and fixes. fixed in cperl, and on https://github.com/rurban/Net-Ping
unmaintained by nwclark, responsible: nobody
Development and maintenance stalled, many fixes unanswered. I had to publish all fixes to cpan as UNAUTHORIZED RELEASE.
Fixed in cperl.
unmaintained by rgs
Development and maintenance stalled, many improvements ignored. had to publish my own version Opcodes. Maintainer only wants Opcode as parent module for Safe, but not to specify Opcode properties. This is hardly an acceptable point of view.
maintained by p5p
Basically this module is only plagued by old sins, exporting all symbols at once and not by request. But the maintainers obviously don't know about this and accepted a bugreport that a new symbol is not automatically exported. This is a feature, not a bug.
The unsafe
tmpnam is still exported, but at least deprecated. The new tmpnam replacements
mkdtemp are missing.
POSIX::1003 should be used instead.
maintained by
pjf, several private core fixes, several unfixed problems
this is a stable pragma with a complicated scoped feature set, which does not really work in corner cases. it broke the compiler with gensyms and empty stashes, and it broke
Porting/sync-with-cpan. no autodie does not properly restore
system() from
CORE::. I had to remove autodie from cperl's improved sync-with-cpan, and I urge everybody else not to use it, as the errors are often invisible and undetected.
It is also considered bad practice to use it. You need to know which open can fail and which not. It's recommended for complete newbies, such as use warnings and Carp, which introduce heavy memory regressions.
maintained by
pevans, but this guy can usually be trusted.
The queue is quite small.
But I had to add missing IPv6 constants in cperl for Net::Ping, a lot more are still missing for ping6 functionality. http://search.cpan.org/~rurban/Socket-2.021_01/
unmaintained by
unwilling to support Cpanel::JSON::XS the follower to the broken JSON::XS
unwilling to support cross-compatibility with the other JSON modules, throws several redefinition warnings if the loading order is different.
unresponsive. we typically wait >1 year to get answers on feature requests. last release 2013.
in cperl we fixed overload stringify and eq as in Cpanel:JSON::XS esp. "true" => true not 1
now maintained by
not much problems, but horrible perldoc.3 vs perldoc.1 conflicts in core integration.
horrible core integration of Pod::Man and a broken $Maintainers{MAP}
Properly maintained, but they still think they are alone on this world, same problem as with Ingy. That there is only one installed perl, and only this can run the tests. There exists $^X for a reason.
I fixed their
t/search50.t test in Dec 2015, but it is still not handled.
Since cperl will ship its own heavily modernized version, it's no big deal. signature all the methods and get type violations at compile time, which caught many errors already.
maintained by
the toolchain gang
I don't expect the toolchain folks to support the cperl variant, so I do it by myself, and added various new features along the line.
wrong Config dependencies, support
PERL_USE_UNSAFE_INC=1, call darwin dsymutil with DEBUGGING, use the fixed and faster YAML and JSON cperl core parsers. see below at Problems in core toolchain cpan modules, kept fixes private.
maintained by
exodist, very sceptical
The big Test2 feature he is working on for 2 years is event-based streamable tests, which still is 2x slower so far. So a no go. See http://search.cpan.org/~exodist/Test-Simple-1.302014_007/lib/Test2/Transition.pod
The old implementation is too heavy, we simplified and improved it internally. Since cperl will ship its own heavily modernized version, it's no big deal. We improved many abstraction methods. Signature all the methods and get type violations at compile time, which caught many errors already. Some of our type checks will break your tests, esp. that the skip count needs to be a number.
maintained by
gisle, no response
core had traditionally a wrong
U32_ALIGNMENT_REQUIRED probe in Configure.
I added a proper probe to fix the intel architecture, and added compatible SIGBUS on alignment fails, to detect previously undetected alignment errors. Fixed 64bit and darwin multiarch probes. Fixed RT #77919
unmaintained by alh
Had to fix 5.16 binary names by myself, which should have happened in the last 8 years, as p5p pushed for binary names, and I opposed it.
cperl also supports @INC without . (-Dfortify_inc)
See https://github.com/rurban/Devel-PPPort/tree/516gvhv
maintained by
Many core features are improperly supported, and many features are missing, so people had to come up with List::MoreUtils. The current maintainers do not known about MULTICALL and lexical $_, the most trivial features needed for this module.
The recent div by zero fix was done much worse than in cperl.
At least he is responsive.
Only minor issues. This is the only core module published as .tgz, so it cannot be updated by p5p with sync-with-cpan. only fixed in cperl.
Basically all toolchain modules which lack cperl support. Esp. the 'c' suffix version detection and comparison, and the lack of knowledge about cperl builtin modules without .pm: XSLoader, DynaLoader, strict, coretypes. The old toolchain still wants to install a missing XSLoader requirement, because it searches for modules statically, not dynamically.
CPAN-Meta-YAML, CPAN-Meta-Requirements, version, CPAN, CPAN-Meta, Parse-CPAN-Meta, EU-MM
The biggest problem is over-architecture, as the toolchain is typically the gathering place for all the important people too incompetent to do core. The old master Dan Golden is the only light in the dark.
Another problem is the lack of efficient JSON and esp. YAML support, and lack of YAML compliance. They gave up on YAML instead of fixing it, as we did.
With cperl we added fast XS variants for JSON and YAML, fixed the broken and overly strict YAML::XS, and use this throughout. And not the infant YAML::Tiny, which also deviates from the YAML specs. cperl added JSON and YAML validation tests for all existing JSON and YAML modules.
I've looked over all my >100 distroprefs patches, and in the end problems are only with ether and schmorp. schmorp at least knows what he is doing and eventually comes up with fixes by himself.
maintained by
Moose was compilable before ether took over, since then it eroded. The maintainer doesn't have an idea how compile-time vs run-time works, which should be critical understanding for such a compile-time optimized module.
A lot of compile-time code is not run in BEGIN or CHECK blocks, rather as main_cv code of compile-time imported modules, which does not work when separated into compiled and run-time.
I didn't even bother to file a ticket, as 1st compared to Mouse Moose is totally unusable, and 2nd the maintainer might be willing to fix it, but is not able to maintain this.
maintained by
The new maintainer is not able to come up with 5.16 support, binary names. She refused to merge my fixes for several years.
maintained and taken over by
ether. I suspect a hostile takeover.
The new maintainer was not able to maintain API stability for
OP::parent, one of the biggest reasons this module exists, and lied for the reasons to take it over. A complete disaster. I had to publish my own stable
B::Utils1 module.
So in summary, only p5p and ether are failing to do their job.
With the core cpan modules there are some typical outliers, nothing dramatic. cpan itself looks very healthy, whilst p5p looks totally dead.
Some people might be aware that we (not p5p) fixed Storable already for the most egregious security problems with Storable, with public CVE, explanation and metasploit module, but those bugs are still in Storable as on CPAN and in the latest perl5.24.
Now a new problem arose on the horizon, that p5p dares to fix another bug, the inability to store overlarge strings. Which would be okay if they would have taken our fixes, which fixes the security problem and all overlarge data >I32, which are arrays and hashes also. But they didn't, so I have to complain again. People apparently don't like me to complain about p5p mistakes, but you should be concerned what p5p is doing.
See perl #127743 for the wrong fix, adding 2 new ops, where only one is needed, and this fix only fixes a third of the overlarge problem, and not the security problems. There's no need for them to deviate from the API with a worse fix.
And compare that to the real fixes at cperl, which I sent to Tony some time ago, but apparently with no effect. So they are playing dumb again.
Note that this is now a security problem they are avoiding to fix.
Note that I cannot fix that for you on CPAN, as Storable is maintained by p5p. It's only fixed for us. A fair warning.
The first step of an automated deployment system is always the build. (For a software that doesn't need a build to be tested, the test might come first, but stay with me nonetheless).
At this point, I assume that there is already a build system in place that produces packages in the desired format, here .deb files. Here I will talk about integrating this build step into a pipeline that automatically polls new versions from a git repository, runs the build, and records the resulting .deb package as a build artifact.
As mentioned earlier, my tool of choice of controlling the pipeline is Go Continuous Delivery. Once you have it installed and configured and agent, you can start to create a pipeline.
GoCD let's you build pipelines in its web interface, which is great for exploring the available options. But for a blog entry, it's easier to look at the resulting XML configuration, which you can also enter directly ("Admin" → "Config XML").
So without further ado, here's the first draft:
-c debuild -b -us -uc
The outer-most group is a pipeline group, which has a name. It can be used to make it easier to get an overview of available pipelines, and also to manage permissions. Not very interesting for now.
The second level is the
<pipeline> with a name, and it contains a list of materials and one or more stages.
A material is anything that can trigger a pipeline, and/or provide files that commands in a pipeline can work with. Here the only material is a git repository, which GoCD happily polls for us. When it detects a new commit, it triggers the first stage in the pipeline.
Each time a job within a stage is run, the go agent (think worker) which runs it prepares a directory in which it makes the materials available. On linux, this directory defaults to
/var/lib/go-agent/pipelines/$pipline_name. Paths in the GoCD configuration are typically relative to this path.
For example the material definition above contains the attribute
dest="package-info", so the absolute path to this git repository is
/var/lib/go-agent/pipelines/package-info/package-info. Leaving out the
dest="..." works, and gives on less level of directory, but only works for a single material. It is a rather shaky assumption that you won't need a second material, so don't do that.
See the config references for a list of available material types and options. Plugins are available that add further material types.
All the stages in a pipeline run serially, and each one only if the previous stage succeed. A stage has a name, which is used both in the front end, and for fetching artifacts.
In the example above, I gave the stage the attribute
cleanWorkingDir="true", which makes GoCD delete files created during the previous build, and discard changes to files under version control. This tends to be a good option to use, otherwise you might unknowingly slide into a situation where a previous build affects the current build, which can be really painful to debug.
Jobs are potentially executed in parallel within a stage, and have names for the same reasons that stages do.
Inside a job there can be one or more tasks. Tasks are executed serially within a job. I tend to mostly use
<exec> tasks (and
<fetchartifact>, which I will cover in a later blog post), which invoke system commands. They follow the UNIX convention of treating an exit status of zero as success, and everything else as a failure.
For more complex commands, I create shell or Perl scripts inside a git repository, and add repository as a material to the pipeline, which makes them available during the build process with no extra effort.
<exec> task in our example invokes
/bin/bash -c 'debuild -b -us -uc'. Which is a case of Cargo Cult Programming, because invoking
debuild directly works just as well. Ah well, will revise later.
debuild -b -us -uc builds the Debian package, and is executed inside the git checkout of the source. It produces a .deb file, a .changes file and possibly a few other files with meta data. They are created one level above the git checkout, so in the root directory of the pipeline run.
These are the files that we want to work with later on, we let GoCD store them in an internal database. That's what the
<artifact> instructs GoCD to do.
Since the name of the generated files depends on the version number of the built Debian package (which comes from the
debian/changelog file in the git repo), it's not easy to reference them by name later on. That's where the
dest="package-info/" comes in play: it makes GoCD store the artifacts in a directory with a fixed name. Later stages then can retrieve all artifact files from this directory by the fixed name.
If nothing goes wrong (and nothing ever does, right?), this is roughly what the web interface looks like after running the new pipeline:
So, whenever there is a new commit in the git repository, GoCD happily builds a Debian pacckage and stores it for further use. Automated builds, yay!
But there is a slight snag: It recycles version numbers, which other Debian tools are very unhappy about. In the next blog post, I'll discuss a way to deal with that.
I'm writing a book on automating deployments. If this topic interests you, please sign up for the Automating Deployments newsletter. It will keep you informed about automating and continuous deployments. It also helps me to gauge interest in this project, and your feedback can shape the course it takes.
This year, Austrian and Swiss Perl Monger groups join forces to host the first Alpine Perl Workshop, taking place at the Medical University of Innsbruck on 2nd and 3rd September 2016 (that's a week after YAPC::Europe). Attendance is free, though we do offer a voluntary business tariff (90€).
We are currently looking for Sponsors and Speakers - and a proper design for the site:
We are looking for talks about Perl 5, Perl 6, CPAN, other Perl-related topics, not-so-much-Perl-related topics and other interesting stuff. We offer 20 and 40 minutes slots, but prefer two shorter talks to one long. There will also be lightning talks (5 minutes).
Talks can be in English or German, preferably in the language you feel more comfortable in. As we expect some guests who might not speak German, it would be a good idea to provide English slides if you plan to speak German. But please consider that the majority of attendees will be German speakers (if we consider schwiizerdütsch, tirolerisch and even wienerisch as German..)
Please submit your talks via the ACT website. Deadline for talk submission is 31st July 2016.
P5P outsider here.
I read through the whole thread "Salvaging lexical $_ from deprecation" and I think that the intent from RGS was correct: let's just talk more about this issue before ditching something that might be useful indeed. RGS saw value in that construct, and by all means this called for this flag raising.
I didn't see abusing, only discussion on technical merits. Is the reference to the CoC actually referring to some other discussion, or maybe to some moderation applied to that thread? I genuinely don't know.
My perl-guts-fu is too low to judge on the technical discussion, and on the technical preparation of each of the respondents. The impression I got is that even very skillful people like RGS sometimes might not have all the details clear; this applies to many others probably, although I'm not sure everyone is as fair as RGS to admit it and stand corrected. Kudos.
As a user of Perl, I can say that the localization of $_ is likely to break the principle of least surprise in many ways, as many examples showed. Even the introduction of ways to solve things for prototypes made me wonder what would happen for a module that tries to be correct for perl-s before and after the introduction of the new feature (like I was reading regarding Try::Tiny for example).
The matter is also probably rooted as to whether we should abandon Perl 5 at some point in time or not. For good or bad, some design decisions in the past were done and have to be taken into account because otherwise people's code is likely to break. Some degree of innovation can be put in Perl 5, some other probably simply can't without much hoop-jumping and confusing behavior.
I feel the frustration of RGS in the thread and the reference to Perl 7. At a certain point, dead ends in Perl 5 related to past design decisions might make it saner to just declare that a drastic cut from the past is needed. Then it will remain to be seen to what extent this will break the community, how much Perl 7-whatever will be considered a sister language, and all the same.
Now that p5p removed the broken lexical topic feature in 5.24 it's time to look back how that happened and why it should not have happened, and how cperl fixed that problem.
In 2013 Rafael Garcia-Suarez posted to p5p a plea to Salvaging lexical $_ from deprecation arguing that the recent deprecation of my $_ is wrong, and can easily be fixed.
He explained the problems pretty nicely on the language level, but forgot to explain the internal advantages of a lexical
$_ over a global or localized
$_. To add that it's pretty simple: A lexical
$_ is an indexed slot on the stack array, calculated at compile-time, whilst a local or global
$_ is a hash entry in the namespace. It's much faster to lookup, write and restore. The slot index is compiled and carried around in the op. That's why it's called lexical, it is resolved at compile-time, and not at run-time.
If you try to read the answers by p5p you will get headaches as their explanations are not only clueless and wrong, they even argue that using
$_ lexically is semantically wrong! Eg. rjbs: "I think it is half-baked, confused, and confusing. I don't see how it can be made useful or straightforward, at the language level."p5p
He clearly is confused because of the tricky bugs on the ops he is talking about, but here he was arguing that the semantics are broken(!). Using
$_ explicitly or implicitly; or global, local or lexical makes no difference, only to RJBS and to some other porters. Doy for example argues that my
$_ should be removed because this example is broken:
my $_ = 'foo'; print = any { $_ eq 'a' } qw(a b c)
which I fixed in 10 minutes by using the lexical
$_ in the XS implementation and not the global. See the simple patch at RT #113939
The underlying problems with the implementation of
my $_ were quite trivial to fix. I just had to fix the initial check for OPp_TARGLEX in the cperl commit 597e929c9 August 2015, which I published quite well. But the message obviously didn't arrive at the p5p team, because the decided that
my $_ cannot be fixed and needs to be removed end of August. This time without any deprecation period.
One other interesting new answer was by zefram that this bug if not fixable, because we'd need support for lexical
$_ in every op which supports implicit
$_ or takes blocks, such as grep and map, obviously not knowing the codebase that this is exactly what we were doing quite efficiently since 2001. There is e.g. a special lexical grep bit. A
git grep GREP_LEX would have helped, which was added 2004 as a special bit to grep.
I think there's no way forward that looks at all similar to what we have. Any lexical topic variable would at least have to be selected on a per-construct basis: you can't have "my $_" causing grep and the like to use a lexical topic. A spearate "grep_lexical" operator should be fine, but if we go that route we should consider forcing the lexical topic variable to have a name other than "$_" to avoid the confusing shadowing. Actual "my $_" should be no more valid than "my @_". - June 2015.
There was no single answer to that clear message. In retrospect I would also don't know what to answer to so much nonsense in one single paragraph.
I concur with rgs that "In my opinion, the more important problem here is the impression that P5P is throwing away without much thought of a perfectly nice and modern language feature (for some value of modern that means "post-FORTRAN"). This could give the impression of a the lack of vision for Perl 5 (and reinforce the "perl is dead" death spiral as perceived by the outside world -- the Perl users)."
Well said, and I knew it beforehand before it became true. But it's pretty easy to foresee such desaster looking at the track record this team is piling up, and how they react to critism, reviews and help. Their latest attempt to come up with an unwritten religious CoC rule, that you need to have faith in the maintainers in order to talk to them is the final sign of "Death by Code of Conduct". It's pretty hard to have faith in someone who decides 90% on the wrong side and only by luck sometimes makes a right decision. Initially I thought this code of conduct could finally stop all the silly bullying and name calling, but it got even worse, and whenever I complain about such abuse p5p punishes the one who complains about abuse, which is clearly only in the interest of the p5p buddies to maintain their powers they are abusing, but not in the interest of anybody else.
Now that p5p decided on this schism and went forward with more totally wrong and outragious decisions to do more and more harm on the perl5 language, I can only recommend to use cperl, the perl5 implementation where such grave mistakes do not happen, where perl5 development actually continues in the spirit before p5p took it over, and where the p5p principles of ruling by incompetence, power and abuse are not tolerated. cperl decisions are made rationally, professionally and most of all "cperl is not a religion". You are allowed to show distrust and criticsm. And in cperl such bugs are actually getting fixed, and the language is not harmed.
You will also hopefully not see those incredibly silly mailinglist threads as the cited one above. It's atrocious. We can only hope that p5p is put to an end soon, and a proper development process can start. There's no way this can go forward like this.
|CPAN module
|A tool to make it easier to manage multiple code repositories using different VCSen
|Engine for tidyall, your all-in-one code tidier and validator
|Generic Config Module
|Time zone object base class and factory
|distribution builder; installer not included!
|a library for sending email
|Create a new file in the Excel 2007+ XLSX format.
|Create a module Makefile
|Nearly transparent SSL encapsulation for IO::Socket::INET.
|Read and write meta information
|Apache Lucy search engine library.
|Job queue
|Compress and convert css, less, sass, javascript and coffeescript files
|A Moose role for processing command line options
|Turnkey ajaxy webapps
|Assemble multiple Regular Expressions into a single RE
|Roles. Like a nouvelle cuisine portion size slice of Moose.
|The official client for Elasticsearch
|Meta-Wrapper for reading spreadsheet data
|create and use a local lib/ for perl modules with PERL5LIB
|turn on strict and make most warnings fatal


text:
From The Article: "Google and Bing are significantly increasing the role of social media in the user experience of searchers. Instead of getting a simple list of 10 links in search results, we now see tons of recommendations from our friends who have shared content on social media.
Additionally, search engines have publicly announced that social signals are being used as a factor to determine search rankings. As a result, search marketers will need to incorporate social media into their strategy to take advantage of the growing opportunities in social + search.
The following resources will help you learn more about integrating social and SEO".
Full Article Here: http://www.sparkplugdigital.com/blog/seo-social-integration/
Via Antonino Militello

subset: commoncrawl


text:
FROM PORTUGAL is a project from "Selectiva Moda Association" and "Textile and Clothing Association of Portugal" to promote the Portuguese: Yarns, Fabrics, Accessories, Technical and Functional Textiles, Fashion, Home Textile and Decoration , from Europe to America and Asia.
For FABRICS and ACCESSORIES we will be in 2016 at: The London Textile Fair, Première Vision New York, Colombiatex, Munich Fabric Start, Milano Unica, Premiere Vision Paris, Jitac European Textile Fair, Intertextile Shanghai Apparel Fabrics, Premiere Vision Istambul and Tissu Premier.VISIT WEBSITE
Business France
Business France is the national agency supporting the international development of the French economy, responsible for fostering export growth by French businesses, as well as promoting and facilitating international investment in France.
It promotes French companies, business image and nationwide attractiveness as an investment location and also run the V.I.E. international internship program.VISIT WEBSITE
La Spola
La Spola was first published in 1997, as the 'voice' of Italian textile districts. The magazine's paper version was issued in 2009, when it became an online daily newspaper and the range of issues covered was extended: not only the entire textile-clothing chain, but also the textile machinery, economy and fashion fields.
Showcase is a special glossy magazine which is published on the occasion of the textile industry's major trade shows. It is usually published every six months but, in 2015, we released a special issue on the ITMA show, of which La Spola was media partner. Showcase magazine is distributed at Pitti Filati, Milano Unica, Première Vision, Filo and other trade shows.VISIT WEBSITE
FashionMag.com is a business information site for fashion professionals. FashionMag.com publishes daily newsletters in 10 languages worldwide. With more than 800,000 subscribers, FashionMag.com is the leading source of information for the world's fashion professionals.VISIT WEBSITE
METAINITALY is an international webzine dedicated to technology and innovative ideas in the field of printing and new materials for high level fashion textiles applied to the world of garments, interior design and technical textiles. METAINITALY focus on technical innovations and insights on the trends as well as the social and environmental sustainability. Updated in real time and open to cooperation with universities and technical institutes, but also for vendors and user companies, META IN ITALY, periodically publish METAnews and twice a year the Special METAtrend with analysis on industry trends. META IN ITALY is widespread among manufacturers of machines, materials and textile accessories; textile printers, stylists and fashion houses in Italy and abroad. The manufacturing companies can find in META IN ITALY a good communication medium for their ideas and innovations.VISIT WEBSITE
Albini & Pitigliani
Extensive network, highly experienced technicians, consistent processes and reliable salesforce are the ingredients to the Alpi formula. Airfreight, seafreight and ground transportation are the main activities of the Alpi network. All phases of the process are covered from order management, to door delivery, going through pick up, consolidation, documentation, customs clearance, certifications management, best carrier selection and an track & trace system that can be tailored to customer's needs.


text:
The Flowlight is a hyped up laser pointer that enables writing and sketching in the air. The streams of light are created when the base unit - a cone shaped device - focuses a laser beam 100 times per second to the pen. The Flowlight then forms small "plasma points that glow in mid-air."
Several of these plasma points result in a continuous glowing line. The Flowlight has many potential applications from medicine to architecture. It could also become the top rated toy for household cats surpassing the laser pointer!
The Flowlight is a concept design from the d-Vision internship program for product development and industrial design.
Stats for Laser Air Writing
Trending: Older & Warm
Research: 16,911 clicks in 405 w
Interest: 1.7 minutes
Concept: Laser Air Writing
Related: 55 examples / 42 photos
Segment: Neutral, 18-35
Comparison Set: 20 similar articles, including: playful gaming drones, sweetened beet snacks, and canned air deliveries.
Laser Air Writing
More Stats +/-
Sweetened Beet Snacks
Playful Gaming Drones
Canned Air Deliveries
Sexism-Fighting Playing Cards
Rainbow Latte Art
The Flowlight
By: Pearl - Published: Jul 28, 2008 • References: d-vision.co.il & interiordesignroom.blogspot


text:
Begin New Search
Refine Last Search
Cemetery Lookup
Add Burial Records
Help with Find A Grave
Find all
s in:
La Verne Cemetery
La Verne
Los Angeles County
Find A Grave
Top Contributors
Success Stories
Community Forums
Find A Grave Store
Log In
ad feedback
ad feedback
Madelle Elizabeth Abbott
Learn about upgrading this memorial...
Jul. 3, 1932
King County
Washington, USA
Aug. 6, 2009
San Dimas
Los Angeles County
California, USA
Madelle (Sally) Elizabeth Abbott of San Dimas, Calif., died on Aug. 6, 2009 at Pomona Valley Hospital of pneumonia due to Leukemia. Sally was born, July 3, 1932 in Seattle, Wash. Sally graduated UC Berkley with a BA degree in Sociology. In 1955 she married Spencer Earl Abbott and they moved to the Charter Oak/San Dimas area to build their life together. Sally was a perpetual volunteer. She spent 16 years as a Camp Fire Girl Leader with five years specializing in teaching the leaders how to cook outdoors with the girls. Additionally, she volunteered for Charter Oak School District, Boy Scouts, La Verne YMCA and 4-H. Sally was a Home Economics Teacher at Chaparral Middle School in Diamond Bar from 1976 to 1990. Her love of cooking and sewing was infectious to all. Sally traveled the West Coast and Mexico for over 50 years joyfully with her husband and family in their motor home every summer visiting family and friends. They purchased a property in Forest Dell in 1978 and for over 30 years enjoyed Star Valley during August and September. One of Sally's favorite things to do was to roam the yard sales in order to meet new people and see new areas of the Valley. She especially enjoyed hosting family and friends in her beloved mountain paradise. Sally is survived by her husband, Spencer Abbott. Her sister, Carol Widrig of Seattle, and sister in-law, Patty Widrig of Gig Harbor, Wash. Her three children: Kathleen Bennet and husband Ed of San Dimas; Raymond Abbott of San Dimas; and Jill Serna of Henderson, Nev. She is also survived by three grandchildren; Bryce Hulet, Danielle Serna, Kevin Serna and two great-granddaughters; Taylor and Trinity. Sally will be remembered as a wonderful wife, mother and friend to all that she met. We who loved her are grateful for her life and her example. She will be greatly missed. A celebration of her life will be held at 11 a.m. on Sunday, August 30 at Todd's Memorial Chapel in Pomona, 570 North Garey Avenue, with lunch following at the Sheraton Fairplex. A private interment at La Verne Cemetery was held Aug. 13, 2009.
La Verne Cemetery
La Verne
Los Angeles County
California, USA
Created by:
suzan gordon
Record added: Sep 27, 2009
Find A Grave Memorial# 42448434
Added by:
suzan gordon
Added by:
Richard Pittman
Cemetery Photo
Added by:
Sal Giambruno
Photos may be scaled.
Click on image for full size.
Leukemia is an awful disease. May you always be comforted by memories of this person.
Added: May. 4, 2013
Privacy Statement
Terms of Service
ad feedback
Other results for
Newspaper records for :
North Carolina
See more…
View records
Military records for :
The Revolutionary War
The Civil War
See more…
View records


text:
Posted Jan. 7, 2010 at 1:26 p.m.
Copyright 2016 WRAL TechWire. All rights reserved.
Square 1 Bank hires veteran exec to lead tech, later stage lending practices
Get the latest news alerts: Follow LTW at Twitter....
Copyright 2016 WRAL TechWire. All rights reserved.
Editor's Blog
The latest blog posts from our WRAL TechWire and WRAL editors. Read more articles…
Please Log In to add a comment.
Latest for Insiders
Latest Tech News
Biotech & Life Science
The Skinny
- Exclusive: AgTech Accelerator CEO spells out mission, offerings to startups, and why it's needed
- Countering downgrades, S&P gives Quintiles a post-merger boost
- 'Look, look:' Mira carries Triangle hopes to Google Demo Day
- Analyst: Q-IMS merger could trigger more deals; why Street doesn't like Q deal
- CEOs' meeting leads to huge $17.6B Quintiles-IMS merger
- Meet Carolyn Sparano, a Bronto vet, now its GM
- Joe Colopy's last Bronto roar: What's next for one of Triangle's best known entrepreneurs?
- Chaz Felix: Why he left Bronto, what's next, and will he work with Joe Colopy again?
- Executive Q&A: Practichem CEO talks new funding, hiring plans, benefits of relocating to Triangle
- Double winners: HQ Raleigh, Red Hat share Full Steam awards spotlight


text:
Oviedo, FLUSA
Hometown: Orlando, FL
September 22, 2013
No answer yet
Well of Course! (and yes, could help out as well)
I do not have a boat, but have been a boater for years! Will Tube and still trying to get back up on those skis!!
Hello My Name is Jane! Love boating, and may even get enough guts up to Hand Glide!
Meetup members, Log in
By clicking "Sign up" or "Sign up using Facebook", you confirm that you accept our Terms of Service & Privacy Policy


text:
Watch "Diablo II: Lord Of Destruction (2001)" Movie Online
The world is torn by war being made by Diablo, the demonic lord of terror from Hell itself. With his brothers, the Satanic manifestations Mephisto and Baal, Diablo wages war on the mortal world. However, holy warriors and rebels, along with the help of a celestial Archangel sent by Heaven, stand against Diablo and his malignant forces as they prepare to fight in the truly apocalyptic conflict. In the expansion, Baal takes over command of Diablo's forces as the end of the war draws near
Share this movie
|HTML code
|Forum code
IMDB page | Add to Favorite | Share
Full-Length Movie Sources Online
100% said link Ok!
Forgot password?
RegisterRegistration is free and you'll be able to make movie request, submit a movie, view other users profile and leave a comments.
Complete the simple form below.


text:
Warmth will hold around Pittsburgh through Monday, but the return of much colder air is on the horizon.
The weekend will end with the warmest air so far this year pouring across southwestern Pennsylvania, boosting temperatures past the 80-degree mark.
Dry weather and some sunshine will compliment the warmth.
Temperatures will still rise well into the 70s on Monday despite some more clouds filtering overhead and a couple of showers and thunderstorms arriving in the afternoon.
Chilly air plunging into the Plains will swing eastward in the upcoming days.
Detailed Pittsburgh Forecast
Pittsburgh Interactive Weather Radar
Forecast Temperature Maps
Steadier rain will follow for Monday night in Pittsburgh as the cold blast approaches, leading to a dramatically colder Tuesday.
Tuesday's expected high of 45 F is likely to occur prior to daybreak with temperatures then falling into the 30s. The rain may even mix with or end as wet snow.
Temperatures will drop into the 20s Tuesday night, spelling bad news for those who planted sensitive vegetation early.
More seasonable high temperatures should follow for later in the week.
The threat of severe weather will return to the south-central United States this weekend.
A massive wildfire burning in Alberta, Canada, moved through the city of Fort McMurray, forcing the entire city to be evacuated.
A system with rain and thunderstorms will bring both good and bad news to the western United States later this week.
Plenty of warmth and sunshine will be in the forecast this Saturday as the 142nd running of the Kentucky Derby takes place at famed Churchill Downs in Louisville this Saturday.
As millions prepare to celebrate Mother's Day on Sunday, May 8, rain and severe storms threaten to disrupt outdoor activities and travel plans.
While thunderstorms produced deadly flooding across portions of the United States this week, destructive wildfires spread rapidly and ravaged Fort McMurrary, Alberta.
Omaha, NE (1975)
Massive tornado killed 3 people and injured 133 while causing 150 million dollars worth of damage. Tornado cut a swath 10 miles long and one-quarter of a mile wide through the industrial and residential areas of west-central Omaha before lifting over the northern section of the city. Most costly U.S. tornado to date.
Plains (1983)
Thunderstorms rake over Nebraska and Kansas with golf ball-sized hail, wind gusts close to 90 mph at Superior, NE, and 3-1/2 inches of rain at Kensaw, NE.
Sheridan Lake, ND (1984)
Lightning struck a boat out on the water, killing two occupants. A life vest was torn to bits by the powerful bolt.


text:
More thrilling horror and excitement in another masterpiece collection of vintage Vampirella classics! Take another journey into frightening and gory tales brought to you by a host of frighteningly talented writers and artists. Reprinting issues #43-49 of Vampirella Magazine as she does battle with the forces of Chaos and a new deadly nemesis â The Blood Red Queen Of Hearts! Also featuring classic covers by the likes of Enrich and Ken Kelly. Stories and art by virtuoso talents like Jose Gonzalez, Esteban Maroto, Len Wein, Neil Adams and many more all bound in another heavy collection brought to you by Dynamite!
"Tomb Raider" Finds Its Lara Croft in "Ex Machina's" Alicia Vikander
Video Games, Film