Angular DevOps Series (Part 2)

Are you searching for a solution for automating the Angular application development process? In this series, I’m taking you along with me in my journey towards a fully automated process for my Angular application. The series includes 4 parts:

Part 1: Establish Workflows from Source Code to Staging Environment Using GitHub, CircleCI, Docker and Firebase.
Part 2: First Quality Gate: Static Testing.
Part 3: Second Quality Gate: Unit Testing.
Part 4: Third Quality Gate: E2E Testing.


Angular DevOps – Part 2: First Quality Gate – Static Testing

Overview

How to answer for the questions:

  • Can I release this feature or not?
  • Can I deliver this build version to production today or not?

Using quality gates is an effectively way to ensure that software products are enforced by a quality policy. We are applying techniques which are used in almost every software development project: Static Testing and Dynamic Testing to build quality gates. In this post, I’m going to implement Static Testing on source code of Angular project and establish Auto Code Quality pipeline.

Static Testing

Static Testing is defined as a software testing technique by which we can check the defects in software without actually executing it. Goals of implementing Static Testing in our Angular project are:

  • Integrate TSLint to check TypeScript code for readability, maintainability, and functionality errors.
  • Integrate Prettier for building and enforcing a coding style guide.
  • Setup Peer Review on important Git branches.

Auto Code Quality pipeline

The auto code quality aims to run static analysis and other code checks on the current source code to understand how their implementations are impacting the code quality. Any coding problems uncovered will be provided to the developer via a report. The report is uploaded as an artifact which you can later download and analyze.
These are main goals of Auto Code Quality pipeline:

  1. Checking code quality, coding style, and coding format when a pull request is created or updated.
  2. Measure code quality with metrics.
  3. Generate reports regarding code quality status with detailed information.

How to implement Static Testing

Static Analysis with TSLint

“TSLint is an extensible static analysis tool that checks Typescript code for readability, maintainability, and functionality errors.” (Source)

TSLint is always installed when creating an Angular project using an Angular CLI tool. The tslint.json is a configuration file for TSLint. From here, you are able to customize standard rules to adapt to your project.
I’m using the TSLint recommended rules from tslint:recommended. So, in order to customize TSLint rules, I will have to add rules that will override the rules objection in the tslint.json file.

{
  "rulesDirectory": ["node_modules/codelyzer"],
  "extends": ["tslint:recommended"],
  "linterOptions": {
    "exclude": ["node_modules"]
  },
  "rules": {
    "object-literal-sort-keys": false,
    "ordered-imports": false,
    "no-console": false,
    "comment-format": false,
    "curly": false,
    "eofline": false,
    "import-spacing": false,
    "indent": false,
    "max-line-length": false,
    "no-trailing-whitespace": false,
    "one-line": false,
    "quotemark": false,
    "semicolon": false,
    "typedef-whitespace": false,
    "whitespace": false,
    "angular-whitespace": false,
    "no-empty": false,
    "member-access": false,
    "member-ordering": false
  }
}

Figure 1: A tslint.json (TSLint configuration file with Lint rules)

Here, we are executing the ng lint command to analyze source code in order to present any coding problems in a terminal screen. You need to follow the error details to fix the coding errors.

Figure 2: Code Analysis (Execute the code analysis with “ng lint” command to find coding problems)

You are able to integrate a TSLint report plugin and visualize TSLint results by installing the tslint-html-report package and integrating it to your Angular project.

npm install tslint-html-report --save-dev

Below is a TSLint HTML Report with the tslint-html-report package:

Figure 3: TSLint Error Report (TSLint Error Report with HTML format shows lint errors with detail information)

Typically, you need to fix Lint errors manually. This will be time consuming. However, we can take an easier route by using the Auto Fix On Save mode, which uses the code editor, Visual Code. To enable this, I need to edit the settings.json file in .vscode folder:

{
    "tslint.autoFixOnSave": true
}

Now, when a file with Lint errors is opened and saved, the Lint errors should be fixed automatically.
In terms of checking code problems automatically following a pull request, the use of TSLint is a fine option; this is because you will have both the support from team members who have the ability to review the source code as well as the tools necessary to do so.
However, I want to introduce a secondary coding analysis tool known as SonarQube, a tool that has more supported features for analyzing and reporting code problems visually.

To learn more about SonarQube, refer to the links below:

Coding Style Checking with Prettier

Prettier is an opinionated code formatter with support for multiple coding languages. It ensures that all outputted code conforms to a consistent style.
We are going to use the NPM command to install the Prettier package, and then execute the prettier command to verify that the Prettier is installed.

npm install -g prettier

Figure 5: A “prettier” command (Try to execute “prettier” command after the Prettier is installed)

Let’s define coding style rules in the Prettier configuration file .prettierrc. You can refer to the Prettier Rules document for other Prettier rules.

