Initial thoughts on deploying with Octopus
I recently began using Octopus to deploy our ASP.NET Core line-of-business web application. Previously I had configured Team Foundation Services (TFS) to do this. The web application was already being built using TFS as part of our Continuous Integration (CI) pipeline, so I had configured TFS to also take care of the Continuous Deployments (CD) too.
I had three deployments configured. One for Development (which was triggered automatically by the build) and one each for our Staging and Production environments. The former deployment was to an on-premise server and was to give the developers an environment where they could test their changes. This Development environment would always have the latest changes as it was triggered by the build server as part of the CI / CD pipeline. The Staging and Production environments were both Azure web sites and would be triggered manually. We didn’t want un-tested changes going into our Staging or Production environments.
In the beginning, the Staging and Production deployments were configured under TFS. This all worked perfectly well until Microsoft updated their Powershell scripts to use the latest RM (Resource Manager) versions. As the TFS deployments to Azure environments use Powershell scripting under the covers, this had the effect of breaking our Azure deployments to our Staging and Production environments. At this point, we could no longer deploy to the Staging or Production environments.
I initially investigated fixing the underlying Powershell scripts to use the updated RM versions, but this involved re-writing some quite complex scripts, and I wasn’t comfortable doing this. I then looked to see if Microsoft has provided any updates for this script but there didn’t appear to be any. As a temporary workaround I decided to write some FTP scripts to do get the job done. I used WinSCP to deploy to our Staging and Production environments.
I wrote two WinSCP scripts. One for deploying to Staging and one for deploying to Production. They both followed the template below. The heavylifting of the deployment is the
synchronize command. This effectively checks for any changes between the local and remote servers and updates to the latest as necessary.
Hide Copy Code
option batch abort
option confirm off
option transfer binary
synchronize remote "C:\Builds\TFS\MyWebApp\Latest" /site/wwwroot
This worked well enough but wasn’t bulletproof. It would sometimes fail when unable to copy one of the assemblies. The assembly was being cached by the Azure web server, and so the deployment would fail. I got round this problem by writing a Powershell script to stop / start the Azure web hosting.
The deployment scripts performed the following tasks.
- Stop the Azure web site (Powershell script)
- Deploy the latest changes (using WinSCP)
- Start the Azure website (Powershell script)
I have previously written an article on how to stop / start an Azure web site here.
So although all these scripts worked and deployed to the Azure environments successfully, having to write and maintain these scripts seemed a bit klunky. I wanted something more robust for our CD pipeline than a bunch of hand written scripts.
This is where Octopus comes in. I’d very briefly looked at Octopus at a previous company I worked for. I decided I would use this for our deployments to our Azure environments. I would still keep the on-premise CD pipeline for Development but use Octopus to deploy to our Azure environments. I created an account with Octopus and began configuring our deployments. It took me a morning to get everything working. I won’t go through a step-by-step guide as these can already be found within the Octopus documentation on their website (and as every deployment configuration is unique it probably wouldn’t be a very useful exercise anyway).
I was very impressed with just how easy and flexible it was to configure our deployments. The documentation was very helpful and all the options and settings all seemed intuitive. If you’re familiar other CD IDEs then Octopus will not be difficult to pick up.
I have a script that is part of our CI pipeline that creates a nuget package from our published artifacts and pushes this nuget package to our Octopus environment. I downloaded and installed the Octopus tools onto our build server which then allows me to invoke the
Here are the two commands the CI pipeline invokes for creating the necessary nuget package and then pushing this to our Octopus environment.
Hide Copy Code
octo.exe pack --id MyWebApp --version %1 --basePath "C:\Builds\TFS\MyWebApp\Latest\websharelatest" --outFolder outputfolder
Hide Copy Code
octo.exe push --package=outputfolder\MyWebApp.%1.nupkg --overwrite-mode=OverwriteExisting --server=https://mydomain.octopus.app --apiKey=API-QWERTY123456 --debug --LogLevel=debug
When we’re ready to deploy to our Azure environment(s), we simply create a new release within Octopus and deploy the latest nuget package which our CI pipeline has already made available for us.
All in all, moving to Octopus has totally streamlined our CD pipeline. It is far more robust and uses a first class technology now instead of the myriad klunky scripts it used previously. We haven’t had a single issue since switching to Octopus. If you really want to take your deployments to the next level, then I’d highly recommend looking into Octopus.