5 min read

Why I Chose Azure DevOps as My Operational Git Platform

Last year, as I began modernizing the operational backend for managing Macs in our organization, it became painfully obvious that our existing setup was long overdue for an overhaul. The inefficiencies of our traditional approach weren’t just annoying anymore; they were holding us back from doing better.

We run our Mac deployments, patching, and updates with Munki. We implemented MicroMDM in 2018 when macOS Mojave forced the MDM hand, so we had Macs with a fully cloud connection since. We also happened to build an offsite Munki repo on AWS before the pandemic—a solid move at the time, giving us redundancy and a better failover option. The thing is, we never actually reimagined how we managed the Munki repo. The beating heart of it all was still sitting on a set of two on-prem Macs (one main and one backup), maintained through outdated workflows.

We went along in this way for years because it wasn't really broken; it just had its headaches, but it was all functional.

We were still screen sharing into the server to make changes to the repo, which doesn't really allow multiple people to work on it. We did log changes to Git… but after the fact. We had an on-prem GitLab instance, and we used it as a logbook and to document our work and changes—honestly, already more than I’m sure other peers in our department did—but all of that still relied on VPN for access.

We also tried cloud-syncing our repo at times, but those efforts are best left buried—so many issues—let's not discuss that.

As I took on a new role as Devices Admin a couple of years ago, I stepped back from the daily nitty-gritty operations of pushing updates, packaging, and scripting. With macOS annual updates being fairly stable, the need for heavy involvement was also lower. Most things were under control.

But a big recent driver ended up being Windows, actually. As I began working on replacing all the legacy systems Windows was running on (GPO and imaged OSes, anyone?), I really wanted to replicate our successful Mac management tools and model on Windows. As I had to think of a fresh start on the Windows side, going fully GitOps with CI/CD pipelines and everything under version control, plus all the infrastructure as code (IaC), was the way®. And as I was planning the Windows side, I saw all the deficiencies more clearly on our Mac side. Last year was the year I decided to make the move.

Choosing a Git Platform

Naturally, the first thought was to migrate our existing GitLab instance to the cloud and continue using it. I had the network folks get it going on Azure as a VM. Working with GitLab itself, I started thinking and designing our workflows, building out the teams, and structuring it in a way that more people in the IT department could use and start to take advantage of Git.

I spent a huge amount of time figuring out this new "CI/CD" world we had never really explored or implemented before—we had this for years in a Trello card titled "Explore CI/CD workflows" that had never gone anywhere! The summary of this part of the project is how infuriatingly hard and confusing it was to use and set up GitLab Runners.

I fell deep into a Kubernetes (gif of Alice falling) rabbit hole that took me at least a month to get out of. I actually got it working and built a couple of Kubernetes clusters in Azure with Helm and all that jazz, but it was expensive! Way more than initially expected, as in 5x the cost after the month up and running. I’m sure I didn’t do proper optimizations or turn them off on a schedule to save money or [insert smarter person’s suggestions].

It all felt way too complicated.

GitLab itself had so many knobs and options and menus and submenus and way too much everywhere.

I wanted simple. I needed simple.

I wanted to have:

  • Git version control repos
  • Run cloud operations on changes to the repo

So that's the point that I started looking elsewhere. What were the options? Obviously, GitHub is the first that comes to mind. But it felt to me the security folks wouldn't love seeing internal work on GitHub, even on a fully internal organization account. GitHub itself emphasizes the "open" in open source a lot. Don't get me wrong, I love GitHub, but I wanted a platform that felt private from the get-go.

Did Google have anything? "Oh, they are deprecating 'Cloud Source Repositories' in a few months."

What about AWS? We already have AWS resources. Our MunkiReport is on AWS, our MDM is on AWS, and we serve Munki with CloudFront. Let's see what they offer.

I got a test repo up in AWS CodeCommit and explored a bit. It’s all fine, but AWS itself has a complexity in it. Their naming conventions, their menus, where things are—you just feel confused while in the AWS backend (am I the only one?).

I noted it down as an alternative but ultimately passed on it.

BitBucket? Maybe. SourceForge? No. Beanstalk? No.

Finally, Azure DevOps showed up on the radar, and I started to explore it.

Initially, that Microsoft-y feel wasn’t that appealing, but I realized that, well, we are a Microsoft shop (or as they say in the horrific "M365" branding of theirs...), and it was the path of least resistance.

Why Azure DevOps

It's fully managed. It's serverless. It’s got Entra ID SSO built in. No account management was a major plus.

But really, after a few days of taking it for a real spin, I realized it had everything and exactly what I needed:

  • Repos
  • Pipelines

Support for multiple repos and running CI/CD workflows in, honestly, a really simple and clean interface.

Best of all, Azure Pipelines have access to Microsoft-hosted agents.

With Microsoft-hosted agents, maintenance and upgrades are taken care of for you.

You always get the latest version of the VM image you specify in your pipeline. Each time you run a pipeline, you get a fresh virtual machine for each job in the pipeline. The virtual machine is discarded after one job (which means any change that a job makes to the virtual machine file system, such as checking out code, will be unavailable to the next job).

Microsoft-hosted agents can run jobs directly on the VM or in a container.

And the kicker was: alongside Ubuntu and Windows for CI/CD jobs, Azure Pipelines includes macOS images out of the box!

I can spin up a cloud Mac VM just with:

- job: macOS
  pool:
    vmImage: 'macOS-latest'
  steps:
  - script: echo hello from macOS

Well, you have probably figured out by now that this is the platform I picked and have been building our entire new fully cloud-based DevOps operations on, and it’s been really, really wonderful.

I was able to import the entire history of commits from our pre-existing Munki repo, so we migrated over six years of history and picked up where we left off.

Things are easy to get to. It has all the Git features we want: commits, pull requests, comments, code review, etc. There are a lot of things I don't even use.

The impact has been massive. Pipelines now handle tasks that used to be manual scripts and little automation scripts on a local Mac. It’s now a fully cloud process that connects to different systems such as my inventory and the repo itself, reducing errors and speeding up deployments. We’ve gone from “this is how we’ve always done it” to “wow, this is how it should’ve been all along.”

I will go into much more detail on ways I am using Azure DevOps in future posts. There's a lot more to discuss regarding the migration of our Mac operations from the two local on-prem Mac minis to a fully DevOps CI/CD cloud system.