Help
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Copilot Lvl 3
Message 1 of 3

How to share shell profile between steps? (or: how to use nvm/rvm in steps?)

Solved! Go to Solution.

I have a workflow consisting of two jobs:  frontend (nodejs) & backend (ruby); that I'm attempting to migrate from TravisCI.

 

The frontend code uses NVM with an `.nvmrc` file to specify the version of Node.JS to use.

The backend code uses RVM with a `.ruby-version` file to specify the version of Ruby to use.

 

TravisCI build environments come with both NVM and RVM pre-installed.

The version of Ruby specified in `.ruby-version` is automatically detected/installed when the Travis job runs; and a simple `nvm install` command in the preinstall stage is all that is required to have Travis detect/install the appropriate version of Node.JS.

 

In Github Actions virtual environments, default versions of both Ruby & Node.JS are pre-installed, however version managers such as NVM/RVM are not.

 

The 'official' way to install a different Ruby/Node version in Github Actions appears to via actions/setup-ruby and actions/setup-node.

 

Unfortunately, `setup-node` doesn't undersand `.nvmrc` files yet, and `setup-ruby` doesn't understand `.ruby-version` files yet (so the specfied runtime versions would need to be duplicated in the workflow).

 

To emulate TravisCI, I'm trying to install both NVM and RVM as the first steps in their respective jobs, so that the jobs can use the .nvmrc and .ruby-version files to detect & install the appropriate runtime versions.

 

The challenge I have is that both NVM and RVM expect to be sourced into the shell after installation, e.g.

echo "source $NVM_DIR/nvm.sh" >> "$HOME/.bash_profile"
...

echo "source $HOME/.rvm/scripts/rvm" >> "$HOME/.bash_profile"
...

 

As I've discovered, each `run` command in a job is a separate shell process; and the default shell command on the Ubuntu environments is:

 

bash --noprofile --norc -eo pipefail {0}

 

(explicitly instructed to not read from `.bash_profile` and `.bashrc` files).

 

I tried adding an explicit `shell: bash {0}` to each step, but this does not seem to have made any difference.

 

Below is an example workflow.

 

For nvm: the `--install` argument when sourcing into the shell tells nvm to auto-install & switch to the version of node found in the .nvmrc file

For rvm: the `rvm_install_on_use_flag` environment variable tells rvm to auto-install & switch to the version of ruby found in the .ruby-version file.

 

  frontend:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v1

- name: Check versions (before)
shell: bash {0}
run: |
node --version
npm --version
- name: Install nvm shell: bash {0} run: | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash export NVM_DIR="$HOME/.nvm" echo "source $NVM_DIR/nvm.sh --install" >> "$HOME/.bash_profile" - name: Check versions (after) shell: bash {0} run: | node --version npm --version backend: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v1
- name: Install rvm shell: bash {0} run: | gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB curl -sSL https://get.rvm.io | bash -s stable export rvm_install_on_use_flag=1 echo "source $HOME/.rvm/scripts/rvm" >> "$HOME/.bash_profile" - name: Check versions (after) shell: bash {0} run: | rvm --version ruby --version gem --version bundler --version

 

For the frontend job, I had expected `node --version` to be v10.16.3 in the 'before' step; and v12.1.0 in the 'after' step;  but it is v10.16.3 in both.

 

It seems that the changes to `.bash_profile` are not seen by other steps?  (for what it's worth, I also tried `.bashrc` instead...to no avail).

 

Is there a way that I can have the NVM/RVM scripts sourced into all subsequent shell processes in a job?

 

(also, having to repeat `shell: bash {0}` in every step is pretty annoying).

2 Replies
Highlighted
Solution
GitHub Staff
Message 2 of 3

Re: How to share shell profile between steps? (or: how to use nvm/rvm in steps?)

You were close: You can actually just add `shell: bash -l {0}` (the -l was missing from yours) for steps where you need to source the bash_profile. See: https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html

 

I am aso assuming that install script primarily exports/updates the PATH to include the nvm install location, so youd only need to add the shell option for steps that need to exec node

 

The default was to invoke bash non-interactive and non-login since semantically thats closest to what we are doing- just running scripts, and I wanted to avoid adding potential side effects, unexpected behavior, re-running the same statup files repeatedly for each step, etc. The shell option was intended to allow you to manage these types of scenarios as necessary. Its not really the expected default behavior since we have setup actions that download/install tools and modify the PATH, etc, so that the tools installed are available everywhere not just from bash steps that pass down the environment, PATH is tracked by the runner across steps, etc

Highlighted
Copilot Lvl 2
Message 3 of 3

Re: How to share shell profile between steps? (or: how to use nvm/rvm in steps?)

To have a working sample snippet. Adding a local Composer's bin to the path. The Drupal step would fail without shell: bash -l {0}.

 

jobs:
build:
name: Build
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Composer
run: |
composer --version
composer validate
composer install -n
echo "export PATH=$PATH:$GITHUB_WORKSPACE/vendor/bin" >> ~/.bash_profile
source ~/.bash_profile
drush --version

- name: Drupal
shell: bash -l {0}
run: |
drush --version