Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(steps): add install-node step #49

Merged
merged 4 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions workflow-steps/install-node/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
## Usage

> [!WARNING]
> This step current does not support Windows yet.

```yaml
- name: Install Node
uses: 'nrwl/nx-cloud-workflows/v4/workflow-steps/install-node/main.yaml'
inputs:
node_version: '20'
```

### Options

#### node_version

The node version to be installed. Any valid [nvm](https://github.com/nvm-sh/nvm/blob/master/README.md#usage) version is accepted.
This input is optional, as the step will also check for a `.nvmrc` file in the root of the repository.
If the file is present, the step will install the version specified in the file.
If the file is not present, the step will not install any node version and leave the default installed node version on the image for subsequent steps

For those using `volta`, the `volta.node` field in the `package.json` will also be picked up and used if present.

The current order of precedence is:

1. `node_version` input
1. `.nvmrc` file
1. `volta.node` field in `package.json`

For example:

- Install a specific node version: `node_version: '20.11.1'`
- Install latest of major node version: `node_version: '20'`
94 changes: 94 additions & 0 deletions workflow-steps/install-node/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
const { platform } = require('os');
const { execSync } = require('child_process');
const { existsSync, readFileSync } = require('fs');

if (platform === 'win32') {
throw new Error('Windows is not supported with this reuseable step yet.');
} else {
// Allow using inputs or env until we fully switch to inputs
const nodeVersionInput =
process.env.NX_CLOUD_INPUT_node_version || process.env.NODE_VERSION;

// set defaults incase they are not set yet
process.env.NVM_DIR ??= '/home/workflows/.nvm';
process.env.COREPACK_ENABLE_AUTO_PIN ??= 0;

const maybeVoltaNodeVersion = getVoltaNodeVersion();

if (nodeVersionInput) {
runNvmInstall(nodeVersionInput);
} else if (isUsingNvm()) {
// nvm will auto detect version in .nvmrc, no need to pass version
runNvmInstall(null);
} else if (maybeVoltaNodeVersion) {
runNvmInstall(maybeVoltaNodeVersion);
} else {
console.warn(
`No node version specified. You can use the step inputs to define a node version.`,
);
console.log(
`Falling back to the default node version in the base image. ${execSync(
'node -v',
)}`,
);
}

function getVoltaNodeVersion() {
try {
if (existsSync('package.json')) {
const packageJsonContents =
JSON.parse(readFileSync('package.json')) ?? {};

return packageJsonContents['volta']?.['node'];
}
} catch (e) {
return null;
}
}

function isUsingNvm() {
try {
return existsSync('.nvmrc');
} catch (e) {
return false;
}
}

function runNvmInstall(version) {
try {
// enable nvm and then run the install command
// nvm command isn't available since nx agents don't run the bash profile
const installNodeWithNvm = `. $NVM_DIR/nvm.sh && nvm install ${
version || ''
} --default`;
const reenableCorePack = `corepack enable`;
// install outside of the current directory,
// otherwise corepack errors if a different package mangager is used than is defined in the workspace
const reinstallPackageManagers = `cd .. && corepack prepare yarn@1 && corepack prepare pnpm@8`;
const printVersions = ['node', 'npm', 'yarn', 'pnpm']
.map((cmd) => `echo "${cmd}: $(${cmd} -v)"`)
.join(' && ');

// path will be updated via nvm to include the new node versions,
const saveEnvVars = `echo "PATH=$PATH\nNVM_DIR=${process.env.NVM_DIR}\nCOREPACK_ENABLE_AUTO_PIN=0" >> $NX_CLOUD_ENV`;

execSync(
[
installNodeWithNvm,
reenableCorePack,
reinstallPackageManagers,
printVersions,
saveEnvVars,
].join(' && '),
{
stdio: 'inherit',
},
);
} catch (e) {
console.error(e);
throw new Error(
`Failed to install node version using nvm ${version || ''}`,
);
}
}
}
9 changes: 9 additions & 0 deletions workflow-steps/install-node/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name: Install Node
description: Install a specific version of Node.js via nvm
inputs:
- name: node_version
description: 'The node version to be installed'

definition:
using: 'node'
main: workflow-steps/install-node/main.js