diff --git a/internal/pkg/labels/labels.go b/internal/pkg/labels/labels.go index 974bad0..a069b1f 100644 --- a/internal/pkg/labels/labels.go +++ b/internal/pkg/labels/labels.go @@ -56,6 +56,7 @@ func (l Labels) RequireDocker() bool { } // PickPlatform selects the appropriate platform based on the runsOn requirements. +// Returns empty string if no matching label is found, which will cause the job to fail. func (l Labels) PickPlatform(runsOn []string) string { platforms := make(map[string]string, len(l)) for _, label := range l { @@ -76,17 +77,12 @@ func (l Labels) PickPlatform(runsOn []string) string { } } - // TODO: support multiple labels - // like: - // ["ubuntu-22.04"] => "ubuntu:22.04" - // ["with-gpu"] => "linux:with-gpu" - // ["ubuntu-22.04", "with-gpu"] => "ubuntu:22.04_with-gpu" - - // return default. - // So the runner receives a task with a label that the runner doesn't have, - // it happens when the user have edited the label of the runner in the web UI. - // TODO: it may be not correct, what if the runner is used as host mode only? - return "docker.gitea.com/runner-images:ubuntu-latest" + // No matching label found. This indicates a mismatch between server's view + // of runner labels and the runner's local configuration (e.g., labels were + // edited in Gitea admin UI after runner registered). Return empty string + // to cause the job to fail with a clear error rather than silently running + // in the wrong environment. + return "" } // Names returns the names of all labels. diff --git a/internal/pkg/labels/labels_test.go b/internal/pkg/labels/labels_test.go index e46a27b..bad16d9 100644 --- a/internal/pkg/labels/labels_test.go +++ b/internal/pkg/labels/labels_test.go @@ -10,6 +10,64 @@ import ( "gotest.tools/v3/assert" ) +func TestPickPlatform(t *testing.T) { + tests := []struct { + name string + labels []string + runsOn []string + want string + }{ + { + name: "exact match host label", + labels: []string{"linux-latest:host", "ubuntu:host"}, + runsOn: []string{"linux-latest"}, + want: "-self-hosted", + }, + { + name: "exact match docker label", + labels: []string{"ubuntu:docker://node:18"}, + runsOn: []string{"ubuntu"}, + want: "node:18", + }, + { + name: "no match returns empty string to fail job", + labels: []string{"linux:host", "debian:host"}, + runsOn: []string{"unknown-label"}, + want: "", + }, + { + name: "no match on docker runner returns empty string", + labels: []string{"ubuntu:docker://node:18", "linux:host"}, + runsOn: []string{"unknown-label"}, + want: "", + }, + { + name: "empty labels returns empty string", + labels: []string{}, + runsOn: []string{"anything"}, + want: "", + }, + { + name: "multiple runsOn matches first available", + labels: []string{"linux:host", "ubuntu:docker://node:18"}, + runsOn: []string{"windows", "ubuntu"}, + want: "node:18", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ls := Labels{} + for _, l := range tt.labels { + label, err := Parse(l) + require.NoError(t, err) + ls = append(ls, label) + } + got := ls.PickPlatform(tt.runsOn) + assert.Equal(t, got, tt.want) + }) + } +} + func TestParse(t *testing.T) { tests := []struct { args string