How to package electron app with stagePackages correctly

electron-builder has a bug pending since a long time which stops packaging a working snap when the project uses some stagePackages. So now that electron-builder is not useful. How to go about packaging that is reliable but also not tedious to maintain. Suggest the tools and steps to package a snap.

I’ve never seen electron-builder before, but looking at the bug here is what I would do.

  • Use electon-builder to generate a snapcraft.yaml file
  • Extract the snapcraft.yaml file either from the build directory (assuming there is one) or from the snaps meta data (/snap/myapp/current/meta/snap.yaml)
  • Commit that snapcraft.yaml file to my repository
  • Fix up snapcraft.yaml until it works
  • Use the snapcraft tools to build the snap

It would appear the snapcraft.yaml template bundled with electron-builder removes a lot of binary files that may be needed.

[Edit] Apparently the snap.yaml file in the meta directory is not the same one used by snapcraft so disregard that idea

you could create a snapcraft.yaml that calls electron-packager instead, this will produce a binary of your app that you can then re-use in your snap … here is an example:

  • Using electron-packager, I do have the bundled application source code for linux.
  • Now how do I go about creating a snap from this bundled code?
  • I tried using electron-installer-snap --src=<path-to-bundled app source code> but that failed with error “could not determine resources directory”. While this error could be a question for the package maintainers of electron-installer-snap but is there any other way than this to create snap from the bundled code?
  • @ogra I do not fully understand the example you shared, how to use that?

you create a similar snapcraft.yaml file that takes your source, runs it against electron-packager and drops it in the right place for your snap (similar to what my snapcraft.yaml does in the override-build block) to then be used via the apps: entry … perhaps start with a basic tutorial to understand snapcraft a bit more

In snapcraft tutorials, I can find info about how to create snapcraft.yaml file but not how to create snap once I have snapcraft.yaml. On the resource to snap a desktop app, there’s nothing else that’s relevant other than electron apps which mentions about building snap using electron-builder only.

Run snapcraft from a terminal and it will start the snapping process for snap/snapcraft.yaml in the current working directory.

You’ll need the snapd daemon, and then snap install --classic snapcraft to get the snapcraft utility.

1 Like

Did I understand you correctly?

  • Create a folder snap where I have basic snap/snapcraft.yaml and snap/gui/icon.png
  • From the directory which has snap and my-app-linux-x64 source code as first child, I run the command snapcraft

I just did that

  • It warned me that I don’t have lxd so I snap set snapcraft provider=multipass
  • I first tried to copy the earlier electron-builder snapcraft.yaml for my app but I couldn’t make sense of what’s happening
  • I used a bare minimum electron app code; used electron-packager to bundle the code to my-app-linux-x64 folder
  • Created snapcraft.yaml using snapcraft init command creates alongwith following addition
parts:
    plugin: nil
    source: ./my-app-linux-x64

The snap was bundled but on installation, I couldn’t find it in the system, not in the snap folder either

Try using the dump plugin instead when you want the content of the dir to be copied,.

nil is essentially not doing anything and expects you to do everything from an override-build script… (you could indeed use such a script and simply use the cp command in it…)

1 Like

I also tried to manually create snap of the same app that was having issue when snap was created using electron-builder. This was the snapcraft file that was created by electron-builder, I used the same to create snap using snapcraft command. But it failed with following error

Failed to pull source: unable to determine source type of ‘scripts’

I’m not able to fathom why does this snapcraft.yaml(built by electron-builder) has the content that it has

I changed nil to dump. Still can’t find the app after install

When you run the snapcraft command successfully, you should find a *.snap file in the current working directory.

To install that snap file, you will run snap install --dangerous mysnap.snap if memory serves correct. The dangerous flag is needed because the snap is unsigned/untrusted. Do not use the dangerous flag on any other snap.

If you have a desktop file specified in your snap, you should see a menu entry for it. Else, your app will be available somewhere in /snap/bin/ so you may inspect the contents of that directory to find it (i.e. console programs and such).

