Web, mobile, and desktop are the three most popular software application platforms. The emergence of Electron.js made it possible to develop cross platform apps for all three of these platforms. With HTML, CSS, and JavaScript being the default languages for the web, developers can now extend their range of application development by using the same technologies to build mobile applications (made possible by the Cordova project) and desktop apps. In this article, we will be configuring a continuous integration (CI) pipeline to build distribution copies of our desktop applications for different operating systems.
Prerequisites
To follow this tutorial, a few things are required:
- Basic knowledge of JavaScript
- Node.js installed on your system (version >= 11)
- A CircleCI account
- A GitHub account
- Familiarity with Electron.js (Not a deal breaker but would be nice).
With all these installed and set up, let’s begin.
Creating a simple Electron project
Let’s quickly scaffold a simple Electron.js application by running the following command:
npx create-electron-app my-electron-app
In the command above, we use npx
to invoke the create-electron-app
utility to scaffold a new Electron.js application in the folder my-electron-app
. We are using create-electron-app
because it helps scaffold an Electron.js application that comes prepackaged with electron-forge, a tool used for packaging and creating distribution builds of our Electron.js desktop application.
Note: You don’t need to have create-electron-app
installed globally to use it. That’s why we are using npx
.
Once the scaffolding process is done, go into the root of the project (cd my-electron-app
) and run the following command to start up the desktop application:
npm start
This will run a local build for your current operating system and boot up the desktop application.
The screen above shows the development tools opened. This is not something you will want in production. Comment out the line below in the file src/index.js
to stop this from opening.
mainWindow.webContents.openDevTools();
Then terminate the app running by hitting Ctrl + C
while you’re on the CLI (Command Line Interface) running the application. Then run npm start
again to relaunch the application.
Now, as seen in the screen above, only our application screen is displayed in the app window.
Configuring the build platforms
As mentioned earlier, the scaffolded project already comes packaged with electron-forge
, which is a package that can help us produce distribution builds from our app. In our case, we are going to be creating a distributable .zip
build for Linux
platforms and a .deb
package for Debian-based Linux distributions such as Ubuntu.
To configure this, replace the config
section in the package.json
file with the following configuration:
"config": {
"forge": {
"packagerConfig": {},
"makers": [
{
"name": "@electron-forge/maker-zip",
"platforms": [
"linux"
]
},
{
"name": "@electron-forge/maker-deb",
"config": {}
}
]
}
},
The electron-forge
package uses a number of internal utilities known as makers
to create distribution builds for different platforms. makers
exist for creating distribution builds for MacOS, Windows, and Linux platforms. In the file above, we have configured two makers
, maker-zip
and maker-deb
, to generate the .zip
file for Linux and the .deb
file for Debian-based platforms, respectively.
For more information about configuring makers
for different platforms, visit the makers documentation page.
Now we have the complete electron-forge
configuration to create our distribution builds.
Connecting the project to CircleCI
Our next task is to get our Electron.js desktop application project set up on CircleCI. Begin by pushing your project to GitHub.
Next, go to the Add Projects page on the CircleCI dashboard.
Click Set Up Project to begin.
On the setup page, click Add Manually to instruct CircleCI that we would be adding a configuration file manually and not using the sample displayed. Next, you get a prompt to either download a configuration file for the pipeline or start building.
Click Start Building. This build will fail because we have not set up our configuration file yet. This we will do in the next section.
Automating distribution builds and storing the build outputs
Time to write our CI pipeline. The following operations need to be done by our pipeline:
- Checkout the repository
- Update npm
- Install project dependencies
- Install system dependencies for target builds (The
.deb
package requires two system packages;dpkg
andfakeroot
, to be installed for a.deb
file to be generated) - Generate the builds
- Store the distributable build files as artifacts that can be downloaded
Inside the root of the project, create a new folder named .circleci
. Within this folder, create a file named config.yml
and enter the following code into it:
version: 2.1
jobs:
build:
working_directory: ~/repo
docker:
- image: circleci/node:11
steps:
- checkout
- run:
name: Update NPM
command: "sudo npm install -g npm"
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: Install Dependencies
command: npm install
- run:
name: Install dpkg and fakeroot
command: |
sudo apt-get update -y
sudo apt-get install -y dpkg fakeroot
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- ./node_modules
- run:
name: Generate Builds
command: npm run make
- store_artifacts:
path: ~/repo/out/make
In the above configuration file, we perform all of the tasks that we listed earlier. Let’s go through the important sections.
First, we specify the working directory for the operations we want to perform. We then specify the Docker image with the minimum required Node.js installation.
Next, we checkout
the project from the remote repository and install dependencies. Then we install dpkg
and fakeroot
using admin privileges.
We finish off by generating our configured builds by running the electron-forge
package’s make
command.
Finally, we store the distributable files, which are located in a generated /out/make
folder.
Commit and push these changes to your GitHub repository. This will trigger the pipeline to go into action and run. You can view it running on the Pipelines
page of the CircleCI console.
You can view the process details by clicking build.
As seen in the above screen, the Upload artifacts
section shows that we now have our two builds generated and stored.
Downloading stored build artifacts
Downloading our builds is pretty easy, click the Artifacts
tab on the build screen and you will see links to download your distributables.
You can now download both the zipped package and the .deb
installation file.
Conclusion
With Electron.js adding more superpowers to web developers by enabling the creation of desktop applications with HTML, CSS, and Javascript, it feels like web developers can now build almost anything. This is pretty exciting!
Distributing applications to end-users is also a very important part of that process and in this tutorial, we have seen how easy it is to create installable desktop applications and even automate the process of packaging distributable builds using CircleCI.
If you are not getting the desired results, please go through the article once again to see if there’s anything you may have missed.
Happy Coding!
Fikayo Adepoju is a LinkedIn Learning (Lynda.com) Author, Full-stack developer, technical writer, and tech content creator proficient in Web and Mobile technologies and DevOps with over 10 years experience developing scalable distributed applications. With over 40 articles written for CircleCI, Twilio, Auth0, and The New Stack blogs, and also on his personal Medium page, he loves to share his knowledge to as many developers as would benefit from it. You can also check out his video courses on Udemy.