Skip to content
This repository has been archived by the owner on Sep 1, 2022. It is now read-only.

Commit

Permalink
feat: add custom bootstrap script support, close #900 (#901)
Browse files Browse the repository at this point in the history
  • Loading branch information
Noah committed Dec 31, 2020
1 parent 47dbbb8 commit 70c831a
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 24 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:
path: ./node_modules
key: ${{ env.NODE_VERSION }}-${{ env.YARN_VERSION }}-${{ hashFiles('yarn.lock') }}
- name: Install yvm
run: node ./scripts/install.js
run: make install-local
- name: Install dependencies
if: steps.node-modules-cache.outputs.cache-hit != 'true'
run: make node_modules
Expand Down Expand Up @@ -109,7 +109,7 @@ jobs:
path: ./node_modules
key: ${{ env.NODE_VERSION }}-${{ env.YARN_VERSION }}-${{ hashFiles('yarn.lock') }}
- name: Install yvm
run: node ./scripts/install.js
run: make install-local
- name: Install dependencies
if: steps.node-modules-cache.outputs.cache-hit != 'true'
run: make node_modules
Expand All @@ -126,7 +126,7 @@ jobs:
sudo apt-get install fish
mkdir -p ~/.config/fish
touch ~/.config/fish/config.fish
node ./scripts/install.js
make install-local
- name: Sanity test ${{ matrix.terminal }}
run: make sanities-${{ matrix.terminal }}
release:
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,21 @@ yvm --help
Yvm defaults to using the `yarn` version in your `package.json` `engines`. Otherwise you can create a `.yvmrc` file containing the version number of yarn in your project's root directory. Afterwards, `yvm use`, `yvm install` and `yvm exec` will use the version specified in the config file if no version number is supplied to the command.
You can also [declare the version using other configuration files](https://yvm.js.org/docs/faq#declare-yvm-version-in-a-configuration-file-where-can-i-place-my-version-number)

### Custom Bootstrapping

When using `yvm exec`, the appropriate `yarn` version is executed using the `node` available in the current context. This can be explicitly specified using the `YVM_BOOTSTRAP_EXEC_PATH` environment variable.

Example: if you are using `nvm`, you can avoid having to execute `nvm use` before using `yvm exec`:

```sh
export YVM_BOOTSTRAP_EXEC_PATH=~/.nvm/nvm-exec
yvm exec my-command
```

You can set this environment variable globally in your preferred shell's setup script (e.g. bashrc/zshrc).

The script referenced via the exec path must be executable. It receives the yarn executable as its first argument, and should forward the remaining arguments to yarn.

<!-- OVERVIEW-DOCS:END -->

### Additional reference
Expand Down
11 changes: 6 additions & 5 deletions src/commands/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@ const getYarnPath = (version, rootPath) =>
* e.g. user input, arrows keys, etc.
*
* __TEST__
* - `nvm use 8.0.0` (lowest supported node version)
* - `nvm use 10.0.0` (lowest supported node version)
* - `make install`
* - `yvm exec contributors:add` and go through the steps
*/
const runYarn = (version, extraArgs, rootPath = yvmPath) => {
process.argv = ['', ''].concat(extraArgs)
const filePath = path.resolve(getYarnPath(version, rootPath), 'bin/yarn.js')
const command = `${filePath} ${extraArgs.join(' ')}`
log.info(command)
const yarnBin = path.resolve(getYarnPath(version, rootPath), 'bin/yarn.js')
const executable = process.env.YVM_BOOTSTRAP_EXEC_PATH || 'node'
const args = [yarnBin, ...extraArgs]
log.info(`${executable} ${args.join(' ')}`)
try {
execFileSync(filePath, extraArgs, {
execFileSync(executable, args, {
stdio: 'inherit',
})
} catch (error) {
Expand Down
53 changes: 43 additions & 10 deletions test/commands/exec.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,19 @@ describe('exec command', () => {
const args = ['extra', 'args']
expect(await exec(version, args)).toBe(0)
expect(install.ensureVersionInstalled).toHaveBeenCalledTimes(1)
expect(
childProcess.execFileSync,
).toHaveBeenCalledWith(
`${rootPath}/versions/v${version}/bin/yarn.js`,
args,
expect(childProcess.execFileSync).toHaveBeenCalledWith(
'node',
[`${rootPath}/versions/v${version}/bin/yarn.js`, ...args],
{ stdio: 'inherit' },
)
})

it('executes yarn with correct rcVersion', async () => {
expect(await exec()).toBe(0)
expect(install.ensureVersionInstalled).toHaveBeenCalledTimes(1)
expect(
childProcess.execFileSync,
).toHaveBeenCalledWith(
`${rootPath}/versions/v${rcVersion}/bin/yarn.js`,
[],
expect(childProcess.execFileSync).toHaveBeenCalledWith(
'node',
[`${rootPath}/versions/v${rcVersion}/bin/yarn.js`],
{ stdio: 'inherit' },
)
})
Expand All @@ -64,4 +60,41 @@ describe('exec command', () => {
expect(log.default).toHaveBeenCalledWith(mockError.message)
expect(log.info).toHaveBeenCalledWith(mockError.stack)
})

describe('custom bootstrap executable', () => {
const originalEnvVars = {}

beforeEach(() => {
originalEnvVars.YVM_BOOTSTRAP_EXEC_PATH =
process.env.YVM_BOOTSTRAP_EXEC_PATH
})

afterEach(() => {
process.env.YVM_BOOTSTRAP_EXEC_PATH =
originalEnvVars.YVM_BOOTSTRAP_EXEC_PATH
})

it('executes yarn via bootstrap script if one specified', async () => {
process.env.YVM_BOOTSTRAP_EXEC_PATH = '/home/test/.nvm/nvm-exec'

expect(await exec()).toBe(0)
expect(install.ensureVersionInstalled).toHaveBeenCalledTimes(1)
expect(childProcess.execFileSync).toHaveBeenCalledWith(
process.env.YVM_BOOTSTRAP_EXEC_PATH,
[`${rootPath}/versions/v${rcVersion}/bin/yarn.js`],
{ stdio: 'inherit' },
)
})

it('executes yarn via node if no bootstrap script specified', async () => {
process.env.YVM_BOOTSTRAP_EXEC_PATH = ''

expect(await exec()).toBe(0)
expect(childProcess.execFileSync).toHaveBeenCalledWith(
'node',
[`${rootPath}/versions/v${rcVersion}/bin/yarn.js`],
{ stdio: 'inherit' },
)
})
})
})
34 changes: 34 additions & 0 deletions test/scripts/yvm.test.fish
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pass
testing "yarn shim passes original arguments"
yarn fake './*.js'
pass
rm "./fake.js"

testing "yarn shimmed config"
set test_shim_config_output (yarn --version)
Expand Down Expand Up @@ -120,3 +121,36 @@ if test "$test4_output" = "1.13.0"
else
fail "yvm current command failed: $test4_output"
end

testing "yvm exec with custom bootstrap"
set bootstrap_exec (mktemp -t yvm_bootstrap.XXX)
chmod +x $bootstrap_exec
echo "#!/usr/bin/env fish
echo "UNIQUE"
exec $argv" > $bootstrap_exec
set -gx YVM_BOOTSTRAP_EXEC_PATH $bootstrap_exec
set test_bootstrap_exec_output (yvm exec --version)
set -e YVM_BOOTSTRAP_EXEC_PATH
rm $bootstrap_exec
if string match -q -- "*UNIQUE*" $test_bootstrap_exec_output
pass
else
fail "yvm exec did not use custom bootstrap script: $test_bootstrap_exec_output"
end

testing "yarn shim with custom bootstrap"
set bootstrap_exec (mktemp -t yvm_bootstrap.XXX)
chmod +x $bootstrap_exec
echo "#!/usr/bin/env fish
echo "UNIQUE"
exec $argv" > $bootstrap_exec
set -gx YVM_BOOTSTRAP_EXEC_PATH $bootstrap_exec
yvm shim
set test_bootstrap_shim_output (yarn --version)
set -e YVM_BOOTSTRAP_EXEC_PATH
rm $bootstrap_exec
if string match -q -- "*UNIQUE*" $test_bootstrap_shim_output
pass
else
fail "yarn shim did not use custom bootstrap script: $test_bootstrap_shim_output"
end
34 changes: 34 additions & 0 deletions test/scripts/yvm.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pass
testing "yarn shim passes original arguments"
yarn fake './*.js'
pass
rm "./fake.js"

testing "yarn shimmed config"
test_shim_config_output=$(yarn --version)
Expand Down Expand Up @@ -120,3 +121,36 @@ if [[ $test4_output == "1.13.0" ]]; then
else
fail "yvm current command failed: $test4_output"
fi

testing "yvm exec with custom bootstrap"
bootstrap_exec=$(mktemp -t yvm_bootstrap.XXX)
chmod +x $bootstrap_exec
echo "#!/usr/bin/env bash
echo "UNIQUE"
exec $@" > $bootstrap_exec
export YVM_BOOTSTRAP_EXEC_PATH=$bootstrap_exec
test_bootstrap_exec_output=$(yvm exec --version)
unset YVM_BOOTSTRAP_EXEC_PATH
rm $bootstrap_exec
if [[ $test_bootstrap_exec_output =~ "UNIQUE" ]]; then
pass
else
fail "yvm exec did not use custom bootstrap script: $test_bootstrap_exec_output"
fi

testing "yarn shim with custom bootstrap"
bootstrap_exec=$(mktemp -t yvm_bootstrap.XXX)
chmod +x $bootstrap_exec
echo "#!/usr/bin/env bash
echo "UNIQUE"
exec $@" > $bootstrap_exec
export YVM_BOOTSTRAP_EXEC_PATH=$bootstrap_exec
yvm shim
test_bootstrap_shim_output=$(yarn --version)
unset YVM_BOOTSTRAP_EXEC_PATH
rm $bootstrap_exec
if [[ $test_bootstrap_shim_output =~ "UNIQUE" ]]; then
pass
else
fail "yarn shim did not use custom bootstrap script: $test_bootstrap_shim_output"
fi
7 changes: 1 addition & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,7 @@
dependencies:
"@babel/types" "^7.11.0"

"@babel/helper-validator-identifier@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==

"@babel/helper-validator-identifier@^7.12.11":
"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11":
version "7.12.11"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==
Expand Down

0 comments on commit 70c831a

Please sign in to comment.