Hello 👋 I'm Dan.

I do Cloud DevOps and write PHP. I also care about web performance and security.

I never talk about my birthday, but when your girlfriend makes a cake this epic how can you not brag?!

Had my first session of laser tattoo removal today. Found that it was a little more painful that getting a tattoo, but so much quicker. It took longer to go through all the paperwork and discussions at the start of the appointment than it did for the removal itself!

Getting a few small ones on my arm lasered to make way for a sleeve tattoo. I definitely don’t regret those other tattoos I had, just regret the placement. Lesson for next time!

Hello New Blog

After many, many years of being dissatisfied with having to use a CMS for maintaining my blog I’ve finally switched to a static site generator.

Having to manage a CMS was a total drainer. I don’t want to have to deal with updates, login bruteforcing attacks, or ensuring my site still works because of a change under the hood.

Goodbye, WordPress. You were pretty good, but not the best tool for me. Hello, Hugo.

Hugo

Hugo is a static site generator written in Go. It’s fast, powerful, and offers a number of conveniences that I really like… which leads me to the following:

Hugo Pipes

I’m using Hugo Pipes to build build my SCSS files, run them through PostCSS, then minify and generate a subresource integrity hash.

It’s so easy in fact, that my entire CSS stack is built during rendering of Hugo:

{{ $css := resources.Get "scss/index.scss" | resources.ToCSS (dict "targetPath" "css/build.css") | resources.PostCSS | resources.Fingerprint "sha512" }}
<link rel="stylesheet" href="{{ $css.Permalink }}" integrity="{{ $css.Data.Integrity }}" />

I love this because it means I don’t have to have a build tool or task runner like webpack, Gulp, Grunt, etc to handle compiling my assets. Every additional dependency used in your site (or project for that matter) is an exponentially increasing burden for you to manage. Maintaining a site should easy!

Shortcodes

A number of static site generators I played with had little to no support for HTML in Markdown files. To me this is an absolute necessity. The trivial convenience of being able to easily add a GitHub Gist to being able to add my own shortcodes to handle HTML <figure>s was a really big bonus for me. Why some static site generators choose to not allow HTML or not have support for some sort of shortcode is beyond me.

Micropub

The Micropub protocol is really taking off. IndieWeb, a community of people aiming to make the web more people-centric (as opposed to more corporate and siloed), came up with the Micropub protocol to make it really easy for one to create, update, and delete content on your own site. This means that even if you change from one CMS to another, or change from a CMS to a static site generator, you can still use the same apps and workflow that you would’ve used previous to the infrastructure transition.

So how does this tie in to the static site generator?

Well, I did what every typical programmer does, and made my own Micropub endpoint. Written in PHP (my go to) and built on the Lumen micro-framework it has support for photo uploads and new posts. My plan is to clean it up a bit and open-source it. Post editing and deleting needs to be added too, but it’s not as important for me.

Rest of the Site

I’ve gone even more minimalist.

  • Basic design.
  • No custom fonts.
  • No JavaScript (where possible, YouTube and Instagram are hold outs).
  • No tracking or analytics of any kind (regrettably excluding those from the above sites).

2017 and 2018 were (and are) interesting years for the web. Web tracking and analytics have gone beyond fucking creepy. Sites are becoming increasingly larger per request, with an excess of JavaScript tracking tools burning CPU cycles, draining batteries (if applicable), and chewing through data like there’s no tomorrow. I don’t like that web, and I don’t want to be a part of it.

Just yesterday I was looking at a single-page site built on a popular hosted site builder that weighed in at just under 7.5 MB. Seven point five fucking megabytes. For a single page website with a handful of images and a buttload of JavaScript being injected into the site.

Us developers have a responsibility to make the web a friendly place for all users, regardless of their device or internet speed. There’s no reason a site with predominently text and a few images should take up more than 3 MB. And yet here we are in a time where major sites who well and truly have the budget to invest in a properly-engineered site abuse the internet pipes we’ve come to take for granted. It’s not hard, it just takes empathy for the machine.

Micro-blogging to the Rescue

Previously this site was long-form content and YouTube music videos only. My thoughts were relegated to third-party platforms like Twitter. Ownership of data is important. Really fucking important. Manton Reece is right on the money when he explains why he made Micro.blog. Algorithmic timelines suck. Ads suck.

