Adopting Azure DevOps : A Step-by-Step Approach

Last year, we decided to build our own Azure
DevOps extension. We realized that it would be pretty ridiculous to create one
for other people to use without fully embracing Azure DevOps ourselves. That’s
how we decided to transition, and we learned quite a bit along the way.

If you were to look at our DevOps pipeline a few years ago, like
most companies and open source projects, we had a mishmash of many different
products, services, and bash scripts, all tied together with some duct tape and
string. It turned out that there were a lot of pieces to the puzzle. Just like
many other organizations, this situation was compounded by the fact that different
DevOps tools from different companies didn’t always communicate well with each
other. In short, we had a lot of work to do, but ultimately, we got our act
together. We now have a beautiful, comprehensive solution that’s all based on
Azure DevOps, instead of having multiple systems that everybody on the team had
to understand and work with.

Here are the six stages of Azure DevOps integration that we went
through. We hope this helps shed light on what you’ll need on your pathway to development
nirvana.

Step 1: Find Your Pain Points

I’m a huge fan of Donovan Brown from the league of DevOps Advocates at Microsoft. When he speaks about DevOps, he often says (paraphrasing): “Find the thing that hurts the most. Do more and more of it and get better and better at it until it doesn’t hurt anymore.” We’ve made that a bit of a mantra.

If you’re going to adopt DevOps, and you’re thinking about
switching to Azure DevOps, look yourself in the eyes and ask: What is the most
painful thing right now in our DevOps pipeline? Is it that we don’t have enoughunit tests?Is it that deploying a new version of the software is a
manual, error-prone process? Do you need a 20-page Word document for each
deployment?

Even ifyou have a perfectly good DevOps pipeline, even if
you’ve reached DevOps heaven, and even if your releases happen with a big shiny
deploy button, you may still be breaking things in production. Then, you find
that you don’t have the right tool to tell you what you broke (p.s. – that’s
where OzCode’s
extension can help). Other things may be bottlenecked, or just not working
the way they’re supposed to. Identify those pain points and start there.

Step 2: Source Control (from SVN to Git)

I like to think about source control as where our code files go to sleep at night. When we were just starting OzCode, in the early proof of concept stage, we were using SVN—archaic technology, in my opinion—for source control. Then we moved to Git. There are plenty of automated tools to transform data from almost any source control to Git, which makes things a bit easier.

If you’re adopting Git, you should do it with full awareness. Take a look at what you are gaining, but also understand the costs you’ll incur along the way. Git requires a huge learning curve. There are functions like merging, re-basing, and push-pull. It can all seem very complicated and threatening to a newbie.

My best advice on how to deal with that? When you’re starting out
with Git, it’s okay to treat it like your old source control system. If you
translate what you know about source control and apply the same to Git, you can
get away with it. It’s a myth that you have to learn all about re-basing,
merging, and re-writing history right off the bat. Over time, you will start to
adapt to its more powerful tools.

Our entire industry has been rapidly adopting Git of late, but if
you’re late to the Git party and wondering if it’s really worth the switch,
he’s my $0.2: Git has one killer feature that is truly transformational: effortless
and instant branching. In archaic version control systems, creating or merging
a branch was a major thing. Sometimes it could take 30 minutes because you needed
to clone an entire copy of your source control.

With Git, you have instant branches that are literally one click
away. That means you can divide work into feature branches in a much more
efficient way. You can create a branch for each pull request and for each new feature
you’re working on without bringing noise into the master. That, alone, will be
transformative. It makes it much easier for people to go into a separate
feature branch, do their work, and merge frequently with the master. You’ll get
more work done with less friction.

Step 3: Task Management
(from Trello to Azure Boards)

Next, it was time to tackle task management. We had been using Trello, which I love for its simplicity. You only have three columns: “TODO”, “Doing”, “Done”. Trello excels at the pure Kanban, no-BS approach to task management: it’s basically a glorified TODO list – you drag the most important stuff to the top, and get them done.

Azure Boards, on the other hand, is much more complicated. There
are Work Items and multiple statuses, which means you lose the straightforward
simplicity. What you gain, however, is customization, allowing you to adapt to
any flow you want.

For example, on the OzCode team board, there are a lot of work
items or bugs that are deeply technical—basically, items that don’t require QA
once they’re resolved. We decided to simply add a check box for “QA needed”, and
created a flow for items that did or did not require QA and which can be
assigned automatically. It took our DevOps guy just a few hours to accomplish
this.

At the end of the day, you can pick and choose your tools, so if
you prefer to stick with something simple like Trello, it will work fine, but
you’ll lose traceability. Using Azure Boards with other parts of Azure DevOps allows
you to do things like correlate pull requests to fixed bugs, which is
incredibly useful.

Step 4: Get on the CI/CD Bandwagon

Continuous Integration (from TeamCity to Azure Pipelines)

Before Azure DevOps, we were using TeamCity, which is a product from JetBrains. It is actually a really good product for continuous integration. Like Azure DevOps, it has an on-premises solution and a SaaS version.

