diff --git a/Dockerfile b/Dockerfile index 74eb9d74..6dfb4f6d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,7 @@ RUN go mod download COPY main.go main.go COPY api/ api/ COPY controllers/ controllers/ +COPY github/ github/ # Build RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go diff --git a/controllers/runner_controller.go b/controllers/runner_controller.go index 7904be83..96d4463b 100644 --- a/controllers/runner_controller.go +++ b/controllers/runner_controller.go @@ -20,10 +20,8 @@ import ( "context" "fmt" "reflect" - "time" "github.com/go-logr/logr" - "github.com/google/go-github/v29/github" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" @@ -34,6 +32,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/summerwind/actions-runner-controller/api/v1alpha1" + "github.com/summerwind/actions-runner-controller/github" ) const ( @@ -41,23 +40,6 @@ const ( finalizerName = "runner.actions.summerwind.dev" ) -type GitHubRunnerList struct { - TotalCount int `json:"total_count"` - Runners []GitHubRunner `json:"runners,omitempty"` -} - -type GitHubRunner struct { - ID int `json:"id"` - Name string `json:"name"` - OS string `json:"os"` - Status string `json:"status"` -} - -type GitHubRegistrationToken struct { - Token string `json:"token"` - ExpiresAt string `json:"expires_at"` -} - // RunnerReconciler reconciles a Runner object type RunnerReconciler struct { client.Client @@ -126,7 +108,7 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { } if !runner.IsRegisterable() { - reg, err := r.newRegistration(ctx, runner.Spec.Repository) + rt, err := r.GitHubClient.GetRegistrationToken(ctx, 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") @@ -134,7 +116,11 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { } updated := runner.DeepCopy() - updated.Status.Registration = reg + updated.Status.Registration = v1alpha1.RunnerStatusRegistration{ + Repository: runner.Spec.Repository, + Token: rt.GetToken(), + ExpiresAt: metav1.NewTime(rt.GetExpiresAt().Time), + } if err := r.Status().Update(ctx, updated); err != nil { log.Error(err, "Failed to update runner status") @@ -226,109 +212,31 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { return ctrl.Result{}, nil } -func (r *RunnerReconciler) newRegistration(ctx context.Context, repo string) (v1alpha1.RunnerStatusRegistration, error) { - var reg v1alpha1.RunnerStatusRegistration - - rt, err := r.getRegistrationToken(ctx, repo) - if err != nil { - return reg, err - } - - expiresAt, err := time.Parse(time.RFC3339, rt.ExpiresAt) - if err != nil { - return reg, err - } - - reg.Repository = repo - reg.Token = rt.Token - reg.ExpiresAt = metav1.NewTime(expiresAt) - - return reg, err -} - -func (r *RunnerReconciler) getRegistrationToken(ctx context.Context, repo string) (GitHubRegistrationToken, error) { - var regToken GitHubRegistrationToken - - req, err := r.GitHubClient.NewRequest("POST", fmt.Sprintf("/repos/%s/actions/runners/registration-token", repo), nil) - if err != nil { - return regToken, err - } - - res, err := r.GitHubClient.Do(ctx, req, ®Token) - if err != nil { - return regToken, err - } - - if res.StatusCode != 201 { - return regToken, fmt.Errorf("unexpected status: %d", res.StatusCode) - } - - return regToken, nil -} - func (r *RunnerReconciler) unregisterRunner(ctx context.Context, repo, name string) (bool, error) { - runners, err := r.listRunners(ctx, repo) + runners, err := r.GitHubClient.ListRunners(ctx, repo) if err != nil { return false, err } - id := 0 - for _, runner := range runners.Runners { - if runner.Name == name { - id = runner.ID + id := int64(0) + for _, runner := range runners { + if runner.GetName() == name { + id = runner.GetID() break } } - if id == 0 { + if id == int64(0) { return false, nil } - if err := r.removeRunner(ctx, repo, id); err != nil { + if err := r.GitHubClient.RemoveRunner(ctx, repo, id); err != nil { return false, err } return true, nil } -func (r *RunnerReconciler) listRunners(ctx context.Context, repo string) (GitHubRunnerList, error) { - runners := GitHubRunnerList{} - - req, err := r.GitHubClient.NewRequest("GET", fmt.Sprintf("/repos/%s/actions/runners", repo), nil) - if err != nil { - return runners, err - } - - res, err := r.GitHubClient.Do(ctx, req, &runners) - if err != nil { - return runners, err - } - - if res.StatusCode != 200 { - return runners, fmt.Errorf("unexpected status: %d", res.StatusCode) - } - - return runners, nil -} - -func (r *RunnerReconciler) removeRunner(ctx context.Context, repo string, id int) error { - req, err := r.GitHubClient.NewRequest("DELETE", fmt.Sprintf("/repos/%s/actions/runners/%d", repo, id), nil) - if err != nil { - return err - } - - res, err := r.GitHubClient.Do(ctx, req, nil) - if err != nil { - return err - } - - if res.StatusCode != 204 { - return fmt.Errorf("unexpected status: %d", res.StatusCode) - } - - return nil -} - func (r *RunnerReconciler) newPod(runner v1alpha1.Runner) (corev1.Pod, error) { var ( privileged bool = true diff --git a/github/fake/fake.go b/github/fake/fake.go new file mode 100644 index 00000000..a9ed3667 --- /dev/null +++ b/github/fake/fake.go @@ -0,0 +1,86 @@ +package fake + +import ( + "fmt" + "net/http" + "net/http/httptest" + "time" +) + +const ( + RegistrationToken = "fake-registration-token" + + RunnersListBody = ` +{ + "total_count": 2, + "runners": [ + {"id": 1, "name": "test1", "os": "linux", "status": "online"}, + {"id": 2, "name": "test2", "os": "linux", "status": "offline"} + ] +} +` +) + +type handler struct { + Status int + Body string +} + +func (h *handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + w.WriteHeader(h.Status) + fmt.Fprintf(w, h.Body) +} + +func NewServer() *httptest.Server { + routes := map[string]handler{ + // For CreateRegistrationToken + "/repos/test/valid/actions/runners/registration-token": handler{ + Status: http.StatusCreated, + Body: fmt.Sprintf("{\"token\": \"%s\", \"expires_at\": \"%s\"}", RegistrationToken, time.Now().Add(time.Hour*1).Format(time.RFC3339)), + }, + "/repos/test/invalid/actions/runners/registration-token": handler{ + Status: http.StatusOK, + Body: fmt.Sprintf("{\"token\": \"%s\", \"expires_at\": \"%s\"}", RegistrationToken, time.Now().Add(time.Hour*1).Format(time.RFC3339)), + }, + "/repos/test/error/actions/runners/registration-token": handler{ + Status: http.StatusBadRequest, + Body: "", + }, + + // For ListRunners + "/repos/test/valid/actions/runners": handler{ + Status: http.StatusOK, + Body: RunnersListBody, + }, + "/repos/test/invalid/actions/runners": handler{ + Status: http.StatusNoContent, + Body: "", + }, + "/repos/test/error/actions/runners": handler{ + Status: http.StatusBadRequest, + Body: "", + }, + + // For RemoveRunner + "/repos/test/valid/actions/runners/1": handler{ + Status: http.StatusNoContent, + Body: "", + }, + "/repos/test/invalid/actions/runners/1": handler{ + Status: http.StatusOK, + Body: "", + }, + "/repos/test/error/actions/runners/1": handler{ + Status: http.StatusBadRequest, + Body: "", + }, + } + + mux := http.NewServeMux() + for path, handler := range routes { + h := handler + mux.Handle(path, &h) + } + + return httptest.NewServer(mux) +} diff --git a/github/github.go b/github/github.go new file mode 100644 index 00000000..401eee4f --- /dev/null +++ b/github/github.go @@ -0,0 +1,147 @@ +package github + +import ( + "context" + "errors" + "fmt" + "net/http" + "strings" + "sync" + "time" + + "github.com/bradleyfalzon/ghinstallation" + "github.com/google/go-github/v31/github" + "golang.org/x/oauth2" +) + +type Client struct { + *github.Client + regTokens map[string]*github.RegistrationToken + mu sync.Mutex +} + +// NewClient returns a client authenticated as a GitHub App. +func NewClient(appID, installationID int64, privateKeyPath string) (*Client, error) { + tr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, appID, installationID, privateKeyPath) + if err != nil { + return nil, fmt.Errorf("authentication failed: %v", err) + } + + return &Client{ + Client: github.NewClient(&http.Client{Transport: tr}), + regTokens: map[string]*github.RegistrationToken{}, + mu: sync.Mutex{}, + }, nil +} + +// NewClient returns a client authenticated with personal access token. +func NewClientWithAccessToken(token string) (*Client, error) { + tc := oauth2.NewClient(context.Background(), oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: token}, + )) + + return &Client{ + Client: github.NewClient(tc), + regTokens: map[string]*github.RegistrationToken{}, + mu: sync.Mutex{}, + }, nil +} + +// GetRegistrationToken returns a registration token tied with the name of repository and runner. +func (c *Client) GetRegistrationToken(ctx context.Context, repository, name string) (*github.RegistrationToken, error) { + c.mu.Lock() + defer c.mu.Unlock() + + owner, repo, err := splitOwnerAndRepo(repository) + if err != nil { + return nil, err + } + + key := fmt.Sprintf("%s/%s", repo, name) + rt, ok := c.regTokens[key] + if ok && rt.GetExpiresAt().After(time.Now().Add(-10*time.Minute)) { + return rt, nil + } + + rt, res, err := c.Client.Actions.CreateRegistrationToken(ctx, owner, repo) + if err != nil { + return nil, fmt.Errorf("failed to create registration token: %v", err) + } + + if res.StatusCode != 201 { + return nil, fmt.Errorf("unexpected status: %d", res.StatusCode) + } + + c.regTokens[key] = rt + go func() { + c.cleanup() + }() + + return rt, nil +} + +// RemoveRunner removes a runner with specified runner ID from repocitory. +func (c *Client) RemoveRunner(ctx context.Context, repository string, runnerID int64) error { + owner, repo, err := splitOwnerAndRepo(repository) + if err != nil { + return err + } + + res, err := c.Client.Actions.RemoveRunner(ctx, owner, repo, runnerID) + if err != nil { + return fmt.Errorf("failed to remove runner: %v", err) + } + + if res.StatusCode != 204 { + return fmt.Errorf("unexpected status: %d", res.StatusCode) + } + + return nil +} + +// ListRunners returns a list of runners of specified repository name. +func (c *Client) ListRunners(ctx context.Context, repository string) ([]*github.Runner, error) { + var runners []*github.Runner + + owner, repo, err := splitOwnerAndRepo(repository) + if err != nil { + return runners, err + } + + opts := github.ListOptions{PerPage: 10} + for { + list, res, err := c.Client.Actions.ListRunners(ctx, owner, repo, &opts) + if err != nil { + return runners, fmt.Errorf("failed to remove runner: %v", err) + } + + runners = append(runners, list.Runners...) + if res.NextPage == 0 { + break + } + opts.Page = res.NextPage + } + + return runners, nil +} + +// cleanup removes expired registration tokens. +func (c *Client) cleanup() { + c.mu.Lock() + defer c.mu.Unlock() + + for key, rt := range c.regTokens { + if rt.GetExpiresAt().Before(time.Now()) { + delete(c.regTokens, key) + } + } +} + +// splitOwnerAndRepo splits specified repository name to the owner and repo name. +func splitOwnerAndRepo(repo string) (string, string, error) { + chunk := strings.Split(repo, "/") + if len(chunk) != 2 { + return "", "", errors.New("invalid repository name") + } + return chunk[0], chunk[1], nil +} diff --git a/github/github_test.go b/github/github_test.go new file mode 100644 index 00000000..bd048efa --- /dev/null +++ b/github/github_test.go @@ -0,0 +1,124 @@ +package github + +import ( + "context" + "net/http/httptest" + "net/url" + "testing" + "time" + + "github.com/google/go-github/v31/github" + "github.com/summerwind/actions-runner-controller/github/fake" +) + +var server *httptest.Server + +func newTestClient() *Client { + client, err := NewClientWithAccessToken("token") + if err != nil { + panic(err) + } + + baseURL, err := url.Parse(server.URL + "/") + if err != nil { + panic(err) + } + client.Client.BaseURL = baseURL + + return client +} + +func TestMain(m *testing.M) { + server = fake.NewServer() + defer server.Close() + m.Run() +} + +func TestGetRegistrationToken(t *testing.T) { + tests := []struct { + repo string + token string + err bool + }{ + {repo: "test/valid", token: fake.RegistrationToken, err: false}, + {repo: "test/invalid", token: "", err: true}, + {repo: "test/error", token: "", err: true}, + } + + client := newTestClient() + for i, tt := range tests { + rt, err := client.GetRegistrationToken(context.Background(), tt.repo, "test") + if !tt.err && err != nil { + t.Errorf("[%d] unexpected error: %v", i, err) + } + if tt.token != rt.GetToken() { + t.Errorf("[%d] unexpected token: %v", i, rt.GetToken()) + } + } +} + +func TestListRunners(t *testing.T) { + tests := []struct { + repo string + length int + err bool + }{ + {repo: "test/valid", length: 2, err: false}, + {repo: "test/invalid", length: 0, err: true}, + {repo: "test/error", length: 0, err: true}, + } + + client := newTestClient() + for i, tt := range tests { + runners, err := client.ListRunners(context.Background(), tt.repo) + if !tt.err && err != nil { + t.Errorf("[%d] unexpected error: %v", i, err) + } + if tt.length != len(runners) { + t.Errorf("[%d] unexpected runners list: %v", i, runners) + } + } +} + +func TestRemoveRunner(t *testing.T) { + tests := []struct { + repo string + err bool + }{ + {repo: "test/valid", err: false}, + {repo: "test/invalid", err: true}, + {repo: "test/error", err: true}, + } + + client := newTestClient() + for i, tt := range tests { + err := client.RemoveRunner(context.Background(), tt.repo, int64(1)) + if !tt.err && err != nil { + t.Errorf("[%d] unexpected error: %v", i, err) + } + } +} + +func TestCleanup(t *testing.T) { + token := "token" + + client := newTestClient() + client.regTokens = map[string]*github.RegistrationToken{ + "active": &github.RegistrationToken{ + Token: &token, + ExpiresAt: &github.Timestamp{Time: time.Now().Add(time.Hour * 1)}, + }, + "expired": &github.RegistrationToken{ + Token: &token, + ExpiresAt: &github.Timestamp{Time: time.Now().Add(-time.Hour * 1)}, + }, + } + + client.cleanup() + if _, ok := client.regTokens["active"]; !ok { + t.Errorf("active token was accidentally removed") + } + if _, ok := client.regTokens["expired"]; ok { + t.Errorf("expired token still exists") + } +} diff --git a/go.mod b/go.mod index 62843417..342f99a2 100644 --- a/go.mod +++ b/go.mod @@ -3,18 +3,14 @@ module github.com/summerwind/actions-runner-controller go 1.13 require ( - github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect - github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect 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 - github.com/google/go-github/v29 v29.0.3 + github.com/google/go-github/v31 v31.0.0 github.com/onsi/ginkgo v1.8.0 github.com/onsi/gomega v1.5.0 - github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 + github.com/stretchr/testify v1.4.0 // indirect golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 - gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect k8s.io/api v0.0.0-20190918155943-95b840bb6a1f k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655 k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90 diff --git a/go.sum b/go.sum index 4f99be54..9c79b86d 100644 --- a/go.sum +++ b/go.sum @@ -18,10 +18,6 @@ github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= @@ -120,12 +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/v29 v29.0.3 h1:IktKCTwU//aFHnpA+2SLIi7Oo9uhAzgsdZNbcAqhgdc= -github.com/google/go-github/v29 v29.0.3/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E= +github.com/google/go-github/v31 v31.0.0 h1:JJUxlP9lFK+ziXKimTCprajMApV1ecWD4NB6CCb0plo= +github.com/google/go-github/v31 v31.0.0/go.mod h1:NQPZol8/1sMoWYGN2yaALIBytu17gAWfhbweiEed3pM= 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= @@ -237,6 +231,7 @@ github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRci github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -343,8 +338,6 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= diff --git a/main.go b/main.go index d4ba7647..8a58de3d 100644 --- a/main.go +++ b/main.go @@ -17,18 +17,14 @@ limitations under the License. package main import ( - "context" "flag" "fmt" - "net/http" "os" "strconv" - "github.com/bradleyfalzon/ghinstallation" - "github.com/google/go-github/v29/github" actionsv1alpha1 "github.com/summerwind/actions-runner-controller/api/v1alpha1" "github.com/summerwind/actions-runner-controller/controllers" - "golang.org/x/oauth2" + "github.com/summerwind/actions-runner-controller/github" "k8s.io/apimachinery/pkg/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" @@ -56,6 +52,9 @@ func init() { func main() { var ( + err error + ghClient *github.Client + metricsAddr string enableLeaderElection bool @@ -66,8 +65,6 @@ func main() { ghAppID int64 ghAppInstallationID int64 ghAppPrivateKey string - - ghClient *github.Client ) flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.") @@ -111,17 +108,17 @@ func main() { os.Exit(1) } - tr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, ghAppID, ghAppInstallationID, ghAppPrivateKey) + ghClient, err = github.NewClient(ghAppID, ghAppInstallationID, ghAppPrivateKey) if err != nil { - fmt.Fprintf(os.Stderr, "Error: Invalid GitHub App credentials: %v\n", err) + fmt.Fprintf(os.Stderr, "Error: Failed to create GitHub client: %v\n", err) os.Exit(1) } - ghClient = github.NewClient(&http.Client{Transport: tr}) } else if ghToken != "" { - tc := oauth2.NewClient(context.Background(), oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: ghToken}, - )) - ghClient = github.NewClient(tc) + ghClient, err = github.NewClientWithAccessToken(ghToken) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: Failed to create GitHub client: %v\n", err) + os.Exit(1) + } } else { fmt.Fprintln(os.Stderr, "Error: GitHub App credentials or personal access token must be specified.") os.Exit(1)