A shell wrapper will be generated for command '/usr/bin/monika' as it does not conform with the command pattern expected by the runtime

Hello,

I am a newbie when it comes to Snapcraft. So I had this snapcraft.yaml to build a Node app based on oclif (https://github.com/oclif/oclif or take Heroku CLI as an example), like so:

name: monika
version: git
summary: Synthetic monitoring made easy
description: Monika is a command line monitoring tool
confinement: devmode
grade: stable

base: core18

apps:
  monika:
    command: monika

architectures:
  - build-on: [amd64]

parts:
  monika:
    plugin: nil
    source: .
    override-pull: |
      snapcraftctl pull
      CLI_VERSION=$(grep \"version\": package.json | head -n 1 | awk '{print $2}' | tr -d \" | tr -d \,)
      snapcraftctl set-version $CLI_VERSION
    override-build: |
      set -ex
      
      # Install Node from Nodesource 
      curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash -
      sudo apt-get install -y nodejs build-essential

      # Verify npm version
      npm -v

      # Build and pack
      npm install --unsafe-perm
      npm run prepack
      npm pack

      # Install pack
      npm install -g --unsafe-perm ./hyperjumptech-monika-*.tgz

      # Confirm Monika is running
      which monika
      monika -v

It builds well. But at the end of the build, there are some errors:

...
> @hyperjumptech/monika@1.6.11 preinstall /usr/lib/node_modules/@hyperjumptech/monika
> node scripts/preinstall.js

/usr/bin/monika -> /usr/lib/node_modules/@hyperjumptech/monika/bin/run
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.3.2 (node_modules/@hyperjumptech/monika/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ @hyperjumptech/monika@1.6.11
updated 1 package in 46.988s
+ which monika
/usr/bin/monika
+ monika -v
@hyperjumptech/monika/1.6.11 linux-x64 node-v14.19.0
Cleaning later steps and re-staging monika ('override-stage' property changed)
+ snapcraftctl stage
Priming monika 
+ snapcraftctl prime
The command 'monika' for 'monika' was resolved to '/usr/bin/monika'.
The command 'monika' has been changed to '/usr/bin/monika'.
A shell wrapper will be generated for command '/usr/bin/monika' as it does not conform with the command pattern expected by the runtime. Commands must be relative to the prime directory and can only consist of alphanumeric characters, spaces, and the following special characters: / . _ # : $ -
Determining the version from the project repo (version: git).
The version has been set to '0+git.b5b5f24-dirty'
Snapping |                                                                          
Snapped monika_0+git.b5b5f24-dirty_amd64.snap

So I thought “let me try to install it first” considering there is a .snap file created. It was installed smoothly, but when I run monika:

❯ monika
/snap/monika/x1/command-monika.wrapper: 2: exec: /usr/bin/monika: not found

Could you point out where did I do wrong?

try changing this to

apps:
  monika:
    command: usr/bin/monika

(the command path must be relative to the $SNAP or prime directory …)

Thank you for the reply! Unfortunately it didn’t work:

I also tried with “/usr/bin/monika”. It build successfully but still the same error:

❯ monika
/snap/monika/x1/command-monika.wrapper: 2: exec: /usr/bin/monika: not found

You’re using a custom script to build and install your app. Unfortunately your script is not installing into $SNAPCRAFT_PART_INSTALL, instead it is installing to the build machine, so your app never actually makes it into the snap. I recommend that you investigate the nodejs or npm snapcraft-plugins (depending on which base snap you’re targeting).

well, that looks like your build did not create $SNAP/usr/bin/monica like it should … probably it does not respect the $DESTDIR variable (which points to $SNAPCRAFT_PART_INSTALL usually) or some such … you can definitely not use /usr/bin/monicahere since this is outside of your snap environment

as @lucyllewy mentions, you need to ensure that npm install is installing to the right place. When we worked with some of the node and yarn developers back then to create the nodejs plugin there was not much standardization on installation, so installation in the plugin was done by creating a package and moving the package contents over to the install dir; this would be one way of solving the problem. The node community has advanced since then.

Another alternative would be to configure the global prefixes so things get install to SNAPCRAFT_PART_INSTALL by setting npm config set prefix

Lastly a combination of npm root (global or not) to grab the directory and copy it over the SNAPCRAFT_PART_INSTALL.

Hopefully these suggestions spark some ideas.

1 Like

After meddling with this, I’ve decided to use dump plugin instead:

name: monika
version: git
summary: Synthetic monitoring made easy
description: Monika is a command line monitoring tool
confinement: devmode
grade: stable
base: core20

apps:
  monika:
    command: bin/run

parts:
  monika:
    plugin: dump
    source: ./monika.tar.gz

Of course, it didn’t technically solve my problem above. But at least it’s working. Thank you everybody for the insights.