<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title type="text">Robbie Mackay</title>
<generator uri="https://github.com/mojombo/jekyll">Jekyll</generator>
<link rel="self" type="application/atom+xml" href="https://robbiemackay.com/feed.xml" />
<link rel="alternate" type="text/html" href="https://robbiemackay.com/" />
<updated>2025-04-07T11:53:58+12:00</updated>
<id>https://robbiemackay.com/</id>
<author>
  <name>Robbie Mackay</name>
  <uri>https://robbiemackay.com/</uri>
  <email>rm@robbiemackay.com</email>
</author>


<entry>
  <title type="html"><![CDATA[This week #7]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/2021/08/20/this-week-7-2"/>
  <id>https://robbiemackay.com/2021/08/20/this-week-7-2</id>
  <published>2021-08-20T00:00:00+12:00</published>
  <updated>2021-08-20T00:00:00+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;A collection of technical, management and other thoughts from this week.&lt;/p&gt;

&lt;h2 id=&quot;thinking&quot;&gt;Thinking&lt;/h2&gt;

&lt;p&gt;I’ve been on-boarding to a new company the last month, and learning a bunch of new codebases. As I’ve started to contribute to code reviews, I was reflecting a bit on code review for knowledge sharing (a heated debate sometimes, I know!). I think t while code review as a &lt;em&gt;teaching tool&lt;/em&gt; might be of dubious value, it can be a great &lt;em&gt;learning tool&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In particular, I find that I use code review as a learning tool myself and find it really effective. It points me at parts of a codebase I might never have seen before and in the process of figuring out if a change makes sense, I have to read and understand what’s happening.&lt;/p&gt;

&lt;p&gt;For the musicians out there - it feels a bit like sight-reading a new piece of music. It’s not the same as playing and coding within that codebase, but it goes a long way to being able to reason about what’s going on there now and in future.&lt;/p&gt;

&lt;h2 id=&quot;reading&quot;&gt;Reading&lt;/h2&gt;

&lt;p&gt;I’m diving into single-table design and DynamoDB, so I’ll share what I’ve read so far there:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.alexdebrie.com/posts/dynamodb-single-table/&quot;&gt;The What, Why and When of Single-Table Design with DynamoDB&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.trek10.com/blog/dynamodb-single-table-relational-modeling/&quot;&gt;From relational DB to single DynamoDB table: a step-by-step exploration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And up next…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6yqfmXiZTlM&quot;&gt;Amazon DynamoDB deep dive: Advanced design patterns&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;&quot;&gt;Data modeling with Amazon DynamoDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/2021/08/20/this-week-7-2&quot;&gt;This week #7&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on August 20, 2021.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[This week #6]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/this-week/2019/05/17/this-week-5"/>
  <id>https://robbiemackay.com/this-week/2019/05/17/this-week-5</id>
  <published>2019-05-17T00:00:00+12:00</published>
  <updated>2019-05-17T00:00:00+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;A collection of technical, management and other thoughts from this week.&lt;/p&gt;

&lt;p&gt;Life happened and I’ve missed a couple weeks but I’m back at writing these.&lt;/p&gt;

&lt;h2 id=&quot;thinking&quot;&gt;Thinking&lt;/h2&gt;

&lt;p&gt;I changed roles in January, moving from a management role to a developer role. I choose an engineering role partly because I wanted to learn and grow my technical skills again, but partly I just wanted to feel like I’d done something at the end of each day.&lt;/p&gt;

&lt;p&gt;As a manager, I often finished the day wondering what I’d done or feeling like maybe I didn’t actually do anything useful at all today. I only recently realised thats a common experience for many new managers. It’s harder to see your impacts as a manager, and part of becoming a good manager is figuring out how to judge your impact.&lt;/p&gt;

&lt;p&gt;I’ve recently found myself in a similar place again. I’m not managing a team, but we’re in a phase of open-ended exploratory work. Once again, it’s hard to tell if what I did today was useful. Did I read anything that gave me insight into the product, or customers needs? Even if I did, was that enough? Is it actually moving us closer to a profitable business? I’m just … not sure. In abscence of a concrete deliverable ie. a working bit of code, it’s hard to see my impact.&lt;/p&gt;

&lt;p&gt;I’ve read a couple of &lt;a href=&quot;https://blog.andymatuschak.org/post/159979927467/satisfaction-and-progress-in-open-ended-work&quot; title=&quot;Satisfaction and progress in open ended work&quot;&gt;good&lt;/a&gt; &lt;a href=&quot;https://blog.coleadership.com/how-to-make-sense-of-your-impact-when-youre-no-longer-coding/&quot; title=&quot;How to Make Sense of Your Impact When You&apos;re No Longer Coding&quot;&gt;pieces&lt;/a&gt; talking about this, and I’ve started trying out some personal processes. I’ve set high level goals: pick an idea in 2 weeks, build and test a prototype in a month. My daily tasks are partly reactive: follow up X, and partly driven by those goals: sketch a lean canvas for Y idea or answer a question about idea Z. It’s early days but it’s helped a little. I have some idea if I’m seeing progress now.&lt;/p&gt;

&lt;h2 id=&quot;reading&quot;&gt;Reading&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://blog.andymatuschak.org/post/159979927467/satisfaction-and-progress-in-open-ended-work&quot;&gt;Satisfaction and progress in open ended work&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://blog.coleadership.com/how-to-make-sense-of-your-impact-when-youre-no-longer-coding/&quot; title=&quot;How to Make Sense of Your Impact When You&apos;re No Longer Coding&quot;&gt;How to Make Sense of Your Impact When You’re No Longer Coding&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://danluu.com/hiring-lemons/&quot; title=&quot;Hiring and the market for lemons&quot;&gt;Hiring and the market for lemons&lt;/a&gt;. An interesting analysis of broken hiring practices. I’m not sure I agree with all of it but it’s worth a read.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://boz.com/articles/disagree.html&quot; title=&quot;How not to disagree&quot;&gt;How not to disagree&lt;/a&gt;. A good piece about how to handle managing a team through changes you don’t agree with.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://lethain.com/fire-fixation/&quot; title=&quot;https://lethain.com/fire-fixation/&quot;&gt;Fire fixation&lt;/a&gt;. I’ve definitely had teams stuck in a place of fighting so many fires we couldn’t get any new work done. It’s a hard place to get out of.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.remotemobprogramming.org/&quot; title=&quot;Remote mob programming&quot;&gt;Remote mob programming&lt;/a&gt;. A good guide, not something I can use right now but saving it for future reference.&lt;/p&gt;

&lt;h2 id=&quot;listening&quot;&gt;Listening&lt;/h2&gt;

&lt;p&gt;a16z on &lt;a href=&quot;https://a16z.com/2019/04/26/building-software-company-healthcare/&quot;&gt;healthcare&lt;/a&gt; and &lt;a href=&quot;https://a16z.com/2019/04/07/fintech-innovation-startups-incumbents-advice/&quot;&gt;fintech&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://changelog.com/podcast/345&quot;&gt;Quick and Cognitive Behavioural Therapy&lt;/a&gt; on &lt;a href=&quot;https://changelog.com/podcast&quot;&gt;Changelog&lt;/a&gt;.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/this-week/2019/05/17/this-week-5&quot;&gt;This week #6&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on May 17, 2019.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[This week #5]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/this-week/2019/04/30/this-week-5"/>
  <id>https://robbiemackay.com/this-week/2019/04/30/this-week-5</id>
  <published>2019-04-30T00:00:00+12:00</published>
  <updated>2019-04-30T00:00:00+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;A collection of technical, management and other thoughts from this week.&lt;/p&gt;

&lt;p&gt;A bit late and short this week. I tried several times to turn my thoughts into a couple of coherent paragraphs but I’m going to call time and publish this as-is.&lt;/p&gt;

&lt;h2 id=&quot;reading&quot;&gt;Reading&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.fastcompany.com/40510522/meritocracy-doesnt-exist-and-believing-it-does-is-bad-for-you&quot; title=&quot;Meritocracy doesn’t exist, and believing it does is bad for you&quot;&gt;Meritocracy doesn’t exist, and believing it does is bad for you&lt;/a&gt;. The title says it all really.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://erikbern.com/2019/04/15/why-software-projects-take-longer-than-you-think-a-statistical-model.html&quot;&gt;Why software projects take longer than you think&lt;/a&gt;. A great write up a possible reason why we’re so bad at estimating software projects: People estimate the &lt;em&gt;median&lt;/em&gt; completion time well, but not the mean. It’d love to see this confirmed with more data.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.troyhunt.com/how-to-track-your-kids-and-other-peoples-kids-with-the-tictoctrack-watch&quot;&gt;How to Track Your Kids (and Other People’s Kids) With the TicTocTrack Watch&lt;/a&gt;. A good break down of the security failures of a watch for tracking your kids. I’m with Germany on this one - ban them -  the security risks are too high to consider any device that tracks children.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://macwright.org/2019/02/09/tachyons-css.html&quot;&gt;A way to do CSS for applications&lt;/a&gt;. Nice and simple. I might try this on my next project.&lt;/p&gt;

&lt;h2 id=&quot;listening&quot;&gt;Listening&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.nightvalepresents.com/startwiththis&quot;&gt;Start With This&lt;/a&gt;. A new podcast from the creators of Welcome to Nightvale about writing and the creative process. Each episode has assignments to help push you to actually create something.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/this-week/2019/04/30/this-week-5&quot;&gt;This week #5&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on April 30, 2019.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[This week #4]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/this-week/2019/04/18/this-week-4"/>
  <id>https://robbiemackay.com/this-week/2019/04/18/this-week-4</id>
  <published>2019-04-18T00:00:00+12:00</published>
  <updated>2019-04-18T00:00:00+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;A collection of technical, management and other thoughts from this week.&lt;/p&gt;

&lt;p&gt;I’m on vacation this week and having mixed success disconnecting from work. Mostly I’m still going down rabbit-holes of interesting tech which at least gives me something to write about.&lt;/p&gt;

&lt;h2 id=&quot;thinking&quot;&gt;Thinking&lt;/h2&gt;

&lt;p&gt;I’m slowly poking at a couple of new things. The first is building &lt;a href=&quot;https://developers.google.com/web/progressive-web-apps/&quot;&gt;progressive web apps&lt;/a&gt; in &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt;, using &lt;a href=&quot;https://vuetifyjs.com/en/&quot;&gt;Vuetify&lt;/a&gt; and Cordova. I’m fairly convinced that this is the stack I would use to build a new frontend today, &lt;em&gt;but only&lt;/em&gt; if it needs a mobile app or offline support. I’m now stuck needing a real project to experiment on before I can get any further.&lt;/p&gt;

&lt;p&gt;The second thing is &lt;a href=&quot;https://phoenixframework.org&quot;&gt;Phoenix&lt;/a&gt;, a web framework built in &lt;a href=&quot;https://elixir-lang.org&quot;&gt;Elixir&lt;/a&gt;. I love the promise of super fast requests, built-in support for web sockets, easy scaling. At first glance, it looks like the early learning curve isn’t too bad, although it’s clear there’s a lot of complexity to uncover eventually. My biggest worry is the deployment story. It’s just not as well supported as something like PHP or Python. You can deploy Elixir to Heroku but &lt;a href=&quot;https://medium.com/mint-digital/elixir-deployments-on-aws-ee787aa02a9d&quot;&gt;lose some of the great features&lt;/a&gt; in the process.&lt;/p&gt;

&lt;h2 id=&quot;reading&quot;&gt;Reading&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.nytimes.com/2018/12/19/smarter-living/attachment-styles-work-life-balance.html&quot;&gt;The 4 ‘Attachment Styles,’ and How They Sabotage Your Work-Life Balance&lt;/a&gt;. An interesting and possibly useful bit of psychology context.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.uxpin.com/studio/ebooks/ux-design-for-startups/&quot; title=&quot;UX Design For Startups&quot;&gt;UX Design For Startups&lt;/a&gt;. I’ve only just started this. So far it looks like a nice overview, but I haven’t seen a lot of depth. Not surprising for a free ebook.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://phili.pe/posts/timestamps-and-time-zones-in-postgresql/&quot; title=&quot;Timestamps and time zones in Postgresql&quot;&gt;Timestamps and time zones in Postgresql&lt;/a&gt;. Time is hard.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://8thlight.com/blog/doug-bradbury/2019/04/16/disrupt-yourself.html&quot; title=&quot;One Neat Trick To Avoid Rewriting Your Software Product&quot;&gt;One Neat Trick To Avoid Rewriting Your Software Product&lt;/a&gt;. Yet another take on why you shouldn’t rewrite, and how better alternatives. I particularly appreciated the points about the need to limit a new products runway. It’s too easy to let a new spin-off product kill the old one slowly without actually proving itself.&lt;/p&gt;

&lt;h2 id=&quot;listening&quot;&gt;Listening&lt;/h2&gt;

&lt;p&gt;I had a long drive by myself recently so I caught up on &lt;a href=&quot;http://www.welcometonightvale.com&quot;&gt;Welcome To Nightvale&lt;/a&gt; and got through a few more episodes of &lt;a href=&quot;http://www.nightvalepresents.com/goodmorningnightvale&quot;&gt;Good Morning Nightvale&lt;/a&gt;. If you don’t already know about Nightvale you should really start listening.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/this-week/2019/04/18/this-week-4&quot;&gt;This week #4&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on April 18, 2019.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[This week #3]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/this-week/2019/04/11/this-week-3"/>
  <id>https://robbiemackay.com/this-week/2019/04/11/this-week-3</id>
  <published>2019-04-11T00:00:00+12:00</published>
  <updated>2019-04-11T00:00:00+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;A collection of technical, management and other thoughts from this week.&lt;/p&gt;

&lt;h2 id=&quot;thinking&quot;&gt;Thinking&lt;/h2&gt;

&lt;p&gt;I haven’t had a clear focus for my reflections this week, but there are some rough themes.&lt;/p&gt;

&lt;h3 id=&quot;building-new-things&quot;&gt;Building new things&lt;/h3&gt;

&lt;p&gt;What’s my ideal prototyping tech stack? Is it worth learning Sketch, Figma or XD or should I just prototype in code? What should I learn now that will help with product development later?&lt;/p&gt;

&lt;p&gt;I have a lot of experience with PHP and Laravel, such that I could very quickly through something together. But I feel like I have to balance that with how much PHP would appeal (or not) when hiring other developers. If I go towards Python, which is having a bit of a resurgence and pair that with Vue or React, that seems more likely to appeal to good developers. But there are also those who would be wary of that stack too.&lt;/p&gt;

&lt;h3 id=&quot;what-should-i-learn-next&quot;&gt;What should I learn next?&lt;/h3&gt;

&lt;p&gt;I could double down of areas I’ve already dabbled in: front-end dev, React, Vue, etc. I could focus on new technical areas: machine learning, graph databases, modelling tricky problems. I could dig into something new outside my field: UX design, user research, or product management.&lt;/p&gt;

&lt;p&gt;Right now I’m tending towards doing some practice building Progressive Web Apps, and trying to use it as practice for more UX and product thinking. How that all fits together is still very much a work-in-progress.&lt;/p&gt;

&lt;h2 id=&quot;reading&quot;&gt;Reading&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://medium.com/@sarvnaz/meritocracy-stinks-585a6d9092a6&quot;&gt;Meritocracy Stinks&lt;/a&gt;. Criticisms of meritocracy aren’t new but I thought this was a really good dig into it, particularly in a New Zealand context.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://hbr.org/2019/03/the-feedback-fallacy&quot;&gt;The Feedback Fallacy&lt;/a&gt;. This is definitely worth reading. It challenged my assumption that critical feedback is necessary and good for growth.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Another of our collective theories is that feedback contains useful information, and that this information is the magic ingredient that will accelerate someone’s learning. Again, the research points in the opposite direction. Learning is less a function of adding something that isn’t there than it is of recognizing, reinforcing, and refining what already is.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://library.gv.com/field-guide-to-ux-research-for-startups-8569114c27fb?gi=85e2281fc721&quot; title=&quot;Field Guide to UX Research for Startups&quot;&gt;Field Guide to UX Research For Startups&lt;/a&gt;. A little lightweight, but a good quick start to answering: what kind of research am I doing right now?&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.paulgraham.com/startupideas.html&quot; title=&quot;How To Get Startup Ideas&quot;&gt;How To Get Startup Ideas&lt;/a&gt;. From 2012 but relevant for me right now.&lt;/p&gt;

&lt;h2 id=&quot;listening&quot;&gt;Listening&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://shouldthisexist.com/&quot;&gt;Should This Exist?&lt;/a&gt;. I’m just getting started on this now but it looks promising.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/this-week/2019/04/11/this-week-3&quot;&gt;This week #3&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on April 11, 2019.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[This week #2]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/this-week/2019/04/05/this-week-2"/>
  <id>https://robbiemackay.com/this-week/2019/04/05/this-week-2</id>
  <published>2019-04-05T00:00:00+13:00</published>
  <updated>2019-04-05T00:00:00+13:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;A random collection of thoughts from this week.&lt;/p&gt;

&lt;h2 id=&quot;thinking&quot;&gt;Thinking&lt;/h2&gt;

&lt;p&gt;I’ve been pondering learning skills from other disciplines. It’s potentially a killer feature. My hunch is that knowing unexpected things outside my field gives me an edge, and helps me remain a high performer.&lt;/p&gt;

&lt;p&gt;Think of the project manager who codes and has a little more context around technical decisions, the developer who can give critical feedback on design, or help do user research.&lt;/p&gt;

&lt;p&gt;I could be a function of the smaller organisations I’ve been in but it’s often been useful to work outside my role, and I’ve seen other succeed doing the same. It might be supporting your coworkers when they’re swamped, or picking up jobs no-one on the team actually has experience doing. It can earn respect as a high performer, and potentially make the whole team faster too. In the best case it can build a sense of cohesion and a team where everyone helps each other out.&lt;/p&gt;

&lt;p&gt;The pitfall - which I have seen too - is that people with a little bit of knowledge start to second guess their coworkers. Imagine the developer with a little bit of product knowledge repeatedly second guessing the product direction. Judgement and humility are essential.&lt;/p&gt;

&lt;h2 id=&quot;reading&quot;&gt;Reading&lt;/h2&gt;

&lt;p&gt;Some from further back:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://uxdesign.cc/a-minimal-viable-product-needs-to-actually-be-viable-8d121e6f31bd?gi=be77603fcc12&quot; title=&quot;https://uxdesign.cc/a-minimal-viable-product-needs-to-actually-be-viable-8d121e6f31bd?gi=be77603fcc12&quot;&gt;A minimal viable product needs to actually be viable&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://blog.doismellburning.co.uk/how-not-to-screw-up-hiring/&quot; title=&quot;https://blog.doismellburning.co.uk/how-not-to-screw-up-hiring/&quot;&gt;How not to screw up hiring&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://medium.com/mule-design/research-questions-are-not-interview-questions-7f90602eb533&quot; title=&quot;https://medium.com/mule-design/research-questions-are-not-interview-questions-7f90602eb533&quot;&gt;Research questions are not interview questions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;https://macwright.org&quot;&gt;@tmcw&lt;/a&gt; for &lt;a href=&quot;https://macwright.org/2019/02/06/how-to-blog.html&quot; title=&quot;How to blog&quot;&gt;inspiration&lt;/a&gt; to just do something simple each week&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/this-week/2019/04/05/this-week-2&quot;&gt;This week #2&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on April 05, 2019.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[This week #1]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/this-week/2019/03/28/this-week"/>
  <id>https://robbiemackay.com/this-week/2019/03/28/this-week</id>
  <published>2019-03-28T00:00:00+13:00</published>
  <updated>2019-03-28T00:00:00+13:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;A random collection of technical, management and other thoughts from this week.&lt;/p&gt;

&lt;h2 id=&quot;thinking&quot;&gt;Thinking&lt;/h2&gt;

&lt;p&gt;I’ve been reflecting a little on how much time I’ve spent on operations work in previous roles - wrangling servers, configuring everything from DNS to job queues.&lt;/p&gt;

&lt;p&gt;I think in many projects I’ve worked on the companies involved would have got much better value from managed / off the shelf solutions. In the smaller ones it might be that they could have just used a managed Drupal or Wordpress host. In others they needed a full continuous development pipeline but might have been able to get 90% of that from Heroku.&lt;/p&gt;

&lt;p&gt;It’s easy to look at Heroku (and similar providers) on paper and label it ‘too expensive’, but when I think of the hundreds of hours spent setting up a deployment pipeline and automating server configurations it would probably have balanced out. The worst factor in roll-your-own solutions is that they potentially slow down the development, so the cost compounds over time.&lt;/p&gt;

&lt;p&gt;It does seem like there might be a gap between a Heroku-style solution which is expensive but basically does everything for you, and a DIY deployment pipeline shipping to EC2 or a Kube cluster. As a company grows, and Heroku gets expensive but the dev team is still &amp;lt; 20 people, it’s not clear to me where those teams should land.&lt;/p&gt;

&lt;h2 id=&quot;reading&quot;&gt;Reading&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://leowid.com/uncoupling-worth-work/&quot; title=&quot;Your work is not your worth&quot;&gt;Your work is not your worth&lt;/a&gt;. Trying to square what I know (&lt;em&gt;I am not my work&lt;/em&gt;) with how I feel.&lt;/p&gt;

&lt;p&gt;This &lt;a href=&quot;https://twitter.com/rrhoover/status/1109542350659817472?s=20&quot;&gt;twitter thread&lt;/a&gt; from Ryan Hoover. Getting paid as an remote contractor outside the US feels messier than necessary, and having a bunch of remote employees in many countries seems nearly impossible for small start ups right now.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://hypothesis.works/articles/calculating-the-mean/&quot; title=&quot;Calculating the mean of a list of numbers&quot;&gt;Calculating the mean of a list of numbers&lt;/a&gt;. Turns out this is much harder than you’d think.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://martinfowler.com/articles/born-for-it.html&quot; title=&quot;Born for it&quot;&gt;Born for it&lt;/a&gt;. A write up of how the image of a socially-awkward, white, male programmer came about, including some good take-aways about how the women and people of colour are disadvantaged by idea of intellectual ability as a fixed gift vs something you can improve over time.&lt;/p&gt;

&lt;h2 id=&quot;listening&quot;&gt;Listening&lt;/h2&gt;

&lt;p&gt;A lot of &lt;a href=&quot;https://soundcloud.com/keenodnb&quot;&gt;Keeno&lt;/a&gt; and other dnb. I’ll try to pay more attention for next week!&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/this-week/2019/03/28/this-week&quot;&gt;This week #1&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on March 28, 2019.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Psychological safety]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/2017/05/19/psychological-safety"/>
  <id>https://robbiemackay.com/2017/05/19/psychological-safety</id>
  <published>2017-05-19T01:05:29+12:00</published>
  <updated>2017-05-19T01:05:29+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;I spent a little time reading and thinking about safety recently: what it means to feel ‘safe’ in a team or an organisation, what impact that has on your and your team.&lt;/p&gt;

&lt;p&gt;I haven’t really formed this into coherent thoughts yet but I’ll leave some links as a placeholder.&lt;/p&gt;

&lt;p&gt;The first I really read about this was looking at Google’s work on building successful teams. One their &lt;a href=&quot;https://rework.withgoogle.com/blog/five-keys-to-a-successful-google-team/&quot;&gt;five keys to a successful team&lt;/a&gt; is Psycological Safety, in fact they list as the &lt;em&gt;most&lt;/em&gt; important.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In a team with high psychological safety, teammates feel safe to take risks around their team members. They feel confident that no one on the team will embarrass or punish anyone else for admitting a mistake, asking a question, or offering a new idea.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And then someone posted a couple of podcasts about safety in the &lt;a href=&quot;http://randsinrepose.com/welcome-to-rands-leadership-slack/&quot;&gt;Rands leadership slack&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://agilepath.fm/episode/in-search-of-safety&quot;&gt;In Search Of Safety&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://agilepath.fm/episode/in-search-of-safety-live-retrospective&quot;&gt;In Search Of Safety: Retrospective&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both of these are well worth a listen.&lt;/p&gt;

&lt;p&gt;I’m still reflecting a bit on how this applies to me, to my team and to how I manage them. I’ll post a link if I have future thoughts or updates.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/2017/05/19/psychological-safety&quot;&gt;Psychological safety&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on May 19, 2017.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[A little less coffee]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/2017/05/19/a-little-less-coffee"/>
  <id>https://robbiemackay.com/2017/05/19/a-little-less-coffee</id>
  <published>2017-05-19T00:57:51+12:00</published>
  <updated>2017-05-19T00:57:51+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;I’ve been experimenting over the last week with reducing my coffee habit, and seeing how that effects my mood, productivity, sleep etc.&lt;/p&gt;

&lt;p&gt;I started at about 3 cups / day. I realised a long time ago that much more that 3 cups a day is probably my limit. Much more and I don’t sleep properly and sometimes get jittery.&lt;/p&gt;

&lt;p&gt;What I’ve noticed so far:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;I slept much better. I took a few days with no coffee at all but then I got much better nights sleep.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I don’t know what to do with my break time, or how to start the day, without my coffee making ritual.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Coffee out, is not the same as coffee at home. Part of how I reduced my intake was by letting my coffee supply at home run out. After a week, and a few coffee’s in cafes - I found what I missed most was the quiet moment with a cup of coffee at home.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I’ve built rituals around coffee. ie. writing and coffee&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I think more clearly in the morning&lt;em&gt;without&lt;/em&gt; the coffee. At least some of the time&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Tiredness and coffee are a bad combination. Where tiredness by itself I can work through. Also if I haven’t had coffee, I can usually nap.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;I &lt;em&gt;think&lt;/em&gt; - though I’m not sure yet - that I’m less grumpy and irritable without coffee.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All in all, I’d like to keep my coffee in take lower. I’m going to try and avoid the coffee absolutely every day habit, and have days I just have none.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s been a couple more weeks and I’m mostly back to a daily coffee habit but only 1 a day. I don’t have any beans in the house right now, which means that its not the  first thing I grab in the morning. I’m finding that makes it a more conscious choice… but also leaves me a bit unsettled sometimes when I want something hot to drink and I don’t have time to go out.&lt;/p&gt;

&lt;p&gt;I’m still sleeping better, probably partially due to reduced caffeine intake, and partially because I’m heading to bed earlier.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/2017/05/19/a-little-less-coffee&quot;&gt;A little less coffee&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on May 19, 2017.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Why I run]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/2017/04/24/why-i-run"/>
  <id>https://robbiemackay.com/2017/04/24/why-i-run</id>
  <published>2017-04-24T08:49:12+12:00</published>
  <updated>2017-04-24T08:49:12+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;This is far from complete but here’s a few thoughts on why I run.&lt;/p&gt;

&lt;h2 id=&quot;i-run-for-clarity&quot;&gt;I run for clarity&lt;/h2&gt;

&lt;p&gt;When I run my mind runs too. Its not empty but theres only one thing to do: run. So as I run it sort through the day, through the problems and often the obvious solutions finally dawn on me, or sometimes just clarity about the actual problem.&lt;/p&gt;

&lt;p&gt;I spent on day stressed out feeling like things just weren’t working and I wouldn’t possibly get everything done.  Within 2 mins of feet moving I realised the obvious things I missed: I have a team, why am I even doing some of these things myself when I have a team?!&lt;/p&gt;

&lt;h2 id=&quot;i-run-for-calm&quot;&gt;I run for calm&lt;/h2&gt;

&lt;p&gt;Running is meditative. To start with my mind chases random thoughts and ideas. After a while I can start to see past those. In a sitting meditation I focus on my breathing and watch it come and go. When I run its similar: I focus on my breathing and sometimes just the pain.  The burn in my legs, and effort to get oxygen demands my attention.&lt;/p&gt;

&lt;p&gt;I’ve learnt over years that when something happens that leaves me angry and fuming: it might be what happened or it might just be the day. Sometimes I can channel the anger into fixing something that really should have been dealt with a long time ago, but often trying to do that might upset someone and create a bigger mess. I never know. I run to calm down. Sometimes when I’m done there’s no anger left. Other times there’s still a spark but usually with more idea &lt;em&gt;why&lt;/em&gt; I’m annoyed and what I can do about it.&lt;/p&gt;

&lt;h2 id=&quot;i-run-to-go-further&quot;&gt;I run to go further&lt;/h2&gt;

&lt;p&gt;If I head out to hike there are plenty of spots that would take me all day to get there. I have to carry food, and more gear. But if I run I cover a 3 hour hike in maybe 1.5 hrs. I live near &lt;a href=&quot;https://en.wikipedia.org/wiki/Waitakere_Ranges&quot;&gt;Waitakere Ranges&lt;/a&gt;, running means I can disappear into the hills for a few hours and get to beautiful spots I’d otherwise miss.&lt;/p&gt;

&lt;h2 id=&quot;i-run-to-explore&quot;&gt;I run to explore&lt;/h2&gt;

&lt;p&gt;There’s a real joy to exploring. Just heading out of a trail with only a vague idea which path I’ll take. Sure I take a map and do some prep, but I have 3 or 4 options and I can just pick whatever looks most interesting when I get there.&lt;/p&gt;

&lt;h2 id=&quot;i-run-to-see-how-far-i-can-go&quot;&gt;I run to see how far I can go&lt;/h2&gt;

&lt;p&gt;I think this actually motivates me more than I notice. I love to just see how far I can get, how much it will hurt, where I’ll end up. This is the temptation to do an ultra, to do a triathlon, or just to enter that next race. Can I do it? Can I do it faster this time?&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/2017/04/24/why-i-run&quot;&gt;Why I run&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on April 24, 2017.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Adding optional parameters in Lumen routes]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/learned/2017/04/24/adding-optional-parameters-in-lumen-routes"/>
  <id>https://robbiemackay.com/learned/2017/04/24/adding-optional-parameters-in-lumen-routes</id>
  <published>2017-04-24T05:52:15+12:00</published>
  <updated>2017-04-24T05:52:15+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;I’ve been working on migrating &lt;a href=&quot;https://www.ushahidi.com&quot;&gt;Ushahidi&lt;/a&gt; from &lt;a href=&quot;https://kohanaframework.org/&quot;&gt;Kohana&lt;/a&gt; to &lt;a href=&quot;https://lumen.laravel.com&quot;&gt;Lumen&lt;/a&gt; recently. Lumen uses a &lt;a href=&quot;https://github.com/nikic/FastRoute&quot;&gt;FastRoute&lt;/a&gt; instead of Laravels core router. This is faster than the core route, but also more limited.&lt;/p&gt;

