Table Of Contents
Overview
In this article, we’ll look at the process of software deployment. How does your code get transferred to the cloud and why Continuous Integration and Continuous Deployment are so crucial in the process, even though it’s possible to release your applications to the production environment without knowing those concepts.
We’ll weigh the pros and cons of using different kinds of deployments.
Video
Local Deployment
Congratulations! You’ve built your web application locally and can successfully run it on your machine. How does it run, though? You press a magical Run button in Visual Studio and it just happens! Well, the CPU can’t quite read your code as it stands – it can only read binary code! That’s the first problem. Then, if the build happens, where is all the binary output stored for the processor? Lastly, how can we run a web app without a server? Well, there is a server involved too! Let’s break down the stuff (it’s still simplified!) that occurs since you press a Run (or F5) button in Visual Studio:
- The project you’re trying to run is recognized by Visual Studio as your local repository
- Compiler builds the code and installs all dependencies (local build agent). The build output is placed in bin and obj folders in your local repository
- Dotnet runtime spins up a local server (localhost) on a port of choice which your application can run against (and acts as your host machine)
- Visual Studio spins up a browser and opens at the given port, i.e. https://localhost:5001/
Let’s review what happened here with a little graph. Your machine effectively acts as a:
- Codebase repository
- Build/Release Agent
- Host Machine
Quite a lot for a laptop, isn’t it?
It’s hardly perfect to keep it this way – your laptop doesn’t make a great server and you’d like to turn it off or disconnect it from the internet and most importantly, no one has access to your localhost server! Thankfully, you can always deploy it to the cloud and share it with the world.
Pros and Cons of Local Deployment
- Pros:
- Fast
- Great for development purposes
- Full Control
- Easy to attach a debugger
- Cons:
- Your development machine has to stay on to accommodate the server
- Your machine is under a lot of stress
- Not suitable for production
Cloud Deployment without CI/CD
There are many ways of deploying an application to the cloud and many reasons why would we want to do that, but it comes with some decisions we have to make. For example, Visual Studio makes it possible to deploy the application directly from within the IDE or you could use a CLI to do that, but think about the consequences! Anyone can do it from the comfort of their own laptops, so you effectively have no clue when someone deploys. You have no control over what is being deployed and no insight into any code changes. In short, it might be a good idea if you work by yourself on a one-off, small project, but in any other case, that shouldn’t be the way to go!
What you do want from your deployment is complete control over what, when, how and if is being deployed.
- Why What? Sometimes the code pushed to production introduces a bug and the first thing to look at are the recent changes – without a proper audit, you won’t know what has changed. Source control comes in handy!
- Why When? You really only want to deploy in quiet times, so you should hold pushing any new releases until the off-peak times, especially if any downtime is expected. You can do that using gates in Azure DevOps pipelines.
- Why How? When using local deployment, you don’t know what pipeline is used and the majority of the build/release configuration is decided for you. It also will differ when you deploy it from your PC, vs your teammate from theirs. Having a centralized pipeline in the cloud will ensure that you’re always using the same build/release configuration.
- Why If? Well, sometimes the code pushed is just missing the point. You then reject the changes. This can be done by using pull requests instead of pushing changes directly to the default branches.
Pros and Cons of Cloud Deployment
- Pros:
- Delegating hosting task to an external server (on-cloud or on-prem)
- If the pipeline is in the repository or i.e. Azure Pipelines/Releases, it provides a centralized point of build and deployment
- Cons:
- If you deploy from your local machine, it may create problems with configuration and doesn’t provide a build/release audit – you don’t know when and what was deployed and by whom.
- Requires manual input to trigger pipelines
Continuous Integration / Deployment
Let’s start with a bit of terminology.
Continuous integration (CI) is a step in which all code is merged as developers complete code in order to run automated builds and tests.
Continuous deployment (CD) is the process of moving software that has been built and tested successfully into production.
https://stackify.com/continuous-delivery-vs-continuous-deployment-vs-continuous-integration/
Looks like CI has to do with source control and builds, whereas CD is more about releasing your application to prod.
Look at the below diagram and I’ll walk you through it.
Local repository
In the above scenario, your PC is only serving the purpose of the local repository. You pull the changes from the remote repository to stay up to date with the code that might have been pushed there by other members of your team. You then write your code (on a new branch derived from test/master) and, once ready, push it to the remote repo. You can use a pull request to merge your code into one of the default branches (i.e. test). This is where things get interesting.
Build Agent
Your build pipeline i.e. in Azure DevOps > Pipelines (as that’s what we’re using as an example) would have a trigger to enable the CI. What this means is any new code changes detected on a branch of your choice (in our case it’s test) will trigger a build pipeline to run and produce a new version of an artifact (your compiled code, packed i.e. in *.zip file). The build is performed on a brand new machine spun up by Azure called a build agent. The pipeline itself is created using a language called YAML. The example build pipeline:
pool:
name: Azure Pipelines
demands:
- msbuild
- visualstudio
- vstest
steps:
- task: NuGetToolInstaller@0
displayName: 'Use NuGet 4.4.1'
inputs:
versionSpec: 4.4.1
- task: DotNetCoreCLI@2
displayName: 'dotnet restore'
inputs:
command: restore
- task: VSBuild@1
displayName: 'Build solution **\*.sln'
inputs:
solution: '$(Parameters.solution)'
msbuildArgs: '/p:DeployOnBuild=true /p:DeployDefaultTarget=WebPublish /p:WebPublishMethod=FileSystem /p:publishUrl="$(Agent.TempDirectory)\WebAppContent\\" /p:DefineConstants=TEST'
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
- task: ArchiveFiles@2
displayName: 'Archive Files'
inputs:
rootFolderOrFile: '$(Agent.TempDirectory)\WebAppContent'
includeRootFolder: false
- task: VSTest@2
displayName: 'VsTest - testAssemblies'
inputs:
testAssemblyVer2: |
**\$(BuildConfiguration)\*test*.dll
!**\obj\**
platform: '$(BuildPlatform)'
configuration: '$(BuildConfiguration)'
- task: PublishSymbols@2
displayName: 'Publish symbols path'
inputs:
SearchPattern: '**\bin\**\*.pdb'
PublishSymbols: false
continueOnError: true
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: drop'
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)'
condition: succeededOrFailed()
In Azure DevOps, you can also view a GUI representation and a visual builder:
The way you set up a CI on your build pipeline is via the triggers tab in the pipeline:
Release Agent
On a similar note, the release agent is a VM with access to your artifact location and a trigger set up to fire every time you produce a new version of a given artifact. Continuous Deployment trigger is available in Azure DevOps > Releases:
The square just below the trigger button is where you select from available artifacts which this pipeline should react to.
Like build pipeline, the release one is also built using a GUI interface or YAML. The above pipeline has a single step, which deploys a web application to Azure, but you can add multiple steps and set gates, which accepts conditions to be met before the step is executed (i.e. deploy multiple apps in a certain order, or don’t deploy in peak times, etc).
Host Machine
Finally, the host machine is a VM which your applications run on. It’s the machine that runs under the hood of your App Service. You can examine a local filesystem of that machine by going to Azure Portal > your App Service > Advanced Tools > Go ->, or navigating to https://your-app-svc-name.scm.azurewebsites.net/. This should take you to the Kudu console. In there, you can examine Debug console (using PowerShell or CMD), check running processes in Process Explorer, and do other exciting things.
Pros and Cons of CI/CD
- Pros:
- One-time setup
- Centralized pipelines (full control over what, when, how and if)
- Full audit trail of previous commits, builds and releases
- Automated process – you only worry about the source control and deployment takes care of itself
- Cons:
- More work to be done when setting up
Conclusion
You should now understand why CI/CD are such an important part of the software development lifecycle and what benefits do they bring to the upkeeping of your application.
In summary, outside of providing the full audit trail of your code changes, builds and releases, they help you control:
- What is being deployed
- When it is being deployed
- How it is getting deployed
- If it is getting deployed
You also now have insight into different machines that make this process seamless and the place they occupy in their respective pipelines.