diff --git a/models/actions/runner.go b/models/actions/runner.go index 09e009320d..1b83280307 100644 --- a/models/actions/runner.go +++ b/models/actions/runner.go @@ -191,9 +191,26 @@ func (r *ActionRunner) GenerateToken() (err error) { // CanMatchLabels checks whether the runner's labels can match a job's "runs-on" // See https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idruns-on +// +// Labels are matched by name, ignoring any ":scheme" suffix (e.g., ":host", ":docker"). +// This means a runner with label "germany-linux:host" will match runs-on "germany-linux", +// and a job with runs-on "germany-linux:host" will also match. func (r *ActionRunner) CanMatchLabels(jobRunsOn []string) bool { - runnerLabelSet := container.SetOf(r.AgentLabels...) - return runnerLabelSet.Contains(jobRunsOn...) // match all labels + // Build a set of runner label names (stripped of :scheme suffix) + runnerNames := make(container.Set[string], len(r.AgentLabels)) + for _, label := range r.AgentLabels { + name, _, _ := strings.Cut(label, ":") + runnerNames.Add(name) + } + + // Check that every runs-on label (also stripped of :scheme) is in the runner set + for _, requiredLabel := range jobRunsOn { + name, _, _ := strings.Cut(requiredLabel, ":") + if !runnerNames.Contains(name) { + return false + } + } + return true } func init() {