Skip to content

Commit faba0a7

Browse files
committed
Add declarative execution environment management to rstudio-connect chart
1 parent 69de043 commit faba0a7

14 files changed

Lines changed: 639 additions & 4 deletions

.github/workflows/chart-test.yaml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,62 @@ jobs:
234234
if: steps.ct-install.outcome == 'failure' || steps.ct-install-all.outcome == 'failure'
235235
run: exit 1
236236

237+
helm-test:
238+
runs-on: ubuntu-latest-4x
239+
strategy:
240+
fail-fast: false
241+
matrix:
242+
include:
243+
- chart: rstudio-connect
244+
base_values: ci/license-file-values.yaml
245+
values: ci/execution-environments-values.yaml
246+
license_secret: PCT_LICENSE_FILE
247+
license_name: pct-license
248+
license_file: pct.lic
249+
steps:
250+
- name: Checkout
251+
uses: actions/checkout@v4
252+
253+
- name: Set up Helm
254+
uses: azure/setup-helm@v4
255+
256+
- name: Add rstudio helm repo
257+
run: helm repo add rstudio https://helm.rstudio.com
258+
259+
- name: Create kind cluster
260+
uses: helm/kind-action@v1
261+
262+
- name: Create namespace
263+
run: kubectl create namespace posit-test
264+
265+
- name: Create license secret
266+
run: |
267+
echo "${{ secrets[matrix.license_secret] }}" > ${{ matrix.license_file }}
268+
kubectl create secret generic ${{ matrix.license_name }} --from-file=${{ matrix.license_file }} --namespace posit-test
269+
rm ${{ matrix.license_file }}
270+
271+
- name: Build dependencies
272+
run: helm dependency build charts/${{ matrix.chart }}
273+
274+
- name: Install chart
275+
run: |
276+
helm install ${{ matrix.chart }} charts/${{ matrix.chart }} \
277+
--namespace posit-test \
278+
--values charts/${{ matrix.chart }}/${{ matrix.base_values }} \
279+
--values charts/${{ matrix.chart }}/${{ matrix.values }} \
280+
--wait \
281+
--timeout 5m
282+
283+
- name: Run helm test
284+
run: helm test ${{ matrix.chart }} --namespace posit-test --timeout 5m
285+
286+
- name: Debug on failure
287+
if: failure()
288+
run: |
289+
kubectl logs -l app.kubernetes.io/instance=${{ matrix.chart }} --namespace posit-test --tail=100
290+
kubectl get pods --namespace posit-test
291+
kubectl describe pod -l helm.sh/hook=test --namespace posit-test
292+
237293
check-versions-connect:
238294
runs-on: ubuntu-latest
239295
steps:

