After update to snapcraft 3.9.5 electron kiosk build fails

Hi,
Two days ago my snapcraft snap was updated from 3.8 to 3.9.5/3.9.7 version, and now my electron kiosk builds fail. I was able to revert it on my local computer to version 3.8, but on my pipeline I was playing with some edge channels during last two days and unfortunately I don’t have previous version of this snapcraft snap on it, and … it is no available to download.

After reverting to 3.8 application builds, but with 3.9.5/3.9.7 I get this error:

Skipping pull xwayland-kiosk-helper (already ran)
Skipping pull terminal (already ran)
Skipping build desktop-gtk3 (already ran)
Skipping build xwayland-kiosk-helper (already ran)
Building terminal 
npm WARN deprecated cross-zip@2.1.6: Possible security issue issue found in 2.x. Please update to 3.x
loadDep:global-tunnel-ng  
> core-js@3.6.4 postinstall /root/parts/terminal/build/node_modules/core-js
> node -e "try{require('./postinstall')}catch(e){}"
terminal@1.0.0 /root/parts/terminal/build
└── electron-packager@14.2.0  extraneous
npm WARN terminal@1.0.0 No repository field.
Cannot find module 'electron' from '/root/parts/terminal/build'
Failed to run 'override-build': Exit code was 1.

It seems like dev dependencies are not installed, like they were before. My snapcraft.yaml looks like this (it is based on https://tutorials.ubuntu.com/tutorial/electron-kiosk#3):

parts:
  terminal:
    plugin: nodejs
    nodejs-version: 12.13.0
    source: ./
    after: [desktop-gtk3, xwayland-kiosk-helper]
    override-build: |
        case $SNAPCRAFT_ARCH_TRIPLET in
          "i386-linux-gnu") ARCH="ia32";;
          "x86_64-linux-gnu") ARCH="x64";;
          "arm-linux-gnueabihf") ARCH="armv7l";;
          "aarch64-linux-gnu") ARCH="arm64";;
          *) echo "ERROR: electron does not support the '$SNAPCRAFT_ARCH_TRIPLET' architecture" && exit 1;;
        esac
        npm install electron-packager &&
        ./node_modules/.bin/electron-packager . --overwrite --platform=linux --arch=$ARCH --output=release-build --prune=true

and my package.json is

{
  "name": "terminal",
  "version": "1.0.0",
  "description": "Electron encapsulation",
  "main": "./src/main/main.js",
  "scripts": {
    "test": "test",
    "start": "electron .",
    "stenv": "electron -r dotenv/config .",
    "dist": "electron-builder --linux snap",
    "postinstall": "electron-builder install-app-deps"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "electron": "^6.0.12",
    "electron-builder": "^21.2.0"
  },
  "dependencies": {
    "@sentry/electron": "^1.2.0",
    "auto-launch": "^5.0.5",
    "dotenv": "^8.2.0",
    "firebase": "^6.6.1",
    "node-rsa": "^1.0.7",
    "qrcode": "^1.4.2",
    "request": "^2.88.0",
    "requests": "^0.3.0",
    "rxfire": "^3.9.1",
    "rxjs": "^6.5.3",
    "serialport": "^7.1.5"
  },
  "build": {
    "appId": "terminal",
    "extraResources": [
      {
        "from": "./extraResources/",
        "to": "extraResources",
        "filter": [
          "**/*"
        ]
      }
    ]
  }
}

If I add npm install to override build like this:

        npm install &&
        npm install electron-packager &&
        ./node_modules/.bin/electron-packager . --overwrite --platform=linux --arch=$ARCH --output=release-build --prune=true

Electron app downloads dependencies and it builds, but there are still some missing dependencies in snap and it fails to start:

glamor: EGL version 1.4:
A JavaScript error occurred in the main process
Uncaught Exception:
Error: Failed to load gRPC binary module because it was not installed for the current system
Expected directory: electron-v6.1-linux-x64-glibc
Found: [node-v57-linux-x64-glibc]
This problem can often be fixed by running "npm rebuild" on the current system
Original error: Cannot find module '/snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/node/extension_binary/electron-v6.1-linux-x64-glibc/grpc_node.node'
Require stack:
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/grpc_extension.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/client_interceptors.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/client.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/index.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/@firebase/firestore/dist/index.node.cjs.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/firebase/firestore/dist/index.cjs.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/src/main/main.js
- 
    at Object.<anonymous> (/snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/grpc_extension.js:53:17)
    at Module._compile (internal/modules/cjs/loader.js:786:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:798:10)
    at Module.load (internal/modules/cjs/loader.js:645:32)
    at Function.Module._load (internal/modules/cjs/loader.js:560:12)
    at Module.require (internal/modules/cjs/loader.js:685:19)
    at require (internal/modules/cjs/helpers.js:16:16)
    at Object.<anonymous> (/snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/client_interceptors.js:144:12)
    at Module._compile (internal/modules/cjs/loader.js:786:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:798:10)

Any ideas what might have changed ? Or I am just missing something obvious?

Sorry about the troubles @PiotrD. I have reproduced a similar issue with the example and my best guess is it might be related to the changes merged in: https://github.com/snapcore/snapcraft/pull/2747/files

However, I’m not really versed in nodejs and am unsure why it would cause this regression.