&lt;p&gt;Initially reading the &lt;a href=&quot;https://lumen.laravel.com/docs/5.4/routing&quot;&gt;documentation&lt;/a&gt; &lt;del&gt;it appears not to support optional URL parameters&lt;/del&gt; &lt;strong&gt;Optional URL parameters are now included in the routing docs&lt;/strong&gt;. But digging into the Fast Route docs it turns out there is some support:&lt;/p&gt;

&lt;blockquote&gt;
parts of the route enclosed in [...] are considered optional, so that &lt;code&gt;/foo[bar]&lt;/code&gt; will match both &lt;code&gt;/foo&lt;/code&gt; and &lt;code&gt;/foobar&lt;/code&gt;. Optional parts are only supported in a trailing position, not in the middle of a route.
&lt;/blockquote&gt;

&lt;p&gt;So you can do something like&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$app-&amp;gt;get(&apos;/config[/{id}]&apos;, &apos;SomeController&apos;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It also turns out that &lt;a href=&quot;https://github.com/laravel/lumen-framework/issues/608&quot;&gt;Lumen doesn’t strip trailing slashes&lt;/a&gt; when parsing URLs so the optional parameters were a useful workaround. I have a few routes like&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$app-&amp;gt;get(&apos;/config[/]&apos;, &apos;ConfigController@index&apos;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/learned/2017/04/24/adding-optional-parameters-in-lumen-routes&quot;&gt;Adding optional parameters in Lumen routes&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on April 24, 2017.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Handling login events with Sentry and AngularJS]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/learned/2017/03/20/handling-login-with-sentry-and-angular"/>
  <id>https://robbiemackay.com/learned/2017/03/20/handling-login-with-sentry-and-angular</id>
  <published>2017-03-20T00:00:00+13:00</published>
  <updated>2017-03-20T00:00:00+13:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;I added &lt;a href=&quot;sentry.io&quot;&gt;Sentry&lt;/a&gt; event tracking to &lt;a href=&quot;rollcall.io&quot;&gt;RollCall&lt;/a&gt; this morning. As part of
that I added some simple handling of login and logout events to set the current
user in the Sentry meta data.&lt;/p&gt;

&lt;p&gt;First we simple add Raven and - if we have a DSN set - configure it:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;raven-js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Load raven if configured&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;RAVEN_DSN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;RAVEN_DSN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;GIT_COMMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ENVIRONMENT&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;raven-js/plugins/angular&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;angular&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There’s some minor sugar in there to add both the environment and current git commit.
Both of these are set during the build process.&lt;/p&gt;

&lt;p&gt;To wire up log in/out events I added this little service&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;RavenService&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$rootScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ngInject&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$rootScope&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$rootScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$rootScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;auth.login&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$rootScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;auth.logout&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleLogout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isLoggedIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;handleLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;handleLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setUserContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;handleLogout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setUserContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;RavenService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And tied it all together in a simple module:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;raven-js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Load raven if configured&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;RAVEN_DSN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;RAVEN_DSN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;GIT_COMMIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ENVIRONMENT&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addPlugin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;raven-js/plugins/angular&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;angular&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ravenModule&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;angular&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;app.raven&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ngRaven&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;userModule&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Raven&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;ravenService&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ravenService&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ravenService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;RAVEN_DSN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;ravenService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}])&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ravenModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A few things to note:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I’m calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ravenService.init()&lt;/code&gt; in a run() block because that way we know that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user&lt;/code&gt; should be ready and we can check it starting state.&lt;/li&gt;
  &lt;li&gt;We already fire &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;auth.login&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;auth.logout&lt;/code&gt; events elsewhere in our code so
