feat: Repository-wide RunnerDeployment Autoscaling (#57)

* feat: Repository-wide RunnerDeployment Autoscaling

This adds `maxReplicas` and `minReplicas` to the RunnerDeploymentSpec. If and only if both fields are set, the controller computes and sets desired `replicas` automatically depending on the demand.

The number of demanded runner replicas is computed by `queued workflow runs + in_progress workflow runs` for the repository. The support for organizational runners is not included.

Ref https://github.com/summerwind/actions-runner-controller/issues/10
This commit is contained in:
KUOKA Yusuke
2020-06-27 17:26:46 +09:00
committed by GitHub
parent 512cae68a1
commit 5bb2694349
12 changed files with 521 additions and 20 deletions

View File

@@ -32,7 +32,13 @@ func (h *handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
// NewServer creates a fake server for running unit tests
func NewServer() *httptest.Server {
func NewServer(opts ...Option) *httptest.Server {
var responses FixedResponses
for _, o := range opts {
o(&responses)
}
routes := map[string]handler{
// For CreateRegistrationToken
"/repos/test/valid/actions/runners/registration-token": handler{
@@ -111,6 +117,9 @@ func NewServer() *httptest.Server {
Status: http.StatusBadRequest,
Body: "",
},
// For auto-scaling based on the number of queued(pending) workflow runs
"/repos/test/valid/actions/runs": responses.listRepositoryWorkflowRuns.handler(),
}
mux := http.NewServeMux()

28
github/fake/options.go Normal file
View File

@@ -0,0 +1,28 @@
package fake
type FixedResponses struct {
listRepositoryWorkflowRuns FixedResponse
}
type FixedResponse struct {
Status int
Body string
}
func (r FixedResponse) handler() handler {
return handler{
Status: r.Status,
Body: r.Body,
}
}
type Option func(responses *FixedResponses)
func WithListRepositoryWorkflowRunsResponse(status int, body string) Option {
return func(r *FixedResponses) {
r.listRepositoryWorkflowRuns = FixedResponse{
Status: status,
Body: body,
}
}
}

View File

@@ -27,8 +27,10 @@ func NewClient(appID, installationID int64, privateKeyPath string) (*Client, err
return nil, fmt.Errorf("authentication failed: %v", err)
}
gh := github.NewClient(&http.Client{Transport: tr})
return &Client{
Client: github.NewClient(&http.Client{Transport: tr}),
Client: gh,
regTokens: map[string]*github.RegistrationToken{},
mu: sync.Mutex{},
}, nil