From d9aeb1f09d3e8e734ccc51c50072a07f822e3033 Mon Sep 17 00:00:00 2001
From: Giteabot <teabot@gitea.io>
Date: Tue, 19 Dec 2023 12:06:31 +0800
Subject: [PATCH] Only check online runner when detecting matching runners in
 workflows (#28286) (#28512)

Backport #28286 by @yp05327

Mentioned:
[#28277](https://github.com/go-gitea/gitea/issues/28277#issuecomment-1831325276)

We should only check online runner when detecting matching runners in
workflows,
as if runner is not online, the workflow will not run.


![image](https://github.com/go-gitea/gitea/assets/18380374/11855e9d-7241-4b7a-b8d7-49dbb94ba1c5)

Co-authored-by: yp05327 <576951401@qq.com>
---
 models/actions/runner.go            | 17 +++++++++++++++--
 options/locale/locale_en-US.ini     |  2 +-
 routers/web/repo/actions/actions.go |  4 +++-
 3 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/models/actions/runner.go b/models/actions/runner.go
index 2c092c2b4a..aaeb80ce63 100644
--- a/models/actions/runner.go
+++ b/models/actions/runner.go
@@ -51,6 +51,11 @@ type ActionRunner struct {
 	Deleted timeutil.TimeStamp `xorm:"deleted"`
 }
 
+const (
+	RunnerOfflineTime = time.Minute
+	RunnerIdleTime    = 10 * time.Second
+)
+
 // BelongsToOwnerName before calling, should guarantee that all attributes are loaded
 func (r *ActionRunner) BelongsToOwnerName() string {
 	if r.RepoID != 0 {
@@ -76,11 +81,12 @@ func (r *ActionRunner) BelongsToOwnerType() types.OwnerType {
 	return types.OwnerTypeSystemGlobal
 }
 
+// if the logic here changed, you should also modify FindRunnerOptions.ToCond
 func (r *ActionRunner) Status() runnerv1.RunnerStatus {
-	if time.Since(r.LastOnline.AsTime()) > time.Minute {
+	if time.Since(r.LastOnline.AsTime()) > RunnerOfflineTime {
 		return runnerv1.RunnerStatus_RUNNER_STATUS_OFFLINE
 	}
-	if time.Since(r.LastActive.AsTime()) > 10*time.Second {
+	if time.Since(r.LastActive.AsTime()) > RunnerIdleTime {
 		return runnerv1.RunnerStatus_RUNNER_STATUS_IDLE
 	}
 	return runnerv1.RunnerStatus_RUNNER_STATUS_ACTIVE
@@ -153,6 +159,7 @@ type FindRunnerOptions struct {
 	OwnerID       int64
 	Sort          string
 	Filter        string
+	IsOnline      util.OptionalBool
 	WithAvailable bool // not only runners belong to, but also runners can be used
 }
 
@@ -178,6 +185,12 @@ func (opts FindRunnerOptions) toCond() builder.Cond {
 	if opts.Filter != "" {
 		cond = cond.And(builder.Like{"name", opts.Filter})
 	}
+
+	if opts.IsOnline.IsTrue() {
+		cond = cond.And(builder.Gt{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
+	} else if opts.IsOnline.IsFalse() {
+		cond = cond.And(builder.Lte{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()})
+	}
 	return cond
 }
 
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index abc99d775d..0454eb68ca 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -3520,7 +3520,7 @@ runs.commit = Commit
 runs.scheduled = Scheduled
 runs.pushed_by = pushed by
 runs.invalid_workflow_helper = Workflow config file is invalid. Please check your config file: %s
-runs.no_matching_runner_helper = No matching runner: %s
+runs.no_matching_online_runner_helper = No matching online runner with label: %s
 runs.actor = Actor
 runs.status = Status
 runs.actors_no_select = All actors
diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go
index 1de402ccc0..9f787f5125 100644
--- a/routers/web/repo/actions/actions.go
+++ b/routers/web/repo/actions/actions.go
@@ -18,6 +18,7 @@ import (
 	"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/routers/web/repo"
 	"code.gitea.io/gitea/services/convert"
 
@@ -77,6 +78,7 @@ func List(ctx *context.Context) {
 		// Get all runner labels
 		opts := actions_model.FindRunnerOptions{
 			RepoID:        ctx.Repo.Repository.ID,
+			IsOnline:      util.OptionalBoolTrue,
 			WithAvailable: true,
 		}
 		runners, err := actions_model.FindRunners(ctx, opts)
@@ -114,7 +116,7 @@ func List(ctx *context.Context) {
 						continue
 					}
 					if !allRunnerLabels.Contains(ro) {
-						workflow.ErrMsg = ctx.Locale.Tr("actions.runs.no_matching_runner_helper", ro)
+						workflow.ErrMsg = ctx.Locale.Tr("actions.runs.no_matching_online_runner_helper", ro)
 						break
 					}
 				}