I tried installing the minimal hello world version again using --dangerous --devmode flags. I do not see the app in /snap/bin but I can now see it in /snap/my-little-app and can run the binary in /snap/my-little-app/current/hello-world.

Next, I will go with adding items to snapcraft.yaml one by one.

Have more follow up questions in order to do that successfully

  1. Does snap provides access to the app via terminal with the app name e.g. $ my-little-app starting the app? Or is there any specific entry to snapcraft.yaml to enable this (basically adding the app to bin path)
  2. Is there a way to dry run a snap without installing? As far as I have discussed and explored, the answer is No but just in case if there is any hack, that’d be helpful because I’d want to add 100s of items in snapcraft.yaml one by one and test each time so I know which configs cause the issue

Yes, as long as /snap/bin is in your path and you have correctly defined your app.command in snapcraft.yaml

A single snap can have multiple “entry points”. Checkout the [nextcloud snap on github.com].(https://github.com/nextcloud-snap/nextcloud-snap/blob/master/snap/snapcraft.yaml)

I’m pretty sure this is snapcraft try. https://snapcraft.io/docs/snap-try

I would suggest using a “binary search” approach instead.

Add half of the items and check if the problem occurs. If the problem manifests, figure out which half is problematic and keep halving the items until you find the root cause. Could be more than 1 item.

Obviously some items depend on others so you’ll have to think about what you’re adding / removing as you go.

Thanks a lot, quite a learning experience. I am using snapcraft try now as you mentioned. This creates a prime folder and then I execute snap try path-to-prime-folder --devmode, this saves a lot of time. Kudos snapcraft team.

Coming back to the original issue of electron app packaging, unfortunately, I’ve run into another blocker here.

As you mentioned

Yes, as long as /snap/bin is in your path and you have correctly defined your app .command in snapcraft.yaml

Now I have added app.command to my minimal hello world app, I can access my app with my-little-snap command from the terminal.

But I get following error on running it

Error while loading shared libraries: libatk-1.0.so.0: cannot open shared object file: No such file or directory

Even before this error, I had similar error for lbnss3.so, so to fix that I had added stage-packages for that. And then I took the liberty to add couple of more stage-packages that mattermost-desktop uses (assuming if mattermost electron app needs that, probably I will also need them). But now that I see libatk error, I think something is wrong here. My app is just a “hello world” electron app. Here’s the full snapcraft.yaml as of now for my hello world electron app

name: my-little-snap # you probably want to 'snapcraft register <name>'
base: core20 # the base snap is the execution environment for this snap
version: '0.1' # just for humans, typically '1.2+git' or '1.3.2'
summary: Single-line elevator pitch for your amazing snap # 79 char long summary
description: |
  This is my-little-snap's description. You have a paragraph or two to tell the
  most important story about your snap. Keep it under 100 words though,
  we live in tweetspace and your description wants to look good in the snap
  store.

grade: devel # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots

parts:
  my-little-snap:
    plugin: dump
    source: ./electron-pacakger-test-linux-x64
    stage-packages:
      - libnspr4
      - libnss3
      - libxss1
      
apps:
  my-little-snap:
    command: electron-pacakger-test

Am I doing something wrong here?

define the gnome extension for your app:, it brings all libs, fonts and themes needed (including atk)

Thanks. How do you deduce what needs to be added and whether that needs to be added as stage-package or plug or extension

snapcraft actually tells you at the end of the build if something is missing … looking at your stage packages list it seems okay for electron (assuming you added the gnome extension) … IIRC it only needs these three packages extra …

Added gnome extension. But during snap build process, I get an error that no extension with the name gnome exists.

This was the change in snapcraft.yaml to include this extension

apps:
  my-little-snap:
    command: electron-pacakger-test
    extensions: [gnome]

Check with snapcraft list-extensions if you actually picked the correct one for your base, each base has a specific extension