feat(github-runner): pod-env DOTNET_INSTALL_DIR + initContainer for non-root runner

Sprint 30 Cl-1 acceptance fix. Sets DOTNET_INSTALL_DIR + NUGET_PACKAGES + 4
sibling env vars on both Deployments so non-root runner (UID 1001) can
write to /home/runner/.dotnet + /home/runner/.nuget without the
per-workflow patch that ~25 flipped Linux repos currently carry.

initContainer pre-creates + chowns the dirs to runner:runner so the
runtime mkdir-or-write succeeds on first restore. emptyDir mounted at
/home/runner; the .nuget/packages PVC (Common runner) wins at its nested
mount path so the persistent NuGet cache survives ephemeral pod restarts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andrew Stoltz
2026-05-17 21:24:30 -05:00
parent 35844e0dbd
commit 9a15e4ce52

View File

@@ -141,6 +141,32 @@ spec:
runAsUser: 1001 runAsUser: 1001
runAsGroup: 1001 runAsGroup: 1001
fsGroup: 1001 fsGroup: 1001
# Sprint 30 Cl-1 pod-env fix (2026-05-21): pre-create + chown
# /home/runner/.dotnet + /home/runner/.nuget so the non-root runner
# (UID 1001) can host setup-dotnet@v4 + dotnet restore writes without
# the per-workflow DOTNET_INSTALL_DIR patch ~25 flipped Linux repos
# have been carrying. Runs as root so chown succeeds; the main
# container then runs as 1001 against an emptyDir mounted at
# /home/runner. The PVC mount at /home/runner/.nuget/packages
# (Common runner) still wins at its nested path because Kubernetes
# honors the deeper mount.
initContainers:
- name: setup-runner-home
image: busybox:1.36
command:
- sh
- -c
- |
set -e
mkdir -p /home/runner/.dotnet /home/runner/.nuget/packages /home/runner/.nuget/NuGet
chown -R 1001:1001 /home/runner/.dotnet /home/runner/.nuget
chmod -R 755 /home/runner/.dotnet /home/runner/.nuget
securityContext:
runAsUser: 0
runAsNonRoot: false
volumeMounts:
- name: runner-home
mountPath: /home/runner
containers: containers:
- name: runner - name: runner
image: myoung34/github-runner:latest image: myoung34/github-runner:latest
@@ -181,6 +207,22 @@ spec:
# setup steps (cache prewarm + apt updates — both already baked). # setup steps (cache prewarm + apt updates — both already baked).
- name: RUN_AS_ROOT - name: RUN_AS_ROOT
value: "false" value: "false"
# Sprint 30 Cl-1 pod-env fix (2026-05-21): retire the per-workflow
# DOTNET_INSTALL_DIR patch by setting it (+ siblings) here so ALL
# flipped Linux repos pick it up automatically. setup-dotnet@v4
# default writes to /usr/share/dotnet (root-only) or HOME-relative
# ~/.dotnet without HOME guard; pin both explicitly to the chowned
# emptyDir at /home/runner.
- name: DOTNET_INSTALL_DIR
value: "/home/runner/.dotnet"
- name: DOTNET_CLI_TELEMETRY_OPTOUT
value: "1"
- name: NUGET_PACKAGES
value: "/home/runner/.nuget/packages"
- name: DOTNET_NOLOGO
value: "1"
- name: DOTNET_GENERATE_ASPNET_CERTIFICATE
value: "false"
resources: resources:
requests: requests:
cpu: "500m" cpu: "500m"
@@ -189,6 +231,14 @@ spec:
cpu: "2000m" cpu: "2000m"
memory: "4Gi" memory: "4Gi"
volumeMounts: volumeMounts:
# /home/runner emptyDir — owned by the non-root runner thanks
# to the setup-runner-home initContainer chown. Hosts .dotnet
# (setup-dotnet@v4 target) and provides a writable HOME without
# forcing a PVC. The PVC mount below at .nuget/packages wins
# at that nested path (deeper mount overrides), so the Common
# NuGet cache continues to persist across ephemeral pod restarts.
- name: runner-home
mountPath: /home/runner
- name: nuget-cache - name: nuget-cache
mountPath: /home/runner/.nuget/packages mountPath: /home/runner/.nuget/packages
- name: tmp - name: tmp
@@ -204,6 +254,8 @@ spec:
periodSeconds: 30 periodSeconds: 30
failureThreshold: 3 failureThreshold: 3
volumes: volumes:
- name: runner-home
emptyDir: {}
- name: nuget-cache - name: nuget-cache
persistentVolumeClaim: persistentVolumeClaim:
claimName: github-runner-nuget-cache claimName: github-runner-nuget-cache
@@ -255,6 +307,27 @@ spec:
runAsUser: 1001 runAsUser: 1001
runAsGroup: 1001 runAsGroup: 1001
fsGroup: 1001 fsGroup: 1001
# Sprint 30 Cl-1 pod-env fix (2026-05-21): see github-runner Deployment
# above for full rationale. Mirrored on the Shared.Pos runner so the
# per-workflow DOTNET_INSTALL_DIR patch can be retired fleet-wide
# rather than re-applied per repo as flipped lanes land.
initContainers:
- name: setup-runner-home
image: busybox:1.36
command:
- sh
- -c
- |
set -e
mkdir -p /home/runner/.dotnet /home/runner/.nuget/packages /home/runner/.nuget/NuGet
chown -R 1001:1001 /home/runner/.dotnet /home/runner/.nuget
chmod -R 755 /home/runner/.dotnet /home/runner/.nuget
securityContext:
runAsUser: 0
runAsNonRoot: false
volumeMounts:
- name: runner-home
mountPath: /home/runner
containers: containers:
- name: runner - name: runner
image: myoung34/github-runner:latest image: myoung34/github-runner:latest
@@ -277,6 +350,17 @@ spec:
key: credential key: credential
- name: RUN_AS_ROOT - name: RUN_AS_ROOT
value: "false" value: "false"
# Sprint 30 Cl-1 pod-env fix (2026-05-21): retire per-workflow patch.
- name: DOTNET_INSTALL_DIR
value: "/home/runner/.dotnet"
- name: DOTNET_CLI_TELEMETRY_OPTOUT
value: "1"
- name: NUGET_PACKAGES
value: "/home/runner/.nuget/packages"
- name: DOTNET_NOLOGO
value: "1"
- name: DOTNET_GENERATE_ASPNET_CERTIFICATE
value: "false"
resources: resources:
requests: requests:
cpu: "500m" cpu: "500m"
@@ -285,6 +369,12 @@ spec:
cpu: "2000m" cpu: "2000m"
memory: "4Gi" memory: "4Gi"
volumeMounts: volumeMounts:
# Shared.Pos runner uses emptyDir for nuget cache (no node pin
# via RWO PVC). /home/runner emptyDir hosts .dotnet via the
# setup-runner-home initContainer chown; the .nuget/packages
# emptyDir mount still wins at its nested path.
- name: runner-home
mountPath: /home/runner
- name: nuget-cache - name: nuget-cache
mountPath: /home/runner/.nuget/packages mountPath: /home/runner/.nuget/packages
- name: tmp - name: tmp
@@ -299,6 +389,8 @@ spec:
periodSeconds: 30 periodSeconds: 30
failureThreshold: 3 failureThreshold: 3
volumes: volumes:
- name: runner-home
emptyDir: {}
- name: nuget-cache - name: nuget-cache
emptyDir: {} emptyDir: {}
- name: tmp - name: tmp