I know those just work.&lt;/li&gt;
&lt;/ul&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/learned/2017/03/20/handling-login-with-sentry-and-angular&quot;&gt;Handling login events with Sentry and AngularJS&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on March 20, 2017.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Auto deploying middleman via Travis-CI]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/learned/2016/07/16/auto-deploying-middleman-via-travis-ci"/>
  <id>https://robbiemackay.com/learned/2016/07/16/auto-deploying-middleman-via-travis-ci</id>
  <published>2016-07-16T13:02:00+12:00</published>
  <updated>2016-07-16T13:02:00+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;I spun up a &lt;a href=&quot;http://til.robbiemackay.com&quot;&gt;Today I Learned site&lt;/a&gt; based on &lt;a href=&quot;http://til.icelab.com.au/&quot;&gt;Today Icelab Learned&lt;/a&gt;. But I wanted a simple set up where any push would auto deploy, and I didn’t have to run some other service to do that. So a bit of quick Travis hacking with the help of &lt;a href=&quot;http://jeremy.jousse.fr/blog/2016-02-08-using-travis-to-deploy-middleman-on-github-pages.html&quot;&gt;this article&lt;/a&gt; and Travis is now building the site and deploying to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh-pages&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;The main additions are were adding NodeJS (as well as Ruby) and running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin/setup&lt;/code&gt; during install&lt;/p&gt;

