diff --git a/options/locale/locale_en-US.json b/options/locale/locale_en-US.json index bee657b8213..06fe859b86d 100644 --- a/options/locale/locale_en-US.json +++ b/options/locale/locale_en-US.json @@ -3854,6 +3854,9 @@ "actions.runs.all_workflows": "All Workflows", "actions.runs.other_workflows": "Other workflows", "actions.runs.other_workflows_tooltip": "Workflows that were executed in this repository but do not exist on the default branch.", + "actions.runs.reusable_workflows": "Reusable workflows", + "actions.runs.reusable_workflows_tooltip": "Workflows that can only be called by other workflows.", + "actions.runs.reusable_workflow_no_runs": "This workflow can only be called by other workflows.", "actions.runs.workflow_run_count_1": "%d workflow run", "actions.runs.workflow_run_count_n": "%d workflow runs", "actions.runs.commit": "Commit", diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go index 1d1ee7bff63..9f7ba159647 100644 --- a/routers/web/repo/actions/actions.go +++ b/routers/web/repo/actions/actions.go @@ -47,6 +47,7 @@ type WorkflowInfo struct { EntryName string ErrMsg string Workflow *act_model.Workflow + Reusable bool // only triggered by workflow_call } type workflowBadge struct { @@ -226,11 +227,13 @@ func prepareWorkflowTemplate(ctx *context.Context, commit *git.Commit) (workflow workflows = append(workflows, workflow) continue } - if _, err := actions.GetEventsFromContent(content); err != nil { + events, err := actions.GetEventsFromContent(content) + if err != nil { workflow.ErrMsg = ctx.Locale.TrString("actions.runs.invalid_workflow_helper", err.Error()) workflows = append(workflows, workflow) continue } + workflow.Reusable = len(events) == 0 && slices.Contains(wf.On(), "workflow_call") // events never include workflow_call workflow.Workflow = wf // The workflow must contain at least one job without "needs". Otherwise, a deadlock will occur and no jobs will be able to run. hasJobWithoutNeeds := false @@ -262,7 +265,11 @@ func prepareWorkflowTemplate(ctx *context.Context, commit *git.Commit) (workflow workflows = append(workflows, workflow) } + reusableWorkflows := slices.DeleteFunc(slices.Clone(workflows), func(w WorkflowInfo) bool { return !w.Reusable }) ctx.Data["workflows"] = workflows + ctx.Data["ReusableWorkflows"] = reusableWorkflows + ctx.Data["CurWorkflowIsReusable"] = ctx.FormInt64("scoped_workflow_source_repo_id") == 0 && + slices.ContainsFunc(reusableWorkflows, func(w WorkflowInfo) bool { return w.EntryName == curWorkflowID }) ctx.Data["RepoLink"] = ctx.Repo.Repository.Link() ctx.Data["RepoID"] = ctx.Repo.Repository.ID ctx.Data["AllowDisableOrEnableWorkflow"] = ctx.Repo.Permission.IsAdmin() diff --git a/templates/repo/actions/list.tmpl b/templates/repo/actions/list.tmpl index 136d3eaf7ad..9d64145c5ac 100644 --- a/templates/repo/actions/list.tmpl +++ b/templates/repo/actions/list.tmpl @@ -1,7 +1,7 @@ {{template "base/head" .}} -{{$showCreateWorkflowBadge := Iif .WorkflowBadge true false}} -{{$showEnableDisableWorkflow := and .AllowDisableOrEnableWorkflow .CurWorkflowIsListed $.CurWorkflow}} +{{$showCreateWorkflowBadge := and .WorkflowBadge (not .CurWorkflowIsReusable)}} +{{$showEnableDisableWorkflow := and .AllowDisableOrEnableWorkflow .CurWorkflowIsListed $.CurWorkflow (or (not .CurWorkflowIsReusable) .CurWorkflowDisabled)}}