181 lines
3.8 KiB
Go
181 lines
3.8 KiB
Go
package simulator
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/google/go-github/v39/github"
|
|
)
|
|
|
|
type RunnerGroupScope int
|
|
|
|
const (
|
|
Organization RunnerGroupScope = iota
|
|
Enterprise
|
|
)
|
|
|
|
func (s RunnerGroupScope) String() string {
|
|
switch s {
|
|
case Organization:
|
|
return "Organization"
|
|
case Enterprise:
|
|
return "Enterprise"
|
|
default:
|
|
panic(fmt.Sprintf("unimplemented RunnerGroupScope: %v", int(s)))
|
|
}
|
|
}
|
|
|
|
type RunnerGroupKind int
|
|
|
|
const (
|
|
Default RunnerGroupKind = iota
|
|
Custom
|
|
)
|
|
|
|
func (s RunnerGroupKind) String() string {
|
|
switch s {
|
|
case Default:
|
|
return "Default"
|
|
case Custom:
|
|
return "Custom"
|
|
default:
|
|
panic(fmt.Sprintf("unimplemented RunnerGroupKind: %v", int(s)))
|
|
}
|
|
}
|
|
|
|
func NewRunnerGroupFromGitHub(g *github.RunnerGroup) RunnerGroup {
|
|
var name string
|
|
if !g.GetDefault() {
|
|
name = g.GetName()
|
|
}
|
|
|
|
var scope RunnerGroupScope
|
|
|
|
if g.GetInherited() {
|
|
scope = Enterprise
|
|
} else {
|
|
scope = Organization
|
|
}
|
|
|
|
return newRunnerGroup(scope, name)
|
|
}
|
|
|
|
func NewRunnerGroupFromProperties(enterprise, organization, group string) RunnerGroup {
|
|
var scope RunnerGroupScope
|
|
|
|
if enterprise != "" {
|
|
scope = Enterprise
|
|
} else {
|
|
scope = Organization
|
|
}
|
|
|
|
return newRunnerGroup(scope, group)
|
|
}
|
|
|
|
// newRunnerGroup creates a new RunnerGroup instance from the provided arguments.
|
|
// There's a convention that an empty name implies a default runner group.
|
|
func newRunnerGroup(scope RunnerGroupScope, name string) RunnerGroup {
|
|
if name == "" {
|
|
return RunnerGroup{
|
|
Scope: scope,
|
|
Kind: Default,
|
|
Name: "",
|
|
}
|
|
}
|
|
|
|
return RunnerGroup{
|
|
Scope: scope,
|
|
Kind: Custom,
|
|
Name: name,
|
|
}
|
|
}
|
|
|
|
type RunnerGroup struct {
|
|
Scope RunnerGroupScope
|
|
Kind RunnerGroupKind
|
|
Name string
|
|
}
|
|
|
|
// VisibleRunnerGroups is a set of enterprise and organization runner groups
|
|
// that are visible to a GitHub repository.
|
|
// GitHub Actions chooses one of such visible group on which the workflow job is scheduled.
|
|
// ARC chooses the same group as Actions as the scale target.
|
|
type VisibleRunnerGroups struct {
|
|
// sortedGroups is a pointer to a mutable list of RunnerGroups that contains all the runner sortedGroups
|
|
// that are visible to the repository, including organization sortedGroups defined at the organization level,
|
|
// and enterprise sortedGroups that are inherited down to the organization.
|
|
sortedGroups []RunnerGroup
|
|
}
|
|
|
|
func NewVisibleRunnerGroups() *VisibleRunnerGroups {
|
|
return &VisibleRunnerGroups{}
|
|
}
|
|
|
|
func (g *VisibleRunnerGroups) IsEmpty() bool {
|
|
return len(g.sortedGroups) == 0
|
|
}
|
|
|
|
func (r *VisibleRunnerGroups) Includes(ref RunnerGroup) bool {
|
|
for _, r := range r.sortedGroups {
|
|
if r.Scope == ref.Scope && r.Kind == ref.Kind && r.Name == ref.Name {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Add adds a runner group into VisibleRunnerGroups
|
|
// at a certain position in the list so that
|
|
// Traverse can return runner groups in order of higher precedence to lower precedence.
|
|
func (g *VisibleRunnerGroups) Add(rg RunnerGroup) error {
|
|
n := len(g.sortedGroups)
|
|
i := sort.Search(n, func(i int) bool {
|
|
data := g.sortedGroups[i]
|
|
|
|
if rg.Kind > data.Kind {
|
|
return false
|
|
} else if rg.Kind < data.Kind {
|
|
return true
|
|
}
|
|
|
|
if rg.Scope > data.Scope {
|
|
return false
|
|
} else if rg.Scope < data.Scope {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
})
|
|
|
|
g.insert(rg, i)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (g *VisibleRunnerGroups) insert(rg RunnerGroup, i int) {
|
|
var result []RunnerGroup
|
|
|
|
result = append(result, g.sortedGroups[:i]...)
|
|
result = append(result, rg)
|
|
result = append(result, g.sortedGroups[i:]...)
|
|
|
|
g.sortedGroups = result
|
|
}
|
|
|
|
// Traverse traverses all the runner groups visible to a repository
|
|
// in order of higher precedence to lower precedence.
|
|
func (g *VisibleRunnerGroups) Traverse(f func(RunnerGroup) (bool, error)) error {
|
|
for _, rg := range g.sortedGroups {
|
|
ok, err := f(rg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if ok {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|