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 } ``` diff --git a/jupyterlab/main.test.ts b/jupyterlab/main.test.ts index cf9ac1f0..a9789c39 100644 --- a/jupyterlab/main.test.ts +++ b/jupyterlab/main.test.ts @@ -33,6 +33,33 @@ 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 gcc musl-dev linux-headers && uv venv", + ]); + 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,19 +67,36 @@ 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([ - "\u001B[0;1mInstalling jupyterlab!", - "pipx is not installed", - "Please install pipx in your Dockerfile/VM image before running this script", + "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", ]); }); + // 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. // it("runs with pipx", async () => { diff --git a/jupyterlab/run.sh b/jupyterlab/run.sh index 0c3780dc..2dd34ace 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,27 +25,30 @@ 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 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" + JUPYTERPATH="$HOME/.local/bin" + ;; + esac else printf "%s\n\n" "🥳 jupyterlab is already installed" 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}" \