Accelerating CI – Part 3: Incremental CI

In my previous blog posts, I explained how parallelization and resource allocation optimization help developers accelerate their CI workflows. Today, I would like to introduce you to another method of optimizing software development processes, which I call “incremental CI”. As its name suggests, it relies on analyzing the source code differences between two versions.

Incremental processing

Nowadays, in order to further increase their productivity, developers include tasks other than builds and tests in their CI workflows. The most common examples are the tools to check code styles for adherence to coding standards and to measure code metrics. Some of these tools, such as gofmt and golint, are designed to process only the files that are passed as inputs and are not affected by any changes in other files. In the case of those tools, the results about input files with no changes are always exactly the same, no matter how many times they are executed. By reusing the result of the previous execution, Inspecode brings a significant performance gain.
To enable this behavior in Inspecode, you should set the value of the incremental parameter to true, as shown in the below example:

inspecode:
    experimental:
        incremental: true

It is important to note that, with Inspecode, incremental processing can also be enabled or disabled on a tool-by-tool basis. In the example below, incremental processing is enabled on gofmt and disabled on golint.

inspecode:
    experimental:
        incremental: true
    gofmt: default
    golint:
        experimental:
            incremental: false

It is also important to note that there are several cases that might cause different results, even if the input source files are not modified:

  • Changes are made in the tool’s option settings
  • The tool’s configuration file is updated
  • The tool is upgraded to a newer version

To avoid any issues in the above scenarios, we take a conservative approach, where the tools are set to process all the input files, no matter if these were updated or not.

Automatic task skipping

Automatic task skipping greatly increases the speed of CI workflows. If incremental processing is enabled and Inspecode does not detect any change on all the target files of a tool, the execution task of the tool will be automatically skipped. You don’t need to write special words like [ci skip] in commit messages. For example, if the all the updates exclusively concern the README file, while the Go source code files are untouched, the execution of golint is skipped. Inspecode reports the same golint issues as detected in the previous task. Hence, the status of the skipped task also remains unchanged from the previous task.

Similarly, if the input and ignore clauses in rocro.yml includes no target files, Inspecode will skip the execution of the tool automatically. The below snippet illustrates a case where all the target files for golint are ignored:

inspecode:
    experimental:
        ignore: "**/*.go"
    golint: default

In the above example, the task execution is skipped regardless of whether incremental processing is enabled or disabled. The status of the task will always be Skipped. You should review the input and ignore settings if the task status is Skipped, although you did not cancel the job including the task.

This blog post introduced you to incremental processing, one of the methods Inspecode uses to help developers speed up their CI workflows. Currently, Inspecode analyses file changes and conservatively decides if incremental processing can be executed so that all the issue reports of tools never change. In the future, we are thinking about making incremental processing the default option. I hope this blog post included useful information that will help you further optimize your CI workflows.