Compare commits

..

1 Commits

Author SHA1 Message Date
Andrew Stoltz
ec78175526 tests: add bluejay-ws runner-exclusion lint + fix 3 stale runner-fleet assertions
Adds Runners_MustNotPinToOperatorWorkstationHosts lint test enforcing
operator directive 2026-05-26: BLUEJAY-WS / iamworkin-ws must never be
a fleet GitHub Actions runner. Build-side analog of the Sprint 9 NEW
safe-account exclusion gate (Puppet GPO/AppLocker/WDAC/audit-forwarder
modules refuse to apply on BLUEJAY-WS). Scans every github-runner
Deployment for forbidden nodeName, nodeSelector, nodeAffinity match
expressions, and toleration key/value pinning. See CLAUDE.md "Common
Mistakes" entry and feedback_bluejay_ws_never_public_runner.md.

Also fixes 3 pre-existing GitHubRunnerFleet_* lint failures that broke
when the runner image bumped to v20260525-ruby3.3.11-stepca (added a
setup-runner-home initContainer):

  * Add MainContainerMappings() helper (containers only, excludes
    initContainers) and switch
    GitHubRunnerFleet_MustRegisterRequiredReposAsRepoScopedDeployments
    + GitHubRunnerFleet_MustSetWritableNonRootDotnetAndCachePaths
    over to it. Without this, ContainerMappings().Should().ContainSingle()
    found the initContainer + runner = 2 containers and failed.

  * Loosen GitHubRunnerFleet_MustAvoidRwoMultiAttachForScaledDeployments
    ReplicaCount assertion from Be(2) to BeGreaterOrEqualTo(2). The
    semantic invariant is "at least 2 replicas so no single-pod
    bottleneck"; deployments tuned upward per 14d CI activity (e.g.
    github-runner-print-web at replicas: 3, see commit 1f1f682 PR #24)
    are valid.

Lint baseline: 6 failed -> 3 failed (the 3 remaining are unrelated:
PublicReadWriteIngressRoutes_* lives in FlowerCore.Updater/k8s/
ingressroute.yaml — separate PR; FcDeviceManagement_* needs operator
domain decision on the missing apps/fc-devicemgmt/argocd-application.yaml).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 22:41:00 -05:00
7 changed files with 70 additions and 482 deletions

View File

@@ -532,7 +532,7 @@ spec:
fsGroupChangePolicy: OnRootMismatch fsGroupChangePolicy: OnRootMismatch
containers: containers:
- name: web - name: web
image: localhost/fc-ttsreader-web:v20260603-s54cx14-pr29-live image: localhost/fc-ttsreader-web:v20260518-sprint36-demo-finish-b132cbf
imagePullPolicy: Never imagePullPolicy: Never
ports: ports:
- containerPort: 5217 - containerPort: 5217
@@ -554,8 +554,6 @@ spec:
value: "/data/chapter-context.db" value: "/data/chapter-context.db"
- name: TtsReader__Jobs__Root - name: TtsReader__Jobs__Root
value: "/data/jobs" value: "/data/jobs"
- name: TtsReader__Export__LocalCasRoot
value: "/data/bundles/cas"
- name: TtsReader__Piper__Host - name: TtsReader__Piper__Host
value: "10.0.57.17" value: "10.0.57.17"
- name: TtsReader__Piper__Port - name: TtsReader__Piper__Port

View File

@@ -58,7 +58,7 @@ spec:
nodeName: rke2-server nodeName: rke2-server
containers: containers:
- name: web - name: web
image: localhost/fc-updater-web:v202605310029-7974fc4 image: localhost/fc-updater-web:v20260509-4162dca-authgate
imagePullPolicy: Never imagePullPolicy: Never
ports: ports:
- containerPort: 8080 - containerPort: 8080
@@ -88,8 +88,6 @@ spec:
value: Faith AI Mike Edition value: Faith AI Mike Edition
- name: FlowerCore__Updater__PublicShares__Links__0__Description - name: FlowerCore__Updater__PublicShares__Links__0__Description
value: Private release link for Mike's Faith AI bundle. value: Private release link for Mike's Faith AI bundle.
- name: FlowerCore__Audit__Sinks__Loki__Enabled
value: "false"
- name: FlowerCore__Updater__Auth__Bootstrap__Enabled - name: FlowerCore__Updater__Auth__Bootstrap__Enabled
value: "true" value: "true"
- name: FlowerCore__Updater__Auth__Bootstrap__Username - name: FlowerCore__Updater__Auth__Bootstrap__Username

