Skip to content

Commit

Permalink
Use fnm to switch between node version
Browse files Browse the repository at this point in the history
Pre-install the current nodejs LTS versions (18, 20, 22) and allow switching between them using `fnm`. The default remains at 18.

Fixes #223
  • Loading branch information
julienp committed Aug 23, 2024
1 parent 6ddd6a8 commit 35518a4
Show file tree
Hide file tree
Showing 26 changed files with 280 additions and 26 deletions.
28 changes: 14 additions & 14 deletions docker/pulumi/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,6 @@ RUN \
kubectl && \
rm -rf /var/lib/apt/lists/*

# Install nodejs and associated tools
RUN \
# Add yarn repo
curl -fsSL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
# Add nodejs repo
curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
# Install packages
apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
nodejs \
yarn && \
rm -rf /var/lib/apt/lists/*

# Install Go
RUN curl -fsSLo /tmp/go.tgz https://golang.org/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz && \
echo "${GOLANG_SHA256} /tmp/go.tgz" | sha256sum -c - && \
Expand Down Expand Up @@ -131,6 +118,19 @@ RUN ln -s /usr/local/share/pypoetry/bin/poetry /usr/local/bin/
# poetry will create virtual environments using the python version used by poetry itself.
RUN poetry config virtualenvs.prefer-active-python true

# Install default nodejs versions and associated tools
RUN curl -fsSL https://fnm.vercel.app/install | bash -s -- --install-dir "/opt/fnm" --skip-shell && \
ln -s /opt/fnm/fnm /usr/local/bin/fnm
ENV FNM_COREPACK_ENABLED="true"
ENV FNM_VERSION_FILE_STRATEGY="recursive"
ENV FNM_DIR=/opt/fnm
RUN fnm install 18 && \
fnm install 20 && \
fnm install 22 && \
fnm alias 18 default
ENV PATH=/opt/fnm/aliases/default/bin:$PATH
RUN corepack install --global pnpm yarn

# Passing --build-arg PULUMI_VERSION=vX.Y.Z will use that version
# of the SDK. Otherwise, we use whatever get.pulumi.com thinks is
# the latest
Expand All @@ -139,7 +139,7 @@ ARG PULUMI_VERSION
# Install the Pulumi SDK, including the CLI and language runtimes.
# TODO: Should use $PULUMI_VERSION, not dev
# RUN curl -fsSL https://get.pulumi.com/ | bash -s -- --version $PULUMI_VERSION && \
RUN curl -fsSL https://get.pulumi.com | sh -s -- --version dev && \
RUN curl -fsSL https://get.pulumi.com | bash -s -- --version dev && \
mv ~/.pulumi/bin/* /usr/bin

# I think it's safe to say if we're using this mega image, we want pulumi
Expand Down
29 changes: 17 additions & 12 deletions tests/containers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ func TestPulumiTemplateTests(t *testing.T) {
}
}

func TestKitchenSinkPythonVersions(t *testing.T) {
func TestKitchenSinkLanguageVersions(t *testing.T) {
if !isKitchenSink(t) {
t.Skip("Only running python version tests on kitchen sink")
t.Skip("Only language version tests on kitchen sink")
}
t.Parallel()

Expand All @@ -134,6 +134,11 @@ func TestKitchenSinkPythonVersions(t *testing.T) {
for _, dir := range dirs {
dir := dir
t.Run(dir.Name(), func(t *testing.T) {
if !strings.HasPrefix(dir.Name(), "node-") {
// We can't run the node tests in parallel because setting the node version is a
// global for the container
t.Parallel()
}
p := filepath.Join("testdata", dir.Name())
copyTestData(t, p)
integration.ProgramTest(t, &integration.ProgramTestOptions{
Expand All @@ -143,7 +148,11 @@ func TestKitchenSinkPythonVersions(t *testing.T) {
PrepareProject: func(info *engine.Projinfo) error {
cmd := exec.Command("pulumi", "install", "--use-language-version-tools")
cmd.Dir = info.Root
return cmd.Run()
out, err := cmd.CombinedOutput()
if err != nil {
t.Logf("install failed: %s: %s", err, out)
}
return err
},
})
})
Expand Down Expand Up @@ -250,26 +259,26 @@ func TestEnvironment(t *testing.T) {
name: "node",
expectedDebian: "/usr/local/bin/node",
expectedUbi: "/usr/bin/node",
expectedKitchen: "/usr/bin/node",
expectedKitchen: "/opt/fnm/aliases/default/bin/node",
},
{
name: "npm",
expectedDebian: "/usr/local/bin/npm",
expectedUbi: "/usr/local/bin/npm",
expectedKitchen: "/usr/bin/npm",
expectedKitchen: "/opt/fnm/aliases/default/bin/npm",
},

{
name: "yarn",
expectedDebian: "/usr/local/bin/yarn",
expectedUbi: "/usr/local/bin/yarn",
expectedKitchen: "/usr/bin/yarn",
expectedKitchen: "/opt/fnm/aliases/default/bin/yarn",
},
{
name: "corepack",
expectedDebian: "/usr/local/bin/corepack",
expectedUbi: "/usr/bin/corepack",
expectedKitchen: "/usr/bin/corepack",
expectedKitchen: "/opt/fnm/aliases/default/bin/corepack",
},
} {
testCase := testCase
Expand All @@ -295,7 +304,7 @@ func TestEnvironment(t *testing.T) {
// Install scripts for various tools can sometimes modify PATH, usually by adding entries
// to ~/.bashrc. This test ensures that we notice such modifications.
expectedPaths := map[string]string{
"pulumi": "/usr/local/share/pyenv/shims:/usr/local/share/pyenv/bin:/usr/share/dotnet:/pulumi/bin:/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"pulumi": "/opt/fnm/aliases/default/bin:/usr/local/share/pyenv/shims:/usr/local/share/pyenv/bin:/usr/share/dotnet:/pulumi/bin:/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"pulumi-debian-dotnet": "/root/.dotnet:/pulumi/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"pulumi-debian-go": "/pulumi/bin:/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"pulumi-debian-java": "/pulumi/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
Expand All @@ -311,10 +320,6 @@ func TestEnvironment(t *testing.T) {
t.Run("PATH when running in bash", func(t *testing.T) {
t.Parallel()
expectedPath := expectedPaths[imageVariant]
// When running in bash, we pick up the PATH entry from the pulumi installation script.
if imageVariant == "pulumi" {
expectedPath += ":/root/.pulumi/bin"
}
requireOutputWithBash(t, expectedPath, "printenv", "PATH")
})

Expand Down
1 change: 1 addition & 0 deletions tests/testdata/node-18/.node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
18
10 changes: 10 additions & 0 deletions tests/testdata/node-18/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: node-default
runtime:
name: nodejs
options:
packagemanager: npm
description: A minimal TypeScript Pulumi program
config:
pulumi:tags:
value:
pulumi:template: typescript
10 changes: 10 additions & 0 deletions tests/testdata/node-18/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as process from "node:process";
import * as semver from "semver";

const version = semver.parse(process.version, {
loose: true
});

if (version?.major != 18) {
throw new Error(`Expected node version 18.x.x, got ${process.version}`);
}
12 changes: 12 additions & 0 deletions tests/testdata/node-18/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "node-default",
"main": "index.ts",
"devDependencies": {
"@types/node": "^18",
"typescript": "^5.0.0"
},
"dependencies": {
"@pulumi/pulumi": "^3.113.0",
"semver": "^7.6.3"
}
}
18 changes: 18 additions & 0 deletions tests/testdata/node-18/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2020",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts"
]
}
1 change: 1 addition & 0 deletions tests/testdata/node-20/.node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20
10 changes: 10 additions & 0 deletions tests/testdata/node-20/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: node-default
runtime:
name: nodejs
options:
packagemanager: npm
description: A minimal TypeScript Pulumi program
config:
pulumi:tags:
value:
pulumi:template: typescript
10 changes: 10 additions & 0 deletions tests/testdata/node-20/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as process from "node:process";
import * as semver from "semver";

const version = semver.parse(process.version, {
loose: true
});

if (version?.major != 20) {
throw new Error(`Expected node version 20.x.x, got ${process.version}`);
}
12 changes: 12 additions & 0 deletions tests/testdata/node-20/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "node-default",
"main": "index.ts",
"devDependencies": {
"@types/node": "^18",
"typescript": "^5.0.0"
},
"dependencies": {
"@pulumi/pulumi": "^3.113.0",
"semver": "^7.6.3"
}
}
18 changes: 18 additions & 0 deletions tests/testdata/node-20/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2020",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts"
]
}
1 change: 1 addition & 0 deletions tests/testdata/node-22.5.1/.node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22.5.1
10 changes: 10 additions & 0 deletions tests/testdata/node-22.5.1/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: node-default
runtime:
name: nodejs
options:
packagemanager: npm
description: A minimal TypeScript Pulumi program
config:
pulumi:tags:
value:
pulumi:template: typescript
5 changes: 5 additions & 0 deletions tests/testdata/node-22.5.1/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import * as process from "node:process";

if (process.version != "v22.5.1") {
throw new Error(`Expected node version 22.5.1 got ${process.version}`);
}
12 changes: 12 additions & 0 deletions tests/testdata/node-22.5.1/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "node-default",
"main": "index.ts",
"devDependencies": {
"@types/node": "^18",
"typescript": "^5.0.0"
},
"dependencies": {
"@pulumi/pulumi": "^3.113.0",
"semver": "^7.6.3"
}
}
18 changes: 18 additions & 0 deletions tests/testdata/node-22.5.1/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2020",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts"
]
}
1 change: 1 addition & 0 deletions tests/testdata/node-22/.node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22
10 changes: 10 additions & 0 deletions tests/testdata/node-22/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: node-default
runtime:
name: nodejs
options:
packagemanager: npm
description: A minimal TypeScript Pulumi program
config:
pulumi:tags:
value:
pulumi:template: typescript
10 changes: 10 additions & 0 deletions tests/testdata/node-22/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as process from "node:process";
import * as semver from "semver";

const version = semver.parse(process.version, {
loose: true
});

if (version?.major != 22) {
throw new Error(`Expected node version 22.x.x, got ${process.version}`);
}
12 changes: 12 additions & 0 deletions tests/testdata/node-22/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "node-default",
"main": "index.ts",
"devDependencies": {
"@types/node": "^18",
"typescript": "^5.0.0"
},
"dependencies": {
"@pulumi/pulumi": "^3.113.0",
"semver": "^7.6.3"
}
}
18 changes: 18 additions & 0 deletions tests/testdata/node-22/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2020",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts"
]
}
10 changes: 10 additions & 0 deletions tests/testdata/node-default/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: node-default
runtime:
name: nodejs
options:
packagemanager: npm
description: A minimal TypeScript Pulumi program
config:
pulumi:tags:
value:
pulumi:template: typescript
10 changes: 10 additions & 0 deletions tests/testdata/node-default/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as process from "node:process";
import * as semver from "semver";

const version = semver.parse(process.version, {
loose: true
});

if (version?.major != 18) {
throw new Error(`Expected node version 18.x.x, got ${process.version}`);
}
12 changes: 12 additions & 0 deletions tests/testdata/node-default/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "node-default",
"main": "index.ts",
"devDependencies": {
"@types/node": "^18",
"typescript": "^5.0.0"
},
"dependencies": {
"@pulumi/pulumi": "^3.113.0",
"semver": "^7.6.3"
}
}
Loading

0 comments on commit 35518a4

Please sign in to comment.