diff --git a/README.md b/README.md index 2b480e19..d96b70de 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,53 @@ helm upgrade --install -n actions-runner-system actions-runner-controller/action ### Github Enterprise support -If you use either Github Enterprise Cloud or Server (and have recent enought version supporting Actions), you can use **actions-runner-controller** with those, too. Authentication works same way as with public Github (repo and organization level). +If you use either Github Enterprise Cloud or Server, you can use **actions-runner-controller** with those, too. +Authentication works same way as with public Github (repo and organization level). +The minimum version of Github Enterprise Server is 3.0.0 (or rc1/rc2). +In most cases maintainers do not have environment where to test changes and are reliant on the community for testing. + ```shell kubectl set env deploy controller-manager -c manager GITHUB_ENTERPRISE_URL= --namespace actions-runner-system ``` -[Enterprise level](https://docs.github.com/en/enterprise-server@2.22/actions/hosting-your-own-runners/adding-self-hosted-runners#adding-a-self-hosted-runner-to-an-enterprise) runners are not working yet as there's no API definition for those. +#### Enterprise runners usage + +In order to use enterprise runners you must have Admin access to Github Enterprise and you should do Personal Access Token (PAT) +with `enterprise:admin` access. Enterprise runners are not possible to run with Github APP or any other permission. + +When you use enterprise runners those will get access to Github Organisations. However, access to the repositories is **NOT** +allowed by default. Each Github Organisation must allow Enterprise runner groups to be used in repositories. +This is needed only one time and is permanent after that. + +Example: + +```yaml +apiVersion: actions.summerwind.dev/v1alpha1 +kind: RunnerDeployment +metadata: + name: ghe-runner-deployment +spec: + replicas: 2 + template: + spec: + enterprise: your-enterprise-name + dockerdWithinRunnerContainer: true + resources: + limits: + cpu: "4000m" + memory: "2Gi" + requests: + cpu: "200m" + memory: "200Mi" + volumeMounts: + - mountPath: /runner + name: runner + volumes: + - name: runner + emptyDir: {} + +``` ## Setting up authentication with GitHub API diff --git a/api/v1alpha1/runner_types.go b/api/v1alpha1/runner_types.go index 8e29f990..614d734d 100644 --- a/api/v1alpha1/runner_types.go +++ b/api/v1alpha1/runner_types.go @@ -25,6 +25,10 @@ import ( // RunnerSpec defines the desired state of Runner type RunnerSpec struct { + // +optional + // +kubebuilder:validation:Pattern=`^[^/]+$` + Enterprise string `json:"enterprise,omitempty"` + // +optional // +kubebuilder:validation:Pattern=`^[^/]+$` Organization string `json:"organization,omitempty"` @@ -92,12 +96,22 @@ type RunnerSpec struct { // ValidateRepository validates repository field. func (rs *RunnerSpec) ValidateRepository() error { - // Organization and repository are both exclusive. - if len(rs.Organization) == 0 && len(rs.Repository) == 0 { - return errors.New("Spec needs organization or repository") + // Enterprise, Organization and repository are both exclusive. + foundCount := 0 + if len(rs.Organization) > 0 { + foundCount += 1 } - if len(rs.Organization) > 0 && len(rs.Repository) > 0 { - return errors.New("Spec cannot have both organization and repository") + if len(rs.Repository) > 0 { + foundCount += 1 + } + if len(rs.Enterprise) > 0 { + foundCount += 1 + } + if foundCount == 0 { + return errors.New("Spec needs enterprise, organization or repository") + } + if foundCount > 1 { + return errors.New("Spec cannot have many fields defined enterprise, organization and repository") } return nil @@ -113,6 +127,7 @@ type RunnerStatus struct { // RunnerStatusRegistration contains runner registration status type RunnerStatusRegistration struct { + Enterprise string `json:"enterprise,omitempty"` Organization string `json:"organization,omitempty"` Repository string `json:"repository,omitempty"` Labels []string `json:"labels,omitempty"` @@ -122,6 +137,7 @@ type RunnerStatusRegistration struct { // +kubebuilder:object:root=true // +kubebuilder:subresource:status +// +kubebuilder:printcolumn:JSONPath=".spec.enterprise",name=Enterprise,type=string // +kubebuilder:printcolumn:JSONPath=".spec.organization",name=Organization,type=string // +kubebuilder:printcolumn:JSONPath=".spec.repository",name=Repository,type=string // +kubebuilder:printcolumn:JSONPath=".spec.labels",name=Labels,type=string diff --git a/charts/actions-runner-controller/crds/actions.summerwind.dev_runnerdeployments.yaml b/charts/actions-runner-controller/crds/actions.summerwind.dev_runnerdeployments.yaml index b867989f..29afc816 100644 --- a/charts/actions-runner-controller/crds/actions.summerwind.dev_runnerdeployments.yaml +++ b/charts/actions-runner-controller/crds/actions.summerwind.dev_runnerdeployments.yaml @@ -426,6 +426,9 @@ spec: type: object dockerdWithinRunnerContainer: type: boolean + enterprise: + pattern: ^[^/]+$ + type: string env: items: description: EnvVar represents an environment variable present in a Container. diff --git a/charts/actions-runner-controller/crds/actions.summerwind.dev_runnerreplicasets.yaml b/charts/actions-runner-controller/crds/actions.summerwind.dev_runnerreplicasets.yaml index 261685e5..6e7a6315 100644 --- a/charts/actions-runner-controller/crds/actions.summerwind.dev_runnerreplicasets.yaml +++ b/charts/actions-runner-controller/crds/actions.summerwind.dev_runnerreplicasets.yaml @@ -426,6 +426,9 @@ spec: type: object dockerdWithinRunnerContainer: type: boolean + enterprise: + pattern: ^[^/]+$ + type: string env: items: description: EnvVar represents an environment variable present in a Container. diff --git a/charts/actions-runner-controller/crds/actions.summerwind.dev_runners.yaml b/charts/actions-runner-controller/crds/actions.summerwind.dev_runners.yaml index ee2aa441..4e5e947b 100644 --- a/charts/actions-runner-controller/crds/actions.summerwind.dev_runners.yaml +++ b/charts/actions-runner-controller/crds/actions.summerwind.dev_runners.yaml @@ -7,6 +7,9 @@ metadata: name: runners.actions.summerwind.dev spec: additionalPrinterColumns: + - JSONPath: .spec.enterprise + name: Enterprise + type: string - JSONPath: .spec.organization name: Organization type: string @@ -419,6 +422,9 @@ spec: type: object dockerdWithinRunnerContainer: type: boolean + enterprise: + pattern: ^[^/]+$ + type: string env: items: description: EnvVar represents an environment variable present in a Container. @@ -1541,6 +1547,8 @@ spec: registration: description: RunnerStatusRegistration contains runner registration status properties: + enterprise: + type: string expiresAt: format: date-time type: string diff --git a/config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml b/config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml index b867989f..29afc816 100644 --- a/config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml +++ b/config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml @@ -426,6 +426,9 @@ spec: type: object dockerdWithinRunnerContainer: type: boolean + enterprise: + pattern: ^[^/]+$ + type: string env: items: description: EnvVar represents an environment variable present in a Container. diff --git a/config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml b/config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml index 261685e5..6e7a6315 100644 --- a/config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml +++ b/config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml @@ -426,6 +426,9 @@ spec: type: object dockerdWithinRunnerContainer: type: boolean + enterprise: + pattern: ^[^/]+$ + type: string env: items: description: EnvVar represents an environment variable present in a Container. diff --git a/config/crd/bases/actions.summerwind.dev_runners.yaml b/config/crd/bases/actions.summerwind.dev_runners.yaml index ee2aa441..4e5e947b 100644 --- a/config/crd/bases/actions.summerwind.dev_runners.yaml +++ b/config/crd/bases/actions.summerwind.dev_runners.yaml @@ -7,6 +7,9 @@ metadata: name: runners.actions.summerwind.dev spec: additionalPrinterColumns: + - JSONPath: .spec.enterprise + name: Enterprise + type: string - JSONPath: .spec.organization name: Organization type: string @@ -419,6 +422,9 @@ spec: type: object dockerdWithinRunnerContainer: type: boolean + enterprise: + pattern: ^[^/]+$ + type: string env: items: description: EnvVar represents an environment variable present in a Container. @@ -1541,6 +1547,8 @@ spec: registration: description: RunnerStatusRegistration contains runner registration status properties: + enterprise: + type: string expiresAt: format: date-time type: string diff --git a/controllers/autoscaling.go b/controllers/autoscaling.go index b3713429..958b5107 100644 --- a/controllers/autoscaling.go +++ b/controllers/autoscaling.go @@ -204,7 +204,7 @@ func (r *HorizontalRunnerAutoscalerReconciler) calculateReplicasByPercentageRunn } // ListRunners will return all runners managed by GitHub - not restricted to ns - runners, err := r.GitHubClient.ListRunners(ctx, orgName, "") + runners, err := r.GitHubClient.ListRunners(ctx, "", orgName, "") if err != nil { return nil, err } diff --git a/controllers/runner_controller.go b/controllers/runner_controller.go index 11230131..41c1d14c 100644 --- a/controllers/runner_controller.go +++ b/controllers/runner_controller.go @@ -95,7 +95,7 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { if removed { if len(runner.Status.Registration.Token) > 0 { - ok, err := r.unregisterRunner(ctx, runner.Spec.Organization, runner.Spec.Repository, runner.Name) + ok, err := r.unregisterRunner(ctx, runner.Spec.Enterprise, runner.Spec.Organization, runner.Spec.Repository, runner.Name) if err != nil { log.Error(err, "Failed to unregister runner") return ctrl.Result{}, err @@ -194,7 +194,7 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { return ctrl.Result{}, err } - runnerBusy, err := r.isRunnerBusy(ctx, runner.Spec.Organization, runner.Spec.Repository, runner.Name) + runnerBusy, err := r.isRunnerBusy(ctx, runner.Spec.Enterprise, runner.Spec.Organization, runner.Spec.Repository, runner.Name) if err != nil { log.Error(err, "Failed to check if runner is busy") return ctrl.Result{}, nil @@ -227,8 +227,8 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { return ctrl.Result{}, nil } -func (r *RunnerReconciler) isRunnerBusy(ctx context.Context, org, repo, name string) (bool, error) { - runners, err := r.GitHubClient.ListRunners(ctx, org, repo) +func (r *RunnerReconciler) isRunnerBusy(ctx context.Context, enterprise, org, repo, name string) (bool, error) { + runners, err := r.GitHubClient.ListRunners(ctx, enterprise, org, repo) if err != nil { return false, err } @@ -242,8 +242,8 @@ func (r *RunnerReconciler) isRunnerBusy(ctx context.Context, org, repo, name str return false, fmt.Errorf("runner not found") } -func (r *RunnerReconciler) unregisterRunner(ctx context.Context, org, repo, name string) (bool, error) { - runners, err := r.GitHubClient.ListRunners(ctx, org, repo) +func (r *RunnerReconciler) unregisterRunner(ctx context.Context, enterprise, org, repo, name string) (bool, error) { + runners, err := r.GitHubClient.ListRunners(ctx, enterprise, org, repo) if err != nil { return false, err } @@ -263,7 +263,7 @@ func (r *RunnerReconciler) unregisterRunner(ctx context.Context, org, repo, name return false, nil } - if err := r.GitHubClient.RemoveRunner(ctx, org, repo, id); err != nil { + if err := r.GitHubClient.RemoveRunner(ctx, enterprise, org, repo, id); err != nil { return false, err } @@ -277,7 +277,7 @@ func (r *RunnerReconciler) updateRegistrationToken(ctx context.Context, runner v log := r.Log.WithValues("runner", runner.Name) - rt, err := r.GitHubClient.GetRegistrationToken(ctx, runner.Spec.Organization, runner.Spec.Repository, runner.Name) + rt, err := r.GitHubClient.GetRegistrationToken(ctx, runner.Spec.Enterprise, runner.Spec.Organization, runner.Spec.Repository, runner.Name) if err != nil { r.Recorder.Event(&runner, corev1.EventTypeWarning, "FailedUpdateRegistrationToken", "Updating registration token failed") log.Error(err, "Failed to get new registration token") @@ -339,6 +339,10 @@ func (r *RunnerReconciler) newPod(runner v1alpha1.Runner) (corev1.Pod, error) { Name: "RUNNER_REPO", Value: runner.Spec.Repository, }, + { + Name: "RUNNER_ENTERPRISE", + Value: runner.Spec.Enterprise, + }, { Name: "RUNNER_LABELS", Value: strings.Join(runner.Spec.Labels, ","), diff --git a/controllers/runnerreplicaset_controller.go b/controllers/runnerreplicaset_controller.go index 45f4dc61..32a2d7db 100644 --- a/controllers/runnerreplicaset_controller.go +++ b/controllers/runnerreplicaset_controller.go @@ -102,7 +102,7 @@ func (r *RunnerReplicaSetReconciler) Reconcile(req ctrl.Request) (ctrl.Result, e // get runners that are currently not busy var notBusy []v1alpha1.Runner for _, runner := range myRunners { - busy, err := r.isRunnerBusy(ctx, runner.Spec.Organization, runner.Spec.Repository, runner.Name) + busy, err := r.isRunnerBusy(ctx, runner.Spec.Enterprise, runner.Spec.Organization, runner.Spec.Repository, runner.Name) if err != nil { log.Error(err, "Failed to check if runner is busy") return ctrl.Result{}, err @@ -187,8 +187,8 @@ func (r *RunnerReplicaSetReconciler) SetupWithManager(mgr ctrl.Manager) error { Complete(r) } -func (r *RunnerReplicaSetReconciler) isRunnerBusy(ctx context.Context, org, repo, name string) (bool, error) { - runners, err := r.GitHubClient.ListRunners(ctx, org, repo) +func (r *RunnerReplicaSetReconciler) isRunnerBusy(ctx context.Context, enterprise, org, repo, name string) (bool, error) { + runners, err := r.GitHubClient.ListRunners(ctx, enterprise, org, repo) r.Log.Info("runners", "github", runners) if err != nil { return false, err diff --git a/github/github.go b/github/github.go index a1c3aead..327c2efc 100644 --- a/github/github.go +++ b/github/github.go @@ -78,7 +78,7 @@ func (c *Config) NewClient() (*Client, error) { } // GetRegistrationToken returns a registration token tied with the name of repository and runner. -func (c *Client) GetRegistrationToken(ctx context.Context, org, repo, name string) (*github.RegistrationToken, error) { +func (c *Client) GetRegistrationToken(ctx context.Context, enterprise, org, repo, name string) (*github.RegistrationToken, error) { c.mu.Lock() defer c.mu.Unlock() @@ -89,13 +89,13 @@ func (c *Client) GetRegistrationToken(ctx context.Context, org, repo, name strin return rt, nil } - owner, repo, err := getOwnerAndRepo(org, repo) + enterprise, owner, repo, err := getEnterpriseOrganisationAndRepo(enterprise, org, repo) if err != nil { return rt, err } - rt, res, err := c.createRegistrationToken(ctx, owner, repo) + rt, res, err := c.createRegistrationToken(ctx, enterprise, owner, repo) if err != nil { return nil, fmt.Errorf("failed to create registration token: %v", err) @@ -114,14 +114,14 @@ func (c *Client) GetRegistrationToken(ctx context.Context, org, repo, name strin } // RemoveRunner removes a runner with specified runner ID from repository. -func (c *Client) RemoveRunner(ctx context.Context, org, repo string, runnerID int64) error { - owner, repo, err := getOwnerAndRepo(org, repo) +func (c *Client) RemoveRunner(ctx context.Context, enterprise, org, repo string, runnerID int64) error { + enterprise, owner, repo, err := getEnterpriseOrganisationAndRepo(enterprise, org, repo) if err != nil { return err } - res, err := c.removeRunner(ctx, owner, repo, runnerID) + res, err := c.removeRunner(ctx, enterprise, owner, repo, runnerID) if err != nil { return fmt.Errorf("failed to remove runner: %v", err) @@ -135,8 +135,8 @@ func (c *Client) RemoveRunner(ctx context.Context, org, repo string, runnerID in } // ListRunners returns a list of runners of specified owner/repository name. -func (c *Client) ListRunners(ctx context.Context, org, repo string) ([]*github.Runner, error) { - owner, repo, err := getOwnerAndRepo(org, repo) +func (c *Client) ListRunners(ctx context.Context, enterprise, org, repo string) ([]*github.Runner, error) { + enterprise, owner, repo, err := getEnterpriseOrganisationAndRepo(enterprise, org, repo) if err != nil { return nil, err @@ -146,7 +146,7 @@ func (c *Client) ListRunners(ctx context.Context, org, repo string) ([]*github.R opts := github.ListOptions{PerPage: 10} for { - list, res, err := c.listRunners(ctx, owner, repo, &opts) + list, res, err := c.listRunners(ctx, enterprise, owner, repo, &opts) if err != nil { return runners, fmt.Errorf("failed to list runners: %v", err) @@ -174,42 +174,52 @@ func (c *Client) cleanup() { } } -// wrappers for github functions (switch between organization/repository mode) +// wrappers for github functions (switch between enterprise/organization/repository mode) // so the calling functions don't need to switch and their code is a bit cleaner -func (c *Client) createRegistrationToken(ctx context.Context, owner, repo string) (*github.RegistrationToken, *github.Response, error) { +func (c *Client) createRegistrationToken(ctx context.Context, enterprise, org, repo string) (*github.RegistrationToken, *github.Response, error) { if len(repo) > 0 { - return c.Client.Actions.CreateRegistrationToken(ctx, owner, repo) - } - - return c.Client.Actions.CreateOrganizationRegistrationToken(ctx, owner) -} - -func (c *Client) removeRunner(ctx context.Context, owner, repo string, runnerID int64) (*github.Response, error) { - if len(repo) > 0 { - return c.Client.Actions.RemoveRunner(ctx, owner, repo, runnerID) - } - - return c.Client.Actions.RemoveOrganizationRunner(ctx, owner, runnerID) -} - -func (c *Client) listRunners(ctx context.Context, owner, repo string, opts *github.ListOptions) (*github.Runners, *github.Response, error) { - if len(repo) > 0 { - return c.Client.Actions.ListRunners(ctx, owner, repo, opts) - } - - return c.Client.Actions.ListOrganizationRunners(ctx, owner, opts) -} - -// Validates owner and repo arguments. Both are optional, but at least one should be specified -func getOwnerAndRepo(org, repo string) (string, string, error) { - if len(repo) > 0 { - return splitOwnerAndRepo(repo) + return c.Client.Actions.CreateRegistrationToken(ctx, org, repo) } if len(org) > 0 { - return org, "", nil + return c.Client.Actions.CreateOrganizationRegistrationToken(ctx, org) } - return "", "", fmt.Errorf("organization and repository are both empty") + return c.Client.Enterprise.CreateRegistrationToken(ctx, enterprise) +} + +func (c *Client) removeRunner(ctx context.Context, enterprise, org, repo string, runnerID int64) (*github.Response, error) { + if len(repo) > 0 { + return c.Client.Actions.RemoveRunner(ctx, org, repo, runnerID) + } + if len(org) > 0 { + return c.Client.Actions.RemoveOrganizationRunner(ctx, org, runnerID) + } + return c.Client.Enterprise.RemoveRunner(ctx, enterprise, runnerID) +} + +func (c *Client) listRunners(ctx context.Context, enterprise, org, repo string, opts *github.ListOptions) (*github.Runners, *github.Response, error) { + if len(repo) > 0 { + return c.Client.Actions.ListRunners(ctx, org, repo, opts) + } + if len(org) > 0 { + return c.Client.Actions.ListOrganizationRunners(ctx, org, opts) + } + return c.Client.Enterprise.ListRunners(ctx, enterprise, opts) +} + +// Validates enterprise, organisation and repo arguments. Both are optional, but at least one should be specified +func getEnterpriseOrganisationAndRepo(enterprise, org, repo string) (string, string, string, error) { + if len(repo) > 0 { + owner, repository, err := splitOwnerAndRepo(repo) + return "", owner, repository, err + } + if len(org) > 0 { + return "", org, "", nil + } + if len(enterprise) > 0 { + return enterprise, "", "", nil + } + return "", "", "", fmt.Errorf("enterprise, organization and repository are all empty") } func getRegistrationKey(org, repo string) string { diff --git a/github/github_test.go b/github/github_test.go index 90832d58..f7852ff2 100644 --- a/github/github_test.go +++ b/github/github_test.go @@ -39,22 +39,26 @@ func TestMain(m *testing.M) { func TestGetRegistrationToken(t *testing.T) { tests := []struct { - org string - repo string - token string - err bool + enterprise string + org string + repo string + token string + err bool }{ - {org: "", repo: "test/valid", token: fake.RegistrationToken, err: false}, - {org: "", repo: "test/invalid", token: "", err: true}, - {org: "", repo: "test/error", token: "", err: true}, - {org: "test", repo: "", token: fake.RegistrationToken, err: false}, - {org: "invalid", repo: "", token: "", err: true}, - {org: "error", repo: "", token: "", err: true}, + {enterprise: "", org: "", repo: "test/valid", token: fake.RegistrationToken, err: false}, + {enterprise: "", org: "", repo: "test/invalid", token: "", err: true}, + {enterprise: "", org: "", repo: "test/error", token: "", err: true}, + {enterprise: "", org: "test", repo: "", token: fake.RegistrationToken, err: false}, + {enterprise: "", org: "invalid", repo: "", token: "", err: true}, + {enterprise: "", org: "error", repo: "", token: "", err: true}, + {enterprise: "test", org: "", repo: "", token: fake.RegistrationToken, err: false}, + {enterprise: "invalid", org: "", repo: "", token: "", err: true}, + {enterprise: "error", org: "", repo: "", token: "", err: true}, } client := newTestClient() for i, tt := range tests { - rt, err := client.GetRegistrationToken(context.Background(), tt.org, tt.repo, "test") + rt, err := client.GetRegistrationToken(context.Background(), tt.enterprise, tt.org, tt.repo, "test") if !tt.err && err != nil { t.Errorf("[%d] unexpected error: %v", i, err) } @@ -66,22 +70,26 @@ func TestGetRegistrationToken(t *testing.T) { func TestListRunners(t *testing.T) { tests := []struct { - org string - repo string - length int - err bool + enterprise string + org string + repo string + length int + err bool }{ - {org: "", repo: "test/valid", length: 2, err: false}, - {org: "", repo: "test/invalid", length: 0, err: true}, - {org: "", repo: "test/error", length: 0, err: true}, - {org: "test", repo: "", length: 2, err: false}, - {org: "invalid", repo: "", length: 0, err: true}, - {org: "error", repo: "", length: 0, err: true}, + {enterprise: "", org: "", repo: "test/valid", length: 2, err: false}, + {enterprise: "", org: "", repo: "test/invalid", length: 0, err: true}, + {enterprise: "", org: "", repo: "test/error", length: 0, err: true}, + {enterprise: "", org: "test", repo: "", length: 2, err: false}, + {enterprise: "", org: "invalid", repo: "", length: 0, err: true}, + {enterprise: "", org: "error", repo: "", length: 0, err: true}, + {enterprise: "test", org: "", repo: "", length: 2, err: false}, + {enterprise: "invalid", org: "", repo: "", length: 0, err: true}, + {enterprise: "error", org: "", repo: "", length: 0, err: true}, } client := newTestClient() for i, tt := range tests { - runners, err := client.ListRunners(context.Background(), tt.org, tt.repo) + runners, err := client.ListRunners(context.Background(), tt.enterprise, tt.org, tt.repo) if !tt.err && err != nil { t.Errorf("[%d] unexpected error: %v", i, err) } @@ -93,21 +101,25 @@ func TestListRunners(t *testing.T) { func TestRemoveRunner(t *testing.T) { tests := []struct { - org string - repo string - err bool + enterprise string + org string + repo string + err bool }{ - {org: "", repo: "test/valid", err: false}, - {org: "", repo: "test/invalid", err: true}, - {org: "", repo: "test/error", err: true}, - {org: "test", repo: "", err: false}, - {org: "invalid", repo: "", err: true}, - {org: "error", repo: "", err: true}, + {enterprise: "", org: "", repo: "test/valid", err: false}, + {enterprise: "", org: "", repo: "test/invalid", err: true}, + {enterprise: "", org: "", repo: "test/error", err: true}, + {enterprise: "", org: "test", repo: "", err: false}, + {enterprise: "", org: "invalid", repo: "", err: true}, + {enterprise: "", org: "error", repo: "", err: true}, + {enterprise: "test", org: "", repo: "", err: false}, + {enterprise: "invalid", org: "", repo: "", err: true}, + {enterprise: "error", org: "", repo: "", err: true}, } client := newTestClient() for i, tt := range tests { - err := client.RemoveRunner(context.Background(), tt.org, tt.repo, int64(1)) + err := client.RemoveRunner(context.Background(), tt.enterprise, tt.org, tt.repo, int64(1)) if !tt.err && err != nil { t.Errorf("[%d] unexpected error: %v", i, err) } diff --git a/go.mod b/go.mod index 29c388a4..0ef66dab 100644 --- a/go.mod +++ b/go.mod @@ -6,10 +6,7 @@ require ( github.com/bradleyfalzon/ghinstallation v1.1.1 github.com/davecgh/go-spew v1.1.1 github.com/go-logr/logr v0.1.0 - github.com/google/go-github v17.0.0+incompatible // indirect - github.com/google/go-github/v32 v32.1.1-0.20200822031813-d57a3a84ba04 - github.com/google/go-github/v33 v33.0.0 - github.com/google/go-querystring v1.0.0 + github.com/google/go-github/v33 v33.0.1-0.20210204004227-319dcffb518a github.com/gorilla/mux v1.8.0 github.com/kelseyhightower/envconfig v1.4.0 github.com/onsi/ginkgo v1.8.0 diff --git a/go.sum b/go.sum index d4c55973..3ce72319 100644 --- a/go.sum +++ b/go.sum @@ -116,14 +116,10 @@ github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github/v29 v29.0.2 h1:opYN6Wc7DOz7Ku3Oh4l7prmkOMwEcQxpFtxdU8N8Pts= github.com/google/go-github/v29 v29.0.2/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E= -github.com/google/go-github/v32 v32.1.1-0.20200822031813-d57a3a84ba04 h1:wEYk2h/GwOhImcVjiTIceP88WxVbXw2F+ARYUQMEsfg= -github.com/google/go-github/v32 v32.1.1-0.20200822031813-d57a3a84ba04/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI= -github.com/google/go-github/v33 v33.0.0 h1:qAf9yP0qc54ufQxzwv+u9H0tiVOnPJxo0lI/JXqw3ZM= -github.com/google/go-github/v33 v33.0.0/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg= +github.com/google/go-github/v33 v33.0.1-0.20210204004227-319dcffb518a h1:Z9Nzq8ntvvXCLnFGOkzzcD8HDOzOo+obuwE5oK85vNQ= +github.com/google/go-github/v33 v33.0.1-0.20210204004227-319dcffb518a/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= diff --git a/runner/entrypoint.sh b/runner/entrypoint.sh index 556eee06..cdbcc673 100755 --- a/runner/entrypoint.sh +++ b/runner/entrypoint.sh @@ -16,14 +16,16 @@ if [ -z "${RUNNER_NAME}" ]; then exit 1 fi -if [ -n "${RUNNER_ORG}" ] && [ -n "${RUNNER_REPO}" ]; then +if [ -n "${RUNNER_ORG}" ] && [ -n "${RUNNER_REPO}" ] && [ -n "${RUNNER_ENTERPRISE}" ]; then ATTACH="${RUNNER_ORG}/${RUNNER_REPO}" elif [ -n "${RUNNER_ORG}" ]; then ATTACH="${RUNNER_ORG}" elif [ -n "${RUNNER_REPO}" ]; then ATTACH="${RUNNER_REPO}" +elif [ -n "${RUNNER_ENTERPRISE}" ]; then + ATTACH="enterprises/${RUNNER_ENTERPRISE}" else - echo "At least one of RUNNER_ORG or RUNNER_REPO must be set" 1>&2 + echo "At least one of RUNNER_ORG or RUNNER_REPO or RUNNER_ENTERPRISE must be set" 1>&2 exit 1 fi