Recently, Burke Holland (@burkeholland) and Cecil Phillip (@cecilphillip) released their awesome app The Urlist, a real world serverless app (check it out, it’s cool). After reading Burke’s blog post talking about The Urlist, I came away with 3 conclusions.
- Very cool app and very cool use of serverless technology
- Burke’s blogging style is freaking awesome!!! (I admit it. I have total man love for Burke and all the content he creates
- Uh… peeps… where’s the DevOps????
So of course I pinged Cecil and I’m all like, “DUDE!!!! Where’s the DevOps??!!! You know this is important. We literally just recorded an 8 part On .NET series talking about how important DevOps is!!!!”
And Cecil replied in that cool chill way that he has, “We did rub DevOps on URList man. Check out our pipelines.”
Ok, that’s not an exact quote. I may have made that up. BUT, Cecil and Burke did create pipelines for URList using Azure Pipelines.
CI/CD Pipelines for URList
The URList consists of a single page web front end, written in typescript and Vue.js hosted as flat files in Azure Blob Storage. It also has a back end piece consisting of Azure Functions, Azure Cosmos DB, Application Insights and App Service Authentication with the Azure Function written in C#/.NET Core. Check out Burke’s blog post detailing how the URList was created.
Looking at their build and release pipelines, they have one build for the front end which links to a release and another build for the back end linked to another release.
Front End Build and Release
It just uses npm to build the app. The npm build task “compiles” the typescript down to static files and stores it in the dist folder. Which makes creating the build artifact for this build super easy. Just grab everything from the dist folder! Looking at their Publish Build Artifacts task, that’s exactly what they do. They grab all the files in the dist folder and upload it back to Azure Pipelines as the build artifact for this build.
The release for their front end is also a standard out of the box release. They release into one stage (production) and they deploy the bits into Azure blob storage (remember, the front end has been “compiled” down to static flies which is hosted in blob storage)
Looking at the task list, deploying to blob storage is super easy. It’s literally one task, the Azure File copy task
Backend Build and Release
The backend consists of an Azure Function written in C#/.NET Core. The build and release pipelines are again, very standard, out of the box .net core pipelines. Here’s the build
And here is the release pipeline. One stage, the production stage
Drilling into the production stage
we can see this release pipeline just uses the Azure App Service Deploy task to deploy the Azure Function.
Bam! CI/CD Pipelines for the front end and back end of the URList!
From a DevOps perspective, where do we go from here?
After looking at their pipelines, I was super excited. They actually had a working CI/CD pipeline for their app. Both for the front end AND the back end! Cecil then told me they wanted to create a Dev branch in their repo and create another CI/CD pipeline that will take the Dev branch and build and release the dev branch to their “beta” environment.
Since I’m a total branching nerd, I immediately wanted to add to it. Instead of a long living Dev branch with a separate CI/CD pipeline into a beta environment, we should do trunk based development with no long running branches. We just branch for a new unit of work. And when done, submit a PR into master. And once code hits master, we can build 1 time, then release to a beta stage, and then if everything looks good, we can approve it, and the exact same build artifacts from the same build will then get deployed to the production stage. The benefits would be huge. No long running branches means WAY less super painful merge conflicts. Every layer of branching adds a significant level of complexity and work to maintain those branches. By doing trunk based development, we simplify our branching strategy while still being flexible enough to handle things like hot fixes. Also, since we are only deploying one branch (master) using one build, we know the beta environment will be exactly the same as the production environment. No stray bits of code will accidently find its way into an environment.
And while we’re at it, why not use Infrastructure as Code. Since everything is hosted in Azure, should be simple enough to create IaC files which define our Azure infrastructure. Save them in source control alongside our source code so now the infrastructure hosting our application is versioned right alongside our source code. And the CI/CD pipelines can then deploy or update the infrastructure based on what’s in those IaC files!
But wait!!! There’s more!!!. What about yaml pipelines? We can convert all the build and release pipelines into yaml pipelines so now the code and the pipelines can be versioned together. And best of all, when someone clones or forks Burke’s repo, not only do they get the source code, the infrastructure needed to host the app, they also get the pipelines that build AND release the app.
And since we’re talking about whole sale changes and using DevOps best practices, we really need to add tests. Unit tests. Automated UI Tests. And these need to run in our pipelines. Oh, and what about adding in feature flags!!!! That way we can do testing in production as well as abstract the release of a feature from the deployment of code!!! And what about creating some automated approval gates so we can use AI to help us determine if the code deployed into beta is good enough to go to production?
Cecil looked at me and without missing a beat said, “Funny you keep saying ‘we’ and ‘our’. Sounds great. Do it. And then document it.”
Heh heh heh. So…. looks like I just joined the URList team
Cecil and Burke created a super cool app and implemented some rudimentary DevOps. We’re gonna make it better. In the next few blog posts, watch as we implement some seriously cool DevOps to the URList.
- Implement Infrastructure as Code and add the ability to create or update our environments from our pipelines
- Create a build and release pipeline using trunk based development deploying first into a beta environment and then into our prod environment
- Converting our build and release pipelines into YAML pipelines.
- Adding Unit Tests and Automated UI tests to our code, running them in our build and release pipelines
- Adding blue/green deployments
- Adding feature flags into our app and pipelines
- Adding testing in production abilities
- Adding automated approval gates to help us deploy faster and safer
What’s that Donovan always says? Rub Some DevOps on it? Yeah, we’re gonna DevOps the sh$%* out of this!