&lt;h2 id=&quot;adding-nodejs-to-our-ruby-build&quot;&gt;Adding NodeJS to our ruby build&lt;/h2&gt;

&lt;p&gt;It turns out Travis already include NodeJS and nvm. So getting the version we want is super simple:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;before_install&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nvm install node&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here’s the final &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;ss&quot;&gt;rvm:
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;branches:
  only:
  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;master&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;cache: &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bundler&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;before_install:
  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nvm&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;install:
  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;before_script:
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;global&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;${GIT_NAME}&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;global&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;${GIT_EMAIL}&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;remote&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;origin&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;https&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:/&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rjmackay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;GH_TOKEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@github&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rjmackay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;til&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;git&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;script:
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundle&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;middleman&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deploy&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;env:
  global:
  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GIT_NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Your&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GIT_EMAIL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;you&lt;/span&gt;&lt;span class=&quot;vi&quot;&gt;@email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;com&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;secure: &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Insert encrypted GH_TOKEN here&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/learned/2016/07/16/auto-deploying-middleman-via-travis-ci&quot;&gt;Auto deploying middleman via Travis-CI&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on July 16, 2016.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Remote Working @ Gather]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/2014/07/14/remote-working-at-gather"/>
  <id>https://robbiemackay.com/2014/07/14/remote-working-at-gather</id>
  <updated>2014-07-14 19:49:07 +1200T00:00:00-00:00</updated>
  <published>2014-07-14T00:00:00+12:00</published>
  
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;The 3rd &lt;a href=&quot;http://gathergather.co.nz/&quot;&gt;Gather&lt;/a&gt; conference happened this Saturday. Despite having been to the last two and many of the previous Barcamp Auckland’s I’ve never run a session myself.. so I finally did:
“&lt;strong&gt;Remote working and distributed workplaces.&lt;/strong&gt; Lets talk about remote working. Good, bad and otherwise. Bring your problems and suggestions”&lt;/p&gt;

&lt;p&gt;I’ve been working remote for 2 1/2 years now, to start with from a coworking space, then later from home. But always very remote, the only Ushahidi staff member in NZ. I’ve had some great moments, and some low ones, and I think (hope) I’ve got better at remote work over time ..&lt;/p&gt;

&lt;p&gt;The general idea for this session was to share some of the common issues and wisdom around working remote. And hopefully get people to help each other out.&lt;/p&gt;

