Merge branch 'master' into feature/mtls-proxy-support

This commit is contained in:
dhawalseth 2026-05-26 15:30:13 -07:00 committed by GitHub
commit b1f916ee90
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 428 additions and 276 deletions

View File

@ -103,6 +103,7 @@ jobs:
- name: Build & push controller image
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f
with:
context: .
file: Dockerfile
platforms: linux/amd64,linux/arm64
build-args: VERSION=${{ inputs.release_tag_name }}

View File

@ -65,82 +65,63 @@ jobs:
echo "$changed" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Install helm-unittest
if: |
contains(steps.list-changed.outputs.changed_charts, 'charts/gha-runner-scale-set-controller-experimental') ||
contains(steps.list-changed.outputs.changed_charts, 'charts/gha-runner-scale-set-experimental')
run: |
helm plugin install https://github.com/helm-unittest/helm-unittest.git
- name: Run helm-unittest (gha-runner-scale-set-controller-experimental)
if: contains(steps.list-changed.outputs.changed_charts, 'charts/gha-runner-scale-set-controller-experimental')
run: |
helm unittest ./charts/gha-runner-scale-set-controller-experimental/
- name: Run helm-unittest (gha-runner-scale-set-experimental)
if: contains(steps.list-changed.outputs.changed_charts, 'charts/gha-runner-scale-set-experimental')
run: |
helm unittest ./charts/gha-runner-scale-set-experimental/
- name: Run chart-testing (lint)
run: |
ct lint --config charts/.ci/ct-config-gha.yaml
- name: Set up docker buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd
if: steps.list-changed.outputs.changed == 'true'
with:
version: latest
- name: Build controller image
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f
if: steps.list-changed.outputs.changed == 'true'
with:
file: Dockerfile
platforms: linux/amd64
load: true
build-args: |
DOCKER_IMAGE_NAME=test-arc
VERSION=dev
tags: |
test-arc:dev
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Create kind cluster
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc
if: steps.list-changed.outputs.changed == 'true'
with:
cluster_name: chart-testing
- name: Load image into cluster
if: steps.list-changed.outputs.changed == 'true'
run: |
export DOCKER_IMAGE_NAME=test-arc
export VERSION=dev
export IMG_RESULT=load
make docker-buildx
kind load docker-image test-arc:dev --name chart-testing
- name: Run chart-testing (install)
if: steps.list-changed.outputs.changed == 'true'
run: |
ct install --config charts/.ci/ct-config-gha.yaml
test-chart:
name: Test Chart
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Helm
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4
with:
version: ${{ env.HELM_VERSION }}
# python is a requirement for the chart-testing action below (supports yamllint among other tests)
- uses: actions/setup-python@v6
with:
python-version: "3.11"
- name: Set up chart-testing
uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f
- name: Run chart-testing (list-changed)
id: list-changed
run: |
ct version
changed=$(ct list-changed --config charts/.ci/ct-config-gha.yaml)
if [[ -n "$changed" ]]; then
echo "changed=true" >> $GITHUB_OUTPUT
fi
echo "changed_charts<<EOF" >> $GITHUB_OUTPUT
echo "$changed" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Install helm-unittest
run: |
helm plugin install https://github.com/helm-unittest/helm-unittest.git
- name: Run helm-unittest (gha-runner-scale-set-controller-experimental)
run: |
helm unittest ./charts/gha-runner-scale-set-controller-experimental/
- name: Run helm-unittest (gha-runner-scale-set-experimental)
run: |
helm unittest ./charts/gha-runner-scale-set-experimental/
- uses: actions/setup-go@v6
with:
go-version-file: "go.mod"
cache: false
- name: Test gha-runner-scale-set
run: go test ./charts/gha-runner-scale-set/...
- name: Test gha-runner-scale-set-controller
run: go test ./charts/gha-runner-scale-set-controller/...
- name: Test gha-runner-scale-set-experimental
run: go test ./charts/gha-runner-scale-set-experimental/...
- name: Test gha-runner-scale-set-controller-experimental
run: go test ./charts/gha-runner-scale-set-controller-experimental/...

View File

@ -1,5 +1,5 @@
# Build the manager binary
FROM --platform=$BUILDPLATFORM golang:1.26.2 AS builder
FROM --platform=$BUILDPLATFORM golang:1.26.3 AS builder
WORKDIR /workspace

View File