{
  "bracketSpacing": true,
  "printWidth": 100,
  "tabWidth": 2,
  "trailingComma": "all",
  "semi": true,
  "singleQuote": true,
  "useTabs": false
}

Figure 6: A .prettierrc file (A configuration file to define Prettier rules)

The command prettier –check is used for scanning specified files and checking their coding style.

prettier --check "src/**/*.ts" "src/**/*.scss" "src/**/*.json"

Prettier scans the specified files and identifies all of the files that are found to have coding style issues based on the defined coding style rules.

Figure 7: Code Style Checking (Executing the code style checking with Prettier command to scan all files with types: .ts, .scss and .json)

At this step, you are able to fix coding style issues before publishing source code. However, an issue regarding duplicate rules between Prettier and Linter (TSLint) may come about when using these two tools independently. This is because they both address the issue of code formatting. TSLint will give us the error “Spaces before function parens are disallowed tslint (space-before-function-paren)” with below lines of code:

class BadClass {
  public user = {
    name: 'Luong Mai',
    jobTitle: 'Web Developer',
  };

  getUserData           (user){
    if (user.jobTitle === 'manager') {
    }
  }
}

Figure 8: A coding format error (An example about source code with a coding format error)

The error “...tslint (space-before-function-paren)” is able to be auto fixed by Prettier when saving the source file. To do that, you need add the option "editor.formatOnSave": true to settings.json file, and then you can enjoy the results!

class BadClass {
  public user = {
    name: 'Luong Mai',
    jobTitle: 'Web Developer',
  };

  getUserData (user){
    if (user.jobTitle === 'manager') {
    }
  }
}

Figure 9: A coding format error is fixed (Source code with coding format error is fixed by Prettier)

This makes the workflow pretty useless, since we’re getting linting errors that Prettier will solve. The solution is use tslint-config-prettier package; it disables all TSLint formatting related rules. To install tslint-config-prettier, use the command:

npm install -D tslint-config-prettier

Also, update tslint.json file.

{
  "extends": ["tslint:recommended", "tslint-config-prettier"]
}

Figure 10: Extends linting rules from “tslint-config-prettier” (By extends linting rules from “tslint-config-prettier” to disable all conflicting rules)

By doing it this way, Prettier can take care of coding format and TSLint can handle the rest. Now, you are able to use Prettier and TSLint without any duplicated rule errors.

So far, you’ve been through the tutorial to setup Static Analysis and Coding Style Checking on an Angular project with support from TSLint and Prettier tools. You are able to use these tools to check code quality on a local machine before making a pull request to publish source code.
In the next section, we are going to establish a quality gate with Auto Code Quality pipeline for the workflow that was established in part 1 of this Angular DevOps series.

Peer Review

We are going to setup the Peer Review step on important branch types that need protection as develop, staging, and master. By combining the Peer Review step, Coding Style Checking step, and Static Analysis step, we are able to prevent bad code from being merged into these important branches. Let’s open the Settings panel on your GitHub repository and follow the steps in the screenshots below.

Figure 10: GitHub Branches Settings (Requires 2 approving reviews for “develop” branches)

With the above settings, a pull request will need at least 2 approvals.


How to Establish Auto Code Quality Pipeline

In this section, we will continue working on the CircleCI and the config.yml file to build steps in the Auto Code Quality pipeline.

Static Analysis and Coding Style Checking with TSLint

By using the tslint-config-prettier package to fix the issue between Prettier and TSLint, we added Prettier tasks for Coding Style Checking to TSLint pipeline. From here, you only need to run TSLint to analyze source code and check coding style.

TSLint is always installed as a built-in dependence in an Angular project. Thus, you don’t need to install it on the CircleCI container. Your remaining tasks are:

  1. Execute the command npm run lint to start the process code analysis.
  2. Generate a TSLint report and save it as an artifact to review or download from team members.

Following the guidelines needed to use tslint-html-report package, you can make a Gulp command in the gulpfile.js file in order to generate a TSLint HTML Report. Be sure to push the gulpfile.js file into the root project folder.

var gulp = require('gulp');
var tslintHtmlReport = require('tslint-html-report');

gulp.task('tslint-report', function (callback) {
  tslintHtmlReport(TSLintReportConfig, callback);
});

var TSLintReportConfig = {
  tslint: 'tslint.json', 
  srcFiles: 'src/**/*.ts', 
  outDir: 'code-quality-report',
  html: 'tslint-report.html',
  breakOnError: false,
  typeCheck: true,
  tsconfig: 'tsconfig.json'
}

Figure 11: A gulpfile.js file (Define a command “tslint-report” in the gulpfile.js to generate a TSLint HTML report)

Now, let’s add the next steps to the static-testing job in the config.yml file.

