Skip to content

refactor(ci): Add actions.summerwind.dev ARC runner deployment option - #797

Merged
XinyueZhang369 merged 7 commits into
mainfrom
xz/runner-deployment
Mar 27, 2026
Merged

XinyueZhang369 merged 7 commits into
mainfrom
xz/runner-deployment

Conversation

@XinyueZhang369

@XinyueZhang369 XinyueZhang369 commented Mar 17, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Problem

The existing ARC deployment guide only covers the official GitHub ARC controller (ghcr.io/actions/actions-runner-controller-charts). Some clusters require or prefer the community actions.summerwind.dev controller which uses RunnerDeployment CRDs and provides HorizontalRunnerAutoscaler support.

Solution

Add an alternative deployment path using the actions.summerwind.dev ARC controller to the README, along with the corresponding Kubernetes manifests for RBAC, CPU runners, GPU runners, and autoscaling.

Changes

  • Add RunnerDeployment-based runner manifests (arc-runner-cpu.yaml, arc-runner-gpu.yaml, arc-runner-rbac.yaml, arc-runner-autoscaler.yaml)
  • Update README.md with an alternative section documenting the actions.summerwind.dev ARC installation and deployment steps
  • Fix GPU resource units and adjust min/max for HorizontalRunnerAutoscaler

Test Plan

  • Deploy the actions.summerwind.dev controller via Helm and verify pods are running in actions-runner-system
  • Apply the RBAC, runner, and autoscaler manifests and confirm RunnerDeployment and HorizontalRunnerAutoscaler resources are created
  • Trigger a GitHub Actions workflow targeting the runner labels and verify runner pods are provisioned
Checklist
  • cargo +nightly fmt passes
  • cargo clippy --all-targets --all-features -- -D warnings passes
  • (Optional) Documentation updated
  • (Optional) Please join us on Slack #sig-smg to discuss, review, and merge PRs

Summary by CodeRabbit

  • New Features

    • Added GPU-based runner deployments (H100, A10 variants) and a CPU-based runner deployment.
    • Added Horizontal Runner Autoscalers to scale deployments automatically.
    • Added service account and RBAC resources for runners.
  • Documentation

    • Added alternative setup docs using the community Actions Runner Controller, including install and verification steps.

@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Mar 17, 2026
@coderabbitai

coderabbitai Bot commented Mar 17, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds ARC-based GitHub Actions runner manifests and docs: RBAC, CPU and multiple GPU RunnerDeployments, HorizontalRunnerAutoscaler resources, and README instructions for installing actions.summerwind.dev/ARC and applying the manifests.

Changes

Cohort / File(s) Summary
Documentation
scripts/k8s-runner-resources/README.md
Adds an "Alternative: Using actions.summerwind.dev ARC" section with Helm install commands, GitHub App secret creation, and kubectl apply verification steps (checks runnerdeployments).
RBAC & ServiceAccount
scripts/k8s-runner-resources/arc-runner-rbac.yaml
Adds arc-runner-sa ServiceAccount, a namespaced Role granting secrets/pod access, and a RoleBinding in actions-runner-system.
CPU RunnerDeployment
scripts/k8s-runner-resources/arc-runner-cpu.yaml
Adds RunnerDeployment/arc-runner-cpu (4 replicas) with large CPU/memory requests, env vars from secrets, and a DinD sidecar.
GPU RunnerDeployments
scripts/k8s-runner-resources/arc-runner-gpu.yaml
Adds five GPU-targeted RunnerDeployment resources (H100/A10 and 1/2/4 GPU variants) with node selectors/tolerations, pod affinity/anti-affinity, model-cache volume mounts, DinD sidecars, and resource sizing per deployment.
Autoscalers
scripts/k8s-runner-resources/arc-runner-autoscaler.yaml
Adds multiple HorizontalRunnerAutoscaler CRs targeting each RunnerDeployment; GPU autoscalers use queued-workflow metrics, CPU autoscaler uses PercentageRunnersBusy with threshold and factor settings.

Sequence Diagram(s)

sequenceDiagram
  participant GitHub
  participant ARC_Controller as "actions-runner-controller"
  participant K8s_API as "Kubernetes API"
  participant RunnerPods as "Runner Pods / DinD"

  GitHub->>ARC_Controller: Workflows queued / Runner registration via GitHub App
  ARC_Controller->>K8s_API: Create RunnerDeployment & RunnerPod resources
  K8s_API->>RunnerPods: Schedule Pod on GPU/CPU node (nodeSelector/tolerations)
  RunnerPods->>GitHub: Register ephemeral runner and accept jobs
  GitHub->>RunnerPods: Dispatch workflow jobs
  RunnerPods->>RunnerPods: Job execution (uses DinD, model cache)
  K8s_API->>ARC_Controller: HorizontalRunnerAutoscaler metrics (queued/busy)
  ARC_Controller->>K8s_API: Scale RunnerDeployment (update replicas)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Suggested labels

ci

Suggested reviewers

  • CatherineSue
  • key4ng
  • slin1237

Poem

🐰 In a burrow of pods and a meadow of queues,
Runners wake up with GPUs and caffeine-infused views,
Autoscalers nudge replicas when workloads expand,
Containers hum lightly across cloud and land,
Hooray—CI hops forward, as planned! 🥕🚀

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding an alternative ARC runner deployment option using actions.summerwind.dev controller alongside documentation updates and manifests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch xz/runner-deployment

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request expands the available options for deploying GitHub Actions self-hosted runners on Kubernetes. It provides a new, fully documented method utilizing the actions.summerwind.dev controller, offering greater flexibility for environments that prefer or require this specific community-driven solution. The changes include all necessary Kubernetes configuration files to set up CPU and GPU runners with proper access controls and dynamic scaling capabilities.

Highlights

  • New ARC Deployment Option: Added an alternative deployment path for GitHub Actions self-hosted runners using the community actions.summerwind.dev ARC controller, which leverages RunnerDeployment CRDs and HorizontalRunnerAutoscaler.
  • Kubernetes Manifests: Introduced new Kubernetes manifests for RBAC, CPU runners, various GPU runners (H100, A10), and their corresponding autoscalers.
  • Documentation Update: Updated the README.md with comprehensive installation and deployment steps for the actions.summerwind.dev ARC option.
  • Resource Configuration: Adjusted GPU resource units and refined minimum/maximum replica settings for HorizontalRunnerAutoscaler configurations.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an alternative deployment method for ARC runners using the actions.summerwind.dev controller, adding new Kubernetes manifests and updating documentation. My review found several critical and high-severity issues in the new manifests. The RBAC role for runner pods is overly permissive, creating a security risk. The CPU runner's Docker-in-Docker configuration is incomplete, lacking proper setup for the Docker socket and requiring DOCKER_TLS_CERTDIR to be explicitly set to an empty string, which will cause Docker-dependent jobs to fail. Additionally, a GPU runner deployment is missing necessary CPU and memory resource definitions and also requires the DOCKER_TLS_CERTDIR environment variable to be set for its Docker-in-Docker setup, potentially causing instability. Finally, the CPU runner's autoscaler configuration contains invalid parameters that will prevent it from functioning correctly. Addressing these points will improve the security, stability, and functionality of the new runner deployments.

Comment on lines +104 to +109
metrics:
- type: PercentageRunnersBusy
scaleUpThreshold: "0.95"
scaleDownThreshold: "0.25"
scaleUpFactor: "0.5"
scaleDownFactor: "0.5"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The arc-cpu-runner-autoscaler is configured to use the PercentageRunnersBusy metric, but it includes scaleUpFactor and scaleDownFactor fields. These fields are only valid for the TotalNumberOfQueuedAndInProgressWorkflowRuns metric type and will be ignored or cause an error here. This will prevent the autoscaler from functioning as expected.

  metrics:
    - type: PercentageRunnersBusy
      scaleUpThreshold: "0.95"
      scaleDownThreshold: "0.25"

