Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ jobs:
dev-versions: "exclude"
matrix-versions: "exclude"
recent: 3
# workbench-session-complete is built by session.yml, after its
# workbench-session base.
image-name: "^(?!workbench-session-complete$)"
# Push images only for merges into main and weekly schduled re-builds.
push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' }}

Expand Down
83 changes: 83 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,89 @@ jobs:
APP_ID: ${{ secrets.WORKBENCH_IDE_RELEASE_APP_ID }}
APP_PRIVATE_KEY: ${{ secrets.WORKBENCH_IDE_RELEASE_PEM }}

# workbench-session-complete is a rolling release: it keeps only the latest
# Workbench version. product-release.yml keeps every edition, so this image is
# handled here instead, on the same release branch (and therefore the same PR).
# A same-edition patch renames the version in place; an edition bump creates
# the new version and removes the old one. Backports to an older edition are
# skipped.
release-session-complete:
needs: release
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
pull-requests: write
steps:
- name: GitHub App Token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.WORKBENCH_IDE_RELEASE_APP_ID }}
private-key: ${{ secrets.WORKBENCH_IDE_RELEASE_PEM }}
permission-contents: write
permission-pull-requests: write

- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install bakery
uses: posit-dev/images-shared/setup-bakery@v0
with:
restore-cache: "false"

- name: Replace version
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
VERSION: ${{ inputs.version }}
IMAGE: workbench-session-complete
run: |
DISPLAY_VERSION="${VERSION%%[+-]*}"
EDITION="${DISPLAY_VERSION%.*}"
BRANCH="release/${DISPLAY_VERSION}"

# Inline auth header so the token is never persisted in .git/config.
AUTH_HEADER="AUTHORIZATION: basic $(printf '%s' "x-access-token:${GH_TOKEN}" | base64 -w0)"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

# Continue on the branch the release job just pushed.
if git -c "http.https://github.com/.extraheader=$AUTH_HEADER" fetch origin "$BRANCH" 2>/dev/null; then
git checkout -B "$BRANCH" "origin/$BRANCH"
else
git checkout -B "$BRANCH"
fi

OLD_VERSION=$(bakery get version "$IMAGE")
OLD_DISPLAY="${OLD_VERSION%%[+-]*}"
OLD_EDITION="${OLD_DISPLAY%.*}"

if [ "$OLD_VERSION" = "$VERSION" ]; then
echo "$IMAGE already at $VERSION; nothing to do."
exit 0
elif [[ "$EDITION" < "$OLD_EDITION" ]]; then
echo "$VERSION is older than $IMAGE's $OLD_VERSION; rolling release skips backports."
exit 0
elif [ "$OLD_EDITION" = "$EDITION" ]; then
echo "Patching $IMAGE: $OLD_VERSION -> $VERSION"
bakery update version "$IMAGE" "$VERSION" --target-version "$OLD_VERSION"
else
echo "Replacing $IMAGE: $OLD_VERSION -> $VERSION (subpath=$EDITION)"
bakery create version "$IMAGE" "$VERSION" --subpath "$EDITION" --mark-latest
bakery remove version "$IMAGE" "$OLD_VERSION"
fi

git add -A
git commit -m "Release ${DISPLAY_VERSION} for ${IMAGE}"
git -c "http.https://github.com/.extraheader=$AUTH_HEADER" push -u origin "$BRANCH" --force-with-lease

gh pr create \
--title "Release ${DISPLAY_VERSION}" \
--body "Updates images to version \`${VERSION}\`." \
--base main \
--head "$BRANCH" || echo "PR already exists"

trigger-specialized:
needs: release
runs-on: ubuntu-latest
Expand Down
34 changes: 34 additions & 0 deletions .github/workflows/session.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
timeout-minutes: 10
needs:
- build
- build-complete
steps:
- uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0
id: alls-green
Expand Down Expand Up @@ -65,3 +66,36 @@ jobs:
matrix-versions: only
# Push images only for merges into main and weekly schduled re-builds.
push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' }}

