Custom Deployments to Netlify
CI/CD workflow for Netlify and Azure Devops or any continuous delivery service

CI/CD workflow for Netlify and Azure Devops or any continuous delivery service
I'll describe the process for Azure Devops, but this should carry over to any other system, or just by running the commands on your local machine. With this method we can support any branching strategy or continuous integration and deployment process outside of the default integrations provide by Netlify, even monorepos and/or promoting a single build through different environments.
tldr
Install the cli on your build server and run the deploy command
Netlify and Site Setup
Login to Netlify and create a personal access token from the application settings. Give it a name, copy it and store it somewhere safe, you'll never be able to access it again from Netlify.
Install the netlify-cli locally:
yarn global add netlify-cli
Now we'll run the tool locally first in order to create the site and retrieve and a site id to be used later. I was unable to figure out how create a site on Netlify without connecting to my repo, but if you were able to do this and have the site id already you can skip this part.
Build your website locally, for my react app the command is:
yarn build
This command produces a folder to called build
that holds the static app to be deployed.
To create your site and retrieve the site id run the following command with your static directory and personal access token. Answer the prompts to create the publish the site.
netlify deploy --dir "build" --auth "qIBibTwvKkE39hY8mdkT_mXZoRh7Ub9cK9hNsqrxem4QJ6sQa36VHfyuBe"
If you did something wrong and the process hangs don't worry about it, if your pat was correct a site would have been created and you'd have your site id so you can ctrl - c the process.
I've created two sites for my app, one for staging and one for production. Our pipelines will deploy first to the staging environment, and if everything looks good I will approve it to move to production. Doing it this way allows us to have static urls for the app in each environment which differs from the dynamic urls produced by Netlify if you use their git integration.
Continuous Integration with Netlify
My build pipeline for a react app called netlify-cd in a monorepo looks like this:
trigger:
branches:
include:
- master
paths:
include:
- netlify-cd/*
pool:
vmImage: 'ubuntu-latest'
steps:
- script: 'yarn install'
workingDirectory: 'netlify-cd'
displayName: 'yarn install'
- script: 'yarn build'
workingDirectory: 'netlify-cd'
displayName: 'yarn build'
- task: PublishPipelineArtifact@1
inputs:
targetPath: 'netlify-cd/build'
artifact: 'drop'
publishLocation: 'pipeline'
With the triggers specified only changes to the react app on the master branch will trigger a build (you can change this to fit your branching strategy). From the application's working directory we install our dependencies, build, and publish our artifacts for use in the release pipeline.
Continuous Delivery with Netlify
Create a release pipeline linked to the artifacts from your build pipeline, mine looks like this

We have a cd trigger to automatically deploy to our staging site on successful builds and a required approval on the production stage.
We need to create some variables to be used in our pipeline
- Netlify.Auth.Token - scope: release, type: secret
- Netlify.Site.Id - scope: stage, type: text
- Netlify.Site.Id - scope: production, type: text
Fill out the variables with your site info.
In each stage I have one job with 3 script tasks, and if you're using the variables as I've specified the stages can be clones of each other that only differ by name.
- update runtime config (not required, check here if interested)
- install netlify-cli
- netlify deploy
Installing a global package in Azure Devops
To install the package on Azure's hosted Ubuntu agents the command is:
sudo yarn global add netlify-cli
Sudo is required and you won't be able to use the package if not part of the command. If you're using a Windows agent the command without sudo should just work as expected.
Deploying to Netlify
This is the important part that allows us to use any build or deploy system to deploy to netlify. The command for my app is:
netlify deploy --prod --dir "$(System.DefaultWorkingDirectory)/_netlify-cd/drop" --site "$(Netlify.Site.Id)" --auth "$(Netlify.Auth.Token)"
Yours might differ a little depending on how your packaged your artifacts from the build pipeline.
Here are the different options you can use from the netlify-cli github README
Flags
dir
(option) - Specify a folder to deploy
functions
(option) - Specify a functions folder to deploy
prod
(boolean) - Deploy to production
open
(boolean) - Open site after deploy
message
(option) - A short message to include in the deploy log
auth
(option) - Netlify auth token to deploy with
site
(option) - A site ID to deploy to
json
(boolean) - Output deployment data as JSON
timeout
(option) - Timeout to wait for deployment to finish
And that's a wrap. We are now able to deploy from Azure Devops even though Netlify offers no integration with Azure Repos and we have a better deployment strategy than the one offered by Netlify as well.