Azure / Office 365 / SharePoint Development / Search

Use build and release pipelines in VSTS to automate your SharePoint Framework deployments

May 08, 2017

A while ago I wrote two articles about how you can automate the publishing process of your SharePoint Framework scripts and solution package via custom gulp tasks.

Info: you can find the articles here and here.

These gulp tasks are already a great step forward but still, requires you to manually launch these gulp commands to push everything to your environments. For publishing, this requires you to execute the following steps: bundle, package, upload scripts, and package.

A couple of weeks ago, when I was setting up a build pipeline for another project, I saw that the gulp and npm build tasks became available in preview on Visual Studio Team Services. These tasks are a great way to automate the deployment process. So, that you only have to commit and push your code (if you use Git of course).

Something else which is great about it is that you can set up multiple builds and release pipelines which allow you to target various environments (development, test, production, …).

Here is an example of the build process:

Build pipeline / tasks

Build pipeline / tasks

In my case, when I push a new release to Git, the build process automatically picks it up and executes the following tasks:

  • Get all files
  • Get all dependencies via the npm install command
  • Update the CDN URL in the manifests JSON file. For this, I created a simple gulp tasks. That way you can change the URL per build task. Here is the code snippet of the task:

  • Bundle the project via the gulp bundle --ship command
  • Package the project via the gulp package-solution --ship command
  • When the project is bundled and the solution package is created, everything will be zipped and published ready for release.
Build tasks

Build tasks

Once the build process is completed, the release task will automatically start the continuous deployment feature.

Info: if you want you can configure everything in the build pipeline, but when you are working with multiple environments. You would most probably like it to set it up via a release pipeline.

Here you can see the output of my production deployment:

Release pipeline

Release pipeline

It is not as fancy as the build output, but it does the following tasks:

  • Retrieve the zip package (this is done automatically, so you do not have to configure it)
  • Extract the files from the retrieved package
  • Upload the SharePoint Framework project bundle files to the SharePoint CDN library
  • Upload the app package to SharePoint
Release tasks

Release tasks

Info: for the upload gulp tasks to SharePoint I made use of the approach I explained in the two articles about automation for SPFx. Only a small change has been made to allow you to make use of gulp arguments. That way, it is not done from a configuration file in your project, but via variables in the build and release pipeline instead.

Sample result of the web part

Sample result of the web part

In the next article, I will explain how you can configure the build and release pipelines yourself.


  • Pingback: Surviving the Rise of the Cloud; SharePoint Library Failures; Windows as a Service Changes()

  • Pingback: Configure a build and release pipeline for your SharePoint Framework solution deployments - @eliostruyf()

  • Gert Braspenning

    One gotcha is that “gulp bundle –ship” seems to return 1 as a statuscode if there are still any warnings left from tslint. In vsts this will throw an error when running the gulp task. It does not throw the error when removing the –ship argument.

    • Good catch, but removing the –ship argument is no option. This means that you will create debug bundles and the package will link to the localhost site instead of the CDN.

      If you want to ignore the tslint warnings, you can also turn them off in the tslint config file (config directory). IMO these are things you have to solve before going to production.

      • Raymond Little

        Great spot I’ve just spent the last couple of hours trying to get to the bottom of this issue. Will try turning off these warnings and see if this fixes it

        • Another way is to enable the continue on error option under the task “control options”

        • Raymond Little

          Thanks. I tried to change all my tslint settings yesterday but i’m still getting errors. I think all my tslint warnings are gone but it still fails. The only warnings I’m getting now are sass caml case ones, would they stop the build?

          I’m not sure about enabling the continue on error as this would mean any actual errors wouldn’t get caught. Any ideas? Seems like a silly issue to be experiencing in what is otherwise a really cool piece of functionality

        • The SPFx warnings are considered as errors in the process.

          You could also suppress them. You can do this in the gulpfile.js file. Like this:

          So you will have to copy the whole message from within your build, and create a new suppression.

        • Raymond Little

          ah ok so any warning cool. I’ll try that thanks

  • Pingback: Easy ways to subscribe to a SharePoint List Webhook – YP code()

  • Abhi

    All works fine but when I am trying to deploy to tenant which is integrated with Azure AD its giving 401 error. Any suggestion ?

    • Check if you are using any special characters in the password. I recently found out that VSTS has problems with & in variables.

      • Abhi

        I get same error when I try to deploy directly by running gulp task from VS Code where Azure AD is integrated

        • What do you provide as arguments?

          Also try to turn on verbose logging by adding verbose:true to the tasks. When you run the command again, you should get information about what it did and where it fails.

        • Abhi

          yes verbose is on. This is the error I see.

          Unhandled rejection StatusCodeError:
          401 – undefined

          at new StatusCodeError

          at Request.RP$callback [as _callback]

          at Request.self.callback

          at emitTwo (events.js:106:13)

          at Request.emit (events.js:191:7)

          at Request.

          at emitOne (events.js:96:13)

          at Request.emit (events.js:188:7)

          at IncomingMessage.

          at IncomingMessage.g

          at emitNone (events.js:91:20)

          at IncomingMessage.emit

          at endReadableNT

          at _combinedTickCallback

          at process._tickCallback

        • Would you be able to share your arguments. You can replace them with tokens, but I want to see how you formatted them.