@ -37,7 +37,7 @@ import (
// +kubebuilder:printcolumn:JSONPath=".spec.minRunners",name=Minimum Runners,type=integer
// +kubebuilder:printcolumn:JSONPath=".spec.maxRunners",name=Maximum Runners,type=integer
// +kubebuilder:printcolumn:JSONPath=".status.currentRunners",name=Current Runners,type=integer
// +kubebuilder:printcolumn:JSONPath=".status.phase",name=Phase,type=string
// +kubebuilder:printcolumn:JSONPath=".status.state",name=State,type=string
// +kubebuilder:printcolumn:JSONPath=".status.pendingEphemeralRunners",name=Pending Runners,type=integer
// +kubebuilder:printcolumn:JSONPath=".status.runningEphemeralRunners",name=Running Runners,type=integer
// +kubebuilder:printcolumn:JSONPath=".status.finishedEphemeralRunners",name=Finished Runners,type=integer

View File

@ -29,7 +29,7 @@ const EphemeralRunnerContainerName = "runner"
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:JSONPath=".spec.githubConfigUrl",name="GitHub Config URL",type=string
// +kubebuilder:printcolumn:JSONPath=".status.runnerId",name=RunnerId,type=number
// +kubebuilder:printcolumn:JSONPath=".status.phase",name=Phase,type=string
// +kubebuilder:printcolumn:JSONPath=".status.phase",name=Status,type=string
// +kubebuilder:printcolumn:JSONPath=".status.jobRepositoryName",name=JobRepository,type=string
// +kubebuilder:printcolumn:JSONPath=".status.jobWorkflowRef",name=JobWorkflowRef,type=string
// +kubebuilder:printcolumn:JSONPath=".status.workflowRunId",name=WorkflowRunId,type=number

View File

@ -64,7 +64,6 @@ const (
// +kubebuilder:printcolumn:JSONPath=".status.runningEphemeralRunners",name=Running Runners,type=integer
// +kubebuilder:printcolumn:JSONPath=".status.finishedEphemeralRunners",name=Finished Runners,type=integer
// +kubebuilder:printcolumn:JSONPath=".status.deletingEphemeralRunners",name=Deleting Runners,type=integer
// +kubebuilder:printcolumn:JSONPath=".status.phase",name=Phase,type=string
// EphemeralRunnerSet is the Schema for the ephemeralrunnersets API
type EphemeralRunnerSet struct {

View File

@ -8,4 +8,6 @@ check-version-increment: false # Disable checking that the chart version has bee
charts:
- charts/gha-runner-scale-set-controller
- charts/gha-runner-scale-set
- charts/gha-runner-scale-set-controller-experimental
- charts/gha-runner-scale-set-experimental
skip-clean-up: true

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.1"
version: "0.14.2"
# 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.1"
appVersion: "0.14.2"
home: https://github.com/actions/actions-runner-controller

View File

@ -24,8 +24,8 @@ spec:
- jsonPath: .status.currentRunners
name: Current Runners
type: integer
- jsonPath: .status.phase
name: Phase
- jsonPath: .status.state
name: State
type: string
- jsonPath: .status.pendingEphemeralRunners
name: Pending Runners

View File

@ -22,7 +22,7 @@ spec:
name: RunnerId
type: number
- jsonPath: .status.phase
name: Phase
name: Status
type: string
- jsonPath: .status.jobRepositoryName
name: JobRepository

View File

@ -33,9 +33,6 @@ spec:
- jsonPath: .status.deletingEphemeralRunners
name: Deleting Runners
type: integer
- jsonPath: .status.phase
name: Phase
type: string
name: v1alpha1
schema:
openAPIV3Schema:

View File

@ -73,6 +73,11 @@ args:
{{- with .Values.controller.manager.config.k8sClientRateLimiterBurst }}
- "--k8s-client-rate-limiter-burst={{ . }}"
{{- end }}
{{- with .Values.controller.manager.config.rateLimiter }}
{{- with .name }}
- "--workqueue-rate-limiter={{ . }}"
{{- end }}
{{- end }}
{{- with .Values.controller.manager.config.healthProbeBindAddress }}
- "--health-probe-bind-address={{ . }}"
{{- end }}

View File

@ -0,0 +1,66 @@
suite: "Controller Deployment rate limiter"
templates:
- deployment.yaml
tests:
- it: should omit workqueue-rate-limiter flag by default
release:
name: "test-arc"
namespace: "test-ns"
asserts:
- notContains:
path: spec.template.spec.containers[0].args
content: "--workqueue-rate-limiter=bucket_rate_limiter"
- notContains:
path: spec.template.spec.containers[0].args
content: "--workqueue-rate-limiter=typed_rate_limiter"
- it: should include workqueue-rate-limiter flag when bucket_rate_limiter is configured
set:
controller:
manager:
config:
rateLimiter:
name: "bucket_rate_limiter"
release:
name: "test-arc"
namespace: "test-ns"
asserts:
- contains:
path: spec.template.spec.containers[0].args
content: "--workqueue-rate-limiter=bucket_rate_limiter"
- it: should include workqueue-rate-limiter flag when typed_rate_limiter is configured
set:
controller:
manager:
config:
rateLimiter:
name: "typed_rate_limiter"
release:
name: "test-arc"
namespace: "test-ns"
asserts:
- contains:
path: spec.template.spec.containers[0].args
content: "--workqueue-rate-limiter=typed_rate_limiter"
- it: should render both config and extraArgs in deterministic order
set:
controller:
manager:
config:
rateLimiter:
name: "bucket_rate_limiter"
container:
extraArgs:
- "--workqueue-rate-limiter=typed_rate_limiter"
release:
name: "test-arc"
namespace: "test-ns"
asserts:
- contains:
path: spec.template.spec.containers[0].args
content: "--workqueue-rate-limiter=bucket_rate_limiter"
- contains:
path: spec.template.spec.containers[0].args
content: "--workqueue-rate-limiter=typed_rate_limiter"

View File

@ -1,52 +0,0 @@
package tests
import (
"os"
"path/filepath"
"strings"
"testing"
"github.com/gruntwork-io/terratest/modules/helm"
"github.com/gruntwork-io/terratest/modules/k8s"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/random"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
appsv1 "k8s.io/api/apps/v1"
)
type Chart struct {
Version string `yaml:"version"`
AppVersion string `yaml:"appVersion"`
}
func TestTemplate_RenderedDeployment_UsesChartMetadataLabels(t *testing.T) {
t.Parallel()
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller-experimental")
require.NoError(t, err)
chartContent, err := os.ReadFile(filepath.Join(helmChartPath, "Chart.yaml"))
require.NoError(t, err)
chart := new(Chart)
err = yaml.Unmarshal(chartContent, chart)
require.NoError(t, err)
releaseName := "test-arc"
namespaceName := "test-" + strings.ToLower(random.UniqueId())
options := &helm.Options{
Logger: logger.Discard,
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
}
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/deployment.yaml"})
var deployment appsv1.Deployment
helm.UnmarshalK8SYaml(t, output, &deployment)
assert.Equal(t, "gha-rs-controller-"+chart.Version, deployment.Labels["helm.sh/chart"])
assert.Equal(t, chart.AppVersion, deployment.Labels["app.kubernetes.io/version"])
}

View File

@ -44,6 +44,13 @@ controller:
k8sClientRateLimiterQPS: null
k8sClientRateLimiterBurst: null
## 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"
# The address the health probe endpoint binds to. Disabled if empty/null.
# When set, liveness and readiness probes are added to the controller pod.
# healthProbeBindAddress: ":8081"

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.1
version: 0.14.2
# 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.1"
appVersion: "0.14.2"
home: https://github.com/actions/actions-runner-controller

View File

@ -24,8 +24,8 @@ spec:
- jsonPath: .status.currentRunners
name: Current Runners
type: integer
- jsonPath: .status.phase
name: Phase
- jsonPath: .status.state
name: State
type: string
- jsonPath: .status.pendingEphemeralRunners
name: Pending Runners

View File

@ -22,7 +22,7 @@ spec:
name: RunnerId
type: number
- jsonPath: .status.phase
name: Phase
name: Status
type: string
- jsonPath: .status.jobRepositoryName
name: JobRepository

View File

@ -33,9 +33,6 @@ spec:
- jsonPath: .status.deletingEphemeralRunners
name: Deleting Runners
type: integer
- jsonPath: .status.phase
name: Phase
type: string
name: v1alpha1
schema:
openAPIV3Schema:

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.1"
version: "0.14.2"
# 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.1"
appVersion: "0.14.2"
home: https://github.com/actions/actions-runner-controller

View File

@ -1,61 +0,0 @@
package tests
import (
"os"
"path/filepath"
"strings"
"testing"
v1alpha1 "github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
"github.com/gruntwork-io/terratest/modules/helm"
"github.com/gruntwork-io/terratest/modules/k8s"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/random"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
)
type Chart struct {
Version string `yaml:"version"`
AppVersion string `yaml:"appVersion"`
}
func TestTemplate_RenderedAutoscalingRunnerSet_UsesChartMetadataLabels(t *testing.T) {
t.Parallel()
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-experimental")
require.NoError(t, err)
chartContent, err := os.ReadFile(filepath.Join(helmChartPath, "Chart.yaml"))
require.NoError(t, err)
chart := new(Chart)
err = yaml.Unmarshal(chartContent, chart)
require.NoError(t, err)
releaseName := "test-runners"
namespaceName := "test-" + strings.ToLower(random.UniqueId())
options := &helm.Options{
Logger: logger.Discard,
SetValues: map[string]string{
"scaleset.name": "test",
"auth.url": "https://github.com/actions",
"auth.githubToken": "gh_token12345",
"controllerServiceAccount.name": "arc",
"controllerServiceAccount.namespace": "arc-system",
},
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
}
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnserset.yaml"})
var autoscalingRunnerSet v1alpha1.AutoscalingRunnerSet
helm.UnmarshalK8SYaml(t, output, &autoscalingRunnerSet)
assert.Equal(t, "gha-rs-"+chart.Version, autoscalingRunnerSet.Labels["helm.sh/chart"])
assert.Equal(t, chart.AppVersion, autoscalingRunnerSet.Labels["app.kubernetes.io/version"])
assert.Equal(t, "gha-rs-"+chart.Version, autoscalingRunnerSet.Spec.Template.Labels["helm.sh/chart"])
assert.Equal(t, chart.AppVersion, autoscalingRunnerSet.Spec.Template.Labels["app.kubernetes.io/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.1
version: 0.14.2
# 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.1"
appVersion: "0.14.2"
home: https://github.com/actions/actions-runner-controller

View File

@ -24,8 +24,8 @@ spec:
- jsonPath: .status.currentRunners
name: Current Runners
type: integer
- jsonPath: .status.phase
name: Phase
- jsonPath: .status.state
name: State
type: string
- jsonPath: .status.pendingEphemeralRunners
name: Pending Runners

View File

@ -22,7 +22,7 @@ spec:
name: RunnerId
type: number
- jsonPath: .status.phase
name: Phase
name: Status
type: string
- jsonPath: .status.jobRepositoryName
name: JobRepository

View File

@ -33,9 +33,6 @@ spec:
- jsonPath: .status.deletingEphemeralRunners
name: Deleting Runners
type: integer
- jsonPath: .status.phase
name: Phase
type: string
name: v1alpha1
schema:
openAPIV3Schema:

View File

@ -138,14 +138,16 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
if !v1alpha1.IsVersionAllowed(autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion], build.Version) {
if err := r.Delete(ctx, autoscalingRunnerSet); err != nil {
log.Error(err, "Failed to delete autoscaling runner set on version mismatch",
log.Error(
err, "Failed to delete autoscaling runner set on version mismatch",
"buildVersion", build.Version,
"autoscalingRunnerSetVersion", autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion],
)
return ctrl.Result{}, nil
}
log.Info("Autoscaling runner set version doesn't match the build version. Deleting the resource.",
log.Info(
"Autoscaling runner set version doesn't match the build version. Deleting the resource.",
"buildVersion", build.Version,
"autoscalingRunnerSetVersion", autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion],
)
@ -270,12 +272,12 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
// Our listener pod is out of date, so we need to delete it to get a new recreate.
listenerValuesHashChanged := listener.Annotations[annotationKeyValuesHash] != autoscalingRunnerSet.Annotations[annotationKeyValuesHash]
listenerSpecHashChanged := listener.Annotations[annotationKeyRunnerSpecHash] != autoscalingRunnerSet.ListenerSpecHash()
if listenerFound && (listenerValuesHashChanged || listenerSpecHashChanged) {
if listenerFound && (listenerValuesHashChanged ||
listenerSpecHashChanged ||
latestRunnerSet == nil ||
listener.Spec.EphemeralRunnerSetName != latestRunnerSet.Name) {
log.Info("RunnerScaleSetListener is out of date. Deleting it so that it is recreated", "name", listener.Name)
if err := r.Delete(ctx, listener); err != nil {
if kerrors.IsNotFound(err) {
return ctrl.Result{}, nil
}
log.Error(err, "Failed to delete AutoscalingListener resource")
return ctrl.Result{}, err
}
@ -473,6 +475,7 @@ func (r *AutoscalingRunnerSetReconciler) removeFinalizersFromDependentResources(
}
func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
original := autoscalingRunnerSet.DeepCopy()
logger.Info("Creating a new runner scale set")
actionsClient, err := r.GetActionsService(ctx, autoscalingRunnerSet)
if len(autoscalingRunnerSet.Spec.RunnerScaleSetName) == 0 {
@ -537,7 +540,8 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex
RunnerSetting: scaleset.RunnerSetting{
DisableUpdate: true,
},
})
},
)
if err != nil {
logger.Error(err, "Failed to create a new runner scale set on Actions service")
return ctrl.Result{}, err
@ -556,15 +560,16 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex
autoscalingRunnerSet.Labels = map[string]string{}
}
autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerScaleSetName] = runnerScaleSet.Name
autoscalingRunnerSet.Annotations[runnerScaleSetIDAnnotationKey] = strconv.Itoa(runnerScaleSet.ID)
autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName] = runnerScaleSet.RunnerGroupName
if err := applyGitHubURLLabels(autoscalingRunnerSet.Spec.GitHubConfigUrl, autoscalingRunnerSet.Labels); err != nil { // should never happen
logger.Error(err, "Failed to apply GitHub URL labels")
return ctrl.Result{}, err
}
logger.Info("Adding runner scale set ID, name and runner group name as an annotation and url labels")
if err = patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
obj.Annotations[AnnotationKeyGitHubRunnerScaleSetName] = runnerScaleSet.Name
obj.Annotations[runnerScaleSetIDAnnotationKey] = strconv.Itoa(runnerScaleSet.ID)
obj.Annotations[AnnotationKeyGitHubRunnerGroupName] = runnerScaleSet.RunnerGroupName
if err := applyGitHubURLLabels(obj.Spec.GitHubConfigUrl, obj.Labels); err != nil { // should never happen
logger.Error(err, "Failed to apply GitHub URL labels")
}
}); err != nil {
if err = r.Patch(ctx, autoscalingRunnerSet, client.MergeFrom(original)); err != nil {
logger.Error(err, "Failed to add runner scale set ID, name and runner group name as an annotation")
return ctrl.Result{}, err
}

View File

@ -85,13 +85,19 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return &scaleset.RunnerGroup{ID: 1, Name: groupName}, nil
}),
scalefake.WithGetRunnerScaleSet(nil, nil),
scalefake.WithCreateRunnerScaleSet(&scaleset.RunnerScaleSet{ID: 1, Name: "test-asrs", RunnerGroupID: 1, RunnerGroupName: "testgroup"}, nil),
scalefake.WithCreateRunnerScaleSetFunc(func(ctx context.Context, rs *scaleset.RunnerScaleSet) (*scaleset.RunnerScaleSet, error) {
// Return a RunnerScaleSet with name matching the requesting ARS
runnerGroupMapLock.RLock()
groupName := runnerGroupMap[rs.RunnerGroupID]
runnerGroupMapLock.RUnlock()
return &scaleset.RunnerScaleSet{ID: 1, Name: rs.Name, RunnerGroupID: rs.RunnerGroupID, RunnerGroupName: groupName}, nil
}),
scalefake.WithUpdateRunnerScaleSetFunc(func(ctx context.Context, scaleSetID int, rs *scaleset.RunnerScaleSet) (*scaleset.RunnerScaleSet, error) {
// Return a RunnerScaleSet with the group name corresponding to the runner group ID
runnerGroupMapLock.RLock()
groupName := runnerGroupMap[rs.RunnerGroupID]
runnerGroupMapLock.RUnlock()
return &scaleset.RunnerScaleSet{ID: 1, Name: "test-asrs", RunnerGroupID: rs.RunnerGroupID, RunnerGroupName: groupName}, nil
return &scaleset.RunnerScaleSet{ID: 1, Name: rs.Name, RunnerGroupID: rs.RunnerGroupID, RunnerGroupName: groupName}, nil
}),
scalefake.WithDeleteRunnerScaleSet(nil),
),
@ -153,7 +159,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return created.Finalizers[0], nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo(autoscalingRunnerSetFinalizerName), "AutoScalingRunnerSet should have a finalizer")
autoscalingRunnerSetTestInterval,
).Should(BeEquivalentTo(autoscalingRunnerSetFinalizerName), "AutoScalingRunnerSet should have a finalizer")
// Check if runner scale set is created on service
Eventually(
@ -202,7 +209,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return fmt.Sprintf("%s/%s", created.Labels[LabelKeyGitHubOrganization], created.Labels[LabelKeyGitHubRepository]), nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("owner/repo"), "RunnerScaleSet should be created/fetched and update the AutoScalingRunnerSet's label")
autoscalingRunnerSetTestInterval,
).Should(BeEquivalentTo("owner/repo"), "RunnerScaleSet should be created/fetched and update the AutoScalingRunnerSet's label")
// Check if ephemeral runner set is created
Eventually(
@ -216,7 +224,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return len(runnerSetList.Items), nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo(1), "Only one EphemeralRunnerSet should be created")
autoscalingRunnerSetTestInterval,
).Should(BeEquivalentTo(1), "Only one EphemeralRunnerSet should be created")
// Check if listener is created
Eventually(
@ -224,7 +233,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return k8sClient.Get(ctx, client.ObjectKey{Name: scaleSetListenerName(autoscalingRunnerSet), Namespace: autoscalingRunnerSet.Namespace}, new(v1alpha1.AutoscalingListener))
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(Succeed(), "Listener should be created")
autoscalingRunnerSetTestInterval,
).Should(Succeed(), "Listener should be created")
// Check if status is updated
runnerSetList := new(v1alpha1.EphemeralRunnerSetList)
@ -242,7 +252,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return k8sClient.Get(ctx, client.ObjectKey{Name: scaleSetListenerName(autoscalingRunnerSet), Namespace: autoscalingRunnerSet.Namespace}, new(v1alpha1.AutoscalingListener))
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(Succeed(), "Listener should be created")
autoscalingRunnerSetTestInterval,
).Should(Succeed(), "Listener should be created")
// Delete the AutoScalingRunnerSet
err := k8sClient.Delete(ctx, autoscalingRunnerSet)
@ -259,7 +270,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return fmt.Errorf("listener is not deleted")
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(Succeed(), "Listener should be deleted")
autoscalingRunnerSetTestInterval,
).Should(Succeed(), "Listener should be deleted")
// Check if all the EphemeralRunnerSet is deleted
Eventually(
@ -277,7 +289,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(Succeed(), "All EphemeralRunnerSet should be deleted")
autoscalingRunnerSetTestInterval,
).Should(Succeed(), "All EphemeralRunnerSet should be deleted")
// Check if the AutoScalingRunnerSet is deleted
Eventually(
@ -290,10 +303,144 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return fmt.Errorf("AutoScalingRunnerSet is not deleted")
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(Succeed(), "AutoScalingRunnerSet should be deleted")
autoscalingRunnerSetTestInterval,
).Should(Succeed(), "AutoScalingRunnerSet should be deleted")
})
})
It("should not churn listener when already referencing latest ERS (no-op stability)", func() {
min := 1
max := 10
testARSName := "test-asrs-no-churn"
testARSNamespace := autoscalingNS.Name
testARS := &v1alpha1.AutoscalingRunnerSet{
ObjectMeta: metav1.ObjectMeta{
Name: testARSName,
Namespace: testARSNamespace,
Labels: map[string]string{
LabelKeyKubernetesVersion: buildVersion,
},
},
Spec: v1alpha1.AutoscalingRunnerSetSpec{
GitHubConfigUrl: "https://github.com/owner/repo",
GitHubConfigSecret: configSecret.Name,
MaxRunners: &max,
MinRunners: &min,
RunnerGroup: "testgroup",
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "runner",
Image: "ghcr.io/actions/runner",
},
},
},
},
},
}
err := k8sClient.Create(ctx, testARS)
Expect(err).NotTo(HaveOccurred(), "failed to create test AutoScalingRunnerSet")
var latestERSName string
Eventually(
func() (string, error) {
runnerSetList := new(v1alpha1.EphemeralRunnerSetList)
err := k8sClient.List(ctx, runnerSetList, client.InNamespace(testARSNamespace))
if err != nil {
return "", err
}
// Filter to only ERS owned by our test ARS
var ownedByTestARS []v1alpha1.EphemeralRunnerSet
for _, ers := range runnerSetList.Items {
for _, owner := range ers.OwnerReferences {
if owner.UID == testARS.UID {
ownedByTestARS = append(ownedByTestARS, ers)
break
}
}
}
if len(ownedByTestARS) != 1 {
return "", fmt.Errorf("expected 1 EphemeralRunnerSet owned by test ARS, got %d", len(ownedByTestARS))
}
return ownedByTestARS[0].Name, nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval,
).Should(Not(BeEmpty()), "ERS should be created")
// Capture the latest ERS name
runnerSetList := new(v1alpha1.EphemeralRunnerSetList)
err = k8sClient.List(ctx, runnerSetList, client.InNamespace(testARSNamespace))
Expect(err).NotTo(HaveOccurred(), "failed to list EphemeralRunnerSet")
var ownedByTestARS []v1alpha1.EphemeralRunnerSet
for _, ers := range runnerSetList.Items {
for _, owner := range ers.OwnerReferences {
if owner.UID == testARS.UID {
ownedByTestARS = append(ownedByTestARS, ers)
break
}
}
}
Expect(len(ownedByTestARS)).To(Equal(1), "should have exactly 1 EphemeralRunnerSet owned by test ARS")
latestERSName = ownedByTestARS[0].Name
listener := new(v1alpha1.AutoscalingListener)
Eventually(
func() (string, error) {
err := k8sClient.Get(ctx, client.ObjectKey{Name: scaleSetListenerName(testARS), Namespace: testARSNamespace}, listener)
if err != nil {
return "", err
}
return listener.Spec.EphemeralRunnerSetName, nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval,
).Should(Equal(latestERSName), "listener should reference the latest ERS")
// Capture listener identity (UID and ResourceVersion)
err = k8sClient.Get(ctx, client.ObjectKey{Name: scaleSetListenerName(testARS), Namespace: testARSNamespace}, listener)
Expect(err).NotTo(HaveOccurred(), "failed to get listener")
originalUID := listener.UID
originalResourceVersion := listener.ResourceVersion
Consistently(
func() (types.UID, error) {
currentListener := new(v1alpha1.AutoscalingListener)
err := k8sClient.Get(ctx, client.ObjectKey{Name: scaleSetListenerName(testARS), Namespace: testARSNamespace}, currentListener)
if err != nil {
return "", err
}
return currentListener.UID, nil
},
time.Second*5,
autoscalingRunnerSetTestInterval,
).Should(Equal(originalUID), "listener UID should remain unchanged (no recreation)")
Consistently(
func() (string, error) {
currentListener := new(v1alpha1.AutoscalingListener)
err := k8sClient.Get(ctx, client.ObjectKey{Name: scaleSetListenerName(testARS), Namespace: testARSNamespace}, currentListener)
if err != nil {
return "", err
}
return currentListener.ResourceVersion, nil
},
time.Second*5,
autoscalingRunnerSetTestInterval,
).Should(Equal(originalResourceVersion), "listener ResourceVersion should remain unchanged (no updates)")
err = k8sClient.Get(ctx, client.ObjectKey{Name: scaleSetListenerName(testARS), Namespace: testARSNamespace}, listener)
Expect(err).NotTo(HaveOccurred(), "failed to get listener")
Expect(listener.Spec.EphemeralRunnerSetName).To(Equal(latestERSName), "listener should still reference latest ERS")
})
Context("When updating a new AutoScalingRunnerSet", func() {
It("It should re-create EphemeralRunnerSet and Listener as needed when updating AutoScalingRunnerSet", func() {
// Wait till the listener is created
@ -303,7 +450,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return k8sClient.Get(ctx, client.ObjectKey{Name: scaleSetListenerName(autoscalingRunnerSet), Namespace: autoscalingRunnerSet.Namespace}, listener)
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(Succeed(), "Listener should be created")
autoscalingRunnerSetTestInterval,
).Should(Succeed(), "Listener should be created")
runnerSetList := new(v1alpha1.EphemeralRunnerSetList)
err := k8sClient.List(ctx, runnerSetList, client.InNamespace(autoscalingRunnerSet.Namespace))
@ -339,7 +487,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return runnerSetList.Items[0].Annotations[annotationKeyRunnerSpecHash], nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).ShouldNot(BeEquivalentTo(runnerSet.Annotations[annotationKeyRunnerSpecHash]), "New EphemeralRunnerSet should be created")
autoscalingRunnerSetTestInterval,
).ShouldNot(BeEquivalentTo(runnerSet.Annotations[annotationKeyRunnerSpecHash]), "New EphemeralRunnerSet should be created")
// We should create a new listener
Eventually(
@ -353,7 +502,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return listener.Spec.EphemeralRunnerSetName, nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).ShouldNot(BeEquivalentTo(runnerSet.Name), "New Listener should be created")
autoscalingRunnerSetTestInterval,
).ShouldNot(BeEquivalentTo(runnerSet.Name), "New Listener should be created")
// Only update the Spec for the AutoScalingListener
// This should trigger re-creation of the Listener only
@ -389,7 +539,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return string(runnerSetList.Items[0].UID), nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo(string(runnerSet.UID)), "New EphemeralRunnerSet should not be created")
autoscalingRunnerSetTestInterval,
).Should(BeEquivalentTo(string(runnerSet.UID)), "New EphemeralRunnerSet should not be created")
// We should only re-create a new listener
Eventually(
@ -403,7 +554,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return string(listener.UID), nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).ShouldNot(BeEquivalentTo(string(listener.UID)), "New Listener should be created")
autoscalingRunnerSetTestInterval,
).ShouldNot(BeEquivalentTo(string(listener.UID)), "New Listener should be created")
// Only update the values hash for the autoscaling runner set
// This should trigger re-creation of the Listener only
@ -438,7 +590,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return string(runnerSetList.Items[0].UID), nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo(string(runnerSet.UID)), "New EphemeralRunnerSet should not be created")
autoscalingRunnerSetTestInterval,
).Should(BeEquivalentTo(string(runnerSet.UID)), "New EphemeralRunnerSet should not be created")
// We should only re-create a new listener
Eventually(
@ -452,7 +605,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return string(listener.UID), nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).ShouldNot(BeEquivalentTo(string(listener.UID)), "New Listener should be created")
autoscalingRunnerSetTestInterval,
).ShouldNot(BeEquivalentTo(string(listener.UID)), "New Listener should be created")
})
It("It should update RunnerScaleSet's runner group on service when it changes", func() {
@ -463,7 +617,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return k8sClient.Get(ctx, client.ObjectKey{Name: scaleSetListenerName(autoscalingRunnerSet), Namespace: autoscalingRunnerSet.Namespace}, new(v1alpha1.AutoscalingListener))
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(Succeed(), "Listener should be created")
autoscalingRunnerSetTestInterval,
).Should(Succeed(), "Listener should be created")
patched := autoscalingRunnerSet.DeepCopy()
patched.Spec.RunnerGroup = "testgroup2"
@ -485,7 +640,8 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
return updated.Annotations[AnnotationKeyGitHubRunnerGroupName], nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the new runner group in its annotation")
autoscalingRunnerSetTestInterval,
).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the new runner group in its annotation")
// delete the annotation and it should be re-added
patched = autoscalingRunnerSet.DeepCopy()
@ -642,13 +798,14 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
).Should(BeTrue(), "AutoscalingRunnerSet should be created")
runnerSetList := new(v1alpha1.EphemeralRunnerSetList)
Eventually(func() (int, error) {
err := k8sClient.List(ctx, runnerSetList, client.InNamespace(ars.Namespace))
if err != nil {
return 0, err
}
return len(runnerSetList.Items), nil
},
Eventually(
func() (int, error) {
err := k8sClient.List(ctx, runnerSetList, client.InNamespace(ars.Namespace))
if err != nil {
return 0, err
}
return len(runnerSetList.Items), nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval,
).Should(BeEquivalentTo(1), "Failed to fetch runner set list")

View File

@ -102,6 +102,13 @@ func WithSystemInfo(info scaleset.SystemInfo) ClientOption {
}
}
// WithCreateRunnerScaleSetFunc configures a function to handle CreateRunnerScaleSet calls dynamically
func WithCreateRunnerScaleSetFunc(fn func(context.Context, *scaleset.RunnerScaleSet) (*scaleset.RunnerScaleSet, error)) ClientOption {
return func(c *Client) {
c.createRunnerScaleSetFunc = fn
}
}
// WithUpdateRunnerScaleSetFunc configures a function to handle UpdateRunnerScaleSet calls dynamically
func WithUpdateRunnerScaleSetFunc(fn func(context.Context, int, *scaleset.RunnerScaleSet) (*scaleset.RunnerScaleSet, error)) ClientOption {
return func(c *Client) {
@ -112,6 +119,7 @@ func WithUpdateRunnerScaleSetFunc(fn func(context.Context, int, *scaleset.Runner
// Client implements multiclient.Client interface for testing
type Client struct {
systemInfo scaleset.SystemInfo
createRunnerScaleSetFunc func(context.Context, *scaleset.RunnerScaleSet) (*scaleset.RunnerScaleSet, error)
updateRunnerScaleSetFunc func(context.Context, int, *scaleset.RunnerScaleSet) (*scaleset.RunnerScaleSet, error)
getRunnerScaleSetResult struct {
@ -215,6 +223,9 @@ func (c *Client) GetRunnerScaleSetByID(ctx context.Context, runnerScaleSetID int
}
func (c *Client) CreateRunnerScaleSet(ctx context.Context, runnerScaleSet *scaleset.RunnerScaleSet) (*scaleset.RunnerScaleSet, error) {
if c.createRunnerScaleSetFunc != nil {
return c.createRunnerScaleSetFunc(ctx, runnerScaleSet)
}
return c.createRunnerScaleSetResult.RunnerScaleSet, c.createRunnerScaleSetResult.err
}

View File

@ -43,6 +43,25 @@ You can follow [this troubleshooting guide](https://docs.github.com/en/actions/h
## Changelog
### 0.14.2
1. Fix orphan no-permission ServiceAccount in kubernetes-novolume mode [#4455](https://github.com/actions/actions-runner-controller/pull/4455)
1. Updates: runner to v2.334.0 [#4467](https://github.com/actions/actions-runner-controller/pull/4467)
1. Add option to disable workqueue bucket rate limiter [#4451](https://github.com/actions/actions-runner-controller/pull/4451)
1. Add a flag for enabling pprof on the controller manager [#4449](https://github.com/actions/actions-runner-controller/pull/4449)
1. Add health and readiness probes to controller manager [#4459](https://github.com/actions/actions-runner-controller/pull/4459)
1. Fix empty GVK in OwnerReferences for modern controllers [#4475](https://github.com/actions/actions-runner-controller/pull/4475)
1. Fix: Detect init container failure in EphemeralRunner controller [#4457](https://github.com/actions/actions-runner-controller/pull/4457)
1. Bump the actions group with 3 updates [#4483](https://github.com/actions/actions-runner-controller/pull/4483)
1. Render empty arrays for kubernetes-novolume volumes fields [#4461](https://github.com/actions/actions-runner-controller/pull/4461)
1. Fix secret reconciliation updates for the listener pod [#4492](https://github.com/actions/actions-runner-controller/pull/4492)
1. Fix job execution duration when runner assign time is not set [#4472](https://github.com/actions/actions-runner-controller/pull/4472)
1. Update CODEOWNERS [#4495](https://github.com/actions/actions-runner-controller/pull/4495)
1. Bump Go to 1.26.2 to fix critical security vulnerabilities [#4491](https://github.com/actions/actions-runner-controller/pull/4491)
1. Fix helm chart validation workflow [#4479](https://github.com/actions/actions-runner-controller/pull/4479)
1. Port rate limiter to experimental charts [#4478](https://github.com/actions/actions-runner-controller/pull/4478)
1. Bump Go to 1.26.3 [#4504](https://github.com/actions/actions-runner-controller/pull/4504)
### 0.14.1
1. Fix null field for resource metadata fields in experimental chart [#4419](https://github.com/actions/actions-runner-controller/pull/4419)

View File

@ -85,7 +85,7 @@ func (c *GitHubConfig) GitHubAPIURL(path string) *url.URL {
result.Host = fmt.Sprintf("api.%s", c.ConfigURL.Host)
result.Path = ""
if strings.EqualFold("www.github.com", c.ConfigURL.Host) {
if c.ConfigURL.Host == "www.github.com" {
// re-routing www.github.com to api.github.com
result.Host = "api.github.com"
}
@ -102,8 +102,8 @@ func isHostedGitHubURL(u *url.URL) bool {
return false
}
return strings.EqualFold(u.Host, "github.com") ||
strings.EqualFold(u.Host, "www.github.com") ||
strings.EqualFold(u.Host, "github.localhost") ||
return u.Host == "github.com" ||
u.Host == "www.github.com" ||
u.Host == "github.localhost" ||
strings.HasSuffix(u.Host, ".ghe.com")
}

4
go.mod
View File

@ -1,12 +1,12 @@
module github.com/actions/actions-runner-controller
go 1.26.2
go 1.26.3
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.3.0
github.com/actions/scaleset v0.4.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

@ -27,6 +27,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.3.0 h1:y5/ClYLJXFuGCikzILOOPhaCShAcL6K0mnUtjDKFxVw=
github.com/actions/scaleset v0.3.0/go.mod h1:2L2I6rggFWV+zprDet6y7y7Vkm3HPudaup78eSc79Uo=
github.com/actions/scaleset v0.4.0 h1:691GC2AkHb3ZGjfNvatboYoRS7CLr3+4VcZk/6w9IbM=
github.com/actions/scaleset v0.4.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.41.3 h1:4kQ/fa22KjDt13QCy1+bYADvdgcxpfH18f0zP542kZA=

View File

@ -783,26 +783,30 @@ func (e *env) installActionsRunnerController(t *testing.T, repo, tag, testID, ch
}
if e.useApp {
varEnv = append(varEnv,
varEnv = append(
varEnv,
"ACCEPTANCE_TEST_SECRET_TYPE=app",
"APP_ID="+e.appID,
"APP_INSTALLATION_ID="+e.appInstallationID,
"APP_PRIVATE_KEY_FILE="+e.appPrivateKeyFile,
)
} else {
varEnv = append(varEnv,
varEnv = append(
varEnv,
"ACCEPTANCE_TEST_SECRET_TYPE=token",
"GITHUB_TOKEN="+e.githubToken,
)
}
if e.logFormat != "" {
varEnv = append(varEnv,
varEnv = append(
varEnv,
"LOG_FORMAT="+e.logFormat,
)
}
varEnv = append(varEnv,
varEnv = append(
varEnv,
"GITHUB_WEBHOOK_SERVER_ENV_NAME="+c.GithubWebhookServerEnvName,
"GITHUB_WEBHOOK_SERVER_ENV_VALUE="+c.GithubWebhookServerEnvValue,
)
@ -909,20 +913,24 @@ func (e *env) do(t *testing.T, op string, kind DeployKind, testID string, env ..
}
if e.dockerdWithinRunnerContainer {
varEnv = append(varEnv,
varEnv = append(
varEnv,
"RUNNER_DOCKERD_WITHIN_RUNNER_CONTAINER=true",
)
if e.rootlessDocker {
varEnv = append(varEnv,
varEnv = append(
varEnv,
"RUNNER_NAME="+e.vars.runnerRootlessDindImageRepo,
)
} else {
varEnv = append(varEnv,
varEnv = append(
varEnv,
"RUNNER_NAME="+e.vars.runnerDindImageRepo,
)
}
} else {
varEnv = append(varEnv,
varEnv = append(
varEnv,
"RUNNER_DOCKERD_WITHIN_RUNNER_CONTAINER=false",
"RUNNER_NAME="+e.vars.runnerImageRepo,
)
@ -1062,14 +1070,16 @@ func installActionsWorkflow(t *testing.T, testName, runnerLabel, testResultCMNam
if !kubernetesContainerMode {
if kind == RunnerDeployments {
steps = append(steps,
steps = append(
steps,
testing.Step{
Run: sudo + "mkdir -p \"${RUNNER_TOOL_CACHE}\" \"${HOME}/.cache\"",
},
)
if useSudo {
steps = append(steps,
steps = append(
steps,
testing.Step{
// This might be the easiest way to handle permissions without use of securityContext
// https://stackoverflow.com/questions/50156124/kubernetes-nfs-persistent-volumes-permission-denied#comment107483717_53186320
@ -1080,7 +1090,8 @@ func installActionsWorkflow(t *testing.T, testName, runnerLabel, testResultCMNam
}
if useSudo {
steps = append(steps,
steps = append(
steps,
testing.Step{
// This might be the easiest way to handle permissions without use of securityContext
// https://stackoverflow.com/questions/50156124/kubernetes-nfs-persistent-volumes-permission-denied#comment107483717_53186320
@ -1102,18 +1113,20 @@ func installActionsWorkflow(t *testing.T, testName, runnerLabel, testResultCMNam
)
}
steps = append(steps,
steps = append(
steps,
testing.Step{
Uses: "actions/setup-go@v3",
With: &testing.With{
GoVersion: "1.26.1",
GoVersion: "1.26.3",
},
},
)
// Ensure both the alias and the full command work after
// https://github.com/actions/actions-runner-controller/pull/2326
steps = append(steps,
steps = append(
steps,
testing.Step{
Run: "docker-compose version",
},
@ -1123,7 +1136,8 @@ func installActionsWorkflow(t *testing.T, testName, runnerLabel, testResultCMNam
)
}
steps = append(steps,
steps = append(
steps,
testing.Step{
Run: "go version",
},
@ -1166,19 +1180,21 @@ func installActionsWorkflow(t *testing.T, testName, runnerLabel, testResultCMNam
if useCustomDockerContext {
setupBuildXActionWith.Endpoint = "mycontext"
steps = append(steps, testing.Step{
// https://github.com/docker/buildx/issues/413#issuecomment-710660155
// To prevent setup-buildx-action from failing with:
// error: could not create a builder instance with TLS data loaded from environment. Please use `docker context create <context-name>` to create a context for current environment and then create a builder instance with `docker buildx create <context-name>`
Run: "docker context create mycontext",
},
steps = append(
steps, testing.Step{
// https://github.com/docker/buildx/issues/413#issuecomment-710660155
// To prevent setup-buildx-action from failing with:
// error: could not create a builder instance with TLS data loaded from environment. Please use `docker context create <context-name>` to create a context for current environment and then create a builder instance with `docker buildx create <context-name>`
Run: "docker context create mycontext",
},
testing.Step{
Run: "docker context use mycontext",
},
)
}
steps = append(steps,
steps = append(
steps,
testing.Step{
Name: "Set up Docker Buildx",
Uses: "docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2",
@ -1203,7 +1219,8 @@ func installActionsWorkflow(t *testing.T, testName, runnerLabel, testResultCMNam
)
if useSudo {
steps = append(steps,
steps = append(
steps,
testing.Step{
// https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#local-cache
// See https://github.com/moby/buildkit/issues/1896 for why this is needed
@ -1218,7 +1235,8 @@ func installActionsWorkflow(t *testing.T, testName, runnerLabel, testResultCMNam
if useSudo {
if kind == RunnerDeployments {
steps = append(steps,
steps = append(
steps,
testing.Step{
// https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#local-cache
// See https://github.com/moby/buildkit/issues/1896 for why this is needed
@ -1232,7 +1250,8 @@ func installActionsWorkflow(t *testing.T, testName, runnerLabel, testResultCMNam
}
}
steps = append(steps,
steps = append(
steps,
testing.Step{
Uses: "azure/setup-kubectl@3e0aec4d80787158d308d7b364cb1b702e7feb7f",
With: &testing.With{