<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Scribblings and Geekery]]></title>
  <link href="http://www.mattshelton.net/atom.xml" rel="self"/>
  <link href="http://www.mattshelton.net/"/>
  <updated>2019-03-23T02:11:18+00:00</updated>
  <id>http://www.mattshelton.net/</id>
  <author>
    <name><![CDATA[Matt Shelton]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Freedom and Compliance]]></title>
    <link href="http://www.mattshelton.net/2019/03/22/freedom-and-compliance/"/>
    <updated>2019-03-22T11:13:13-04:00</updated>
    <id>http://www.mattshelton.net/2019/03/22/freedom-and-compliance</id>
    <content type="html"><![CDATA[<p>I'm speaking at <a href="https://www.atlassian.com/company/events/summit">Atlassian Summit</a> this year on the topic of <a href="https://www.atlassian.com/company/events/summit/schedule?sessionid=509650">Continuous Delivery</a> at Scale. In the lead up to the conference, which is April 9-11 in Las Vegas, I recorded an interview about the topic with our marketing team:</p>

<iframe width="100%" height="300" scrolling="no" frameborder="no" allow="autoplay" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/590730711&color=%23ff5500&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true"></iframe>


<p>It came out pretty well and I'm now even more excited to speak.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Jekyll to Day One]]></title>
    <link href="http://www.mattshelton.net/2018/12/04/jekyll-to-dayone/"/>
    <updated>2018-12-04T22:00:53-04:00</updated>
    <id>http://www.mattshelton.net/2018/12/04/jekyll-to-dayone</id>
    <content type="html"><![CDATA[<p>After pushing my post on <a href="http://www.mattshelton.net/2018/12/01/how-i-use-day-one/">How I Use Day One</a> live the other day, I got to thinking about other Day One use cases that I wasn’t actively exploring which might be useful or interesting. The first one that came to mind was something I had considered in the past but rejected for largely refutable reasons: storing a backup of the posts on this site. Since my posts are already markdown-formatted, storing them in Day One <em>should</em> have been something I did ages ago, but I had wanted to keep my first post date to my younger son’s birthday. Since my blog existed before that, storing those posts in Day One would “mess things up” in some sense.</p>

<p>Except it was my own stupid rule so I got over it.</p>

<p>Now, since it’s all Markdown, I could just copy and paste every single entry into Day One, update the date/time, add some tags, and repeat… but that’s a lot of work and absolutely no fun. Instead I spent my Sunday afternoon writing a python script to parse the <a href="https://jekyllrb.com/docs/front-matter/">YAML front-matter</a> for each post, re-format any content which used <a href="https://jekyllrb.com/docs/liquid/">Liquid</a> tags and Jekyll <a href="https://jekyllrb.com/docs/plugins/">plugins</a>, and rip out images to a local directory so that all of this could be imported to a Blog journal via the <a href="http://help.dayoneapp.com/tips-and-tutorials/command-line-interface-cli">Day One CLI</a>.</p>

<p>This mostly worked, except where it did not, for instance</p>

<ul>
<li>Any remote images whose links were broken. The code doesn’t handle that situation, so I had to manually fix the whole two posts that were like this.</li>
<li>Sometimes an entire post would be in italics or bolded after import. I saw nothing consistent about these, and I suspect a Day One issue as I’ve had random “stuck in italics” problems on the Mac client that I cannot reliably reproduce.</li>
<li>Day One no longer <em>technically</em> supports footnotes. They still work for now, but I’m wary and in a few spot-check cases I just removed them and put the content in-line. This isn’t much of a backup but makes the post more portable to a non-Markdown-based system in the future. Maybe.</li>
<li>There is no valid way to use a strike-through in Markdown, so in my blog entries I used <code>s</code> tags. Those translate as code fragments in Day One, which is weird looking. It’s just a visual abberation.</li>
<li>Any cross-reference links that make use of Liquid tags (e.g. ) just stay like that. I fixed those ~30ish posts manually.</li>
<li>Any time my Liquid syntax or YAML front-matter wasn’t perfect. Jekyll is more forgiving than me, apparently, so there were a few posts that threw <em>really</em> ugly error messages when their imports failed.</li>
<li>Too many markdown reference-style links in a post just break the entry and the links stop working. I only had a couple of posts like this but they required a <em>lot</em> of work to fix.</li>
</ul>


<p>Of the 232 posts that I imported, about 55 had something about them which needed to be fixed.</p>

<p>Since the script might be useful to someone else, I put it up on <a href="https://bitbucket.org/">Bitbucket</a>. You can find it <a href="http://bitbucket.org/mattshelton/jekyll-to-dayone/">here</a>. I have a little clean-up to do in the repo, but it’s serviceable.</p>

<p>My “Journal” journal still has the start date that’s important to me, but now my site’s posts are preserved in another format that’s just as, if not more, important to me.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How I Use Day One]]></title>
    <link href="http://www.mattshelton.net/2018/12/01/how-i-use-day-one/"/>
    <updated>2018-12-01T10:04:26-04:00</updated>
    <id>http://www.mattshelton.net/2018/12/01/how-i-use-day-one</id>
    <content type="html"><![CDATA[<p>Or, why I don’t write on this site anymore.</p>

<h2>Why I Journal</h2>

<p>When my younger son, B, was born, I wanted to record my thoughts on being a dad to two boys. My handwriting is horrific, so a written journal was not going to support this habit. I had an iPhone, and was already snapping photos of our older son all the time, so the fusion of my circumstances led me to buy <a href="https://dayoneapp.com/">Day One</a> for iOS on the (really early) morning of B’s birth, and write about sleeping and feeding and how this all compared to when his brother was born.</p>

<p>Even over five years ago, the UI for Day One was <em>really</em> superb. It had been the App of the year in 2012, and it won an Apple Design Award shortly thereafter that was well-deserved. Writing in it was (and still is) a joy. I could use the form of Markdown I already knew and loved, and the stylesheet looked great. I grabbed the Mac app a week or two later and could write from nearly anywhere. At the time, it only supported a single journal (called Journal) and synchronization was done either via iCloud (buggy as all get out) or Dropbox (super-reliable but a little slow). I chose the latter, and upgraded to the “Plus” tier at some point to be able to have multiple photos per entry and multiple Journals. I used both <a href="https://ifttt.com">IFTTT</a> and <a href="http://brettterpstra.com/projects/slogger/">Slogger</a> to automate my social life and other services into my journal.</p>

<p>A couple of years ago, Day One introduced a Paid subscription tier, as many other app/service vendors have. I avoided upgrading for a long time, but as they started talking about their roadmap (end-to-end encryption, audio recordings, web editing, etc.), I realized that this app’s future was <em>actually</em> important to me. I was using it almost daily, and if I wanted it to be there in the future, it behooved me to provide, in some small part, financial support. Since then, those first two features have arrived and then some, and they continue to be worth every penny.</p>

<p>Realistically, though, these are <em>excuses</em>. I don’t journal just because I like writing, <strong>I journal because I don’t want to forget.</strong> While I can remember convoluted plot lines of almost any fiction I consume, I struggle to remember precisely what I was thinking about 30 minutes ago, let alone yesterday, last month, or last year. On a recent episode of <a href="https://dchhaddendum.libsyn.com/ep6-on-the-vietnam-war-with-sir-max">Hardcore History Addendum</a>, <a href="https://www.dancarlin.com">Dan Carlin</a> said something to the effect that, to people in the midst of some event, that event is “the most important” thing happening, but as time separates the observer from the event, and it is seen within the grand context of existence, that event is somewhat unimportant. Even historical figures like, say, Aristotle, may have just been some guy yelling in a marketplace, but with a good publisher...</p>

<p>In any case, I journal because I know I’d forget details of my life that have monumental value in the moment and which may have some value to future me. When I look back at these writings through the lens of time I get to re-live some of that weight and re-learn some of the lessons I was learning then. That has supreme value to me.</p>

<h2>What I Journal</h2>

<div class="right"><img class="right" src="http://www.mattshelton.net/assets/img/day-one-journals.png"></div>


<p>I use Day One for, at the moment, 8 major categories of things, and these line up with the individual journals that I have:</p>

<h3>Journal</h3>

<p>This is where I do general journaling about life. It’s for things I’m thinking about, for when my kids do something cute, or for when I take a nice picture of my dog that I want to capture. This is what a “journal” might be if I only used it for personal activity and life commentary.</p>

<p>As I take photos on my phone, any good ones, or any that catalog what I have been up to recently end up in Journal with a paragraph or two about it, why it was momentous, etc. I liberally tag my entries with people’s names, topics, event groupings, etc. I’d love to have richer tagging for people to make a mini/personal social graph of people and places and events, but that sort of scope creeps beyond a journal and I like that Day One focuses on what it does best.</p>

<p>I automate hardly anything into Journal, save podcast notes which are templated by sharing an <a href="https://overcast.fm/">Overcast</a> link with a Shortcut that pulls down all of the metadata and formats the entry. All of the rest of this content is created by me. I do enjoy the Activity Feed view in the iOS client as it helps me catch up and write entries about places and photos of the last few days.</p>

<h3>Faith &amp; Scripture</h3>

<p>This journal is for sermon notes, Bible study notes, thoughts on a verse of the day that I want to capture or highlight, things where I see God clearly doing something in my or someone else’s life that I want to remember, etc..</p>

<p>I have a particular format for some entry types and I am really looking forward to in-app templates that I can use for that content. I tag each book of the Bible mentioned in each entry, as well as any themes, study plans, etc. So far Genesis has the most uses followed closely by 1 Corinthians, but that’s mostly because every time I start a chronological study, I am really diligent about journaling my notes and less so over time. I found the <a href="https://replicate.org/f260-bible-reading-plan/">F260 method</a> earlier this year and that’s certainly helped.</p>

<p>I don’t automate anything into this Journal. I would love to see an integration between <a href="https://www.youversion.com/the-bible-app/">The Bible App - YouVersion</a> and Day One so that my highlights and notes could be brought over. I considered building a Shortcut for it, but it’s not too many fewer steps to copy and paste than to share to a Shortcut.</p>

<h3>Daily Book</h3>

<p>This is an inconsistent attempt to write a summary of my working day. I earnestly tried to write this for about a month. It was useful at the time, and I should get back to it. It’s another use case for a structured template.</p>

<p>I semi-automate the creation of these entries with a reminder template. When the editor switched out of Markdown to rich text, though, the template got all wonky. My ideal world is one where, every morning, some service or process creates a template with the content I want in it from Google Calendar and Todoist and then places it in my journal to be filled in throughout the day. This journal isn’t encrypted so that might be possible with the <a href="http://help.dayoneapp.com/tips-and-tutorials/command-line-interface-cli">CLI</a>. A project for a rainy day, perhaps.</p>

<h3>Instagram</h3>

<p>All of my wife and my Instagram feeds dump our photos here via <a href="https://ifttt.com/">IFTTT</a>. I add/edit tags after the fact to include people’s names that we wouldn’t tag on Instagram, like our kids. I’d love for Day One to support multiple Instagram accounts so that I didn’t need to have multiple IFTTT accounts to cover all of these feeds.</p>

<h3>Reading</h3>

<p>This journal is for any time I am reading a book and want to quote something, or I am reading something on <a href="http://instapaper.com/">http://instapaper.com/</a> and I highlight it. The Instapaper entries are created via IFTTT as one per highlight, so I go back later and consolidate.</p>

<p>To capture text from physical books, I use either <a href="https://itunes.apple.com/us/app/scanner-pro/id333710667?mt=8">Scanner Pro</a> or <a href="https://itunes.apple.com/us/app/prizmo-go-instant-text-ocr/id1183367390?mt=8">Prizmo Go</a>. Both work pretty well and I haven’t settled on one that I prefer. I don’t use tags much in this journal.</p>

<h3>Libations</h3>

<p>My whisky (and Scotch and Bourbon) tasting notes go here. I use a 5-star rating system, tag by rating, region, variety, etc., and write my thoughts on the liquor. I have a few beers in here also, but it’s mostly whisky and whisky-like drinks. I’ve used a handful of iOS apps for this purpose before, but their providers all fall into dis-use over time. My notes are really for me, anyway, but I’m always happy to share.</p>

<p>Entries into this journal are 75% automated via a Siri Shortcut that I wrote. In addition to needing to write my own notes for obvious reasons, I also have to have a photo already in my photos library, though I suppose I could modify it to let me take a new one at the time. There is no searchable whisky database I could use to back-end my creation process. That would be nifty.</p>

<h3>Notes</h3>

<p>This is for general notes which I want to be more permanent. Notes from one or more transient note applications end up here if I want them to live forever. More on this in a bit.</p>

<h3>The Plan</h3>

<p>My wife and I are starting to look at other properties. So far there are only two entries; we’re not that serious yet.</p>

<p>This journal is almost entirely automated. I wrote a small python script to scrape relevant details out of a Zillow listing and shove them into a journal entry that I can go back and write about later. I share a listing to a Shortcut and the entry is created in a few seconds. Right now my script is running on PyhonAnywhere, but I will probably move it to run only locally via Pythonista.</p>

<p>As we get more serious I’ll probably start using the audio recording feature to capture our thoughts as we walk around a property or as we leave.</p>

<h3>Gratitude</h3>

<p>(Wait, that’s nine…)</p>

<p>I’m reading through <a href="http://www.gratitudediaries.com">The Gratitude Diaries</a> by <a href="http://www.janicekaplan.com">Janice Kaplan</a> right now, at the recommendation of the <a href="https://www.facebook.com/groups/DayOneCommunity/">Day One community</a>. It’s a pretty good read, and I think I’m going to give her method a shot in 2019. So that’s one more journal, but I haven’t started that yet, so it’s still technically 8.</p>

<h2>Day One as the End Game</h2>

<p><em>So I use Day One for a few things, eh?</em></p>

<p>In an article on <a href="https://thesweetsetup.com/use-day-one-aside-differences-bear-day-one/">The Sweet Setup</a>, Josh Ginter wrote about for what he uses each of <a href="https://bear.app/">Bear</a> and Day One and why they have different places in his tool belt. I admit that Bear is useful; I drafted this post in Bear, for instance, but ultimately Bear is transient for me, much the way that Apple Notes was for a long time. What he says rings true to me, too: Day One is the end game; anything that I want to have last for any reasonable period of time finds its way into Day One. Bear is for meeting notes and packing lists and drafts of things I will eventually journal.</p>

<p>That’s where my Notes Journal comes in handy: for those notes (that were originally) in Apple Notes or Bear which have long-standing purpose, there is a specific journal where they end up. If Bear disappeared tomorrow (read: the day after I publish <em>this</em> draft) there isn’t much I’d miss. If Day One were gone, I’d be crushed.</p>

<p>That concept is what underscores the purpose of Day One in my life: it is a <a href="https://thesweetsetup.com/how-to-use-day-one-as-a-commonplace-book-part-ii/">commonplace book</a>, as another Sweet Setup writer put it. I automate the process of funneling my other creations into Day One so that I have <strong>one</strong> place for things. I don’t care that Instapaper has my highlights, for instance—they have been copied into Day One and that’s where I read and review them anyway. I used to be a <a href="https://getpocket.com/">Pocket</a> user and only switched because Instapaper had highlighting that I could put into Day One. It looks like Pocket can, now, too, so one day I may end up switching back. The initiating platform is unimportant; the result is what I care about.</p>

<p>A note about encryption: I’m a big fan, however as you might expect, an encrypted journal cannot be written to by external automation systems, such as IFTTT. This means that my default is that a journal should be encrypted unless I plan to automate entries into it. Automation from Shortcuts still works regardless of the state of the journal, so long as I’m willing to open Day One at the end.</p>

<h2>Memories</h2>

<p>As I said when I started this post, though, the other, and really more important reason why I do all of this, is so that I remember. My natural memory is shockingly poor at times. I have a very hard time remembering events or remembering what I was thinking when something happened, or my rationale for a decision. Journaling gives me a chance to capture that information and then re-visit it on occasion.</p>

<p>Day One makes this all the easier with the “On this day” feature, which ranks as pretty much every user’s favorite thing about the app. Every single day, I look at things I wrote between one and five years ago on that same day. It’s humbling to see where we all were in life even just one year ago. The most amazing is 3-4 years ago when my kids were at <em>very</em> different stages of life. These are the years my mind has found easiest to lose track of and without this journal I would not regularly have the joy of looking back on them at those ages.</p>

<p>Memory is a funny thing. As prideful humans, we think that our memories are indelible, especially events we consider particularly important. A <a href="https://www.psychologytoday.com/us/blog/media-spotlight/201503/remembering-911">study was done in the aftermath of 9/11</a> where people who were in NYC and up close to the event were asked to describe where they were that day, on the one year anniversary, at two years, at five years, and finally at ten years. They were then shown what they wrote at each of those increments. Most whose depictions differed over the years were adamant that they could not have possibly written what’s they wrote at the one year mark, that their memory now was clearer, and that their writings must have been altered (despite agreeing it was, indeed, their handwriting...).</p>

<p>We really do give our brains too much credit. Instead, as we get further removed from an event, our brains fill in gaps with other things people have said, other events we have experienced, or even just crap it made up. When we try to look back on past events, we need to remember that we look through a mirror darkly, not through a magnifying glass.</p>

<p>Unless, that is, you wrote it all down!</p>

<p>In my case, on the morning of 9/11/2002 I wrote down what happened on that day one year prior. I have a journal entry long-ago-exported from <a href="https://www.livejournal.com/">LiveJournal</a> which survived imports into my subsequent MovableType- and then Wordpress-based blog(s) and several years of languishing in a mysql db export. I know pretty well what happened in my life that day because I can read about it and refresh the gaps in my fuzzy memory with my own words.</p>

<p>Forgive the writing style… it was 16 years ago. Names changed for privacy:</p>

<blockquote><p>When Flight 175 barreled into the South Tower, everything stood still. It was the first one I watched happen on CNN. I woke up around 8:55. My friend [Jill] had something in her [AIM] profile about “my heart goes out to all the families..” I got spooked really quick. My energy went, and I turned to the only authoritative news source I could think of, msnbc.com. There I saw pictures of the North Tower, and was impressed that... wow... this happened about 8 minutes ago, and there's an almost full spread on it.</p>

<p>I tuned to CNN as the maintenance dude knocked on my door to fix my rug (it was bunched up in front of my doorway). We both watched CNN as the South Tower was hit. Then it was 9:04, and the panic continued.</p>

<p>It was a long day at work, even though we closed early. Many of the staff watched CNN on the TV that was normally reserved for Printer and Public Site status reports. I kept #news rolling on IRC b/c it was many times more up to date than cnn or msnbc… those sites were smacked pretty bad that day.</p>

<p>I tried calling [Jess in NYC], but the phones were all a mess. Thankfully her building hadn't lost its internet connection, and she was online.. 'scared to death' but still alive.. that's all that mattered to me. It was only a dozen blocks from where she slept.</p>

<p>We kept asking the consultants if they had family in NYC - many do. It took a few days, but everyone's everyone was accounted for. I called [Allie] to make sure her dad was ok, and he had been in Disaster Mode at [redacted place of work] all morning, but he was fine. Everyone I knew was ok, but I'm a lucky one.</p>

<p>God be with us.</p></blockquote>

<p>That day is mostly indelible for me <strong>because I made the effort to make it that way</strong>, and I re-read that post on 9/11 every year because I put it in Day One a few years ago, so now I see it every other! There wasn’t much effort to do this. It was worth it for that memory, and is worth it for the others that I capture as my life has changed since B was born. <strong>A lot</strong> has happened since then, and it is a real blessing to to be able to read about it and feel some of those feelings again.</p>

<h2>What Next</h2>

<p>I do have some regrets that I didn’t start this all sooner. I am down to a single grandparent, for instance, and I have lost a lot of memories from my childhood for not having been a faithful journaler at a younger age. The journals I do have from my adolescence are hilarious, embarrassing, and should be used as fire-starter. My other LiveJournal-era entries are similarly embarrassing for the most part.</p>

<p>That said, there are more things being considered in the app that I am looking forward to:</p>

<ol>
<li>More and more functionality for audio recording. This has been an amazing addition to the tool belt for me. I record a post every now and again while walking the dog. If it’s short enough, Day One transcribes it for me and I can edit it after the fact. It’s hard to type when walking a dog, as you might expect. I’m planning on buying an Apple Watch Series 4 in the new year to replace my aging Series 0. One of the features that works on the newer watches is that you can natively record audio on-device for up to 90 minutes. This will be a game-changer for me. When I’m having a chat with one of my kids that I want to remember or when my wife and I are wrestling with a decision, or when I cannot take notes on something someone is saying, I can revisit it later and also not worry about its privacy due to the end-to-end encryption of my most sensitive journals.</li>
<li>Video support. Most of the videos I take with my phone are there to chronicle a short event. I don’t want them on Youtube or another hosting service, and for now they are “collecting dust” in a Dropbox folder tree. Adding video support in Day One would be supremely helpful. I have converted some very short videos to GIFs to make an entry more “alive”, though, and that’s nifty.</li>
<li>Shared journals. This is one extension for my “The Plan” journal which would open up a lot of potential. My wife, who doesn’t use Day One much, could open the same journal and add her thoughts.</li>
</ol>


<p>Again, Day One is the end game. It’s where all of the stuff I want to keep track of ends up.</p>

<p>I <em>would</em> like to automate more things into Day One, but I’ve reached the limits of my digital life for now. There are numerous inspirations out there for automation, for example:</p>

<ul>
<li><a href="https://thesweetsetup.com/make-journaling-day-one-even-better-automation/">How to make journaling in Day One even better with automation – The Sweet Setup</a></li>
<li><a href="https://thesweetsetup.com/automate-day-one-entries-using-ifttt/">How to automate Day One entries using IFTTT – The Sweet Setup</a></li>
<li><a href="https://dayoneapp.com/templates/">Templates | Day One</a></li>
<li><a href="https://medium.com/day-one/five-ways-to-automate-your-day-one-journal-with-textexpander-226e8a9ad45d">Five Ways to Automate Your Day One Journal with TextExpander</a></li>
</ul>


<h2>Why I Don’t Blog Anymore</h2>

<blockquote><p>And now we come to the payoff…</p></blockquote>

<p>A colleague of mine asked me what my next blog post was going to be about way back in May. I was sure I would write about the treehouse I was going to build, but I never really wanted to share it like that. It was a rushed process that I over-engineered, and I wasn’t sure how to describe it. I sure do have a ton of journal entries about it, though, and that is why I do not post here any more: most of my written thoughts are for later recall and not for public consumption. I don’t have any need to share them, so I just do not.</p>

<p>It’s not healthy, though, to keep everything inside. I firmly believe that the best life is one shared with, and especially in service to, others, however that doesn’t mean I need to blog more. It means that I need to share life with people 1:1 and 1:several. A customer of mine stumbled upon this blog and mentioned to me that he liked what I posted and would enjoy seeing more. I get it; I consume other people’s writing all the time and would it not be fair for some to expect me to share alike?</p>

<p>Despite being an extrovert, this isn’t the medium I want to contribute my thoughts to right now. I could make an empty promise to the ether about aiming to write more, but who am I trying to impress? I am <strong>definitely</strong> going to journal more, but I promise nothing about this place.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Admins of Atlassian Podcast Appearance]]></title>
    <link href="http://www.mattshelton.net/2017/12/19/admins-of-atlassian-podcast-appearance/"/>
    <updated>2017-12-19T20:58:16-05:00</updated>
    <id>http://www.mattshelton.net/2017/12/19/admins-of-atlassian-podcast-appearance</id>
    <content type="html"><![CDATA[<p>Finally.&#8482;</p>

<p>I set a goal a long, long time ago to be on a podcast at some point. I've been an avid consumer of them for over a decade, starting with <a href="https://twit.tv/shows/this-week-in-tech">TWiT</a> and <a href="http://www.dancarlin.com/hardcore-history-series/">Hardcore History</a> on my long train rides between Everett and Wellesley back in 2004. As much fun as I thought it would be, I struggled to figure out how to get started. I could talk about <em>anything</em> but the podcasts I enjoyed the most had hosts who really <em>knew their topic cold</em> and as much as I was willing to talk about something, I never felt I had a handle on any one thing enough to talk about it on a regular basis.</p>

<p>Fast forward a decade... I met Mark Williams at Summit 2015. I had started listening to his "Admins of Atlassian" podcast a few weeks beforehand, and so I took a shot and  asked him if I could collaborate. Mark was kind enough to not say "no" right away, so I figured there was hope... He ended up taking a job at Atlassian shortly after we met, and the podcast went on hiatus for a good long while. After my move over, I reached out to see if I could help restart the podcast, and a well-intentioned as I am, I think Mark likes doing it on his own for the most part. It's his brand and I do not fault him one single bit for this.</p>

<p>But, Mark is an awesome guy and he recognized that there were some topics where having a guest host or two makes for a good show, and so when he asked, I may have been the first person to volunteer. Maybe.</p>

<p>I can neither confirm nor deny.</p>

<p>Turns out, I really <em>did</em> love the experience, and I really <em>don't</em> hate the way my voice sounds.</p>

<p>Take a listen below, or check the episode out <a href="http://adminsofatlassian.com/e13-upgrade-best-practices/">here</a> if you're interested, wherein Mark chats with Jennifer Van Leeuwen and me about our best practice thoughts around upgrading Atlassian tools.</p>

<iframe src="//player.blubrry.com/?media_url=http%3A%2F%2Fmedia.blubrry.com%2Fadminsofatlassian%2Fp%2Fcontent.blubrry.com%2Fadminsofatlassian%2FAOA-E13-Upgrade-Best-Practices-FINAL_mixdown_Chapters.mp3" scrolling="no" width="100%" height="138px" frameborder="0"></iframe>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Enter Sandman on Classroom Instruments]]></title>
    <link href="http://www.mattshelton.net/2016/11/18/enter-sandman-on-classroom-instruments/"/>
    <updated>2016-11-18T09:16:40-05:00</updated>
    <id>http://www.mattshelton.net/2016/11/18/enter-sandman-on-classroom-instruments</id>
    <content type="html"><![CDATA[<p>This is so great... and I was wondering the best way to get my kids into Metallica...</p>

<div class="video-container"><iframe src="https://www.youtube.com/embed/GXJifYl_byU "></iframe></div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Publishing This Blog With Bitbucket Pipelines]]></title>
    <link href="http://www.mattshelton.net/2016/11/10/publishing-this-blog-with-bitbucket-pipelines/"/>
    <updated>2016-11-10T13:15:00-05:00</updated>
    <id>http://www.mattshelton.net/2016/11/10/publishing-this-blog-with-bitbucket-pipelines</id>
    <content type="html"><![CDATA[<p>Earlier this year, Atlassian released <a href="https://bitbucket.org/product/features/pipelines">Bitbucket Pipelines</a>, it's Cloud CI offering, as a beta product coupled with their hosted Git/Hg source control service. I like to know as much as possible about my products, but I'm not much of a software developer<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>, so finding a use case to try out Pipelines was puzzling.</p>

<p>Then I remembered that I build this very blog. (Oops) It's not much of a job to run an octopres/jekyll build, but my current setup was highly-dependent on a single machine at my house always being on with Dropbox working. It was a little <em>too</em> fragile. I host this blog on <a href="https://www.nearlyfreespeech.net">nearlyfreespeech.net</a>, and though I know there are other hosting options out there that might do the whole build and deploy process natively for me<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>, I (also) try to never shy away from a challenge.</p>

<p>At <a href="https://www.atlassian.com/company/events/summit/2016">Summit last month</a>, Atlassian released Pipelines as GA, and set an intro price of FREE for the remainder of the year.<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup> I was out of excuses, so in my spare minutes over the past month I have tried to get a simple jekyll build of the site to work in pipelines.</p>

<p>And, of course, ran into one problem after another.</p>

<p>First, pipelines runs its build in a Docker container. This isn't a negative, actually, but it added a complexity with which I had relatively little experience.. I figured the simplest way to get started was to use an existing ruby image that was the same version on my Mac and just install dependencies as part of the build. Jekyll, though, requires a JavaScript compiler and no matter what I tried to do in the build to install <s>one</s>all of them, the best option was to get node working since that's how my current build works. At that point, though, my build script was tens of steps each run, meaning my build-minute use was going to be super high each time I wanted to publish something.</p>

<p>Rather than <a href="https://answers.atlassian.com/questions/39140980/how-do-i-create-a-docker-image-for-bitbucket-pipelines">build my own Dockerfile</a>, which was really tempting, I deciced to use another image in the <a href="https://hub.docker.com">Docker Hub</a> that has <a href="https://hub.docker.com/r/starefossen/ruby-node/">both ruby and node already set up</a>. It's not far from what I was about to do myself, so no use re-inventing...</p>

<p>...which was good, because second, I really didn't want to have to install Docker. Every time I have previously tried to install Docker and have it work reliably, the VirtualBox piece just dies on me at some point. (More on this in a moment, though, because I'm rarely this lucky.)</p>

<p>My blog is already a private bitbucket repository. I was able to skip a few parts of the setup and just enable Pipelines on my existing repo, though I chose to create a branch for this work which I merged in once I was happy with the results. I also wanted my repo to be as simple as possible, so I spent some time adding items to my .gitignore and expanding the rake task for cleanup to remove the generated site.</p>

<blockquote><p>An aside: Now that I work for Atlassian, I have a parallel set of accounts to the ones I had before as a customer. This means I have two bitbucket accounts, and as a result my normal method of keeping my bitbucket ssh key in my local keyring failed to choose the right key when working with my blog repo locally. Enter [git aliasing](https://developer.atlassian.com/blog/2016/04/different-ssh-keys-multiple-bitbucket-accounts/), which is super handy.</p></blockquote>


<p>That fixed, I looked at how my current site generation task is run<sup id="fnref:4"><a href="#fn:4" rel="footnote">4</a></sup> and tried to replicate that via the bitbucket-pipelines.yml:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>image: starefossen/ruby-node:latest
</span><span class='line'>
</span><span class='line'>pipelines:
</span><span class='line'>  default:
</span><span class='line'>    - step:
</span><span class='line'>        script:
</span><span class='line'>          - bundle install
</span><span class='line'>          - rake generate
</span><span class='line'>          - rake deploy</span></code></pre></td></tr></table></div></figure>


<p>After that, I knew I'd need to get <a href="https://confluence.atlassian.com/bitbucket/access-remote-hosts-via-ssh-847452940.html">key-based SSH</a> set up to actually deploy the content:<sup id="fnref:5"><a href="#fn:5" rel="footnote">5</a></sup></p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>image: starefossen/ruby-node:latest
</span><span class='line'>
</span><span class='line'>pipelines:
</span><span class='line'>  default:
</span><span class='line'>    - step:
</span><span class='line'>        script:
</span><span class='line'>          - mkdir -p ~/.ssh
</span><span class='line'>          - cat my_known_hosts >> ~/.ssh/known_hosts
</span><span class='line'>          - (umask 077 ; echo $SSH_KEY_VAR | base64 --decode > ~/.ssh/id_rsa)
</span><span class='line'>          - bundle install
</span><span class='line'>          - rake generate
</span><span class='line'>          - rake deploy</span></code></pre></td></tr></table></div></figure>


<p>And while I expected that to work, I quickly found out that rsync wasn't part of the ruby-node docker image:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>image: starefossen/ruby-node:latest
</span><span class='line'>
</span><span class='line'>pipelines:
</span><span class='line'>  default:
</span><span class='line'>    - step:
</span><span class='line'>        script:
</span><span class='line'>          - apt-get update
</span><span class='line'>          - apt-get install -y rsync
</span><span class='line'>          - mkdir -p ~/.ssh
</span><span class='line'>          - cat my_known_hosts >> ~/.ssh/known_hosts
</span><span class='line'>          - (umask 077 ; echo $SSH_KEY_VAR | base64 --decode > ~/.ssh/id_rsa)
</span><span class='line'>          - bundle install
</span><span class='line'>          - rake generate
</span><span class='line'>          - rake deploy</span></code></pre></td></tr></table></div></figure>


<p>This worked, nearly flawlessly, with one <strong>major</strong> problem: the results of <code>rake generate</code> did not match what I had at home, and for a little while I had a very ugly, completely empty, web site. (Oops)</p>

<p>After a respite and far too many (frustrating) re-runs, I decided I had no choice but to bite the bullet and get Docker installed locally. In the last 8-ish months, though, Docker has fixed the problem that had been bugging me for ever and ever, and <a href="https://docs.docker.com/docker-for-mac/">removed the need</a> to have a separate VM application running on the machine. Replicating my pipeline environment was therefore trivial<sup id="fnref:6"><a href="#fn:6" rel="footnote">6</a></sup> and I ran through the build steps without any issues.</p>

<p>Which was infuriating, because it worked perfectly fine.</p>

<p>So, you know, it has to be the environment.</p>

<p>Turns out I was over-zealous in my cleanup efforts and had removed the <code>Gemfile.lock</code> from the repo, meaning that it was grabbing all of the latest dependency versions from rubygems. Somewhere in there was an update that broke generation altogether. The lock file was still there locally (because I had run bundle install outside of Docker at some point in the troubleshooting process), so once it was pushed back to the remote, the pipeline build completed flawlessly. And deployed. And I was happy.</p>

<p>Each time my site builds, I will be consuming about 2.5 build-minutes. I can publish 20ish posts per month (HA!) for free for the foreseeable future.</p>

<p>This was a great learning experience. Prior to this a majority of my CI experience had been using Bamboo to kick off <code>mvn</code> commands. I'd highly recommend using pipelines for simple build tasks, even if it's for things like unit tests, content generation, publishing to a remote, whatever.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>My weak-arse perl skills don&rsquo;t count, nor do I write unit tests for my hack-jobs, alleviating me of any sort of CI benefits&hellip;<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>I had been using the free aerobatic.io hosting in bitbucket for a bit, and I could move to Github and hsot there with a CNAME, but I&rsquo;m happy with my setup.<a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
<li id="fn:3">
<p><a href="https://bitbucket.org/product/pricing/upcoming?tab=host-in-the-cloud">Starting in January</a> the cost goes up to whopping $0 for 50 build-minutes, $10/mo for 1000 if for some reason I need that much.<a href="#fnref:3" rev="footnote">&#8617;</a></p></li>
<li id="fn:4">
<p>Via hazel, as a simple shell script.<a href="#fnref:4" rev="footnote">&#8617;</a></p></li>
<li id="fn:5">
<p>I apprecate that Atlassian made it trivial to store a local key securely via a protected environment variable.<a href="#fnref:5" rev="footnote">&#8617;</a></p></li>
<li id="fn:6">
<p>No, seriously. Maybe 5 minutes, while the kids ran around screaming and hitting each other with light sabers.<a href="#fnref:6" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Cubs Win! Cubs Win! Holy Cow!]]></title>
    <link href="http://www.mattshelton.net/2016/11/03/cubs-win-cubs-win-holy-cow/"/>
    <updated>2016-11-03T00:54:42-04:00</updated>
    <id>http://www.mattshelton.net/2016/11/03/cubs-win-cubs-win-holy-cow</id>
    <content type="html"><![CDATA[<div class="video-container"><iframe src="https://www.youtube.com/embed/b8Of8YEjtaQ "></iframe></div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Wintergatan]]></title>
    <link href="http://www.mattshelton.net/2016/09/04/wintergatan/"/>
    <updated>2016-09-04T21:51:57-04:00</updated>
    <id>http://www.mattshelton.net/2016/09/04/wintergatan</id>
    <content type="html"><![CDATA[<div class="video-container"><iframe src="https://www.youtube.com/embed/IvUU8joBb1Q "></iframe></div>


<p>Breathtakingly awesome. The videos explaining how it works (<a href="https://www.youtube.com/watch?v=uog48viZUbM">Part 1</a> and <a href="https://www.youtube.com/watch?v=p0Guq7vZb_E">Part 2</a>) are fascinating. He plays the song on the keyboard at the end of part 2 to explain how he modifies a repeated set of melodies. It's almost as good on just a piano.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Leaving on a Rocket Ship]]></title>
    <link href="http://www.mattshelton.net/2016/08/27/leaving-on-a-rocket-ship/"/>
    <updated>2016-08-27T17:06:46-04:00</updated>
    <id>http://www.mattshelton.net/2016/08/27/leaving-on-a-rocket-ship</id>
    <content type="html"><![CDATA[<p>In mid-2005, I was working as the Residential Network Support Manager for <a href="http://www.wellesley.edu">Wellesley College</a>. It was my job to coordinate all of the technical support for the 2,000+ students, train two dozen students with almost no tech support background to do field and email support, and plan out the welcome program for getting new students acclimated to their network and software and such. Though I had been relatively successful there, I really didn't enjoy my job. There was a vast cultural difference between myself and the other staff, and despite my best efforts to push for material changes, they were met with an attitude of "that's not the way we do things", which was prevalent in EdTech, especially at smaller schools.</p>

<p>So I started job-hunting, and through a roller-coaster of life events, finally took a job doing application support for a small-ish healthcare tech startup called <a href="http://www.escription.com">eScription</a>. They made a suite of tools for Computer Aided Medical Transcription using a mixture of proprietary and open-source speech recognition tools and home-grown applications. The solution was sold as a SaaS platform with some on-premise workflow tools and a user-facing client embedded in Microsoft Word, and the entire stack was supported by a (then) 7-person team. We had about four dozen customers at the time, mostly individual hospitals around the country. The job gave me all sorts of opportunities to flex my unix muscles, and I grew with the organization, eventually managing one of the support teams.</p>

<p>About two years later, I moved out of Support and into R&amp;D, owning one of those workflow products. Shortly after that, eScription was acquired by <a href="http://www.nuance.com/">Nuance</a>, and we were quickly assimilated into the vast acquisitive machine, joining <a href="https://en.wikipedia.org/wiki/Dictaphone">Dictaphone</a> and <a href="http://www.nuance.com/support/radwhere/">Commissure</a> among the Healthcare division's more recent acquisitions. eScription was the go-forward platform for background-speech transcription<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>, and though we bled original staff members like a stuck pig, we generally flourished.</p>

<p>In late 2010, my team was spun off of eScription along with some other staff in the division to start a <a href="https://en.wikipedia.org/wiki/Skunkworks_project">skunkworks project</a> to deliver our first NLP solution to the healthcare market. Though we stumbled a bit those first couple of years an had a failed partnership or two, we learned from our mistakes and put some narrowly-focused products in the market. After a couple of additional acquisitions in 2014, we developed more of a footing in the industry, and now deliver the top-ranked <a href="http://www.nuance.com/for-healthcare/clintegrity360/clinical-document-improvement/cdi/index.htm">Clinical Documentation Improvement</a> platform in the industry, along with the under-pinnings for <a href="http://www.nuance.com/products/powerscribe360/index.htm">intelligent Radiology assistance</a>, <a href="https://www.nuancehealthcaredeveloper.com/?q=clinical-language-understanding-sdk">structured documentation generation</a> from narrative medical text, and <a href="http://www.nuance.com/for-healthcare/clintegrity360/computer-assisted-coding/index.htm">Computer Assisted Coding</a> for medical billing. It's a platform I am proud to have helped build from the ground, up.</p>

<p>...and now I'm done. Though it has been a <em>great</em> ride, my days at Nuance have come to an end. I am going to miss my team so very much, but after just shy of 11 years, I am ready for my next adventure: In mid-September, I am going to be joining <a href="https://www.atlassian.com">Atlassian</a> as a <a href="https://www.atlassian.com/enterprise/services/tam">Technical Account Manager</a> working remotely with East Coast enterprise customers. Over the last three years, I've become intimately familiar with their tools and services, and have gotten to know many of their staff. Atlassian looks like <a href="http://fortune.com/best-medium-workplaces/atlassian-2/">a great place to work</a>, and I am looking forward to finding out for myself in just a few short weeks.</p>

<p>When the TAM program was introduced<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>, I pushed to have Nuance purchase this service as we were growing our footprint of users from a few dozen to a few hundred (which then turned in to a couple thousand). It was one of the best decisions we made. Our TAM has been instrumental in supporting our division's adoption of every tool that Atlassian makes, from JIRA to Bamboo, and ensuring we follow best practices along the way. I'm such an unabashed fan that I'm quoted on the TAM web site (scroll to the bottom):</p>

<blockquote><p>Our TAM gave us product advice that was able to save a department of 300 people roughly four hours a night.
—Matt Shelton, Engineering Manager, Nuance Communications</p></blockquote>

<p>Admittedly I'm just as much of a fan of the <a href="https://www.atlassian.com/enterprise/services/premier-support">Premier Support</a> team -- these two services are worth every penny for an enterprise customer.<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup></p>

<p>This is going to be a very different job from the <s>one</s>many that I do now. For starters, I haven't been an individual contributor since 2006! Having only my own work products to focus on will be a change. Not working directly for an R&amp;D group will also be a big shift, but I haven't been able to do much that is customer-facing in a while, and I am excited to get out there again. I'm going to be adding some DevOps experience and CI/CD exposure to the team, and given Atlassian's trajectory there is so much room to grow. I can barely wait.</p>

<p>Here's to the getting on the rocket ship!</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>If ever there were to be a niche&hellip;<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>Late 2013/Early 2014, if memory serves.<a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
<li id="fn:3">
<p>This wasn&rsquo;t <em>supposed</em> to be an ad read.<a href="#fnref:3" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Maven Extension for Feature Branch Isolation]]></title>
    <link href="http://www.mattshelton.net/2016/07/29/maven-extension-for-feature-branch-isolation/"/>
    <updated>2016-07-29T12:00:00-04:00</updated>
    <id>http://www.mattshelton.net/2016/07/29/maven-extension-for-feature-branch-isolation</id>
    <content type="html"><![CDATA[<p>Last year I had the privilege of speaking at the <a href="https://summit.atlassian.com/videos/build/git-branching-models">Atlassian Summit</a> on the topic of <a href="http://www.mattshelton.net/2015/10/30/git-or-svn-how-nuance-healthcare-chose-a-git-branching-model/">selecting a branching model when migrating a team to Git</a>. I had a blast, but I also came away with a small amount of regret: During the presentation, I mentioned that my team had used a custom maven extension to automate the process of isolating our build artifacts in Artifactory. We had been, and at the time still were, working with our legal department to obtain clearance to publish the extension as an open source project.</p>

<p>That process, unfortunately, took <em>a lot</em> longer than I had expected. Thankfully, the wait is over. I am incredibly pleased to finally release our <a href="https://bitbucket.org/mattshelton/maven-branch-extension/">Maven Feature Branch Extension</a> to the general public. The extension is published under the Apache Software License, using the same version as Maven 3.x. Take it, use it, fork it, etc. We'll <a href="https://bitbucket.org/mattshelton/maven-branch-extension/issues">track issues</a> in our bitbucket project and try to get to them as quickly as we can. We'll also happily accept pull requests.</p>

<p>I am deeply embarrassed that there is a very real possibility that someone's work might have been stalled waiting on me for nine months. I have tried to reach out to everyone that asked for this extension at Summit, posted comments on this blog, and emailed me directly. I may have missed some and if you fall into that category, please accept my most sincere apologies. I'll be at <a href="http://summit.atlassian.com">Summit</a> this year; I'd be happy to buy you a beer.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Open Feedback]]></title>
    <link href="http://www.mattshelton.net/2016/03/15/open-feedback/"/>
    <updated>2016-03-15T20:40:36-04:00</updated>
    <id>http://www.mattshelton.net/2016/03/15/open-feedback</id>
    <content type="html"><![CDATA[<p>A few weeks ago, <a href="http://becky.coffee">Becky Hansmeyer</a> wrote <a href="http://beckyhansmeyer.com/2016/02/17/slack-is-making-my-twitter-sad/">a post</a> about how some of her "favorite people on Twitter seem to be…well, avoiding Twitter…and how that made [me] kinda sad". I wholeheartedly agreed with her original post and was both fascinated and excited (for her, this person I don't know personally) to hear this post be the topic of discussion on <a href="https://www.relay.fm/analogue/75">this past week's Analog(ue)</a>.</p>

<p>I've been ruminating on the concepts that Becky, Mike, and Casey all touched on for a few days. I wanted to share it with them, but I thought... is it my place to do so? I enjoy reading what Becky writes about app development<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>, and enjoy listening to Mike and Casey talk about their lives. Does that give me any sort of right to tell them what I think about what they wrote/said? I know the latter pair receive a fair amount of feedback. I've sent Casey some regarding his other podcast (ATP), but why was it ok for me to do that?</p>

<p>We live in both a highly-connected, and highly-insular world. The capability of our words to impact people we don't even know is more a reality now than ever before. There can be many positives to this, though it also leads to a logical fallacy: because we <em>can</em> say it, and we live in a place where "Congress shall make no law abridging" us from having our <em>God-given</em> right to an opinion, we therefore believe that we have the <em>right</em> to broadcast any opinion, no matter how completely uninformed, disrespectful, unkind, etc. We think that our opinion about a topic we just got all rage-y on today is as valid to be consumed by the masses as the critic, lawmaker, and victim who have first-hand experience with that issue and may have for <em>far</em> longer than we could imagine. Our perceived right broadcast our indignance leads to a world full of angry people, many of whom don't have a clue from where their rage truly originates.</p>

<p>And the culture uses this to its benefit all the while creating victims of groupthink rage. The mob mentality takes over before anyone can reasonably ask themselves "is it right for me to be angry?"<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup> .</p>

<p>Sometimes it <em>is</em> right. Most of the time, though, we're spectators in a globally-viewable personal conversation, weighing in on someone else's business or throwing trash on their lawn.</p>

<p>(And some of the time it's just the election season.)</p>

<p>Becky wrote a <a href="http://beckyhansmeyer.com/2016/03/07/follow-up-the-nuances-of-online-discussion/">follow-up post</a> and hit the content I wanted to touch on squarely on the head. It made me feel like it was 2004 all over again, where conversations between personal content creators (<em><em>cough</em></em> bloggers <em><em>cough</em></em>) was managed through trackback links and comment threads, pingomatic and technorati. Content was harder to find, and it was harder to randomly stumble into rage -- you either had to explicitly leave a comment with your email address attached, or wrote your own darn blog post to respond to someone else's ideas.</p>

<p>Now all you have to do is fire off a potentially-anonymous tweet, and that's why I don't blame folks who want to take their content into walled gardens instead of the public square.</p>

<p>But what about me and my thoughts? Should anyone listen to what I have to say in response to their opinions which they shared publicly? Nope. I mean... they can if they want, but something has changed in our culture that we expect they should, and so we send unfiltered responses without questioning if it's our place to do so.</p>

<p>And if I'm completely honest, some part of me wants to anyway despite knowing all of this. I want to be able to send criticism and be told I'm right because on one level I'm self-centered and consider myself important.</p>

<p>Instead I'm going to throw back to 2004 and be perfectly content with what I have here.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>And, let&rsquo;s be honest: her dog is adorable. More corgis! Corgis for everyone!<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>Jonah 4:9<a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Frederick Douglass Daguerreotype]]></title>
    <link href="http://www.mattshelton.net/2016/01/07/frederick-douglass-daguerreotype/"/>
    <updated>2016-01-07T11:45:49-05:00</updated>
    <id>http://www.mattshelton.net/2016/01/07/frederick-douglass-daguerreotype</id>
    <content type="html"><![CDATA[<p>My father-in-law sent us a video about one of his long-ongoing research projects, the study of an early <a href="https://en.wikipedia.org/wiki/Daguerreotype">Daguerreotype</a> of <a href="https://en.wikipedia.org/wiki/Frederick_Douglass">Frederick Douglass</a>.<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> For a nerd with any sort of science leaning, this is a pretty interesting topic. Every time we visit my wife's home, he has some new story about this project with twists, turns, "plot thickens" moments, etc. It's great to see the attention start to ramp up a bit!</p>

<div class="video-container"><iframe src="https://www.youtube.com/embed/k33G-67FlwI "></iframe></div>


<p>I'm really quite proud to be related to this guy. He does some pretty cool work in the nano scale up at the UofR.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>In the video, he&rsquo;s the guy doing all of the work on the microscope, pointing out findings, etc.<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Creative Branching Models for Multiple Release Streams]]></title>
    <link href="http://www.mattshelton.net/2015/11/17/creative-branching-models-for-multiple-release-streams/"/>
    <updated>2015-11-17T17:34:53-05:00</updated>
    <id>http://www.mattshelton.net/2015/11/17/creative-branching-models-for-multiple-release-streams</id>
    <content type="html"><![CDATA[<p>A couple of weeks ago, I had the incredible opportunity to speak at the 2015 <a href="https://summit.atlassian.com">Atlassian Summit</a> in San Francisco, CA. The conference lasts about three days and covers a wide range of topics from Software Engineering to Process Improvement to Team Dynamics to Enhancing Communication and so on. Most of the sessions are focused on using Atlassian's tools to accomplish a given goal, but many are generally applicable to anyone in a Software Engineering field.</p>

<p>My presentation covered my team's migration from Subversion to Git with a long time spent talking about the work we needed to do to keep our multi-module build setup in Maven whilst using git-flow as a branching model and making our engineers do as few manual steps as possible. I was limited to about 30 minutes, so I wrote a brief series of posts to cover everything I couldn't say on stage:</p>

<ol>
<li><a href="http://www.mattshelton.net/2015/10/30/git-or-svn-how-nuance-healthcare-chose-a-git-branching-model/">Git or SVN? How Nuance Healthcare chose a Git branching model</a>)</li>
<li><a href="http://www.mattshelton.net/2015/10/31/dealing-with-maven-dependencies-when-switching-to-git/">Dealing with Maven dependencies when switching to Git</a></li>
<li><a href="http://www.mattshelton.net/2015/11/01/pulling-the-trigger-migrating-from-svn-to-git/">Pulling the Trigger: Migrating from SVN to Git</a></li>
</ol>


<h2>Video</h2>

<div class="video-container"><iframe src="https://www.youtube.com/embed/bCU_D7EHqLg "></iframe></div>


<h2>Slides</h2>

<iframe src="https://www.slideshare.net/slideshow/embed_code/key/qTYt7fiY2hNuVS " width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px;max-width: 100%;" allowfullscreen></iframe>


<p></p>

<p>This was my first time presenting at a technical conference. It was a great experience that I hope to repeat in the future.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Pulling the Trigger: Migrating from SVN to Git]]></title>
    <link href="http://www.mattshelton.net/2015/11/01/pulling-the-trigger-migrating-from-svn-to-git/"/>
    <updated>2015-11-01T00:09:23-04:00</updated>
    <id>http://www.mattshelton.net/2015/11/01/pulling-the-trigger-migrating-from-svn-to-git</id>
    <content type="html"><![CDATA[<blockquote><p><strong>Note:</strong> The official version of this post can be found at <a href="https://www.atlassian.com/git/articles/migrating-svn-git-branching-workflow">https://www.atlassian.com/git/articles/migrating-svn-git-branching-workflow</a>.</p></blockquote>

<p>We're <a href="http://www.mattshelton.net/2015/10/30/git-or-svn-how-nuance-healthcare-chose-a-git-branching-model/">moving to Git</a>, and we <a href="http://www.mattshelton.net/2015/10/31/dealing-with-maven-dependencies-when-switching-to-git/">figured out how to use git-flow and Maven together</a> in an efficient devleopment workflow. Before I get into what our workflow looks like now, it's important to know where we came from.</p>

<h2>Back In the Olden Days...</h2>

<p>In the our previous world, before migrating from SVN to Git, all of our version management was manual. Development took place on trunk simultaneously across all active features for the team. When a developer committed their changes to SVN, Bamboo would kick off a snapshot build (<code>1.0.0-SNAPSHOT</code>). If their work passed integration testing, they'd run the release plan after manually verifying nobody else had run a subsequent snapshot<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>. That release build (<code>1.0.0-1</code>)<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup> would be quickly smoke tested and then handed to QA for functional validation.</p>

<p>We were "releasing" all the time; every build that went to QA was from a Maven release goal without incrementing the minor or patch number. We had <a href="https://www.atlassian.com/software/bamboo/">Bamboo</a> tack on that <code>-buildnumber</code> to each release so that we could track specific releases to QA,.</p>

<p>Then, once QA blessed the "last one" for that release, we'd increment the minor version using <code>mvn version:set</code>. This meant that if yours truly wasn't completely on top of his game, we ran the risk of forgetting to increase that version number and building a "release" of <code>1.0.0-x</code> that was after what we had released to production. Big mess. Big pain. But it meant that every build out of development had a clear, trackable, permanent number.</p>

<p>That was "good", but it was a tracking nightmare.</p>

<p>We didn't want to do that anymore. We only wanted to release when something was going to go out the door, customer-ready. Also, no more build numbers in production&#8212;major.minor.patch only.</p>

<p>However, we also wanted to ensure QA had a way to track a specific delivery to a specific release. QA couldn't be testing SNAPSHOT releases all the time. Thankfully, JIRA Software makes some of this easy by showing links between JIRA issues, Bitbucket repositories and build plans containing builds for that issue.</p>

<p>In the end, we decided that we would adhere to a few rules:</p>

<ol>
<li>Developers perform integration testing from their <code>feature</code> branch, which they are keeping up to date with the <code>develop</code> branch.</li>
<li>Once integration testing is complete and passing, they issue a pull-request and have their code pulled into the <code>develop</code> branch.</li>
<li>They promote a QA candidate cut of our common project, and then trigger a QA candidate cut of <code>develop</code> for their product project. Since we need to use a specific common project release at build time<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup>, we prompt a developer for the aforementioned common QA candidate release version.</li>
<li>QA tests QA candidate builds only. Never snapshots.</li>
</ol>


<p>We repeat steps 1-5 for all features, bugs found in QA, etc. Then, once we're all done with a version's efforts, we follow git-flow and branch to a release branch by promoting a specific QA candidate build in Bamboo. This creates our first release candidate set, and QA performs final testing, regression testing, etc.</p>

<h2>Building It Right</h2>

<p>Getting your builds <em>just right</em> can be tricky. Before we moved everybody off of SVN and our original Bamboo build plans, we set up a POC project and then worked out all of our Bamboo plans using those. In the end, we found the following plans met our needs:</p>

<ol>
<li><strong>develop</strong>: Triggered from <a href="https://bitbucket.org/product/server">Bitbucket Server</a>, it creates SNAPSHOT builds with every change pulled in from pull requests. The build plan has three stages:

<ol>
<li>Snapshot - Builds snapshots and doesn't touch versions.</li>
<li>QA Build - Builds a "QA Candidate" release numbered <code>X.Y.Z-qa{buildnunber}</code> from the same git commit used to create that snapshot.</li>
<li>Promote To Release - Creates the release branch and increments develop's minor version number, all from the same git commit used to create the QA build.</li>
</ol>
</li>
<li><strong>feature</strong>: Set up with a default build plan, but mostly is watching for new branches created with <code>feature/*</code> in the name, using <a href="https://confluence.atlassian.com/bamboo/using-plan-branches-289276872.html">Bamboo's plan branches feature</a>, and creates a branch plan for that branch whenever it does. It has only one stage, which builds SNAPSHOTs.<sup id="fnref:4"><a href="#fn:4" rel="footnote">4</a></sup> Also, because we don't want feature to build by itself, we point its repository to a branch called "fake-branch" so that it never triggers.</li>
<li><strong>release and hotfix</strong>: These have the same set of build and release steps so they get to share a plan. The plan also points to a "fake-branch" and only cuts branch plan-based releases with the following two stages:

<ol>
<li>Build Candidate Release - This creates a release numbered <code>X.Y.Z-rc{buildnumber}</code>.</li>
<li>Finalize Release - This sets the final release number, merges up to master, and creates a tag. Then it removes the release branch which disables the plan.</li>
</ol>
</li>
<li><strong>support</strong>: This is nearly identical to release and hotfix, but it never merges to master. Instead, we increament the minor version at the end of the Finalize Release stage.</li>
</ol>


<p>Because feature, release_hotfix, and support plans are all running branch plans, when you view them in Bamboo, you see “Never built” for each plan. The first time this happened everyone had a blank look on their face... <em>where are my builds??</em> but then we realized this made sense.</p>

<p>We have so many build plans<sup id="fnref:5"><a href="#fn:5" rel="footnote">5</a></sup> that if bamboo displayed all of the plans inline including branch plans, you'd be scrolling forever and a day. The information overload would actually be <em>less</em> helpful. So we click once more to see our branch plan status. It's not a big deal, but it would be nice to find an easy way to see them all.<sup id="fnref:6"><a href="#fn:6" rel="footnote">6</a></sup></p>

<h2>Migration Process</h2>

<p>Once we were satisfied that the POC project worked the way we wanted it to, and the developer workflow was consistent and reliable, we ran an import of our SVN codebase into Git and ran through several more iterations of testing each possible workflow to iron out build issues, workflow oddities, etc.</p>

<p>We found some things like my note above about cleaning the Maven workspace every time you run a <a href="https://www.atlassian.com/continuous-delivery/building-feature-branches-with-bamboo">feature branch build in Bamboo</a>, and certain times we needed various flags for a specific maven lifecycle. Generally, these were easy to figure out, but once in awhile there was much shaking of fists and gnashing of teeth.<sup id="fnref:7"><a href="#fn:7" rel="footnote">7</a></sup></p>

<p>After all of that, we decided it was actually now or never, and announced our migration date. As a part of the migration, we decide to do a bunch of cleanup so that our Git repo had a nice starting place. We did things like:</p>

<ul>
<li>Bulk code re-formatting so that we could enable some stricter style checks as a part of the build process</li>
<li>Converted all line endings to UNIX</li>
<li>Squashed three top-level dependency projects into one and refactored all dependent code as a result</li>
</ul>


<p>These things out of the way, we kicked everybody out of SVN, made it read-only and did a final pull into Git. We conducted a training session with all of our developers to go through our workflow one more time and show it in action with the actual codebase.</p>

<p>It was the smoothest migration I've ever experienced. We froze SVN around 5pm on a Monday and by 10pm we were done with all of our initial build issues worked out. There were no major issues; some things required a lot of waiting. Training was the next morning and we were doing feature work by lunch.</p>

<h2>New Developer Flow</h2>

<p>Once through the migration, we were able to see how this workflow would work in the real world. When a developer starts work on a feature (ABC-4321), they need to do a few things to get started:</p>

<ol>
<li>From JIRA Software, in the Development area of the issue, click on <em>Create Branch</em>.</li>
<li>This opens a screen within Bitbucket Server that lets them select the branch type (usually <code>feature</code>), repository, and branch name. Because of our Maven extension I mentioned in the previous post, the branch name is always the JIRA issue key, no description.</li>
<li>Repeat steps 1-2 for each of the associated projects for that feature, always using the single, same issue key.</li>
<li><code>git pull &amp;&amp; git checkout origin/feature/ABC-4321 feature/ABC-4321</code><sup id="fnref:8"><a href="#fn:8" rel="footnote">8</a></sup></li>
</ol>


<p>This workflow is straightforward, repeatable and reliable. Developers can work in isolation and pull in contributed changes from develop as they move forward. The branching action can feel a bit repetitive if, say, a user story has work in all four of our product verticals and the common project. We've been thinking about automating this with some sort of JIRA workflow post-function to call the Bitbucket Server REST API, but that might be overkill for something that isn't costing us too much developer time.</p>

<h2>Lessons Learned</h2>

<p>This process to get us from SVN to git with a shiny new workflow was a long one &#8212; from kickoff to migration we took almost seven months. A vast majority of that time was spent wrestling with maven.</p>

<p>I'll admit that we had some staffing concerns along the way; in parallel to this work the same group of engineers working on the mgiration were supporting a department of 800 people on the Atlassian toolset, providing production support for our platform applications, and working on other operational R&amp;D projects. Once we finally put three people on the migration nearly full-time, we were done in about a month.</p>

<p>Despite all of it, we learned a lot:</p>

<ol>
<li>No amount of preparation truly prepares you for the real thing. For instance, each release build type we tried to perform failed the first time we tried for one reason or another. Once we fixed one project's build for that type, we copied the config to the others and haven't had a single repeat.</li>
<li>This workflow generates a <em>lot</em> of builds. So. Many. Builds. We needed to double our Bamboo agents to keep up.</li>
<li>This workflow generates a <em>lot</em> of build artifacts. Within the first week we ran out of disk space on our Artifactory instance and had to spend a solid day manually purging old release candidates and QA builds no longer needed. Then we needed to think of a way to ensure that when feature branches are removed, we also remove all of their branch-specific snapshot artifacts.</li>
<li>The team doesn't really like needing to pick between a hotfix or having a support branch. It makes sense to <em>be able</em> to cut a hotfix, but most of the time they want a support branch. We might decide to only use hotfixes on special occaisions when the merge would truly be straightforward.</li>
<li>The combination of <a href="https://www.atlassian.com/continuous-delivery">JIRA Software, Bitbucket Server and Bamboo</a> are seriously killer. Watching someone start work in JIRA Software, create a branch and immediately have a branch plan built and ready to validate their work is beautiful.</li>
<li>Pull Requests in Bitbucket Server are the greatest thing since sliced bread. Between keeping a push-happy engineer at bay or making sure we're ready for an offshore team's contributions, we couldn't be happier with the pull-request process. Given we perform code inspection in <a href="https://www.atlassian.com/software/crucible/overview">Crucible</a> rather than at pull-request, we're able to use it for quick sanity checks as well.</li>
<li>Our previous SVN-based tags had been tagged by a service account that was performing the build. Since that user <em>wasn't real</em>, when we tried to create branches from tags, our git-hook to validate the user was valid for a given commit failed. I wrote an article on my personal blog on <a href="http://www.mattshelton.net/2015/08/12/changing-the-author-of-a-single-tag-in-git/">how to change the author of a single commit in Git</a>, which came in handy the first time we needed to create a support branch from an old SVN-based tag... which was the day after the migration!</li>
</ol>


<p>All in all, our migration was a great success. It didn't solve every problem my team has had, but it certainly solved many and gave us a more stable footing to move forward.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>An uncomfortable amount of HipChat conversations in our Developers room went to asking if anyone needed to commit any changes before a release build was made. Prior to HipChat: Lync, email, or yelling over a cube wall.<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>The <code>-1</code> is an incrementing build number for the plan that never resets to 1. It didn&rsquo;t take too long for release builds to have numbers in the high 100s.<a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
<li id="fn:3">
<p>The POM still refers to a <code>-SNAPSHOT</code> release of common here and can&rsquo;t risk the build pulling the wrong SNAPSHOT.<a href="#fnref:3" rev="footnote">&#8617;</a></p></li>
<li id="fn:4">
<p>It also forcibly cleans up the workspace every time it builds. YMMV, but we found this to be necessary.<a href="#fnref:4" rev="footnote">&#8617;</a></p></li>
<li id="fn:5">
<p>Across the org we have something like 120 plans in this particular Bamboo instance, growing all the time. Filtered just to my team&rsquo;s plans, we&rsquo;re roughly half of that list. With all of our branches we&rsquo;re pushing 200.<a href="#fnref:5" rev="footnote">&#8617;</a></p></li>
<li id="fn:6">
<p>One of my engineers wrote a greasemonkey script that lets him see all branch plans. It only works if you aren&rsquo;t a Bamboo admin due to the number of visible plans. I&rsquo;m working on whipping up a dedicated <a href="http://atlasboard.bitbucket.org">AtlasBoard</a> for myself.<a href="#fnref:6" rev="footnote">&#8617;</a></p></li>
<li id="fn:7">
<p>We only burned maven in effigy once or twice.<a href="#fnref:7" rev="footnote">&#8617;</a></p></li>
<li id="fn:8">
<p>The exact steps here vary depending on if the developer is using the command line or using Eclipse to switch branches.<a href="#fnref:8" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Dealing with Maven dependencies when switching to Git]]></title>
    <link href="http://www.mattshelton.net/2015/10/31/dealing-with-maven-dependencies-when-switching-to-git/"/>
    <updated>2015-10-31T10:00:00-04:00</updated>
    <id>http://www.mattshelton.net/2015/10/31/dealing-with-maven-dependencies-when-switching-to-git</id>
    <content type="html"><![CDATA[<blockquote><p><strong>Note:</strong> The official version of this post can be found at <a href="https://www.atlassian.com/git/articles/maven-dependencies-versions-merging">https://www.atlassian.com/git/articles/maven-dependencies-versions-merging</a>.</p></blockquote>

<p>So we're <a href="http://www.mattshelton.net/2015/10/30/git-or-svn-how-nuance-healthcare-chose-a-git-branching-model/">moving to Git</a> and we like git-flow. Now what? Let's test it all out!</p>

<p>My team is great. They threw together a hit list of developer workflows in <a href="https://www.atlassian.com/software/confluence/">Confluence</a>, all based on what we had been doing as a team and all of the weird things they thought we might have to do in the future. Then, in a project structure mirroring our own (but with no code in it&#8212;just a pom.xml), tried every workflow.</p>

<p>Maven dependencies were about to prove themselves to be our biggest problem in all of this.</p>

<blockquote><p><strong>Maven Build Numbering</strong></p>

<p>Maven produces <code>1.0.0-SNAPSHOT</code> builds until you release. When you release, <code>-SNAPSHOT</code> is removed and your version is <code>1.0.0</code>. Your build process needs to be able to support incrementing your minor version up after the fact so that subsequent work on your next effort will produce builds like <code>1.1.0-SNAPSHOT</code>. You're not tied to three digits -- you can define this when you start a project, but we use three. Anyway, the -SNAPSHOT part is really important to understand. This is always going to represent the latest pre-release cut of a project.</p></blockquote>

<h2>Artifacts</h2>

<p>See, our big concern in <em>all</em> of these workflows was how we were going to ensure that our project versions and inter-project dependencies were properly managed.</p>

<p>Each time Maven dependencies are retrieved for a build, it will, by default, pull those down from Ye Olde Internet(e)&#8482;. Those artifacts are stored locally so that subsequent builds can be performed more quickly. One solution to make this a bit less painful is to use an artifact repository on your local network for acting as a local cache for those external dependencies. LAN retrieval is almost always going to be faster than downloading even from the quickest of CDNs. We use Artifactory Pro as our artifact repository. In addition, since we have a multi-module structure, we store our own build artifacts in Artifactory as well. When we build one of our common packages, we can pull that specific version in via maven dependency resolution and retrieve the artifact right out of the artifact repository.</p>

<p>This works swimmingly. Artifactory also lets you synchronize your artifacts between instances so if you wanted to, say, use it to replicate your release repository to your data centers for production deployments, you could do this without needing to build a separate process.</p>

<h2>Maven dependencies, feature branches and pull requests</h2>

<p>All of our builds go into Artifactory. With SVN, we had been using  a snapshot repository for keeping the latest 2 snapshot builds, a staging repostory for any release builds not yet approved, and a release repository only for the builds blessed to go into production.<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> These builds are numbered like I described earlier, and are retrievable by a predictable URL pattern based on repository and version.</p>

<p>The primary workflow for each developer was to create a feature branch from the develop branch for their work, complete it, and place a pull request to have that work merged back into the develop branch. For a single project, this works mostly without issue, but let me paint a picture for you of the first problem we ran into head-first, and one that had us seriously reconsidering the entire migration:</p>

<p>As I said before we have multiple layers of dependency between our projects. There's a very good reason for this&#8212;both historically and strategically&#8212;for our products. We've considered alternate architectures that would eliminate this problem, but they'd introduce others. We can make our lives easier (and we did, but that's for a later post), but for now it's strategic for us to keep our structure as it is.</p>

<p>So developer A, let's call her Angela, starts work on a feature in <a href="https://www.atlassian.com/software/jira/">JIRA</a>. This requires two branches: one from our common project and one from product X. The version for common is <code>2.1.0-SNAPSHOT</code>. The version for productX is <code>2.4.0-SNAPSHOT</code>. She works locally for a while and then finally pushes back up to Bitbucket Server. Bamboo picks up these changes, builds the common package and uploads <code>common-2.1.0-SNAPSHOT</code> to Artifactory, then builds productX with a dependency on <code>common-2.1.0-SNAPSHOT</code>, uploading <code>productX-2.4.0-SNAPSHOT</code> as well. Unit tests pass!</p>

<p>Developer B, let's call him Bruce, starts work on another feature in JIRA, for a different product: productY. This also requires two branches: one from our common project and one from productY. The version for common is, as above, <code>2.1.0-SNAPSHOT</code>. The version of product Y is <code>2.7.0-SNAPSHOT</code>. He works locally for a while and then finally pushes his changes up to Bitbucket Server. Bamboo picks up these changes, builds the common package and uploads <code>common-2.1.0-SNAPSHOT</code> to Artifactory, then builds productX with a dependency on <code>common-2.1.0-SNAPSHOT</code>, uploading <code>productX-2.4.0-SNAPSHOT</code> as well. Unit tests pass!</p>

<p>Angela, meanwhile, finds a small bug in her productX code and writes a unit test to validate her fix. She runs it locally and it passes. She pushes her changes to <a href="https://bitbucket.org/product/server">Bitbucket Server</a>, and <a href="https://www.atlassian.com/software/bamboo/">Bamboo</a> picks up the change and builds productX. The build succeeds, but some of her unit tests fail. It's not the new ones she wrote, but the first ones from her initial changes to the feature. Somehow the Bamboo build has found a regression that her local build didn't? How is that possible?</p>

<p>Because her common dependency, the one Bamboo pulled in when it built productX, was no longer her copy. Bruce over-wrote <code>common-2.1.0-SNAPSHOT</code> in artifactory when his feature build completed. There was no source code conflict&#8212;both developers were working in isolation on their own branches, but the source of truth for Maven's artifact retrieval was <em>corrupted</em>.</p>

<p>Head. Meet desk.</p>

<p>For about a month after we discovered this problem we tried <em>everything</em> to get around this. Through our TAM<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>, we talked to people on the Bamboo team who use git-flow, and we talked to the developer who maintains <a href="https://ecosystem.atlassian.net/projects/MJF/">jgit-flow</a>, a java implementation of git-flow. They were all super helpful, but short of a process that required a list of manual steps for each developer every time they worked on a feature, we couldn't find a resolution that was tolerable.</p>

<p>If you're curious what we considered, here's everything we tried:</p>

<ol>
<li>Modify the version number on branch creation, or immediately thereafter.

<ul>
<li>We can do this with <code>mvn jgitflow:feature-start</code> to create the branch.</li>
<li>We can use a Bitbucket Server hook or a local githook.</li>
<li>We can manually set with <code>mvn version:set-version</code> after we create the branch.</li>
<li>We can automate the change with the [mavent-external-version] plugin.</li>
</ul>
</li>
<li>Modify the version number when finishing the branch and merging back to develop.

<ul>
<li>We can do this with <code>mvn jgitflow:feature-finish</code> to finish the branch.</li>
<li>Use a git merge driver to handle pom conflicts.</li>
<li>Use an <a href="https://confluence.atlassian.com/stash/using-repository-hooks-321858734.html">asynchronous post-receive hook</a> in Bitbucket Server</li>
</ul>
</li>
<li>Do it all manually. (Just kidding. We didn’t consider this option very long.)</li>
</ol>


<p>Each one of these options had some sort of negative side-effect. Chiefly, manual steps for a developer each and every time they needed a feature branch. And we wanted them to create feature branches all the time. Also in most cases we could not effectively use pull requests, which was a deal-breaker.</p>

<p>This consumed 1-2 people for almost two months until we had a (mindblown) revelation as to why we were approaching this problem from the wrong direction.</p>

<h2>One version to rule them all</h2>

<p>Hindsight being 20/20, I can clearly see that our biggest mistake was that we were focusing our attention on the git-flow tools rather than using the tools we <em>already</em> had to implement the workflow we wanted. We had:</p>

<ul>
<li>JIRA Software</li>
<li>Bamboo Server</li>
<li>Maven</li>
<li>Artifactory Pro</li>
</ul>


<p>Turns out, those were all of the tools we needed.</p>

<p>One of our engineers got the very bright idea that since the problem wasn't the build management itself but rather the artifacts being over-written, that we should fix Artifactory instead. His idea was to use a Maven property to set the snapshot repository URL to a custom URL which included the JIRA issue ID, and then write out its artifacts to a dynamically-created repository in Artifactory with a custom template. Maven’s dependency resolver will find artifacts in the develop snapshot repository if we haven’t needed to branch them, for instance if we’re only working on a product and not also common.</p>

<p>We set that handy little property variable in our build settings file, and wrote a Maven plugin to populate it during the earliest part of maven’s build lifecycle. On paper, this sounded incredible and re-invigorated the team to work harder to solve this problem. Trouble was that we couldn't <em>actually</em> do this. The earliest stage of the maven lifecycle is 'validate'. By the time plugins bound to validate have been run, the repository URLs were already resolved. Because of this, our variable never populated and the URL is not branch-named after all. Even though we had been using a layout in a separate repository from our develop snapshots, it wouldn’t be isolated for parallel development.</p>

<p>Head, meet desk again, your BEST FRIEND.</p>

<p>After a beer, the aforementioned engineer did some more digging and research into another way to add functionality to maven: extensions.</p>

<blockquote><p>“Here’s to beer: the cause of, and solution to, all of life’s problems.” &#8212;Homer Simpson</p></blockquote>

<p>Extensions, like plugins, give you a whole host of power to enhance your Maven workflow, however they are executed <em>before</em> lifecycle goals, and have greater access to the Maven internals. By utilizing the RepositoryUtils package, we forced Maven to re-evaluate its URLs using a custom parser and then re-set them using our updated values.<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup></p>

<p>Extension in place and tested, we started knocking off pre-migration tasks one after another, going from "this is never going to happen" to "this IS going to happen Monday... so now I need to write ten pages of documentation by tomorrow". I'll write more soon about how the tools work together to achieve our new development workflow, and some of the lessons we learned about the process.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>One downside here was that I had to use a script I wrote to hit the Artifactory REST API to &ldquo;promote&rdquo; builds from staging to release. It&rsquo;s fast enough, but begging for more automation.<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>Technical Account Manager. More information <a href="https://www.atlassian.com/enterprise/services/">here</a>.<a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
<li id="fn:3">
<p>After the initial development efforts, we found that we had to do even more to make this work 100% of the time, like when a snapshot is newer in Artifactory (from another engineer) than your local snapshot, Maven grabs the remote artifact because hey, it&rsquo;s NEWER, so it must be BETTER, right?<a href="#fnref:3" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Git or SVN? How Nuance Healthcare chose a Git branching model]]></title>
    <link href="http://www.mattshelton.net/2015/10/30/git-or-svn-how-nuance-healthcare-chose-a-git-branching-model/"/>
    <updated>2015-10-30T21:56:00-04:00</updated>
    <id>http://www.mattshelton.net/2015/10/30/git-or-svn-how-nuance-healthcare-chose-a-git-branching-model</id>
    <content type="html"><![CDATA[<blockquote><p>This is the first post in a series about my engineering team moving from Subversion to Git, why we did it, and what we encountered along the way. I am speaking on this topic at <a href="https://summit.atlassian.com">Atlassian Summit 2015</a>, and since I'm limited to 30 minutes, I wanted to provide more context and some pieces I'll be leaving out of the presentation for anyone interested.</p>

<p><strong>Note:</strong> The official version of this post can be found at <a href="https://www.atlassian.com/git/articles/git-or-svn-git-branching-model">https://www.atlassian.com/git/articles/git-or-svn-git-branching-model</a>.</p></blockquote>

<h2>Background</h2>

<p>My team is in the healthcare division at <a href="http://www.nuancehealthcare.com/">Nuance</a>. We're geographically-distributed between a couple of offices and homes on the East Cast of the US, and in an office in Pune. We develop Java web services to deliver NLP<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> solutions to the healthcare market.</p>

<p>For the most part, our service consumers are other healthcare software companies (including ourselves) such as EHR vendors and healthcare analytics companies. We do directly sell some products to hospitals, and the end-users of the applications range from physicians to medical billing staff. "Normal" people like you and me don't ever touch the software my team builds.</p>

<p>Our team has been around the block a few times with Application Lifecycle Management product combinations. We started life with a mix of <a href="https://www.rallydev.com">Rally Enterprise</a> and <a href="http://www.seapine.com/testtrack/">Seapine TestTrack Pro</a>, did about 14 months of hard labor with <a href="https://jazz.net/products/rational-team-concert/">Rational Team Concert</a>, and eventually migrated fully to the <a href="https://www.atlassian.com">Atlassian</a> stack (<a href="https://www.atlassian.com/software/jira/">JIRA Software</a>, <a href="https://www.atlassian.com/software/confluence/">Confluence</a>, <a href="https://www.atlassian.com/software/bamboo/">Bamboo</a>, <a href="https://www.atlassian.com/software/crucible/overview">Crucible</a>, <a href="http://bitbucket.org/">Bitbucket</a> and <a href="https://www.hipchat.com/">HipChat</a>). Historically we used Subversion 1.4/1.5 an our SCM with a quasi-normal trunk/branches/tags structure. We have been using <a href="https://maven.apache.org">maven</a> since forever  manage our build projects and dependencies, and switched from Jenkins to Bamboo for continuous integration (CI) a while ago in order to make use of tighter integrations with JIRA and its flexible build and deploy agent capabilities. Everything we use (now) is behind the firewall for reasons<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>.</p>

<h2>Git or SVN?</h2>

<p>We support roughly ten individual products across four product families, and the owners of these products are <em>always</em> battling for prioritization and timing. It’s nice to have our work be in high demand, and this is by no means a <em>complaint</em>, but it also necessitates cutting releases at a weird cadence and needing to change directions in the middle of a sprint<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup>.</p>

<p>Our development process really felt prohibitive at times. There was a conversation that my team was having on a regular basis that went something like this:</p>

<blockquote><p><strong>Me</strong>: We need to release 1.8.0 to QA now for regression testing so that Customer foo can go to beta next week.</p>

<p><strong>Dev</strong>: I'm still working on ABC-123 which is in trunk. It's not done yet.</p>

<p><strong>Me</strong>: Foo doesn't need ABC-123. We could put it in the next release.</p>

<p><strong>Dev</strong>: But I've been working on it for weeks. There's no clear spot to branch from to cut a release.</p>

<p><strong>Me</strong>: Well, you'll need to pull out all of your changes by hand. You have about two hours or QA can't finish in time.</p></blockquote>

<p>I know, I sound like a jerk! I never meant to be, and of course I'm exaggerating a bit to make a point, but we really did have to figure out how to get code that was in one place out of that place temporarily so that we could cut a release, and then <em>put it right back</em> for the next release<sup id="fnref:4"><a href="#fn:4" rel="footnote">4</a></sup>. And this happened all the time.</p>

<p>Now, I know some of you are thinking "Subversion supports branches, Matt...". It absolutely does, and we used them on occasion with SVN 1.4 and 1.5. Branching is a fine operation in SVN; <em>merging</em> can be a pain in the ass. As SVN has matured, it has gotten better, for sure. But we knew there were better options out there <em>for us</em>, so when the question of SCN or git arose, we set out to get Git.</p>

<blockquote><p>A side note: We briefly looked at the latest SVN (1.8 at the time) to see if it was strong enough to solve our problems, but weren't completely satisfied. One of our peer groups has a large Perforce setup and it had a lot of what we needed, but I simply couldn't stomach the licensing costs. We also looked at Mercurial for a moment, but in the end, the existing team's exposure to Git was enough to tell us that it was the right direction.</p></blockquote>

<p>I won't sugar-coat this: Atlassian's tools really favor teams who use git. Other SCMs work fine; our SVN integration was <em>sufficient</em> in that it linked us to where a given user story's changes were made. The integration capabilities for teams who use <a href="https://bitbucket.org/product/server">Bitbucket Server</a><sup id="fnref:5"><a href="#fn:5" rel="footnote">5</a></sup> instead, however, are both stronger and more natural-feeling in the <a href="https://www.atlassian.com/software/jira/">JIRA Software</a> interface and development experience &#8212; ditto with Bamboo.</p>

<p>Knowing this, and having seen some very stellar demos at <a href="https://summit.atlassian.com/archives/2013/general-sessions/dev-tools-state-of-the-union-">Summit 2013</a>, I strongly encouraged the team to go for it. Nobody objected, and we already had the licenses in place to make change.</p>

<h2>Choosing a Git Branching Model</h2>

<p>After deciding to make this change, the first challenge we had was deciding what Git branching model to implement for our team. Atlassian's <a href="https://www.atlassian.com/git/">Git microsite</a> as well as <a href="https://summit.atlassian.com/archives/2013/inside-the-development-team/git-workflows-a-la-carte">this great presentation from Summit 2013</a> explain in greater detail what a branching model is. The short version is that it describes how you will use branches in git to power your development workflow.</p>

<p>In SVN, we had a model for branching I'll call "make one when you realize you &#8212; OMG! &#8212; need one":</p>

<ul>
<li>The newest code is in <code>trunk</code>. Releases from trunk will be numbered <code>A.B.0-{build}</code>.</li>
<li>If a fix is required to a trunk-based release (e.g. we have a bug in 1.2.0-64), a branch is created and from there we will release <code>A.B.C-{build}</code> releases, where <code>C</code> increments after every release that goes out the door. These branches may never exist for a given <code>A.B</code> and we could even have more than one.</li>
<li>We also tag every release in a tags directory.</li>
</ul>


<blockquote><p><strong>An Aside About Versions</strong>
Many years ago, when I was just cutting my teath on managing a development team, our release engineer had a system of versining that was... how shall I say?... <em>really unintuitive</em>. Essentially, every release was a patch on the previous one (A.B.n), with no respect for the place from which the patch originated. Figuring out where something came from and, in almost all cases, the <em>release order</em>, required you to look at <code>svn log</code>. We printed the tree on a wall for reference.</p>

<p>In addition, our public-facing release numbers tend to be things like 3.0, 3.1, 3.5, 4.0, or essentially something a customer might expect. Remember, though that my team builds <em>web services</em> not a boxed product. Our APIs are a contract. A few years ago I made the executive that my team's builds, and therefore its releases, would adhere to <a href="http://semver.org">Semantic Versioning</a> rules. I've' had to stand my ground a few times with upper management, but now it is understood why the rules are what they are, and we haven't looked back. Partners appreciate that sort of clarity.</p></blockquote>

<p>I mentioned a problem earlier wherein we'd be working on a release (let's say <code>1.2.0</code>) and we'd have a feature still in progress as we approached a release date. We would need to pull that code out, cut our release, branch to <code>branches/1.2.1</code> and then merge that code back in, hoping nobody had a hard drive crash in the meantime<sup id="fnref:6"><a href="#fn:6" rel="footnote">6</a></sup>.</p>

<p>Removing a whole feature by itself from a shared trunk is a pain. Everyone hated life when they had to do that. <code>svn blame</code> can be useful, as can a strong diff tool, but it’s still annoying to work with. I often took it personally, feeling that my bad planning had led to us not having all of our ducks in a row before it was time to be done with a release<sup id="fnref:7"><a href="#fn:7" rel="footnote">7</a></sup>. My team dealt with this for long enough.</p>

<p>Sometimes we'd over-correct to avoid the pain and would ask developers to sit on their hands for a couple of days (a virtual code freeze, if you will), just so we didn't pollute trunk before a release.</p>

<p>So we knew we needed, at least, feature branches. There's a simple Git branching model that is applicable: a master branch for what's in prod, and using feature branches for every feature, bug, etc. Team's have to manage merge order to ensure that what ships out in master is what is supposed to ship out for the release. This is, essentially, the same thing we had before, with some better feature isolation, but we wanted freedom with our power.</p>

<p>In our environment, we often need to keep a few versions in production, and may need to fix defects in a release that is 2-3 minor revisions older than what we are working on right now. So, in addition to feature branches, we also needed some sort of release branch or similar that would let us fix issues from previous releases. The Atlassian Bitbucket Server team <a href="http://blogs.atlassian.com/2013/10/inside-atlassian-feature-branching-on-the-stash-team/">does this</a>. They make fixes in long-running support branches, and then merge them up the branch stream so that a fix makes it in to all of the support streams.</p>

<p>Their model looked really good, and we ran a few prototype interactions with this model to see if it would suit our needs. The "killer app" for them is their rolling merge of a fix up to their develop branch. While we liked this concept, every time we tried it, we ran into one issue or another with our maven dependencies. Also, as a rule, we couldn't guarantee we wanted a straight merge of the work from one version into another. In some cases we needed to implement the same fix in slightly different ways between versions, so a direct merge wasn't possible.</p>

<p>A few of the members of the team strongly favored a variation of this model known as "git-flow". <a href="http://nvie.com/posts/a-successful-git-branching-model/">Git-flow</a> is a set of branch naming conventions and merge guidelines, authored by <a href="http://nvie.com/">Vincent Driessen</a>. This felt very natural to the team, and we liked the structure since it eliminated many of the questions around "what do I do when we need to do x?". The answers were generally very obvious. Rather than explaining what git-flow is, you can read more about it in <a href="https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow">Atlassian's tutorial</a>.</p>

<p>The only gap left for us with git-flow was what to do about those long-running releases in production. Since master keeps moving forward, we couldn't use the git-flow hotfix workflow for a bug fix from a previous release. On the other hand, we didn't <em>always</em> want a support branch.</p>

<p>Most of the time a hotfix, only patching the latest release in production, should be sufficient; support is only there when we need to go back further, or when we need to maintain compatibility for one reason or another. That latter use case we dissected further and came up with criteria for choosing to use a support branch rather than a hotfix and minor version upgrade:</p>

<ol>
<li>This code cannot be trivially merged back into develop.</li>
<li>The partner/customer cannot handle an interface change that comes with the latest release.</li>
<li>There is an internal dependency which cannot be changed.<sup id="fnref:8"><a href="#fn:8" rel="footnote">8</a></sup></li>
</ol>


<p>Both git-flow extension packages<sup id="fnref:9"><a href="#fn:9" rel="footnote">9</a></sup> provide support for the support branch concept, which isn't part of the original draft of git-flow, but has become popular enough to warrant inclusion.</p>

<p>Git-flow offered a workflow we liked, with the tooling support we needed. In the next post I'll go into what happened when we actually tried using it in a POC project we used to represent our development process. It was... a learning experience!</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>Natural Language Processing. WE CAN READ YOUR THOUGHTS. (No. Not really.)<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>There is a <em>lot</em> that is attractive about Atlassian&rsquo;s cloud offerings, but we need to keep our fingers wrapped tightly around our servers and data for the time being. While we don&rsquo;t personally need to do much with PHI data, our software <em>does</em> and it&rsquo;s important to keep it as secure as possible.<a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
<li id="fn:3">
<p>Shhhh&hellip; don&rsquo;t tell Ken Schwaber. <a href="#fnref:3" rev="footnote">&#8617;</a></p></li>
<li id="fn:4">
<p>Which might have only been a few days later anyway.<a href="#fnref:4" rev="footnote">&#8617;</a></p></li>
<li id="fn:5">
<p>Formerly known as Stash. Hello, Atlassian Fall Rebranding!<a href="#fnref:5" rev="footnote">&#8617;</a></p></li>
<li id="fn:6">
<p>I know we could always pull it out of the previous commit. I was kidding.<a href="#fnref:6" rev="footnote">&#8617;</a></p></li>
<li id="fn:7">
<p>This wasn&rsquo;t usually the case&#8212;generally it was because someone else&rsquo;s timeframe moved up and we had to react quickly.<a href="#fnref:7" rev="footnote">&#8617;</a></p></li>
<li id="fn:8">
<p>This is one of those things I can&rsquo;t get into on my own blog. Just trust me. &ldquo;Reasons&rdquo;.<a href="#fnref:8" rev="footnote">&#8617;</a></p></li>
<li id="fn:9">
<p>The <a href="https://github.com/nvie/gitflow">original package</a> by Vincent Driessen isn&rsquo;t being maintained any longer. A <a href="https://github.com/petervanderdoes/gitflow-avh">new fork</a> , however, is regularly updated.<a href="#fnref:9" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Canonical Post Urls in Jekyll]]></title>
    <link href="http://www.mattshelton.net/2015/10/27/canonical-post-urls-in-jekyll/"/>
    <updated>2015-10-27T14:21:31-04:00</updated>
    <id>http://www.mattshelton.net/2015/10/27/canonical-post-urls-in-jekyll</id>
    <content type="html"><![CDATA[<p>In the next couple of days I'll be contributing a series of blog posts to the <a href="https://developer.atlassian.com/blog/">Atlassian Developers blog</a> to serve as a backdrop for my presentation at <a href="https://summit.atlassian.com">Atlassian Summit 2015</a>, about a week and a half from now<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>. I wanted to syndicate that content here, but for SEO reasons I was asked to mark the Atlassian URL as the canonical one for each post. That isn't possible out of the box, so here's how I modified my Jekyll template to accommodate this change:</p>

<p>First, I add a <code>canonical-url</code> tag to my YAML front-matter:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>canonical-url: http://www.yahoo.com</span></code></pre></td></tr></table></div></figure>


<p>And second, I modified my header template to set the <code>canonical</code> variable and populate the proper <code>&lt;link ...&gt;</code> tag:</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>{% if page.canonical-url == nil %}
</span><span class='line'>{% capture canonical %}{{ site.url }}{% if site.permalink contains '.html' %}{{ page.url }}{% else %}{{ page.url | remove:'index.html' | strip_slash }}{% endif %}{% endcapture %}
</span><span class='line'>{% else %}
</span><span class='line'>{% assign canonical = page.canonical-url %}
</span><span class='line'>{% endif %}
</span><span class='line'>&lt;link rel="canonical" href="{{ canonical }}"></span></code></pre></td></tr></table></div></figure>


<p>The documentation out there for liquid is somewhat less helpful than I'd prefer, so the proper way to test if a variable was truly unset took a few stabs, and getting the proper context for the page variable, despite pages really being posts, was also unintuitive. One of these days, I might have to give up on Jekyll based purely on the "clear as mud" factor.</p>

<p>NB: Getting the above Liquid code to actually display was a royal pain in the butt. <a href="https://truongtx.me/2013/01/09/display-liquid-code-in-jekyll/">This site</a> was helpful, and I appreciated his closing sentence:</p>

<blockquote><p>Displaying liquid code in jekyll is really an annoying task. So try to avoid it as much as you can.</p></blockquote>



<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>Holy crap.<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Selfish Ambition]]></title>
    <link href="http://www.mattshelton.net/2015/10/08/selfish-ambition/"/>
    <updated>2015-10-08T21:32:02-04:00</updated>
    <id>http://www.mattshelton.net/2015/10/08/selfish-ambition</id>
    <content type="html"><![CDATA[<blockquote><p>He who attempts to act and do things for others or for the world without deepening his own self-understanding, freedom, integrity and capacity to love, will not have anything to give others. He will communicate to them nothing but the contagion of his own obsessions, his aggressiveness, his ego-centered ambitions, his delusions about ends and means, his doctrinaire prejudices and ideas.</p><footer><strong>Thomas Merton</strong> <cite>Contemplation in a World of Action</cite></footer></blockquote>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Harder Better Faster Stronger Cover]]></title>
    <link href="http://www.mattshelton.net/2015/10/05/harder-better-faster-stronger-cover/"/>
    <updated>2015-10-05T17:27:24-04:00</updated>
    <id>http://www.mattshelton.net/2015/10/05/harder-better-faster-stronger-cover</id>
    <content type="html"><![CDATA[<div class="video-container"><iframe src="https://www.youtube.com/embed/vwf2uvWlL_c "></iframe></div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Ranked List of Star Trek Films]]></title>
    <link href="http://www.mattshelton.net/2015/09/30/ranked-list-of-star-trek-films/"/>
    <updated>2015-09-30T17:17:32-04:00</updated>
    <id>http://www.mattshelton.net/2015/09/30/ranked-list-of-star-trek-films</id>
    <content type="html"><![CDATA[<p>On a recent <a href="http://www.relay.fm/mpu/280">Mac Power Users</a> episode, David Sparks and Katie Floyd were trading their most and least favorite Star Trek movies<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>. I haven't given the series much thought in a while, and had some different opinions.<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup></p>

<ol>
<li>Star Trek VI: The Undiscovered Country (1991)</li>
<li>Star Trek (2009)</li>
<li>Star Trek II: The Wrath of Khan (1982)</li>
<li>Star Trek: First Contact (1996)</li>
<li>Star Trek Into Darkness (2013)</li>
<li>Star Trek IV: The Voyage Home (1986)</li>
<li>Star Trek Generations (1994)</li>
<li>Star Trek III: The Search for Spock (1984)</li>
<li>Star Trek V: The Final Frontier (1989)</li>
<li>Star Trek: The Motion Picture (1979)</li>
<li>Star Trek: Insurrection (1998)</li>
<li>Star Trek: Nemesis (2002)</li>
</ol>


<p>Most people rank The Final Frontier as their least favorite of the set, but I don't mind it as a movie. It's my least favorite of the original series crew, but definitely not my least favorite overall.</p>

<p>I <strong>really</strong> like The Undiscovered Country. It was the first one I saw in theatres, having only recently gotten into Star Trek TNG around the same time, and it showed off the growing special effects capabilities of the industry with the older cast.</p>

<p>I also am a big fan of the reboot films. I think Chris Pine is a better Kirk than Shatner<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup>, and the casting overall is spectacular. The writing is great and the integration of Leonard Nimoy as Spock' is a bonus. I get all of the timeline weirdness, and truthfully I don't care how/why they are where they are and how it's not the same as the original timeline. I'm not a purist.</p>

<p>Overall, the TNG cast films aren't my favorites. Once Frakes got ahold of the director's chair, the films became too much inside baseball and less about advancing the universe. Generations was good, mostly because of the Kirk. First Contact was really good. Insurrection was ok, but not good. The ending to Nemesis made me furious.<sup id="fnref:4"><a href="#fn:4" rel="footnote">4</a></sup> It might be one of the only times I didn't enjoy Tom Hardy in a film.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
<p>though not very seriously<a href="#fnref:1" rev="footnote">&#8617;</a></p></li>
<li id="fn:2">
<p>To be clear, I own all of them and would watch any of it were offered.<a href="#fnref:2" rev="footnote">&#8617;</a></p></li>
<li id="fn:3">
<p>sacrilege, I know  <a href="#fnref:3" rev="footnote">&#8617;</a></p></li>
<li id="fn:4">
<p>That whole movie made me furious. It should have been called Star Trek: Narcissist for how Picard-focused it was. I wanted so badly to like it, but ended up hating nearly every plot direction.<a href="#fnref:4" rev="footnote">&#8617;</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
</feed>
