diff --git a/.github/workflows/build-bake.yaml b/.github/workflows/build-bake.yaml index e2d9f539..bb8301ca 100644 --- a/.github/workflows/build-bake.yaml +++ b/.github/workflows/build-bake.yaml @@ -323,6 +323,48 @@ jobs: snyk-org: ${{ secrets.SNYK_ORG }} snyk-token: '${{ secrets.SNYK_TOKEN }}' + workbench-session: + needs: [setup] + name: Workbench Session + runs-on: ubuntu-latest-8x + + concurrency: + group: bake-workbench-session-${{ github.ref }} + cancel-in-progress: true + + env: + target: workbench-session + GIT_SHA: ${{ needs.setup.outputs.GIT_SHA }} + + steps: + - name: Checkout + if: github.event_name == 'schedule' + uses: actions/checkout@v4 + with: + ref: 'main' + + - name: Checkout + if: github.event_name != 'schedule' + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + id: setup-buildx + with: + buildkitd-config: ./share/buildkitd.toml + + - name: Build, Test, and Push + uses: ./.github/actions/bake-test-push + with: + target: ${{ env.target }} + push-image: ${{ github.ref == 'refs/heads/main' || github.event_name == 'schedule' }} + ghcr-token: ${{ secrets.GITHUB_TOKEN }} + dockerhub-username: ${{ secrets.DOCKER_HUB_USERNAME }} + dockerhub-token: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + gcp-json: '${{ secrets.GCP_ARTIFACT_REGISTRY_JSON }}' + snyk-org: ${{ secrets.SNYK_ORG }} + snyk-token: '${{ secrets.SNYK_TOKEN }}' + workbench-session-init: needs: [setup, versions] name: Workbench Session Init diff --git a/docker-bake.hcl b/docker-bake.hcl index 3306e3a9..e03890c4 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -185,6 +185,10 @@ variable WORKBENCH_BUILD_MATRIX { } } +variable WORKBENCH_SESSION_MATRIX { + default = PRO_BUILD_MATRIX +} + variable WORKBENCH_SESSION_INIT_BUILD_MATRIX { default = { builds = [ @@ -221,6 +225,7 @@ group "default" { "package-manager", "r-session-complete", "workbench", + "workbench-session", "workbench-session-init", ] } @@ -441,6 +446,31 @@ target "r-session-complete" { } } +target "workbench-session" { + inherits = ["base"] + name = "workbench-session-${builds.os}-r${replace(builds.r_primary, ".", "-")}_${replace(builds.r_alternate, ".", "-")}-py${replace(builds.py_primary, ".", "-")}_${replace(builds.py_alternate, ".", "-")}" + + tags = [ + "ghcr.io/rstudio/workbench-session:${builds.os}-r${builds.r_primary}_${builds.r_alternate}-py${builds.py_primary}_${builds.py_alternate}", + "docker.io/rstudio/workbench-session:${builds.os}-r${builds.r_primary}_${builds.r_alternate}-py${builds.py_primary}_${builds.py_alternate}", + ] + + dockerfile = "Dockerfile.${builds.os}" + context = "workbench-session" + contexts = { + product-base-pro = "target:product-base-pro-${builds.os}-r${replace(builds.r_primary, ".", "-")}_${replace(builds.r_alternate, ".", "-")}-py${replace(builds.py_primary, ".", "-")}_${replace(builds.py_alternate, ".", "-")}" + } + + matrix = BASE_BUILD_MATRIX + args = { + R_VERSION = builds.r_primary + R_VERSION_ALT = builds.r_alternate + PYTHON_VERSION = builds.py_primary + PYTHON_VERSION_ALT = builds.py_alternate + JUPYTERLAB_VERSION = DEFAULT_JUPYTERLAB_VERSION + } +} + target "workbench" { inherits = ["base"] diff --git a/workbench-session-init/README.md b/workbench-session-init/README.md index 662b595f..76c82b74 100644 --- a/workbench-session-init/README.md +++ b/workbench-session-init/README.md @@ -7,8 +7,8 @@ This directory contains a Dockerfile and script that will create an init contain * Maintained by: [the Posit Docker team](https://github.com/rstudio/rstudio-docker-products) * Where to get help: [our Github Issues page](https://github.com/rstudio/rstudio-docker-products/issues) * Posit Workbench image: [Docker Hub](https://hub.docker.com/r/rstudio/rstudio-workbench) -* RStudio r-session-complete image: [Docker Hub](https://hub.docker.com/r/rstudio/r-session-complete) -* Workbench Session Init image: [Docker Hub](https://hub.docker.com/r/rstudio/workbench-session-init) +* Posit Workbench session image: [Docker Hub](https://hub.docker.com/r/rstudio/workbench-session) +* Posit Workbench session init image: [Docker Hub](https://hub.docker.com/r/rstudio/workbench-session-init) ## Supported tags and respective Dockerfile links diff --git a/workbench-session/.env b/workbench-session/.env new file mode 100644 index 00000000..1c5333d8 --- /dev/null +++ b/workbench-session/.env @@ -0,0 +1,3 @@ +R_VERSION=4.1.0 +PYTHON_VERSION=3.9.5 +DRIVERS_VERSION=2024.03.0-1 diff --git a/workbench-session/.snyk b/workbench-session/.snyk new file mode 100644 index 00000000..909ad99a --- /dev/null +++ b/workbench-session/.snyk @@ -0,0 +1,20 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.25.0 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-GOLANG-GITHUBCOMCREWJAMSAML-5971016: + - '*': + reason: >- + Reported upstream in + https://github.com/rstudio/rstudio-pro/issues/6529 + expires: 2024-08-31T00:00:00.000Z + created: 2024-07-02T20:33:30.847Z + SNYK-GOLANG-GITHUBCOMGOJOSEGOJOSEV3-6070737: + - '*': + reason: >- + Confirmed fixed upstream in + https://github.com/rstudio/rstudio-pro/issues/6635. Patch will be + ingested in Workbench 2024.08.0 (expected within 1 week). + expires: 2024-08-07T00:00:00.000Z + created: 2024-07-31T17:46:24.852Z +patch: {} diff --git a/workbench-session/Dockerfile.ubuntu2204 b/workbench-session/Dockerfile.ubuntu2204 new file mode 100644 index 00000000..060933b3 --- /dev/null +++ b/workbench-session/Dockerfile.ubuntu2204 @@ -0,0 +1,50 @@ +FROM product-base-pro as build + +ARG DEBIAN_FRONTEND=noninteractive +ARG R_VERSION=4.4.0 +ARG R_VERSION_ALT=4.3.3 +ARG PYTHON_VERSION=3.9.17 +ARG PYTHON_VERSION_ALT=3.8.17 +ARG JUPYTERLAB_VERSION=3.6.5 +ARG SCRIPTS_DIR=/opt/positscripts +ARG QUARTO_VERSION=1.3.340 + +ENV WORKBENCH_JUPYTER_PATH=/usr/local/bin/jupyter + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN apt-get update \ + && apt-get install --no-install-recommends -y \ + krb5-user \ + libcurl4-gnutls-dev \ + libuser \ + libuser1-dev \ + libpq-dev \ + rrdtool \ + subversion \ + && apt-get autoremove -y \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Add Jupyter, Python, and Quarto to the PATH +ENV PATH="/opt/python/jupyter/bin:/opt/python/bin:/usr/lib/rstudio-server/bin/quarto/bin:${PATH}" + +### Install TinyTeX using Quarto ### +RUN $SCRIPTS_DIR/install_quarto.sh --install-tinytex --add-path-tinytex + +RUN /opt/python/"${PYTHON_VERSION}"/bin/python -m venv /opt/python/jupyter \ + && /opt/python/jupyter/bin/python -m pip install --upgrade pip \ + && /opt/python/jupyter/bin/python -m pip install --upgrade setuptools \ + && /opt/python/jupyter/bin/python -m pip install \ + jupyterlab~=4.2.4 \ + notebook \ + pwb_jupyterlab~=1.0 \ + && ln -s /opt/python/jupyter/bin/jupyter /usr/local/bin/jupyter \ + && /opt/python/${PYTHON_VERSION}/bin/python -m pip install ipykernel \ + && /opt/python/${PYTHON_VERSION_ALT}/bin/python -m pip install ipykernel \ + && /opt/python/${PYTHON_VERSION}/bin/python -m ipykernel install --name py${PYTHON_VERSION} --display-name "Python ${PYTHON_VERSION}" \ + && /opt/python/${PYTHON_VERSION_ALT}/bin/python -m ipykernel install --name py${PYTHON_VERSION_ALT} --display-name "Python ${PYTHON_VERSION_ALT}" \ + && /opt/python/jupyter/bin/python -m pip cache purge + +COPY vscode.extensions.conf /etc/rstudio/vscode.extensions.conf + +EXPOSE 8788/tcp diff --git a/workbench-session/NEWS.md b/workbench-session/NEWS.md new file mode 100644 index 00000000..e76e114b --- /dev/null +++ b/workbench-session/NEWS.md @@ -0,0 +1,4 @@ +# 2024-11-15 + +- Add NEWS.md +- Add daily builds diff --git a/workbench-session/README.md b/workbench-session/README.md new file mode 100644 index 00000000..c921d26c --- /dev/null +++ b/workbench-session/README.md @@ -0,0 +1,76 @@ +# Quick reference + +* Maintained by: [the Posit Docker team](https://github.com/rstudio/rstudio-docker-products) +* Where to get help: [our Github Issues page](https://github.com/rstudio/rstudio-docker-products/issues) +* Posit Workbench image: [Docker Hub](https://hub.docker.com/r/rstudio/rstudio-workbench) +* Posit Workbench session image: [Docker Hub](https://hub.docker.com/r/rstudio/workbench-session) +* Posit Workbench session init image: [Docker Hub](https://hub.docker.com/r/rstudio/workbench-session-init) + +# Supported tags and respective Dockerfile links + +* [`jammy`, `ubuntu2204`, `jammy-2024.09.1`, `ubuntu2204-2024.09.1`](https://github.com/rstudio/rstudio-docker-products/blob/main/r-session-complete/Dockerfile.ubuntu2204) + +# What are the r-session-complete images? + +Images for R and Python sessions and jobs to be used RStudio Workbench, Launcher, and Kubernetes. + +# Notice for support + +1. This image may introduce **BREAKING** changes; as such we recommend: + - Avoid using the `{operating-system}` tags to avoid unexpected version changes, and + - Always read through the [NEWS](./NEWS.md) to understand the changes before updating. +1. Outdated images will be removed periodically from DockerHub as product version updates are made. Please make plans to + update at times or use your own build of the images. +1. These images are meant as a starting point for your needs. Consider creating a fork of this repo, where you can + continue to merge in changes we make while having your own security scanning, base OS in use, or other custom + changes. We + provide [instructions for how to build and use](#how-to-use-these-docker-images) + for these cases. +1. **Security Note:** These images are provided AS IS based on the build environment at the time their product version was released/updated. They should be reviewed and updated before production use. If your organization has a specific set of security requirements related to CVE/Vulnerability severity levels, you should plan to use the [instructions for building](https://github.com/rstudio/rstudio-docker-products#instructions-for-building) to clone this repository, and rebuild these images to your specific internal security standards. + +# How to use these images + +The Docker images built from these Dockerfiles are intended to be used for R and +Jupyter sessions and jobs with RStudio Workbench (RSW), Launcher, and +Kubernetes. + +Note: These Docker images are not equipped or intended to be used to run Posit +Workbench within a Docker container. Visit the +[rstudio/rstudio-worbench Docker Hub page](https://hub.docker.com/r/rstudio/rstudio-workbench) +for images built for that purpose. + +For more information about Posit Workbench and Launcher, refer to the +[Launcher Overview](https://solutions.rstudio.com/launcher/overview/) on the +RStudio Solutions website. + +For more information about how to use these images with RStudio Workbench and +Launcher, refer to the RStudio support article on [Using Docker images with +RStudio Workbench, Launcher, and Kubernetes](https://support.rstudio.com/hc/en-us/articles/360019253393-Using-Docker-images-with-RStudio-Server-Pro-Launcher-and-Kubernetes). + +We provide simple ways to extend and build the Dockerfiles. After you have cloned the repo, you can create your own containers fairly simply with the provided Justfile. + +## Overview + +Built images are available from the +[rstudio/workbench-session](https://hub.docker.com/r/rstudio/workbench-session) +repository on Docker Hub. + +These images include the following layers: + +* Base OS +* System packages required for R, R packages, RStudio Professional Drivers, and Workbench Session Components +* One version of R +* One version of Python +* Jupyter Notebooks, JupyterLab, and RSW/RSC notebook extensions +* RStudio Professional Drivers + +# Licensing + +The license associated with the RStudio Docker Products repository is located [in LICENSE.md](https://github.com/rstudio/rstudio-docker-products/blob/main/LICENSE.md). + +As is the case with all container images, the images themselves also contain other software which may be under other +licenses (i.e. bash, linux, system libraries, etc., along with any other direct or indirect dependencies of the primary +software being contained). + +It is an image user's responsibility to ensure that use of this image (and any of its dependent layers) complies with +all relevant licenses for the software contained in the image. diff --git a/workbench-session/docker-compose.test.yml b/workbench-session/docker-compose.test.yml new file mode 100644 index 00000000..ab22c81a --- /dev/null +++ b/workbench-session/docker-compose.test.yml @@ -0,0 +1,15 @@ +version: '2.3' +services: + + sut: + image: $IMAGE_NAME + command: /run_tests.sh + entrypoint: [] + environment: + # uses .env by default + - R_VERSION + - PYTHON_VERSION + volumes: + - "./test/run_tests.sh:/run_tests.sh" + - "./test/goss.yaml:/tmp/goss.yaml" + - "./test/goss_vars.yaml:/tmp/goss_vars.yaml" diff --git a/workbench-session/positron.extensions.conf b/workbench-session/positron.extensions.conf new file mode 100644 index 00000000..42191cc9 --- /dev/null +++ b/workbench-session/positron.extensions.conf @@ -0,0 +1,2 @@ +posit.shiny +posit.publisher diff --git a/workbench-session/test/goss.yaml b/workbench-session/test/goss.yaml new file mode 100644 index 00000000..030ff180 --- /dev/null +++ b/workbench-session/test/goss.yaml @@ -0,0 +1,69 @@ +file: + /usr/lib/rstudio-server: + exists: true + /usr/lib/rstudio-server/bin/rsession: + exists: true + /usr/local/bin/jupyter: + exists: true + {{ $version_split := split "." .Env.RSW_VERSION }} + {{ if or (ge ($version_split._0 | atoi) 2025) (and (ge ($version_split._0 | atoi) 2024) (ge ($version_split._1 | atoi) 7)) }} + /usr/lib/rstudio-server/bin/pwb-code-server/bin/code-server: + exists: true + {{ else }} + /usr/lib/rstudio-server/bin/code-server/bin/code-server: + exists: true + {{ end }} + /opt/rstudio-drivers: + exists: true + filetype: directory + /var/lib/rstudio-server/r-versions: + exists: false + /usr/local/bin/quarto: + exists: true + filetype: symlink + +command: + "echo '{ \"cells\": [], \"metadata\": {}, \"nbformat\": 4, \"nbformat_minor\": 2}' | /opt/python/jupyter/bin/jupyter nbconvert --to notebook --stdin --stdout": + title: jupyter_works + timeout: 60000 + exit-status: 0 + +# Ensure correct R version + "/opt/R/{{.Env.R_VERSION}}/bin/R --version": + title: r_version_match + exit-status: 0 + stdout: [ + "{{.Env.R_VERSION}}" + ] + +# Ensure correct python version + "/opt/python/{{.Env.PYTHON_VERSION}}/bin/python3 --version": + title: python_version_matches + exit-status: 0 + stdout: [ + "{{ .Env.PYTHON_VERSION }}" + ] + + "python3 --version": + title: python_in_path_var + exit-status: 0 + stdout: [ + "{{ .Env.PYTHON_VERSION }}" + ] + + "jupyter --version": + title: jupyter_in_path_var + timeout: 60000 + exit-status: 0 + +# Ensure Quarto works + "/usr/local/bin/quarto check --quiet": + title: quarto_check + exit-status: 0 + +# Ensure TinyTeX is installed + "quarto list tools": + title: quarto_tinytex_installed + exit-status: 0 + stderr: + - "/tinytex\\s+Up to date\\s+v\\d{4}\\.\\d{2}(\\.\\d{2})?\\s+v\\d{4}\\.\\d{2}(\\.\\d{2})?/" diff --git a/workbench-session/test/run_tests.sh b/workbench-session/test/run_tests.sh new file mode 100755 index 00000000..8aff0f84 --- /dev/null +++ b/workbench-session/test/run_tests.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +GOSS_FILE=${GOSS_FILE:-/test/goss.yaml} +GOSS_VERSION=${GOSS_VERSION:-0.4.6} +GOSS_MAX_CONCURRENT=${GOSS_MAX_CONCURRENT:-50} + +if [ -f /etc/debian_version ]; then + OS="ubuntu" +else + echo "OS not supported. Exiting" + exit 1 +fi + +# install goss to tmp location and make executable +curl -fsSL https://github.com/aelsabbahy/goss/releases/download/v$GOSS_VERSION/goss-linux-amd64 -o /tmp/goss \ + && chmod +x /tmp/goss \ + && GOSS=/tmp/goss + +OS=$OS GOSS_FILE=$GOSS_FILE $GOSS v --format documentation --max-concurrent $GOSS_MAX_CONCURRENT diff --git a/workbench-session/vscode.extensions.conf b/workbench-session/vscode.extensions.conf new file mode 100644 index 00000000..80e04b95 --- /dev/null +++ b/workbench-session/vscode.extensions.conf @@ -0,0 +1,5 @@ +quarto.quarto +REditorSupport.r@2.8.2 +ms-python.python +posit.shiny +ms-toolsai.jupyter