From 01214c8ada993bf5f54a4149979d140443d69410 Mon Sep 17 00:00:00 2001
From: yp05327 <576951401@qq.com>
Date: Wed, 19 Apr 2023 21:51:20 +0900
Subject: [PATCH] Add runner check in repo action page (#24124)

![image](https://user-images.githubusercontent.com/18380374/232996647-13c2b9f1-c9e9-42d9-acbf-8a6e16b175a6.png)

Maybe we can also add online runner check? e.g. : Target runner is
offline.
---
 options/locale/locale_en-US.ini     |  2 +-
 routers/web/repo/actions/actions.go | 46 +++++++++++++++++++++++++----
 templates/repo/actions/list.tmpl    |  8 ++---
 3 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 416e883fc7..96e28fe87a 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -3407,7 +3407,7 @@ runs.open_tab = %d Open
 runs.closed_tab = %d Closed
 runs.commit = Commit
 runs.pushed_by = Pushed by
-runs.valid_workflow_helper = Workflow config file is valid.
 runs.invalid_workflow_helper = Workflow config file is invalid. Please check your config file: %s
+runs.no_matching_runner_helper = No matching runner: %s
 
 need_approval_desc = Need approval to run workflows for fork pull request.
diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go
index dd2dc55bd5..fc7ac2d714 100644
--- a/routers/web/repo/actions/actions.go
+++ b/routers/web/repo/actions/actions.go
@@ -4,6 +4,7 @@
 package actions
 
 import (
+	"bytes"
 	"net/http"
 
 	actions_model "code.gitea.io/gitea/models/actions"
@@ -11,11 +12,14 @@ import (
 	"code.gitea.io/gitea/models/unit"
 	"code.gitea.io/gitea/modules/actions"
 	"code.gitea.io/gitea/modules/base"
+	"code.gitea.io/gitea/modules/container"
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/services/convert"
+
+	"github.com/nektos/act/pkg/model"
 )
 
 const (
@@ -24,9 +28,8 @@ const (
 )
 
 type Workflow struct {
-	Entry     git.TreeEntry
-	IsInvalid bool
-	ErrMsg    string
+	Entry  git.TreeEntry
+	ErrMsg string
 }
 
 // MustEnableActions check if actions are enabled in settings
@@ -73,6 +76,23 @@ func List(ctx *context.Context) {
 			ctx.Error(http.StatusInternalServerError, err.Error())
 			return
 		}
+
+		// Get all runner labels
+		opts := actions_model.FindRunnerOptions{
+			RepoID:        ctx.Repo.Repository.ID,
+			WithAvailable: true,
+		}
+		runners, err := actions_model.FindRunners(ctx, opts)
+		if err != nil {
+			ctx.ServerError("FindRunners", err)
+			return
+		}
+		allRunnerLabels := make(container.Set[string])
+		for _, r := range runners {
+			allRunnerLabels.AddMultiple(r.AgentLabels...)
+			allRunnerLabels.AddMultiple(r.CustomLabels...)
+		}
+
 		workflows = make([]Workflow, 0, len(entries))
 		for _, entry := range entries {
 			workflow := Workflow{Entry: *entry}
@@ -81,10 +101,24 @@ func List(ctx *context.Context) {
 				ctx.Error(http.StatusInternalServerError, err.Error())
 				return
 			}
-			_, err = actions.GetEventsFromContent(content)
+			wf, err := model.ReadWorkflow(bytes.NewReader(content))
 			if err != nil {
-				workflow.IsInvalid = true
-				workflow.ErrMsg = err.Error()
+				workflow.ErrMsg = ctx.Locale.Tr("actions.runs.invalid_workflow_helper", err.Error())
+				workflows = append(workflows, workflow)
+				continue
+			}
+			// Check whether have matching runner
+			for _, j := range wf.Jobs {
+				runsOnList := j.RunsOn()
+				for _, ro := range runsOnList {
+					if !allRunnerLabels.Contains(ro) {
+						workflow.ErrMsg = ctx.Locale.Tr("actions.runs.no_matching_runner_helper", ro)
+						break
+					}
+				}
+				if workflow.ErrMsg != "" {
+					break
+				}
 			}
 			workflows = append(workflows, workflow)
 		}
diff --git a/templates/repo/actions/list.tmpl b/templates/repo/actions/list.tmpl
index b0e513cfb2..15f0d607a3 100644
--- a/templates/repo/actions/list.tmpl
+++ b/templates/repo/actions/list.tmpl
@@ -10,14 +10,10 @@
 					<div class="divider"></div>
 					{{range .workflows}}
 						<a class="item{{if eq .Entry.Name $.CurWorkflow}} active{{end}}" href="{{$.Link}}?workflow={{.Entry.Name}}">{{.Entry.Name}}
-							{{if .IsInvalid}}
-								<span data-tooltip-content="{{$.locale.Tr "actions.runs.invalid_workflow_helper" (.ErrMsg)}}">
+							{{if .ErrMsg}}
+								<span data-tooltip-content="{{.ErrMsg}}">
 									<i class="warning icon red"></i>
 								</span>
-							{{else}}
-								<span data-tooltip-content="{{$.locale.Tr "actions.runs.valid_workflow_helper"}}">
-									<i class="check icon green"></i>
-								</span>
 							{{end}}
 						</a>
 					{{end}}