Marcus Ramberg <insert something deeply moving and profound>

NoOps is an awful word #

What do IT Ops do? We manage IT risk on behalf of the business. Thinking Ops is about servers is like thinking Dev is about code cutting.

If you think devops means eliminating operations, you don't understand development or operations.

How GitHub uses GitHub to document GitHub #

Documentation teams across GitHub can take advantage of the GitHub Flow, Jekyll 2.0, and GitHub Pages to produce high-quality documentation. The benefits that GitHub Pages provides to our Documentation team is already available to any user running a GitHub Pages site.

Great dogfooding

Posting To Github Pages From Ios

This post is a quick test to see if I can easily post to my blog from Working Copy and Textastic. It is still a little beta, but it seems very promising!

Building Ansible Modules with Perl and Mojolicious

While setting up Output, we decided to automate all our infrastructure using Ansible. This lets us easily do zero downtime releases and create new workers as needed to scale. We've got roles for haproxy, postgresql, nginx, our app servers and a lot more. One thing we've been handling manually so far is DNS. We're happy Cloudflare users, and they have one of the best DNS admin tools I've used, but still I felt like we could do better.

My friend Jan Henning also felt this way, and had already written Mojo::Cloudflare, a simple API client for Cloudflare. Even tho Ansible is Python-based, you can write your plugins in whatever language you like, so I decided to glue the two together. This turned out to be quite easy. First you need to tell ansible you can handle json:

#!/usr/bin/env perl

Then we get the module argument file from the args, and parse the JSON:

use Mojo::JSON;
use Mojo::Util qw/slurp/;

my $json = Mojo::JSON->new;
my $args = $json->decode(slurp($ARGV[0]));

And then you just process those arguments and do your thing. Lets say you want to check for required arguments:

for (qw/email api_key zone name/) {
  fail("$_ is a required argument") unless exists $args->{$_};

My fail method looks like this:

sub fail {
  my $msg = shift;
  print $json->encode({failed => 1, message => $msg});
  exit 1;

The important thing here is to exit 1, the json response is icing on the cake. For success you could could do something like this:

print $json->encode({changed => \$changed, record => $current->id});

Note the bool reference to make Mojo::JSON return true/false. $changed will make the difference between OK and CHANGED output in your ansible run.

Put your module in a library/ sub directory of your playbook folder, and you can just use it in your playbook like this:

local_action: cloudflare name=sentry type=CNAME service_mode=1 email= 

I store my Cloudflare credentials in an ansible-vault and just include that in my playbook. Note that using this module will require having the latest version of Mojo::Cloudflare installed. If you want to run it on the remote server rather than as a local_action, that server must also have the module.

Anyways, if you want to try it yourself, you can find the latest version of my cloudflare ansible module here.

Convos 0.8 - Spit and polish

This fall we released Convos 0.8, with the latest update 0.83 hitting CPAN today. As we're inching closer to 1.0, we've been focusing on polishing the user interface, fixing bugs and other rough patches in the user experience. One of the most important improvements in this round is how you switch between conversations.

Previously, when you pressed shift+enter, we shifted focus to the conversation list on the top, to let you tab through your most recent conversations . Now, shift enter will open up a panel on your right hand, where you can tab through all known channels and usernames, or you can start typing to filter the list. You can even join a new channel by typing in a unknown channel name and selecting the server to join on (if you have more than one).

Change channel dialog

The same list is available by hitting the hamburger menu to the right of the channel list, and of course this works just as well on mobile.

Change on mobile

We've also replaced the dropdowns on the top with slide in panels that works more smoothly both on the desktop and mobile.

Another new feature in the 0.8 series that I really enjoy is the recent activity line. We now track whenever a channel goes out of focus, either because you switch to another tab, or to another channel. When you return, there's a line showing you what's new since you switching away.

screenshot of activity line

Desktop notifications, which was broken in 0.7, has been fixed and improved a lot as well. Now, we ask you if you want desktop notifications like this - it works in all major browsers.

screenshot of notification

We've also changed the way web sockets are handled, now we always load new messages on web socket connect, significantly improving stability and performance. We've also added some more irc commands. You can now /kick people, and /names will show you who's op and voiced in the current channel at any time.

There's alot of other bugfixes and improvements as well, if you're interested in learning more you can check out the full changelog, try our demo or follow our Installation instructions to run your own.

Our main focus for the next release is cleaning up the Connection Manager, and there's already solid progress on this work. I'll leave you with this sneak peak of the new channel join dialog.