diff --git a/services/actions/job_emitter.go b/services/actions/job_emitter.go
index d2bbbd9a7ca2..1f859fcf7050 100644
--- a/services/actions/job_emitter.go
+++ b/services/actions/job_emitter.go
@@ -7,7 +7,6 @@ import (
 	"context"
 	"errors"
 	"fmt"
-	"strings"
 
 	actions_model "code.gitea.io/gitea/models/actions"
 	"code.gitea.io/gitea/models/db"
@@ -141,18 +140,19 @@ func (r *jobStatusResolver) resolve() map[int64]actions_model.Status {
 			if allSucceed {
 				ret[id] = actions_model.StatusWaiting
 			} else {
-				// If a job's "if" condition is "always()", the job should always run even if some of its dependencies did not succeed.
-				// See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idneeds
-				always := false
+				// Check if the job has an "if" condition
+				hasIf := false
 				if wfJobs, _ := jobparser.Parse(r.jobMap[id].WorkflowPayload); len(wfJobs) == 1 {
 					_, wfJob := wfJobs[0].Job()
-					expr := strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(wfJob.If.Value, "${{"), "}}"))
-					always = expr == "always()"
+					hasIf = len(wfJob.If.Value) > 0
 				}
 
-				if always {
+				if hasIf {
+					// act_runner will check the "if" condition
 					ret[id] = actions_model.StatusWaiting
 				} else {
+					// If the "if" condition is empty and not all dependent jobs completed successfully,
+					// the job should be skipped.
 					ret[id] = actions_model.StatusSkipped
 				}
 			}
diff --git a/services/actions/job_emitter_test.go b/services/actions/job_emitter_test.go
index 038df7d4f86b..58c2dc3b242b 100644
--- a/services/actions/job_emitter_test.go
+++ b/services/actions/job_emitter_test.go
@@ -71,9 +71,9 @@ func Test_jobStatusResolver_Resolve(t *testing.T) {
 			want: map[int64]actions_model.Status{},
 		},
 		{
-			name: "with ${{ always() }} condition",
+			name: "`if` is not empty and all jobs in `needs` completed successfully",
 			jobs: actions_model.ActionJobList{
-				{ID: 1, JobID: "job1", Status: actions_model.StatusFailure, Needs: []string{}},
+				{ID: 1, JobID: "job1", Status: actions_model.StatusSuccess, Needs: []string{}},
 				{ID: 2, JobID: "job2", Status: actions_model.StatusBlocked, Needs: []string{"job1"}, WorkflowPayload: []byte(
 					`
 name: test
@@ -82,15 +82,15 @@ jobs:
   job2:
     runs-on: ubuntu-latest
     needs: job1
-    if: ${{ always() }}
+    if: ${{ always() && needs.job1.result == 'success' }}
     steps:
-      - run: echo "always run"
+      - run: echo "will be checked by act_runner"
 `)},
 			},
 			want: map[int64]actions_model.Status{2: actions_model.StatusWaiting},
 		},
 		{
-			name: "with always() condition",
+			name: "`if` is not empty and not all jobs in `needs` completed successfully",
 			jobs: actions_model.ActionJobList{
 				{ID: 1, JobID: "job1", Status: actions_model.StatusFailure, Needs: []string{}},
 				{ID: 2, JobID: "job2", Status: actions_model.StatusBlocked, Needs: []string{"job1"}, WorkflowPayload: []byte(
@@ -101,15 +101,15 @@ jobs:
   job2:
     runs-on: ubuntu-latest
     needs: job1
-    if: always()
+    if: ${{ always() && needs.job1.result == 'failure' }}
     steps:
-      - run: echo "always run"
+      - run: echo "will be checked by act_runner"
 `)},
 			},
 			want: map[int64]actions_model.Status{2: actions_model.StatusWaiting},
 		},
 		{
-			name: "without always() condition",
+			name: "`if` is empty and not all jobs in `needs` completed successfully",
 			jobs: actions_model.ActionJobList{
 				{ID: 1, JobID: "job1", Status: actions_model.StatusFailure, Needs: []string{}},
 				{ID: 2, JobID: "job2", Status: actions_model.StatusBlocked, Needs: []string{"job1"}, WorkflowPayload: []byte(
@@ -121,7 +121,7 @@ jobs:
     runs-on: ubuntu-latest
     needs: job1
     steps:
-      - run: echo "not always run"
+      - run: echo "should be skipped"
 `)},
 			},
 			want: map[int64]actions_model.Status{2: actions_model.StatusSkipped},