build-complete:
name: Build Session Complete
# workbench-session-complete layers Workbench on top of workbench-session,
# so it builds after the session matrix to pick up the fresh base. It still
# runs if the matrix build fails, falling back to the last published base.
#
# Excluded from production.yml so it is only built here.
needs:
- build
if: ${{ !cancelled() && (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') }}
permissions:
contents: read
packages: write
id-token: write

uses: "posit-dev/images-shared/.github/workflows/bakery-build-native.yml@v0"
secrets:
DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
DOCKER_HUB_README_USERNAME: ${{ secrets.DOCKER_HUB_README_USERNAME }}
DOCKER_HUB_README_PASSWORD: ${{ secrets.DOCKER_HUB_README_PASSWORD }}
WIZ_CLIENT_ID: ${{ secrets.WIZ_CLIENT_ID }}
WIZ_CLIENT_SECRET: ${{ secrets.WIZ_CLIENT_SECRET }}
WIZ_POLICY_ID: ${{ secrets.WIZ_POLICY_ID }}
WIZ_PROJECT_ID: ${{ secrets.WIZ_PROJECT_ID }}
with:
# ~15 GB image on a ~7 GB base; needs the larger runner's disk.
amd64-builder: "ubuntu-latest-amd64-8-core"
image-name: "^workbench-session-complete$"
dev-versions: "exclude"
matrix-versions: "exclude"
# Push images only for merges into main and weekly schduled re-builds.
push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' }}
11 changes: 9 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Repository Overview

Posit Workbench container images built with [Posit Bakery](https://github.com/posit-dev/images-shared/tree/main/posit-bakery). Contains `workbench` (Standard/Minimal variants), `workbench-session` (R x Python matrix), and `workbench-session-init`.
Posit Workbench container images built with [Posit Bakery](https://github.com/posit-dev/images-shared/tree/main/posit-bakery). Contains `workbench` (Standard/Minimal variants), `workbench-session` (R x Python matrix), `workbench-session-init`, and `workbench-session-complete`.

## Sibling Repositories

Expand Down Expand Up @@ -82,6 +82,13 @@ Session images for Workbench's Launcher. Uses a **matrix** of R x Python version
(e.g., `R4.5.2-python3.14.3`). No variants — single image per combination.
Also includes Quarto and TinyTeX.

### workbench-session-complete

`workbench-session` (OS-qualified `ubuntu-26.04-{std,min}` tag) with the full Workbench deb
installed, so sessions need no init container. amd64 + arm64. **Rolling release:** `bakery.yaml`
keeps only the latest Workbench version; the `release-session-complete` job in `release.yml`
replaces it on each release. Never add a second version.

### workbench-session-init

Session initialization image. Downloads and packages the session components binary
Expand Down Expand Up @@ -191,7 +198,7 @@ All workflows call shared reusable workflows from `images-shared`:
| `production.yml` | `workbench` + `workbench-session-init` (excludes dev/matrix) | `bakery-build-native.yml` |
| `development-workbench.yml` | `workbench` + `workbench-session-init` dev versions (daily previews) | `bakery-build-native.yml` |
| `development-positron.yml` | `workbench-positron-init` dev version (daily Positron previews) | `bakery-build-native.yml` |
| `session.yml` | `workbench-session` + `workbench-positron-init` matrix images | `bakery-build-native.yml` |
| `session.yml` | `workbench-session` + `workbench-positron-init` matrix images, then `workbench-session-complete` | `bakery-build-native.yml` |

Images push to `docker.io/posit` and `ghcr.io/posit-dev` on main merges and scheduled runs.
Dev preview images push to ghcr.io/posit-dev/workbench-preview and
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ bakery dgoss run --image-name workbench --image-version 2026.01
| `production.yml` | Weekly Sun 03:15 UTC, push to main, dispatch | `workbench` + `workbench-session-init` (excludes dev and matrix) |
| `development-workbench.yml` | Daily 09:45 UTC, push to main, dispatch | `workbench` + `workbench-session-init` dev versions → ghcr.io/posit-dev/workbench-preview |
| `development-positron.yml` | Daily 09:55 UTC, push to main, dispatch | `workbench-positron-init` dev version → ghcr.io/posit-dev/workbench-positron-init-preview |
| `session.yml` | Weekly Sun 03:45 UTC, push to main, dispatch | `workbench-session` + `workbench-positron-init` matrix images |
| `session.yml` | Weekly Sun 03:45 UTC, push to main, dispatch | `workbench-session` + `workbench-positron-init` matrix images, then `workbench-session-complete` |

All workflows use `bakery-build-native.yml` (native amd64 + arm64 runners).

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Container images for [Workbench](https://docs.posit.co/ide/server-pro).
| [workbench](./workbench/) | Provides the Workbench application.<br>This image is for all containerized deployments of Workbench. | [`docker.io/posit/workbench`](https://hub.docker.com/r/posit/workbench) | [`ghcr.io/posit-dev/workbench`](https://github.com/posit-dev/images-workbench/pkgs/container/workbench) |
| [workbench-session](./workbench-session/) | Provides the session runtime environment for Workbench.<br>This image is used for Kubernetes deployments. | [`docker.io/posit/workbench-session`](https://hub.docker.com/r/posit/workbench-session) | [`ghcr.io/posit-dev/workbench-session`](https://github.com/posit-dev/images-workbench/pkgs/container/workbench-session) |
| [workbench-session-init](./workbench-session-init/) | An init container for Workbench that pulls runtime components into a shared volume.<br>This image is for Kubernetes deployments. | [`docker.io/posit/workbench-session-init`](https://hub.docker.com/r/posit/workbench-session-init) | [`ghcr.io/posit-dev/workbench-session-init`](https://github.com/posit-dev/images-workbench/pkgs/container/workbench-session-init) |
| [workbench-session-complete](./workbench-session-complete/) | A session image with the session components built in, so it needs no init container.<br>Rolling release: only the latest Workbench version is maintained. | [`docker.io/posit/workbench-session-complete`](https://hub.docker.com/r/posit/workbench-session-complete) | [`ghcr.io/posit-dev/workbench-session-complete`](https://github.com/posit-dev/images-workbench/pkgs/container/workbench-session-complete) |
| [workbench-positron-init](./workbench-positron-init/) | An init container for Workbench that pulls Positron IDE components into a shared volume.<br>This optional image lets Kubernetes deployments upgrade Positron independently of Workbench releases. | [`docker.io/posit/workbench-positron-init`](https://hub.docker.com/r/posit/workbench-positron-init) | [`ghcr.io/posit-dev/workbench-positron-init`](https://github.com/posit-dev/images-workbench/pkgs/container/workbench-positron-init) |

Posit publishes additional container images to [Docker Hub](https://hub.docker.com/u/posit) and [GitHub Container Registry](https://github.com/orgs/posit-dev/packages).
Expand Down
37 changes: 37 additions & 0 deletions bakery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -376,3 +376,40 @@ images:
- linux/amd64
- linux/arm64
- name: Ubuntu 22.04
- name: workbench-session-complete
displayName: "Posit Workbench Session Complete"
description: "A Posit Workbench session image with a full Workbench installation
layered on, so the session components ship in the image and sessions run without
a workbench-session-init init container alongside them."
documentationUrl: "https://docs.posit.co/ide/server-pro/integration/kubernetes.html"
variants:
- name: Standard
extension: std
tagDisplayName: std
primary: true
- name: Minimal
extension: min
tagDisplayName: min
# No `options` here:
# * goss -- a session image starts no long-running service of its own (the
# Job Launcher execs a session per request), so dgoss runs the default
# `sleep infinity` and the suite is purely structural.
# * soci -- deliberately not enabled yet; worth revisiting given the image size.
versions:
# Rolling release: only the latest Workbench version is kept. The release
# workflow replaces this entry on each Workbench release (see
# .github/workflows/release.yml).
#
# The version is the WORKBENCH release, used verbatim as the apt version
# pin for the rstudio-server package in scripts/install_workbench.sh. It is
# not an R/Python matrix coordinate -- those come from whichever
# workbench-session base build the OS-qualified tag resolves to.
- name: 2026.09.0+174.pro3
subpath: '2026.09'
latest: true
os:
- name: Ubuntu 26.04
primary: true
platforms:
- linux/amd64
- linux/arm64
Loading
Loading