From 86d7893d61b95af3c621455d23694a9d5fa216b4 Mon Sep 17 00:00:00 2001 From: Yusuke Kuoka Date: Tue, 22 Nov 2022 12:08:29 +0900 Subject: [PATCH] breaking: Make legacy webhook scale triggers no-op (#2001) Ref #1607 --- .../horizontal_runner_autoscaler_webhook.go | 50 - ..._runner_autoscaler_webhook_on_check_run.go | 53 - ...nner_autoscaler_webhook_on_pull_request.go | 32 - ...ontal_runner_autoscaler_webhook_on_push.go | 20 - ...rizontal_runner_autoscaler_webhook_test.go | 72 -- controllers/integration_test.go | 969 ------------------ 6 files changed, 1196 deletions(-) delete mode 100644 controllers/horizontal_runner_autoscaler_webhook_on_check_run.go delete mode 100644 controllers/horizontal_runner_autoscaler_webhook_on_pull_request.go delete mode 100644 controllers/horizontal_runner_autoscaler_webhook_on_push.go diff --git a/controllers/horizontal_runner_autoscaler_webhook.go b/controllers/horizontal_runner_autoscaler_webhook.go index 0a969390..58c1f7a1 100644 --- a/controllers/horizontal_runner_autoscaler_webhook.go +++ b/controllers/horizontal_runner_autoscaler_webhook.go @@ -175,56 +175,6 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) Handle(w http.Respons enterpriseSlug := enterpriseEvent.Enterprise.Slug switch e := event.(type) { - case *gogithub.PushEvent: - target, err = autoscaler.getScaleUpTarget( - context.TODO(), - log, - e.Repo.GetName(), - e.Repo.Owner.GetLogin(), - e.Repo.Owner.GetType(), - // Most go-github Event types don't seem to contain Enteprirse(.Slug) fields - // we need, so we parse it by ourselves. - enterpriseSlug, - autoscaler.MatchPushEvent(e), - ) - case *gogithub.PullRequestEvent: - target, err = autoscaler.getScaleUpTarget( - context.TODO(), - log, - e.Repo.GetName(), - e.Repo.Owner.GetLogin(), - e.Repo.Owner.GetType(), - // Most go-github Event types don't seem to contain Enteprirse(.Slug) fields - // we need, so we parse it by ourselves. - enterpriseSlug, - autoscaler.MatchPullRequestEvent(e), - ) - - if pullRequest := e.PullRequest; pullRequest != nil { - log = log.WithValues( - "pullRequest.base.ref", e.PullRequest.Base.GetRef(), - "action", e.GetAction(), - ) - } - case *gogithub.CheckRunEvent: - target, err = autoscaler.getScaleUpTarget( - context.TODO(), - log, - e.Repo.GetName(), - e.Repo.Owner.GetLogin(), - e.Repo.Owner.GetType(), - // Most go-github Event types don't seem to contain Enteprirse(.Slug) fields - // we need, so we parse it by ourselves. - enterpriseSlug, - autoscaler.MatchCheckRunEvent(e), - ) - - if checkRun := e.GetCheckRun(); checkRun != nil { - log = log.WithValues( - "checkRun.status", checkRun.GetStatus(), - "action", e.GetAction(), - ) - } case *gogithub.WorkflowJobEvent: if workflowJob := e.GetWorkflowJob(); workflowJob != nil { log = log.WithValues( diff --git a/controllers/horizontal_runner_autoscaler_webhook_on_check_run.go b/controllers/horizontal_runner_autoscaler_webhook_on_check_run.go deleted file mode 100644 index 1b30cced..00000000 --- a/controllers/horizontal_runner_autoscaler_webhook_on_check_run.go +++ /dev/null @@ -1,53 +0,0 @@ -package controllers - -import ( - "github.com/actions-runner-controller/actions-runner-controller/api/v1alpha1" - "github.com/actions-runner-controller/actions-runner-controller/pkg/actionsglob" - "github.com/google/go-github/v47/github" -) - -func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) MatchCheckRunEvent(event *github.CheckRunEvent) func(scaleUpTrigger v1alpha1.ScaleUpTrigger) bool { - return func(scaleUpTrigger v1alpha1.ScaleUpTrigger) bool { - g := scaleUpTrigger.GitHubEvent - - if g == nil { - return false - } - - cr := g.CheckRun - - if cr == nil { - return false - } - - if !matchTriggerConditionAgainstEvent(cr.Types, event.Action) { - return false - } - - if cr.Status != "" && (event.CheckRun == nil || event.CheckRun.Status == nil || *event.CheckRun.Status != cr.Status) { - return false - } - - if checkRun := event.CheckRun; checkRun != nil && len(cr.Names) > 0 { - for _, pat := range cr.Names { - if r := actionsglob.Match(pat, checkRun.GetName()); r { - return true - } - } - - return false - } - - if len(scaleUpTrigger.GitHubEvent.CheckRun.Repositories) > 0 { - for _, repository := range scaleUpTrigger.GitHubEvent.CheckRun.Repositories { - if repository == *event.Repo.Name { - return true - } - } - - return false - } - - return true - } -} diff --git a/controllers/horizontal_runner_autoscaler_webhook_on_pull_request.go b/controllers/horizontal_runner_autoscaler_webhook_on_pull_request.go deleted file mode 100644 index 892229d3..00000000 --- a/controllers/horizontal_runner_autoscaler_webhook_on_pull_request.go +++ /dev/null @@ -1,32 +0,0 @@ -package controllers - -import ( - "github.com/actions-runner-controller/actions-runner-controller/api/v1alpha1" - "github.com/google/go-github/v47/github" -) - -func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) MatchPullRequestEvent(event *github.PullRequestEvent) func(scaleUpTrigger v1alpha1.ScaleUpTrigger) bool { - return func(scaleUpTrigger v1alpha1.ScaleUpTrigger) bool { - g := scaleUpTrigger.GitHubEvent - - if g == nil { - return false - } - - pr := g.PullRequest - - if pr == nil { - return false - } - - if !matchTriggerConditionAgainstEvent(pr.Types, event.Action) { - return false - } - - if !matchTriggerConditionAgainstEvent(pr.Branches, event.PullRequest.Base.Ref) { - return false - } - - return true - } -} diff --git a/controllers/horizontal_runner_autoscaler_webhook_on_push.go b/controllers/horizontal_runner_autoscaler_webhook_on_push.go deleted file mode 100644 index 675f353d..00000000 --- a/controllers/horizontal_runner_autoscaler_webhook_on_push.go +++ /dev/null @@ -1,20 +0,0 @@ -package controllers - -import ( - "github.com/actions-runner-controller/actions-runner-controller/api/v1alpha1" - "github.com/google/go-github/v47/github" -) - -func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) MatchPushEvent(event *github.PushEvent) func(scaleUpTrigger v1alpha1.ScaleUpTrigger) bool { - return func(scaleUpTrigger v1alpha1.ScaleUpTrigger) bool { - g := scaleUpTrigger.GitHubEvent - - if g == nil { - return false - } - - push := g.Push - - return push != nil - } -} diff --git a/controllers/horizontal_runner_autoscaler_webhook_test.go b/controllers/horizontal_runner_autoscaler_webhook_test.go index d1a336e6..e231bd52 100644 --- a/controllers/horizontal_runner_autoscaler_webhook_test.go +++ b/controllers/horizontal_runner_autoscaler_webhook_test.go @@ -30,78 +30,6 @@ func init() { _ = actionsv1alpha1.AddToScheme(sc) } -func TestOrgWebhookCheckRun(t *testing.T) { - f, err := os.Open("testdata/org_webhook_check_run_payload.json") - if err != nil { - t.Fatalf("could not open the fixture: %s", err) - } - defer f.Close() - var e github.CheckRunEvent - if err := json.NewDecoder(f).Decode(&e); err != nil { - t.Fatalf("invalid json: %s", err) - } - testServer(t, - "check_run", - &e, - 200, - "no horizontalrunnerautoscaler to scale for this github event", - ) -} - -func TestRepoWebhookCheckRun(t *testing.T) { - f, err := os.Open("testdata/repo_webhook_check_run_payload.json") - if err != nil { - t.Fatalf("could not open the fixture: %s", err) - } - defer f.Close() - var e github.CheckRunEvent - if err := json.NewDecoder(f).Decode(&e); err != nil { - t.Fatalf("invalid json: %s", err) - } - testServer(t, - "check_run", - &e, - 200, - "no horizontalrunnerautoscaler to scale for this github event", - ) -} - -func TestWebhookPullRequest(t *testing.T) { - testServer(t, - "pull_request", - &github.PullRequestEvent{ - PullRequest: &github.PullRequest{ - Base: &github.PullRequestBranch{ - Ref: github.String("main"), - }, - }, - Repo: &github.Repository{ - Name: github.String("myorg/myrepo"), - Organization: &github.Organization{ - Name: github.String("myorg"), - }, - }, - Action: github.String("created"), - }, - 200, - "no horizontalrunnerautoscaler to scale for this github event", - ) -} - -func TestWebhookPush(t *testing.T) { - testServer(t, - "push", - &github.PushEvent{ - Repo: &github.PushEventRepository{ - Name: github.String("myrepo"), - Organization: github.String("myorg"), - }, - }, - 200, - "no horizontalrunnerautoscaler to scale for this github event", - ) -} - func TestWebhookPing(t *testing.T) { testServer(t, "ping", diff --git a/controllers/integration_test.go b/controllers/integration_test.go index a0d7d22c..614e20ff 100644 --- a/controllers/integration_test.go +++ b/controllers/integration_test.go @@ -192,351 +192,6 @@ var _ = Context("INTEGRATION: Inside of a new namespace", func() { Describe("when no existing resources exist", func() { - It("should create and scale organizational runners without any scaling metrics on pull_request event", func() { - name := "example-runnerdeploy" - - { - rd := &actionsv1alpha1.RunnerDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.RunnerDeploymentSpec{ - Replicas: intPtr(1), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "foo": "bar", - }, - }, - Template: actionsv1alpha1.RunnerTemplate{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: actionsv1alpha1.RunnerSpec{ - RunnerConfig: actionsv1alpha1.RunnerConfig{ - Organization: "test", - Image: "bar", - Group: "baz", - }, - RunnerPodSpec: actionsv1alpha1.RunnerPodSpec{ - Env: []corev1.EnvVar{ - {Name: "FOO", Value: "FOOVALUE"}, - }, - }, - }, - }, - }, - } - - ExpectCreate(ctx, rd, "test RunnerDeployment") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1) - } - - // Scale-up to 2 replicas - { - hra := &actionsv1alpha1.HorizontalRunnerAutoscaler{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.HorizontalRunnerAutoscalerSpec{ - ScaleTargetRef: actionsv1alpha1.ScaleTargetRef{ - Name: name, - }, - MinReplicas: intPtr(2), - MaxReplicas: intPtr(5), - ScaleDownDelaySecondsAfterScaleUp: intPtr(1), - Metrics: nil, - ScaleUpTriggers: []actionsv1alpha1.ScaleUpTrigger{ - { - GitHubEvent: &actionsv1alpha1.GitHubEventScaleUpTriggerSpec{ - PullRequest: &actionsv1alpha1.PullRequestSpec{ - Types: []string{"created"}, - Branches: []string{"main"}, - }, - }, - Amount: 1, - Duration: metav1.Duration{Duration: time.Minute}, - }, - }, - }, - } - - ExpectCreate(ctx, hra, "test HorizontalRunnerAutoscaler") - - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 2) - } - - { - env.ExpectRegisteredNumberCountEventuallyEquals(2, "count of fake runners after HRA creation") - } - - // Scale-up to 3 replicas on second pull_request create webhook event - { - env.SendOrgPullRequestEvent("test", "valid", "main", "created") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 3, "runners after second webhook event") - } - }) - - It("should create and scale organization's repository runners on pull_request event", func() { - name := "example-runnerdeploy" - - { - rd := &actionsv1alpha1.RunnerDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.RunnerDeploymentSpec{ - Replicas: intPtr(1), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "foo": "bar", - }, - }, - Template: actionsv1alpha1.RunnerTemplate{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: actionsv1alpha1.RunnerSpec{ - RunnerConfig: actionsv1alpha1.RunnerConfig{ - Repository: "test/valid", - Image: "bar", - Group: "baz", - }, - RunnerPodSpec: actionsv1alpha1.RunnerPodSpec{ - Env: []corev1.EnvVar{ - {Name: "FOO", Value: "FOOVALUE"}, - }, - }, - }, - }, - }, - } - - ExpectCreate(ctx, rd, "test RunnerDeployment") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1) - } - - { - ExpectRunnerDeploymentEventuallyUpdates(ctx, ns.Name, name, func(rd *actionsv1alpha1.RunnerDeployment) { - rd.Spec.Replicas = intPtr(2) - }) - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 2) - } - - // Scale-up to 3 replicas - { - hra := &actionsv1alpha1.HorizontalRunnerAutoscaler{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.HorizontalRunnerAutoscalerSpec{ - ScaleTargetRef: actionsv1alpha1.ScaleTargetRef{ - Name: name, - }, - MinReplicas: intPtr(1), - MaxReplicas: intPtr(3), - ScaleDownDelaySecondsAfterScaleUp: intPtr(1), - Metrics: []actionsv1alpha1.MetricSpec{ - { - Type: actionsv1alpha1.AutoscalingMetricTypeTotalNumberOfQueuedAndInProgressWorkflowRuns, - }, - }, - ScaleUpTriggers: []actionsv1alpha1.ScaleUpTrigger{ - { - GitHubEvent: &actionsv1alpha1.GitHubEventScaleUpTriggerSpec{ - PullRequest: &actionsv1alpha1.PullRequestSpec{ - Types: []string{"created"}, - Branches: []string{"main"}, - }, - }, - Amount: 1, - Duration: metav1.Duration{Duration: time.Minute}, - }, - }, - }, - } - - ExpectCreate(ctx, hra, "test HorizontalRunnerAutoscaler") - - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 3) - } - - { - env.ExpectRegisteredNumberCountEventuallyEquals(3, "count of fake runners after HRA creation") - } - - // Scale-down to 1 replica - { - time.Sleep(time.Second) - - env.Responses.ListRepositoryWorkflowRuns.Body = workflowRunsFor1Replicas - env.Responses.ListRepositoryWorkflowRuns.Statuses["queued"] = workflowRunsFor1Replicas_queued - env.Responses.ListRepositoryWorkflowRuns.Statuses["in_progress"] = workflowRunsFor1Replicas_in_progress - - var hra actionsv1alpha1.HorizontalRunnerAutoscaler - - err := k8sClient.Get(ctx, types.NamespacedName{Namespace: ns.Name, Name: name}, &hra) - - Expect(err).NotTo(HaveOccurred(), "failed to get test HorizontalRunnerAutoscaler resource") - - hra.Annotations = map[string]string{ - "force-update": "1", - } - - err = k8sClient.Update(ctx, &hra) - - Expect(err).NotTo(HaveOccurred(), "failed to get test HorizontalRunnerAutoscaler resource") - - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1, "runners after HRA force update for scale-down") - } - - // Scale-up to 2 replicas on first pull_request create webhook event - { - env.SendOrgPullRequestEvent("test", "valid", "main", "created") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1, "runner sets after webhook") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 2, "runners after first webhook event") - } - - // Scale-up to 3 replicas on second pull_request create webhook event - { - env.SendOrgPullRequestEvent("test", "valid", "main", "created") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 3, "runners after second webhook event") - } - }) - - It("should create and scale organization's repository runners on check_run event", func() { - name := "example-runnerdeploy" - - { - rd := &actionsv1alpha1.RunnerDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.RunnerDeploymentSpec{ - Replicas: intPtr(1), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "foo": "bar", - }, - }, - Template: actionsv1alpha1.RunnerTemplate{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: actionsv1alpha1.RunnerSpec{ - RunnerConfig: actionsv1alpha1.RunnerConfig{ - Repository: "test/valid", - Image: "bar", - Group: "baz", - }, - RunnerPodSpec: actionsv1alpha1.RunnerPodSpec{ - Env: []corev1.EnvVar{ - {Name: "FOO", Value: "FOOVALUE"}, - }, - }, - }, - }, - }, - } - - ExpectCreate(ctx, rd, "test RunnerDeployment") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1) - env.ExpectRegisteredNumberCountEventuallyEquals(1, "count of fake list runners") - } - - // Scale-up to 3 replicas by the default TotalNumberOfQueuedAndInProgressWorkflowRuns-based scaling - // See workflowRunsFor3Replicas_queued and workflowRunsFor3Replicas_in_progress for GitHub List-Runners API responses - // used while testing. - { - hra := &actionsv1alpha1.HorizontalRunnerAutoscaler{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.HorizontalRunnerAutoscalerSpec{ - ScaleTargetRef: actionsv1alpha1.ScaleTargetRef{ - Name: name, - }, - MinReplicas: intPtr(1), - MaxReplicas: intPtr(5), - ScaleDownDelaySecondsAfterScaleUp: intPtr(1), - Metrics: []actionsv1alpha1.MetricSpec{ - { - Type: actionsv1alpha1.AutoscalingMetricTypeTotalNumberOfQueuedAndInProgressWorkflowRuns, - }, - }, - ScaleUpTriggers: []actionsv1alpha1.ScaleUpTrigger{ - { - GitHubEvent: &actionsv1alpha1.GitHubEventScaleUpTriggerSpec{ - CheckRun: &actionsv1alpha1.CheckRunSpec{ - Types: []string{"created"}, - Status: "pending", - Repositories: []string{"valid", "foo", "bar"}, - }, - }, - Amount: 1, - Duration: metav1.Duration{Duration: time.Minute}, - }, - }, - }, - } - - ExpectCreate(ctx, hra, "test HorizontalRunnerAutoscaler") - - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 3) - env.ExpectRegisteredNumberCountEventuallyEquals(3, "count of fake list runners") - env.SyncRunnerRegistrations() - ExpectRunnerCountEventuallyEquals(ctx, ns.Name, 3) - } - - // Scale-up to 4 replicas on first check_run create webhook event - { - env.SendOrgCheckRunEvent("test", "valid", "pending", "created") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1, "runner sets after webhook") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 4, "runners after first webhook event") - env.ExpectRegisteredNumberCountEventuallyEquals(4, "count of fake list runners") - env.SyncRunnerRegistrations() - ExpectRunnerCountEventuallyEquals(ctx, ns.Name, 4) - } - - // Scale-up to 5 replicas on second check_run create webhook event - replicasAfterSecondWebhook := 5 - { - env.SendOrgCheckRunEvent("test", "valid", "pending", "created") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, replicasAfterSecondWebhook, "runners after second webhook event") - env.ExpectRegisteredNumberCountEventuallyEquals(replicasAfterSecondWebhook, "count of fake list runners") - env.SyncRunnerRegistrations() - ExpectRunnerCountEventuallyEquals(ctx, ns.Name, replicasAfterSecondWebhook) - } - - // Do not scale-up on third check_run create webhook event - // example repo is not in specified in actionsv1alpha1.CheckRunSpec.Repositories - { - env.SendOrgCheckRunEvent("test", "example", "pending", "created") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, replicasAfterSecondWebhook, "runners after third webhook event") - env.ExpectRegisteredNumberCountEventuallyEquals(replicasAfterSecondWebhook, "count of fake list runners") - env.SyncRunnerRegistrations() - ExpectRunnerCountEventuallyEquals(ctx, ns.Name, replicasAfterSecondWebhook) - } - }) - It("should create and scale organization's repository runners on workflow_job event", func() { name := "example-runnerdeploy" @@ -637,543 +292,6 @@ var _ = Context("INTEGRATION: Inside of a new namespace", func() { } }) - It("should create and scale organization's repository runners only on check_run event", func() { - name := "example-runnerdeploy" - - { - rd := &actionsv1alpha1.RunnerDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.RunnerDeploymentSpec{ - Replicas: intPtr(1), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "foo": "bar", - }, - }, - Template: actionsv1alpha1.RunnerTemplate{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: actionsv1alpha1.RunnerSpec{ - RunnerConfig: actionsv1alpha1.RunnerConfig{ - Repository: "test/valid", - Image: "bar", - Group: "baz", - }, - RunnerPodSpec: actionsv1alpha1.RunnerPodSpec{ - Env: []corev1.EnvVar{ - {Name: "FOO", Value: "FOOVALUE"}, - }, - }, - }, - }, - }, - } - - ExpectCreate(ctx, rd, "test RunnerDeployment") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1) - env.ExpectRegisteredNumberCountEventuallyEquals(1, "count of fake list runners") - } - - // Scale-up to 1 replica via ScaleUpTriggers.GitHubEvent.CheckRun based scaling - { - hra := &actionsv1alpha1.HorizontalRunnerAutoscaler{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.HorizontalRunnerAutoscalerSpec{ - ScaleTargetRef: actionsv1alpha1.ScaleTargetRef{ - Name: name, - }, - MinReplicas: intPtr(1), - MaxReplicas: intPtr(5), - ScaleDownDelaySecondsAfterScaleUp: intPtr(1), - ScaleUpTriggers: []actionsv1alpha1.ScaleUpTrigger{ - { - GitHubEvent: &actionsv1alpha1.GitHubEventScaleUpTriggerSpec{ - CheckRun: &actionsv1alpha1.CheckRunSpec{ - Types: []string{"created"}, - Status: "pending", - }, - }, - Amount: 1, - Duration: metav1.Duration{Duration: time.Minute}, - }, - }, - }, - } - - ExpectCreate(ctx, hra, "test HorizontalRunnerAutoscaler") - - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1) - env.ExpectRegisteredNumberCountEventuallyEquals(1, "count of fake list runners") - } - - // Scale-up to 2 replicas on first check_run create webhook event - { - env.SendOrgCheckRunEvent("test", "valid", "pending", "created") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1, "runner sets after webhook") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 2, "runners after first webhook event") - env.ExpectRegisteredNumberCountEventuallyEquals(2, "count of fake list runners") - } - - // Scale-up to 3 replicas on second check_run create webhook event - { - env.SendOrgCheckRunEvent("test", "valid", "pending", "created") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 3, "runners after second webhook event") - env.ExpectRegisteredNumberCountEventuallyEquals(3, "count of fake list runners") - } - }) - - It("should create and scale user's repository runners on pull_request event", func() { - name := "example-runnerdeploy" - - { - rd := &actionsv1alpha1.RunnerDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.RunnerDeploymentSpec{ - Replicas: intPtr(1), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "foo": "bar", - }, - }, - Template: actionsv1alpha1.RunnerTemplate{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: actionsv1alpha1.RunnerSpec{ - RunnerConfig: actionsv1alpha1.RunnerConfig{ - Repository: "test/valid", - Image: "bar", - Group: "baz", - }, - RunnerPodSpec: actionsv1alpha1.RunnerPodSpec{ - Env: []corev1.EnvVar{ - {Name: "FOO", Value: "FOOVALUE"}, - }, - }, - }, - }, - }, - } - - ExpectCreate(ctx, rd, "test RunnerDeployment") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1) - } - - { - ExpectRunnerDeploymentEventuallyUpdates(ctx, ns.Name, name, func(rd *actionsv1alpha1.RunnerDeployment) { - rd.Spec.Replicas = intPtr(2) - }) - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 2) - } - - // Scale-up to 3 replicas - { - hra := &actionsv1alpha1.HorizontalRunnerAutoscaler{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.HorizontalRunnerAutoscalerSpec{ - ScaleTargetRef: actionsv1alpha1.ScaleTargetRef{ - Name: name, - }, - MinReplicas: intPtr(1), - MaxReplicas: intPtr(3), - ScaleDownDelaySecondsAfterScaleUp: intPtr(1), - Metrics: []actionsv1alpha1.MetricSpec{ - { - Type: actionsv1alpha1.AutoscalingMetricTypeTotalNumberOfQueuedAndInProgressWorkflowRuns, - }, - }, - ScaleUpTriggers: []actionsv1alpha1.ScaleUpTrigger{ - { - GitHubEvent: &actionsv1alpha1.GitHubEventScaleUpTriggerSpec{ - PullRequest: &actionsv1alpha1.PullRequestSpec{ - Types: []string{"created"}, - Branches: []string{"main"}, - }, - }, - Amount: 1, - Duration: metav1.Duration{Duration: time.Minute}, - }, - }, - }, - } - - ExpectCreate(ctx, hra, "test HorizontalRunnerAutoscaler") - - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 3) - } - - { - env.ExpectRegisteredNumberCountEventuallyEquals(3, "count of fake runners after HRA creation") - } - - // Scale-down to 1 replica - { - time.Sleep(time.Second) - - env.Responses.ListRepositoryWorkflowRuns.Body = workflowRunsFor1Replicas - env.Responses.ListRepositoryWorkflowRuns.Statuses["queued"] = workflowRunsFor1Replicas_queued - env.Responses.ListRepositoryWorkflowRuns.Statuses["in_progress"] = workflowRunsFor1Replicas_in_progress - - var hra actionsv1alpha1.HorizontalRunnerAutoscaler - - err := k8sClient.Get(ctx, types.NamespacedName{Namespace: ns.Name, Name: name}, &hra) - - Expect(err).NotTo(HaveOccurred(), "failed to get test HorizontalRunnerAutoscaler resource") - - hra.Annotations = map[string]string{ - "force-update": "1", - } - - err = k8sClient.Update(ctx, &hra) - - Expect(err).NotTo(HaveOccurred(), "failed to get test HorizontalRunnerAutoscaler resource") - - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1, "runners after HRA force update for scale-down") - ExpectHRADesiredReplicasEquals(ctx, ns.Name, name, 1, "runner deployment desired replicas") - } - - // Scale-up to 2 replicas on first pull_request create webhook event - { - env.SendUserPullRequestEvent("test", "valid", "main", "created") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1, "runner sets after webhook") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 2, "runners after first webhook event") - ExpectHRADesiredReplicasEquals(ctx, ns.Name, name, 2, "runner deployment desired replicas") - } - - // Scale-up to 3 replicas on second pull_request create webhook event - { - env.SendUserPullRequestEvent("test", "valid", "main", "created") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 3, "runners after second webhook event") - ExpectHRADesiredReplicasEquals(ctx, ns.Name, name, 3, "runner deployment desired replicas") - } - }) - - It("should create and scale user's repository runners only on pull_request event", func() { - name := "example-runnerdeploy" - - { - rd := &actionsv1alpha1.RunnerDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.RunnerDeploymentSpec{ - Replicas: intPtr(1), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "foo": "bar", - }, - }, - Template: actionsv1alpha1.RunnerTemplate{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: actionsv1alpha1.RunnerSpec{ - RunnerConfig: actionsv1alpha1.RunnerConfig{ - Repository: "test/valid", - Image: "bar", - Group: "baz", - }, - RunnerPodSpec: actionsv1alpha1.RunnerPodSpec{ - Env: []corev1.EnvVar{ - {Name: "FOO", Value: "FOOVALUE"}, - }, - }, - }, - }, - }, - } - - ExpectCreate(ctx, rd, "test RunnerDeployment") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1) - } - - { - hra := &actionsv1alpha1.HorizontalRunnerAutoscaler{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.HorizontalRunnerAutoscalerSpec{ - ScaleTargetRef: actionsv1alpha1.ScaleTargetRef{ - Name: name, - }, - MinReplicas: intPtr(1), - MaxReplicas: intPtr(3), - ScaleDownDelaySecondsAfterScaleUp: intPtr(1), - ScaleUpTriggers: []actionsv1alpha1.ScaleUpTrigger{ - { - GitHubEvent: &actionsv1alpha1.GitHubEventScaleUpTriggerSpec{ - PullRequest: &actionsv1alpha1.PullRequestSpec{ - Types: []string{"created"}, - Branches: []string{"main"}, - }, - }, - Amount: 1, - Duration: metav1.Duration{Duration: time.Minute}, - }, - }, - }, - } - - ExpectCreate(ctx, hra, "test HorizontalRunnerAutoscaler") - - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1) - } - - { - env.ExpectRegisteredNumberCountEventuallyEquals(1, "count of fake runners after HRA creation") - } - - // Scale-up to 2 replicas on first pull_request create webhook event - { - env.SendUserPullRequestEvent("test", "valid", "main", "created") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1, "runner sets after webhook") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 2, "runners after first webhook event") - ExpectHRADesiredReplicasEquals(ctx, ns.Name, name, 2, "runner deployment desired replicas") - } - - // Scale-up to 3 replicas on second pull_request create webhook event - { - env.SendUserPullRequestEvent("test", "valid", "main", "created") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 3, "runners after second webhook event") - ExpectHRADesiredReplicasEquals(ctx, ns.Name, name, 3, "runner deployment desired replicas") - } - }) - - It("should create and scale user's repository runners on check_run event", func() { - name := "example-runnerdeploy" - - { - rd := &actionsv1alpha1.RunnerDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.RunnerDeploymentSpec{ - Replicas: intPtr(1), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "foo": "bar", - }, - }, - Template: actionsv1alpha1.RunnerTemplate{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: actionsv1alpha1.RunnerSpec{ - RunnerConfig: actionsv1alpha1.RunnerConfig{ - Repository: "test/valid", - Image: "bar", - Group: "baz", - }, - RunnerPodSpec: actionsv1alpha1.RunnerPodSpec{ - Env: []corev1.EnvVar{ - {Name: "FOO", Value: "FOOVALUE"}, - }, - }, - }, - }, - }, - } - - ExpectCreate(ctx, rd, "test RunnerDeployment") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1) - env.ExpectRegisteredNumberCountEventuallyEquals(1, "count of fake list runners") - } - - // Scale-up to 3 replicas by the default TotalNumberOfQueuedAndInProgressWorkflowRuns-based scaling - // See workflowRunsFor3Replicas_queued and workflowRunsFor3Replicas_in_progress for GitHub List-Runners API responses - // used while testing. - { - hra := &actionsv1alpha1.HorizontalRunnerAutoscaler{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.HorizontalRunnerAutoscalerSpec{ - ScaleTargetRef: actionsv1alpha1.ScaleTargetRef{ - Name: name, - }, - MinReplicas: intPtr(1), - MaxReplicas: intPtr(5), - ScaleDownDelaySecondsAfterScaleUp: intPtr(1), - Metrics: []actionsv1alpha1.MetricSpec{ - { - Type: actionsv1alpha1.AutoscalingMetricTypeTotalNumberOfQueuedAndInProgressWorkflowRuns, - }, - }, - ScaleUpTriggers: []actionsv1alpha1.ScaleUpTrigger{ - { - GitHubEvent: &actionsv1alpha1.GitHubEventScaleUpTriggerSpec{ - CheckRun: &actionsv1alpha1.CheckRunSpec{ - Types: []string{"created"}, - Status: "pending", - }, - }, - Amount: 1, - Duration: metav1.Duration{Duration: time.Minute}, - }, - }, - }, - } - - ExpectCreate(ctx, hra, "test HorizontalRunnerAutoscaler") - - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 3) - env.ExpectRegisteredNumberCountEventuallyEquals(3, "count of fake list runners") - } - - // Scale-up to 4 replicas on first check_run create webhook event - { - env.SendUserCheckRunEvent("test", "valid", "pending", "created") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1, "runner sets after webhook") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 4, "runners after first webhook event") - env.ExpectRegisteredNumberCountEventuallyEquals(4, "count of fake list runners") - } - - // Scale-up to 5 replicas on second check_run create webhook event - { - env.SendUserCheckRunEvent("test", "valid", "pending", "created") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 5, "runners after second webhook event") - env.ExpectRegisteredNumberCountEventuallyEquals(5, "count of fake list runners") - } - }) - - It("should create and scale user's repository runners only on check_run event", func() { - name := "example-runnerdeploy" - - { - rd := &actionsv1alpha1.RunnerDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.RunnerDeploymentSpec{ - Replicas: intPtr(1), - Selector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "foo": "bar", - }, - }, - Template: actionsv1alpha1.RunnerTemplate{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "foo": "bar", - }, - }, - Spec: actionsv1alpha1.RunnerSpec{ - RunnerConfig: actionsv1alpha1.RunnerConfig{ - Repository: "test/valid", - Image: "bar", - Group: "baz", - }, - RunnerPodSpec: actionsv1alpha1.RunnerPodSpec{ - Env: []corev1.EnvVar{ - {Name: "FOO", Value: "FOOVALUE"}, - }, - }, - }, - }, - }, - } - - ExpectCreate(ctx, rd, "test RunnerDeployment") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1) - } - - { - env.ExpectRegisteredNumberCountEventuallyEquals(1, "count of fake list runners") - } - - // Scale-up to 3 replicas by the default TotalNumberOfQueuedAndInProgressWorkflowRuns-based scaling - // See workflowRunsFor3Replicas_queued and workflowRunsFor3Replicas_in_progress for GitHub List-Runners API responses - // used while testing. - { - hra := &actionsv1alpha1.HorizontalRunnerAutoscaler{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: ns.Name, - }, - Spec: actionsv1alpha1.HorizontalRunnerAutoscalerSpec{ - ScaleTargetRef: actionsv1alpha1.ScaleTargetRef{ - Name: name, - }, - MinReplicas: intPtr(1), - MaxReplicas: intPtr(5), - ScaleDownDelaySecondsAfterScaleUp: intPtr(1), - ScaleUpTriggers: []actionsv1alpha1.ScaleUpTrigger{ - { - GitHubEvent: &actionsv1alpha1.GitHubEventScaleUpTriggerSpec{ - CheckRun: &actionsv1alpha1.CheckRunSpec{ - Types: []string{"created"}, - Status: "pending", - }, - }, - Amount: 1, - Duration: metav1.Duration{Duration: time.Minute}, - }, - }, - }, - } - - ExpectCreate(ctx, hra, "test HorizontalRunnerAutoscaler") - - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1) - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 1) - } - - { - env.ExpectRegisteredNumberCountEventuallyEquals(1, "count of fake list runners") - } - - // Scale-up to 2 replicas on first check_run create webhook event - { - env.SendUserCheckRunEvent("test", "valid", "pending", "created") - ExpectRunnerSetsCountEventuallyEquals(ctx, ns.Name, 1, "runner sets after webhook") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 2, "runners after first webhook event") - env.ExpectRegisteredNumberCountEventuallyEquals(2, "count of fake list runners") - } - - // Scale-up to 3 replicas on second check_run create webhook event - { - env.SendUserCheckRunEvent("test", "valid", "pending", "created") - ExpectRunnerSetsManagedReplicasCountEventuallyEquals(ctx, ns.Name, 3, "runners after second webhook event") - env.ExpectRegisteredNumberCountEventuallyEquals(3, "count of fake list runners") - } - }) - It("should be able to scale visible organization runner group with default labels", func() { name := "example-runnerdeploy" @@ -1370,51 +488,6 @@ func (env *testEnvironment) ExpectRegisteredNumberCountEventuallyEquals(want int time.Second*10, time.Millisecond*500).Should(Equal(want), optionalDescriptions...) } -func (env *testEnvironment) SendOrgPullRequestEvent(org, repo, branch, action string) { - resp, err := sendWebhook(env.webhookServer, "pull_request", &github.PullRequestEvent{ - PullRequest: &github.PullRequest{ - Base: &github.PullRequestBranch{ - Ref: github.String(branch), - }, - }, - Repo: &github.Repository{ - Name: github.String(repo), - Owner: &github.User{ - Login: github.String(org), - Type: github.String("Organization"), - }, - }, - Action: github.String(action), - }) - - ExpectWithOffset(1, err).NotTo(HaveOccurred(), "failed to send pull_request event") - - ExpectWithOffset(1, resp.StatusCode).To(Equal(200)) -} - -func (env *testEnvironment) SendOrgCheckRunEvent(org, repo, status, action string) { - resp, err := sendWebhook(env.webhookServer, "check_run", &github.CheckRunEvent{ - CheckRun: &github.CheckRun{ - Status: github.String(status), - }, - Org: &github.Organization{ - Login: github.String(org), - }, - Repo: &github.Repository{ - Name: github.String(repo), - Owner: &github.User{ - Login: github.String(org), - Type: github.String("Organization"), - }, - }, - Action: github.String(action), - }) - - ExpectWithOffset(1, err).NotTo(HaveOccurred(), "failed to send check_run event") - - ExpectWithOffset(1, resp.StatusCode).To(Equal(200)) -} - func (env *testEnvironment) SendWorkflowJobEvent(org, repo, statusAndAction string, labels []string, runID int64, ID int64) { resp, err := sendWebhook(env.webhookServer, "workflow_job", &github.WorkflowJobEvent{ WorkflowJob: &github.WorkflowJob{ @@ -1441,48 +514,6 @@ func (env *testEnvironment) SendWorkflowJobEvent(org, repo, statusAndAction stri ExpectWithOffset(1, resp.StatusCode).To(Equal(200)) } -func (env *testEnvironment) SendUserPullRequestEvent(owner, repo, branch, action string) { - resp, err := sendWebhook(env.webhookServer, "pull_request", &github.PullRequestEvent{ - PullRequest: &github.PullRequest{ - Base: &github.PullRequestBranch{ - Ref: github.String(branch), - }, - }, - Repo: &github.Repository{ - Name: github.String(repo), - Owner: &github.User{ - Login: github.String(owner), - Type: github.String("User"), - }, - }, - Action: github.String(action), - }) - - ExpectWithOffset(1, err).NotTo(HaveOccurred(), "failed to send pull_request event") - - ExpectWithOffset(1, resp.StatusCode).To(Equal(200)) -} - -func (env *testEnvironment) SendUserCheckRunEvent(owner, repo, status, action string) { - resp, err := sendWebhook(env.webhookServer, "check_run", &github.CheckRunEvent{ - CheckRun: &github.CheckRun{ - Status: github.String(status), - }, - Repo: &github.Repository{ - Name: github.String(repo), - Owner: &github.User{ - Login: github.String(owner), - Type: github.String("User"), - }, - }, - Action: github.String(action), - }) - - ExpectWithOffset(1, err).NotTo(HaveOccurred(), "failed to send check_run event") - - ExpectWithOffset(1, resp.StatusCode).To(Equal(200)) -} - func (env *testEnvironment) SyncRunnerRegistrations() { var runnerList actionsv1alpha1.RunnerList