Comment on lines +9 to +48
spec:
ephemeral: true
repository: lightseekorg/smg
labels:
- k8s-runner-cpu
serviceAccountName: arc-runner-sa

containers:
- name: runner
image: fra.ocir.io/idqj093njucb/action-runner:v0.0.1
resources:
requests:
cpu: "8"
memory: "16Gi"
limits:
cpu: "8"
memory: "16Gi"
env:
- name: HF_TOKEN
valueFrom:
secretKeyRef:
key: HUGGINGFACE_API_KEY
name: huggingface-secret
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
key: OPENAI_API_KEY
name: openai-api-key
- name: ANTHROPIC_API_KEY
valueFrom:
secretKeyRef:
key: ANTHROPIC_API_KEY
name: anthropic-api-key
- name: XAI_API_KEY
valueFrom:
secretKeyRef:
key: XAI_API_KEY
name: xai-api-key
- name: docker
image: fra.ocir.io/idqj093njucb/docker:dind

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The Docker-in-Docker (dind) configuration for the CPU runner is incomplete. The runner container is missing the DOCKER_HOST environment variable and volume mounts for the Docker socket. The docker sidecar is missing the privileged security context, resource definitions, and volume mounts required for it to function correctly. Additionally, the DOCKER_TLS_CERTDIR environment variable must be set to an empty string in the docker sidecar to disable TLS for the Docker socket, which is necessary for DinD setups. This will cause any Docker operations in workflows on this runner to fail. The configuration should be updated to properly set up the dind sidecar and the communication between the two containers, similar to the GPU runner definitions.

    spec:
      ephemeral: true
      repository: lightseekorg/smg
      labels:
        - k8s-runner-cpu
      serviceAccountName: arc-runner-sa

      volumes:
        - name: docker-sock
          emptyDir: {}
        - name: docker-storage
          emptyDir: {}

      containers:
        - name: runner
          image: fra.ocir.io/idqj093njucb/action-runner:v0.0.1
          resources:
            requests:
              cpu: "8"
              memory: "16Gi"
            limits:
              cpu: "8"
              memory: "16Gi"
          volumeMounts:
            - name: docker-sock
              mountPath: /var/run
          env:
            - name: DOCKER_HOST
              value: unix:///var/run/docker.sock
            - name: HF_TOKEN
              valueFrom:
                secretKeyRef:
                  key: HUGGINGFACE_API_KEY
                  name: huggingface-secret
            - name: OPENAI_API_KEY
              valueFrom:
                secretKeyRef:
                  key: OPENAI_API_KEY
                  name: openai-api-key
            - name: ANTHROPIC_API_KEY
              valueFrom:
                secretKeyRef:
                  key: ANTHROPIC_API_KEY
                  name: anthropic-api-key
            - name: XAI_API_KEY
              valueFrom:
                secretKeyRef:
                  key: XAI_API_KEY
                  name: xai-api-key
        - name: docker
          image: fra.ocir.io/idqj093njucb/docker:dind
          securityContext:
            privileged: true
          resources:
            requests:
              cpu: "1"
              memory: "2Gi"
            limits:
              cpu: "2"
              memory: "4Gi"
          env:
            - name: DOCKER_TLS_CERTDIR
              value: ""
            - name: DOCKER_DRIVER
              value: overlay2
          volumeMounts:
            - name: docker-sock
              mountPath: /var/run
            - name: docker-storage
              mountPath: /var/lib/docker
References
  1. When using a Docker-in-Docker (DinD) setup, it is necessary to disable TLS for the Docker socket by setting the DOCKER_TLS_CERTDIR environment variable to an empty string.

Comment on lines +168 to +215
containers:
- name: runner
image: fra.ocir.io/idqj093njucb/action-runner:v0.0.1
resources:
limits:
nvidia.com/gpu: 4
volumeMounts:
- name: model-cache
mountPath: /models
- name: docker-sock
mountPath: /var/run
- name: dshm
mountPath: /dev/shm
env:
- name: DOCKER_HOST
value: unix:///var/run/docker.sock
- name: HF_TOKEN
valueFrom:
secretKeyRef:
key: HUGGINGFACE_API_KEY
name: huggingface-secret
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
key: OPENAI_API_KEY
name: openai-api-key
- name: ANTHROPIC_API_KEY
valueFrom:
secretKeyRef:
key: ANTHROPIC_API_KEY
name: anthropic-api-key
- name: XAI_API_KEY
valueFrom:
secretKeyRef:
key: XAI_API_KEY
name: xai-api-key
- name: docker
image: fra.ocir.io/idqj093njucb/docker:dind
securityContext:
privileged: true # Required for DinD
env:
- name: DOCKER_TLS_CERTDIR
value: "" # Disables TLS for shared socket use
volumeMounts:
- name: docker-sock
mountPath: /var/run
- name: docker-storage
mountPath: /var/lib/docker

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The arc-runner-gpu-a10 deployment is missing CPU and memory resource requests and limits for both the runner and docker containers. Additionally, for the docker sidecar, the DOCKER_TLS_CERTDIR environment variable must be set to an empty string to disable TLS for the Docker socket, which is necessary for DinD setups. This results in a lower Quality of Service (QoS) class, making the pods more likely to be evicted under node pressure. It is a best practice to explicitly define resources for all containers to ensure predictable performance and scheduling.

      containers:
        - name: runner
          image: fra.ocir.io/idqj093njucb/action-runner:v0.0.1
          resources:
            requests:
              cpu: "16"
              memory: "64Gi"
            limits:
              cpu: "16"
              memory: "64Gi"
              nvidia.com/gpu: 4
          volumeMounts:
            - name: model-cache
              mountPath: /models
            - name: docker-sock
              mountPath: /var/run
            - name: dshm
              mountPath: /dev/shm
          env:
            - name: DOCKER_HOST
              value: unix:///var/run/docker.sock
            - name: HF_TOKEN
              valueFrom:
                secretKeyRef:
                  key: HUGGINGFACE_API_KEY
                  name: huggingface-secret
            - name: OPENAI_API_KEY
              valueFrom:
                secretKeyRef:
                  key: OPENAI_API_KEY
                  name: openai-api-key
            - name: ANTHROPIC_API_KEY
              valueFrom:
                secretKeyRef:
                  key: ANTHROPIC_API_KEY
                  name: anthropic-api-key
            - name: XAI_API_KEY
              valueFrom:
                secretKeyRef:
                  key: XAI_API_KEY
                  name: xai-api-key
        - name: docker
          image: fra.ocir.io/idqj093njucb/docker:dind
          securityContext:
            privileged: true  # Required for DinD
          resources:
            requests:
              cpu: "1"
              memory: "2Gi"
            limits:
              cpu: "2"
              memory: "4Gi"
          env:
            - name: DOCKER_TLS_CERTDIR
              value: ""  # Disables TLS for shared socket use
            - name: DOCKER_DRIVER
              value: overlay2
          volumeMounts:
            - name: docker-sock
              mountPath: /var/run
            - name: docker-storage
              mountPath: /var/lib/docker
References
  1. When using a Docker-in-Docker (DinD) setup, it is necessary to disable TLS for the Docker socket by setting the DOCKER_TLS_CERTDIR environment variable to an empty string.