.github/workflows/helm-test.yaml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: Helm Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- "charts/rstudio-connect/**"
9+
- "!charts/rstudio-connect/README.md"
10+
- "!charts/rstudio-connect/README.md.gotmpl"
11+
- "!charts/rstudio-connect/NEWS.md"
12+
- ".github/workflows/helm-test.yaml"
13+
pull_request:
14+
paths:
15+
- "charts/rstudio-connect/**"
16+
- "!charts/rstudio-connect/README.md"
17+
- "!charts/rstudio-connect/README.md.gotmpl"
18+
- "!charts/rstudio-connect/NEWS.md"
19+
- ".github/workflows/helm-test.yaml"
20+
workflow_dispatch:
21+
22+
jobs:
23+
helm-test:
24+
runs-on: ubuntu-latest-4x
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
include:
29+
- chart: rstudio-connect
30+
base_values: ci/license-file-values.yaml
31+
values: ci/execution-environments-values.yaml
32+
license_secret: PCT_LICENSE_FILE
33+
license_name: pct-license
34+
license_file: pct.lic
35+
steps:
36+
- name: Checkout
37+
uses: actions/checkout@v4
38+
39+
- name: Set up Helm
40+
uses: azure/setup-helm@v4
41+
42+
- name: Add rstudio helm repo
43+
run: helm repo add rstudio https://helm.rstudio.com
44+
45+
- name: Create kind cluster
46+
uses: helm/kind-action@v1
47+
48+
- name: Create namespace
49+
run: kubectl create namespace posit-test
50+
51+
- name: Create license secret
52+
run: |
53+
echo "${{ secrets[matrix.license_secret] }}" > ${{ matrix.license_file }}
54+
kubectl create secret generic ${{ matrix.license_name }} --from-file=${{ matrix.license_file }} --namespace posit-test
55+
rm ${{ matrix.license_file }}
56+
57+
- name: Build dependencies
58+
run: helm dependency build charts/${{ matrix.chart }}
59+
60+
- name: Install chart
61+
run: |
62+
helm install ${{ matrix.chart }} charts/${{ matrix.chart }} \
63+
--namespace posit-test \
64+
--values charts/${{ matrix.chart }}/${{ matrix.base_values }} \
65+
--values charts/${{ matrix.chart }}/${{ matrix.values }} \
66+
--wait \
67+
--timeout 5m
68+
69+
- name: Run helm test
70+
run: helm test ${{ matrix.chart }} --namespace posit-test --timeout 5m
71+
72+
- name: Debug on failure
73+
if: failure()
74+
run: |
75+
kubectl logs -l app.kubernetes.io/instance=${{ matrix.chart }} --namespace posit-test --tail=100
76+
kubectl get pods --namespace posit-test
77+
kubectl describe pod -l helm.sh/hook=test --namespace posit-test

charts/rstudio-connect/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: rstudio-connect
22
description: Official Helm chart for Posit Connect
3-
version: 0.8.30
3+
version: 0.8.31
44
apiVersion: v2
55
appVersion: 2026.02.0
66
icon: https://raw.githubusercontent.com/rstudio/helm/main/images/posit-icon-fullcolor.svg

charts/rstudio-connect/NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 0.8.31
4+
5+
- Add `executionEnvironments` value for declarative management of execution environments. Unlike `launcher.customRuntimeYaml`, changes take effect on every `helm upgrade` without requiring a pod restart or database reset.
6+
37
## 0.8.30
48

59
- Fix connect-version-check in CI

charts/rstudio-connect/README.md

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Posit Connect
22

