diff --git a/.github/workflows/gha-validate-chart.yaml b/.github/workflows/gha-validate-chart.yaml index cfcad8fcd3..d9314cc3e5 100644 --- a/.github/workflows/gha-validate-chart.yaml +++ b/.github/workflows/gha-validate-chart.yaml @@ -65,23 +65,6 @@ 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 @@ -132,15 +115,53 @@ jobs: 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<> $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/... diff --git a/charts/.ci/ct-config-gha.yaml b/charts/.ci/ct-config-gha.yaml index b0a15a3726..095e6573d7 100644 --- a/charts/.ci/ct-config-gha.yaml +++ b/charts/.ci/ct-config-gha.yaml @@ -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 diff --git a/charts/gha-runner-scale-set-controller-experimental/templates/_controller_template.tpl b/charts/gha-runner-scale-set-controller-experimental/templates/_controller_template.tpl index 44a17b3ce8..18cd6ccfc6 100644 --- a/charts/gha-runner-scale-set-controller-experimental/templates/_controller_template.tpl +++ b/charts/gha-runner-scale-set-controller-experimental/templates/_controller_template.tpl @@ -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 }} diff --git a/charts/gha-runner-scale-set-controller-experimental/tests/controller_deployment_rate_limiter_test.yaml b/charts/gha-runner-scale-set-controller-experimental/tests/controller_deployment_rate_limiter_test.yaml new file mode 100644 index 0000000000..30039ed32c --- /dev/null +++ b/charts/gha-runner-scale-set-controller-experimental/tests/controller_deployment_rate_limiter_test.yaml @@ -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" diff --git a/charts/gha-runner-scale-set-controller-experimental/tests/template_test.go b/charts/gha-runner-scale-set-controller-experimental/tests/template_test.go deleted file mode 100644 index 80870ec350..0000000000 --- a/charts/gha-runner-scale-set-controller-experimental/tests/template_test.go +++ /dev/null @@ -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"]) -} diff --git a/charts/gha-runner-scale-set-controller-experimental/values.yaml b/charts/gha-runner-scale-set-controller-experimental/values.yaml index 75bcc31422..a06d86c695 100644 --- a/charts/gha-runner-scale-set-controller-experimental/values.yaml +++ b/charts/gha-runner-scale-set-controller-experimental/values.yaml @@ -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" diff --git a/charts/gha-runner-scale-set-experimental/tests/template_test.go b/charts/gha-runner-scale-set-experimental/tests/template_test.go deleted file mode 100644 index 2a1aa6152b..0000000000 --- a/charts/gha-runner-scale-set-experimental/tests/template_test.go +++ /dev/null @@ -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"]) -}