Continuous integration & deployment of Angular applications

In an earlier story on better deployment of Angular applications, I described the transition my team made from packaging a manual grunt build in a Java back-end deployment to executing deployjs deploy --activate with DeployJS and having a new version deployed to S3 with close to no effort.

While continuous integration, automated testing and continuous deployment are terms often heard in back-end applications, front-end slightly lags behind. With end to end testing in Protractor and unit tests in Karma already offering great testing pipelines for Angular, all that is left is to hook those up to a test and build server.

Testing and deploying in Bitbucket Pipelines with Selenium

Our source code is hosted in Bitbucket. In 2016, they introduced Bitbucket Pipelines, a Docker-based continuous delivery framework. Later that year they extended the capabilities of running additional services next to the current solution being tested or deployed.

With Pipelines, developers can build, test and deploy solutions right from Bitbucket Cloud. (From SDTimes)
Key features for Bitbucket Pipelines, from the Atlassian Blog.

As a base image to start testing and deploying from, we needed Node installed for the DeployJS CLI and for creating Angular builds, plus Java JRE to start Protractor.

The Bitbucket Pipelines file defines an additional service to run Selenium in. If the branch the pipeline is running in is the master branch, also a deployment step is executed.

The last deployjs deploy --activate builds all assets and pushes it to an S3 bucket, updating index.html so end users receive the latest and greatest version of the application.

A few things to note is that we’re explicitly killing grunt after testing with protractor, to clear out the dist folder, which is needed for the DeployJS build step with @deployjs/grunt-build. Also the sleep 30 command might need to be customized (and can definitely be improved!) depending on how long the application takes to compile.

Is there a better way to run Protractor tests in CI/CD situations? What commands would Travis or Gitlab use to do something similar? Are you on React and can something similar be applicable to you? Did I over-complicate matters or did I take too many shortcuts? Other glaring oversights? Any feedback is welcome.