static-testing:
    executor: my-executor
    parameters:
      target-path:
        description: Path for report directory
        type: string
        default: code-quality-report
      artifact-path:
        description: Path that will be used when storing result as artifact
        type: string
        default: Report/Code-Quality
    steps:
      ...
      - run:
          name: Install Gulp package globally
          command: sudo npm i gulp -g
      - run:
          name: Static Analysis
          command: npm run lint
      - run:
          name: Generate Static Analysis Report
          command: gulp tslint-report
          when: always
      - store_artifacts:
          path: << parameters.target-path >>
          destination: << parameters.artifact-path >>

Figure 12: A config.yml file (Define the “static-testing” job)

Integrate the Static Testing Gate to CI Workflows

We have to push the source code to go through the Static Testing gate before it comes to the Auto Build and Auto Deploy pipelines. If there are any code problems, the Static Testing gate will prevent the source code from the running the workflow and notifying code problems to the developer.

To do that, let’s open the config.yml file and edit the section workflows. We need to let the CircleCI know about the static-testing job, and require this job in build job.

workflows:
  version: 2
  nightly:
    triggers:
      - schedule:
          cron: '0 0 * * *'
          filters:
            branches:
              only:
                - master
    jobs:
      - build
  commit:
    jobs:
      - setup-environment
      - static-testing:
          requires:
            - setup-enviroment
      - build:
          requires:
            - setup-environment
            - static-testing
      - build-docker:
          requires:
            - build
          filters:
            branches:
              only:
                - /staging-.*/
                - master
      - deploy:
          requires:
            - build
          filters:
            branches:
              only:
                - master

Figure 13: A config.yml file (Setup the “static-testing” job in CI workflows)

Integrate the Static Testing Gate to Git Branches.

We also need to ensure that quality checks are passed before a pull request is merged. Opening the Settings panel again, be sure to require quality checks for your branches.

Figure 14: GitHub Banches Settings (Requires the ‘static-testing’ check for a pull request)

Coding Style Checking and Static Analysis are included in the static-testing option.


Verify Auto Code Quality Pipeline

In this section, I’m going to trigger the Auto Code Quality pipeline from a pull request. By doing it this way, we are also able to verify that the steps Coding Style Checking and Static Analysis are working for the defined goals.
I created a new branch, zth-002, from the develop-1.0.0 branch to fix bug, BUG-2. After that, I’ll make a pull request to merge zth-002 to the develop-1.0.0 branch, and request 3 reviewers to review my pull request.

Figure 15: A Feature Pull Request (Make a pull request to merge zth-002 branch to the develop-1.0.0 branch)

Following the above settings, the Auto Quality pipeline is triggered and requires:

  • Need least 2 approvals.
  • Check points setup-environmentbuild, and static-testing must be PASSED.

Figure 16: All required quality checks (All required quality checks are executed when submit a pull request)

You are able to merge the pull request with the quality points that are PASSED.

Figure 17: The pull request is ready to merge (All required quality checks are PASSED and the pull request is able to be merged)

To see details of the Static Testing or any quality checks, click on the Details link to view CI build details.

Figure 18: A “static-testing” CircleCi build (A “static-testing” CircleCi build is completed with a TSLint Report)

Now, let’s make a small change on the pull request.

I created some lines of code smell, enabled a code checking rule no-hardcoded-credentials, and made a new commit. The Auto Code Quality pipeline is triggered to immediately verify code quality and requires a reviewer to review new changes.

Figure 19: All required quality checks (All required quality checks are executed when a pull request is updated)

Now, you can see the Static Testing gate prevented the bad source code from continuing on and updated the status to “FAILED” on the pull request.

Figure 20: A “static-testing” quality check is failed (A “static-testing” quality check is failed with any coding style errors)

Let’s see the error details on CI build. From here, you are able to fix bad lines of code and update the pull request again.

Figure 21: A “static-testing” CircleCi build (A “static-testing” CircleCi build is completed with a TSLint Report)


Summary

Let’s take a look at all we’ve accomplished in this part of the series.

In this article, Angular DevOps – Part 2: First Quality Gates – Static Testing, we implemented the Static Testing gate on an Angular project and integrated this quality gate to our CI workflows by establishing the Auto Code Quality pipeline.
Below is our CI workflow chart so far.

Next up, we are going to add the quality gates Unit Testing and End-to-End Testing to continue to improve the quality. Stay tuned for part 3!

Luong Mai
Luong Mai joined LogiGear in 2012 as an Automation Engineer. Currently, he works as a Software Developer for MOWEDE. He is responsible for developing front end applications (mobile, web) and DevOps in web development. Mai loves to automate everything in software development in order to maximize the productivity of development teams and is actively involved in developing software framework in MOWEDE
Luong Mai
Luong Mai joined LogiGear in 2012 as an Automation Engineer. Currently, he works as a Software Developer for MOWEDE. He is responsible for developing front end applications (mobile, web) and DevOps in web development. Mai loves to automate everything in software development in order to maximize the productivity of development teams and is actively involved in developing software framework in MOWEDE