Comment on lines +25 to +27
- pods
- pods/log
- pods/exec

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The Role for the runner pods grants permissions for pods/log and pods/exec. This is overly permissive and violates the principle of least privilege. A standard runner pod does not need to execute commands in or view logs of other pods. These permissions could be abused if a workflow is compromised and should be removed to enhance security.

      - pods

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/k8s-runner-resources/arc-runner-autoscaler.yaml`:
- Around line 104-109: The PercentageRunnersBusy metric configuration uses scale
factors that decrease capacity on scale-up; update the metric block (metrics /
type: PercentageRunnersBusy) so that scaleUpFactor is greater than 1 (e.g.,
"1.4" or "1.5") to increase runners when busy and scaleDownFactor remains less
than 1 (e.g., "0.7") to reduce runners when underutilized, keeping the existing
thresholds (scaleUpThreshold and scaleDownThreshold) as-is.

In `@scripts/k8s-runner-resources/arc-runner-cpu.yaml`:
- Around line 47-48: The docker sidecar container (name: docker) is missing
critical DinD configuration: add securityContext.privileged: true to the docker
container, add volumeMounts for the docker socket and storage (mounts named
docker-sock and docker-storage) and ensure matching volumes are defined at the
pod level, add environment variables DOCKER_TLS_CERTDIR (empty string) and
DOCKER_DRIVER (e.g., overlay2) to the docker container, and add appropriate
resources.requests and resources.limits (cpu/memory) similar to the GPU runner's
docker sidecar so DinD can run properly and the runner can access the
socket/storage.
- Around line 16-48: The CPU deployment is missing the Docker socket and related
volumes/volumeMounts so the runner container cannot talk to the dind container;
add a top-level volumes block defining docker-sock (hostPath
/var/run/docker.sock), docker-storage (emptyDir) and dshm (emptyDir with medium:
Memory) and update the runner container (name: runner) to include volumeMounts
for docker-sock (mountPath: /var/run/docker.sock), docker-storage (mountPath:
/var/lib/docker) and dshm (mountPath: /dev/shm); ensure the dind container
(name: docker) also mounts those same volumes so DOCKER_HOST:
unix:///var/run/docker.sock works correctly.

In `@scripts/k8s-runner-resources/arc-runner-gpu.yaml`:
- Around line 168-215: The arc-runner-gpu-a10 deployment is missing resource
requests for the runner container, resources for the docker sidecar, and a
memory-backed docker-storage volume; update the YAML to match other GPU
deployments by adding a resources block to the runner container (keep
limits.nvidia.com/gpu: 4 and add cpu and memory requests and limits), add a
resources.requests/limits block to the docker sidecar container (name: docker)
similar to other DinD sidecars, and change the docker-storage volume definition
(name: docker-storage) to an emptyDir with medium: Memory and sizeLimit: 4Gi to
make it memory-backed. Ensure you modify the runner and docker container specs
and the docker-storage volume declaration accordingly.

In `@scripts/k8s-runner-resources/arc-runner-rbac.yaml`:
- Around line 13-20: Replace the misleading "# Argo Workflows" comment above the
RBAC block with an accurate label for ARC/GitHub Actions runners (e.g., "#
Actions Runner Controller (ARC) Runners" or "# ARC runners") so the comment
correctly reflects the RBAC purpose; update the comment that immediately
precedes the secrets resource block (the line containing "# Argo Workflows") to
the new text in the same location.
- Around line 22-31: The RBAC rule for the Pods resource includes the pods/exec
subresource but only grants read verbs (get, list, watch), which prevents exec
operations; update the verbs array for the Pods rule that lists "pods" and
"pods/exec" to include "create" if runners should be able to exec into pods, or
add a clear inline comment next to the resources/verbs block (referencing the
Pods rule and the "pods/exec" entry) stating the intent is read-only and that
"create" was intentionally omitted.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d7c51f99-fc49-4531-b171-992bec599165

📥 Commits

Reviewing files that changed from the base of the PR and between 7f54c64 and 070ea73.

📒 Files selected for processing (5)
  • scripts/k8s-runner-resources/README.md
  • scripts/k8s-runner-resources/arc-runner-autoscaler.yaml
  • scripts/k8s-runner-resources/arc-runner-cpu.yaml
  • scripts/k8s-runner-resources/arc-runner-gpu.yaml
  • scripts/k8s-runner-resources/arc-runner-rbac.yaml

Comment on lines +104 to +109
metrics:
- type: PercentageRunnersBusy
scaleUpThreshold: "0.95"
scaleDownThreshold: "0.25"
scaleUpFactor: "0.5"
scaleDownFactor: "0.5"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

actions-runner-controller PercentageRunnersBusy scaleUpFactor scaleDownFactor configuration

💡 Result:

In Actions Runner Controller (ARC), PercentageRunnersBusy is a HorizontalRunnerAutoscaler.spec.metrics[].type that scales a RunnerDeployment based on the percentage of runners currently busy (running jobs). ARC queries GitHub for the number of busy runners in the RunnerDeployment’s namespace, then adjusts the desired replica count when thresholds are crossed. [1]

Example configuration

apiVersion: actions.summerwind.dev/v1alpha1
kind: HorizontalRunnerAutoscaler
spec:
  scaleTargetRef:
    name: example-runner-deployment
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: PercentageRunnersBusy
    scaleUpThreshold: "0.75"
    scaleDownThreshold: "0.30"
    scaleUpFactor: "1.4"
    scaleDownFactor: "0.7"

[1][2]

What the fields mean (for PercentageRunnersBusy)

  • scaleUpThreshold: if % busy is greater than this value, ARC re-evaluates desired runners to scale up. [2]
  • scaleDownThreshold: if % busy is less than this value, ARC re-evaluates desired runners to scale down. [2][3]
  • scaleUpFactor: multiplier applied to the current runner count to compute the new desired count on scale-up (e.g., 10 → 10 * 1.4 → 14). [1][2]
  • scaleDownFactor: multiplier applied to the current runner count to compute the new desired count on scale-down (e.g., 10 → 10 * 0.7 → 7). [1][2]

Notes:

  • You typically pair these with minReplicas / maxReplicas bounds. [1]
  • ARC supports either factor-based scaling (scaleUpFactor/scaleDownFactor) or step-based scaling (scaleUpAdjustment/scaleDownAdjustment) for a metric (not both). [3]

Sources:
[1] ARC docs (actions.github.io/actions-runner-controller)
[2] ARC API docs on pkg.go.dev (actions-runner-controller)
[3] HorizontalRunnerAutoscalerMetrics docs (docs.rs)


Correct scaleUpFactor and scaleDownFactor values for PercentageRunnersBusy metric.

The format of scaleUpFactor: "0.5" and scaleDownFactor: "0.5" as strings is correct, but the values are problematic. These fields are multipliers applied to the current runner count:

  • When scaleUpThreshold: "0.95" is exceeded (≥95% runners busy), the system applies scaleUpFactor: "0.5", which reduces the runner count to 50% of current (e.g., 4 → 2 runners). This is the opposite of the intended behavior—you should add runners when they are busy, not remove them.
  • Similarly, scaleDownFactor: "0.5" also reduces runners, making both directions reduce capacity.

Use a factor greater than 1 for scaleUpFactor (e.g., "1.5" or "1.4") to increase runners, and keep scaleDownFactor less than 1 (e.g., "0.7") to decrease runners during low usage.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/arc-runner-autoscaler.yaml` around lines 104 -
109, The PercentageRunnersBusy metric configuration uses scale factors that
decrease capacity on scale-up; update the metric block (metrics / type:
PercentageRunnersBusy) so that scaleUpFactor is greater than 1 (e.g., "1.4" or
"1.5") to increase runners when busy and scaleDownFactor remains less than 1
(e.g., "0.7") to reduce runners when underutilized, keeping the existing
thresholds (scaleUpThreshold and scaleDownThreshold) as-is.

Comment on lines +16 to +48
containers:
- name: runner
image: fra.ocir.io/idqj093njucb/action-runner:v0.0.1
resources:
requests:
cpu: "8"
memory: "16Gi"
limits:
cpu: "8"
memory: "16Gi"
env:
- name: HF_TOKEN
valueFrom:
secretKeyRef:
key: HUGGINGFACE_API_KEY
name: huggingface-secret
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
key: OPENAI_API_KEY
name: openai-api-key
- name: ANTHROPIC_API_KEY
valueFrom:
secretKeyRef:
key: ANTHROPIC_API_KEY
name: anthropic-api-key
- name: XAI_API_KEY
valueFrom:
secretKeyRef:
key: XAI_API_KEY
name: xai-api-key
- name: docker
image: fra.ocir.io/idqj093njucb/docker:dind

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Missing volumes and volume mounts for Docker socket sharing.