Perhaps @sergiusens and/or @NickZ can take a look?

For convenience, this is the snapcraft.yaml pasted from the tutorial:

Ok, great that you were able to reproduce it. For a moment I thought it was related to my build environment only. I will wait then, for someone, to suggest at least a workaround for it.

Any idea ? Or should I just fill in a bug report ?

And if there is any convenient way to, at least, downgrade snapcraft to 3.8 version.

Should electron not be in dependencies?

Don’t think so. If you add it to dependencies, you will get warning like this:

WARNING: Found 'electron' but not as a devDependency, pruning anyway

and it won’t add missing dependencies in snap.

Let’s see if @NickZ has a proposal

The main issue is that the example assumed that the pull step would do an npm install; we no longer do that during the pull step.

I reproduced the first bug, it crashed because it couldn’t find the dependencies due to npm install not running beforehand. However with the same edits as PiotrD to my snapcraft.yaml to npm install during override-build, I could not reproduce the second; it found all the dependencies and it snapped successfully.

All I can suggest that the example be modified to npm install during the override build. @PiotrD can you please try updating to 3.9.8 and running again?

1 Like

Hi, it also snaps for me correctly if I add npm install, but for some reason some dependencies are not in snap and it doesn’t start after installing it. Snap that I build with previous snaprcraft version doesn’t have this problem and new one get this error:

# snap run terminal-app.terminal-kiosk
glamor: EGL version 1.4:
A JavaScript error occurred in the main process
Uncaught Exception:
Error: Failed to load gRPC binary module because it was not installed for the current system
Expected directory: electron-v6.1-linux-x64-glibc
Found: [node-v57-linux-x64-glibc]
This problem can often be fixed by running "npm rebuild" on the current system
Original error: Cannot find module '/snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/node/extension_binary/electron-v6.1-linux-x64-glibc/grpc_node.node'
Require stack:
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/grpc_extension.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/client_interceptors.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/client.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/index.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/@firebase/firestore/dist/index.node.cjs.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/firebase/firestore/dist/index.cjs.js
- /snap/terminal-app/x1/terminal-linux-x64/resources/app/src/main/main.js
- 
    at Object.<anonymous> (/snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/grpc_extension.js:53:17)
    at Module._compile (internal/modules/cjs/loader.js:786:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:798:10)
    at Module.load (internal/modules/cjs/loader.js:645:32)
    at Function.Module._load (internal/modules/cjs/loader.js:560:12)
    at Module.require (internal/modules/cjs/loader.js:685:19)
    at require (internal/modules/cjs/helpers.js:16:16)
    at Object.<anonymous> (/snap/terminal-app/x1/terminal-linux-x64/resources/app/node_modules/grpc/src/client_interceptors.js:144:12)
    at Module._compile (internal/modules/cjs/loader.js:786:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:798:10)

In addition new snap is much smaller than old working one.
terminal-app_0.1.7_bad_amd64.snap 173M
terminal-app_0.1.7_good_amd64.snap 252M

If I mount both of them to check files that are inside, there is a lot of differences. e.g.

In working one there is electron-v6.1-linux-x64-glibc

#snap_0.1.7_working/terminal-linux-x64/resources/app/node_modules/grpc/src/node/extension_binary$ ls 
electron-v6.1-linux-x64-glibc  node-v72-linux-x64-glibc

and in bad one there is no electron-v6.1-linux-x64-glibc

#snap_0.1.7_bad/terminal-linux-x64/resources/app/node_modules/grpc/src/node/extension_binary$ ls
node-v57-linux-x64-glibc

I am pretty sure, that there are more differences. Maybe someone working with ubuntu core and kiosk might look into this ?

Thanks for taking a look, on a closer inspection, that kiosk snap example refers to the electron quickstart guide

PiotrD, are you able to post that snap that you’re using? I can’t seem to get the example app to break in the same way that your app is breaking.

Hi, Finally, I was able to fix the problem. After adding npm install I did not notice that post-install part fails with following error:

npm WARN lifecycle terminal@1.0.0~postinstall: cannot run in wd %s %s (wd=%s) terminal@1.0.0 electron-builder install-app-deps /root/parts/terminal/build

I added npm set unsafe-perm true to override part and it did a trick:

npm set unsafe-perm true &&
npm install &&
npm install electron-packager &&
./node_modules/.bin/electron-packager . --overwrite --platform=linux --arch=$ARCH --output=release-build --prune=true

I am not sure what changed, but it seems that there was a permission issue. Maybe npm drops privileges, I do not know. Hmm, I use jenkins agent with sudo privileges, which starts lxd container to build this snap so maybe this is the problem.

Maybe, it would be good idea to update Electron kiosk tutorial with these two lines. :slight_smile:

https://ubuntu.com/tutorials/electron-kiosk#4-converting-the-electron-snap-into-a-kiosk-snap

I am not sure what changed, but it seems that there was a permission issue. Maybe npm drops privileges, I do not know.

Yes! That was it. We had changed the build process to unset SUDO_UID and set unsafe-perm because npm refused to run any scripts as root during the build step; by overriding the build step, that doesn’t happen, so npm naturally refused to run the script. This is something that should probably be documented in the plugin docs.

1 Like