Automating Stratopan Releases with Perl's Dist::Zilla

| No Comments | No TrackBacks

I recently started using Jeffrey Thalhammer's excellent Stratopan to manage CPAN dependencies for a new Perl project. I had played a little with Stratopan before, but now that I'm starting to get some use out of it, I am even more impressed with Jeffrey's work.

Stratopan allows you to create your own CPAN-like site in the cloud, which you can use to maintain a stable basket of dependencies for your project. You won't have to worry about new versions of distributions sneaking onto your private CPAN and breaking your stuff. Even better, you can upload your own, private CPAN-like distributions, and now you have the entire CPAN toolchain available to manage your internal codebase.

The one shortcoming I ran into was releasing my own distributions directly to Stratopan. Stratopan has a web interface where you can upload distribution tarballs, but I wanted to just be able to type dzil release, just like I do to make public CPAN releases. Those make use of Dist::Zilla::Plugin::UploadToCPAN, but there was no equivalent for Stratopan. Until now!

I just released the first version of Dist::Zilla::Plugin::UploadToStratopan which will handle automated Stratopan releases for you. All you have to do is specify the project and stack name in your dist.ini and the rest is automatic.

Stratopan does not yet have a REST API (they're working on it) so this module just uses LWP to upload via Stratopan's upload form. It will prompt you for your username and password and then you're done.

The meat of it is pretty straightforward. After setting up some Moose attributes and consuming the dzil Releaser role, the actual release process works as follows:

sub release {
    my ( $self, $tarball ) = @_;

    $tarball = "$tarball";    # stringify object

    my $ua = $self->_lwp;
    my $resp = $ua->post( $self->_strato_base . '/signin', {
                  login    => $self->_username,
                  password => $self->_password
              } );

    # do this the stupid way for now.
    if ( $resp->decoded_content =~ m{<div id="page-alert".+Incorrect login}s ) {
        $self->log_fatal( "Stratopan authentication failed." );

    my $submit_url = sprintf '%s/%s/%s/%s/stack/add',
        $self->_strato_base, $self->_username, $self->project, $self->stack;

    $self->log( [ "uploading %s to %s", $tarball, $submit_url ] );

    $resp = $ua->post( $submit_url,
        Content_Type    => 'form-data',
        Content         => [
            archive         => [ $tarball, $tarball,
                                 Content_Type => "application/x-gzip" ],
            recurse     => 1,

    if ( $resp->code == 302 ) {
        return $self->log( "success." );

    $self->log_fatal( $resp->status_line );

Not too fancy at all.

If you haven't already, be sure to check out Stratopan and Pinto the project on which it's built. There is no question in my mind that they will have a very prominent place in Perl development going forward.

No TrackBacks

TrackBack URL:

Leave a comment

About this Entry

This page contains a single entry by Mike Friedman published on June 10, 2014 7:23 PM.

Removing Perl Boilerplate with Import::Into was the previous entry in this blog.

(Ab)using the MongoDB Aggregation Framework for Symbolic Computation is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.


  • Exploring Perl 6


Powered by Movable Type 5.14-en