The runner container references DOCKER_HOST: unix:///var/run/docker.sock in GPU deployments, but this CPU deployment is missing:

  1. The volumes section entirely (no docker-sock, docker-storage, dshm volumes)
  2. Volume mounts in the runner container

Without shared volumes, the runner and DinD containers cannot communicate.

Proposed fix to add volumes section
       serviceAccountName: arc-runner-sa
+
+      volumes:
+        - name: docker-sock
+          emptyDir: {}
+        - name: docker-storage
+          emptyDir:
+            medium: Memory
+            sizeLimit: 4Gi
 
       containers:
         - name: runner
           image: fra.ocir.io/idqj093njucb/action-runner:v0.0.1
           resources:
             requests:
               cpu: "8"
               memory: "16Gi"
             limits:
               cpu: "8"
               memory: "16Gi"
+          volumeMounts:
+            - name: docker-sock
+              mountPath: /var/run
           env:
+            - name: DOCKER_HOST
+              value: unix:///var/run/docker.sock
             - name: HF_TOKEN
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/arc-runner-cpu.yaml` around lines 16 - 48, The
CPU deployment is missing the Docker socket and related volumes/volumeMounts so
the runner container cannot talk to the dind container; add a top-level volumes
block defining docker-sock (hostPath /var/run/docker.sock), docker-storage
(emptyDir) and dshm (emptyDir with medium: Memory) and update the runner
container (name: runner) to include volumeMounts for docker-sock (mountPath:
/var/run/docker.sock), docker-storage (mountPath: /var/lib/docker) and dshm
(mountPath: /dev/shm); ensure the dind container (name: docker) also mounts
those same volumes so DOCKER_HOST: unix:///var/run/docker.sock works correctly.

Comment on lines +47 to +48
- name: docker
image: fra.ocir.io/idqj093njucb/docker:dind

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Docker-in-Docker sidecar is missing critical configuration.

The docker container is incomplete compared to the GPU runner manifests. It's missing:

  • securityContext.privileged: true (required for DinD)
  • Volume mounts for docker-sock and docker-storage
  • Environment variables (DOCKER_TLS_CERTDIR, DOCKER_DRIVER)
  • Resource requests/limits

Without these, the DinD sidecar will fail to function, and the runner container won't be able to use Docker.

Proposed fix based on GPU runner configuration
         - name: docker
           image: fra.ocir.io/idqj093njucb/docker:dind
+          securityContext:
+            privileged: true  # Required for DinD
+          resources:
+            requests:
+              cpu: "1"
+              memory: "2Gi"
+            limits:
+              cpu: "2"
+              memory: "4Gi"
+          env:
+            - name: DOCKER_TLS_CERTDIR
+              value: ""  # Disables TLS for shared socket use
+            - name: DOCKER_DRIVER
+              value: overlay2
+          volumeMounts:
+            - name: docker-sock
+              mountPath: /var/run
+            - name: docker-storage
+              mountPath: /var/lib/docker
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/arc-runner-cpu.yaml` around lines 47 - 48, The
docker sidecar container (name: docker) is missing critical DinD configuration:
add securityContext.privileged: true to the docker container, add volumeMounts
for the docker socket and storage (mounts named docker-sock and docker-storage)
and ensure matching volumes are defined at the pod level, add environment
variables DOCKER_TLS_CERTDIR (empty string) and DOCKER_DRIVER (e.g., overlay2)
to the docker container, and add appropriate resources.requests and
resources.limits (cpu/memory) similar to the GPU runner's docker sidecar so DinD
can run properly and the runner can access the socket/storage.

Comment on lines +168 to +215
containers:
- name: runner
image: fra.ocir.io/idqj093njucb/action-runner:v0.0.1
resources:
limits:
nvidia.com/gpu: 4
volumeMounts:
- name: model-cache
mountPath: /models
- name: docker-sock
mountPath: /var/run
- name: dshm
mountPath: /dev/shm
env:
- name: DOCKER_HOST
value: unix:///var/run/docker.sock
- name: HF_TOKEN
valueFrom:
secretKeyRef:
key: HUGGINGFACE_API_KEY
name: huggingface-secret
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
key: OPENAI_API_KEY
name: openai-api-key
- name: ANTHROPIC_API_KEY
valueFrom:
secretKeyRef:
key: ANTHROPIC_API_KEY
name: anthropic-api-key
- name: XAI_API_KEY
valueFrom:
secretKeyRef:
key: XAI_API_KEY
name: xai-api-key
- name: docker
image: fra.ocir.io/idqj093njucb/docker:dind
securityContext:
privileged: true # Required for DinD
env:
- name: DOCKER_TLS_CERTDIR
value: "" # Disables TLS for shared socket use
volumeMounts:
- name: docker-sock
mountPath: /var/run
- name: docker-storage
mountPath: /var/lib/docker

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Inconsistent configuration in arc-runner-gpu-a10 deployment.

This deployment differs from the other GPU deployments in several ways:

  1. Missing runner container resource requests (lines 171-173): Only limits.nvidia.com/gpu is specified; no CPU/memory requests like other deployments have.
  2. Missing docker container resources (lines 204-215): No resource requests/limits for the DinD sidecar.
  3. docker-storage volume not memory-backed (lines 161-162): Other deployments use medium: Memory with sizeLimit: 4Gi.

These inconsistencies may cause scheduling issues or resource contention.

Proposed fix to align with other GPU deployments
       containers:
         - name: runner
           image: fra.ocir.io/idqj093njucb/action-runner:v0.0.1
           resources:
+            requests:
+              cpu: "32"
+              memory: "128Gi"
             limits:
               nvidia.com/gpu: 4
         - name: docker-storage
-          emptyDir: {}
+          emptyDir:
+            medium: Memory
+            sizeLimit: 4Gi
         - name: docker
           image: fra.ocir.io/idqj093njucb/docker:dind
           securityContext:
             privileged: true  # Required for DinD