View File

@@ -241,7 +241,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -306,7 +306,7 @@ spec:
# UN-PARKED 2026-05-21: Shared.Pos #5 fixed the non-root setup-dotnet path # UN-PARKED 2026-05-21: Shared.Pos #5 fixed the non-root setup-dotnet path
# (DOTNET_INSTALL_DIR step-scoped). Sprint 30 Cl-8 capacity Q-CI-52: raised # (DOTNET_INSTALL_DIR step-scoped). Sprint 30 Cl-8 capacity Q-CI-52: raised
# to replicas: 2 to absorb top-8 burst load per substrate-recommended default. # to replicas: 2 to absorb top-8 burst load per substrate-recommended default.
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-sharedpos app.kubernetes.io/name: github-runner-sharedpos
@@ -397,7 +397,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -448,7 +448,7 @@ metadata:
flowercore.io/runner-repo: puppet flowercore.io/runner-repo: puppet
flowercore.io/github-repo: FlowerCore.Puppet flowercore.io/github-repo: FlowerCore.Puppet
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-puppet app.kubernetes.io/name: github-runner-puppet
@@ -533,7 +533,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -580,7 +580,7 @@ metadata:
flowercore.io/runner-repo: signage flowercore.io/runner-repo: signage
flowercore.io/github-repo: FlowerCore.Signage flowercore.io/github-repo: FlowerCore.Signage
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-signage app.kubernetes.io/name: github-runner-signage
@@ -665,7 +665,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -712,7 +712,7 @@ metadata:
flowercore.io/runner-repo: dms flowercore.io/runner-repo: dms
flowercore.io/github-repo: FlowerCore.DMS flowercore.io/github-repo: FlowerCore.DMS
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-dms app.kubernetes.io/name: github-runner-dms
@@ -797,7 +797,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -844,7 +844,7 @@ metadata:
flowercore.io/runner-repo: telephony flowercore.io/runner-repo: telephony
flowercore.io/github-repo: FlowerCore.Telephony flowercore.io/github-repo: FlowerCore.Telephony
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-telephony app.kubernetes.io/name: github-runner-telephony
@@ -929,7 +929,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -979,7 +979,7 @@ spec:
# Sprint 33 morning-routine (2026-05-25): bumped 2 → 3 because help-screenshots # Sprint 33 morning-routine (2026-05-25): bumped 2 → 3 because help-screenshots
# AAT job holds a runner 30+ min, causing head-of-line blocking on parallel PRs. # AAT job holds a runner 30+ min, causing head-of-line blocking on parallel PRs.
# 12 runs in trailing 5d. # 12 runs in trailing 5d.
replicas: 1 replicas: 3
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-print-web app.kubernetes.io/name: github-runner-print-web
@@ -1064,7 +1064,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -1111,7 +1111,7 @@ metadata:
flowercore.io/runner-repo: chat flowercore.io/runner-repo: chat
flowercore.io/github-repo: FlowerCore.Chat flowercore.io/github-repo: FlowerCore.Chat
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-chat app.kubernetes.io/name: github-runner-chat
@@ -1196,7 +1196,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -1243,7 +1243,7 @@ metadata:
flowercore.io/runner-repo: mysql flowercore.io/runner-repo: mysql
flowercore.io/github-repo: FlowerCore.MySQL flowercore.io/github-repo: FlowerCore.MySQL
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-mysql app.kubernetes.io/name: github-runner-mysql
@@ -1328,7 +1328,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -1375,7 +1375,7 @@ metadata:
flowercore.io/runner-repo: kiosk-linux flowercore.io/runner-repo: kiosk-linux
flowercore.io/github-repo: FlowerCore.Kiosk.Linux flowercore.io/github-repo: FlowerCore.Kiosk.Linux
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-kiosk-linux app.kubernetes.io/name: github-runner-kiosk-linux
@@ -1460,7 +1460,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -1509,7 +1509,7 @@ metadata:
flowercore.io/runner-repo: marquee flowercore.io/runner-repo: marquee
flowercore.io/github-repo: FlowerCore.Marquee flowercore.io/github-repo: FlowerCore.Marquee
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-marquee app.kubernetes.io/name: github-runner-marquee
@@ -1594,7 +1594,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -1643,7 +1643,7 @@ metadata:
flowercore.io/runner-repo: tts-reader flowercore.io/runner-repo: tts-reader
flowercore.io/github-repo: FlowerCore.TtsReader flowercore.io/github-repo: FlowerCore.TtsReader
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-tts-reader app.kubernetes.io/name: github-runner-tts-reader
@@ -1732,7 +1732,7 @@ spec:
# symptoms surfaced. 8Gi gives ~30% headroom over peak observed. # symptoms surfaced. 8Gi gives ~30% headroom over peak observed.
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "2Gi" memory: "2Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -1867,7 +1867,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -2001,7 +2001,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -2135,7 +2135,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -2269,7 +2269,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -2317,7 +2317,7 @@ metadata:
flowercore.io/runner-repo: remote-desktop flowercore.io/runner-repo: remote-desktop
flowercore.io/github-repo: FlowerCore.RemoteDesktop flowercore.io/github-repo: FlowerCore.RemoteDesktop
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-remote-desktop app.kubernetes.io/name: github-runner-remote-desktop
@@ -2402,7 +2402,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -2536,7 +2536,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -2584,7 +2584,7 @@ metadata:
flowercore.io/runner-repo: distribution flowercore.io/runner-repo: distribution
flowercore.io/github-repo: FlowerCore.Distribution flowercore.io/github-repo: FlowerCore.Distribution
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-distribution app.kubernetes.io/name: github-runner-distribution
@@ -2669,7 +2669,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -2717,7 +2717,7 @@ metadata:
flowercore.io/runner-repo: scoreboard flowercore.io/runner-repo: scoreboard
flowercore.io/github-repo: FlowerCore.Scoreboard flowercore.io/github-repo: FlowerCore.Scoreboard
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-scoreboard app.kubernetes.io/name: github-runner-scoreboard
@@ -2802,7 +2802,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -2850,7 +2850,7 @@ metadata:
flowercore.io/runner-repo: segment-display flowercore.io/runner-repo: segment-display
flowercore.io/github-repo: FlowerCore.SegmentDisplay flowercore.io/github-repo: FlowerCore.SegmentDisplay
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-segment-display app.kubernetes.io/name: github-runner-segment-display
@@ -2935,7 +2935,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -2983,7 +2983,7 @@ metadata:
flowercore.io/runner-repo: signage-contracts flowercore.io/runner-repo: signage-contracts
flowercore.io/github-repo: FlowerCore.Signage.Contracts flowercore.io/github-repo: FlowerCore.Signage.Contracts
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-signage-contracts app.kubernetes.io/name: github-runner-signage-contracts
@@ -3068,7 +3068,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -3116,7 +3116,7 @@ metadata:
flowercore.io/runner-repo: signal-control flowercore.io/runner-repo: signal-control
flowercore.io/github-repo: FlowerCore.SignalControl flowercore.io/github-repo: FlowerCore.SignalControl
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-signal-control app.kubernetes.io/name: github-runner-signal-control
@@ -3201,7 +3201,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -3335,7 +3335,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -3469,7 +3469,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -3603,7 +3603,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -3737,7 +3737,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -3871,7 +3871,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -3919,7 +3919,7 @@ metadata:
flowercore.io/runner-repo: pimanager flowercore.io/runner-repo: pimanager
flowercore.io/github-repo: FlowerCore.PiManager flowercore.io/github-repo: FlowerCore.PiManager
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-pimanager app.kubernetes.io/name: github-runner-pimanager
@@ -4004,7 +4004,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -4053,7 +4053,7 @@ metadata:
flowercore.io/runner-repo: updater flowercore.io/runner-repo: updater
flowercore.io/github-repo: FlowerCore.Updater flowercore.io/github-repo: FlowerCore.Updater
spec: spec:
replicas: 1 replicas: 2
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: github-runner-updater app.kubernetes.io/name: github-runner-updater
@@ -4138,419 +4138,7 @@ spec:
value: "false" value: "false"
resources: resources:
requests: requests:
cpu: "100m" cpu: "500m"
memory: "1Gi"
limits:
cpu: "2000m"
memory: "4Gi"
volumeMounts:
- name: runner-home
mountPath: /home/runner
- name: nuget-cache
mountPath: /home/runner/.nuget/packages
- name: tmp
mountPath: /tmp
livenessProbe:
exec:
command:
- /bin/sh
- -c
- "pgrep -f Runner.Listener > /dev/null"
initialDelaySeconds: 30
periodSeconds: 30
failureThreshold: 3
volumes:
- name: runner-home
emptyDir: {}
- name: nuget-cache
emptyDir:
sizeLimit: 2Gi
- name: tmp
emptyDir: {}
restartPolicy: Always
---
# Runner for FlowerCore.DeviceManagement. Two replicas use per-pod emptyDir
# caches, so backlog can drain without sharing a ReadWriteOnce PVC. Added
# 2026-05-26 morning-routine — DM had ZERO registered runners while Sprint 37
# Cx-1 PRs #20 (CI-to-Linux migration), #21 (WDAC), and #22 (AppLocker) were
# all queued indefinitely. Chicken-and-egg: the migration PRs need Linux
# runners that the migration creates.
apiVersion: apps/v1
kind: Deployment
metadata:
name: github-runner-device-management
namespace: github-runner
labels:
app.kubernetes.io/name: github-runner-device-management
app.kubernetes.io/component: runner
app.kubernetes.io/part-of: flowercore
app.kubernetes.io/managed-by: argocd
flowercore.io/created-by: argocd
flowercore.io/runner-repo: device-management
flowercore.io/github-repo: FlowerCore.DeviceManagement
spec:
# Single replica until cluster CPU pressure resolves; the fleet-wide
# request right-sizing pass is queued for a future sweep.
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: github-runner-device-management
strategy:
type: Recreate
template:
metadata:
labels:
app.kubernetes.io/name: github-runner-device-management
app.kubernetes.io/component: runner
app.kubernetes.io/part-of: flowercore
flowercore.io/created-by: argocd
flowercore.io/runner-repo: device-management
flowercore.io/github-repo: FlowerCore.DeviceManagement
spec:
serviceAccountName: github-runner
securityContext:
runAsNonRoot: true
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
initContainers:
- name: setup-runner-home
image: localhost/fc-github-runner:v20260525-ruby3.3.11-stepca
imagePullPolicy: Never
command:
- sh
- -c
- |
set -e
mkdir -p /home/runner/.dotnet /home/runner/.nuget/packages /home/runner/.nuget/NuGet /home/runner/.cache /home/runner/_tool
if [ -d /opt/runner-toolcache/Ruby ] && [ ! -d /home/runner/_tool/Ruby ]; then
cp -a /opt/runner-toolcache/Ruby /home/runner/_tool/
fi
chown -R 1001:1001 /home/runner/.dotnet /home/runner/.nuget /home/runner/.cache /home/runner/_tool
chmod -R 755 /home/runner/.dotnet /home/runner/.nuget /home/runner/.cache /home/runner/_tool
securityContext:
runAsUser: 0
runAsNonRoot: false
volumeMounts:
- name: runner-home
mountPath: /home/runner
containers:
- name: runner
image: localhost/fc-github-runner:v20260525-ruby3.3.11-stepca
imagePullPolicy: Never
env:
- name: REPO_URL
value: "https://github.com/astoltz/FlowerCore.DeviceManagement"
- name: RUNNER_NAME_PREFIX
value: "rke2-linux-device-management"
- name: RUNNER_WORKDIR
value: "/tmp/runner/work"
- name: EPHEMERAL
value: "true"
- name: LABELS
value: "self-hosted,linux,fc-build-linux"
- name: HOME
value: "/home/runner"
- name: DOTNET_INSTALL_DIR
value: "/home/runner/.dotnet"
- name: DOTNET_CLI_TELEMETRY_OPTOUT
value: "1"
- name: DOTNET_NOLOGO
value: "1"
- name: DOTNET_GENERATE_ASPNET_CERTIFICATE
value: "false"
- name: DOTNET_CLI_HOME
value: "/home/runner"
- name: NUGET_PACKAGES
value: "/home/runner/.nuget/packages"
- name: XDG_CACHE_HOME
value: "/home/runner/.cache"
- name: RUNNER_TOOL_CACHE
value: "/home/runner/_tool"
- name: ACCESS_TOKEN
valueFrom:
secretKeyRef:
name: github-runner-token
key: credential
- name: RUN_AS_ROOT
value: "false"
resources:
# Reduced from 500m → 100m 2026-05-26 because cluster CPU
# requests were at 99% across all 3 nodes; idle runners use ~1m.
# Burst headroom preserved by limits.cpu: 2000m.
requests:
cpu: "100m"
memory: "1Gi"
limits:
cpu: "2000m"
memory: "4Gi"
volumeMounts:
- name: runner-home
mountPath: /home/runner
- name: nuget-cache
mountPath: /home/runner/.nuget/packages
- name: tmp
mountPath: /tmp
livenessProbe:
exec:
command:
- /bin/sh
- -c
- "pgrep -f Runner.Listener > /dev/null"
initialDelaySeconds: 30
periodSeconds: 30
failureThreshold: 3
volumes:
- name: runner-home
emptyDir: {}
- name: nuget-cache
emptyDir:
sizeLimit: 2Gi
- name: tmp
emptyDir: {}
restartPolicy: Always
---
# Runner for FlowerCore.AiStation.Linux. Two replicas use per-pod emptyDir
# caches. Added 2026-05-26 — #13 master-CI-fix PR was queued indefinitely
# (Linux job has no runner; Windows job remains queued until the Windows
# runner host substrate lands per Sprint 36 v2 Cl-2 / ADR-174).
apiVersion: apps/v1
kind: Deployment
metadata:
name: github-runner-aistation-linux
namespace: github-runner
labels:
app.kubernetes.io/name: github-runner-aistation-linux
app.kubernetes.io/component: runner
app.kubernetes.io/part-of: flowercore
app.kubernetes.io/managed-by: argocd
flowercore.io/created-by: argocd
flowercore.io/runner-repo: aistation-linux
flowercore.io/github-repo: FlowerCore.AiStation.Linux
spec:
# Single replica until cluster CPU pressure resolves; the fleet-wide
# request right-sizing pass is queued for a future sweep.
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: github-runner-aistation-linux
strategy:
type: Recreate
template:
metadata:
labels:
app.kubernetes.io/name: github-runner-aistation-linux
app.kubernetes.io/component: runner
app.kubernetes.io/part-of: flowercore
flowercore.io/created-by: argocd
flowercore.io/runner-repo: aistation-linux
flowercore.io/github-repo: FlowerCore.AiStation.Linux
spec:
serviceAccountName: github-runner
securityContext:
runAsNonRoot: true
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
initContainers:
- name: setup-runner-home
image: localhost/fc-github-runner:v20260525-ruby3.3.11-stepca
imagePullPolicy: Never
command:
- sh
- -c
- |
set -e
mkdir -p /home/runner/.dotnet /home/runner/.nuget/packages /home/runner/.nuget/NuGet /home/runner/.cache /home/runner/_tool
if [ -d /opt/runner-toolcache/Ruby ] && [ ! -d /home/runner/_tool/Ruby ]; then
cp -a /opt/runner-toolcache/Ruby /home/runner/_tool/
fi
chown -R 1001:1001 /home/runner/.dotnet /home/runner/.nuget /home/runner/.cache /home/runner/_tool
chmod -R 755 /home/runner/.dotnet /home/runner/.nuget /home/runner/.cache /home/runner/_tool
securityContext:
runAsUser: 0
runAsNonRoot: false
volumeMounts:
- name: runner-home
mountPath: /home/runner
containers:
- name: runner
image: localhost/fc-github-runner:v20260525-ruby3.3.11-stepca
imagePullPolicy: Never
env:
- name: REPO_URL
value: "https://github.com/astoltz/FlowerCore.AiStation.Linux"
- name: RUNNER_NAME_PREFIX
value: "rke2-linux-aistation-linux"
- name: RUNNER_WORKDIR
value: "/tmp/runner/work"
- name: EPHEMERAL
value: "true"
- name: LABELS
value: "self-hosted,linux,fc-build-linux"
- name: HOME
value: "/home/runner"
- name: DOTNET_INSTALL_DIR
value: "/home/runner/.dotnet"
- name: DOTNET_CLI_TELEMETRY_OPTOUT
value: "1"
- name: DOTNET_NOLOGO
value: "1"
- name: DOTNET_GENERATE_ASPNET_CERTIFICATE
value: "false"
- name: DOTNET_CLI_HOME
value: "/home/runner"
- name: NUGET_PACKAGES
value: "/home/runner/.nuget/packages"
- name: XDG_CACHE_HOME
value: "/home/runner/.cache"
- name: RUNNER_TOOL_CACHE
value: "/home/runner/_tool"
- name: ACCESS_TOKEN
valueFrom:
secretKeyRef:
name: github-runner-token
key: credential
- name: RUN_AS_ROOT
value: "false"
resources:
requests:
cpu: "100m"
memory: "1Gi"
limits:
cpu: "2000m"
memory: "4Gi"
volumeMounts:
- name: runner-home
mountPath: /home/runner
- name: nuget-cache
mountPath: /home/runner/.nuget/packages
- name: tmp
mountPath: /tmp
livenessProbe:
exec:
command:
- /bin/sh
- -c
- "pgrep -f Runner.Listener > /dev/null"
initialDelaySeconds: 30
periodSeconds: 30
failureThreshold: 3
volumes:
- name: runner-home
emptyDir: {}
- name: nuget-cache
emptyDir:
sizeLimit: 2Gi
- name: tmp
emptyDir: {}
restartPolicy: Always
---
# Runner for FlowerCore.WorldBuilder. Two replicas use per-pod emptyDir
# caches. Added 2026-05-26 — #3 and #4 Linux migration PRs queued
# indefinitely with one stale offline runner registered against the repo.
apiVersion: apps/v1
kind: Deployment
metadata:
name: github-runner-worldbuilder
namespace: github-runner
labels:
app.kubernetes.io/name: github-runner-worldbuilder
app.kubernetes.io/component: runner
app.kubernetes.io/part-of: flowercore
app.kubernetes.io/managed-by: argocd
flowercore.io/created-by: argocd
flowercore.io/runner-repo: worldbuilder
flowercore.io/github-repo: FlowerCore.WorldBuilder
spec:
# Single replica until cluster CPU pressure resolves; the fleet-wide
# request right-sizing pass is queued for a future sweep.
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: github-runner-worldbuilder
strategy:
type: Recreate
template:
metadata:
labels:
app.kubernetes.io/name: github-runner-worldbuilder
app.kubernetes.io/component: runner
app.kubernetes.io/part-of: flowercore
flowercore.io/created-by: argocd
flowercore.io/runner-repo: worldbuilder
flowercore.io/github-repo: FlowerCore.WorldBuilder
spec:
serviceAccountName: github-runner
securityContext:
runAsNonRoot: true
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
initContainers:
- name: setup-runner-home
image: localhost/fc-github-runner:v20260525-ruby3.3.11-stepca
imagePullPolicy: Never
command:
- sh
- -c
- |
set -e
mkdir -p /home/runner/.dotnet /home/runner/.nuget/packages /home/runner/.nuget/NuGet /home/runner/.cache /home/runner/_tool
if [ -d /opt/runner-toolcache/Ruby ] && [ ! -d /home/runner/_tool/Ruby ]; then
cp -a /opt/runner-toolcache/Ruby /home/runner/_tool/
fi
chown -R 1001:1001 /home/runner/.dotnet /home/runner/.nuget /home/runner/.cache /home/runner/_tool
chmod -R 755 /home/runner/.dotnet /home/runner/.nuget /home/runner/.cache /home/runner/_tool
securityContext:
runAsUser: 0
runAsNonRoot: false
volumeMounts:
- name: runner-home
mountPath: /home/runner
containers:
- name: runner
image: localhost/fc-github-runner:v20260525-ruby3.3.11-stepca
imagePullPolicy: Never
env:
- name: REPO_URL
value: "https://github.com/astoltz/FlowerCore.WorldBuilder"
- name: RUNNER_NAME_PREFIX
value: "rke2-linux-worldbuilder"
- name: RUNNER_WORKDIR
value: "/tmp/runner/work"
- name: EPHEMERAL
value: "true"
- name: LABELS
value: "self-hosted,linux,fc-build-linux"
- name: HOME
value: "/home/runner"
- name: DOTNET_INSTALL_DIR
value: "/home/runner/.dotnet"
- name: DOTNET_CLI_TELEMETRY_OPTOUT
value: "1"
- name: DOTNET_NOLOGO
value: "1"
- name: DOTNET_GENERATE_ASPNET_CERTIFICATE
value: "false"
- name: DOTNET_CLI_HOME
value: "/home/runner"
- name: NUGET_PACKAGES
value: "/home/runner/.nuget/packages"
- name: XDG_CACHE_HOME
value: "/home/runner/.cache"
- name: RUNNER_TOOL_CACHE
value: "/home/runner/_tool"
- name: ACCESS_TOKEN
valueFrom:
secretKeyRef:
name: github-runner-token
key: credential
- name: RUN_AS_ROOT
value: "false"
resources:
requests:
cpu: "100m"
memory: "1Gi" memory: "1Gi"
limits: limits:
cpu: "2000m" cpu: "2000m"
@@ -4587,6 +4175,3 @@ spec:
# Common as the only PVC-backed runner at replicas: 1. Any future multi-replica # Common as the only PVC-backed runner at replicas: 1. Any future multi-replica
# runner must use per-pod emptyDir caches, not a shared ReadWriteOnce PVC. # runner must use per-pod emptyDir caches, not a shared ReadWriteOnce PVC.
# 2026-05-25: PiManager added (was missed in the Sprint 32 long-tail sweep). # 2026-05-25: PiManager added (was missed in the Sprint 32 long-tail sweep).
# 2026-05-26: Updater + DeviceManagement + AiStation.Linux + WorldBuilder
# added by the morning-routine sweep — those repos had had ZERO online Linux
# PR-CI capacity, blocking the Sprint 37 Cx-1 Linux-CI-migration PRs.

