mirror of
https://github.com/bapung/gitea-runner-operator.git
synced 2026-06-21 23:48:43 +00:00
fix label logic
This commit is contained in:
@@ -5,7 +5,7 @@ kind: Kustomization
|
|||||||
images:
|
images:
|
||||||
- name: controller
|
- name: controller
|
||||||
newName: ghcr.io/bapung/gitea-runner-operator
|
newName: ghcr.io/bapung/gitea-runner-operator
|
||||||
newTag: sha-00496f8
|
newTag: sha-a34dedb
|
||||||
|
|
||||||
patchesStrategicMerge:
|
patchesStrategicMerge:
|
||||||
- image_pull_secret_patch.yaml
|
- image_pull_secret_patch.yaml
|
||||||
|
|||||||
@@ -117,6 +117,9 @@ func (r *RunnerGroupReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||||||
|
|
||||||
logger.Info("Checking Gitea for queued jobs", "url", runnerGroup.Spec.GiteaURL, "scope", runnerGroup.Spec.Scope)
|
logger.Info("Checking Gitea for queued jobs", "url", runnerGroup.Spec.GiteaURL, "scope", runnerGroup.Spec.Scope)
|
||||||
|
|
||||||
|
// Calculate effective labels (spec labels + defaults)
|
||||||
|
effectiveLabels := r.getEffectiveLabels(runnerGroup.Spec.Labels)
|
||||||
|
|
||||||
// Query for queued workflow runs
|
// Query for queued workflow runs
|
||||||
queuedJobs, err := r.GiteaClient.GetQueuedRuns(
|
queuedJobs, err := r.GiteaClient.GetQueuedRuns(
|
||||||
ctx,
|
ctx,
|
||||||
@@ -125,7 +128,7 @@ func (r *RunnerGroupReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||||||
runnerGroup.Spec.Scope,
|
runnerGroup.Spec.Scope,
|
||||||
runnerGroup.Spec.Org,
|
runnerGroup.Spec.Org,
|
||||||
runnerGroup.Spec.Repo,
|
runnerGroup.Spec.Repo,
|
||||||
runnerGroup.Spec.Labels,
|
effectiveLabels,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to query Gitea for queued runs")
|
logger.Error(err, "Failed to query Gitea for queued runs")
|
||||||
@@ -153,7 +156,7 @@ func (r *RunnerGroupReconciler) Reconcile(ctx context.Context, req ctrl.Request)
|
|||||||
|
|
||||||
// Spawn jobs
|
// Spawn jobs
|
||||||
for i := 0; i < toSpawn; i++ {
|
for i := 0; i < toSpawn; i++ {
|
||||||
job, err := r.constructJobForRunnerGroup(runnerGroup, registrationToken)
|
job, err := r.constructJobForRunnerGroup(runnerGroup, registrationToken, effectiveLabels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to construct Job")
|
logger.Error(err, "Failed to construct Job")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
@@ -191,8 +194,43 @@ func (r *RunnerGroupReconciler) getSecretValue(ctx context.Context, namespace st
|
|||||||
return string(value), nil
|
return string(value), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getEffectiveLabels merges spec labels with default labels
|
||||||
|
func (r *RunnerGroupReconciler) getEffectiveLabels(specLabels []string) []string {
|
||||||
|
defaultLabels := []string{
|
||||||
|
"ubuntu-latest:docker://node:16-bullseye",
|
||||||
|
"ubuntu-22.04:docker://node:16-bullseye",
|
||||||
|
"ubuntu-20.04:docker://node:16-bullseye",
|
||||||
|
"ubuntu-18.04:docker://node:16-buster",
|
||||||
|
}
|
||||||
|
|
||||||
|
effectiveLabels := make([]string, len(specLabels))
|
||||||
|
copy(effectiveLabels, specLabels)
|
||||||
|
|
||||||
|
for _, defaultLabel := range defaultLabels {
|
||||||
|
// Check if this default label key is already overridden in specLabels
|
||||||
|
// defaultLabel format is "key:schema"
|
||||||
|
parts := strings.SplitN(defaultLabel, ":", 2)
|
||||||
|
key := parts[0]
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, specLabel := range specLabels {
|
||||||
|
// Spec label can be "key" or "key:schema"
|
||||||
|
if specLabel == key || strings.HasPrefix(specLabel, key+":") {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
effectiveLabels = append(effectiveLabels, defaultLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return effectiveLabels
|
||||||
|
}
|
||||||
|
|
||||||
// constructJobForRunnerGroup creates a Job object for the RunnerGroup
|
// constructJobForRunnerGroup creates a Job object for the RunnerGroup
|
||||||
func (r *RunnerGroupReconciler) constructJobForRunnerGroup(runnerGroup *giteav1alpha1.RunnerGroup, registrationToken string) (*batchv1.Job, error) {
|
func (r *RunnerGroupReconciler) constructJobForRunnerGroup(runnerGroup *giteav1alpha1.RunnerGroup, registrationToken string, labels []string) (*batchv1.Job, error) {
|
||||||
// Generate random suffix for name
|
// Generate random suffix for name
|
||||||
name := fmt.Sprintf("%s-%s", runnerGroup.Name, randString(8))
|
name := fmt.Sprintf("%s-%s", runnerGroup.Name, randString(8))
|
||||||
|
|
||||||
@@ -206,8 +244,8 @@ func (r *RunnerGroupReconciler) constructJobForRunnerGroup(runnerGroup *giteav1a
|
|||||||
{Name: "DOCKER_TLS_VERIFY", Value: "1"},
|
{Name: "DOCKER_TLS_VERIFY", Value: "1"},
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(runnerGroup.Spec.Labels) > 0 {
|
if len(labels) > 0 {
|
||||||
labelsStr := strings.Join(runnerGroup.Spec.Labels, ",")
|
labelsStr := strings.Join(labels, ",")
|
||||||
envVars = append(envVars, corev1.EnvVar{Name: "GITEA_RUNNER_LABELS", Value: labelsStr})
|
envVars = append(envVars, corev1.EnvVar{Name: "GITEA_RUNNER_LABELS", Value: labelsStr})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -465,16 +465,11 @@ func (c *HTTPClient) fetchUserRepos(ctx context.Context, giteaURL, authToken str
|
|||||||
}
|
}
|
||||||
|
|
||||||
// filterQueuedJobs filters workflow jobs by labels
|
// filterQueuedJobs filters workflow jobs by labels
|
||||||
func (c *HTTPClient) filterQueuedJobs(jobs []ActionWorkflowJob, requiredLabels []string) int {
|
func (c *HTTPClient) filterQueuedJobs(jobs []ActionWorkflowJob, runnerLabels []string) int {
|
||||||
if len(requiredLabels) == 0 {
|
|
||||||
// No label filtering required, return all queued jobs
|
|
||||||
return len(jobs)
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
count := 0
|
||||||
for _, job := range jobs {
|
for _, job := range jobs {
|
||||||
match := c.jobMatchesLabels(job.Labels, requiredLabels)
|
match := c.jobMatchesLabels(job.Labels, runnerLabels)
|
||||||
fmt.Printf("DEBUG: Job %d (Status: %s, Labels: %v) matches requirements %v? %v\n", job.ID, job.Status, job.Labels, requiredLabels, match)
|
fmt.Printf("DEBUG: Job %d (Status: %s, Labels: %v) matches runner capabilities %v? %v\n", job.ID, job.Status, job.Labels, runnerLabels, match)
|
||||||
if match {
|
if match {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
@@ -482,17 +477,24 @@ func (c *HTTPClient) filterQueuedJobs(jobs []ActionWorkflowJob, requiredLabels [
|
|||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
// jobMatchesLabels checks if a job's labels match the required labels
|
// jobMatchesLabels checks if a job's requirements are satisfied by the runner's supported labels
|
||||||
func (c *HTTPClient) jobMatchesLabels(jobLabels, requiredLabels []string) bool {
|
func (c *HTTPClient) jobMatchesLabels(jobLabels, supportedLabels []string) bool {
|
||||||
// Convert job labels to map for faster lookup
|
if len(jobLabels) == 0 {
|
||||||
labelSet := make(map[string]bool)
|
return true
|
||||||
for _, label := range jobLabels {
|
|
||||||
labelSet[label] = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if all required labels are present
|
// For each label required by the job, check if the runner supports it
|
||||||
for _, required := range requiredLabels {
|
for _, req := range jobLabels {
|
||||||
if !labelSet[required] {
|
found := false
|
||||||
|
for _, supp := range supportedLabels {
|
||||||
|
// Check for exact match or schema match (label:schema)
|
||||||
|
// e.g. Job asks for "ubuntu-latest", Runner has "ubuntu-latest:docker://..."
|
||||||
|
if req == supp || strings.HasPrefix(supp, req+":") {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user