### PostgreSQL Client Usage Examples (Bash) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Provides command-line examples for interacting with a PostgreSQL database after the client tools have been installed. Includes connecting to the database, backing up, and restoring data. ```bash # Connect to PostgreSQL database psql -h database-host -U username -d database_name # Backup database pg_dump -h database-host -U username database_name > backup.sql # Restore database pg_restore -h database-host -U username -d database_name backup.dump ``` -------------------------------- ### Install Python Packaging Tools Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/jupyter-common/extension-builder/extension/server-proxy-notif/RELEASE.md Installs necessary tools for building and uploading Python packages: 'build' for package creation, 'twine' for uploading to PyPI, and 'hatch' for version management. ```bash pip install build twine hatch ``` -------------------------------- ### Local Development Setup with Devcontainer CLI (Bash) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Steps to set up a local development environment using the devcontainer CLI. This includes creating a Docker network, navigating to the app directory, commenting out Workbench-specific commands, and starting the devcontainer. ```bash # 1. Install devcontainer CLI # https://code.visualstudio.com/docs/devcontainers/devcontainer-cli # 2. Create the required Docker network docker network create app-network # 3. Navigate to your app directory cd src/my-custom-app # 4. Comment out Workbench-specific commands for local testing # In .devcontainer.json, comment out postCreateCommand and postStartCommand # 5. Start the devcontainer devcontainer up --workspace-folder . # 6. Access your app # Jupyter: http://localhost:8888 # RStudio: http://localhost:8787 # VSCode: http://localhost:8443 # ttyd terminal: http://localhost:7681 ``` -------------------------------- ### Install PostgreSQL Client Tools (JSON) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Installs essential PostgreSQL client utilities such as psql, pg_dump, and pg_restore. This feature is configured within the devcontainer setup, allowing for database connectivity and management. ```json { "features": { "./.devcontainer/features/postgres-client": { "version": "16" } } } ``` -------------------------------- ### Post-Startup Script for Workbench Environment Setup (Bash) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt A bash script executed after container creation to configure the Workbench environment. It installs the workbench CLI, sets up bash profiles, mounts cloud storage, and configures git if login is enabled. ```bash # Script usage (called automatically via postCreateCommand) ./startupscript/post-startup.sh # Example invocation ./startupscript/post-startup.sh jovyan /home/jovyan gcp true # What the script configures: # - Installs workbench CLI to /usr/bin/wb # - Configures ~/.bashrc and ~/.bash_profile # - Installs gcsfuse for cloud storage mounting # - Mounts workspace resources to ${home_dir}/workspaces # - Sets up git configuration if login is enabled ``` -------------------------------- ### Install bats-core for Script Testing Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/scripts/test/README.md Instructions for installing the bats-core testing framework on macOS and Ubuntu/Debian systems, or from source. This is a prerequisite for running the script tests. ```bash # On macOS with Homebrew brew install bats-core # On Ubuntu/Debian sudo apt-get install bats # Or install from source git clone https://github.com/bats-core/bats-core.git cd bats-core sudo ./install.sh /usr/local ``` -------------------------------- ### Run Local Testing Script with Bash Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/ubuntu-example/README.md This bash command navigates to the 'test' directory and executes the test script for the 'ubuntu-example' application. This is used to verify the application's functionality locally. ```bash cd test ./test.sh ubuntu-example ``` -------------------------------- ### bats Test Setup and Teardown Functions Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/scripts/test/README.md Demonstrates the use of `setup()` and `teardown()` functions in bats for managing test environment state before and after each test execution. This is crucial for ensuring test isolation and cleanup. ```bash setup() { # Runs before each test TEST_TEMP_DIR="$(mktemp -d)" } teardown() { # Runs after each test rm -rf "${TEST_TEMP_DIR}" } ``` -------------------------------- ### Install Java 17 in Dev Container Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/features/src/java/README.md This snippet shows how to configure your devcontainer.json file to install Java 17. It utilizes a specific feature path to enable the Java installation. No external dependencies are required beyond the dev container setup itself. ```json { "features": { "./.devcontainer/features/src/java:1": {} } } ``` -------------------------------- ### Development Install for aou_jupyterlab Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/aou-common/extension-builder/extension/aou-jupyterlab/README.md Steps to install the aou_jupyterlab extension in development mode. This involves cloning the repository, installing the package, linking it to JupyterLab, and building the extension. ```bash # Clone the repo to your local environment # Change directory to the aou_jupyterlab directory # Install package in development mode pip install -e "." # Link your development version of the extension with JupyterLab jupyter labextension develop . --overwrite # Rebuild extension Typescript source after making changes jlpm build ``` -------------------------------- ### Install Jupyter Server Dev Container Feature Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/features/src/jupyter/README.md Example of how to include the Jupyter Server dev container feature in your devcontainer configuration. This snippet demonstrates the basic inclusion of the feature. ```json "features": { "./.devcontainer/features/src/jupyter:1": {} } ``` -------------------------------- ### Testing Dataproc Post-Startup Script Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/startupscript/README.md This snippet shows how to test a post-startup script for a Dataproc cluster. It involves creating a Dataproc cluster and specifying the URL of the startup script from a GitHub repository. ```bash wb resource create dataproc-cluster --name=dataprocForTesting --metadata=startup-script-url=https://raw.githubusercontent.com/verily-src/workbench-app-devcontainers//startupscript/dataproc/startup.sh ``` -------------------------------- ### Configure ttyd Startup Command with YAML Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/ubuntu-example/README.md This YAML snippet demonstrates how to configure the ttyd startup command within `docker-compose.yaml`. It specifies the port and the shell to run, ensuring web terminal access. ```yaml command: ["ttyd", "-W", "-p", "7681", "bash"] ``` -------------------------------- ### JavaScript: App Creation Modal and Examples Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html Manages the modal for creating new applications, including form reset and setting default Caddy templates. It also handles loading example application configurations (ttyd, JupyterLab) into the form. ```javascript function openCreateModal() { document.getElementById('modal-title').textContent = 'Create New App'; document.getElementById('app-form').reset(); document.getElementById('app-id').value = ''; document.getElementById('examples-section').style.display = 'block'; document.getElementById('modal-error').style.display = 'none'; // Set default Caddy template document.getElementById('caddy-config').value = DEFAULT_CADDY_TEMPLATE; onCaddyConfigChange(); // Update checkbox state document.getElementById('app-modal').style.display = 'block'; } function loadExample(type) { const examples = { ttyd: { name: 'ttyd', username: 'root', userHome: '/root', port: 7681, caddyConfig: STRIP_PREFIX_CADDY_TEMPLATE, dockerfile: `FROM tsl0922/ttyd:latest # Install sudo RUN apt-get update && apt-get install -y sudo && rm -rf /var/lib/apt/lists/*` }, jupyterlab: { name: 'jupyterlab', username: 'jovyan', userHome: '/home/jovyan', port: 8888, caddyConfig: DEFAULT_CADDY_TEMPLATE, dockerfile: `FROM quay.io/jupyter/base-notebook USER root # Ensure the jovyan user has proper ownership of home` } }; const example = examples[type]; if (example) { document.getElementById('app-name').value = example.name; document.getElementById('username').value = example.username; document.getElementById('user-home-directory').value = example.userHome; document.getElementById('port').value = example.port; document.getElementById('caddy-config').value = example.caddyConfig; document.getElementById('dockerfile').value = example.dockerfile; onCaddyConfigChange(); // Update based on loaded config } } ``` -------------------------------- ### Run Workbench App Locally (Bash) Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/README.md Commands to navigate to the application's source directory and then build and run the application using the devcontainer CLI. This assumes the devcontainer CLI is installed and the Docker network is set up. ```bash cd src/ devcontainer up --workspace-folder . ``` -------------------------------- ### Testing Vertex AI Post-Startup Script Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/startupscript/README.md This snippet demonstrates how to test a modified post-startup script for a Vertex AI user-managed notebook. It involves creating a new notebook instance, pointing to a specific branch of the script in a GitHub repository. ```bash wb resource create gcp-notebook --id=jupyterNotebookForTesting --post-startup-script=https://raw.githubusercontent.com/verily-src/workbench-app-devcontainers//startupscript/vertex-ai-user-managed-notebook/post-startup.sh ``` -------------------------------- ### Scaffold Custom App with Bash Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/ubuntu-example/README.md This bash script command is used to create an initial scaffold for a custom application. It takes the application name, base image, port, user, and home directory as arguments. ```bash ./scripts/create-custom-app.sh ubuntu-example mcr.microsoft.com/devcontainers/base:ubuntu 7681 vscode /home/vscode ``` -------------------------------- ### Create Docker Network (Bash) Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/README.md Creates an external Docker network named 'app-network', which is a prerequisite for running Workbench applications locally. This command requires Docker to be installed and running. ```bash docker network create app-network ``` -------------------------------- ### Workbench Tools Feature Configuration (JSON) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Example JSON configuration for the `workbench-tools` devcontainer feature. It specifies the cloud provider, username, and home directory for the tools installation. ```json { "features": { "./.devcontainer/features/workbench-tools": { "cloud": "gcp", "username": "rstudio", "userHomeDir": "/home/rstudio" } } } ``` -------------------------------- ### Example Usage of Workbench Tools Dev Container Feature Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/features/src/workbench-tools/README.md Demonstrates how to include the workbench-tools dev container feature in a devcontainer.json configuration. This feature installs common tools required for Workbench Applications. ```json { "features": { "ghcr.io/verily-src/workbench-app-devcontainers/workbench-tools:1": {} } } ``` -------------------------------- ### Verify Installed Tools (Bash) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Commands to verify the installation of bioinformatics tools and Python packages provided by the `workbench-tools` feature. Includes checks for common scientific computing libraries and GCP's `dsub`. ```bash # Bioinformatics tools bcftools --version samtools --version-only plink --version plink2 --version regenie --version vcftools --version bedtools --version nextflow -v cromwell --version vep --help # Python packages (via /opt/workbench-tools/2/bin/python3) python3 -c "import pandas, numpy, matplotlib, scipy, sklearn" # GCP-specific: dsub for batch processing dsub -v ``` -------------------------------- ### JavaScript: Populate Application Form Fields Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html Populates form fields in a modal dialog with example application settings. It takes an application type, retrieves corresponding example data, and updates input fields for name, username, user home, port, Dockerfile, and Caddy configuration. ```javascript function populateExample(type) { const examples = { jupyterlab: { name: 'jupyterlab', username: 'jovyan', userHome: '/home/jovyan', port: 8888, caddyConfig: STRIP_PREFIX_CADDY_TEMPLATE, dockerfile: `RUN chown -R jovyan:users /home/jovyan && \\ mkdir -p /home/jovyan/.local/share/jupyter && \\ chown -R jovyan:users /home/jovyan/.local USER jovyan # Start JupyterLab with base_url CMD ["sh", "-c", "start-notebook.sh --NotebookApp.token='' --NotebookApp.password='' --ServerApp.base_url=/{{.AppName}}"]` }, rstudio: { name: 'rstudio', username: 'rstudio', userHome: '/home/rstudio', port: 8787, caddyConfig: STRIP_PREFIX_CADDY_TEMPLATE, dockerfile: `FROM ghcr.io/rocker-org/devcontainer/tidyverse:4.5 ENV DISABLE_AUTH=true RUN echo "www-root-path=/{{.AppName}}/" >> /etc/rstudio/disable_auth_rserver.conf` } }; const example = examples[type]; if (!example) return; document.getElementById('app-name').value = example.name; document.getElementById('username').value = example.username; document.getElementById('user-home').value = example.userHome; document.getElementById('port').value = example.port; document.getElementById('dockerfile').value = example.dockerfile; document.getElementById('caddy-config').value = example.caddyConfig; onCaddyConfigChange(); // Update checkbox state document.getElementById('feature-wb').checked = false; document.getElementById('feature-workbench-tools').checked = false; } ``` -------------------------------- ### Install aou_jupyterlab Extension Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/aou-common/extension-builder/extension/aou-jupyterlab/README.md Command to install the aou_jupyterlab JupyterLab extension using pip. This makes the extension available in the JupyterLab environment. ```bash pip install aou_jupyterlab ``` -------------------------------- ### Making Variables Readonly in Shell Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/startupscript/README.md Demonstrates how to declare shell variables as readonly. The first example shows a direct assignment, while the second shows how to handle assignments involving command output, where readonly is applied subsequently. ```shell readonly FOO="foo" FOO="$(command)" readonly FOO ``` -------------------------------- ### JupyterLab Devcontainer Configuration Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html Defines the configuration for a JupyterLab devcontainer. It sets up the user, home directory, and starts JupyterLab with specific base URL settings. This configuration is part of a larger devcontainer setup. ```dockerfile RUN chown -R jovyan:users /home/jovyan && \\ mkdir -p /home/jovyan/.local/share/jupyter && \\ chown -R jovyan:users /home/jovyan/.local USER jovyan # Start JupyterLab with base_url CMD ["sh", "-c", "start-notebook.sh --NotebookApp.token='' --NotebookApp.password='' --ServerApp.base_url=/{{.AppName}}"] ``` -------------------------------- ### Write a Basic bats Test Case Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/scripts/test/README.md Example of a basic test case structure in bats, demonstrating how to run a script and assert its exit status and output. This follows the standard bats format for defining tests. ```bash @test "description of test" { run ./your-script.sh args [ "$status" -eq 0 ] [[ "$output" == *"expected string"* ]] } ``` -------------------------------- ### Start/Stop App (JavaScript) Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html These functions are wrappers around the `controlApp` function, specifically for starting and stopping applications. They take the application ID as input and call `controlApp` with the appropriate action. ```javascript async function startApp(id) { await controlApp(id, 'start'); } async function stopApp(id) { await controlApp(id, 'stop'); } ``` -------------------------------- ### Add ttyd Dev Container Feature with JSON Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/ubuntu-example/README.md This JSON snippet shows how to add the ttyd dev container feature to the `.devcontainer.json` file. This enables web-based terminal access to the container. ```json "ghcr.io/ar90n/devcontainer-features/ttyd:1": {} ``` -------------------------------- ### Install Jupyter with Python and Cloud Configuration (JSON) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Installs Python and JupyterLab with options for specific Python versions, cloud platform integration (e.g., GCP), and configurable web access origins. This feature is defined in the devcontainer configuration. ```json { "features": { "./.devcontainer/features/jupyter": { "version": "3.11", "installJupyterlab": true, "cloudPlatform": "gcp", "configureJupyterlabAllowOrigin": "*", "user": "jupyter" } } } ``` -------------------------------- ### Start Polling for Status Updates (JavaScript) Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html This function starts polling for application status updates. It checks if any applications are in a 'pending' state and reloads the application list every 5 seconds if so. ```javascript function startPolling() { pollInterval = setInterval(async () => { const hasPending = apps.some(app => app.status === 'pending'); if (hasPending) { await loadApps(); } }, 5000); } ``` -------------------------------- ### Devcontainer Configuration (.devcontainer.json) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Defines the devcontainer application configuration, including the Docker image, startup commands, and features. `postCreateCommand` runs once after creation, and `postStartCommand` runs on each container start. ```json { "name": "my-app", "dockerComposeFile": "docker-compose.yaml", "service": "app", "shutdownAction": "none", "workspaceFolder": "/workspace", "postCreateCommand": [ "./startupscript/post-startup.sh", "jovyan", "/home/jovyan", "${templateOption:cloud}", "${templateOption:login}" ], "postStartCommand": [ "./startupscript/remount-on-restart.sh", "jovyan", "/home/jovyan", "${templateOption:cloud}", "${templateOption:login}" ], "features": { "ghcr.io/devcontainers/features/java:1": { "version": "17" }, "ghcr.io/devcontainers/features/aws-cli:1": {}, "ghcr.io/dhoeric/features/google-cloud-cli:1": {}, "./.devcontainer/features/workbench-tools": { "cloud": "${templateOption:cloud}", "username": "jovyan", "userHomeDir": "/home/jovyan" } }, "remoteUser": "root" } ``` -------------------------------- ### Integration Test Execution for App Templates (Bash) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt A bash script used to run integration tests for app templates, verifying the correct installation and configuration of tools like gcsfuse, workbench CLI, and other features. Tests can be run for specific templates. ```bash # Run tests for a specific app template cd test ./test.sh jupyter-template # Test script verifies: # - gcsfuse installation # - Workbench CLI installation (wb version) # - fuse.conf configuration # - Bioinformatics tools (if workbench-tools feature enabled) # - PostgreSQL client (if postgres-client feature enabled) # Example test output: # [PASS] gcsfuse # [PASS] wb cli # [PASS] fuse.conf user_allow_other # [PASS] python3 # [PASS] bcftools # [PASS] plink ``` -------------------------------- ### Docker Compose Configuration (docker-compose.yaml) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Defines the container setup, including Workbench networking and storage mounting. The container must be named `application-server` and connect to the `app-network`. It requires specific capabilities for `gcsfuse`. ```yaml services: app: # Required: container name must be "application-server" container_name: "application-server" image: "quay.io/jupyter/base-notebook" restart: always volumes: - .:/workspace:cached - work:/home/jovyan/work # Port forwarded to Workbench UI ports: - 8888:8888 # Required: must connect to app-network networks: - app-network # Required for gcsfuse cloud storage mounting cap_add: - SYS_ADMIN devices: - /dev/fuse security_opt: - apparmor:unconfined volumes: work: networks: # External network created by Workbench app-network: external: true ``` -------------------------------- ### Development Uninstall for aou_jupyterlab Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/aou-common/extension-builder/extension/aou-jupyterlab/README.md Steps to uninstall the aou_jupyterlab extension when installed in development mode. This includes uninstalling the pip package and removing the development symlink. ```bash pip uninstall aou_jupyterlab In development mode, you will also need to remove the symlink created by `jupyter labextension develop` command. To find its location, you can run `jupyter labextension list` to figure out where the `labextensions` folder is located. Then you can remove the symlink named `aou-jupyterlab` within that folder. ``` -------------------------------- ### Control App (JavaScript) Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html This function controls an application by sending a POST request to start or stop it. It takes the application ID and the desired action as input. It reloads the application list and displays a success or error message. ```javascript async function controlApp(id, action) { try { const response = await fetch(`/_app/${id}/${action}`, { method: 'POST' }); if (!response.ok) throw new Error(`Failed to ${action} app`); await loadApps(); showSuccess(`App ${action}ed successfully`); } catch (error) { showError(`Failed to ${action} app: ` + error.message); } } ``` -------------------------------- ### Configuring ShellCheck for Local Linting Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/startupscript/README.md This snippet provides the content for a local ShellCheck configuration file. It disables specific checks (SC1090, SC1091) to work around limitations with dynamic file handling in ShellCheck. ```shell disable=SC1090,SC1091 ``` -------------------------------- ### Declaring Readonly Functions in Shell Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/startupscript/README.md Illustrates the syntax for declaring shell functions and then making them readonly using the `readonly -f` command. This prevents the function from being redefined or unset. ```shell function my_function { # ... function logic ... } readonly -f my_func ``` -------------------------------- ### JavaScript: Edit Application Modal Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html Handles the editing of an existing application through a modal dialog. It fetches application data based on ID and populates the modal's form fields, including optional features. It also manages the display of example sections and error messages. ```javascript async function editApp(id) { const app = apps.find(a => a.id === id); if (!app) return; document.getElementById('modal-title').textContent = 'Edit App'; document.getElementById('app-id').value = app.id; document.getElementById('app-name').value = app.app_name; document.getElementById('username').value = app.username; document.getElementById('user-home').value = app.user_home_directory; document.getElementById('port').value = app.port; document.getElementById('caddy-config').value = app.caddy_config || DEFAULT_CADDY_TEMPLATE; onCaddyConfigChange(); // Update checkbox state document.getElementById('dockerfile').value = app.dockerfile; document.getElementById('feature-wb').checked = app.optional_features?.includes('wb') || false; document.getElementById('feature-workbench-tools').checked = app.optional_features?.includes('workbench-tools') || false; document.getElementById('examples-section').style.display = 'none'; document.getElementById('modal-error').style.display = 'none'; document.getElementById('app-modal').style.display = 'block'; } ``` -------------------------------- ### Comment Out Devcontainer Commands (JSON) Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/README.md Illustrates how to comment out the `postCreateCommand` and `postStartCommand` within a `.devcontainer.json` file. These commands are specific to the Workbench environment and should be disabled for local development to prevent potential errors. ```json { // "postCreateCommand": [ // "./startupscript/post-startup.sh", // "username", // "/home/username", // "gcp" // ], // "postStartCommand": [ // "./startupscript/remount-on-restart.sh", // "username", // "/home/username", // "gcp" // ] } ``` -------------------------------- ### Build Python Distribution Packages Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/jupyter-common/extension-builder/extension/server-proxy-notif/RELEASE.md Generates Python source distribution (.tar.gz) and binary wheel (.whl) packages in the 'dist/' directory. Note that 'python setup.py sdist bdist_wheel' is deprecated for this package. ```bash python -m build ``` -------------------------------- ### Configure .devcontainer.json for Custom Apps Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/README.md This snippet illustrates the essential configurations for a `.devcontainer.json` file when creating a custom Workbench application. It includes specifying the Docker image, exposed port, default user, and home directory, along with optional settings like post-create commands and feature inclusions. ```json { "image": "jupyter/base-notebook", "forwardPorts": [8888], "remoteUser": "jovyan", "workspaceFolder": "/home/jovyan", "postCreateCommand": "./post-startup.sh jovyan /home/jovyan ${templateOption:cloud}", "features": { "ghcr.io/verily-src/workbench-tools/workbench-tools:0": {}, "ghcr.io/devcontainers/features/common-utils:2": { "installZsh": true } } } ``` -------------------------------- ### Publish NPM Package Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/jupyter-common/extension-builder/extension/server-proxy-notif/RELEASE.md Publishes the frontend part of the extension as an NPM package. Requires prior login to the NPM registry. '--access public' makes the package publicly available. ```bash npm login npm publish --access public ``` -------------------------------- ### Run All Script Tests Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/scripts/test/README.md Command to execute all tests located in the scripts/test directory. This provides a comprehensive check of the script functionalities. ```bash cd scripts/test bats . ``` -------------------------------- ### Upload Python Package to PyPI Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/jupyter-common/extension-builder/extension/server-proxy-notif/RELEASE.md Uploads the generated Python distribution packages from the 'dist/' directory to the Python Package Index (PyPI) using the 'twine' tool. ```bash twine upload dist/* ``` -------------------------------- ### Docker Compose for ttyd Terminal Access Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/README.md This docker-compose.yaml configuration shows how to set up a container with ttyd for lightweight, web-based terminal access. It includes necessary capabilities and device mappings for ttyd to function correctly, providing a read-write terminal session. ```yaml services: app: container_name: "application-server" image: "mcr.microsoft.com/devcontainers/base:ubuntu" user: vscode command: ["ttyd", "-W", "-p", "7681", "bash"] ports: - 7681:7681 cap_add: - SYS_ADMIN devices: - /dev/fuse security_opt: - apparmor:unconfined ``` -------------------------------- ### Create Custom App Script (Bash) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Generates a devcontainer application structure with configuration files. It takes the app name, Docker image, port, username, and home directory as arguments. Supports creating apps with custom Dockerfiles. ```bash # Basic usage: create a Jupyter-based custom app ./scripts/create-custom-app.sh my-jupyter-app quay.io/jupyter/base-notebook 8888 jovyan /home/jovyan # Create an RStudio-based app ./scripts/create-custom-app.sh my-rstudio rocker/rstudio 8787 rstudio /home/rstudio # Create an app with root user (defaults to /root home) ./scripts/create-custom-app.sh my-ubuntu-app ubuntu:22.04 7681 root # Create app with custom Dockerfile (leave image empty, then add Dockerfile) ./scripts/create-custom-app.sh my-custom-app "" 8080 myuser /home/myuser # Then add Dockerfile to src/my-custom-app/ and uncomment build section in docker-compose.yaml ``` -------------------------------- ### Build JupyterLab with Source Maps Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/aou-common/extension-builder/extension/aou-jupyterlab/README.md Command to rebuild JupyterLab, including source maps for core extensions, to aid in debugging. The --minimize=False flag ensures source maps are generated. ```bash jupyter lab build --minimize=False ``` -------------------------------- ### Create/Update App (JavaScript) Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html This function handles the creation or updating of an application. It sends a POST request to the server with application data, handles the response, and displays success or error messages. It also closes the modal and reloads the application list upon success. ```javascript async function saveApp(id) { const form = document.getElementById('app-form'); const errorDiv = document.getElementById('error-message'); errorDiv.textContent = ''; errorDiv.style.display = 'none'; const data = Object.fromEntries(new FormData(form)); const closeModal = () => { const modal = document.getElementById('app-modal'); modal.style.display = 'none'; }; try { const response = await fetch(`/_app/${id || ''}`, { method: id ? 'PUT' : 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); if (!response.ok) { const error = await response.text(); throw new Error(error); } closeModal(); await loadApps(); showSuccess(id ? 'App updated successfully' : 'App created successfully'); } catch (error) { errorDiv.textContent = 'Failed to save app: ' + error.message; errorDiv.style.display = 'block'; } } ``` -------------------------------- ### Clean Development Files for Python Package Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/jupyter-common/extension-builder/extension/server-proxy-notif/RELEASE.md Removes development-related files and directories before building the Python package to ensure a clean distribution. This step is crucial for accurate packaging. ```bash jlpm clean:all ``` -------------------------------- ### JavaScript: Load and Render Applications Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html Handles loading application data from the server and rendering it into an HTML table. It manages the display of application status, container status, and provides action buttons for each app. Includes logic for handling empty states and loading indicators. ```javascript let apps = []; let pollInterval = null; let currentLogsContext = null; // { type: 'app', id: 123, name: 'app-name' } or { type: 'playground' } let logsRefreshInterval = null; // Caddy template constants const DEFAULT_CADDY_TEMPLATE = `@{{.AppName}} path /{{.AppName}} /{{.AppName}}/* route @{{.AppName}} { reverse_proxy {{.ContainerName}}:{{.Port}} }`; const STRIP_PREFIX_CADDY_TEMPLATE = `@{{.AppName}} path /{{.AppName}} /{{.AppName}}/* route @{{.AppName}} { uri strip_prefix /{{.AppName}} reverse_proxy {{.ContainerName}}:{{.Port}} }`; // Load apps on page load document.addEventListener('DOMContentLoaded', () => { loadApps(); startPolling(); }); async function loadApps() { try { const response = await fetch('/_app'); if (!response.ok) throw new Error('Failed to load apps'); const data = await response.json(); // Handle both array response and object response with apps field apps = Array.isArray(data) ? data : (data.apps || []); renderApps(); } catch (error) { showError('Failed to load apps: ' + error.message); } } function renderApps() { const loading = document.getElementById('loading'); const emptyState = document.getElementById('empty-state'); const table = document.getElementById('apps-table'); const tbody = document.getElementById('apps-tbody'); loading.style.display = 'none'; if (apps.length === 0) { emptyState.style.display = 'block'; table.style.display = 'none'; return; } emptyState.style.display = 'none'; table.style.display = 'table'; body.innerHTML = apps.map(app => { const appUrl = `/${app.app_name}/`; const containerStatus = app.container_status || 'unknown'; const containerStatusLabel = containerStatus.replace('_', ' '); // Determine button states based on container status const isRunning = containerStatus === 'running'; const canStart = !isRunning && containerStatus !== 'unknown'; const canStop = isRunning; const canOpen = isRunning; return ` ${app.id} ${app.app_name} ${app.username} ${app.port} ${app.optional_features?.join(', ') || 'None'} ${app.status.toUpperCase()} ${containerStatusLabel.toUpperCase()} Open `; }).join(''); } ``` -------------------------------- ### Run Specific Script Test File Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/scripts/test/README.md Command to run a single test file, identified by its path. This is useful for isolating and testing specific script functionalities. ```bash bats scripts/test/create-custom-app.bats ``` -------------------------------- ### Run Specific Test Case within a File Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/scripts/test/README.md Command to execute a particular test case within a specified test file using a filter. This allows for granular testing of individual scenarios. ```bash bats scripts/test/create-custom-app.bats --filter "shows usage" ``` -------------------------------- ### View Logs (JavaScript) Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html This function fetches and displays logs for a given context (app or playground). It fetches logs from a specified URL, updates the logs modal, and handles potential errors. It also manages scrolling to the bottom and refreshing logs. ```javascript async function viewLogs(context, isRefresh = false) { currentLogsContext = context; const logsModal = document.getElementById('logs-modal'); const logsTitle = document.getElementById('logs-title'); const logsContent = document.getElementById('logs-content'); logsTitle.textContent = context.title; if (!isRefresh) { logsContent.textContent = 'Loading logs...'; } logsModal.style.display = 'block'; const wasScrolledToBottom = logsContent.scrollTop + logsContent.clientHeight >= logsContent.scrollHeight - 10; try { const response = await fetch(context.url); if (!response.ok) throw new Error('Failed to fetch logs'); const data = await response.json(); logsContent.textContent = data.logs || 'No logs available'; if (!isRefresh || wasScrolledToBottom) { logsContent.scrollTop = logsContent.scrollHeight; } } catch (error) { logsContent.textContent = `Error loading logs: ${error.message}`; } } ``` -------------------------------- ### Bump Python Package Version with Hatch Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/jupyter-common/extension-builder/extension/server-proxy-notif/RELEASE.md Updates the version of the Python package using the 'hatch' tool. This command typically creates a Git tag for the new version. Refer to hatch-nodejs-version documentation for detailed semver information. ```bash hatch version ``` -------------------------------- ### Configure Workbench File Extensions and URL Routing (JSON) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt This JSON configuration defines custom file extensions that Workbench should recognize and handle. It also specifies URL suffixes for routing file and folder paths, enabling deep linking into applications. This is useful for data scientists and DevOps teams building specialized development environments. ```json { "customizations": { "workbench": { "opens": { "extensions": [ ".ipynb", ".R", ".py", ".md", ".html", ".pdf", ".csv", ".json", ".tsv" ], "fileUrlSuffix": "/lab/tree/{path}", "folderUrlSuffix": "/lab/tree/{path}" } } } } ``` -------------------------------- ### Watch for Changes during Development Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/aou-common/extension-builder/extension/aou-jupyterlab/README.md Commands to simultaneously watch for source file changes and run JupyterLab during development. This allows for automatic rebuilding and live updates in the browser. ```bash # Watch the source directory in one terminal, automatically rebuilding when needed jlpm watch # Run JupyterLab in another terminal jupyter lab ``` -------------------------------- ### JavaScript: Handle Strip Prefix Checkbox Change Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html Updates the Caddy configuration textarea when the 'strip prefix' checkbox is toggled. It switches between the default and strip prefix templates if the current configuration matches one of the defaults. It also ensures the UI state is consistent. ```javascript function onStripPrefixChange() { const textarea = document.getElementById('caddy-config'); const currentTemplate = textarea.value.trim(); const stripPrefix = document.getElementById('strip-prefix').checked; // Only update if template matches one of the defaults if (currentTemplate === DEFAULT_CADDY_TEMPLATE.trim()) { if (stripPrefix) { textarea.value = STRIP_PREFIX_CADDY_TEMPLATE; } } else if (currentTemplate === STRIP_PREFIX_CADDY_TEMPLATE.trim()) { if (!stripPrefix) { textarea.value = DEFAULT_CADDY_TEMPLATE; } } // If custom template, do nothing (shouldn't reach here as checkbox is disabled) // Update checkbox state in case template was changed onCaddyConfigChange(); } ``` -------------------------------- ### Configure JupyterLab Command in Docker Compose (YAML) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Defines the command to run JupyterLab within a Docker container, specifying IP address, port, disabling browser launch, and disabling token authentication for easier access. This is typically part of a docker-compose.yaml file. ```yaml services: app: container_name: "application-server" image: "ubuntu:22.04" command: ["jupyter", "lab", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--LabApp.token=''"] ports: - 8888:8888 ``` -------------------------------- ### View App/Playground Logs (JavaScript) Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html These functions are used to view logs for a specific application or the playground. They call the `viewLogs` function with the appropriate context, including the application ID, name, and log URL. ```javascript async function viewAppLogs(id, appName) { await viewLogs({ type: 'app', id: id, name: appName, title: `Logs - ${appName}`, url: `/_app/${id}/logs?tail=500` }); } async function viewPlaygroundLogs() { await viewLogs({ type: 'playground', title: 'Playground Logs', url: '/_app/logs?tail=500' }); } ``` -------------------------------- ### Clean Local Git Repository Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/jupyter-common/extension-builder/extension/server-proxy-notif/RELEASE.md Cleans the local Git repository by removing untracked files and directories. This ensures that only intended files are included in the release. ```bash git clean -dfX ``` -------------------------------- ### JavaScript: Handle Caddy Config Change Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html Manages the UI state when the Caddy configuration textarea content changes. It disables the 'strip prefix' checkbox if the current configuration is a custom template and updates the checkbox's checked state to match the template if it's a default one. ```javascript function onCaddyConfigChange() { const textarea = document.getElementById('caddy-config'); const checkbox = document.getElementById('strip-prefix'); const currentTemplate = textarea.value.trim(); // Disable checkbox if using custom template if (isCustomTemplate(currentTemplate)) { checkbox.disabled = true; checkbox.checked = false; } else { checkbox.disabled = false; // Update checkbox state based on template checkbox.checked = currentTemplate === STRIP_PREFIX_CADDY_TEMPLATE.trim(); } } ``` -------------------------------- ### Configure ttyd for Browser-Based Terminal Access (YAML) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Sets up ttyd within a docker-compose.yaml file to enable browser-based terminal access. It specifies the command to run ttyd, the port mapping, and necessary capabilities for running as a privileged service. ```yaml # docker-compose.yaml services: app: container_name: "application-server" image: "mcr.microsoft.com/devcontainers/base:ubuntu" user: vscode # -W flag enables writable/interactive terminal command: ["ttyd", "-W", "-p", "7681", "bash"] ports: - 7681:7681 networks: - app-network cap_add: - SYS_ADMIN devices: - /dev/fuse security_opt: - apparmor:unconfined ``` -------------------------------- ### Devcontainer Template Metadata Configuration (JSON) Source: https://context7.com/verily-src/workbench-app-devcontainers/llms.txt Defines the metadata and configurable options for a devcontainer template used in Workbench UI. This includes template ID, version, name, description, and user-selectable options like cloud provider and login status. ```json { "id": "my-app", "version": "1.0.0", "name": "My Custom App", "description": "Custom Workbench app with Jupyter and bioinformatics tools", "options": { "cloud": { "type": "string", "enum": ["gcp", "aws"], "default": "gcp", "description": "Cloud provider (gcp or aws)" }, "login": { "type": "string", "proposals": ["true", "false"], "default": "false", "description": "Whether to log in to workbench CLI" } } } ``` -------------------------------- ### Update Copier Template Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/aou-common/extension-builder/extension/aou-jupyterlab/README.md Command to update the JupyterLab extension template using Copier. This ensures the project uses the latest template configurations. ```bash copier update --trust ``` -------------------------------- ### JavaScript: Check for Custom Caddy Template Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html Determines if the current Caddy configuration in the textarea is a custom template, meaning it does not match the default or strip prefix templates. This is used to manage the state of a 'strip prefix' checkbox. ```javascript function isCustomTemplate(template) { const trimmed = template.trim(); return trimmed !== DEFAULT_CADDY_TEMPLATE.trim() && trimmed !== STRIP_PREFIX_CADDY_TEMPLATE.trim(); } ``` -------------------------------- ### Delete App (JavaScript) Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html This function deletes an application. It prompts the user for confirmation before sending a DELETE request to the server. It then reloads the application list and displays a success or error message. ```javascript async function deleteApp(id, name) { if (!confirm(`Are you sure you want to delete "${name}"?`)) return; try { const response = await fetch(`/_app/${id}`, { method: 'DELETE' }); if (!response.ok) throw new Error('Failed to delete app'); await loadApps(); showSuccess('App deleted successfully'); } catch (error) { showError('Failed to delete app: ' + error.message); } } ``` -------------------------------- ### Show Error/Success Message (JavaScript) Source: https://github.com/verily-src/workbench-app-devcontainers/blob/master/src/playground/playground/static/index.html These functions display error or success messages on the page. They take a message as input, set the text content of the corresponding div, and make the div visible. The error message is displayed for 5 seconds. ```javascript function showError(message) { const errorDiv = document.getElementById('error-message'); errorDiv.textContent = message; errorDiv.style.display = 'block'; setTimeout(() => { errorDiv.style.display = 'none'; }, 5000); } function showSuccess(message) { console.log(message); } ```