For anyone who uses Azure Powershell scripts, it will come as no surprise that as of November last year, they deprecated all their existing Powershell functions that related to Azure. These have instead been replaced with new Azure Resource Manager (ARM) equivalent functions. These new functions supercede the previous suite of Azure Powershell functions. Microsoft began initially deprecating these as far back as 2018, but due to pressure from the development community, Microsoft delayed this for a further year to give developers more time to find workarounds and / or solutions.
I was blissfully unaware of this fact, as I do not make any direct use of their Azure Powershell functions anywhere in our development ecosystem. I only became aware of the fact that these Azure Powershell functions were deprecated when our Team Foundation Services (TFS) deployments to Azure started failing. Unknown to me, the TFS Azure Web App Deployment task uses an Azure Powershell script to push deployments to Azure. This Powershell script implemented several of the now deprecated Azure Powershell functions. Hence it began failing as the functions it was attempting to invoke no longer existed.
This left me in the rather awkward predicament of not being to deploy any of our ASP.NET Web API services to Azure. No new features could therefore be deployed for any of the apps that consumed these services. All of our web and mobile apps consume these services, so until I found a solution we would be unable to release any new features and / or maintenance fixes for the apps that consumed these services.
I began scrambling to look for a solution. I came across several articles that outlined the replacement functions and how to implement them. This was all well and good, but I didn’t particularly want to have to rewrite the entire Microsoft Azure Powershell script that was responsible for deployments using the new ARM functions. I tried looking for a new version of the original Azure Powershell script, but could only find the existing version on Github. There didn’t seem to be an updated version of this script anywhere.
I could either rewrite the original Azure Powershell script myself (which for obvious reasons I wasn’t particularly keen on doing), or try to find another solution. After some further head scratching, I had an epiphany. Why didn’t I write an FTP script that would deploy to Azure? From the Azure portal for a web app, you are able to download the publishing profile. The publishing profile (among other things) contains the FTP details required to connect to your Azure web app.
So I looked at writing a simple FTP script. I needed an FTP client that could be invoked from the command line (and therefore be scripted) as I didn’t want this to be a manual task. I wanted this to work exactly as it already did i.e. to be a TFS task (and also because after each deployment to a particular endpoint I run a suite of unit tests to ensure that the code all works correctly from the Azure hosting).
I had previous experience of using WinSCP[^] so knew that this would do the job. I had only ever previously used WinSCP for uploading single files, never for uploading the hundreds of files our ASP.NET Web API services contained. After some further research I discovered that WinSCP contained a command called synchronize. This command would synchronize a local directory with a remote one, including all sub-directories. This was exactly what I needed.
I eventually wrote the following scripts that deploy our services to Azure. They are invoked from our TFS build so there is no change to our deployment process whatsoever.
Here is the batch script that is invoked from the TFS deployment task.
Hide Copy Code
cls"C:\Program Files (x86)\WinSCP\WinSCP.com" /script=ftpDeployServices.ftp
Here is the FTP script containing the WinSCP FTP commands (ftpDeployServices.ftp).
Hide Copy Code
option batch abort
option confirm off
option transfer binary
synchronize remote -delete <mylocalfolder> /site/wwwroot
The synchronize command does all the heavy lifting of checking the timestamps and uploading only those files that have changed. The -delete parameter removes any files from the remote site that don’t exist on the local site. If no files have been changed since the last deployment, then no files are uploaded. Only those files that have been changed are uploaded. This results in much faster deployments as only the incrementally changed files are ever uploaded.
By hand rolling my own FTP script means that I am no longer at the mercy of any future changes to any Microsoft related Powershell script(s) or infrastructure. This means I have one less headache to worry about. In fact, the updating of the previous Azure Powershell scripts was a blessing in disguise, as my workaround is faster and reduces our dependency on Microsoft infrastructure. A good result given the severity of the impact that this update had on our deployment process.