CI/CD an ASP.NET Core application to Plesk/Azure
This article will cover what you need to do to continuously deploy your ASP.NET Core application to a Plesk or Azure environment.
Creating the project
- Start by creating an ASP.NET Core project in Visual Studio
- Just create the project with the default settings.
- Add the project to your github account
Setup github action
We’ll now setup a github action that does the following:
- Build the project
- Checkout a
deploy
branch - Commit the build on the deploy branch
As you can see, we need an SSH keypair. Let’s create it:
ssh-keygen -t rsa -f deploy
This gives us a
deploy
file containing the private keydeploy.pub
containing the public key
We need to add the SSH_PRIVATE_KEY
as a repository secret. So in your github repository under Settings → Security → Secrets and variables → Actions we can add it:
And the SSH_PUBLIC_KEY
needs to be added under Deploy keys
Before we go further, we can simply create a deploy
branch through the github website:
Create a deploy
branch.
We can now commit and push this project setup to github, and check if the branch gets a new commit with the published files.
The workflow succeeded, and we can now see our build in the deploy
branch:
Creating the website in Plesk
Add a new domain or subdomain
Configuring the git-hook
This brings you to the following overview
You can now click the Deploy now button:
- This pulls the files from the
deploy
branch to the document root - Since we have the deployment inside a
deploy
folder, and not straight under the repo-root, this doesn’t cause any file conflicts - After this, the post-deployment script is executed
- The
app-offline.htm
file shuts down the website, and releases the lock on theexe
anddll
files - Somehow, the recommended way to have a delay in batch, is by using a ping. Here we wait 2 seconds until the application pool has fully shutdown
- We delete all dll’s, exe’s and pdb’s from the application root, then wait another 2 seconds (it’s necessary)
- We use XCOPY to copy the files inside the publish folder to the webroot. I think MOVE would also do it okay
- Then we once again wait 2 seconds, before deleting the
app-offline.htm
andpublish
folder
Note that we (or at least I) cannot use dotnet
in this script. Otherwise it would be pretty easy, right? This is why we have to do the build in Github, and push the result to another branch
Configure the webhook
Last but not least, we have to setup a webhook that sends a notification from Github to plesk to indicate that there’s a new commit on a branch. Go to the git module in your plesk website and click the switches in the bottom-right of the card.
Here you need to copy the Webhook URL, then in Github go to your repository → Settings → Webhooks → Create webhook → Pastte the url under Payload URL
- Content-type: application/json
- Just the push event is okay
- Make sure the webhook is active
Test
Now try doing some changes to the project and verify that they’re being deployed fine, without the script exiting in advance. This is why the delays (pings) are added to the script.
Warning
Obviously you need to make sure nobody else can push commits to your master/deploy branch.
Conclusion
We have successfully configured our repository to deploy the master branch to a Plesk/Azure environment. We leveraged app_offline.htm
to suspend the web application, which releases the lock on the exe and dll files.
I have considered using Github actions rightaway to deploy the files to the webserver, but since the exe and dll files are locked by the webserver, they cannot be overwritten. An untested option is to do the following in our github action:
- Create
app_offline.htm
using echo - Upload this file through FTP
- Delay by using
sleep 2s
orStart-Sleep -s 2
- Upload the files through FTP, fingers-crossed existing files can be overwritten and are no longer locked
- Delay 2 seconds again
- Remove
app_offline.htm
By organizing the deploy
branch so that the files are inside a subfolder, we no longer need a pre-checkout script to create app_offline.htm
to suspend the application pool. We don’t have a pre-checkout script, so this is a nifty workaround.
We can’t use dotnet
in the post-deploy script.