nvm: Use a Node Version from .nvmrc in CI
nvm is a shell function, not a binary: source $NVM_DIR/nvm.sh first, then nvm install reads .nvmrc and installs that Node.
nvm switches Node versions per shell. In CI the catch is that it is a shell function defined by an init script, so a fresh non-login job shell does not have it until you source nvm.sh.
What it does
nvm (Node Version Manager) installs multiple Node.js versions under $NVM_DIR/versions/node and switches the active one for the current shell by rewriting PATH. nvm use with no argument reads the .nvmrc file in the working directory.
Common usage
# .nvmrc contains e.g. "20.11.1" or "lts/iron"
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # load the function
nvm install # installs the version in .nvmrc
nvm use # selects it for this shell
node -vOptions
| Command / flag | What it does |
|---|---|
| nvm install <v> | Install a Node version (or the one in .nvmrc with no arg) |
| nvm use <v> | Switch the active version for this shell |
| nvm install --lts | Install the latest LTS line |
| nvm alias default <v> | Set the version new shells start with |
| nvm exec <v> <cmd> | Run a command under a specific version without switching |
| --no-progress | Suppress the download progress bar in logs |
In CI
A non-login shell (GitHub Actions run: steps use bash --noprofile --norc style invocation) does not auto-source nvm.sh. Source it explicitly at the top of every step, or set the step shell: bash -l {0} so it reads the profile. Cache $NVM_DIR/versions/node between runs to skip re-downloading.
Common errors in CI
"nvm: command not found" means nvm.sh was never sourced in this shell: add . "$NVM_DIR/nvm.sh". "N/A: version \"\" is not yet installed" from nvm use means there is no .nvmrc or the file value is unknown; run nvm install first. "Version 'v20' not found" usually means the .nvmrc holds a partial version nvm cannot resolve offline; pre-install it.