+          resources:
+            requests:
+              cpu: "1"
+              memory: "2Gi"
+            limits:
+              cpu: "2"
+              memory: "4Gi"
           env:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/arc-runner-gpu.yaml` around lines 168 - 215, The
arc-runner-gpu-a10 deployment is missing resource requests for the runner
container, resources for the docker sidecar, and a memory-backed docker-storage
volume; update the YAML to match other GPU deployments by adding a resources
block to the runner container (keep limits.nvidia.com/gpu: 4 and add cpu and
memory requests and limits), add a resources.requests/limits block to the docker
sidecar container (name: docker) similar to other DinD sidecars, and change the
docker-storage volume definition (name: docker-storage) to an emptyDir with
medium: Memory and sizeLimit: 4Gi to make it memory-backed. Ensure you modify
the runner and docker container specs and the docker-storage volume declaration
accordingly.

Comment on lines +22 to +31
# Pods
- apiGroups: [""]
resources:
- pods
- pods/log
- pods/exec
verbs:
- get
- list
- watch

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if other runner RBAC files in the repo grant create verb for pods/exec
rg -n "pods/exec" --type yaml -A 5 -B 2

Repository: lightseekorg/smg

Length of output: 585


🌐 Web query:

Kubernetes RBAC pods/exec create verb permission required

💡 Result:

To allow kubectl exec via Kubernetes RBAC, you must grant the create verb on the pods/exec subresource (core API group ""). [1], [2]

Typical minimal Role rules (namespace-scoped):

rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get"]          # kubectl commonly reads the Pod first
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create"]       # required for exec (kubectl uses POST -> RBAC "create")

Note: some client libraries negotiate exec using an HTTP GET first (e.g., WebSocket), in which case you may also need verbs: ["get","create"] on pods/exec. [2]

Quick check:

  • kubectl auth can-i create pods/exec -n <ns> [3]

Sources:
[1] Kubernetes RBAC docs (subresources via resource/subresource) https://kubernetes.io/docs/reference/access-authn-authz/rbac/
[2] Stack Overflow: kubectl exec requires create on pods/exec (and sometimes get) https://stackoverflow.com/questions/48118125/kubernetes-rbac-role-verbs-to-exec-to-pod
[3] Kubenomicon: kubectl auth can-i create pods/exec https://kubenomicon.com/Execution/Exec_inside_container.html


🏁 Script executed:

#!/bin/bash
# Check if there's any documentation in the repo about this RBAC config
find . -type f \( -name "*.md" -o -name "*.txt" -o -name "README*" \) | xargs grep -l "rbac\|pods/exec" 2>/dev/null || echo "No documentation found"

# Also check if there are comments in the RBAC file itself
head -50 scripts/k8s-runner-resources/arc-runner-rbac.yaml

Repository: lightseekorg/smg

Length of output: 1024


🏁 Script executed:

#!/bin/bash
# Check the README for context about the runner RBAC requirements
cat scripts/k8s-runner-resources/README.md

Repository: lightseekorg/smg

Length of output: 6147


Add create verb to pods/exec or clarify intent with a comment.

Kubernetes RBAC requires the create verb on the pods/exec subresource to enable actual pod exec operations. The current permissions grant only get, list, and watch verbs, which are insufficient for exec functionality. Either add create to the verbs list if runners need to exec into pods, or add an inline comment explaining that this is intentionally limited to read-only access.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/arc-runner-rbac.yaml` around lines 22 - 31, The
RBAC rule for the Pods resource includes the pods/exec subresource but only
grants read verbs (get, list, watch), which prevents exec operations; update the
verbs array for the Pods rule that lists "pods" and "pods/exec" to include
"create" if runners should be able to exec into pods, or add a clear inline
comment next to the resources/verbs block (referencing the Pods rule and the
"pods/exec" entry) stating the intent is read-only and that "create" was
intentionally omitted.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 070ea73062

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +47 to +48
- name: docker
image: fra.ocir.io/idqj093njucb/docker:dind

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Configure DinD sidecar for CPU RunnerDeployment

This RunnerDeployment adds a docker:dind sidecar but does not wire it up for usable Docker access from the runner (no shared /var/run volume, no privileged DinD setup, and no runner-side Docker endpoint wiring). In workflows that run on k8s-runner-cpu and invoke Docker (for example container actions or docker build), jobs will fail because the runner cannot reach a functional daemon.

Useful? React with 👍 / 👎.

Comment on lines +28 to +31
verbs:
- get
- list
- watch

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Grant create on pods/exec in runner Role

The Role includes pods/exec but only grants get, list, and watch; exec requests are authorized via the create verb on the pods/exec subresource. As written, any workflow step that uses kubectl exec from these runners will get RBAC forbidden errors even though exec access appears intended.

Useful? React with 👍 / 👎.

@CatherineSue

Copy link
Copy Markdown
Member

What about the old files using the github CRD? should we remove them?

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (3)
scripts/k8s-runner-resources/arc-runner-autoscaler.yaml (1)

104-109: ⚠️ Potential issue | 🔴 Critical

Fix the CPU scale-up factor.

On Lines 106-109, scaleUpFactor: "0.5" halves the pool when busy instead of adding runners, so the CPU HRA cannot scale out under load.

Minimal patch
   metrics:
     - type: PercentageRunnersBusy
       scaleUpThreshold: "0.95"
       scaleDownThreshold: "0.25"
-      scaleUpFactor: "0.5"
+      scaleUpFactor: "1.5"
       scaleDownFactor: "0.5"
In `actions-runner-controller` `HorizontalRunnerAutoscaler` with metric `PercentageRunnersBusy`, how are `scaleUpFactor` and `scaleDownFactor` applied? Must `scaleUpFactor` be greater than 1 to increase replicas?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/arc-runner-autoscaler.yaml` around lines 104 -
109, The HorizontalRunnerAutoscaler metric block using PercentageRunnersBusy has
the scaleUpFactor set to "0.5", which decreases replicas when busy; change
scaleUpFactor to a value greater than 1 (for example "1.5") so that the
autoscaler increases replicas under load; update the metrics entry that contains
PercentageRunnersBusy (the scaleUpFactor and optionally scaleDownFactor fields)
to use the correct >1 scaleUpFactor to enable scale-out.
scripts/k8s-runner-resources/arc-runner-gpu.yaml (1)

174-224: ⚠️ Potential issue | 🟠 Major

Bring arc-runner-gpu-a10 back in line with the other GPU pools.

On Lines 177-182, the runner requests only ephemeral storage, so CPU and memory are left unreserved, and on Lines 213-224 the DinD sidecar has no resource envelope at all. The other GPU RunnerDeployments pin those values, so this pool will schedule and behave differently under load.

#!/bin/bash
set -euo pipefail

python -m pip install --quiet pyyaml >/dev/null 2>&1

python - <<'PY'
import yaml
from pathlib import Path

docs = [d for d in yaml.safe_load_all(Path("scripts/k8s-runner-resources/arc-runner-gpu.yaml").read_text()) if d]

for name in ("arc-runner-4-gpu-h100", "arc-runner-gpu-a10"):
    doc = next(d for d in docs if d["metadata"]["name"] == name)
    spec = doc["spec"]["template"]["spec"]
    print(f"\n{name}")
    for c in spec["containers"]:
        print(c["name"], {
            "requests": c.get("resources", {}).get("requests"),
            "limits": c.get("resources", {}).get("limits"),
            "env": [e["name"] for e in c.get("env", [])],
        })
PY
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/arc-runner-gpu.yaml` around lines 174 - 224, The
"arc-runner-gpu-a10" Deployment's runner container only requests
ephemeral-storage and omits CPU/memory requests/limits, and the docker sidecar
has no resources at all; update the containers named "runner" and "docker" to
include the same resources.requests and resources.limits entries used by the
other GPU pools (add CPU and memory request/limit values alongside
ephemeral-storage and keep nvidia.com/gpu in limits for "runner"), modifying the
resources block under each container (resources.requests and resources.limits)
so both containers have explicit CPU and memory reservations and limits to match
the other GPU RunnerDeployments.
scripts/k8s-runner-resources/arc-runner-cpu.yaml (1)

14-48: ⚠️ Potential issue | 🔴 Critical

Wire the CPU runner to a real DinD socket.

On Lines 16-48, this pod adds a docker sidecar but never defines shared /var/run or /var/lib/docker volumes, and the sidecar on Line 47 is missing the privileged/resource setup used in arc-runner-gpu.yaml. As written, the runner container has no path to a working Docker daemon, so Docker-based jobs on the CPU pool will fail.

#!/bin/bash
set -euo pipefail

python -m pip install --quiet pyyaml >/dev/null 2>&1

python - <<'PY'
import yaml
from pathlib import Path

targets = [
    ("scripts/k8s-runner-resources/arc-runner-cpu.yaml", "arc-runner-cpu"),
    ("scripts/k8s-runner-resources/arc-runner-gpu.yaml", "arc-runner-4-gpu-h100"),
]

for file, name in targets:
    docs = [d for d in yaml.safe_load_all(Path(file).read_text()) if d]
    doc = next(d for d in docs if d["metadata"]["name"] == name)
    spec = doc["spec"]["template"]["spec"]
    print(f"\n{name}")
    print("volumes:", [v["name"] for v in spec.get("volumes", [])])
    for c in spec["containers"]:
        print(c["name"], {
            "mounts": [m["name"] for m in c.get("volumeMounts", [])],
            "privileged": c.get("securityContext", {}).get("privileged"),
            "env": [e["name"] for e in c.get("env", [])],
            "resources": c.get("resources"),
        })
