diff --git a/models/issues/comment.go b/models/issues/comment.go index 25e74c01ea..72c4d8e009 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -237,6 +237,13 @@ func (r RoleInRepo) LocaleHelper(lang translation.Locale) string { type SpecialDoerNameType string const SpecialDoerNameCodeOwners SpecialDoerNameType = "CODEOWNERS" +const SpecialDoerNameProjectWorkflow SpecialDoerNameType = "PROJECT_WORKFLOW" + +type ProjectWorkflowCommentMeta struct { + ProjectTitle string + ProjectWorkflowID int64 + ProjectWorkflowEvent project_model.WorkflowEvent +} // CommentMetaData stores metadata for a comment, these data will not be changed once inserted into database type CommentMetaData struct { @@ -244,9 +251,26 @@ type CommentMetaData struct { ProjectColumnTitle string `json:"project_column_title,omitempty"` ProjectTitle string `json:"project_title,omitempty"` + ProjectWorkflowID int64 `json:"project_workflow_id,omitempty"` + ProjectWorkflowEvent project_model.WorkflowEvent `json:"project_workflow_event,omitempty"` + SpecialDoerName SpecialDoerNameType `json:"special_doer_name,omitempty"` // e.g. "CODEOWNERS" for CODEOWNERS-triggered review requests } +type commentMetaDataKey struct{} + +func WithProjectWorkflowCommentMeta(ctx context.Context, meta ProjectWorkflowCommentMeta) context.Context { + if meta.ProjectWorkflowID == 0 { + return ctx + } + return context.WithValue(ctx, commentMetaDataKey{}, meta) +} + +func getProjectWorkflowCommentMeta(ctx context.Context) (ProjectWorkflowCommentMeta, bool) { + meta, ok := ctx.Value(commentMetaDataKey{}).(ProjectWorkflowCommentMeta) + return meta, ok +} + // Comment represents a comment in commit and issue page. type Comment struct { ID int64 `xorm:"pk autoincr"` @@ -775,8 +799,17 @@ func (c *Comment) MetaSpecialDoerTr(locale translation.Locale) template.HTML { if c.CommentMetaData == nil { return "" } - if c.CommentMetaData.SpecialDoerName == SpecialDoerNameCodeOwners { + switch c.CommentMetaData.SpecialDoerName { + case SpecialDoerNameCodeOwners: return locale.Tr("repo.issues.review.codeowners_rules") + case SpecialDoerNameProjectWorkflow: + if c.CommentMetaData.ProjectWorkflowID > 0 { + return htmlutil.HTMLFormat("%s", locale.Tr("repo.issues.project_workflow_action", + htmlutil.HTMLFormat("%s", locale.Tr(c.CommentMetaData.ProjectWorkflowEvent.LangKey())), + htmlutil.HTMLFormat("%s", c.CommentMetaData.ProjectTitle), + )) + } + return locale.Tr("repo.issues.project_workflow") } return htmlutil.HTMLFormat("%s", c.CommentMetaData.SpecialDoerName) } @@ -823,6 +856,15 @@ func CreateComment(ctx context.Context, opts *CreateCommentOptions) (_ *Comment, SpecialDoerName: opts.SpecialDoerName, } } + if workflowMeta, ok := getProjectWorkflowCommentMeta(ctx); ok { + if commentMetaData == nil { + commentMetaData = &CommentMetaData{} + } + commentMetaData.ProjectWorkflowID = workflowMeta.ProjectWorkflowID + commentMetaData.ProjectWorkflowEvent = workflowMeta.ProjectWorkflowEvent + commentMetaData.ProjectTitle = workflowMeta.ProjectTitle + commentMetaData.SpecialDoerName = SpecialDoerNameProjectWorkflow + } comment := &Comment{ Type: opts.Type, diff --git a/models/user/user.go b/models/user/user.go index 48066ea26f..d74c1a2f87 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -564,7 +564,6 @@ var globalVars = sync.OnceValue(func() *globalVarsStruct { systemUserNewFuncs: map[int64]func() *User{ GhostUserID: NewGhostUser, ActionsUserID: NewActionsUser, - ProjectWorkflowsUserID: NewProjectWorkflowsUser, }, } }) diff --git a/models/user/user_list.go b/models/user/user_list.go index 0114db8dbd..1b6a27dd86 100644 --- a/models/user/user_list.go +++ b/models/user/user_list.go @@ -36,8 +36,6 @@ func GetPossibleUserFromMap(userID int64, usererMaps map[int64]*User) *User { return NewGhostUser() case ActionsUserID: return NewActionsUser() - case ProjectWorkflowsUserID: - return NewProjectWorkflowsUser() case 0: return nil default: diff --git a/models/user/user_system.go b/models/user/user_system.go index 416ecac783..cf4306df25 100644 --- a/models/user/user_system.go +++ b/models/user/user_system.go @@ -79,37 +79,6 @@ func (u *User) IsGiteaActions() bool { return u != nil && u.ID == ActionsUserID } -const ( - ProjectWorkflowsUserID int64 = -3 - ProjectWorkflowsUserName = "project-workflows" - ProjectWorkflowsUserEmail = "workflows@gitea.io" -) - -func IsProjectWorkflowsUserName(name string) bool { - return strings.EqualFold(name, ProjectWorkflowsUserName) -} - -// NewProjectWorkflowsUser creates and returns a fake user for running the project workflows. -func NewProjectWorkflowsUser() *User { - return &User{ - ID: ProjectWorkflowsUserID, - Name: ProjectWorkflowsUserName, - LowerName: ProjectWorkflowsUserName, - IsActive: true, - FullName: "Project Workflows", - Email: ProjectWorkflowsUserEmail, - KeepEmailPrivate: true, - LoginName: ProjectWorkflowsUserName, - Type: UserTypeBot, - AllowCreateOrganization: true, - Visibility: structs.VisibleTypePublic, - } -} - -func (u *User) IsProjectWorkflows() bool { - return u != nil && u.ID == ProjectWorkflowsUserID -} - func GetSystemUserByName(name string) *User { if strings.EqualFold(name, GhostUserName) { return NewGhostUser() @@ -117,8 +86,5 @@ func GetSystemUserByName(name string) *User { if strings.EqualFold(name, ActionsUserName) { return NewActionsUser() } - if IsProjectWorkflowsUserName(name) { - return NewProjectWorkflowsUser() - } return nil } diff --git a/models/user/user_system_test.go b/models/user/user_system_test.go index bfc56322a1..70a900378f 100644 --- a/models/user/user_system_test.go +++ b/models/user/user_system_test.go @@ -31,13 +31,6 @@ func TestSystemUser(t *testing.T) { require.NotNil(t, u) assert.Equal(t, "Gitea Actions", u.FullName) - u, err = GetPossibleUserByID(t.Context(), -3) - require.NoError(t, err) - assert.Equal(t, "project-workflows", u.Name) - assert.Equal(t, "project-workflows", u.LowerName) - assert.True(t, u.IsProjectWorkflows()) - assert.True(t, IsProjectWorkflowsUserName("Project-Workflows")) - - _, err = GetPossibleUserByID(t.Context(), -4) + _, err = GetPossibleUserByID(t.Context(), -3) require.Error(t, err) } diff --git a/options/locale/locale_en-US.json b/options/locale/locale_en-US.json index 0a91a59579..79a893a580 100644 --- a/options/locale/locale_en-US.json +++ b/options/locale/locale_en-US.json @@ -1529,6 +1529,8 @@ "repo.issues.context.edit": "Edit", "repo.issues.context.delete": "Delete", "repo.issues.no_content": "No description provided.", + "repo.issues.project_workflow": "Project workflow", + "repo.issues.project_workflow_action": "Workflow %[1]s of Project %[2]s", "repo.issues.close": "Close Issue", "repo.issues.comment_pull_merged_at": "merged commit %[1]s into %[2]s %[3]s", "repo.issues.comment_manually_pull_merged_at": "manually merged commit %[1]s into %[2]s %[3]s", diff --git a/services/projects/workflow_notifier.go b/services/projects/workflow_notifier.go index 20f96d26b8..c99a7adaf9 100644 --- a/services/projects/workflow_notifier.go +++ b/services/projects/workflow_notifier.go @@ -345,6 +345,15 @@ func matchWorkflowsFilters(workflow *project_model.Workflow, issue *issues_model } func executeWorkflowActions(ctx context.Context, workflow *project_model.Workflow, issue *issues_model.Issue) { + if err := workflow.LoadProject(ctx); err != nil { + log.Error("LoadProject: %v", err) + } + workflowCtx := issues_model.WithProjectWorkflowCommentMeta(ctx, issues_model.ProjectWorkflowCommentMeta{ + ProjectTitle: util.Iif(workflow.Project != nil, workflow.Project.Title, ""), + ProjectWorkflowID: workflow.ID, + ProjectWorkflowEvent: workflow.WorkflowEvent, + }) + doer := user_model.NewGhostUser() var toAddedLabels, toRemovedLabels []*issues_model.Label for _, action := range workflow.WorkflowActions { @@ -360,7 +369,7 @@ func executeWorkflowActions(ctx context.Context, workflow *project_model.Workflo log.Error("GetColumnByIDAndProjectID: %v", err) continue } - if err := MoveIssueToAnotherColumn(ctx, user_model.NewProjectWorkflowsUser(), issue, column); err != nil { + if err := MoveIssueToAnotherColumn(workflowCtx, doer, issue, column); err != nil { log.Error("MoveIssueToAnotherColumn: %v", err) continue } @@ -391,14 +400,14 @@ func executeWorkflowActions(ctx context.Context, workflow *project_model.Workflo case project_model.WorkflowActionTypeIssueState: if strings.EqualFold(action.Value, "reopen") { if issue.IsClosed { - if err := issue_service.ReopenIssue(ctx, issue, user_model.NewProjectWorkflowsUser(), ""); err != nil { + if err := issue_service.ReopenIssue(workflowCtx, issue, doer, ""); err != nil { log.Error("ReopenIssue: %v", err) continue } } } else if strings.EqualFold(action.Value, "close") { if !issue.IsClosed { - if err := issue_service.CloseIssue(ctx, issue, user_model.NewProjectWorkflowsUser(), ""); err != nil { + if err := issue_service.CloseIssue(workflowCtx, issue, doer, ""); err != nil { log.Error("CloseIssue: %v", err) continue } @@ -410,7 +419,7 @@ func executeWorkflowActions(ctx context.Context, workflow *project_model.Workflo } if len(toAddedLabels)+len(toRemovedLabels) > 0 { - if err := issue_service.AddRemoveLabels(ctx, issue, user_model.NewProjectWorkflowsUser(), toAddedLabels, toRemovedLabels); err != nil { + if err := issue_service.AddRemoveLabels(workflowCtx, issue, doer, toAddedLabels, toRemovedLabels); err != nil { log.Error("AddRemoveLabels: %v", err) } } diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index e7b4c8758d..982c8373b2 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -144,7 +144,7 @@ {{template "shared/user/avatarlink" dict "user" .Poster}} {{if eq .RefAction 3}}{{end}} - {{template "shared/user/authorlink" .Poster}} + {{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}} {{ctx.Locale.Tr $refTr .EventTag $createdStr (.RefCommentLink ctx) $refFrom}} {{if eq .RefAction 3}}{{end}} @@ -158,7 +158,7 @@ {{svg "octicon-bookmark"}} {{template "shared/user/avatarlink" dict "user" .Poster}} - {{template "shared/user/authorlink" .Poster}} + {{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}} {{ctx.Locale.Tr "repo.issues.commit_ref_at" .EventTag $createdStr}}
@@ -173,7 +173,7 @@ {{svg "octicon-tag"}} {{template "shared/user/avatarlink" dict "user" .Poster}} - {{template "shared/user/authorlink" .Poster}} + {{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}} {{if and .AddedLabels (not .RemovedLabels)}} {{ctx.Locale.TrN (len .AddedLabels) "repo.issues.add_label" "repo.issues.add_labels" (ctx.RenderUtils.RenderLabels .AddedLabels $.RepoLink .Issue) $createdStr}} {{else if and (not .AddedLabels) .RemovedLabels}} @@ -588,7 +588,7 @@ {{svg "octicon-project"}} {{template "shared/user/avatarlink" dict "user" .Poster}} - {{template "shared/user/authorlink" .Poster}} + {{template "repo/issue/view_content/comments_authorlink" dict "ctxData" $ "comment" .}} {{$newProjectDisplay := .CommentMetaData.ProjectTitle}} {{if .Project}} {{$trKey := printf "projects.type-%d.display_name" .Project.Type}} diff --git a/templates/repo/issue/view_content/comments_authorlink.tmpl b/templates/repo/issue/view_content/comments_authorlink.tmpl index f652a0bec3..26c223c5d2 100644 --- a/templates/repo/issue/view_content/comments_authorlink.tmpl +++ b/templates/repo/issue/view_content/comments_authorlink.tmpl @@ -7,5 +7,10 @@ ({{ctx.Locale.Tr "repo.migrated_from" .ctxData.Repository.OriginalURL .ctxData.Repository.GetOriginalURLHostname}}) {{end}} {{else}} - {{template "shared/user/authorlink" .comment.Poster}} + {{$specialDoerHtml := .comment.MetaSpecialDoerTr ctx.Locale}} + {{if $specialDoerHtml}} + {{$specialDoerHtml}} + {{else}} + {{template "shared/user/authorlink" .comment.Poster}} + {{end}} {{end}}