3-
![Version: 0.8.30](https://img.shields.io/badge/Version-0.8.30-informational?style=flat-square) ![AppVersion: 2026.02.0](https://img.shields.io/badge/AppVersion-2026.02.0-informational?style=flat-square)
3+
![Version: 0.8.31](https://img.shields.io/badge/Version-0.8.31-informational?style=flat-square) ![AppVersion: 2026.02.0](https://img.shields.io/badge/AppVersion-2026.02.0-informational?style=flat-square)
44

55
#### _Official Helm chart for Posit Connect_
66

@@ -30,11 +30,11 @@ To ensure reproducibility in your environment and insulate yourself from future
3030

3131
## Installing the chart
3232

33-
To install the chart with the release name `my-release` at version 0.8.30:
33+
To install the chart with the release name `my-release` at version 0.8.31:
3434

3535
```{.bash}
3636
helm repo add rstudio https://helm.rstudio.com
37-
helm upgrade --install my-release rstudio/rstudio-connect --version=0.8.30
37+
helm upgrade --install my-release rstudio/rstudio-connect --version=0.8.31
3838
```
3939

4040
To explore other chart versions, look at:
@@ -191,6 +191,44 @@ the API key unset for the Chronicle agent, deploy the chart, create an administr
191191
secret with the API key. Once the secret is created, the value of `chronicleAgent.connectApiKey.secretKeyRef`
192192
can be set and the release can be upgraded to include the new value.
193193

194+
## Execution Environments
195+
196+
This chart supports declarative management of execution environments via
197+
`ExecutionEnvironments.ConfigFilePath`. Unlike the legacy `launcher.customRuntimeYaml`,
198+
changes to `executionEnvironments` take effect on every `helm upgrade` without requiring
199+
a pod restart or database reset.
200+
201+
When `executionEnvironments` is set, the chart renders the list into a dedicated
202+
ConfigMap and mounts it into the Connect pod.
203+
204+
By default, the chart sets `ExecutionEnvironments.ConfigFilePath` to
205+
`/etc/rstudio-connect/execution-environments/environments.yaml` and mounts the
206+
ConfigMap at `/etc/rstudio-connect/execution-environments/`. If you set
207+
`config.ExecutionEnvironments.ConfigFilePath` to a custom path, the chart uses
208+
that path instead and mounts the ConfigMap at its parent directory.
209+
210+
The ConfigMap is deliberately not included in the pod's checksum annotations, so
211+
changes do not trigger a pod restart. The kubelet updates the mounted file
212+
automatically when the ConfigMap changes (typically within 60-120 seconds), and
213+
Connect detects the update via file polling.
214+
215+
Example `values.yaml`:
216+
217+
```yaml
218+
executionEnvironments:
219+
- name: ghcr.io/my-org/connect-runtime:ubuntu22
220+
title: "Default Runtime"
221+
matching: any
222+
python:
223+
installations:
224+
- version: "3.11.3"
225+
path: /opt/python/3.11.3/bin/python3
226+
r:
227+
installations:
228+
- version: "4.4.0"
229+
path: /opt/R/4.4.0/bin/R
230+
```
231+
194232
## General principles
195233

196234
- In most places, we opt to pass Helm values over configmaps. We translate these into the valid `.gcfg` file format
@@ -234,6 +272,7 @@ The Helm `config` values are converted into the `rstudio-connect.gcfg` service c
234272
| chronicleAgent.volumeMounts | list | `[]` | Verbatim volumeMounts to attach to the Chronicle agent container |
235273
| command | list | `[]` | The pod's run command. By default, it uses the container's default |
236274
| config | object | [Posit Connect Configuration Reference](https://docs.posit.co/connect/admin/appendix/off-host/helm-reference/) | A nested map of maps that generates the rstudio-connect.gcfg file |
275+
| executionEnvironments | list | `[]` (disabled) | Optional list of execution environments to manage declaratively. When set, the chart renders these into a ConfigMap, mounts it into the Connect pod, and sets ExecutionEnvironments.ConfigFilePath in the Connect configuration. Unlike launcher.customRuntimeYaml, changes take effect on every helm upgrade without requiring a pod restart or database reset. |
237276
| extraObjects | list | `[]` | Extra objects to deploy (value evaluated as a template) |
238277
| fullnameOverride | string | `""` | The full name of the release (can be overridden) |
239278
| image | object | `{"imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"repository":"ghcr.io/rstudio/rstudio-connect","tag":"","tagPrefix":"ubuntu2204-"}` | Defines the Posit Connect image to deploy |

charts/rstudio-connect/README.md.gotmpl

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,44 @@ the API key unset for the Chronicle agent, deploy the chart, create an administr
131131
secret with the API key. Once the secret is created, the value of `chronicleAgent.connectApiKey.secretKeyRef`
132132
can be set and the release can be upgraded to include the new value.
133133

134+
## Execution Environments
135+
136+
This chart supports declarative management of execution environments via
137+
`ExecutionEnvironments.ConfigFilePath`. Unlike the legacy `launcher.customRuntimeYaml`,
138+
changes to `executionEnvironments` take effect on every `helm upgrade` without requiring
139+
a pod restart or database reset.
140+
141+
When `executionEnvironments` is set, the chart renders the list into a dedicated
142+
ConfigMap and mounts it into the Connect pod.
143+
144+
By default, the chart sets `ExecutionEnvironments.ConfigFilePath` to
145+
`/etc/rstudio-connect/execution-environments/environments.yaml` and mounts the
146+
ConfigMap at `/etc/rstudio-connect/execution-environments/`. If you set
147+
`config.ExecutionEnvironments.ConfigFilePath` to a custom path, the chart uses
148+
that path instead and mounts the ConfigMap at its parent directory.
149+
150+
The ConfigMap is deliberately not included in the pod's checksum annotations, so
151+
changes do not trigger a pod restart. The kubelet updates the mounted file
152+
automatically when the ConfigMap changes (typically within 60-120 seconds), and
153+
Connect detects the update via file polling.
154+
155+
Example `values.yaml`:
156+
157+
```yaml
158+
executionEnvironments:
159+
- name: ghcr.io/my-org/connect-runtime:ubuntu22
160+
title: "Default Runtime"
161+
matching: any
162+
python:
163+
installations:
164+
- version: "3.11.3"
165+
path: /opt/python/3.11.3/bin/python3
166+
r:
167+
installations:
168+
- version: "4.4.0"
169+
path: /opt/R/4.4.0/bin/R
170+
```
171+
134172
## General principles
135173

136174
- In most places, we opt to pass Helm values over configmaps. We translate these into the valid `.gcfg` file format
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
image:
2+
repository: ghcr.io/rstudio/rstudio-connect-preview
3+
tag: ubuntu2204-daily
4+
5+
executionEnvironments:
6+
- name: ghcr.io/rstudio/content-base:r4.4.0-py3.11.3-jammy
7+
title: "Test Runtime"
8+
matching: any
9+
python:
10+
installations:
11+
- version: "3.11.3"
12+
path: /opt/python/3.11.3/bin/python3
13+
r:
14+
installations:
15+
- version: "4.4.0"
16+
path: /opt/R/4.4.0/bin/R
17+
18+
config:
19+
Authentication:
20+
InsecureDefaultUserAPIKey: true
21+
Database:
22+
SeedUsers: true
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
executionEnvironments:
2+
- name: ghcr.io/rstudio/content-base:r4.4.0-py3.11.3-jammy
3+
title: "Test Runtime"
4+
matching: any
5+
python:
6+
installations:
7+
- version: "3.11.3"
8+
path: /opt/python/3.11.3/bin/python3
9+
r:
10+
installations:
11+
- version: "4.4.0"
12+
path: /opt/R/4.4.0/bin/R

charts/rstudio-connect/templates/_helpers.tpl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ app.kubernetes.io/instance: {{ .Release.Name }}
7676
{{- $launcherDict := dict "Launcher" ( $launcherSettingsDict ) }}
7777
{{- $defaultConfig = merge $defaultConfig $launcherDict }}
7878
{{- end }}
79+
{{- /* declarative execution environments configuration */}}
80+
{{- if .Values.executionEnvironments }}
81+
{{- $eeDict := dict "ExecutionEnvironments" (dict "ConfigFilePath" "/etc/rstudio-connect/execution-environments/environments.yaml") }}
82+
{{- $defaultConfig = merge $defaultConfig $eeDict }}
83+
{{- end }}
7984
{{- /* default licensing configuration */}}
8085
{{- if .Values.license.server }}
8186
{{- $licenseDict := dict "Licensing" ( dict "LicenseType" ("Remote") ) }}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
{{- if .Values.executionEnvironments }}
3+
{{- range $i, $env := .Values.executionEnvironments }}
4+
{{- if not $env.name }}
5+
{{- fail (printf "executionEnvironments[%d].name is required" $i) }}
6+
{{- end }}
7+
{{- end }}
8+
apiVersion: v1
9+
kind: ConfigMap
10+
metadata:
11+
name: {{ include "rstudio-connect.fullname" . }}-execution-environments
12+
namespace: {{ $.Release.Namespace }}
13+
labels:
14+
{{- include "rstudio-connect.labels" . | nindent 4 }}
15+
data:
16+
environments.yaml: |
17+
{{- toYaml .Values.executionEnvironments | nindent 4 }}
18+
{{- end }}

0 commit comments

Comments
 (0)