I want my content to be portable. To remain on a platform I control. Because I control the entire stack I don’t have to be concerned with the direction of the site, or dissatisfied with how a site is being run.

Because of this, my blog will contain short-form, long-form, image posting, and links. All in the one feed and all in the one spot. I hope you, the reader, like the new direction of the site.

I think this is the best photo I’ve ever taken. Shot recently in Tasmania with a Nikon D something something.

Redid the blog. It’s built with Hugo and supports Micropub posting with my own Micropub endpoint (which I’ll release soon). Loving the speed I get from this site!

A Reflection on Perth

I’ve lived in Perth for just over three years and on this coming Monday I’ll be moving back to my original home of Melbourne, Victoria, and to join my girlfriend (who moved a few weeks earlier for work). It’s been an amazing experience living in one of the most isolated capital cities in the world, and one I will not forget.

Location and Career Change

Before I moved to Perth I was working as a Mac technician and SME consultant. I’d done web development on and off since 2005 but it was always as a side project and just a bit of fun. I had no intention of continuing to be a technician/SME consultant in Perth so a career change was in order. I’ve done web development as a hobby for a long time, so why not make a career out of it.

Sometimes turning a hobby into a job can take all the fun out of it. I love going to the gym and keeping fit, but I know I would never want to become a personal trainer, let alone work in a gym. Thankfully turning web development from a hobby into a career did not meet that unfortunate demise.

Web Developer, Officially!

My first job was handling the entire development process where I worked with some amazing talent in Perth. Henry Luong, Daniel Elliot, and Ryan Vincent were all really clever designers and it was a great experience to try and turn their designs into a reality. I knew that I was definitely on the right path, but I found I enjoyed more of the backend process. Dealing with browser quirks for the frontend frustrated me. I knew that I’d prefer to handle the backend side of things, and a year later got the opportunity of a lifetime to work at Humaan.

A defector outside Defectors. Perfect.

A defector outside Defectors. Perfect 👌

My last day at Humaan was yesterday but I was there for just under two years. Working with the team there has been an incredible experience and I’ve had the pleasure of working on some really cool projects, one of which is easily the biggest project I’ve ever got to work on. The team at Humaan are amazing and I feel truly honoured to have worked with them all for two years. It was easily the best job I’ve ever had. You know it’s a great job when you’re excited to go to work every day.

Just managed to avoid singeing my hair on the birthday cake.

Just managed to avoid singeing my hair on the birthday cake.

Awards, awards, and more awards!

Awards, awards, and more awards!

Web Directions 2015.  My first ever conference.  It was amazing!

Web Directions 2015. My first ever conference. It was amazing!

I’ve made some lifelong friends at Humaan and while it pains me to leave such an experienced team, it’s time to move on back home.

The Perth Web Community

When I moved to Perth and trying to immerse myself into the web scene I found a group on meetup.com called Front End Web Developers Perth (or just Fenders for short). There I met some really amazing people and learnt a tremendous amount of things!

The leader of the group, Mandy Michael (who I can neither confirm nor deny is also Batmandy) deserves special recognition. She built up a community that is super friendly, helpful, and supportive. Mandy gave me opportunities where I got to do a number of presentations, run a workshop, and be a judge for a competition. I am forever thankful to Mandy for those opportunities. I honestly believe the Perth web development community wouldn’t be the same without Mandy’s incredibly hard work and commitment to setting up the group, organising events, and just generally being an all-round superstar. Three cheers to Mandy!

Patima Tantiprasut also deserves a special mention, her infectious energy and personality drives Localhost. I honestly have no idea how Patima manages to do so many things but also remain the most energetic person I’ve ever met. Thank you Pats, you’re awesome!

Melbourne Bound

As I write this it’s Saturday evening. On Monday I fly back to Melbourne and start the next chapter of my life. I’ve got a gig as a developer for a small boutique development agency where I’ll be doing more PHP , Vue.js and probably some Golang! I’m super excited to see what comes next.

Tracking Envoyer Releases in Sentry

Note: this article I wrote originally appeared on the Humaan blog.

Dan looking out from a Sentry tower

Tracking down bugs can be hard. Damn hard. And figuring out how or when they cropped up in the first place can be even harder. Recently, we launched our social media aggregator platform, Waaffle. It’s written in Laravel and deployed with Envoyer, but we also took the opportunity to try out Sentry for tracking bugs.

