diff --git a/models/actions/run.go b/models/actions/run.go
index 4f886999e9cd..37064520a213 100644
--- a/models/actions/run.go
+++ b/models/actions/run.go
@@ -361,6 +361,19 @@ func GetRunByIndex(ctx context.Context, repoID, index int64) (*ActionRun, error)
 	return run, nil
 }
 
+func GetLatestRun(ctx context.Context, repoID int64) (*ActionRun, error) {
+	run := &ActionRun{
+		RepoID: repoID,
+	}
+	has, err := db.GetEngine(ctx).Where("repo_id=?", repoID).Desc("index").Get(run)
+	if err != nil {
+		return nil, err
+	} else if !has {
+		return nil, fmt.Errorf("latest run with repo_id %d: %w", repoID, util.ErrNotExist)
+	}
+	return run, nil
+}
+
 func GetWorkflowLatestRun(ctx context.Context, repoID int64, workflowFile, branch, event string) (*ActionRun, error) {
 	var run ActionRun
 	q := db.GetEngine(ctx).Where("repo_id=?", repoID).
diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go
index 84319fc8609b..6b422891648c 100644
--- a/routers/web/repo/actions/view.go
+++ b/routers/web/repo/actions/view.go
@@ -33,9 +33,19 @@ import (
 	"xorm.io/builder"
 )
 
+func getRunIndex(ctx *context_module.Context) int64 {
+	// if run param is "latest", get the latest run index
+	if ctx.PathParam("run") == "latest" {
+		if run, _ := actions_model.GetLatestRun(ctx, ctx.Repo.Repository.ID); run != nil {
+			return run.Index
+		}
+	}
+	return ctx.PathParamInt64("run")
+}
+
 func View(ctx *context_module.Context) {
 	ctx.Data["PageIsActions"] = true
-	runIndex := ctx.PathParamInt64("run")
+	runIndex := getRunIndex(ctx)
 	jobIndex := ctx.PathParamInt64("job")
 	ctx.Data["RunIndex"] = runIndex
 	ctx.Data["JobIndex"] = jobIndex
@@ -130,7 +140,7 @@ type ViewStepLogLine struct {
 
 func ViewPost(ctx *context_module.Context) {
 	req := web.GetForm(ctx).(*ViewRequest)
-	runIndex := ctx.PathParamInt64("run")
+	runIndex := getRunIndex(ctx)
 	jobIndex := ctx.PathParamInt64("job")
 
 	current, jobs := getRunJobs(ctx, runIndex, jobIndex)
@@ -289,7 +299,7 @@ func ViewPost(ctx *context_module.Context) {
 // Rerun will rerun jobs in the given run
 // If jobIndexStr is a blank string, it means rerun all jobs
 func Rerun(ctx *context_module.Context) {
-	runIndex := ctx.PathParamInt64("run")
+	runIndex := getRunIndex(ctx)
 	jobIndexStr := ctx.PathParam("job")
 	var jobIndex int64
 	if jobIndexStr != "" {
@@ -379,7 +389,7 @@ func rerunJob(ctx *context_module.Context, job *actions_model.ActionRunJob, shou
 }
 
 func Logs(ctx *context_module.Context) {
-	runIndex := ctx.PathParamInt64("run")
+	runIndex := getRunIndex(ctx)
 	jobIndex := ctx.PathParamInt64("job")
 
 	job, _ := getRunJobs(ctx, runIndex, jobIndex)
@@ -428,7 +438,7 @@ func Logs(ctx *context_module.Context) {
 }
 
 func Cancel(ctx *context_module.Context) {
-	runIndex := ctx.PathParamInt64("run")
+	runIndex := getRunIndex(ctx)
 
 	_, jobs := getRunJobs(ctx, runIndex, -1)
 	if ctx.Written() {
@@ -469,7 +479,7 @@ func Cancel(ctx *context_module.Context) {
 }
 
 func Approve(ctx *context_module.Context) {
-	runIndex := ctx.PathParamInt64("run")
+	runIndex := getRunIndex(ctx)
 
 	current, jobs := getRunJobs(ctx, runIndex, -1)
 	if ctx.Written() {
@@ -518,7 +528,6 @@ func getRunJobs(ctx *context_module.Context, runIndex, jobIndex int64) (*actions
 		return nil, nil
 	}
 	run.Repo = ctx.Repo.Repository
-
 	jobs, err := actions_model.GetRunJobsByRunID(ctx, run.ID)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, err.Error())
@@ -550,7 +559,7 @@ type ArtifactsViewItem struct {
 }
 
 func ArtifactsView(ctx *context_module.Context) {
-	runIndex := ctx.PathParamInt64("run")
+	runIndex := getRunIndex(ctx)
 	run, err := actions_model.GetRunByIndex(ctx, ctx.Repo.Repository.ID, runIndex)
 	if err != nil {
 		if errors.Is(err, util.ErrNotExist) {
@@ -588,7 +597,7 @@ func ArtifactsDeleteView(ctx *context_module.Context) {
 		return
 	}
 
-	runIndex := ctx.PathParamInt64("run")
+	runIndex := getRunIndex(ctx)
 	artifactName := ctx.PathParam("artifact_name")
 
 	run, err := actions_model.GetRunByIndex(ctx, ctx.Repo.Repository.ID, runIndex)
@@ -606,7 +615,7 @@ func ArtifactsDeleteView(ctx *context_module.Context) {
 }
 
 func ArtifactsDownloadView(ctx *context_module.Context) {
-	runIndex := ctx.PathParamInt64("run")
+	runIndex := getRunIndex(ctx)
 	artifactName := ctx.PathParam("artifact_name")
 
 	run, err := actions_model.GetRunByIndex(ctx, ctx.Repo.Repository.ID, runIndex)