&lt;p&gt;All in all it went pretty well.. we were in the first slot of the day, not much of a hallway track so plenty of people showed. I talked for about 2 mins then left people to discuss. We spent a bit too long on the tools discussion.. and I didn’t pull that back in. But there was some good advice offered.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;https://twitter.com/lancewiggs&quot;&gt;Lance Wiggs&lt;/a&gt; for taking notes during the session. I grabbed some photos so here is a rough transcribed version..&lt;/p&gt;

&lt;h2 id=&quot;whiteboard-notes-secrets-of-remote-working&quot;&gt;Whiteboard notes: Secrets of Remote Working&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Get you timezones right
    &lt;ul&gt;
      &lt;li&gt;Do a proper shift handover&lt;/li&gt;
      &lt;li&gt;Use video for depth, context&lt;/li&gt;
      &lt;li&gt;Design teams with time zone crossover&lt;/li&gt;
      &lt;li&gt;Know your handover times&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Have explicit conversations/processes on how you wokr&lt;/li&gt;
  &lt;li&gt;Have a visit schedule to ensure constant interchange
    &lt;ul&gt;
      &lt;li&gt;Get everyone together periodically
        &lt;ul&gt;
          &lt;li&gt;Annual dev day&lt;/li&gt;
          &lt;li&gt;Second people to other offices - short and long times&lt;/li&gt;
          &lt;li&gt;Local, regional global gatherings&lt;/li&gt;
          &lt;li&gt;Functional gatherings&lt;/li&gt;
          &lt;li&gt;Training groups that are diverse&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Be aware &amp;amp; work constantly on culture
    &lt;ul&gt;
      &lt;li&gt;Make sure people know others cultures&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Pre-book flights so you know who is coming when&lt;/li&gt;
  &lt;li&gt;Have a system for passive comms&lt;/li&gt;
  &lt;li&gt;Break into manageable teams, groups&lt;/li&gt;
  &lt;li&gt;Create processes that work for you&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;tools&quot;&gt;Tools&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Check timezones: &lt;a href=&quot;http://time.is/&quot;&gt;time.is&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Collab
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com&quot;&gt;Github&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://phabricator.com/&quot;&gt;Phabricator&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://trello.com/&quot;&gt;Trello&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Team chat
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;http://slack.com/&quot;&gt;Slack&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://hipchat.com&quot;&gt;Hipchat&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;IRC&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.sqwiggle.com/&quot;&gt;Sqwiggle&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Audio
    &lt;ul&gt;
      &lt;li&gt;Skype&lt;/li&gt;
      &lt;li&gt;Telephone&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Video
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.sqwiggle.com/&quot;&gt;Sqwiggle&lt;/a&gt; (maybe more team chat)&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://zoom.us/&quot;&gt;Zoom.us&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;Google Hangouts&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Meeting / measurements
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.7geese.com&quot;&gt;7geese&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.small-improvements.com/&quot;&gt;small improvements&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://results.com&quot;&gt;results.com&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-else&quot;&gt;What else?&lt;/h2&gt;

&lt;p&gt;I knew we wouldn’t manage to cover everything. I realised as soon as the session finished I’d missed something I wanted to know about: how do people plan remote?&lt;/p&gt;

&lt;p&gt;Every year Ushahidi brings our team together for a week. Largely to touch base with each other, but also to do high level planning. This works alright but I’ve often wondered if doing a big sprint of planning in person prevents us figuring out how to plan remote. Things always change during the year, without notice, so some form of continuous planning while remote is necessary. How does anyone else do this?&lt;/p&gt;

&lt;h3 id=&quot;coming-back-from-breakdown&quot;&gt;Coming back from breakdown&lt;/h3&gt;

&lt;p&gt;Chatting at the pub after Gather another good question came from &lt;a href=&quot;https://twitter.com/wombleton&quot;&gt;wombleton&lt;/a&gt;: has anyone experienced broken, failing remote work and resolved it? what happened? how did they bring it back? Breakdown is easy to achieve: miscommunication, not including remote workers, silo’d info. There’s a lot of opportunity for making things difficult in remote work.. but I haven’t seen much about how to get things back to workability again if you hit that point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I’m pretty happy to have started discussion. Looking forward to doing it again at Gather next year, or elsewhere&lt;/strong&gt;&lt;/p&gt;


  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/2014/07/14/remote-working-at-gather&quot;&gt;Remote Working @ Gather&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on July 14, 2014.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Remote working]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/2014/04/21/remote-working"/>
  <id>https://robbiemackay.com/2014/04/21/remote-working</id>
  <published>2014-04-21T09:00:17+12:00</published>
  <updated>2014-04-21T09:00:17+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;My alarm goes off early.. I jump out of bed, a bit groggy and head for a quick 2 min shower.
Grab breakfast - a bowl of cereal.
Make coffee.
Head straight out to my office.
Open up the laptop, sign in and wait..&lt;/p&gt;

&lt;p&gt;Check a few emails, start to catch up on skype chats from last night.. keep waiting.&lt;/p&gt;

&lt;p&gt;Ping someone else: Is this call on?&lt;/p&gt;

&lt;p&gt;5 mins longer.. still no call.&lt;/p&gt;

&lt;p&gt;Check the calendar: Yup it’s right there in mine, good good.&lt;/p&gt;

&lt;p&gt;Check the team calendar.. OH &lt;strong&gt;it was 5 hours ago..&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;this-is-remote-working&quot;&gt;This is remote working..&lt;/h3&gt;

&lt;p&gt;Sometimes this is just how it goes. There over 20 of us, spread over 7 countries, we hit at least 7 timezones. Most of us work from home or a coworking space. We can’t all talk daily. Not even in chat. Some days you just don’t overlap. We can’t run video on our team calls: the bandwidth just doesn’t hold up to that.&lt;/p&gt;

&lt;p&gt;Our teams aren’t always grouped together: Crowdmap has 1 person in the US and 1 in South Korea. Ushahidi 3.0 has developers in Atlanta, Greensboro, Nairobi, Cape Town and Auckland.&lt;/p&gt;

&lt;p&gt;Sometimes I think we’re mad. But then I couldn’t work on what I do if we didn’t work this way.&lt;/p&gt;

&lt;p&gt;I get to live in New Zealand, close to family, often working at home with my 2 year old son. I get to work on open source software every day, With amazing users mapping corruption, environmental pollution, tracking violence and much more.&lt;/p&gt;

&lt;p&gt;Maybe we’d be more effective if we were all in the same place, or even in just one country, but we also wouldn’t be the same company. Our odd mix of staff from around the world, all passionate and dedicated to the work we’re doing.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/2014/04/21/remote-working&quot;&gt;Remote working&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on April 21, 2014.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Automating Behat and Mink tests with Travis CI]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/2013/05/03/automating-behat-and-mink-tests-with-travis-ci"/>
  <id>https://robbiemackay.com/2013/05/03/automating-behat-and-mink-tests-with-travis-ci</id>
  <published>2013-05-03T00:00:00+12:00</published>
  <updated>2013-05-03T00:00:00+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;I was excited to see Github now shows &lt;a href=&quot;https://github.com/blog/1484-check-the-status-of-your-branches&quot;&gt;build status branches&lt;/a&gt;. Even more so when I &lt;a href=&quot;https://github.com/bshaffer/oauth2-server-php/pull/112&quot;&gt;submitted code&lt;/a&gt; to an upstream library and was surprised by the tests results appearing in my pull request.&lt;/p&gt;

&lt;p&gt;So I jumped in to get it running for Ushahidi 3.0&lt;/p&gt;

&lt;p&gt;We’ve been running some tests through Jenkins already, but I’ve largely been doing manual runs locally. &lt;a href=&quot;https://travis-ci.org&quot;&gt;Travis-CI&lt;/a&gt; integrates with Github automatically, so I figured that was the easiest path to integration.&lt;/p&gt;

&lt;p&gt;First impression: &lt;strong&gt;its really really easy to get started&lt;/strong&gt;, and the docs were great.&lt;/p&gt;

&lt;h2 id=&quot;getting-started&quot;&gt;Getting started&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Log in with Github, turn on builds for the repo&lt;/li&gt;
  &lt;li&gt;Add .travis.yml file, configure the language, and PHP version to use&lt;/li&gt;
  &lt;li&gt;Push to github&lt;/li&gt;
  &lt;li&gt;Wait for builds to run&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;installing-behat-mink-and-guzzle&quot;&gt;Installing Behat, Mink and Guzzle.&lt;/h3&gt;

&lt;p&gt;We use &lt;a href=&quot;http://getcomposer.org&quot;&gt;composer&lt;/a&gt; to install &lt;a href=&quot;behat.org&quot;&gt;behat&lt;/a&gt;, &lt;a href=&quot;http://mink.behat.org/&quot;&gt;mink&lt;/a&gt; and guzzle. I had just been doing this locally anyway so that turned out to be easy. Just add:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;before_script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;composer install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;running-phpunit-and-behat&quot;&gt;Running PHPUnit and Behat&lt;/h3&gt;

&lt;p&gt;By default Travis-CI would just run PHPUnit. We use both PHPUnit and Behat so we have to run both. That’s as simple 2 extra lines in the config&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./bin/behat --config application/tests/behat.yml&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;phpunit -c application/tests/phpunit.xml&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;further-config&quot;&gt;Further config&lt;/h2&gt;

&lt;p&gt;The next steps get little trickier.&lt;/p&gt;

