In the first blog on this subject, I detailed the process for installing VS Code, GIT as a local repository, followed by how to setup and configure integration with an Azure DevOps project. If you didn’t get a chance to read it I’d suggest you go back and do so before continuing here. http://seanmcdonnell.blog/azuredevops-part1/
Ok, so apologies are required up front, this post is rather long and detailed…But stick with it, I think it’s important for IT Pro’s who are looking to define their DevOps strategy and improve their understanding of Infrastructure as Code with Azure DevOps. In the first part I’ll continue on from the previous blog post and show you how to work with VS Code to commit code to your local GIT repository before committing the same code into an Azure DevOps project. The second part of the blog will then focus on defining your Branch strategy, working with the Master, creating Branches, Pull requests and Branch policies.
GIT vs VSTS
In the previous blog I selected GIT as the private repository type. When comparing VSTS vs GIT, you’ll find that the version control protocol works slightly differently in GIT. In TFVS, you typically lock and shelf sets, which is essentially how you save your code. In VSTS (or TFS server) the version control is centralised. You have one copy of the file/s at any point in time and when you need to update, check-in and check-out code, you need to deal with conflict resolution. GIT works differently in that it’s a distributed source control, meaning everyone maintains their own copy of the code before committing a merge into the repository. The authority of source is called the “Master” (Also known as a trunk). I’ll go into these concepts in more detail later in the post
NOTE: For IT Pro’s I would generally recommend use the following with Azure DevOps:
- Code: PowerShell, ARM Templates, DSC
- Documentation: Mark Down (You can technically store documents such as Word, Excel and PowerPoint documents, however as those are complex documents it’s very hard to get the benefits of source control when using these.)
Firstly, I’ll be adding some documentation to the repository. To do this, I’ve created a ReadMe.md (mark down) file within VS Code. In the following screenshot you can see that I have created the “ReadMe.md” markdown file. The centre panel is the markdown code and the right panel is the preview of the output of the ReadMe file. As you can see, I have added a header with information about the repository, with a link to my blog, followed by a subheading with a link to a mark down cheat sheet which I’ve imbedded as a hyperlink https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#html
Next I need to save the updates locally before syn’cing changes to the Azure DevOps repository.
- Before doing so, a description of the changes is required. Each time you make a change to a file, you will need to add a comment around what the change relates to.
- Select the ✔ icon to commit the changes locally.
- Select Yes on the below, do no select “Always” as it will automatically stage all changes. NOTE: If you had more than one file and only wanted to commit changes to one particular file, you select the arrow (Shown in the below screenshot) to stage just that particular file. Otherwise, if you don’t stage a file, it will commit all files together.
- Following that, you will need to commit the changes to the Azure DevOps project. To do this, select the little icon (Shown in the following picture). This will sync any changes directly to the master in the repository.
- Next, click on the “IaaS V1” icon as shown above and that will open the Azure DevOps portal and link to the project I previously created. From here I can see if the files have committed successfully. I could also review the output within VS Code for any errors
Next up i’m going to make a couple of changes to the ReadMe.md file. The purpose of this is to show how useful the Gitlens extension is for tracking changes in VS Code, particularly if you are working with other team members on a set of files. As you can see in the following screenshot, the text highlighted in Red was the last saved commit and the Green text on the right side panel shows the changes that were made. As a side note, Azure DevOps also provides this functionality within the portal.
Defining your Branch Strategy
Defining your Branch strategy is vital to ensure a secure, flexible and consistent workflow across your team. The general rule of thumb is to keep your branching strategy as simple as possible. Microsoft recommends the following as a baseline:
- Use feature branches for all new features and bug fixes.
- Merge feature branches into the master branch using pull requests.
- Keep a high quality, up-to-date master branch.
“A strategy that extends these concepts and avoids contradictions will result in a version control workflow for your team that is consistent and easy to follow.”
When defining your organisations branch strategy, one of the first things you will need to work out is how your organisation should use the Master in terms of release management. Here are some important questions you will want to answer before defining yours:
- Will the Master be used for changes that are already deployed in Production or ready to be deployed to Production?
- How will you manage changes into source control, particularly your Prod environment?
- What change control process do you have in place and how will it integrate with changes made to your source control repository?
- What about approvals, who is going to review changes and who is going to manage releases?
- What will your folder structure look like within Azure DevOps, this should be consistent across GIT also? Where will you store templates, scripts, artifacts etc?
These are all important questions that you and your team will need to work through, generally I recommend the following high-level approach with Azure DevOps:
- The master is considered ready to be or is already deployed into Production.
- If changes to the Master are required, a branch must be created and approved before a merge is complete back into Master
- Branch Policies should be mandatory for Production code, automated approvals should be assigned where possible (Discussed later in this post)
- Any Branches should be named correctly, ideally marked with the userID, description and change record number (discussed later in this post)
I’ve put together a generic high-level workflow below to represent some of the previous questions
Working with the Master, Branches, Pull requests and Branch Policies
Creating a Branch
The safest way to ensure that changes to source code are managed correctly and peer reviewed, is the Branch. A Branch will enable you to work in a way where you can commit your changes to your source control repository without impacting the Master. To create a Branch, you can select the Master icon in the bottom left panel of VS Code and then select “Create a new branch”. You will be asked to create to enter a new branch name. My suggestion would be to use your username followed by a description of the change followed by change number. Eg
Hit “Enter then at the bottom of the VS Code screen, you will see that you are no longer on the Master, rather you are working from the Branch
Next I will add some folders to the branch which we will use to store our templates.
- Create a blueprints folder, which will be used for storing reusable templates
- Create a deployment folder, which will be used to store deployment templates
- Create a infrastructure folder and a sub-folder where we will host the management templates. In this case, I’ve kept the folder name the same name as the resource group name.
You will see that the templates will show as “Untracked” meaning that you will need to commit them locally before Push to your DevOps repository. Remember to click on the Cloud icon to sync the branch to the source repository server in Azure DevOp. Once the push has completed, you can check that the branch has been updated in the Azure DevOps portal. Because I used my username/description when creating the branch, it has automatically put the branch within a folder which is really useful.
On the right hand side of the above picture, you can see that it is listed as 0 | 1 for the Behind | Ahead. This means that the Branch is one change ahead of the Master.
Creating a Pull request
Once you have tested your changes and are happy with to Push the code into the Master, we will then create a “Pull request” within
Azure DevOps. The most effective and easiest way to do this is directly through the Azure DevOps portal, however there are other ways to do this.
Under Repos -> Branches you will see “New Pull Request” as per the following screenshot
A pull request is a way for you to flag to other team members that you’re going to make a change to the Master repository. This opens up an opportunity for peer review, which is particularly important when you’re working with different teams/vendors. Select “New Pull Request”
- Add Title, ensure it’s something that is meaningful and include ticket numbers where appropriate
- Add your description, you can use Markdown here also
- Reviewers – You can select other team members to review
- Select Create
The key idea here is that I am submitting changes to a team repository where another team member can review and can add value, help improve your code or pick up errors. You or other team members can add comments as shown in the following screenshot.
You can also see the files, any updates and commits that have occurred. Under Updates, if you’re a reviewer you can add comments for the creator to make changes. The creator who wrote the original template would then see the comment, fix the template, and initiate “Complete Pull Request”.
I’ve selected to delete the branch but also to “Squash changes when merging”. If you select this option, it will take the total number of commits (changes) you took to get to the final output and will compress them to get the final output files, which gets merged back into the Master (With the metadata description in it). I recommend this if you’ve made a large number of changes, however these settings should generally be configured with Branch Policies, which I’ll discuss next.
NOTE: When working back in VS Code, if you try to sync and you still on the Branch you will receive an error. Switch back to the master before Syncing
Up until this point, we’ve been able to work on both the Master and Branches, allowing us to commit branches back into the master without any policies in place. This generally isn’t a good idea, we want to ensure that we have policies defined so that any pull requests are reviewed and approved before being merged back into the Master
Assuming you have the appropriate permissions, go to Branches, Master and select “Branch Policies” which will take you to the project settings
The Policy settings are quite self-explanatory and can be set according to your needs. I’ve set the minimum number of reviewers to 2, check for comment resolution as enabled and enforce a merge strategy, which is set to “Squash merge”. This policy will now enforce the following when attempting to merge a branch back into the master.
- 2 reviewers are required and users are unable to approve their own change
- The policy checks that all comments have been resolved before continuing
- And lastly, it will enforce a squash merge strategy.
If you work in a team with different levels of expertise and you expect the same reviewers for each template, you can add automatic reviewers in the Policy settings. If you can’t find the Reviewers name after searching, you will need to add them to the repository as either a stakeholder or contributor. The “Path Filter” can be configured so the reviewers only approve for any files for that have changed. For this demo I won’t be selecting this.
Once you apply the policy, any changes you make within VS Code (local) will not require approval. However, if you are attempting to push those changes to the Master in Azure DevOps, you will be prompted with an error. The error is related to the policy that we just created. You will need to create a branch and pull request (which needs approval) before it is approved into the master
That’s it for now, I hope it was useful. In the next blob I’ll tackle Pipelines and how you can use them to build out your IaaS Azure environments.