-
Notifications
You must be signed in to change notification settings - Fork 12
Distributing tC: Package Build Publish
Distributing an Electron Application such as translationCore via tools, configuration and continuous integration services.
This covers what it takes to go from running npm start
to being able to download and install the application.
This documentation is for tC developers to better understand the process involved.
While these can be complicated steps, a single tool partnered with Continuous Integration services can make this much easier to deal with than using separate tools and scripts.
- Package (via electron-forge)
- Build/Make (via electron-forge)
- Publish/Release (via continuous integration services)
- Tag/Version (via script)
- electron-forge
Electron-Forge is used bootstrap templated electron apps including react ready ones to help you get started creating an app, including many best practices such as babel, web-pack, es-linters like air-bnb. What it really offers us is abstracting the complicated Packaging and Building processes so that we don't have to.
Before you can use the app, you have to make sure Electron-Forge is installed. There is an alias to make sure we are all using the same version of Electron-Forge, and it installs it globally so you can run the CLI.
- Delete
node_modules
to be safe and ensure we clean it up. - Install Electron-Forge:
npm run install-electron-forge
- Install fresh npm dependencies:
npm install
I've prepared a sample electron app using electron-forge that you can browse to see how simple the configuration can be with no scripts. The configuration is basic and can be expanded to cover details such as mac/windows specific icons.
- Documentation: https://github.com/electron-userland/electron-forge/blob/master/README.md
- Sample config: https://github.com/klappy/electron-forge/blob/master/.forge.config.json
- Reference config from package.json: https://github.com/klappy/electron-forge/blob/master/package.json
The first section, make_targets
, tells the current OS the desired build target. Windows uses Squirrel that generates nice .exe installers. Darwin/OSX/Mac uses a DMG image for installation and compressed images. For Linux we will use DEB packages since that's Ubuntu uses and its the most common Desktop flavor of Linux.
Update package.json scripts for package and make. Due to an issue on Linux where current relative path isn't the default, pass the current relative path to avoid it raising an error that path is undefined.
- Sample package.json: https://github.com/klappy/electron-forge/blob/master/package.json
- Package script:
electron-forge package ./
- Make script:
electron-forge make ./
Electron-forge only builds for the OS and Architecture it is run on. While that seems limited at first, we choose to run on continuous integration servers that provide the desired OS builds.
- Windows: https://github.com/electron/windows-installer#usage
- Mac/OSX/Darwin: https://github.com/mongodb-js/electron-installer-dmg#api
It's as easy as npm run package
which via package.json scripts is an alias for electron-forge package
. This runs webpack and takes care of es6/babel type stuff behind the scenes so we don't have to, including copying them to a path that is non-destructive and won't be committed to our codebase since our .gitignore file ignores the out
folder.
Electron-Forge is configured to allow babel to happen in production just like it does in development mode with npm start
. Keep in mind this means all babel plugins and presets are required to be in dependencies and not dev-dependencies in the package.json.
- Sample package.json: https://github.com/klappy/electron-forge/blob/master/package.json
When packaging on your local Windows machine, Node-gyp requires python to be installed and may cause issues when packaging.
- Documented fix: https://github.com/electron-userland/electron-forge/issues/172
- Right click on PowerShell and run as Admin.
- Run:
npm install --global --production windows-build-tools
- Run:
npm install --global node-gyp
- Run:
setx PYTHON "%USERPROFILE%\.windows-build-tools\python27\python.exe"
- Ensure to install and use Electron-Forge via PowerShell and not Bash as it thinks the environment is Linux.
- Ensure to use npm@^5.1.0 as v5 up until that release had a bug in Windows not skipping other OS dependencies.
- NPM bugfix: https://github.com/npm/npm/pull/17552
It's as easy as npm run make
which via package.json scripts is an alias for electron-forge make
. This runs electron-build behind the scenes with many default configurations and scripts for each OS that abstracts the complications. We can configure this via special sections for each OS.
After taking the functioning package from Windows, Electron-Forge Makes an installable executable via Squirrel. Squirrel has a path character limitation of 260 characters. The issue is with the nested dependencies of node_modules folder and it gets pretty deep. This breaks the build and the most common way to address this is by using Asar=true
setting in the package step. This makes a virtual file system that works around the limit. Unless we change many of our file references, our App isn't setup to use the virtual file system. The other approach to try is running npm dedupe
to flatten the node_modules folder and potentially fix this issue. No successful build has been made for Windows through either method, when it does this will be updated. Dedupe adds considerable amounts of time to the builds both to run dedupe and subsequent package and make steps. Do not do this for Mac builds even if it fixes Windows.
- TODO, look into this: https://github.com/MarshallOfSound/electron-forge-demo123/blob/master/.appveyor.yml
We don't use this as we want to let this be done via our continuous integration services.
Continuous Integration (CI) allows us to use git hooks to run things like automated tests on our code on their servers and run our package/build/publishing automagically via our configurations.
- Travis-CI for Mac/Linux (travis-ci.org)
- Appveyor for Windows (appveyor.com)
Travis-CI is the standard in Mac/Linux CI services. Here is a sample .travis.yml configuration file that can run tests and package/build/publish the sample app.
- Commented sample config: https://github.com/klappy/electron-forge/blob/master/.travis.yml
- Releases Documentation: https://docs.travis-ci.com/user/deployment/releases/
Travis times out by default after not receiving output for 10 minutes. This can be increased by prepending travis_wait
before the command that needs to take up to 20 minutes. If you need more time, add a number afterwards, travis_wait 30 npm run make
.
- Documentation: https://docs.travis-ci.com/user/common-build-problems/#Build-times-out-because-no-output-was-received
Appveyor is the standard in Windows CI services. Here is a sample appveyor.yml configuration file that can run tests and package/build/publish the sample app.
- Commented sample config: https://github.com/klappy/electron-forge/blob/master/appveyor.yml
- Releases Documentation: https://www.appveyor.com/docs/deployment/github/
- Choosing files to release: https://www.appveyor.com/docs/packaging-artifacts/
Testing on CI servers requires a "headless" virtual display since there is no monitor attached to the servers. Tests will fail to run on Linux/Mac but Windows should be fine.
- Headless Testing Documentation: https://electron.atom.io/docs/tutorial/testing-on-headless-ci/
To Deploy we are using Github personal Access tokens. Before using them they must be encrypted. During encryption, they will only usable for the specified repository. Not updating these values may result in 401 Authentication errors from Github API.
- Create Github Personal Access Token.
- Encrypt Access Token with Travis:
travis encrypt [paste token]
. - Replace the api.secure value in Travis config with output after removing line breaks.
- Set/replace the GH_TOKEN environment variable in the settings of Travis to the same encrypted token.
Before you make a release, the first step is making sure your tests pass and you have a working version of your app. After you are sure you have your codebase ready for primetime or at least QA testing, you can now create a tag to trigger all of the above automagically.
The sample script is aliased in the package.json so it can be run as npm run update-version x.x.x-beta.x
. Basically what it does is updates the version of your app via npm version command and then after committing to your branch, creates a tag that is then pushed up to github to trigger continuous integration services to package/build/deploy for you. Version numbers aren't arbitrary and NPM/Github/Travis/Appveyor all use the same conventions for versioning including namespaces for major.minor.patch-[alpha/beta].build
.
- Sample version update script: https://github.com/klappy/electron-forge/blob/master/scripts/updateVersion.js