diff --git a/.github/workflows/build-bake-preview.yaml b/.github/workflows/build-bake-preview.yaml index 641787f5b..5912e781e 100644 --- a/.github/workflows/build-bake-preview.yaml +++ b/.github/workflows/build-bake-preview.yaml @@ -421,3 +421,43 @@ jobs: dockerhub-token: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} snyk-org: ${{ secrets.SNYK_ORG }} snyk-token: '${{ secrets.SNYK_TOKEN }}' + + workbench-session-init-daily: + needs: [versions] + name: Workbench Session Init - Daily + runs-on: ubuntu-latest-4x + + env: + target: "workbench-session-init-daily" + WORKBENCH_DAILY_VERSION: ${{ needs.versions.outputs.WORKBENCH_DAILY_VERSION }} + WORKBENCH_PREVIEW_VERSION: ${{ needs.versions.outputs.WORKBENCH_PREVIEW_VERSION }} + PACKAGE_MANAGER_DAILY_VERSION: ${{ needs.versions.outputs.PACKAGE_MANAGER_DAILY_VERSION }} + PACKAGE_MANAGER_PREVIEW_VERSION: ${{ needs.versions.outputs.PACKAGE_MANAGER_PREVIEW_VERSION }} + CONNECT_DAILY_VERSION: ${{ needs.versions.outputs.CONNECT_DAILY_VERSION }} + BRANCH: ${{ github.head_ref || github.ref_name }} + + concurrency: + group: bake-workbench-session-init-daily-${{ github.ref }} + cancel-in-progress: true + + steps: + - name: Checkout + 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 }} + bakefile: docker-bake.preview.hcl + push-image: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/dev-rspm' }} + ghcr-token: ${{ secrets.GITHUB_TOKEN }} + dockerhub-username: ${{ secrets.DOCKER_HUB_USERNAME }} + dockerhub-token: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + snyk-org: ${{ secrets.SNYK_ORG }} + snyk-token: '${{ secrets.SNYK_TOKEN }}' diff --git a/.github/workflows/build-manual.yaml b/.github/workflows/build-manual.yaml index 2f9917747..5900804b9 100644 --- a/.github/workflows/build-manual.yaml +++ b/.github/workflows/build-manual.yaml @@ -21,6 +21,7 @@ on: - workbench - workbench-for-google-cloud-workstations - workbench-for-microsoft-azure-ml + - workbench-session-init type: description: "The type of image being built." required: false diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 8503bb735..55c018330 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -25,6 +25,7 @@ jobs: - {product: 'connect-content-init', os: 'ubuntu2204'} - {product: 'package-manager', os: 'ubuntu2204'} - {product: 'r-session-complete', os: 'ubuntu2204'} + - {product: 'workbench-session-init', os: 'ubuntu2204'} - {product: 'workbench-for-microsoft-azure-ml', os: 'ubuntu2204'} - {product: 'content/base', os: 'ubuntu1804'} - {product: 'content/base', os: 'ubuntu2204'} diff --git a/.github/workflows/update-readme.yaml b/.github/workflows/update-readme.yaml index 0e264b21b..65715320d 100644 --- a/.github/workflows/update-readme.yaml +++ b/.github/workflows/update-readme.yaml @@ -25,6 +25,7 @@ jobs: - {prefix: 'rstudio-', repository: 'package-manager', readme_path: './package-manager/README.md'} - {prefix: '', repository: 'r-session-complete', readme_path: './r-session-complete/README.md'} - {prefix: 'rstudio-', repository: 'workbench-for-microsoft-azure-ml', readme_path: './workbench-for-microsoft-azure-ml/README.md'} + - {prefix: '', repository: 'workbench-session-init', readme_path: './workbench-session-init/README.md'} steps: - name: Check Out Repo diff --git a/Justfile b/Justfile index ac062e795..1cda2d0ca 100644 --- a/Justfile +++ b/Justfile @@ -295,16 +295,17 @@ update-rsw-versions: r-session-complete/.env \ workbench-for-microsoft-azure-ml/.env \ r-session-complete/Dockerfile.ubuntu2204 \ - r-session-complete/Dockerfile.centos7 \ workbench/Dockerfile.ubuntu2204 \ - workbench-for-microsoft-azure-ml/Dockerfile.ubuntu2204 + workbench-for-microsoft-azure-ml/Dockerfile.ubuntu2204 \ + workbench-session-init/Dockerfile.ubuntu2204 sed {{ sed_vars }} "s/RSW_VERSION:.*/RSW_VERSION: {{ RSW_VERSION }}/g" docker-compose.yml sed {{ sed_vars }} "s/rstudio\/rstudio-workbench:.*/rstudio\/rstudio-workbench:$(just _get-clean-version {{ RSW_VERSION }})/g" docker-compose.yml sed {{ sed_vars }} "s/^RSW_VERSION := .*/RSW_VERSION := \"{{ RSW_VERSION }}\"/g" \ Justfile sed {{ sed_vars }} "s/[0-9]\{4\}\.[0-9]\{1,2\}\.[0-9]\{1,2\}/`just _get-clean-version {{ RSW_VERSION }}`/g" \ workbench/README.md \ - r-session-complete/README.md + r-session-complete/README.md \ + workbench-session-init/README.md awk -v new_version="{{ RSW_VERSION }}" ' /variable WORKBENCH_VERSION/ { print; getline; print " default = \"" new_version "\""; next } { print } diff --git a/ci.Justfile b/ci.Justfile index 1de52f56d..bfdf18b1c 100644 --- a/ci.Justfile +++ b/ci.Justfile @@ -69,7 +69,7 @@ get-product-args $PRODUCT $OS $VERSION $USE_S3="false" $BRANCH=`git branch --sho RSW_DOWNLOAD_URL=$(just -f ci.Justfile _get-rsw-download-url preview $OS) fi - if [[ $PRODUCT == "workbench" || $PRODUCT == "r-session-complete" || $PRODUCT == "workbench-for-microsoft-azure-ml" ]]; then + if [[ $PRODUCT == "workbench" || $PRODUCT == "workbench-session-init" || $PRODUCT == "r-session-complete" || $PRODUCT == "workbench-for-microsoft-azure-ml" ]]; then SHORT_NAME="RSW" elif [[ $PRODUCT == "connect" || $PRODUCT == "connect-content-init" ]]; then SHORT_NAME="RSC" @@ -158,7 +158,7 @@ get-prerelease-args $TYPE $PRODUCT $OS $VERSION $BRANCH=`git branch --show`: RSW_DOWNLOAD_URL=$(just -f ci.Justfile _get-rsw-download-url $TYPE $OS) - if [[ $PRODUCT == "workbench" || $PRODUCT == "r-session-complete" || $PRODUCT == "workbench-for-microsoft-azure-ml" ]]; then + if [[ $PRODUCT == "workbench" || $PRODUCT == "workbench-session-init" || $PRODUCT == "r-session-complete" || $PRODUCT == "workbench-for-microsoft-azure-ml" ]]; then SHORT_NAME="RSW" elif [[ $PRODUCT == "connect" || $PRODUCT == "connect-content-init" ]]; then SHORT_NAME="RSC" diff --git a/docker-bake.preview.hcl b/docker-bake.preview.hcl index 400b13f73..b81c79862 100644 --- a/docker-bake.preview.hcl +++ b/docker-bake.preview.hcl @@ -163,6 +163,14 @@ variable WORKBENCH_BUILD_MATRIX { } } +variable WORKBENCH_SESSION_INIT_BUILD_MATRIX { + default = { + builds = [ + {os = "ubuntu2204"}, + ] + } +} + ### Group definitions ### group "default" { targets = [ @@ -175,6 +183,7 @@ group "default" { "r-session-complete-daily", "workbench-preview", "workbench-daily", + "workbench-session-init-daily", ] } @@ -450,3 +459,20 @@ target "workbench-preview" { RSW_DOWNLOAD_URL = get_rsw_download_url(builds.os) } } + +target "workbench-session-init-daily" { + inherits = ["base"] + target = "build" + + name = "workbench-session-init-daily-${builds.os}-${replace(tag_safe_version(WORKBENCH_DAILY_VERSION), ".", "-")}" + tags = get_tags(builds.os, "workbench-session-init-preview", WORKBENCH_DAILY_VERSION, "daily") + + dockerfile = "Dockerfile.${builds.os}" + context = "workbench-session-init" + + matrix = WORKBENCH_SESSION_INIT_BUILD_MATRIX + + args = { + RSW_VERSION = WORKBENCH_DAILY_VERSION + } +} diff --git a/tools/dockerhub_clean.py b/tools/dockerhub_clean.py index 0bace396b..5cb1c592f 100755 --- a/tools/dockerhub_clean.py +++ b/tools/dockerhub_clean.py @@ -23,6 +23,7 @@ "rstudio-workbench", "rstudio-workbench-for-microsoft-azure-ml", "rstudio-workbench-preview", + "workbench-session-init-preview", ] diff --git a/tools/get-version.py b/tools/get-version.py index 411d18eac..bba275d10 100755 --- a/tools/get-version.py +++ b/tools/get-version.py @@ -97,7 +97,7 @@ def clean_product_selection(product: str) -> str: def rstudio_workbench_daily(): - version_json = download_json("https://dailies.rstudio.com/rstudio/cranberry-hibiscus/index.json") + version_json = download_json("https://dailies.rstudio.com/rstudio/kousa-dogwood/index.json") return version_json['workbench']['platforms']['jammy-amd64']['version'] diff --git a/workbench-session-init/Dockerfile.ubuntu2204 b/workbench-session-init/Dockerfile.ubuntu2204 new file mode 100644 index 000000000..0ccfb3cc7 --- /dev/null +++ b/workbench-session-init/Dockerfile.ubuntu2204 @@ -0,0 +1,25 @@ +FROM ubuntu:22.04 AS build + +# Install required tools: +# - ca-certificates installs necessary certificates to use cURL with HTTPS websites +# - curl is used to download the runtime tar.gz +ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update && \ + apt-get install -y --no-install-recommends ca-certificates curl && \ + rm -rf /var/lib/apt/lists/* + +ARG RSW_VERSION=2024.09.0+375.pro3 + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN mkdir -p /pwb-staging && \ + RSW_VERSION_URL=$(echo -n "${RSW_VERSION}" | sed 's/+/-/g') && \ + echo "Downloading https://s3.amazonaws.com/rstudio-ide-build/session/multi/x86_64/rsp-session-multi-linux-${RSW_VERSION_URL}-x86_64.tar.gz" && \ + curl -fsSL -o /pwb-staging/rsp-session-multi-linux.tar.gz "https://s3.amazonaws.com/rstudio-ide-build/session/multi/x86_64/rsp-session-multi-linux-${RSW_VERSION_URL}-x86_64.tar.gz" && \ + mkdir -p /opt/session-components && \ + tar -C /opt/session-components -xf /pwb-staging/rsp-session-multi-linux.tar.gz && \ + chmod -R 755 /opt/session-components && \ + rm -rf /pwb-staging + +COPY --chmod=755 run.sh /usr/local/bin/run.sh + +ENTRYPOINT ["/usr/local/bin/run.sh"] diff --git a/workbench-session-init/NEWS.md b/workbench-session-init/NEWS.md new file mode 100644 index 000000000..4789c2473 --- /dev/null +++ b/workbench-session-init/NEWS.md @@ -0,0 +1,4 @@ +# 2024.11.0 + +- Add NEWS.md +- Add daily builds diff --git a/workbench-session-init/README.md b/workbench-session-init/README.md new file mode 100644 index 000000000..ecae3c923 --- /dev/null +++ b/workbench-session-init/README.md @@ -0,0 +1,50 @@ +# Posit Workbench Session Init Container + +This directory contains a Dockerfile and script that will create an init container to copy session runtime components from a release package into a target mount directory. This init container can be used to pull the session runtime components into another base sesssion image, which can then be used to run Workbench sessions. + +## 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) +* RStudio r-session-complete image: [Docker Hub](https://hub.docker.com/r/rstudio/r-session-complete) +* Workbench Session Init image (Daily/Preview): [Docker Hub](https://hub.docker.com/r/rstudio/rstudio-workbench-session-init-preview) + +## Supported tags and respective Dockerfile links + +* [`jammy-daily`, `ubuntu2204-daily`, `jammy-2024.11.0`, `ubuntu2204-2024.11.0`](https://github.com/rstudio/rstudio-docker-products/blob/main/workbench-session-init/Dockerfile.2204) + +## Building + +Currently daily builds are supported. To build the image, run: + +```console +just preview-bake workbench-session-init-daily +``` + +## Testing + +You can observe what gets copied by the container: + +```console +mkdir init +docker run --rm -v $(pwd)/init:/mnt/init rstudio/workbench-session-init-preview:workbench-session-init-jammy-2024.11.0-daily-328.pro3 +# The init directory has been populated with the Workbench session runtime components. +``` + +You can also test using GOSS: + +```console +just preview-test workbench-session-init-daily +``` + +## 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-init/run.sh b/workbench-session-init/run.sh new file mode 100644 index 000000000..9c29238e5 --- /dev/null +++ b/workbench-session-init/run.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -euo pipefail +set -x + +S=/opt/session-components + +# The target should exist and be an empty directory. +T=/mnt/init + +if [ ! -d "${T}" ] ; then + echo "Cannot find the copy target ${T}" + exit 1 +fi + +echo "Copying files from /session-components to /mnt/init" +time cp -r $S/* $T diff --git a/workbench-session-init/test/goss.yaml b/workbench-session-init/test/goss.yaml new file mode 100644 index 000000000..7c9ab9e76 --- /dev/null +++ b/workbench-session-init/test/goss.yaml @@ -0,0 +1,13 @@ +package: + curl: + installed: true + +file: + /opt/session-components/: + exists: true + mode: "0755" + filetype: directory + /usr/local/bin/run.sh: + exists: true + filetype: file + mode: "0755" diff --git a/workbench-session-init/test/run_tests.sh b/workbench-session-init/test/run_tests.sh new file mode 100755 index 000000000..fc48b0e67 --- /dev/null +++ b/workbench-session-init/test/run_tests.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# install goss +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