PY
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/arc-runner-cpu.yaml` around lines 14 - 48, The
pod mounts for the Docker sidecar are missing so the runner cannot reach a
Docker daemon; add shared volumes (e.g., volume names docker-sock and
docker-graph) to the pod spec and mount them into both containers: mount
docker-sock at /var/run/docker.sock in the runner container and the docker
sidecar, and mount docker-graph at /var/lib/docker in both containers (use
emptyDir for graph storage or match arc-runner-gpu.yaml). Also update the docker
sidecar container "docker" to include the same securityContext.privileged: true
and the same resources (requests/limits) used in arc-runner-gpu.yaml so it runs
as DinD; ensure the runner container either has the socket mount or an
appropriate DOCKER_HOST env var to point to the sidecar.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/k8s-runner-resources/arc-runner-autoscaler.yaml`:
- Around line 14-17: The autoscalers all use the same repo-wide metric
TotalNumberOfQueuedAndInProgressWorkflowRuns for repository lightseekorg/smg,
causing unrelated GPU pools to scale; update each HRA block that references
TotalNumberOfQueuedAndInProgressWorkflowRuns to scope the metric to the intended
pool by adding workflowLabels (or repository/workflow selectors) that match the
target RunnerDeployment labels or use a metric that filters by runner labels, so
each autoscaler only observes queue depth for its specific RunnerDeployment;
locate the metric entries named TotalNumberOfQueuedAndInProgressWorkflowRuns and
replace or augment repositoryNames: - lightseekorg/smg with the appropriate
workflowLabels or label-based selector for the corresponding GPU pool.

In `@scripts/k8s-runner-resources/arc-runner-gpu.yaml`:
- Around line 237-239: The GPU runner pools are missing the shared label that
workflows expect; in each pool where labels currently contain entries like
"1-gpu-h100" and "1-gpu" (the label lists at the three GPU pools), add
"k8s-runner-gpu" to the labels array so workflows using runs-on: k8s-runner-gpu
can match these GPU-capable pools; update the label lists for the pools that
currently list "1-gpu-h100" / "1-gpu" (and the other two similar GPU pools) to
include "k8s-runner-gpu".

In `@scripts/k8s-runner-resources/arc-runner-rbac.yaml`:
- Around line 13-20: The Role for arc-runner-sa currently grants namespace-wide
secrets access; remove the entire secrets rule under arc-runner-sa (the
apiGroups: [""], resources: - secrets, verbs: - get - list - watch) or restrict
it to a minimal scoped rule: only "get" and list explicit resourceNames required
by the runner. Locate the Role/ClusterRole definition that mentions
arc-runner-sa in arc-runner-rbac.yaml and either delete that secrets stanza or
replace it with a single-verb "get" rule that enumerates the exact secret names
in resourceNames to avoid namespace-wide secret enumeration.

In `@scripts/k8s-runner-resources/README.md`:
- Around line 175-189: Update the "Apply Runner Resources" section to list the
required cluster prerequisites and/or split CPU/GPU steps: explicitly document
that the manifests (arc-runner-rbac.yaml, arc-runner-cpu.yaml,
arc-runner-gpu.yaml, arc-runner-autoscaler.yaml) require pre-created secrets
huggingface-secret, openai-api-key, anthropic-api-key, xai-api-key and that GPU
runners additionally require the model-cache PersistentVolumeClaim (model-cache
PVC); either add a prerequisites subsection with commands or links to create
those secrets/PVCs before running kubectl apply, or separate the CPU and GPU
apply instructions with the GPU block noting the model-cache PVC dependency.

---

Duplicate comments:
In `@scripts/k8s-runner-resources/arc-runner-autoscaler.yaml`:
- Around line 104-109: The HorizontalRunnerAutoscaler metric block using
PercentageRunnersBusy has the scaleUpFactor set to "0.5", which decreases
replicas when busy; change scaleUpFactor to a value greater than 1 (for example
"1.5") so that the autoscaler increases replicas under load; update the metrics
entry that contains PercentageRunnersBusy (the scaleUpFactor and optionally
scaleDownFactor fields) to use the correct >1 scaleUpFactor to enable scale-out.

In `@scripts/k8s-runner-resources/arc-runner-cpu.yaml`:
- Around line 14-48: The pod mounts for the Docker sidecar are missing so the
runner cannot reach a Docker daemon; add shared volumes (e.g., volume names
docker-sock and docker-graph) to the pod spec and mount them into both
containers: mount docker-sock at /var/run/docker.sock in the runner container
and the docker sidecar, and mount docker-graph at /var/lib/docker in both
containers (use emptyDir for graph storage or match arc-runner-gpu.yaml). Also
update the docker sidecar container "docker" to include the same
securityContext.privileged: true and the same resources (requests/limits) used
in arc-runner-gpu.yaml so it runs as DinD; ensure the runner container either
has the socket mount or an appropriate DOCKER_HOST env var to point to the
sidecar.

In `@scripts/k8s-runner-resources/arc-runner-gpu.yaml`:
- Around line 174-224: The "arc-runner-gpu-a10" Deployment's runner container
only requests ephemeral-storage and omits CPU/memory requests/limits, and the
docker sidecar has no resources at all; update the containers named "runner" and
"docker" to include the same resources.requests and resources.limits entries
used by the other GPU pools (add CPU and memory request/limit values alongside
ephemeral-storage and keep nvidia.com/gpu in limits for "runner"), modifying the
resources block under each container (resources.requests and resources.limits)
so both containers have explicit CPU and memory reservations and limits to match
the other GPU RunnerDeployments.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2a4ee299-4ccc-4a1c-83e7-47fdce08bcfe

📥 Commits

Reviewing files that changed from the base of the PR and between 070ea73 and 7f2a061.

📒 Files selected for processing (5)
  • scripts/k8s-runner-resources/README.md
  • scripts/k8s-runner-resources/arc-runner-autoscaler.yaml
  • scripts/k8s-runner-resources/arc-runner-cpu.yaml
  • scripts/k8s-runner-resources/arc-runner-gpu.yaml
  • scripts/k8s-runner-resources/arc-runner-rbac.yaml

Comment on lines +14 to +17
metrics:
- type: TotalNumberOfQueuedAndInProgressWorkflowRuns
repositoryNames:
- lightseekorg/smg

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

For actions-runner-controller/actions.summerwind.dev HorizontalRunnerAutoscaler, does the TotalNumberOfQueuedAndInProgressWorkflowRunsmetric filter by the targetRunnerDeployment labels, or does it count all queued/in-progress jobs for the listed repositories? If I create multiple HRAs for the same repository but different runner labels, will they all observe the same queue depth?

💡 Result:

The TotalNumberOfQueuedAndInProgressWorkflowRuns metric counts all queued and in-progress workflow runs across the specified repositoryNames in the HorizontalRunnerAutoscaler (HRA) spec. It does not filter by the labels of the target RunnerDeployment or RunnerSet. The metric polls GitHub's API for pending workflow runs against the listed repositories and uses this total to suggest desired replicas (up to maxReplicas), without considering which specific runners (identified by labels) those jobs are targeted to. If multiple HRAs are created for the same repository(ies) but target different RunnerDeployments with different runner labels, they will all observe the same queue depth because each HRA's metric calculation is independent and based solely on the repository-scoped workflow run counts from GitHub, not on label-matched jobs or current runner availability for those labels. Jobs queued for specific labels will only be assignable to matching runners, but the scaling decision doesn't filter the count by labels—leading to potential over-scaling across HRAs if not managed carefully (e.g., via unique repositories per HRA).

Citations:


All five GPU autoscalers will scale based on the same repo-wide queue metric, causing unrelated pools to scale unnecessarily.

The TotalNumberOfQueuedAndInProgressWorkflowRuns metric (lines 14–17, 32–35, 50–53, 68–71, 86–89) counts all queued and in-progress workflow runs across lightseekorg/smg without filtering by RunnerDeployment labels. Each GPU autoscaler observes the total repository queue depth and scales independently, so a single job queued for one GPU pool will trigger scale-up across all five pools.

