The new workflow uses Docker-based build, managed by a declarative pipeline in Jenkins. All images and volumes are unique per Git branch to avoid contamination. The declarative pipeline consists of four major sequential phases:
- Filter and preinstall dependencies into Deps image.
- Build the Builder image.
- Run the application build and QA.
- Package the application for each platform.
Process packages.json
with jq
to extract and presort only the crucial package information and dependencies, when building the Deps image. This allows skipping rebuilds completely, even if other members in package.json
change. Also, it ensures the image layers are as small as possible to increase container launch speed. This phase Node 16.
Use Node 16 to build the DLL, then use Electron to prebuild the Main module.
Both builds depend on code that changes infrequently, allowing CI to cache and skip steps in future. Steps are ordered from least to most likely to change, in order to increase chance of cache hit. Output is produced outside of the app
tree, in order to keep the latter unmodified for the upcoming phases.
This phase entirely consists of stages running in parallel, using the Builder image:
- Run Mocha test
- Run ESLint
- Build the Renderer module; output directed outside the
app
tree, onto a Docker volume for upcoming phases
All stages use read-only bind mounts of source code and tests into their containers, in order to guarantee code staying unmodified, to avoid sending unnecessary data into Docker context (faster builds) during all earlier phases, and increase container launch speed in later phases.
Launch containers per each platform in parallel to package the Electron app. Stages matrix is defined by Carthesian product of package type (win, deb) by CPU arch (32, 64). The containers are completely independent, and each uses its own Docker volume to cache web downloads between builds, and its own output directory that is bind-mounted from the Jenkins workdir.
When packaging completes, Jenkins picks up the packaged artifacts and stores them for the last 5 successful builds of each branch. Finally, the CI cleans up the intermediate artifact directories and Docker volumes, and posts an update to Slack.