1// Copyright 2023 The Gitea Authors. All rights reserved.2// SPDX-License-Identifier: MIT34package labels56import (7 "fmt"8 "strings"9)1011const (12 SchemeHost = "host"13 SchemeDocker = "docker"14 SchemeQemu = "qemu"15 SchemeSSH = "ssh"16 SchemeLXC = "lxc"17)1819type Label struct {20 Name string21 Schema string22 Arg string23}2425func Parse(str string) (*Label, error) {26 splits := strings.SplitN(str, ":", 3)27 label := &Label{28 Name: splits[0],29 Schema: "host",30 Arg: "",31 }32 if len(splits) >= 2 {33 label.Schema = splits[1]34 }35 if len(splits) >= 3 {36 label.Arg = splits[2]37 }38 if label.Schema != SchemeHost && label.Schema != SchemeDocker && label.Schema != SchemeLXC && label.Schema != SchemeQemu && label.Schema != SchemeSSH {39 return nil, fmt.Errorf("unsupported schema: %s", label.Schema)40 }41 return label, nil42}4344type Labels []*Label4546func (l Labels) RequireDocker() bool {47 for _, label := range l {48 if label.Schema == SchemeDocker {49 return true50 }51 }52 return false53}5455func (l Labels) PickPlatform(runsOn []string) string {56 platforms := make(map[string]string, len(l))57 for _, label := range l {58 switch label.Schema {59 case SchemeDocker:60 // "//" will be ignored61 platforms[label.Name] = strings.TrimPrefix(label.Arg, "//")62 case SchemeHost:63 platforms[label.Name] = "-self-hosted"64 case SchemeLXC:65 platforms[label.Name] = "lxc:" + strings.TrimPrefix(label.Arg, "//")66 case SchemeQemu:67 platforms[label.Name] = strings.TrimPrefix(label.Arg, "//")68 case SchemeSSH:69 platforms[label.Name] = strings.TrimPrefix(label.Arg, "//")70 default:71 // It should not happen, because Parse has checked it.72 continue73 }74 platforms[label.Name] = fmt.Sprintf("%s://%s", label.Schema, platforms[label.Name])75 }76 for _, v := range runsOn {77 if v, ok := platforms[v]; ok {78 return v79 }80 }8182 // TODO: support multiple labels83 // like:84 // ["ubuntu-22.04"] => "ubuntu:22.04"85 // ["with-gpu"] => "linux:with-gpu"86 // ["ubuntu-22.04", "with-gpu"] => "ubuntu:22.04_with-gpu"8788 // return default.89 // So the runner receives a task with a label that the runner doesn't have,90 // it happens when the user have edited the label of the runner in the web UI.91 // TODO: it may be not correct, what if the runner is used as host mode only?92 return "node:20-bullseye"93}9495func (l Labels) Names() []string {96 names := make([]string, 0, len(l))97 for _, label := range l {98 names = append(names, label.Name)99 }100 return names101}102103func (l Labels) ToStrings() []string {104 ls := make([]string, 0, len(l))105 for _, label := range l {106 lbl := label.Name107 if label.Schema != "" {108 lbl += ":" + label.Schema109 if label.Arg != "" {110 lbl += ":" + label.Arg111 }112 }113 ls = append(ls, lbl)114 }115 return ls116}