Compare commits

...

11 Commits

Author SHA1 Message Date
Junya Okabe
13a03302c8 Add a flag for enabling pprof on the controller manager (#4449)
Some checks failed
Runner Updates Check (Scheduled Job) / update_version (push) Has been cancelled
(gha) E2E Tests / default-setup (push) Has been cancelled
(gha) E2E Tests / default-setup-v2 (push) Has been cancelled
(gha) E2E Tests / single-namespace-setup (push) Has been cancelled
(gha) E2E Tests / single-namespace-setup-v2 (push) Has been cancelled
(gha) E2E Tests / dind-mode-setup (push) Has been cancelled
(gha) E2E Tests / dind-mode-setup-v2 (push) Has been cancelled
(gha) E2E Tests / kubernetes-mode-setup (push) Has been cancelled
(gha) E2E Tests / kubernetes-mode-setup-v2 (push) Has been cancelled
(gha) E2E Tests / auth-proxy-setup (push) Has been cancelled
(gha) E2E Tests / auth-proxy-setup-v2 (push) Has been cancelled
(gha) E2E Tests / anonymous-proxy-setup (push) Has been cancelled
(gha) E2E Tests / anonymous-proxy-setup-v2 (push) Has been cancelled
(gha) E2E Tests / self-signed-ca-setup (push) Has been cancelled
(gha) E2E Tests / self-signed-ca-setup-v2 (push) Has been cancelled
(gha) E2E Tests / update-strategy-tests (push) Has been cancelled
(gha) E2E Tests / update-strategy-tests-v2 (push) Has been cancelled
(gha) E2E Tests / init-with-min-runners (push) Has been cancelled
(gha) E2E Tests / init-with-min-runners-v2 (push) Has been cancelled
Go / lint (push) Has been cancelled
Go / generate (push) Has been cancelled
Run CodeQL / Analyze (push) Has been cancelled
Go / fmt (push) Has been cancelled
(gha) Validate Helm Charts / Lint Chart (push) Has been cancelled
(gha) Validate Helm Charts / Test Chart (push) Has been cancelled
Publish Canary Images / Build and Publish Legacy Canary Image (push) Has been cancelled
Publish Canary Images / Build and Publish gha-runner-scale-set-controller Canary Image (push) Has been cancelled
Go / mocks (push) Has been cancelled
Go / test (push) Has been cancelled
Run Stale Bot / Run Stale (push) Has been cancelled
2026-04-24 10:03:26 +02:00
Junya Okabe
a401686bd5 Add option to disable workqueue bucket rate limiter (#4451) 2026-04-22 23:26:39 +02:00
github-actions[bot]
012f1a5b23 Updates: runner to v2.334.0 (#4467)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-22 17:26:50 +02:00
Gleb Khaykin
e0feb3b711 Fix orphan no-permission ServiceAccount in kubernetes-novolume mode (#4455) 2026-04-20 13:31:23 +02:00
Francesco Renzi
74cfc3855e Prepare 0.14.1 release (#4448)
Some checks failed
Validate Helm Chart / Lint Chart (push) Has been cancelled
(gha) Validate Helm Charts / Lint Chart (push) Has been cancelled
(gha) Validate Helm Charts / Test Chart (push) Has been cancelled
2026-04-14 17:03:22 +01:00
Francesco Renzi
eb1544f848 Bump actions/scaleset to v0.3.0 (#4447) 2026-04-14 14:08:22 +01:00
Nikola Jokic
79e7b17b56 Fix null field for resource metadata fields in experimental chart (#4419) 2026-04-02 23:44:37 +02:00
github-actions[bot]
39934ce5eb Updates: runner to v2.333.1 (#4427)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-31 19:35:28 -05:00
github-actions[bot]
5f4c132f12 Updates: runner to v2.333.0 (#4412)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-23 12:46:49 +01:00
Vinayak Gaikwad
0d1e2b3e74 remove redundant ticks around "name" and use plural (#3661) 2026-03-23 12:46:13 +01:00
Nikola Jokic
104bc6b0b0 Fix chart version for publishing (#4415) 2026-03-19 18:13:17 +00:00
23 changed files with 650 additions and 70 deletions

View File

@@ -6,7 +6,7 @@ endif
DOCKER_USER ?= $(shell echo ${DOCKER_IMAGE_NAME} | cut -d / -f1)
VERSION ?= dev
COMMIT_SHA = $(shell git rev-parse HEAD)
RUNNER_VERSION ?= 2.332.0
RUNNER_VERSION ?= 2.334.0
TARGETPLATFORM ?= $(shell arch)
RUNNER_NAME ?= ${DOCKER_USER}/actions-runner
RUNNER_TAG ?= ${VERSION}

View File

@@ -15,13 +15,13 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.14.0
version: "0.14.1"
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "0.14.0"
appVersion: "0.14.1"
home: https://github.com/actions/actions-runner-controller

View File

@@ -15,13 +15,13 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.14.0
version: 0.14.1
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "0.14.0"
appVersion: "0.14.1"
home: https://github.com/actions/actions-runner-controller

View File

@@ -84,6 +84,9 @@ spec:
- "--listener-metrics-endpoint="
- "--metrics-addr=0"
{{- end }}
{{- if .Values.pprof.addr }}
- "--pprof-addr={{ .Values.pprof.addr }}"
{{- end }}
{{- range .Values.flags.excludeLabelPropagationPrefixes }}
- "--exclude-label-propagation-prefix={{ . }}"
{{- end }}
@@ -93,14 +96,26 @@ spec:
{{- with .Values.flags.k8sClientRateLimiterBurst }}
- "--k8s-client-rate-limiter-burst={{ . }}"
{{- end }}
{{- with .Values.flags.rateLimiter }}
{{- with .name }}
- "--workqueue-rate-limiter={{ . }}"
{{- end }}
{{- end }}
command:
- "/manager"
{{- with .Values.metrics }}
{{- if or .Values.metrics .Values.pprof.addr }}
ports:
- containerPort: {{regexReplaceAll ":([0-9]+)" .controllerManagerAddr "${1}"}}
{{- end }}
{{- with .Values.metrics }}
- containerPort: {{ required "Values.metrics.controllerManagerAddr must end with a numeric port" (regexFind "[0-9]+$" .controllerManagerAddr) }}
protocol: TCP
name: metrics
{{- end }}
{{- if .Values.pprof.addr }}
- containerPort: {{ required "Values.pprof.addr must end with a numeric port" (regexFind "[0-9]+$" .Values.pprof.addr) }}
protocol: TCP
name: pprof
{{- end }}
env:
- name: CONTROLLER_MANAGER_CONTAINER_IMAGE
value: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"

View File

@@ -94,6 +94,10 @@ priorityClassName: ""
# listenerAddr: ":8080"
# listenerEndpoint: "/metrics"
## To enable pprof, uncomment the addr field below.
pprof: {}
# addr: ":6060"
flags:
## Log level can be set here with one of the following values: "debug", "info", "warn", "error".
## Defaults to "debug".
@@ -136,6 +140,13 @@ flags:
# excludeLabelPropagationPrefixes:
# - "argocd.argoproj.io/instance"
## Workqueue rate limiter configuration.
## By default, controller-runtime uses a combined rate limiter with both a per-item
## exponential backoff and an overall token bucket (10 QPS, 100 bucket size).
## Valid names: "bucket_rate_limiter" (default), "typed_rate_limiter" (per-item only, no global token bucket).
# rateLimiter:
# name: "bucket_rate_limiter"
# Overrides the default `.Release.Namespace` for all resources in this chart.
namespaceOverride: ""

View File

@@ -15,13 +15,13 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: "0.14.0"
version: "0.14.1"
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "0.14.0"
appVersion: "0.14.1"
home: https://github.com/actions/actions-runner-controller

View File

@@ -175,44 +175,68 @@ spec:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.resource.autoscalingListener.metadata }}
{{- $meta := .Values.resource.autoscalingListener.metadata | default dict }}
{{- $lbls := $meta.labels | default dict }}
{{- $anns := $meta.annotations | default dict }}
{{- if or (not (empty $lbls)) (not (empty $anns)) }}
autoscalingListener:
{{- include "autoscaling-runner-set.spec-resource-metadata" . | nindent 4 }}
{{- include "autoscaling-runner-set.spec-resource-metadata" $meta | nindent 4 }}
{{- end }}
{{- with .Values.resource.listenerServiceAccount.metadata }}
{{- $meta := .Values.resource.listenerServiceAccount.metadata | default dict }}
{{- $lbls := $meta.labels | default dict }}
{{- $anns := $meta.annotations | default dict }}
{{- if or (not (empty $lbls)) (not (empty $anns)) }}
listenerServiceAccountMetadata:
{{- include "autoscaling-runner-set.spec-resource-metadata" . | nindent 4 }}
{{- include "autoscaling-runner-set.spec-resource-metadata" $meta | nindent 4 }}
{{- end }}
{{- with .Values.resource.listenerRole.metadata }}
{{- $meta := .Values.resource.listenerRole.metadata | default dict }}
{{- $lbls := $meta.labels | default dict }}
{{- $anns := $meta.annotations | default dict }}
{{- if or (not (empty $lbls)) (not (empty $anns)) }}
listenerRoleMetadata:
{{- include "autoscaling-runner-set.spec-resource-metadata" . | nindent 4 }}
{{- include "autoscaling-runner-set.spec-resource-metadata" $meta | nindent 4 }}
{{- end }}
{{- with .Values.resource.listenerRoleBinding.metadata }}
{{- $meta := .Values.resource.listenerRoleBinding.metadata | default dict }}
{{- $lbls := $meta.labels | default dict }}
{{- $anns := $meta.annotations | default dict }}
{{- if or (not (empty $lbls)) (not (empty $anns)) }}
listenerRoleBindingMetadata:
{{- include "autoscaling-runner-set.spec-resource-metadata" . | nindent 4 }}
{{- include "autoscaling-runner-set.spec-resource-metadata" $meta | nindent 4 }}
{{- end }}
{{- with .Values.resource.listenerConfigSecret.metadata }}
{{- $meta := .Values.resource.listenerConfigSecret.metadata | default dict }}
{{- $lbls := $meta.labels | default dict }}
{{- $anns := $meta.annotations | default dict }}
{{- if or (not (empty $lbls)) (not (empty $anns)) }}
listenerConfigSecretMetadata:
{{- include "autoscaling-runner-set.spec-resource-metadata" . | nindent 4 }}
{{- include "autoscaling-runner-set.spec-resource-metadata" $meta | nindent 4 }}
{{- end }}
{{- with .Values.resource.ephemeralRunnerSet.metadata }}
{{- $meta := .Values.resource.ephemeralRunnerSet.metadata | default dict }}
{{- $lbls := $meta.labels | default dict }}
{{- $anns := $meta.annotations | default dict }}
{{- if or (not (empty $lbls)) (not (empty $anns)) }}
ephemeralRunnerSetMetadata:
{{- include "autoscaling-runner-set.spec-resource-metadata" . | nindent 4 }}
{{- include "autoscaling-runner-set.spec-resource-metadata" $meta | nindent 4 }}
{{- end }}
{{- with .Values.resource.ephemeralRunner.metadata }}
{{- $meta := .Values.resource.ephemeralRunner.metadata | default dict }}
{{- $lbls := $meta.labels | default dict }}
{{- $anns := $meta.annotations | default dict }}
{{- if or (not (empty $lbls)) (not (empty $anns)) }}
ephemeralRunnerMetadata:
{{- include "autoscaling-runner-set.spec-resource-metadata" . | nindent 4 }}
{{- include "autoscaling-runner-set.spec-resource-metadata" $meta | nindent 4 }}
{{- end }}
{{- with .Values.resource.ephemeralRunnerConfigSecret.metadata }}
{{- $meta := .Values.resource.ephemeralRunnerConfigSecret.metadata | default dict }}
{{- $lbls := $meta.labels | default dict }}
{{- $anns := $meta.annotations | default dict }}
{{- if or (not (empty $lbls)) (not (empty $anns)) }}
ephemeralRunnerConfigSecretMetadata:
{{- include "autoscaling-runner-set.spec-resource-metadata" . | nindent 4 }}
{{- include "autoscaling-runner-set.spec-resource-metadata" $meta | nindent 4 }}
{{- end }}
template:

View File

@@ -0,0 +1,432 @@
suite: "Test AutoscalingRunnerSet ResourceMeta Omission"
templates:
- autoscalingrunnserset.yaml
tests:
- it: should omit all ResourceMeta fields when metadata is empty
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- notExists:
path: spec.autoscalingListener
- notExists:
path: spec.listenerServiceAccountMetadata
- notExists:
path: spec.listenerRoleMetadata
- notExists:
path: spec.listenerRoleBindingMetadata
- notExists:
path: spec.listenerConfigSecretMetadata
- notExists:
path: spec.ephemeralRunnerSetMetadata
- notExists:
path: spec.ephemeralRunnerMetadata
- notExists:
path: spec.ephemeralRunnerConfigSecretMetadata
- it: should render autoscalingListener when labels are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
autoscalingListener:
metadata:
labels:
listener-key: "listener-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.autoscalingListener.labels.listener-key
value: "listener-value"
- notExists:
path: spec.listenerServiceAccountMetadata
- it: should render autoscalingListener when annotations are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
autoscalingListener:
metadata:
annotations:
listener-ann: "ann-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.autoscalingListener.annotations.listener-ann
value: "ann-value"
- notExists:
path: spec.listenerServiceAccountMetadata
- it: should render listenerServiceAccountMetadata when labels are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
listenerServiceAccount:
metadata:
labels:
sa-key: "sa-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.listenerServiceAccountMetadata.labels.sa-key
value: "sa-value"
- notExists:
path: spec.autoscalingListener
- notExists:
path: spec.listenerRoleMetadata
- it: should render listenerServiceAccountMetadata when annotations are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
listenerServiceAccount:
metadata:
annotations:
sa-ann: "ann-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.listenerServiceAccountMetadata.annotations.sa-ann
value: "ann-value"
- notExists:
path: spec.autoscalingListener
- it: should render listenerRoleMetadata when labels are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
listenerRole:
metadata:
labels:
role-key: "role-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.listenerRoleMetadata.labels.role-key
value: "role-value"
- notExists:
path: spec.autoscalingListener
- it: should render listenerRoleMetadata when annotations are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
listenerRole:
metadata:
annotations:
role-ann: "ann-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.listenerRoleMetadata.annotations.role-ann
value: "ann-value"
- it: should render listenerRoleBindingMetadata when labels are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
listenerRoleBinding:
metadata:
labels:
rolebinding-key: "rolebinding-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.listenerRoleBindingMetadata.labels.rolebinding-key
value: "rolebinding-value"
- it: should render listenerRoleBindingMetadata when annotations are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
listenerRoleBinding:
metadata:
annotations:
rolebinding-ann: "ann-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.listenerRoleBindingMetadata.annotations.rolebinding-ann
value: "ann-value"
- it: should render listenerConfigSecretMetadata when labels are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
listenerConfigSecret:
metadata:
labels:
secret-key: "secret-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.listenerConfigSecretMetadata.labels.secret-key
value: "secret-value"
- it: should render listenerConfigSecretMetadata when annotations are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
listenerConfigSecret:
metadata:
annotations:
secret-ann: "ann-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.listenerConfigSecretMetadata.annotations.secret-ann
value: "ann-value"
- it: should render ephemeralRunnerSetMetadata when labels are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
ephemeralRunnerSet:
metadata:
labels:
runner-set-key: "runner-set-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.ephemeralRunnerSetMetadata.labels.runner-set-key
value: "runner-set-value"
- it: should render ephemeralRunnerSetMetadata when annotations are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
ephemeralRunnerSet:
metadata:
annotations:
runner-set-ann: "ann-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.ephemeralRunnerSetMetadata.annotations.runner-set-ann
value: "ann-value"
- it: should render ephemeralRunnerMetadata when labels are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
ephemeralRunner:
metadata:
labels:
runner-key: "runner-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.ephemeralRunnerMetadata.labels.runner-key
value: "runner-value"
- it: should render ephemeralRunnerMetadata when annotations are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
ephemeralRunner:
metadata:
annotations:
runner-ann: "ann-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.ephemeralRunnerMetadata.annotations.runner-ann
value: "ann-value"
- it: should render ephemeralRunnerConfigSecretMetadata when labels are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
ephemeralRunnerConfigSecret:
metadata:
labels:
runner-config-key: "runner-config-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.ephemeralRunnerConfigSecretMetadata.labels.runner-config-key
value: "runner-config-value"
- it: should render ephemeralRunnerConfigSecretMetadata when annotations are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
ephemeralRunnerConfigSecret:
metadata:
annotations:
runner-config-ann: "ann-value"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.ephemeralRunnerConfigSecretMetadata.annotations.runner-config-ann
value: "ann-value"
- it: should render mixed populated and empty ResourceMeta fields correctly
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
autoscalingListener:
metadata:
labels:
listener: "true"
listenerServiceAccount:
metadata:
annotations:
sa-ann: "true"
ephemeralRunner:
metadata:
labels:
runner: "true"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.autoscalingListener.labels.listener
value: "true"
- equal:
path: spec.listenerServiceAccountMetadata.annotations.sa-ann
value: "true"
- equal:
path: spec.ephemeralRunnerMetadata.labels.runner
value: "true"
- notExists:
path: spec.listenerRoleMetadata
- notExists:
path: spec.listenerRoleBindingMetadata
- notExists:
path: spec.listenerConfigSecretMetadata
- notExists:
path: spec.ephemeralRunnerSetMetadata
- notExists:
path: spec.ephemeralRunnerConfigSecretMetadata
- it: should render both labels and annotations when both are populated
set:
scaleset.name: "test"
auth.url: "https://github.com/org"
auth.githubToken: "gh_token12345"
controllerServiceAccount.name: "arc"
controllerServiceAccount.namespace: "arc-system"
resource:
listenerServiceAccount:
metadata:
labels:
team: "platform"
annotations:
owner: "devops"
release:
name: "test-name"
namespace: "test-namespace"
asserts:
- equal:
path: spec.listenerServiceAccountMetadata.labels.team
value: "platform"
- equal:
path: spec.listenerServiceAccountMetadata.annotations.owner
value: "devops"

View File

@@ -15,13 +15,13 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.14.0
version: 0.14.1
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "0.14.0"
appVersion: "0.14.1"
home: https://github.com/actions/actions-runner-controller

View File

@@ -1,6 +1,6 @@
{{- $hasCustomResourceMeta := (and .Values.resourceMeta .Values.resourceMeta.noPermissionServiceAccount) }}
{{- $containerMode := .Values.containerMode }}
{{- if and (ne $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
{{- if and (ne $containerMode.type "kubernetes") (ne $containerMode.type "kubernetes-novolume") (not .Values.template.spec.serviceAccountName) }}
apiVersion: v1
kind: ServiceAccount
metadata:

View File

@@ -335,6 +335,46 @@ func TestTemplateRenderedSetServiceAccountToKubeNoVolumeMode(t *testing.T) {
assert.Equal(t, expectedServiceAccountName, ars.Annotations[actionsgithubcom.AnnotationKeyKubernetesModeServiceAccountName])
}
func TestTemplateRenderedNoPermissionServiceAccountNotRenderedInKubernetesModes(t *testing.T) {
t.Parallel()
for _, mode := range []string{"kubernetes", "kubernetes-novolume"} {
t.Run("containerMode "+mode, func(t *testing.T) {
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
require.NoError(t, err)
releaseName := "test-runners"
namespaceName := "test-" + strings.ToLower(random.UniqueId())
options := &helm.Options{
Logger: logger.Discard,
SetValues: map[string]string{
"githubConfigUrl": "https://github.com/actions",
"githubConfigSecret.github_token": "gh_token12345",
"controllerServiceAccount.name": "arc",
"controllerServiceAccount.namespace": "arc-system",
"containerMode.type": mode,
},
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
}
_, err = helm.RenderTemplateE(
t,
options,
helmChartPath,
releaseName,
[]string{"templates/no_permission_serviceaccount.yaml"},
)
assert.ErrorContains(
t,
err,
"could not find template templates/no_permission_serviceaccount.yaml in chart",
"no permission service account should not be rendered in "+mode+" mode",
)
})
}
}
func TestTemplateRenderedUserProvideSetServiceAccount(t *testing.T) {
t.Parallel()

View File

@@ -692,7 +692,7 @@ func (r *AutoscalingListenerReconciler) publishRunningListener(autoscalingListen
}
// SetupWithManager sets up the controller with the Manager.
func (r *AutoscalingListenerReconciler) SetupWithManager(mgr ctrl.Manager) error {
func (r *AutoscalingListenerReconciler) SetupWithManager(mgr ctrl.Manager, opts ...Option) error {
labelBasedWatchFunc := func(_ context.Context, obj client.Object) []reconcile.Request {
var requests []reconcile.Request
labels := obj.GetLabels()
@@ -716,14 +716,16 @@ func (r *AutoscalingListenerReconciler) SetupWithManager(mgr ctrl.Manager) error
return requests
}
return ctrl.NewControllerManagedBy(mgr).
For(&v1alpha1.AutoscalingListener{}).
Owns(&corev1.Pod{}).
Owns(&corev1.ServiceAccount{}).
Watches(&rbacv1.Role{}, handler.EnqueueRequestsFromMapFunc(labelBasedWatchFunc)).
Watches(&rbacv1.RoleBinding{}, handler.EnqueueRequestsFromMapFunc(labelBasedWatchFunc)).
WithEventFilter(predicate.ResourceVersionChangedPredicate{}).
Complete(r)
return builderWithOptions(
ctrl.NewControllerManagedBy(mgr).
For(&v1alpha1.AutoscalingListener{}).
Owns(&corev1.Pod{}).
Owns(&corev1.ServiceAccount{}).
Watches(&rbacv1.Role{}, handler.EnqueueRequestsFromMapFunc(labelBasedWatchFunc)).
Watches(&rbacv1.RoleBinding{}, handler.EnqueueRequestsFromMapFunc(labelBasedWatchFunc)).
WithEventFilter(predicate.ResourceVersionChangedPredicate{}),
opts,
).Complete(r)
}
func listenerContainerStatus(pod *corev1.Pod) *corev1.ContainerStatus {

View File

@@ -762,25 +762,27 @@ func (r *AutoscalingRunnerSetReconciler) listEphemeralRunnerSets(ctx context.Con
}
// SetupWithManager sets up the controller with the Manager.
func (r *AutoscalingRunnerSetReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&v1alpha1.AutoscalingRunnerSet{}).
Owns(&v1alpha1.EphemeralRunnerSet{}).
Watches(&v1alpha1.AutoscalingListener{}, handler.EnqueueRequestsFromMapFunc(
func(_ context.Context, o client.Object) []reconcile.Request {
autoscalingListener := o.(*v1alpha1.AutoscalingListener)
return []reconcile.Request{
{
NamespacedName: types.NamespacedName{
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
Name: autoscalingListener.Spec.AutoscalingRunnerSetName,
func (r *AutoscalingRunnerSetReconciler) SetupWithManager(mgr ctrl.Manager, opts ...Option) error {
return builderWithOptions(
ctrl.NewControllerManagedBy(mgr).
For(&v1alpha1.AutoscalingRunnerSet{}).
Owns(&v1alpha1.EphemeralRunnerSet{}).
Watches(&v1alpha1.AutoscalingListener{}, handler.EnqueueRequestsFromMapFunc(
func(_ context.Context, o client.Object) []reconcile.Request {
autoscalingListener := o.(*v1alpha1.AutoscalingListener)
return []reconcile.Request{
{
NamespacedName: types.NamespacedName{
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
Name: autoscalingListener.Spec.AutoscalingRunnerSetName,
},
},
},
}
},
)).
WithEventFilter(predicate.ResourceVersionChangedPredicate{}).
Complete(r)
}
},
)).
WithEventFilter(predicate.ResourceVersionChangedPredicate{}),
opts,
).Complete(r)
}
type autoscalingRunnerSetFinalizerDependencyCleaner struct {

View File

@@ -522,12 +522,14 @@ func (r *EphemeralRunnerSetReconciler) deleteEphemeralRunnerWithActionsClient(ct
}
// SetupWithManager sets up the controller with the Manager.
func (r *EphemeralRunnerSetReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&v1alpha1.EphemeralRunnerSet{}).
Owns(&v1alpha1.EphemeralRunner{}).
WithEventFilter(predicate.ResourceVersionChangedPredicate{}).
Complete(r)
func (r *EphemeralRunnerSetReconciler) SetupWithManager(mgr ctrl.Manager, opts ...Option) error {
return builderWithOptions(
ctrl.NewControllerManagedBy(mgr).
For(&v1alpha1.EphemeralRunnerSet{}).
Owns(&v1alpha1.EphemeralRunner{}).
WithEventFilter(predicate.ResourceVersionChangedPredicate{}),
opts,
).Complete(r)
}
type ephemeralRunnerStepper struct {

View File

@@ -1,8 +1,10 @@
package actionsgithubcom
import (
"k8s.io/client-go/util/workqueue"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)
// Options is the optional configuration for the controllers, which can be
@@ -37,6 +39,25 @@ func WithMaxConcurrentReconciles(n int) Option {
}
}
// WithTypedRateLimiter sets the rate limiter for the controller's workqueue.
//
// By default, the controller-runtime uses
// workqueue.DefaultTypedControllerRateLimiter[reconcile.Request], which combines
// an exponential backoff per-item limiter with a token bucket overall limiter
// (10 QPS, 100 bucket size). In large-scale environments with many runner
// scale sets, the token bucket limiter can become a bottleneck for
// reconciliation throughput.
//
// Use this option to override the default rate limiter, for example, to use
// workqueue.DefaultTypedItemBasedRateLimiter[reconcile.Request], which removes
// the overall token bucket constraint while keeping the per-item exponential
// backoff.
func WithTypedRateLimiter(rateLimiter workqueue.TypedRateLimiter[reconcile.Request]) Option {
return func(b *controller.Options) {
b.RateLimiter = rateLimiter
}
}
// builderWithOptions applies the given options to the provided builder, if any.
// This is a helper function to avoid the need to import the controller-runtime package in every reconciler source file
// and the command package that creates the controller.

View File

@@ -70,7 +70,7 @@ Fields like `volumeClaimTemplates` that originates from `StatefulSet` should als
Pod-related fields like security contexts and volumes are written under `spec.template.spec` like `StatefulSet`.
Similarly, container-related fields like resource requests and limits, container image names and tags, security context, and so on are written under `spec.template.spec.containers`. There are two reserved container `name`, `runner` and `docker`. The former is for the container that runs [actions runner](https://github.com/actions/runner) and the latter is for the container that runs a `dockerd`.
Similarly, container-related fields like resource requests and limits, container image names and tags, security context, and so on are written under `spec.template.spec.containers`. There are two reserved container names, `runner` and `docker`. The former is for the container that runs [actions runner](https://github.com/actions/runner) and the latter is for the container that runs a `dockerd`.
For a more complex example, see the below:

View File

@@ -43,6 +43,12 @@ You can follow [this troubleshooting guide](https://docs.github.com/en/actions/h
## Changelog
### 0.14.1
1. Fix null field for resource metadata fields in experimental chart [#4419](https://github.com/actions/actions-runner-controller/pull/4419)
1. Updates: runner to v2.333.1 [#4427](https://github.com/actions/actions-runner-controller/pull/4427)
1. Bump actions/scaleset to [v0.3.0](https://github.com/actions/scaleset/releases/tag/v0.3.0) [#4447](https://github.com/actions/actions-runner-controller/pull/4447)
### 0.14.0
1. Fix ActivityId typo in error strings [#4359](https://github.com/actions/actions-runner-controller/pull/4359)

2
go.mod
View File

@@ -6,7 +6,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v1.4.0
github.com/actions/scaleset v0.2.0
github.com/actions/scaleset v0.3.0
github.com/bradleyfalzon/ghinstallation/v2 v2.18.0
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/evanphx/json-patch v5.9.11+incompatible

2
go.sum
View File

@@ -37,6 +37,8 @@ github.com/actions-runner-controller/httpcache v0.2.0 h1:hCNvYuVPJ2xxYBymqBvH0hS
github.com/actions-runner-controller/httpcache v0.2.0/go.mod h1:JLu9/2M/btPz1Zu/vTZ71XzukQHn2YeISPmJoM5exBI=
github.com/actions/scaleset v0.2.0 h1:CKsDtTjOBCwjyT4ikwiMykMttzuKejimWRAvVr8xj9w=
github.com/actions/scaleset v0.2.0/go.mod h1:ncR5vzCCTUSyLgvclAtZ5dRBgF6qwA2nbTfTXmOJp84=
github.com/actions/scaleset v0.3.0 h1:y5/ClYLJXFuGCikzILOOPhaCShAcL6K0mnUtjDKFxVw=
github.com/actions/scaleset v0.3.0/go.mod h1:2L2I6rggFWV+zprDet6y7y7Vkm3HPudaup78eSc79Uo=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aws/aws-sdk-go-v2 v1.39.2 h1:EJLg8IdbzgeD7xgvZ+I8M1e0fL0ptn/M47lianzth0I=

31
main.go
View File

@@ -39,10 +39,12 @@ import (
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/util/workqueue"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/webhook"
// +kubebuilder:scaffold:imports
)
@@ -83,6 +85,7 @@ func main() {
listenerMetricsEndpoint string
metricsAddr string
pprofAddr string
autoScalingRunnerSetOnly bool
enableLeaderElection bool
disableAdmissionWebhook bool
@@ -110,6 +113,8 @@ func main() {
k8sClientRateLimiterQPS int
k8sClientRateLimiterBurst int
workqueueRateLimiter string
)
var c github.Config
err = envconfig.Process("github", &c)
@@ -121,6 +126,7 @@ func main() {
flag.StringVar(&listenerMetricsAddr, "listener-metrics-addr", ":8080", "The address applied to AutoscalingListener metrics server")
flag.StringVar(&listenerMetricsEndpoint, "listener-metrics-endpoint", "/metrics", "The AutoscalingListener metrics server endpoint from which the metrics are collected")
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&pprofAddr, "pprof-addr", "", "The address the pprof endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
"Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
flag.StringVar(&leaderElectionID, "leader-election-id", "actions-runner-controller", "Controller id for leader election.")
@@ -155,6 +161,7 @@ func main() {
flag.Var(&autoScalerImagePullSecrets, "auto-scaler-image-pull-secrets", "The default image-pull secret name for auto-scaler listener container.")
flag.IntVar(&k8sClientRateLimiterQPS, "k8s-client-rate-limiter-qps", 20, "The QPS value of the K8s client rate limiter.")
flag.IntVar(&k8sClientRateLimiterBurst, "k8s-client-rate-limiter-burst", 30, "The burst value of the K8s client rate limiter.")
flag.StringVar(&workqueueRateLimiter, "workqueue-rate-limiter", "", `The workqueue rate limiter to use. Valid values are "bucket_rate_limiter" (default) and "typed_rate_limiter" (per-item only, no global token bucket).`)
flag.Parse()
runnerPodDefaults.RunnerImagePullSecrets = runnerImagePullSecrets
@@ -239,6 +246,7 @@ func main() {
SyncPeriod: &syncPeriod,
DefaultNamespaces: defaultNamespaces,
},
PprofBindAddress: pprofAddr,
WebhookServer: webhookServer,
LeaderElection: enableLeaderElection,
LeaderElectionID: leaderElectionID,
@@ -293,6 +301,20 @@ func main() {
log.Info("Resource builder initializing")
var controllerOpts []actionsgithubcom.Option
switch workqueueRateLimiter {
case "typed_rate_limiter":
log.Info("Using typed rate limiter (per-item only, no global token bucket)")
controllerOpts = append(controllerOpts,
actionsgithubcom.WithTypedRateLimiter(workqueue.DefaultTypedItemBasedRateLimiter[reconcile.Request]()),
)
case "bucket_rate_limiter", "":
log.Info("Using default bucket rate limiter")
default:
log.Error(fmt.Errorf("unknown workqueue rate limiter: %s", workqueueRateLimiter), "invalid --workqueue-rate-limiter value")
os.Exit(1)
}
if err = (&actionsgithubcom.AutoscalingRunnerSetReconciler{
Client: mgr.GetClient(),
Log: log.WithName("AutoscalingRunnerSet").WithValues("version", build.Version),
@@ -302,17 +324,18 @@ func main() {
UpdateStrategy: actionsgithubcom.UpdateStrategy(updateStrategy),
DefaultRunnerScaleSetListenerImagePullSecrets: autoScalerImagePullSecrets,
ResourceBuilder: rb,
}).SetupWithManager(mgr); err != nil {
}).SetupWithManager(mgr, controllerOpts...); err != nil {
log.Error(err, "unable to create controller", "controller", "AutoscalingRunnerSet")
os.Exit(1)
}
runnerOpts := append(controllerOpts, actionsgithubcom.WithMaxConcurrentReconciles(opts.RunnerMaxConcurrentReconciles))
if err = (&actionsgithubcom.EphemeralRunnerReconciler{
Client: mgr.GetClient(),
Log: log.WithName("EphemeralRunner").WithValues("version", build.Version),
Scheme: mgr.GetScheme(),
ResourceBuilder: rb,
}).SetupWithManager(mgr, actionsgithubcom.WithMaxConcurrentReconciles(opts.RunnerMaxConcurrentReconciles)); err != nil {
}).SetupWithManager(mgr, runnerOpts...); err != nil {
log.Error(err, "unable to create controller", "controller", "EphemeralRunner")
os.Exit(1)
}
@@ -323,7 +346,7 @@ func main() {
Scheme: mgr.GetScheme(),
PublishMetrics: metricsAddr != "0",
ResourceBuilder: rb,
}).SetupWithManager(mgr); err != nil {
}).SetupWithManager(mgr, controllerOpts...); err != nil {
log.Error(err, "unable to create controller", "controller", "EphemeralRunnerSet")
os.Exit(1)
}
@@ -335,7 +358,7 @@ func main() {
ListenerMetricsAddr: listenerMetricsAddr,
ListenerMetricsEndpoint: listenerMetricsEndpoint,
ResourceBuilder: rb,
}).SetupWithManager(mgr); err != nil {
}).SetupWithManager(mgr, controllerOpts...); err != nil {
log.Error(err, "unable to create controller", "controller", "AutoscalingListener")
os.Exit(1)
}

View File

@@ -6,7 +6,7 @@ DIND_ROOTLESS_RUNNER_NAME ?= ${DOCKER_USER}/actions-runner-dind-rootless
OS_IMAGE ?= ubuntu-22.04
TARGETPLATFORM ?= $(shell arch)
RUNNER_VERSION ?= 2.332.0
RUNNER_VERSION ?= 2.334.0
RUNNER_CONTAINER_HOOKS_VERSION ?= 0.8.1
DOCKER_VERSION ?= 28.0.4

View File

@@ -1,2 +1,2 @@
RUNNER_VERSION=2.332.0
RUNNER_VERSION=2.334.0
RUNNER_CONTAINER_HOOKS_VERSION=0.8.1

View File

@@ -36,7 +36,7 @@ var (
testResultCMNamePrefix = "test-result-"
RunnerVersion = "2.332.0"
RunnerVersion = "2.334.0"
RunnerContainerHooksVersion = "0.8.1"
)