&lt;p&gt;Bootstrapping the DB wasn’t too bad. Add mysql to ‘services’ and add a couples of ‘before_script’ steps:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mysql&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;before_script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# db setup&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mysql -e &apos;create database lamu_test;&apos;&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mv application/config/database.travis application/config/database.php&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./minion --task=migrations:run --up&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;api-tests&quot;&gt;API tests&lt;/h3&gt;

&lt;p&gt;We’re running API tests by hitting a web server with &lt;a href=&quot;http://guzzlephp.org&quot;&gt;Guzzle&lt;/a&gt;. This means I need a web server running in my Travis-CI build. Theres a few docs on doing this for other projects but not so much PHP, and the &lt;a href=&quot;https://gist.github.com/roderik/3123962&quot;&gt;examples&lt;/a&gt; I found were ugly at best.&lt;/p&gt;

&lt;p&gt;In the end I’m running the built in PHP dev server, and restricting builds to PHP 5.4.&lt;/p&gt;

&lt;h3 id=&quot;final-script&quot;&gt;Final script&lt;/h3&gt;

&lt;p&gt;A few other bits of bootstrapping and I had working builds:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;language&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;php&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;php&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;5.4&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mysql&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;before_script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# install behat, mink etc&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;composer install --no-interaction --prefer-source&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Have to prefer source or hit github rate limit&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;git submodule update --init --recursive&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;# not really needed but makes sure submodules are there&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mkdir application/cache application/logs&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# create cache and log dirs&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;chmod 777 application/cache application/logs&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# set permission&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# db setup&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mysql -e &apos;create database lamu_test;&apos;&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mv application/config/database.travis application/config/database.php&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mv application/config/auth.travis application/config/auth.php&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./minion --task=migrations:run --up&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# webserver setup&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;php -S localhost:8000 httpdocs/index.php &amp;amp;&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sleep &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./bin/behat --config application/tests/behat.yml&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# run behat&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;phpunit -c application/tests/phpunit.xml&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# run php unit&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;not-quite-done&quot;&gt;Not quite done..&lt;/h2&gt;

&lt;p&gt;I quickly realised that my code actually had some issues:&lt;/p&gt;

&lt;h3 id=&quot;php-54&quot;&gt;PHP 5.4&lt;/h3&gt;

&lt;p&gt;I’ve been building on PHP 5.3, so immediatey hit a bunch of ‘Array to string conversion’ bugs in PHP 5.4. The main culprit for this was a bug in Kohana 3.3, so I’ve ported a rough fix from the develop branch.&lt;/p&gt;

&lt;h3 id=&quot;case-sensitivity&quot;&gt;Case sensitivity&lt;/h3&gt;

&lt;p&gt;I develop on OS X using a Vagrant box that mounts project code over NFS. The side effect of this is that my filesystem &lt;em&gt;isn’t really case sensitive&lt;/em&gt;. Kohana uses PSR-0 autoloading, so the filename and class names need to match.
The Travis builds run on a standard Ubuntu box: I suddenly hit errors about missing classes, etc.&lt;/p&gt;

&lt;p&gt;Fixing this was a bit slow and painful but actually a win in the long run. The first linux user to fire up the code base would have hit these issues immediately!&lt;/p&gt;

&lt;h2 id=&quot;done&quot;&gt;Done&lt;/h2&gt;
&lt;p&gt;In the end getting this set up took longer than expected, but I’m pretty pleased with the result. I’ve merged these changes into all my work-in-progress branches and fixed a few bugs as a result already. I’ll call that success.&lt;/p&gt;


  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/2013/05/03/automating-behat-and-mink-tests-with-travis-ci&quot;&gt;Automating Behat and Mink tests with Travis CI&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on May 03, 2013.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[API wrangling]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/2013/04/11/api-wrangling"/>
  <id>https://robbiemackay.com/2013/04/11/api-wrangling</id>
  <published>2013-04-11T00:00:00+12:00</published>
  <updated>2013-04-11T00:00:00+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;Following on from my &lt;a href=&quot;http://blog.ushahidi.com/2013/03/21/building-ushahidi-3-0/&quot;&gt;Building 3.0&lt;/a&gt; blog post, here’s another update on Ushahidi 3.0.&lt;/p&gt;

&lt;p&gt;We’re currently still pushing on finishing the 3.0 API, or at least the first cut at it. The original due date for this was March 30, but thats slipped to mid April. Conversations have quieted down a little as we get to work on &lt;em&gt;getting things done&lt;/em&gt;. Thats good, but means we need to keep working hard to keep the community up to date on our progress.&lt;/p&gt;

&lt;h2 id=&quot;api-design-primer&quot;&gt;API design primer&lt;/h2&gt;

&lt;p&gt;Designing an API seemed simple.. but once you get into the weeds and start building things there are a lot of questions to answer. I’ve done a chunk of reading as I tried to figure out 1. what a proper RESTful approach would look like, 2. what’s normal practice, ie. where do developers often cut corners? why? is this good or bad?&lt;/p&gt;

&lt;p&gt;A few valuable resources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://info.apigee.com/Portals/62317/docs/web%20api.pdf&quot;&gt;Web API Design&lt;/a&gt; from apigee&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/WhiteHouse/api-standards&quot;&gt;Whitehouse API standards&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;progress&quot;&gt;Progress&lt;/h2&gt;

&lt;p&gt;The last couple of weeks have been dominated by the thousands of tiny decisions made at each step of building the API. I’ve tried to keep the wiki updated with the &lt;a href=&quot;https://wiki.ushahidi.com/display/WIKI/REST+API#RESTAPI-GeneralPatterns&quot;&gt;general patterns&lt;/a&gt; of our API. This gives a few guidelines&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;What methods to use, and how to accomodate more complex queries (ie. search)&lt;/li&gt;
  &lt;li&gt;What HTTP response codes to use&lt;/li&gt;
  &lt;li&gt;What to cover in functional tests&lt;/li&gt;
  &lt;li&gt;How to expose relations and links beteen resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ve got the basics in now: forms, with their attributes and group, and posts. This gives us enough to start experimenting, but there are still a lot of loose ends. The next things we’re looking at are: &lt;a href=&quot;https://github.com/ushahidi/Lamu/issues/3&quot;&gt;sets&lt;/a&gt;, &lt;a href=&quot;https://github.com/ushahidi/Lamu/issues/14&quot;&gt;tags&lt;/a&gt;, &lt;a href=&quot;https://github.com/ushahidi/Lamu/issues/17&quot;&gt;users&lt;/a&gt; - along with their roles and permissions - and extensions to posts - adding &lt;a href=&quot;https://github.com/ushahidi/Lamu/issues/29&quot;&gt;revisions&lt;/a&gt;, &lt;a href=&quot;https://github.com/ushahidi/Lamu/issues/28&quot;&gt;translations&lt;/a&gt; and &lt;a href=&quot;https://github.com/ushahidi/Lamu/issues/26&quot;&gt;updates&lt;/a&gt;. I’ve built out most of the &lt;a href=&quot;https://github.com/ushahidi/Lamu/pull/41&quot;&gt;translations and revisions support&lt;/a&gt; already, but it still needs polish and documentation.&lt;/p&gt;

&lt;h2 id=&quot;authentication&quot;&gt;Authentication&lt;/h2&gt;

&lt;p&gt;This is probably the next major decision. How do we handle API authentication? do we use OAuth? 1.0 or 2.0?
Where do we handle actual user login/registration?… the entire app is going to be built on the API.&lt;/p&gt;

&lt;p&gt;At the moment I’m leaning towards OAuth 2.0, primarily because its what &lt;a href=&quot;https://wiki.ushahidi.com/display/WIKI/SwiftRiver+API+Authentication&quot;&gt;Swiftriver uses&lt;/a&gt;, and consistency between products is important. However OAuth 2.0 has some issues:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the editor for the spec &lt;a href=&quot;http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/&quot;&gt;withdrew&lt;/a&gt; &lt;a href=&quot;http://hueniverse.com/2012/07/on-leaving-oauth/&quot;&gt;saying&lt;/a&gt; OAuth 2 had failed&lt;/li&gt;
  &lt;li&gt;there are a few ways to &lt;a href=&quot;http://www.theregister.co.uk/2011/02/02/facebook_plugs_authentication_flaw/&quot;&gt;mess&lt;/a&gt; &lt;a href=&quot;http://stephensclafani.com/2011/04/06/oauth-2-0-csrf-vulnerability/&quot;&gt;up&lt;/a&gt; &lt;a href=&quot;http://www.thread-safe.com/2012/02/more-on-oauth-implicit-flow-application.html&quot;&gt;an&lt;/a&gt; &lt;a href=&quot;http://homakov.blogspot.co.nz/2012/07/saferweb-most-common-oauth2.html&quot;&gt;implementation&lt;/a&gt; security wise&lt;/li&gt;
  &lt;li&gt;and one implementation isn’t guaranteed to be interoperable with another&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That said the many &lt;em&gt;almost-oauth&lt;/em&gt; APIs out there probably have more, and similar problems: rolling our own is not an option.&lt;/p&gt;

&lt;p&gt;OAuth 2 is probably still going to get a lot of use, and there are &lt;a href=&quot;https://blog.apigee.com/taglist/oauth&quot;&gt;good resources&lt;/a&gt; appearing on how to do it right, and a couple of good &lt;a href=&quot;https://github.com/andreassolberg/jso&quot;&gt;oauth2&lt;/a&gt; &lt;a href=&quot;https://github.com/adoy/PHP-OAuth2&quot;&gt;clients&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One &lt;a href=&quot;https://blog.apigee.com/detail/oauth_is_it_worth_the_effort/&quot;&gt;recommendation&lt;/a&gt; that stuck out was “If your API can require HTTPS, use OAuth 2.0 with bearer tokens. Otherwise, use OAuth 1.0a”. I need to dig into the details of this, but given deployers won’t always use SSL this is worth considering.&lt;/p&gt;