One of the nicest things about using Azure Pipelines, instead of TeamCity, is how fast your builds start. With TeamCity, every time we needed a new build, a VM would be provisioned, and that could take five to ten minutes. This feedback loop was slow and became really annoying. But with Azure DevOps, Microsoft has an infinite pool of hot, ready-to-go build machines in the cloud, so as soon as somebody pushes in a new commit, and the build happens instantly.

Side note/pro-tip: give your old laptop new life as Build Agent

By the way, if you’re trying to save costs and time, you might want
to consider using an old laptop or an existing VM as your build agent. Even
though Azure DevOps offers a generous 1800 free cloud build minutes per month
(and infinite free minutes for open source projects!), there’s a catch – host builds
can be slow. Every time a cloud Hosted Agents starts, it’s a fresh, squeaky
clean machine – so it needs to clone all of your source code every time. Although
the cloud-to-cloud clone process is quite fast, it’s still a waste of time and
money for this to happen for each build. Another advantage of using an old
laptop instead is that build artifacts that were already on the machine from
the previous build don’t need to be rebuilt. This can save even more precious
build minutes.

Continuous Delivery (from manual deployments to Azure Pipelines)

Previously, our deployment process was quite manual, and we just ran
a bunch of batch scripts. Using Azure Pipelines has been a pleasure: it’s not
just about having a big shiny button that says “Deploy” that pushes the
software to production. It’s much more than that: Azure Pipelines gives us
perfect visibility. If there’s a problem, or if I just want to know whether a
specific commit or change has been entered into the new version of the product,
I can get that information from the Azure DevOps pipeline almost immediately.

Azure Pipelines is also customizable. For example, being the
paranoid person that I am, I always run multiple
virus scans on an installer before I release it to customers. So, we’re now
writing a new script to automate this process, so that I don’t have to think
about it – we send our installers through VirusTotal automatically, and fail
the build if something ever comes up. No matter how weird or unique or eclectic
you think your scenario might be, Azure Pipelines can automate it for you.

Step 5: Bug Tracking (from FogBugz to Azure Boards)

Our next move was to perform bug tracking with Azure Boards. Before that, we were using FogBugz, and leveraging the fact FogBugz can work as both a ticketing system and a bug management system combined.

As mentioned, Azure Boards is completely customizable. Of course, nothing is perfect, so I can definitely describe Azure Boards in terms of the good, the bad, and the ugly.

The good,
obviously, is the customization part. Let’s say that your goal is to link your bug
tracking to customer success and customer support. Azure Boards enabled our
support engineer to create an issue whenever a new bug was found by a customer.
We also automated our workflow with a custom field that linked back from the
Azure Boards Work Item to the ticket in our support system, FreshDesk. Upon resolution of the bug, when
we deploy a version that includes the bug fix, the customer success engineer or
support engineer now gets an automatic email informing them to contact the
customer to let them know that their issue was solved.

The bad is that
the number of fields and options can get confusing. However, the system is
integrated with Virtual Studio as part of the IDE (even more so in VS2019),
which is also very useful.

And the ugly is that the UX is kind of confusing. Best example: the commenting system works differently than any other you’ve ever seen: instead of just hitting Control + Enter to save a comment, you have to save the work item instead (good luck finding that out the first time around!). In general, it’s often not obvious what buttons you’re supposed to be pushing. Although this situation is improving, it’s still kind of archaic, primarily because it comes from TFS, which was a very old-school system.

Step 6: Customize Azure DevOps to Your Taste

Don’t get bogged down in the way Azure DevOps or Azure Boards in
particular wants you to work. If having those millions of different statuses
like approved, committed, resolved, verified, or succumbing to their definition
of Agile or Scrum or whatever doesn’t work for you, just ask yourself what’s
the simplest thing that could possibly work, and do that on top of Azure
Boards. Don’t force yourself to overthink things just because the people who made
Azure Boards probably over-thought some things.

Customization is easy because Azure Boards gives you full
customizability over the fields. You can use that to add things but you can
also use that to take away things. So, take away whatever doesn’t make sense
for you. Keep only the bare minimum. That way, you can get a more Trello-style experience where you only see
what matters. You really want to use it as a tool to gain visibility into what
your team is doing and communicate priorities, so keep it simple and remove any
cruft that isn’t relevant and is just getting in your way.

The Big Picture

The most important thing about adopting Azure DevOps is the sort of
aggregate effect it has as a holistic solution. You can go the route of using
certain components. But, if you choose to go the full Monty, you can find an
overwhelming positive change.

This is not without issues, of course. The switch to DevOps can be
tough on many levels, from changing corporate culture to investing in up-to-date
software for use across the organization. But this really is a case of short-term
pain for long-term gain.

The holistic approach is a winner. Once we adopted the holistic
approach, shipping software to our customers became easier, more automatic, and
even a good experience because there was only one place to look when things
went wrong.

In any case, what’s there to lose? Whether you start with one
component or the whole bunch, Azure DevOps provides immediate and noticeable
benefits, across the board.