Consider scoping each HRA to a dedicated repository, workflow label, or using a different metric that respects runner labels to prevent over-scaling.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/arc-runner-autoscaler.yaml` around lines 14 -
17, The autoscalers all use the same repo-wide metric
TotalNumberOfQueuedAndInProgressWorkflowRuns for repository lightseekorg/smg,
causing unrelated GPU pools to scale; update each HRA block that references
TotalNumberOfQueuedAndInProgressWorkflowRuns to scope the metric to the intended
pool by adding workflowLabels (or repository/workflow selectors) that match the
target RunnerDeployment labels or use a metric that filters by runner labels, so
each autoscaler only observes queue depth for its specific RunnerDeployment;
locate the metric entries named TotalNumberOfQueuedAndInProgressWorkflowRuns and
replace or augment repositoryNames: - lightseekorg/smg with the appropriate
workflowLabels or label-based selector for the corresponding GPU pool.

Comment on lines +237 to +239
labels:
- 1-gpu-h100
- 1-gpu

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

python -m pip install --quiet pyyaml >/dev/null 2>&1

python - <<'PY'
from pathlib import Path
import yaml

docs = [d for d in yaml.safe_load_all(Path("scripts/k8s-runner-resources/arc-runner-gpu.yaml").read_text()) if d]
print("Manifest labels:")
for doc in docs:
    print(f"  {doc['metadata']['name']}: {doc['spec']['template']['spec'].get('labels', [])}")

print("\nWorkflow runs-on labels:")
for path in sorted(Path(".github/workflows").rglob("*.y*ml")):
    data = yaml.safe_load(path.read_text()) or {}
    for job_name, job in (data.get("jobs") or {}).items():
        runs_on = job.get("runs-on")
        labels = runs_on if isinstance(runs_on, list) else [runs_on]
        labels = [label for label in labels if isinstance(label, str)]
        if any("gpu" in label or label.startswith("k8s-runner") for label in labels):
            print(f"  {path}:{job_name}: {labels}")
PY

Repository: lightseekorg/smg

Length of output: 1982


Add the shared k8s-runner-gpu label to all GPU runner pools to match workflow selectors.

The three pools at lines 237-239, 355-356, and 471-472 are missing the k8s-runner-gpu label that workflows explicitly request. Without it, jobs using runs-on: k8s-runner-gpu cannot schedule on these pools, even though they are GPU-capable.

Patch to add the missing label
       labels:
         - 1-gpu-h100
         - 1-gpu
+        - k8s-runner-gpu
@@
       labels:
         - 1-gpu
+        - k8s-runner-gpu
@@
       labels:
         - 2-gpu-h100
+        - k8s-runner-gpu
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
labels:
- 1-gpu-h100
- 1-gpu
labels:
- 1-gpu-h100
- 1-gpu
- k8s-runner-gpu
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/arc-runner-gpu.yaml` around lines 237 - 239, The
GPU runner pools are missing the shared label that workflows expect; in each
pool where labels currently contain entries like "1-gpu-h100" and "1-gpu" (the
label lists at the three GPU pools), add "k8s-runner-gpu" to the labels array so
workflows using runs-on: k8s-runner-gpu can match these GPU-capable pools;
update the label lists for the pools that currently list "1-gpu-h100" / "1-gpu"
(and the other two similar GPU pools) to include "k8s-runner-gpu".

Comment on lines +13 to +20
# Argo Workflows
- apiGroups: [""]
resources:
- secrets
verbs:
- get
- list
- watch

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

In Kubernetes, does a Pod that consumes a Secret via env.valueFrom.secretKeyRefor a Secret volume need the Pod's service account to have RBACget/list/watchpermissions on secrets? What is the security impact of granting a namespaced service accountget, list, and watch on all secrets in that namespace?

💡 Result:

No, a Pod that consumes a Secret via env.valueFrom.secretKeyRef or a Secret volume does not need the Pod's service account to have RBAC get/list/watch permissions on secrets. The kubelet fetches the Secret on behalf of the Pod using its own broad API permissions and mounts it into the container's filesystem or sets the environment variable during Pod startup. RBAC permissions on secrets control only direct API access from within the Pod (e.g., via kubectl or API clients), not the kubelet's mounting mechanism. Granting a namespaced service account get, list, and watch on all secrets in that namespace allows any application running in Pods using that service account to read the contents of all Secrets in the namespace via the Kubernetes API. This violates least privilege, enables compromised Pods to exfiltrate unrelated credentials (e.g., database passwords, API keys), and increases blast radius if the Pod is compromised. Official guidance recommends restricting such access, using resourceNames for specific secrets only, and preferring namespace isolation or external secret stores.

Citations:


Remove namespace-wide secret access from runner jobs.

Lines 13-20 grant arc-runner-sa unrestricted get/list/watch on all secrets in the actions-runner-system namespace. Every workflow pod using this service account can enumerate and read any secret in the namespace, including controller and API-key credentials. Pod secret consumption via secretKeyRef does not require the pod's service account to have RBAC permissions on secrets; the kubelet handles secret retrieval independently. Remove this rule entirely, or if the runner genuinely needs Kubernetes API access, scope it to explicit resourceNames with get only.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/arc-runner-rbac.yaml` around lines 13 - 20, The
Role for arc-runner-sa currently grants namespace-wide secrets access; remove
the entire secrets rule under arc-runner-sa (the apiGroups: [""], resources: -
secrets, verbs: - get - list - watch) or restrict it to a minimal scoped rule:
only "get" and list explicit resourceNames required by the runner. Locate the
Role/ClusterRole definition that mentions arc-runner-sa in arc-runner-rbac.yaml
and either delete that secrets stanza or replace it with a single-verb "get"
rule that enumerates the exact secret names in resourceNames to avoid
namespace-wide secret enumeration.

Comment on lines +175 to +189
### 4. Apply Runner Resources

```bash
# RBAC for runner pods
kubectl apply -f scripts/k8s-runner-resources/arc-runner-rbac.yaml

# CPU runner deployment
kubectl apply -f scripts/k8s-runner-resources/arc-runner-cpu.yaml

# GPU runner deployment
kubectl apply -f scripts/k8s-runner-resources/arc-runner-gpu.yaml

# Autoscaler
kubectl apply -f scripts/k8s-runner-resources/arc-runner-autoscaler.yaml
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Document the missing cluster prerequisites before kubectl apply.

On Lines 179-188, the referenced manifests depend on preexisting huggingface-secret, openai-api-key, anthropic-api-key, xai-api-key, and, for GPU runners, the model-cache PVC. A fresh install following this section will create RunnerDeployments that either stay Pending or fail to start. Please add those prerequisites here, or split the CPU/GPU steps so the dependency surface is explicit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/k8s-runner-resources/README.md` around lines 175 - 189, Update the
"Apply Runner Resources" section to list the required cluster prerequisites
and/or split CPU/GPU steps: explicitly document that the manifests
(arc-runner-rbac.yaml, arc-runner-cpu.yaml, arc-runner-gpu.yaml,
arc-runner-autoscaler.yaml) require pre-created secrets huggingface-secret,
openai-api-key, anthropic-api-key, xai-api-key and that GPU runners additionally
require the model-cache PersistentVolumeClaim (model-cache PVC); either add a
prerequisites subsection with commands or links to create those secrets/PVCs
before running kubectl apply, or separate the CPU and GPU apply instructions
with the GPU block noting the model-cache PVC dependency.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@github-actions github-actions Bot added grpc gRPC client and router changes model-gateway Model gateway crate changes labels Mar 24, 2026
@mergify

mergify Bot commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Hi @XinyueZhang369, the DCO sign-off check has failed. All commits must include a Signed-off-by line.

To fix existing commits:

# Sign off the last N commits (replace N with the number of unsigned commits)
git rebase HEAD~N --signoff
git push --force-with-lease

