From d0dbd934435b7db9813b4348c7cc4caaf1dfbe90 Mon Sep 17 00:00:00 2001 From: ffais Date: Fri, 14 Feb 2025 16:52:46 +0100 Subject: [PATCH 1/6] feat(jupyterlab): support uv as installer Signed-off-by: ffais --- jupyterlab/main.test.ts | 44 ++++++++++++++++++++++++++++++++++++++--- jupyterlab/run.sh | 42 ++++++++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 14 deletions(-) diff --git a/jupyterlab/main.test.ts b/jupyterlab/main.test.ts index cf9ac1f0..de6f0ecc 100644 --- a/jupyterlab/main.test.ts +++ b/jupyterlab/main.test.ts @@ -33,6 +33,29 @@ const executeScriptInContainerWithPip = async ( }; }; +// executes the coder script after installing pip +const executeScriptInContainerWithUv = async ( + state: TerraformState, + image: string, + shell = "sh", +): Promise<{ + exitCode: number; + stdout: string[]; + stderr: string[]; +}> => { + const instance = findResourceInstance(state, "coder_script"); + const id = await runContainer(image); + const respPipx = await execContainer(id, [shell, "-c", "apk --no-cache add uv"]); + const resp = await execContainer(id, [shell, "-c", instance.script]); + const stdout = resp.stdout.trim().split("\n"); + const stderr = resp.stderr.trim().split("\n"); + return { + exitCode: resp.exitCode, + stdout, + stderr, + }; +}; + describe("jupyterlab", async () => { await runTerraformInit(import.meta.dir); @@ -40,16 +63,31 @@ describe("jupyterlab", async () => { agent_id: "foo", }); - it("fails without pipx", async () => { + it("fails without installers", async () => { const state = await runTerraformApply(import.meta.dir, { agent_id: "foo", }); const output = await executeScriptInContainer(state, "alpine"); expect(output.exitCode).toBe(1); expect(output.stdout).toEqual([ + "Checking for a supported installer", + "No valid installer is not installed", + "Please install pipx or uv in your Dockerfile/VM image before running this script", + ]); + }); + + it("runs with uv", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + }); + const output = await executeScriptInContainerWithUv(state, "alpine"); + expect(output.exitCode).toBe(0); + expect(output.stdout).toEqual([ + "Checking for a supported installer", + "uv is installed", "\u001B[0;1mInstalling jupyterlab!", - "pipx is not installed", - "Please install pipx in your Dockerfile/VM image before running this script", + "🥳 jupyterlab has been installed", + "👷 Starting jupyterlab in background...check logs at /tmp/jupyterlab.log", ]); }); diff --git a/jupyterlab/run.sh b/jupyterlab/run.sh index 0c3780dc..0a913640 100755 --- a/jupyterlab/run.sh +++ b/jupyterlab/run.sh @@ -1,4 +1,23 @@ #!/usr/bin/env sh +INSTALLER="" +check_available_installer () { + # check if pipx is installed + echo "Checking for a supported installer" + if command -v pipx > /dev/null 2>&1; then + echo "pipx is installed" + INSTALLER="pipx" + return + fi + # check if uv is installed + if command -v uv > /dev/null 2>&1; then + echo "uv is installed" + INSTALLER="uv" + return + fi + echo "No valid installer is not installed" + echo "Please install pipx or uv in your Dockerfile/VM image before running this script" + exit 1 +} if [ -n "${BASE_URL}" ]; then BASE_URL_FLAG="--ServerApp.base_url=${BASE_URL}" @@ -6,20 +25,21 @@ fi BOLD='\033[0;1m' -printf "$${BOLD}Installing jupyterlab!\n" - # check if jupyterlab is installed if ! command -v jupyter-lab > /dev/null 2>&1; then # install jupyterlab - # check if pipx is installed - if ! command -v pipx > /dev/null 2>&1; then - echo "pipx is not installed" - echo "Please install pipx in your Dockerfile/VM image before running this script" - exit 1 - fi - # install jupyterlab - pipx install -q jupyterlab - printf "%s\n\n" "🥳 jupyterlab has been installed" + check_available_installer + printf "$${BOLD}Installing jupyterlab!\n" + case $INSTALLER in + uv) + uv add jupyter-lab + printf "%s\n" "🥳 jupyterlab has been installed" + ;; + pipx) + pipx install -q jupyterlab + printf "%s\n" "🥳 jupyterlab has been installed" + ;; + esac else printf "%s\n\n" "🥳 jupyterlab is already installed" fi From 63a9c273d81577a3dcf9af7c9b040b3e6f1d0485 Mon Sep 17 00:00:00 2001 From: ffais Date: Tue, 18 Feb 2025 10:49:51 +0100 Subject: [PATCH 2/6] fix(jupyterlab): added changes suggested by prettier Signed-off-by: ffais --- jupyterlab/main.test.ts | 6 +++++- jupyterlab/run.sh | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/jupyterlab/main.test.ts b/jupyterlab/main.test.ts index de6f0ecc..816afd2a 100644 --- a/jupyterlab/main.test.ts +++ b/jupyterlab/main.test.ts @@ -45,7 +45,11 @@ const executeScriptInContainerWithUv = async ( }> => { const instance = findResourceInstance(state, "coder_script"); const id = await runContainer(image); - const respPipx = await execContainer(id, [shell, "-c", "apk --no-cache add uv"]); + const respPipx = await execContainer(id, [ + shell, + "-c", + "apk --no-cache add uv", + ]); const resp = await execContainer(id, [shell, "-c", instance.script]); const stdout = resp.stdout.trim().split("\n"); const stderr = resp.stderr.trim().split("\n"); diff --git a/jupyterlab/run.sh b/jupyterlab/run.sh index 0a913640..10392bdf 100755 --- a/jupyterlab/run.sh +++ b/jupyterlab/run.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh INSTALLER="" -check_available_installer () { +check_available_installer() { # check if pipx is installed echo "Checking for a supported installer" if command -v pipx > /dev/null 2>&1; then From 01c8f7e46699dea349e9d11605b1c1a272364393 Mon Sep 17 00:00:00 2001 From: ffais Date: Tue, 18 Feb 2025 12:53:02 +0100 Subject: [PATCH 3/6] fix(jupyterlab): bump module version in README Signed-off-by: ffais --- jupyterlab/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jupyterlab/README.md b/jupyterlab/README.md index c285c275..8c2af03f 100644 --- a/jupyterlab/README.md +++ b/jupyterlab/README.md @@ -17,7 +17,7 @@ A module that adds JupyterLab in your Coder template. module "jupyterlab" { count = data.coder_workspace.me.start_count source = "registry.coder.com/modules/jupyterlab/coder" - version = "1.0.23" + version = "1.0.30" agent_id = coder_agent.example.id } ``` From 9ceb8906ebdbd07338007f5138fcbaa56a468dd4 Mon Sep 17 00:00:00 2001 From: ffais Date: Tue, 18 Feb 2025 13:41:21 +0100 Subject: [PATCH 4/6] fix(jupyterlab): fix uv package name Signed-off-by: ffais --- jupyterlab/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jupyterlab/run.sh b/jupyterlab/run.sh index 10392bdf..9ca5c6d4 100755 --- a/jupyterlab/run.sh +++ b/jupyterlab/run.sh @@ -32,7 +32,7 @@ if ! command -v jupyter-lab > /dev/null 2>&1; then printf "$${BOLD}Installing jupyterlab!\n" case $INSTALLER in uv) - uv add jupyter-lab + uv add jupyterlab printf "%s\n" "🥳 jupyterlab has been installed" ;; pipx) From 96555d7725416b42f15daa92c1a9bf89914e980d Mon Sep 17 00:00:00 2001 From: ffais Date: Tue, 18 Feb 2025 15:13:49 +0100 Subject: [PATCH 5/6] fix(jupyterlab): improve jupyterlab path handling & disabled test because of timeout Signed-off-by: ffais --- jupyterlab/main.test.ts | 32 +++++++++++++++++--------------- jupyterlab/run.sh | 8 +++++--- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/jupyterlab/main.test.ts b/jupyterlab/main.test.ts index 816afd2a..a9789c39 100644 --- a/jupyterlab/main.test.ts +++ b/jupyterlab/main.test.ts @@ -48,7 +48,7 @@ const executeScriptInContainerWithUv = async ( const respPipx = await execContainer(id, [ shell, "-c", - "apk --no-cache add uv", + "apk --no-cache add uv gcc musl-dev linux-headers && uv venv", ]); const resp = await execContainer(id, [shell, "-c", instance.script]); const stdout = resp.stdout.trim().split("\n"); @@ -80,20 +80,22 @@ describe("jupyterlab", async () => { ]); }); - it("runs with uv", async () => { - const state = await runTerraformApply(import.meta.dir, { - agent_id: "foo", - }); - const output = await executeScriptInContainerWithUv(state, "alpine"); - expect(output.exitCode).toBe(0); - expect(output.stdout).toEqual([ - "Checking for a supported installer", - "uv is installed", - "\u001B[0;1mInstalling jupyterlab!", - "🥳 jupyterlab has been installed", - "👷 Starting jupyterlab in background...check logs at /tmp/jupyterlab.log", - ]); - }); + // TODO: Add faster test to run with uv. + // currently times out. + // it("runs with uv", async () => { + // const state = await runTerraformApply(import.meta.dir, { + // agent_id: "foo", + // }); + // const output = await executeScriptInContainerWithUv(state, "python:3-alpine"); + // expect(output.exitCode).toBe(0); + // expect(output.stdout).toEqual([ + // "Checking for a supported installer", + // "uv is installed", + // "\u001B[0;1mInstalling jupyterlab!", + // "🥳 jupyterlab has been installed", + // "👷 Starting jupyterlab in background...check logs at /tmp/jupyterlab.log", + // ]); + // }); // TODO: Add faster test to run with pipx. // currently times out. diff --git a/jupyterlab/run.sh b/jupyterlab/run.sh index 9ca5c6d4..e2f2e9ac 100755 --- a/jupyterlab/run.sh +++ b/jupyterlab/run.sh @@ -32,12 +32,14 @@ if ! command -v jupyter-lab > /dev/null 2>&1; then printf "$${BOLD}Installing jupyterlab!\n" case $INSTALLER in uv) - uv add jupyterlab + uv pip install -q jupyterlab && \ printf "%s\n" "🥳 jupyterlab has been installed" + JUPYTERPATH="$HOME/.venv/bin/" ;; pipx) - pipx install -q jupyterlab + pipx install jupyterlab && \ printf "%s\n" "🥳 jupyterlab has been installed" + JUPYTERPATH="$HOME/.local/bin" ;; esac else @@ -46,7 +48,7 @@ fi printf "👷 Starting jupyterlab in background..." printf "check logs at ${LOG_PATH}" -$HOME/.local/bin/jupyter-lab --no-browser \ +$JUPYTERPATH/jupyter-lab --no-browser \ "$BASE_URL_FLAG" \ --ServerApp.ip='*' \ --ServerApp.port="${PORT}" \ From 6344d1a22e96b48beaaf147eecf6e69973b4b1b2 Mon Sep 17 00:00:00 2001 From: ffais Date: Tue, 18 Feb 2025 15:35:40 +0100 Subject: [PATCH 6/6] fix(jupyterlab): fix lint Signed-off-by: ffais --- jupyterlab/run.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jupyterlab/run.sh b/jupyterlab/run.sh index e2f2e9ac..2dd34ace 100755 --- a/jupyterlab/run.sh +++ b/jupyterlab/run.sh @@ -32,13 +32,13 @@ if ! command -v jupyter-lab > /dev/null 2>&1; then printf "$${BOLD}Installing jupyterlab!\n" case $INSTALLER in uv) - uv pip install -q jupyterlab && \ - printf "%s\n" "🥳 jupyterlab has been installed" + uv pip install -q jupyterlab \ + && printf "%s\n" "🥳 jupyterlab has been installed" JUPYTERPATH="$HOME/.venv/bin/" ;; pipx) - pipx install jupyterlab && \ - printf "%s\n" "🥳 jupyterlab has been installed" + pipx install jupyterlab \ + && printf "%s\n" "🥳 jupyterlab has been installed" JUPYTERPATH="$HOME/.local/bin" ;; esac