View File

@@ -46,7 +46,7 @@ spec:
spec: spec:
containers: containers:
- name: intranet-web - name: intranet-web
image: localhost/fc-intranet-web:v20260531-ttsreader-bridge image: localhost/fc-intranet-web:v20260508-brochure-w1
imagePullPolicy: Never imagePullPolicy: Never
ports: ports:
- containerPort: 5300 - containerPort: 5300

View File

@@ -25,7 +25,7 @@ metadata:
role: github-actions-runner role: github-actions-runner
flowercore.io/managed-by: bluejay-infra flowercore.io/managed-by: bluejay-infra
spec: spec:
runStrategy: Halted runStrategy: Always
template: template:
metadata: metadata:
labels: labels:

View File

@@ -207,13 +207,20 @@ spec:
- port: 993 - port: 993
targetPort: 993 targetPort: 993
name: imaps name: imaps
# --- mail-tls Certificate REMOVED 2026-06-01 --- ---
# mail-tls is now managed OUTSIDE cert-manager: issued from step-ca's JWK 'admin' # TLS Certificate via cert-manager
# provisioner and auto-renewed by a systemd timer on noc1 (step ca renew), which apiVersion: cert-manager.io/v1
# writes the mail-tls secret directly. step-ca-acme only has an HTTP-01 (Traefik) kind: Certificate
# solver, but mail.iamworkin.lan must resolve to the dedicated MetalLB IP 10.0.56.202 metadata:
# (SMTP/IMAP), so HTTP-01 cannot validate. Do NOT re-add a cert-manager Certificate name: mail-tls
# here unless a DNS-01 solver is deployed for step-ca-acme. namespace: mail
spec:
secretName: mail-tls
issuerRef:
name: step-ca-acme
kind: ClusterIssuer
dnsNames:
- mail.iamworkin.lan
--- ---
# Traefik IngressRoute - Webmail placeholder # Traefik IngressRoute - Webmail placeholder
apiVersion: traefik.io/v1alpha1 apiVersion: traefik.io/v1alpha1

View File

@@ -479,11 +479,11 @@ data:
- "https://gitea.iamworkin.lan/" - "https://gitea.iamworkin.lan/"
- "https://argocd.iamworkin.lan/" - "https://argocd.iamworkin.lan/"
- "https://intranet.iamworkin.lan/" - "https://intranet.iamworkin.lan/"
- "https://signage.iamworkin.lan/healthz" # root 401 auth-gated 2026-06-01; /healthz anon 200 - "https://signage.iamworkin.lan/"
- "https://kiosk.iamworkin.lan/" - "https://kiosk.iamworkin.lan/"
- "https://media.iamworkin.lan/" - "https://media.iamworkin.lan/"
- "https://mysql.iamworkin.lan/healthz" # root 401 auth-gated 2026-06-01; /healthz anon 200 - "https://mysql.iamworkin.lan/"
- "https://php.iamworkin.lan/healthz" # root 401 auth-gated 2026-06-01; /healthz anon 200 - "https://php.iamworkin.lan/"
- "https://zabbix.iamworkin.lan/" - "https://zabbix.iamworkin.lan/"
- "https://desktop.iamworkin.lan/" - "https://desktop.iamworkin.lan/"
- "https://print.iamworkin.lan/" - "https://print.iamworkin.lan/"