&lt;h2 id=&quot;stumbling-blocks&quot;&gt;Stumbling blocks&lt;/h2&gt;

&lt;p&gt;In my last post I mentioned adding support for other databases, particularly PostgreSQL/PostGIS. I’ve already hit the first snag with this: &lt;a href=&quot;https://github.com/kohana-minion/tasks-migrations&quot;&gt;minion migrations&lt;/a&gt; doesn’t handle other database engines &lt;strong&gt;at all&lt;/strong&gt;. There are a few forks on github that try to solve this, but its mixed in with some other major changes. This isn’t a show stopper, but there’s some unpicking to be done and for now we’re concentrating on building a working API.&lt;/p&gt;

&lt;p&gt;If anyone has working PostGIS knowledge and whats to have a go at getting this working, grab &lt;a href=&quot;https://github.com/ushahidi/Lamu&quot;&gt;the code&lt;/a&gt;, &lt;a href=&quot;https://github.com/ushahidi/Lamu/issues/25&quot;&gt;leave a note&lt;/a&gt; and hopefully send a pull request. I’m happy to walk you through the existing code and answer questions.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/2013/04/11/api-wrangling&quot;&gt;API wrangling&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on April 11, 2013.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Improving Ushahidi Bug Triage]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/2013/04/09/improving-ushahidi-bug-triage"/>
  <id>https://robbiemackay.com/2013/04/09/improving-ushahidi-bug-triage</id>
  <published>2013-04-09T00:00:00+12:00</published>
  <updated>2013-04-09T00:00:00+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;I’ve been thinking around how we manage our bug and features backlogs.
The current Ushahidi 2.x backlogs have 144 features, and 47 Open bugs (even more last week before our bug fix sprint). At this size these start to get a little unweildy and feel overwhelming.&lt;/p&gt;

&lt;p&gt;My previous experience with Kanban and other agile methods has demonstrated that limiting work-in-progress, can make life for developers and customers much easier. It reduces the number of things you need to think about, and the amount of time spent on work that hasn’t yet shipped.&lt;/p&gt;

&lt;p&gt;I recently read &lt;a href=&quot;http://www.joelonsoftware.com/items/2012/07/09.html&quot;&gt;joelonsoftware&lt;/a&gt; talking about software inventory and I’ve been thinking about how this could be applied to Ushahidi.
We’re building open source software, and delivering a long lived product, not just a one off project, so not everything transfers perfectly.&lt;/p&gt;

&lt;p&gt;For instance &lt;em&gt;“Do not allow more than two weeks (in fix time) of bugs to get into the bug database”&lt;/em&gt; just doesn’t work for us. Our users can add bugs directly themselves and we have no desire to change that, and our pace is slower as our resources are stretched.&lt;/p&gt;

&lt;p&gt;However we still have a  large amount of what could be described as ‘software inventory’ thats built or managed by the core team. Bug queues, feature queues, partially complete code branches, completed work waiting for QA, completed work waiting for release. We need all of these, but when they grow too large they become significantly less useful. Looking at a list of 144 features.. its much harder to know which ones are important, similarly with bugs: we still have issues in the system from 6 months ago.&lt;/p&gt;

&lt;p&gt;For bug tracking: &lt;strong&gt;what matters is are the bugs in github valid, fixable, and current.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some issues which have been in the system for many months, with little activity fail on both being not current, and probably no longer valid.
Other bugs are not fixable, not because its not technically possible, but because they’re low priorities (can be worked around) and our resources are limited - we could leave these bugs in the system, but a more honest response might be to close these and mark them as ‘wont fix’.&lt;/p&gt;

&lt;p&gt;Feature backlogs are a little different: if our users are happy to invest time in detailing a feature they need thats great. If that leads to large detailed backlog thats ok. What we still need to avoid is expending developer time scoping a feature that we don’t have time to build. Ushahidi 2.x is now a feature freeze so this is less of an issue, however I have no doubt we’re going to have to look at this again with Ushahidi 3.0.&lt;/p&gt;

&lt;p&gt;I’ve also been guilty of expanding the feature backlog myself by dropping every idea I have into a 2 sec feature ticket. This is useful initially, but over time its just filling the backlog with things that aren’t really useful, and maybe just unneeded by our users.&lt;/p&gt;

&lt;p&gt;Those watching the github issues will have noticed a recent flurry of closing tickets.. this isn’t a major change in behaviour. But it reflects a recent bug fix sprint and a push to close invalid bugs as mentioned above.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You closed my bug, but its not fixed. What should I do?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you think we’ve closed an issue thats still important for you, just let us know: comment on the ticket (and maybe reopen it). The worst thing you could do here would be to ignore it, and decide we don’t care. We simply don’t always know if you’re waiting patiently on an issues, or is you’ve forgotten about it and moved on. Give us an update!&lt;/p&gt;


  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/2013/04/09/improving-ushahidi-bug-triage&quot;&gt;Improving Ushahidi Bug Triage&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on April 09, 2013.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Building custom blocks in Ushahidi]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/2012/12/24/custom-blocks-in-ushahidi"/>
  <id>https://robbiemackay.com/2012/12/24/custom-blocks-in-ushahidi</id>
  <published>2012-12-24T00:00:00+13:00</published>
  <updated>2012-12-24T00:00:00+13:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;I’ve been meaning to write this up for a while. Adding custom blocks to Ushahidi is a fairly common request
but generally requires a developer, or at least some basic coding skills. However for some basic use cases
it should be possible to add a block with a bit of cut and paste scripting.&lt;/p&gt;

&lt;p&gt;To add a block you’ll need to create a plugin. This is actually less complicated than it sounds.
In your Ushahidi install find the directory ‘plugins’ and create a new folder. The structure is like this:&lt;/p&gt;

&lt;pre&gt;
/plugins
  /my-custom-blocks
    readme.txt
    /hooks
      register_category_blocks.php
    /views
      category_block.php
&lt;/pre&gt;

&lt;p&gt;In more complicated plugins we might also have libraries, controllers, helpers or anything else that exists
in the usual Kohana module structure. But for this simple case lets still to just hooks and views.&lt;/p&gt;

&lt;h3 id=&quot;readmetxt&quot;&gt;readme.txt&lt;/h3&gt;
&lt;p&gt;The readme file is required for Ushahidi to pick up the plugin at all. The first section of this file is parsed for plugin name, description and other details used in the Ushahidi admin.&lt;/p&gt;

&lt;pre&gt;
=== About ===
name: Category Block
website: http://www.ushahidi.com
description: Adds custom category blocks
version: 0.1
requires: 2.5
tested up to: 2.5
author: Ushahidi Team
author website: http://www.ushahidi.com

Add any other docs here
&lt;/pre&gt;

&lt;h3 id=&quot;hooksregister_category_blocksphp&quot;&gt;hooks/register_category_blocks.php&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;defined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;SYSPATH&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;die&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;No direct script access.&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Start wildlife category block&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;category_wildlife_block&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// CHANGE THIS FOR OTHER BLOCKS&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;c1&quot;&gt;// Array of block params&lt;/span&gt;
		&lt;span class=&quot;nv&quot;&gt;$block&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;s2&quot;&gt;&quot;classname&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;category_wildlife_block&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Must match class name above&lt;/span&gt;
			&lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Wildlife Reports&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;s2&quot;&gt;&quot;description&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;List the 10 latest reports in the wildlife category&quot;&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;c1&quot;&gt;// register block with core, this makes it available to users &lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;blocks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;c1&quot;&gt;// Load the reports block view&lt;/span&gt;
		&lt;span class=&quot;nv&quot;&gt;$content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;blocks/category_wildlife_block&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// CHANGE THIS IF YOU WANT A DIFFERENT VIEW&lt;/span&gt;
		
		&lt;span class=&quot;c1&quot;&gt;// ID of the category we&apos;re looking for&lt;/span&gt;
		&lt;span class=&quot;nv&quot;&gt;$category_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// CHANGE THIS&lt;/span&gt;

		&lt;span class=&quot;c1&quot;&gt;// Get Reports&lt;/span&gt;
		&lt;span class=&quot;nv&quot;&gt;$content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incidents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ORM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;incident&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;location&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;incident_category&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;incident.id&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;incident_category.incident_id&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;incident_active&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;category_id&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$category_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;10&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;orderby&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;incident_date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;desc&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

		&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;category_wildlife_block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;viewscategory_blockphp&quot;&gt;views/category_block.php&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html-php&quot; data-lang=&quot;html+php&quot;&gt;&amp;lt;?php blocks::open(&quot;reports&quot;);?&amp;gt;
