├── .editorconfig
├── .gitattributes
├── .github
└── workflows
│ ├── lint.yml
│ └── test.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── action.yml
├── index.js
├── package.json
├── test
├── app-in-root
│ ├── index.html
│ ├── main.js
│ ├── package.json
│ ├── preload.js
│ └── renderer.js
├── app-in-subdirectory
│ ├── app
│ │ ├── index.html
│ │ ├── main.js
│ │ ├── preload.js
│ │ └── renderer.js
│ └── package.json
└── vue-app
│ ├── babel.config.js
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ └── index.html
│ ├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── background.js
│ ├── components
│ │ └── HelloWorld.vue
│ └── main.js
│ └── vue.config.js
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 2
7 | indent_style = tab
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.{md,yml}]
12 | indent_style = space
13 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 | test/**/* linguist-vendored
3 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yml:
--------------------------------------------------------------------------------
1 | name: Lint
2 |
3 | on:
4 | - pull_request
5 | - push
6 |
7 | jobs:
8 | lint:
9 | name: Lint
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - name: Check out Git repository
14 | uses: actions/checkout@v2
15 |
16 | - name: Set up Node.js
17 | uses: actions/setup-node@v1
18 | with:
19 | node-version: 16
20 |
21 | - name: Install dependencies
22 | run: yarn install
23 |
24 | - name: Lint
25 | run: |
26 | yarn lint
27 | yarn format
28 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 |
3 | on:
4 | - push
5 | - pull_request
6 |
7 | jobs:
8 | test:
9 | name: Test
10 | runs-on: ${{ matrix.os }}
11 |
12 | strategy:
13 | matrix:
14 | os: [macos-latest, ubuntu-latest, windows-latest]
15 | package_manager: [npm, yarn]
16 | package_root: ["./test/app-in-root/", "./test/app-in-subdirectory/", "./test/vue-app"]
17 |
18 | steps:
19 | - name: Check out Git repository
20 | uses: actions/checkout@v2
21 |
22 | - name: Set up Node.js
23 | uses: actions/setup-node@v1
24 | with:
25 | node-version: 16
26 |
27 | - name: Install test app dependencies
28 | run: |
29 | cd ${{ matrix.package_root }}
30 | ${{ matrix.package_manager }} install
31 |
32 | - name: Run action
33 | uses: ./
34 | with:
35 | github_token: ${{ secrets.github_token }}
36 | package_root: ${{ matrix.package_root }}
37 | use_vue_cli: ${{ contains(matrix.package_root, 'vue')}}
38 | max_attempts: "2"
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
3 | # Lockfiles in test projects
4 | test/**/yarn.lock
5 | test/**/dist_electron
6 |
7 | # Generated files in test projects
8 | test/**/dist/
9 | test/**/dist_electron/
10 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright (c) 2019 Samuel Meuli
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Electron Builder Action
2 |
3 | **GitHub Action for building and releasing Electron apps**
4 |
5 | This is a GitHub Action for automatically building and releasing your Electron app using GitHub's CI/CD capabilities. It uses [`electron-builder`](https://github.com/electron-userland/electron-builder) to package your app and release it to a platform like GitHub Releases.
6 |
7 | GitHub Actions allows you to build your app on macOS, Windows and Linux without needing direct access to each of these operating systems.
8 |
9 | ## Setup
10 |
11 | 1. **Install and configure `electron-builder`** (v22+) in your Electron app. You can read about this in [the project's docs](https://www.electron.build) or in [my blog post](https://samuelmeuli.com/blog/2019-04-07-packaging-and-publishing-an-electron-app).
12 |
13 | 2. If you need to compile code (e.g. TypeScript to JavaScript or Sass to CSS), make sure this is done using a **`build` script in your `package.json` file**. The action will execute that script before packaging your app. However, **make sure that the `build` script does _not_ run `electron-builder`**, as this action will do that for you.
14 |
15 | 3. **Add a workflow file** to your project (e.g. `.github/workflows/build.yml`):
16 |
17 | ```yml
18 | name: Build/release
19 |
20 | on: push
21 |
22 | jobs:
23 | release:
24 | runs-on: ${{ matrix.os }}
25 |
26 | strategy:
27 | matrix:
28 | os: [macos-latest, ubuntu-latest, windows-latest]
29 |
30 | steps:
31 | - name: Check out Git repository
32 | uses: actions/checkout@v1
33 |
34 | - name: Install Node.js, NPM and Yarn
35 | uses: actions/setup-node@v1
36 | with:
37 | node-version: 10
38 |
39 | - name: Build/release Electron app
40 | uses: samuelmeuli/action-electron-builder@v1
41 | with:
42 | # GitHub token, automatically provided to the action
43 | # (No need to define this secret in the repo settings)
44 | github_token: ${{ secrets.github_token }}
45 |
46 | # If the commit is tagged with a version (e.g. "v1.0.0"),
47 | # release the app after building
48 | release: ${{ startsWith(github.ref, 'refs/tags/v') }}
49 | ```
50 |
51 | ## Usage
52 |
53 | ### Building
54 |
55 | Using this the workflow above, GitHub will build your app every time you push a commit.
56 |
57 | ### Releasing
58 |
59 | When you want to create a new release, follow these steps:
60 |
61 | 1. Update the version in your project's `package.json` file (e.g. `1.2.3`)
62 | 2. Commit that change (`git commit -am v1.2.3`)
63 | 3. Tag your commit (`git tag v1.2.3`). Make sure your tag name's format is `v*.*.*`. Your workflow will use this tag to detect when to create a release
64 | 4. Push your changes to GitHub (`git push && git push --tags`)
65 |
66 | After building successfully, the action will publish your release artifacts. By default, a new release draft will be created on GitHub with download links for your app. If you want to change this behavior, have a look at the [`electron-builder` docs](https://www.electron.build).
67 |
68 | ## Configuration
69 |
70 | ### Options
71 |
72 | You can configure the action further with the following options:
73 |
74 | - `package_root`: Directory where NPM/Yarn commands should be run (default: `"."`)
75 | - `build_script_name`: Name of the optional NPM build script which is executed before `electron-builder` (default: `"build"`)
76 | - `skip_build`: Whether the action should execute the NPM build script before running `electron-builder`
77 | - `use_vue_cli`: Whether to run `electron-builder` using the [Vue CLI plugin](https://nklayman.github.io/vue-cli-plugin-electron-builder) instead of calling the command directly
78 | - `args`: Other arguments to pass to the `electron-builder` command, e.g. configuration overrides (default: `""`)
79 | - `max_attempts`: Maximum number of attempts for completing the build and release step (default: `1`)
80 |
81 | See [`action.yml`](./action.yml) for a list of all possible input variables.
82 |
83 | ### Code Signing
84 |
85 | If you are building for **macOS**, you'll want your code to be [signed](https://samuelmeuli.com/blog/2019-04-07-packaging-and-publishing-an-electron-app/#code-signing). GitHub Actions therefore needs access to your code signing certificates:
86 |
87 | - Open the Keychain Access app or the Apple Developer Portal. Export all certificates related to your app into a _single_ file (e.g. `certs.p12`) and set a strong password
88 | - Base64-encode your certificates using the following command: `base64 -i certs.p12 -o encoded.txt`
89 | - In your project's GitHub repository, go to Settings → Secrets and add the following two variables:
90 | - `mac_certs`: Your encoded certificates, i.e. the content of the `encoded.txt` file you created before
91 | - `mac_certs_password`: The password you set when exporting the certificates
92 |
93 | Add the following options to your workflow's existing `action-electron-builder` step:
94 |
95 | ```yml
96 | - name: Build/release Electron app
97 | uses: samuelmeuli/action-electron-builder@v1
98 | with:
99 | # ...
100 | mac_certs: ${{ secrets.mac_certs }}
101 | mac_certs_password: ${{ secrets.mac_certs_password }}
102 | ```
103 |
104 | The same goes for **Windows** code signing (`windows_certs` and `windows_certs_password` secrets).
105 |
106 | ### Notarization
107 |
108 | If you've configured `electron-builder` to notarize your Electron Mac app [as described in this guide](https://samuelmeuli.com/blog/2019-12-28-notarizing-your-electron-app), you can use the following steps to let GitHub Actions perform the notarization for you:
109 |
110 | 1. Define the following secrets in your repository's settings on GitHub:
111 |
112 | - `api_key`: Content of the API key file (with the `p8` file extension)
113 | - `api_key_id`: Key ID found on App Store Connect
114 | - `api_key_issuer_id`: Issuer ID found on App Store Connect
115 |
116 | 2. In your workflow file, add the following step before your `action-electron-builder` step:
117 |
118 | ```yml
119 | - name: Prepare for app notarization
120 | if: startsWith(matrix.os, 'macos')
121 | # Import Apple API key for app notarization on macOS
122 | run: |
123 | mkdir -p ~/private_keys/
124 | echo '${{ secrets.api_key }}' > ~/private_keys/AuthKey_${{ secrets.api_key_id }}.p8
125 | ```
126 |
127 | 3. Pass the following environment variables to `action-electron-builder`:
128 |
129 | ```yml
130 | - name: Build/release Electron app
131 | uses: samuelmeuli/action-electron-builder@v1
132 | with:
133 | # ...
134 | env:
135 | # macOS notarization API key
136 | API_KEY_ID: ${{ secrets.api_key_id }}
137 | API_KEY_ISSUER_ID: ${{ secrets.api_key_issuer_id }}
138 | ```
139 |
140 | ## Development
141 |
142 | Suggestions and contributions are always welcome! Please discuss larger changes via issue before submitting a pull request.
143 |
144 | ## Credit
145 |
146 | Credit to Samuel Meuli for starting this [project](https://github.com/samuelmeuli/action-electron-builder)
147 |
--------------------------------------------------------------------------------
/action.yml:
--------------------------------------------------------------------------------
1 | name: Macro Electron Builder Action
2 | author: William Hutchinson
3 | description: GitHub Action for building and releasing Electron apps
4 |
5 | inputs:
6 | github_token:
7 | description: GitHub authentication token
8 | required: true
9 | mac_certs:
10 | description: Base64-encoded code signing certificate for macOS
11 | required: false
12 | mac_certs_password:
13 | description: Password for decrypting `mac_certs`
14 | required: false
15 | release:
16 | description: Whether the app should be released after a successful build
17 | required: false
18 | default: false
19 | windows_certs:
20 | description: Base64-encoded code signing certificate for Windows
21 | required: false
22 | windows_certs_password:
23 | description: Password for decrypting `windows_certs`
24 | required: false
25 | package_root:
26 | description: Directory where NPM/Yarn commands should be run
27 | required: false
28 | default: "."
29 | build_script_name:
30 | description: Name of the optional NPM build script which is executed before `electron-builder`
31 | required: false
32 | default: build
33 | skip_build:
34 | description: Whether the action should execute the NPM build script before running `electron-builder`
35 | required: false
36 | default: false
37 | use_vue_cli:
38 | description: Whether to run `electron-builder` using the Vue CLI plugin instead of calling the command directly
39 | required: false
40 | default: false
41 | args:
42 | description: Other arguments to pass to the `electron-builder` command, e.g. configuration overrides
43 | required: false
44 | default: ""
45 | max_attempts:
46 | description: Maximum number of attempts for completing the build and release step
47 | required: false
48 | default: "1"
49 |
50 | # Deprecated
51 | app_root:
52 | description: Directory where `electron-builder` commands should be run
53 | required: false
54 |
55 | runs:
56 | using: node16
57 | main: index.js
58 |
59 | branding:
60 | icon: upload-cloud
61 | color: blue
62 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const { execSync } = require("child_process");
2 | const { existsSync, readFileSync } = require("fs");
3 | const { join } = require("path");
4 |
5 | /**
6 | * Logs to the console
7 | */
8 | const log = (msg) => console.log(`\n${msg}`); // eslint-disable-line no-console
9 |
10 | /**
11 | * Exits the current process with an error code and message
12 | */
13 | const exit = (msg) => {
14 | console.error(msg);
15 | process.exit(1);
16 | };
17 |
18 | /**
19 | * Executes the provided shell command and redirects stdout/stderr to the console
20 | */
21 | const run = (cmd, cwd) => execSync(cmd, { encoding: "utf8", stdio: "inherit", cwd });
22 |
23 | /**
24 | * Determines the current operating system (one of ["mac", "windows", "linux"])
25 | */
26 | const getPlatform = () => {
27 | switch (process.platform) {
28 | case "darwin":
29 | return "mac";
30 | case "win32":
31 | return "windows";
32 | default:
33 | return "linux";
34 | }
35 | };
36 |
37 | /**
38 | * Returns the value for an environment variable (or `null` if it's not defined)
39 | */
40 | const getEnv = (name) => process.env[name.toUpperCase()] || null;
41 |
42 | /**
43 | * Sets the specified env variable if the value isn't empty
44 | */
45 | const setEnv = (name, value) => {
46 | if (value) {
47 | process.env[name.toUpperCase()] = value.toString();
48 | }
49 | };
50 |
51 | /**
52 | * Returns the value for an input variable (or `null` if it's not defined). If the variable is
53 | * required and doesn't have a value, abort the action
54 | */
55 | const getInput = (name, required) => {
56 | const value = getEnv(`INPUT_${name}`);
57 | if (required && !value) {
58 | exit(`"${name}" input variable is not defined`);
59 | }
60 | return value;
61 | };
62 |
63 | /**
64 | * Installs NPM dependencies and builds/releases the Electron app
65 | */
66 | const runAction = () => {
67 | const platform = getPlatform();
68 | const release = getInput("release", true) === "true";
69 | const pkgRoot = getInput("package_root", true);
70 | const buildScriptName = getInput("build_script_name", true);
71 | const skipBuild = getInput("skip_build") === "true";
72 | const useVueCli = getInput("use_vue_cli") === "true";
73 | const args = getInput("args") || "";
74 | const maxAttempts = Number(getInput("max_attempts") || "1");
75 |
76 | // TODO: Deprecated option, remove in v2.0. `electron-builder` always requires a `package.json` in
77 | // the same directory as the Electron app, so the `package_root` option should be used instead
78 | const appRoot = getInput("app_root") || pkgRoot;
79 |
80 | const pkgJsonPath = join(pkgRoot, "package.json");
81 | const pkgLockPath = join(pkgRoot, "package-lock.json");
82 |
83 | // Determine whether NPM should be used to run commands (instead of Yarn, which is the default)
84 | const useNpm = existsSync(pkgLockPath);
85 | log(`Will run ${useNpm ? "NPM" : "Yarn"} commands in directory "${pkgRoot}"`);
86 |
87 | // Make sure `package.json` file exists
88 | if (!existsSync(pkgJsonPath)) {
89 | exit(`\`package.json\` file not found at path "${pkgJsonPath}"`);
90 | }
91 |
92 | // Copy "github_token" input variable to "GH_TOKEN" env variable (required by `electron-builder`)
93 | setEnv("GH_TOKEN", getInput("github_token", true));
94 |
95 | // Require code signing certificate and password if building for macOS. Export them to environment
96 | // variables (required by `electron-builder`)
97 | if (platform === "mac") {
98 | setEnv("CSC_LINK", getInput("mac_certs"));
99 | setEnv("CSC_KEY_PASSWORD", getInput("mac_certs_password"));
100 | } else if (platform === "windows") {
101 | setEnv("CSC_LINK", getInput("windows_certs"));
102 | setEnv("CSC_KEY_PASSWORD", getInput("windows_certs_password"));
103 | }
104 |
105 | // Disable console advertisements during install phase
106 | setEnv("ADBLOCK", true);
107 |
108 | log(`Installing dependencies using ${useNpm ? "NPM" : "Yarn"}…`);
109 | run(useNpm ? "npm install" : "yarn", pkgRoot);
110 |
111 | // Run NPM build script if it exists
112 | if (skipBuild) {
113 | log("Skipping build script because `skip_build` option is set");
114 | } else {
115 | log("Running the build script…");
116 | if (useNpm) {
117 | run(`npm run ${buildScriptName} --if-present`, pkgRoot);
118 | } else {
119 | // TODO: Use `yarn run ${buildScriptName} --if-present` once supported
120 | // https://github.com/yarnpkg/yarn/issues/6894
121 | const pkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf8"));
122 | if (pkgJson.scripts && pkgJson.scripts[buildScriptName]) {
123 | run(`yarn run ${buildScriptName}`, pkgRoot);
124 | }
125 | }
126 | }
127 |
128 | log(`Building${release ? " and releasing" : ""} the Electron app…`);
129 | const cmd = useVueCli ? "vue-cli-service electron:build" : "electron-builder";
130 | for (let i = 0; i < maxAttempts; i += 1) {
131 | try {
132 | run(
133 | `${useNpm ? "npx --no-install" : "yarn run"} ${cmd} --${platform} ${
134 | release ? "--publish always" : ""
135 | } ${args}`,
136 | appRoot,
137 | );
138 | break;
139 | } catch (err) {
140 | if (i < maxAttempts - 1) {
141 | log(`Attempt ${i + 1} failed:`);
142 | log(err);
143 | } else {
144 | throw err;
145 | }
146 | }
147 | }
148 | };
149 |
150 | runAction();
151 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "action-electron-builder",
3 | "version": "1.6.0",
4 | "description": "GitHub Action for building and releasing Electron apps",
5 | "author": {
6 | "name": "William Hutchinson",
7 | "email": "hutch@macro.com"
8 | },
9 | "repository": "github:coparse-inc/action-electron-builder",
10 | "license": "MIT",
11 | "private": true,
12 | "main": "./index.js",
13 | "scripts": {
14 | "lint": "eslint --max-warnings 0 \"**/*.js\"",
15 | "lint:fix": "yarn lint --fix",
16 | "format": "prettier --ignore-path ./.gitignore --list-different \"**/*.{css,html,js,json,jsx,less,md,scss,ts,tsx,vue,yaml,yml}\"",
17 | "format:fix": "yarn format --write"
18 | },
19 | "dependencies": {},
20 | "peerDependencies": {},
21 | "devDependencies": {
22 | "@samuelmeuli/eslint-config": "^6.0.0",
23 | "@samuelmeuli/prettier-config": "^2.0.1",
24 | "eslint": "6.8.0",
25 | "eslint-config-airbnb-base": "14.1.0",
26 | "eslint-config-prettier": "^6.10.1",
27 | "eslint-plugin-import": "^2.20.2",
28 | "prettier": "^2.0.4"
29 | },
30 | "eslintConfig": {
31 | "root": true,
32 | "extends": "@samuelmeuli/eslint-config",
33 | "env": {
34 | "node": true
35 | }
36 | },
37 | "eslintIgnore": [
38 | "node_modules/",
39 | "test/"
40 | ],
41 | "prettier": "@samuelmeuli/prettier-config"
42 | }
43 |
--------------------------------------------------------------------------------
/test/app-in-root/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Hello World!
9 |
10 |
11 |
Hello World!
12 | We are using Node.js , Chromium
13 | , and Electron .
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/test/app-in-root/main.js:
--------------------------------------------------------------------------------
1 | // Modules to control application life and create native browser window
2 | const { app, BrowserWindow } = require("electron");
3 | const path = require("path");
4 |
5 | // Keep a global reference of the window object, if you don't, the window will
6 | // be closed automatically when the JavaScript object is garbage collected.
7 | let mainWindow;
8 |
9 | function createWindow() {
10 | // Create the browser window.
11 | mainWindow = new BrowserWindow({
12 | width: 800,
13 | height: 600,
14 | webPreferences: {
15 | preload: path.join(__dirname, "preload.js"),
16 | },
17 | });
18 |
19 | // and load the index.html of the app.
20 | mainWindow.loadFile(path.join(__dirname, "index.html"));
21 |
22 | // Open the DevTools.
23 | // mainWindow.webContents.openDevTools()
24 |
25 | // Emitted when the window is closed.
26 | mainWindow.on("closed", function () {
27 | // Dereference the window object, usually you would store windows
28 | // in an array if your app supports multi windows, this is the time
29 | // when you should delete the corresponding element.
30 | mainWindow = null;
31 | });
32 | }
33 |
34 | // This method will be called when Electron has finished
35 | // initialization and is ready to create browser windows.
36 | // Some APIs can only be used after this event occurs.
37 | app.on("ready", createWindow);
38 |
39 | // Quit when all windows are closed.
40 | app.on("window-all-closed", function () {
41 | // On macOS it is common for applications and their menu bar
42 | // to stay active until the user quits explicitly with Cmd + Q
43 | if (process.platform !== "darwin") app.quit();
44 | });
45 |
46 | app.on("activate", function () {
47 | // On macOS it's common to re-create a window in the app when the
48 | // dock icon is clicked and there are no other windows open.
49 | if (mainWindow === null) createWindow();
50 | });
51 |
52 | // In this file you can include the rest of your app's specific main process
53 | // code. You can also put them in separate files and require them here.
54 |
--------------------------------------------------------------------------------
/test/app-in-root/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-quick-start",
3 | "version": "1.0.0",
4 | "description": "A minimal Electron application",
5 | "main": "main.js",
6 | "scripts": {
7 | "start": "electron ."
8 | },
9 | "repository": "https://github.com/electron/electron-quick-start",
10 | "keywords": [
11 | "Electron",
12 | "quick",
13 | "start",
14 | "tutorial",
15 | "demo"
16 | ],
17 | "author": "GitHub",
18 | "license": "CC0-1.0",
19 | "devDependencies": {
20 | "electron": "^7.1.7",
21 | "electron-builder": "^22.0.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/test/app-in-root/preload.js:
--------------------------------------------------------------------------------
1 | // All of the Node.js APIs are available in the preload process.
2 | // It has the same sandbox as a Chrome extension.
3 | window.addEventListener("DOMContentLoaded", () => {
4 | const replaceText = (selector, text) => {
5 | const element = document.getElementById(selector);
6 | if (element) element.innerText = text;
7 | };
8 |
9 | for (const type of ["chrome", "node", "electron"]) {
10 | replaceText(`${type}-version`, process.versions[type]);
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/test/app-in-root/renderer.js:
--------------------------------------------------------------------------------
1 | // This file is required by the index.html file and will
2 | // be executed in the renderer process for that window.
3 | // No Node.js APIs are available in this process because
4 | // `nodeIntegration` is turned off. Use `preload.js` to
5 | // selectively enable features needed in the rendering
6 | // process.
7 |
--------------------------------------------------------------------------------
/test/app-in-subdirectory/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Hello World!
9 |
10 |
11 |
Hello World!
12 | We are using Node.js , Chromium
13 | , and Electron .
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/test/app-in-subdirectory/app/main.js:
--------------------------------------------------------------------------------
1 | // Modules to control application life and create native browser window
2 | const { app, BrowserWindow } = require("electron");
3 | const path = require("path");
4 |
5 | // Keep a global reference of the window object, if you don't, the window will
6 | // be closed automatically when the JavaScript object is garbage collected.
7 | let mainWindow;
8 |
9 | function createWindow() {
10 | // Create the browser window.
11 | mainWindow = new BrowserWindow({
12 | width: 800,
13 | height: 600,
14 | webPreferences: {
15 | preload: path.join(__dirname, "preload.js"),
16 | },
17 | });
18 |
19 | // and load the index.html of the app.
20 | mainWindow.loadFile(path.join(__dirname, "index.html"));
21 |
22 | // Open the DevTools.
23 | // mainWindow.webContents.openDevTools()
24 |
25 | // Emitted when the window is closed.
26 | mainWindow.on("closed", function () {
27 | // Dereference the window object, usually you would store windows
28 | // in an array if your app supports multi windows, this is the time
29 | // when you should delete the corresponding element.
30 | mainWindow = null;
31 | });
32 | }
33 |
34 | // This method will be called when Electron has finished
35 | // initialization and is ready to create browser windows.
36 | // Some APIs can only be used after this event occurs.
37 | app.on("ready", createWindow);
38 |
39 | // Quit when all windows are closed.
40 | app.on("window-all-closed", function () {
41 | // On macOS it is common for applications and their menu bar
42 | // to stay active until the user quits explicitly with Cmd + Q
43 | if (process.platform !== "darwin") app.quit();
44 | });
45 |
46 | app.on("activate", function () {
47 | // On macOS it's common to re-create a window in the app when the
48 | // dock icon is clicked and there are no other windows open.
49 | if (mainWindow === null) createWindow();
50 | });
51 |
52 | // In this file you can include the rest of your app's specific main process
53 | // code. You can also put them in separate files and require them here.
54 |
--------------------------------------------------------------------------------
/test/app-in-subdirectory/app/preload.js:
--------------------------------------------------------------------------------
1 | // All of the Node.js APIs are available in the preload process.
2 | // It has the same sandbox as a Chrome extension.
3 | window.addEventListener("DOMContentLoaded", () => {
4 | const replaceText = (selector, text) => {
5 | const element = document.getElementById(selector);
6 | if (element) element.innerText = text;
7 | };
8 |
9 | for (const type of ["chrome", "node", "electron"]) {
10 | replaceText(`${type}-version`, process.versions[type]);
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/test/app-in-subdirectory/app/renderer.js:
--------------------------------------------------------------------------------
1 | // This file is required by the index.html file and will
2 | // be executed in the renderer process for that window.
3 | // No Node.js APIs are available in this process because
4 | // `nodeIntegration` is turned off. Use `preload.js` to
5 | // selectively enable features needed in the rendering
6 | // process.
7 |
--------------------------------------------------------------------------------
/test/app-in-subdirectory/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-quick-start",
3 | "version": "1.0.0",
4 | "description": "A minimal Electron application",
5 | "main": "./app/main.js",
6 | "scripts": {
7 | "start": "electron ."
8 | },
9 | "repository": "https://github.com/electron/electron-quick-start",
10 | "keywords": [
11 | "Electron",
12 | "quick",
13 | "start",
14 | "tutorial",
15 | "demo"
16 | ],
17 | "author": "GitHub",
18 | "license": "CC0-1.0",
19 | "devDependencies": {
20 | "electron": "^7.1.7",
21 | "electron-builder": "^22.0.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/test/vue-app/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"],
3 | };
4 |
--------------------------------------------------------------------------------
/test/vue-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-app",
3 | "version": "0.1.0",
4 | "author": {
5 | "email": "matthew@rathbonelabs.com",
6 | "url": "https://github.com/samuelmeuli/action-electron-builder"
7 | },
8 | "repository": "https://github.com/samuelmeuli/action-electron-builder",
9 | "private": true,
10 | "scripts": {
11 | "serve": "vue-cli-service serve",
12 | "build": "vue-cli-service build",
13 | "lint": "vue-cli-service lint",
14 | "electron:build": "vue-cli-service electron:build",
15 | "electron:serve": "vue-cli-service electron:serve",
16 | "postinstall": "electron-builder install-app-deps",
17 | "postuninstall": "electron-builder install-app-deps"
18 | },
19 | "main": "background.js",
20 | "dependencies": {
21 | "core-js": "^3.6.4",
22 | "vue": "^2.6.11"
23 | },
24 | "devDependencies": {
25 | "@vue/cli-plugin-babel": "~4.3.0",
26 | "@vue/cli-plugin-eslint": "~4.3.0",
27 | "@vue/cli-service": "~4.3.0",
28 | "babel-eslint": "^10.1.0",
29 | "electron": "^6.0.0",
30 | "eslint": "^6.7.2",
31 | "eslint-plugin-vue": "^6.2.2",
32 | "vue-cli-plugin-electron-builder": "^2.0.0-beta.6",
33 | "vue-template-compiler": "^2.6.11"
34 | },
35 | "eslintConfig": {
36 | "root": true,
37 | "env": {
38 | "node": true
39 | },
40 | "extends": [
41 | "plugin:vue/essential",
42 | "eslint:recommended"
43 | ],
44 | "parserOptions": {
45 | "parser": "babel-eslint"
46 | },
47 | "rules": {}
48 | },
49 | "browserslist": [
50 | "> 1%",
51 | "last 2 versions",
52 | "not dead"
53 | ]
54 | }
55 |
--------------------------------------------------------------------------------
/test/vue-app/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/macro-inc/action-electron-builder/29a7606c7d726b5b0f4dc2f334026f58bea0e1bb/test/vue-app/public/favicon.ico
--------------------------------------------------------------------------------
/test/vue-app/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/test/vue-app/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
18 |
19 |
29 |
--------------------------------------------------------------------------------
/test/vue-app/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/macro-inc/action-electron-builder/29a7606c7d726b5b0f4dc2f334026f58bea0e1bb/test/vue-app/src/assets/logo.png
--------------------------------------------------------------------------------
/test/vue-app/src/background.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { app, protocol, BrowserWindow } from "electron";
4 | import {
5 | createProtocol,
6 | /* installVueDevtools */
7 | } from "vue-cli-plugin-electron-builder/lib";
8 | const isDevelopment = process.env.NODE_ENV !== "production";
9 |
10 | // Keep a global reference of the window object, if you don't, the window will
11 | // be closed automatically when the JavaScript object is garbage collected.
12 | let win;
13 |
14 | // Scheme must be registered before the app is ready
15 | protocol.registerSchemesAsPrivileged([
16 | { scheme: "app", privileges: { secure: true, standard: true } },
17 | ]);
18 |
19 | function createWindow() {
20 | // Create the browser window.
21 | win = new BrowserWindow({
22 | width: 800,
23 | height: 600,
24 | webPreferences: {
25 | nodeIntegration: true,
26 | },
27 | });
28 |
29 | if (process.env.WEBPACK_DEV_SERVER_URL) {
30 | // Load the url of the dev server if in development mode
31 | win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
32 | if (!process.env.IS_TEST) win.webContents.openDevTools();
33 | } else {
34 | createProtocol("app");
35 | // Load the index.html when not in development
36 | win.loadURL("app://./index.html");
37 | }
38 |
39 | win.on("closed", () => {
40 | win = null;
41 | });
42 | }
43 |
44 | // Quit when all windows are closed.
45 | app.on("window-all-closed", () => {
46 | // On macOS it is common for applications and their menu bar
47 | // to stay active until the user quits explicitly with Cmd + Q
48 | if (process.platform !== "darwin") {
49 | app.quit();
50 | }
51 | });
52 |
53 | app.on("activate", () => {
54 | // On macOS it's common to re-create a window in the app when the
55 | // dock icon is clicked and there are no other windows open.
56 | if (win === null) {
57 | createWindow();
58 | }
59 | });
60 |
61 | // This method will be called when Electron has finished
62 | // initialization and is ready to create browser windows.
63 | // Some APIs can only be used after this event occurs.
64 | app.on("ready", async () => {
65 | if (isDevelopment && !process.env.IS_TEST) {
66 | // Install Vue Devtools
67 | // Devtools extensions are broken in Electron 6.0.0 and greater
68 | // See https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/378 for more info
69 | // Electron will not launch with Devtools extensions installed on Windows 10 with dark mode
70 | // If you are not using Windows 10 dark mode, you may uncomment these lines
71 | // In addition, if the linked issue is closed, you can upgrade electron and uncomment these lines
72 | // try {
73 | // await installVueDevtools()
74 | // } catch (e) {
75 | // console.error('Vue Devtools failed to install:', e.toString())
76 | // }
77 | }
78 | createWindow();
79 | });
80 |
81 | // Exit cleanly on request from parent process in development mode.
82 | if (isDevelopment) {
83 | if (process.platform === "win32") {
84 | process.on("message", (data) => {
85 | if (data === "graceful-exit") {
86 | app.quit();
87 | }
88 | });
89 | } else {
90 | process.on("SIGTERM", () => {
91 | app.quit();
92 | });
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/test/vue-app/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 | For a guide and recipes on how to configure / customize this project,
6 | check out the
7 | vue-cli documentation.
8 |