To sign off future commits automatically:

  • Use git commit -s every time, or
  • VSCode: enable Git: Always Sign Off in Settings
  • PyCharm: enable Sign-off commit in the Commit tool window

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
model_gateway/src/routers/grpc/harmony/stages/request_building.rs (1)

104-112: ⚠️ Potential issue | 🟠 Major

Keep Harmony stop-token injection in one layer.

These new arguments now conflict with the existing append step at Lines 226-257. On the Responses path, SGLang and vLLM already write harmony_stop_ids inside their builders, and this stage then appends the same prep.harmony_stop_ids again, so the final request carries duplicated Harmony stop IDs. TensorRT-LLM still ignores the extra parameter, so backend behavior has also become inconsistent.

Please pick a single owner for this wiring: either keep the stage-level injection and stop passing prep.harmony_stop_ids into the backend builders, or move the logic fully into each builder and delete the later append step.

Also applies to: 151-158, 197-204

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@model_gateway/src/routers/grpc/harmony/stages/request_building.rs` around
lines 104 - 112, The Responses branch is duplicating Harmony stop-token wiring:
you currently pass prep.harmony_stop_ids into
sglang_client.build_generate_request_from_responses (and analogous vLLM/TensorRT
builders) while the stage later re-appends prep.harmony_stop_ids, causing
duplicate IDs and inconsistent backend behavior; choose one owner—either stop
passing prep.harmony_stop_ids into the builders (remove the harmony_stop_ids
args from build_generate_request_from_responses and other builder calls like the
vLLM/TensorRT equivalents) so the stage append remains the single injection
point, or move injection entirely into each builder (keep the builder args and
delete the later append logic that mutates the request with
prep.harmony_stop_ids); update all affected paths (Responses and the other
mentioned request branches) consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@model_gateway/src/routers/grpc/harmony/stages/request_building.rs`:
- Around line 104-112: The Responses branch is duplicating Harmony stop-token
wiring: you currently pass prep.harmony_stop_ids into
sglang_client.build_generate_request_from_responses (and analogous vLLM/TensorRT
builders) while the stage later re-appends prep.harmony_stop_ids, causing
duplicate IDs and inconsistent backend behavior; choose one owner—either stop
passing prep.harmony_stop_ids into the builders (remove the harmony_stop_ids
args from build_generate_request_from_responses and other builder calls like the
vLLM/TensorRT equivalents) so the stage append remains the single injection
point, or move injection entirely into each builder (keep the builder args and
delete the later append logic that mutates the request with
prep.harmony_stop_ids); update all affected paths (Responses and the other
mentioned request branches) consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fcebbd40-98ee-4af5-a2dd-614fd791b0a9

📥 Commits

Reviewing files that changed from the base of the PR and between 7f2a061 and 45fc5d7.

📒 Files selected for processing (4)
  • crates/grpc_client/src/sglang_scheduler.rs
  • crates/grpc_client/src/trtllm_service.rs
  • crates/grpc_client/src/vllm_engine.rs
  • model_gateway/src/routers/grpc/harmony/stages/request_building.rs

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@github-actions github-actions Bot removed grpc gRPC client and router changes model-gateway Model gateway crate changes labels Mar 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/k8s-runner-resources/arc-runner-rbac.yaml`:
- Line 13: The comment "# Argo Workflows" is incorrect for this RBAC YAML;
locate the literal comment "# Argo Workflows" and replace it with a clear,
accurate comment like "# GitHub Actions runners RBAC" (or remove the comment
entirely) so the RBAC manifest reflects that it configures GitHub Actions runner
permissions rather than Argo Workflows.

In `@scripts/k8s-runner-resources/README.md`:
- Around line 145-157: Update the "Alternative: Using `actions.summerwind.dev`
ARC" section to explicitly distinguish the two ARC implementations: state that
the community controller (actions.summerwind.dev /
summerwind/actions-runner-controller) uses RunnerDeployment CRDs and the
community Helm chart, while the official GitHub ARC referenced earlier uses
GitHub's controller with runner scale sets; adjust the section title/link text
and descriptive lines to reference "RunnerDeployment CRDs" and "runner scale
sets" so readers clearly understand they are choosing between two different
implementations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2d88f2f0-6b07-4205-90b9-0c41514b0d61

📥 Commits

Reviewing files that changed from the base of the PR and between 45fc5d7 and 1281d26.

📒 Files selected for processing (5)
  • scripts/k8s-runner-resources/README.md
  • scripts/k8s-runner-resources/arc-runner-autoscaler.yaml
  • scripts/k8s-runner-resources/arc-runner-cpu.yaml
  • scripts/k8s-runner-resources/arc-runner-gpu.yaml
  • scripts/k8s-runner-resources/arc-runner-rbac.yaml

Comment thread scripts/k8s-runner-resources/arc-runner-rbac.yaml Outdated
Comment thread scripts/k8s-runner-resources/README.md
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

Signed-off-by: XinyueZhang369 <zoeyzhang369@gmail.com>
Signed-off-by: XinyueZhang369 <zoeyzhang369@gmail.com>
Signed-off-by: XinyueZhang369 <zoeyzhang369@gmail.com>
Signed-off-by: XinyueZhang369 <zoeyzhang369@gmail.com>
Signed-off-by: XinyueZhang369 <zoeyzhang369@gmail.com>
Signed-off-by: XinyueZhang369 <zoeyzhang369@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f4c59fa4b9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

- type: PercentageRunnersBusy
scaleUpThreshold: "0.95"
scaleDownThreshold: "0.25"
scaleUpFactor: "0.5"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Set CPU scaleUpFactor above 1 for busy-triggered growth

With PercentageRunnersBusy, scaleUpFactor is a multiplier on current replicas, so setting it to "0.5" causes the "scale up" path to reduce desired replicas instead of increasing them. In this config (minReplicas: 4), that means busy periods will keep being clamped back to 4 and the CPU runner pool will not scale out under load, which can stall queued CI jobs.

Useful? React with 👍 / 👎.

@XinyueZhang369

Copy link
Copy Markdown
Collaborator Author

What about the old files using the github CRD? should we remove them?

Thinking to keep them as another option to set up runners for some time in case we need it again, like after 2 ~ 3 weeks, the CI becomes pretty stable and we don't foresee any reason to replace current one, we can remove them

Signed-off-by: XinyueZhang369 <zoeyzhang369@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9366b81c8b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +118 to +121
volumeMounts:
- name: docker-sock
mountPath: /var/run
- name: docker-storage

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Mount runner workspace into DinD sidecar

The DinD sidecar is only given /var/run and /var/lib/docker, but not the runner workspace path (/home/runner/_work). With DOCKER_HOST pointing to this sidecar, bind mounts for container actions and jobs.container are resolved inside the daemon container; without a shared work volume, those mounts point to missing/empty paths and containerized workflow steps fail. The same mount pattern is repeated across the other RunnerDeployments in this file.

Useful? React with 👍 / 👎.

Comment on lines +15 to +17
- type: TotalNumberOfQueuedAndInProgressWorkflowRuns
repositoryNames:
- lightseekorg/smg

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use label-aware autoscaling for each runner pool

Each autoscaler is configured with TotalNumberOfQueuedAndInProgressWorkflowRuns on the same repository (lightseekorg/smg), which is repo-wide rather than runner-label specific. That means queue pressure from one workload class can scale unrelated RunnerDeployments (e.g., CPU backlog scaling H100 pools), causing unnecessary scale-outs and resource/cost churn. Consider a per-deployment signal such as PercentageRunnersBusy or splitting autoscaler scope.

Useful? React with 👍 / 👎.

@XinyueZhang369
XinyueZhang369 merged commit dcc2225 into main Mar 27, 2026
27 checks passed
@XinyueZhang369
XinyueZhang369 deleted the xz/runner-deployment branch March 27, 2026 00:03
smfirmin pushed a commit to smfirmin/smg that referenced this pull request Apr 2, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Jun 12, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants