Skip to main content

Run `npx` from PHP app

Comments

6 comments

  • Platform.sh DevRel

    Hey!

    I haven’t been able to replicate your issue.
    Could you tell me what version of PHP you’re using and show me your build hook?

    Thanks!

    0
  • Quentin Thiaucourt

    Sure, here’s a portion of my YAML:

    # The name of this app. Must be unique within a project.
    name: app
    
    # The type of the application to build.
    type: 'php:7.4'
    build:
        flavor: composer
    
    variables:
        php:
            "date.timezone": "Europe/Paris"
            "opcache.preload": "src/.preload.php"
            "opcache.memory_consumption": 256
            "opcache.max_accelerated_files": 20000
            "opcache.validate_timestamps": 0
            realpath_cache_size: 4096K
            realpath_cache_ttl: 600
    #    env:
            # Tell Symfony to always install in production-mode.
    #        APP_ENV: 'prod'
    #        APP_DEBUG: 0
    
    # The hooks that will be performed when the package is deployed.
    hooks:
        build: |
            set -e
            bin/console assets:install --no-debug
            bin/console cache:clear
            curl -sS https://platform.sh/cli/installer | php
            unset NPM_CONFIG_PREFIX
            curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.2/install.sh | dash
            export NVM_DIR="$PLATFORM_APP_DIR/.nvm"
            [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
            nvm current
            nvm install 12.16.1
            npm install
            npm run quiet-build
        deploy: |
            set -e
            bin/console assets:install --symlink --relative public
            bin/console cache:clear
            bin/console doctrine:migrations:migrate --allow-no-migration --no-interaction
            unset NPM_CONFIG_PREFIX
            export NVM_DIR="$PLATFORM_APP_DIR/.nvm"
            [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
            nvm use 12.16.1
    
    0
  • Platform.sh DevRel

    I still haven’t been able to replicate your npx error using a similar build hook.

    If we follow what happens during your build hook once you’ve installed nvm, we have:

    • nvm current: should display “system” at this point. The node system version is 6.17.1 which comes with npm 3.10.10. npx is not available with this npm version, as it only appeared with version 5. You cannot use npx using the node version that comes by default.
    • nvm install 12.16.1: you will get the specified node version, which comes with npm 6.13.4 so npx will now be available. Trying to install npx after this step will get you into a EEXIST error as npx can already be found in the bin folder of your current node version.
    • npm run quiet-build: the quiet-build npm script should be able to make use of npx as well as everything that lives under node_modules/.bin. When running an npm script, the local node_modules/.bin directory and the npm global’s bin directory (in your case /app/.nvm/versions/node/v12.16.1/bin) are automatically added to your PATH by npm.

    If this clarification doesn’t help, let me know at which step you are trying to use npx and how you invoke the command (e.g. in an npm script or directly in your build hook) so I can try to mimic your situation as good as possible.

    0
  • Quentin Thiaucourt

    Hey Rudy,
    I agree with the steps and how you describe them:

    • nvm current displays system
    • nvm install 12.16.1 does its job
    • npm run quiet-build, too

    But what I’m looking for is the ability to run npx afterwards, when the app is built and deployed.

    When connecting with platform ssh and running npx -v I get -bash: npx: command not found (which makes sense because node -v displays v6.17.1). Is that normal?

    How come Node “switched back” to its system version?
    How can I use the node/npm/npx tools installed by nvm?

    But! I now understand why npx can’t run anything, that’s because the filesystem is read-only so it can’t download packages, right? But I could theorically call it with --no-install if the packages are listed in packages.json and installed, right?

    0
  • Quentin Thiaucourt

    Current fix (but looks like a hack to me):

    Replace npx --no-install calls with

    /app/.nvm/versions/node/v12.16.1/bin/node /app/.nvm/versions/node/v12.16.1/bin/npx --no-install
    
    0
  • Platform.sh DevRel

    Oh, if you want to be able to run npx via SSH directly in your container, then it’s a different story!

    When connecting with platform ssh and running npx -v I get -bash: npx: command not found (which makes sense because node -v displays v6.17.1). Is that normal?
    How come Node “switched back” to its system version?

    This is normal. The different build hooks and your shell when you SSH into your container are different sessions. Therefore, environment variables set in your hooks won’t affect your environment when using SSH. Everything the nvm.sh script does has no effect anywhere else than in the hook it is being executed. After that, your environment is unaware of nvm's presence. Since node 12 has been installed via nvm, the only available version to your system at this point is the default one: 6.17.1.

    How can I use the node/npm/npx tools installed by nvm?

    Everything is there, but you need to set the environment variables. To do so, just add these lines in your .environment file:

    # This is necessary for nvm to work.
    unset NPM_CONFIG_PREFIX
    # Disable npm update notifier; being a read only system it will probably annoy you.
    export NO_UPDATE_NOTIFIER=1
    # This loads nvm for general usage.
    export NVM_DIR="$PLATFORM_APP_DIR/.nvm"
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
    

    When connecting with plaftorm ssh, you should now be able to be in a situation where:

    $ command -v nvm
    nvm
    $ node -v
    12.16.1
    $ which npx
    /app/.nvm/versions/node/v12.16.1/bin/npx
    

    Note: you will see a message saying npm update check failed when getting in your shell. This is due to an access right limitation when nvm wants to check for updates. You can ignore this. Just know that you will be running npm and npx 6.13.4 at this point (as opposed to 6.17.1 (as of today) in your hooks.)

    I now understand why npx can’t run anything, that’s because the filesystem is read-only so it can’t download packages, right? But I could theorically call it with --no-install if the packages are listed in packages.json and installed, right?

    Yes, the filesystem is read-only so this will limit what you can do with npx but you don’t have to pass the --no-install option. npx will check for the command you want to execute in the local and global bin directories before trying to download anything so any already installed packages can be run by doing npx [package] directly. Also, even with the --no-install option, trying to run a non-installed package will result in a EROFS error as npx is going to try to perform write operations anyway.

    0

Please sign in to leave a comment.