Spoiler alert: it was awesome.

Releases in a Sentry issue

One of the features I really like is the ability to track releases, which means you can tell at a glance which release was responsible for your bug. We’ve got a deployment hook in Envoyer that pings Sentry when we deploy a new release. Our hook runs in the “After” section of the “Activate New Release” action and contains the following command:

curl https://sentry.io/api/hooks/release/builtin/project_id/project_webhook_token/ \
-X POST -H 'Content-Type: application/json' -d '{"version": "{{ sha }}"}'

(FYI, it’s the very last post-deployment hook we run, just in case another hook fails.)

The Sentry PHP package includes a section in the config for specifying your app version. However, things can get tricky if, like us, you’re using, say, git commit hashes instead of version numbers.

Thankfully, Sentry’s Laravel package provides code for a nice release hash you can use for getting your git commit hash:

'release' => trim(exec('git log --pretty="%h" -n1 HEAD')),

Which if you run in Artisan’s tinker mode, gives you something like this:

1a2b3c

Now the problem: we use Envoyer for our deployments, which downloads the tarball of a specified branch/release/tag instead the entire git repository. That tarball doesn’t contain any of the git history in it, so it’s not technically a repository, thus running the Sentry Laravel command won’t give you a commit hash. If you try, you’ll get the following lovely error:

fatal: Not a git repository (or any of the parent directories): .git

Which means if Sentry tracks an error and saves it, you’ll see there’s no release attached to the issue. Drats!

Somehow, we need a way to get the current commit hash from our Envoyer deployments so we can tell Sentry how to get the current commit. Thankfully, Envoyer comes to the rescue!

In the Envoyer docs, under Deployment Hooks, you’ll see a section on how you can get the current git commit hash (or sha1 hash). Now, this hash is actually the first 12 characters of the current git commit hash - aka. something you can use in the deployment lifecycle.

From here, we want to target the current release directory, so let’s create a deployment hook in the “After” section of “Activate New Release” and call it “Write Git Hash to File” with the user “forge”:

echo "{{ sha }}" > {{release}}/.commit_hash
Our Envoyer hook

Pretty simple, huh? All it does is echoes the current git hash to stdout (standard output), then we redirect that output to a file called .commit_hash in the current release directory. The single arrow (>) means “set the file .commit_hash to 0 length, then append to it”. If we used two arrows (>>) we’d only append to the file, which we wouldn’t want to do - though technically it doesn’t really matter given the release directory has just been created, but it’s the principle of the thing!

Once we’ve got that file written on every deployment, we need to tell Sentry how to get that commit hash! If you wanted to, you could change the config so Sentry fetches the release, like so:

'release' => trim(exec('echo "$(< .commit_hash)"')),

(Note that I’m using echo and redirection here, I don’t want to get into the UUOC debate!)

Except this only works if you have that .commit_hash file in every environment, which we don’t. So, we’re stuck between a rock and a hard place. What we need is a solution that uses the .commit_hash file if it exists, or falls back to a git repository, or finally, returns null if neither of those exist.

In our project, we’ve got a small helpers file with all functions that exist in the global namespace. That’s where we put our solution:

Pretty basic really - just an if/elseif/else block with three possible outcomes. Note that I’m using the base_path Laravel helper, so we can be sure we’ve got the full path to the file/folder in question. Then, in our Sentry configuration file we have the following for the release:

'release' => get_commit_hash(),

Now whenever Sentry needs the commit hash, it’ll call that function and get its return value. Nice! And for those of you concerned about the overheads of getting the commit hash, you can do a php artisan config:cache so the hash is only calculated once. I highly recommend caching the app configuration as part of your deployment process to help to make things that little bit faster. That file is located in bootstrap/cache/config.php and you can verify the existence of this cached value by doing the following (in the root of the project, with the configuration cached):

grep -n --context=3 \'release\' bootstrap/cache/config.php

You should see something like this:

484-    'sentry' =>
485-    array (
486-        'dsn' => 'https://xxxxx:[email protected]/project_id',
487:        'release' => '1a2b3c4d5e6f',
488-    ),
489-    'auth' =>
490-    array (

(The line numbers to the left indicate where in the file it was found.)

Now you’re set! The next time you do a deployment, you’ll have Sentry correctly logging issues with the current release throughout the life of the project.

Happy tracking, folks!

1 2 3 7 8 9 15