&amp;lt;?php blocks::title(Kohana::lang(&apos;ui_main.reports_listed&apos;));?&amp;gt;
&amp;lt;table class=&quot;table-list&quot;&amp;gt;
	&amp;lt;thead&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;th scope=&quot;col&quot; class=&quot;title&quot;&amp;gt;&amp;lt;?php echo Kohana::lang(&apos;ui_main.title&apos;); ?&amp;gt;&amp;lt;/th&amp;gt;
			&amp;lt;th scope=&quot;col&quot; class=&quot;location&quot;&amp;gt;&amp;lt;?php echo Kohana::lang(&apos;ui_main.location&apos;); ?&amp;gt;&amp;lt;/th&amp;gt;
			&amp;lt;th scope=&quot;col&quot; class=&quot;date&quot;&amp;gt;&amp;lt;?php echo Kohana::lang(&apos;ui_main.date&apos;); ?&amp;gt;&amp;lt;/th&amp;gt;
		&amp;lt;/tr&amp;gt;
	&amp;lt;/thead&amp;gt;
	&amp;lt;tbody&amp;gt;
		&amp;lt;?php
		if ($incidents-&amp;gt;count() == 0)
		{
			?&amp;gt;
			&amp;lt;tr&amp;gt;&amp;lt;td colspan=&quot;3&quot;&amp;gt;&amp;lt;?php echo Kohana::lang(&apos;ui_main.no_reports&apos;); ?&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
			&amp;lt;?php
		}
		foreach ($incidents as $incident)
		{
			$incident_id = $incident-&amp;gt;id;
			$incident_title = text::limit_chars(strip_tags($incident-&amp;gt;incident_title), 40, &apos;...&apos;, True);
			$incident_date = $incident-&amp;gt;incident_date;
			$incident_date = date(&apos;M j Y&apos;, strtotime($incident-&amp;gt;incident_date));
			$incident_location = $incident-&amp;gt;location-&amp;gt;location_name;
		?&amp;gt;
		&amp;lt;tr&amp;gt;
			&amp;lt;td&amp;gt;&amp;lt;a href=&quot;&amp;lt;?php echo url::site() . &apos;reports/view/&apos; . $incident_id; ?&amp;gt;&quot;&amp;gt; &amp;lt;?php echo html::specialchars($incident_title) ?&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;&amp;lt;?php echo html::specialchars($incident_location) ?&amp;gt;&amp;lt;/td&amp;gt;
			&amp;lt;td&amp;gt;&amp;lt;?php echo $incident_date; ?&amp;gt;&amp;lt;/td&amp;gt;
		&amp;lt;/tr&amp;gt;
		&amp;lt;?php
		}
		?&amp;gt;
	&amp;lt;/tbody&amp;gt;
&amp;lt;/table&amp;gt;
&amp;lt;a class=&quot;more&quot; href=&quot;&amp;lt;?php echo url::site() . &apos;reports/&apos; ?&amp;gt;&quot;&amp;gt;&amp;lt;?php echo Kohana::lang(&apos;ui_main.view_more&apos;); ?&amp;gt;&amp;lt;/a&amp;gt;
&amp;lt;div style=&quot;clear:both;&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;?php blocks::close();?&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;so-how-does-this-work&quot;&gt;So how does this work?&lt;/h2&gt;

&lt;p&gt;The hook ‘register_category_blocks.php’ is included by Ushahidi (and Kohana). This hook registers the ‘Wildlife Reports’ block with Ushahidi core by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blocks::register()&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Array of block params&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$block&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;classname&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;category_wildlife_block&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Must match class name above&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;name&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Wildlife Reports&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;description&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;List the 10 latest reports in the wildlife category&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// register block with core, this makes it available to users&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;blocks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The array passed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blocks::register()&lt;/code&gt; tells Ushahidi the plugin name, description, and where to find the plugin content.&lt;/p&gt;

&lt;p&gt;When the plugin is rendered, Ushahidi will call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;category_wildlife_blocks::block()&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Load the reports block view&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;blocks/category_wildlife_block&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// CHANGE THIS IF YOU WANT A DIFFERENT VIEW&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// ID of the category we&apos;re looking for&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$category_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// CHANGE THIS&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Get Reports&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incidents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ORM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;incident&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;location&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;incident_category&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;incident.id&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;incident_category.incident_id&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;incident_active&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;category_id&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$category_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;limit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;10&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;orderby&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;incident_date&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;desc&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;find_all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This loads the view &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blocks/category_wildlife_block.php&lt;/code&gt; and passes it a list of incidents: the last 10 incidents with category ID = 7.&lt;/p&gt;

&lt;h2 id=&quot;tweaking-it&quot;&gt;Tweaking it&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Change the category ID - just change line 24 of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;register_category_blocks.php&lt;/code&gt;. You might also want to change the name and class for the block too.&lt;/li&gt;
  &lt;li&gt;Change the html in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;category_wildlife_block.php&lt;/code&gt; - if you want to tweak the output slightly you can easily change it here&lt;/li&gt;
  &lt;li&gt;Filter the incidents by something else - change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;where()&lt;/code&gt; call on line 30 of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;register_category_blocks.php&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Load images or similar - I’ll post an example for this in the new year…&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;see-also&quot;&gt;See also&lt;/h2&gt;

&lt;p&gt;Grab the &lt;a href=&quot;http://gist.github.com/3291463&quot;&gt;Gist&lt;/a&gt; of all the example code.&lt;/p&gt;

&lt;p&gt;See also: &lt;a href=&quot;https://wiki.ushahidi.com/display/WIKI/Plugins+-+Developers+Guide&quot;&gt;wiki docs on creating Ushahidi plugins&lt;/a&gt;&lt;/p&gt;


  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/2012/12/24/custom-blocks-in-ushahidi&quot;&gt;Building custom blocks in Ushahidi&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on December 24, 2012.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Installing Ubuntu 12.04 on a Macbook Pro 8,2]]></title>
  <link rel="alternate" type="text/html" href="https://robbiemackay.com/2012/08/13/ubuntu-12.04-install-on-macbook-pro-8,2"/>
  <id>https://robbiemackay.com/2012/08/13/ubuntu-12.04-install-on-macbook-pro-8,2</id>
  <published>2012-08-13T00:00:00+12:00</published>
  <updated>2012-08-13T00:00:00+12:00</updated>
  <author>
    <name>Robbie Mackay</name>
    <uri>https://robbiemackay.com</uri>
    <email>rm@robbiemackay.com</email>
  </author>
  <content type="html">&lt;p&gt;This has been waiting around for a while so I’ll give it a quick clean up and hit publish. Unfortunately because its been waiting a while I might have missed some details but I wouldn’t remember now.&lt;/p&gt;

&lt;p&gt;Thankfully the notes on &lt;a href=&quot;https://help.ubuntu.com/community/MacBookPro8-2/Oneiric&quot;&gt;help.ubuntu.com&lt;/a&gt; have vastly improved since I first tried this, so check those out first.&lt;/p&gt;

&lt;h3 id=&quot;weirdest-part-of-the-whole-thing&quot;&gt;Weirdest part of the whole thing&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Use both USB and CD installer&lt;/strong&gt;.
It took me a while to find this out, but they only way to get the installer to boot properly is to use the same install image on both a USB key and CD at the same time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;what-i-did&quot;&gt;What I did:&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;Resize the OSX partition with disk utility&lt;/li&gt;
  &lt;li&gt;Create an MSDos partition&lt;/li&gt;
  &lt;li&gt;Install &lt;a href=&quot;http://refit.sourceforge.net/&quot;&gt;rEFIT&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Boot the installer using both USB and CD&lt;/li&gt;
  &lt;li&gt;Install ubuntu as usual&amp;lt;ul&amp;gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;Delete msdos partition and replace with ext4&lt;/li&gt;
&lt;li&gt;Install the MBR onto sda5 (ie. the linux ext4 partition)&lt;/li&gt;
&lt;li&gt;You can probably skip creating the swap, I had to delete it later, but with 8GB of ram it wasn&apos;t an issue.&lt;/li&gt;
&lt;p&gt;&amp;lt;/ul&amp;gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Sync MBR/partition table (using refit)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;fails to boot&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Boot LiveCD (+USB) again&lt;/li&gt;
  &lt;li&gt;Delete swap partition (Probably could have skipped this to start with and it would have gone better)&lt;/li&gt;
  &lt;li&gt;Restart&lt;/li&gt;
  &lt;li&gt;Sync partition table (using refit)&lt;/li&gt;
  &lt;li&gt;Restart&lt;/li&gt;
  &lt;li&gt;Boot linux&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;works&lt;/strong&gt; Successful boot, yay!&lt;/li&gt;
  &lt;li&gt;Add ppa for &lt;a href=&quot;https://help.ubuntu.com/community/MacBookPro8-2/Oneiric#Wireless&quot;&gt;wireless driver&lt;/a&gt; (installing using ethernet)&lt;/li&gt;
  &lt;li&gt;reboot&lt;/li&gt;
  &lt;li&gt;wireless works (no extra hacking)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;extra-packages-to-installconfigure&quot;&gt;Extra packages to install/configure:&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.ubuntu.com/community/MacBookPro8-2/Oneiric#Sensors&quot;&gt;macfanctld&lt;/a&gt;
&lt;strong&gt;Absolutely essential unless you want to cook your CPU.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;natural scrolling&lt;/li&gt;
  &lt;li&gt;other &lt;a href=&quot;https://help.ubuntu.com/community/MacBookPro8-2/Oneiric#Touchpad&quot;&gt;synaptics wrangling&lt;/a&gt; - definitely worth it&lt;/li&gt;
  &lt;li&gt;enable extra drivers (?)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll have to go find more info to document these last bits properly.. however I’m back on OSX so it’ll need to wait for a reboot.&lt;/p&gt;

  &lt;p&gt;&lt;a href=&quot;https://robbiemackay.com/2012/08/13/ubuntu-12.04-install-on-macbook-pro-8,2&quot;&gt;Installing Ubuntu 12.04 on a Macbook Pro 8,2&lt;/a&gt; was originally published by Robbie Mackay at &lt;a href=&quot;https://robbiemackay.com&quot;&gt;Robbie Mackay&lt;/a&gt; on August 13, 2012.&lt;/p&gt;</content>
</entry>

</feed>
