2

I have a Node app that uses a specific version of node, so I use nvm to trigger the correct version in the .npmrc file.

The app is deployed with Gitlab. The process is simple: when I push from local to gitlab repo, gitlab will connect to the production server via ssh and pull the latest version of the repo in Gitlab

image: node:latest

before_script:
  - apt-get update -qq
  - apt-get install -qq git
  - 'which ssh-agent || ( apt-get install -qq openssh-client )'
  - eval $(ssh-agent -s)
  - ssh-add <(echo "$K8S_SECRET_SSH_PRIVATE_KEY" | base64 -d)
  - mkdir -p ~/.ssh
  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

stages:
  - deploy_production

deploy_production:
  stage: deploy_production
  only:
    - master
  script:
    - ssh myuser@example.com 'export NPM_TOKEN=${NPM_TOKEN} && cd www/myproject && rm -rf node_modules dist/* && git pull && export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" --no-use && eval "[ -f .nvmrc ] && nvm install || nvm install stable" && nvm use --delete-prefix && npm ci && npm run prod'
    - ssh myuser@example.com "cd www/myproject && nvm use --delete-prefix"

The problem is in the last script. I get this response:

Webpack Bundle Analyzer saved report to /usr/home/myuser/www/myproject/dist/client-report.html
$ ssh myuser@example.com "cd www/myproject && nvm use --delete-prefix"
bash: nvm: command not found
ERROR: Job failed: exit code 1

If I enter directly from my local terminal to the deployment server and ask for the NVM_DIR variable I can get it as expected:

ssh myuser@example.com
cd www/myproject
echo $NVM_DIR
$~/home/myuser/.nvm

But if I add a script to my gitlab-ci.yml with this same action:

image: node:latest

before_script:
  - apt-get update -qq
  - apt-get install -qq git
  - 'which ssh-agent || ( apt-get install -qq openssh-client )'
  - eval $(ssh-agent -s)
  - ssh-add <(echo "$K8S_SECRET_SSH_PRIVATE_KEY" | base64 -d)
  - mkdir -p ~/.ssh
  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

stages:
  - deploy_production

deploy_production:
  stage: deploy_production
  only:
    - master
  script:
    - ssh myuser@example.com 'export NPM_TOKEN=${NPM_TOKEN} && cd www/myproject && rm -rf node_modules dist/* && git pull && export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" --no-use && eval "[ -f .nvmrc ] && nvm install || nvm install stable" && nvm use --delete-prefix && npm ci && npm run prod'
    - ssh myuser@example.com "cd www/myproject && echo $NVM_DIR"
    - ssh myuser@example.com "cd www/myproject && nvm use --delete-prefix"

The result is empty

[…]
Webpack Bundle Analyzer saved report to /usr/home/myuser/www/myproject/dist/client-report.html
$ ssh myuser@example.com "cd www/myproject && echo $NVM_DIR"

$ ssh myuser@example.com "cd www/myproject && nvm use --delete-prefix"
bash: nvm: command not found
ERROR: Job failed: exit code 1

What can I do to trigger NVM in example.com via ssh in gitlab-ci.yml?

Emille C.
  • 562
  • 1
  • 7
  • 23

1 Answers1

2

When you log in, your environment (in particular, the variable NVM_PATH but also PATH itself which causes "bash: nvm: command not found") is different than when executing commands with the SSH command. You can check this like so:

ssh myuser@example.com
env
# vs:
ssh myuser@example.com env

The first will execute—depending on what shell and OS you use—files such as .bashrc which execute after an interactive login, the second will (often) not. An excerpt of what NVM adds:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

The first defines the variable you're missing, the second executes a script that among other things, alters your PATH so that the nvm executable can be found.

You can execute this file manually or add the snippet that NVM adds to your CI pipeline before calling nvm use.

RickN
  • 12,537
  • 4
  • 24
  • 28
  • I can confirm that adding that snippet to source nvm.sh worked. Used it in a deploy.sh with Github actions. – J. Unkrass Aug 04 '22 at 06:19