Skip to content

Commit a14ef2e

Browse files
zeripathtechknowlogickjolheiserguillep2klafriks
authored and
Yohann Delafollye
committed
Make API EditIssue and EditPullRequest issue notifications (go-gitea#11123)
* Make API EditIssue and EditPullRequest issue notifications Restructure models.UpdateIssueByAPI and EditIssue/EditPullRequest to issue notifications Fix go-gitea#10014 Signed-off-by: Andrew Thornton <[email protected]> * As per @6543 Signed-off-by: Andrew Thornton <[email protected]> * update status! Signed-off-by: Andrew Thornton <[email protected]> Co-authored-by: techknowlogick <[email protected]> Co-authored-by: John Olheiser <[email protected]> Co-authored-by: guillep2k <[email protected]> Co-authored-by: Lauris BH <[email protected]>
1 parent bb5a45c commit a14ef2e

File tree

3 files changed

+87
-37
lines changed

3 files changed

+87
-37
lines changed

models/issue.go

+51-16
Original file line numberDiff line numberDiff line change
@@ -580,8 +580,13 @@ func (issue *Issue) changeStatus(e *xorm.Session, doer *User, isClosed, isMergeP
580580
}
581581
}
582582

583+
issue.IsClosed = isClosed
584+
return issue.doChangeStatus(e, doer, isMergePull)
585+
}
586+
587+
func (issue *Issue) doChangeStatus(e *xorm.Session, doer *User, isMergePull bool) (*Comment, error) {
583588
// Check for open dependencies
584-
if isClosed && issue.Repo.isDependenciesEnabled(e) {
589+
if issue.IsClosed && issue.Repo.isDependenciesEnabled(e) {
585590
// only check if dependencies are enabled and we're about to close an issue, otherwise reopening an issue would fail when there are unsatisfied dependencies
586591
noDeps, err := issueNoDependenciesLeft(e, issue)
587592
if err != nil {
@@ -593,23 +598,22 @@ func (issue *Issue) changeStatus(e *xorm.Session, doer *User, isClosed, isMergeP
593598
}
594599
}
595600

596-
issue.IsClosed = isClosed
597-
if isClosed {
601+
if issue.IsClosed {
598602
issue.ClosedUnix = timeutil.TimeStampNow()
599603
} else {
600604
issue.ClosedUnix = 0
601605
}
602606

603-
if err = updateIssueCols(e, issue, "is_closed", "closed_unix"); err != nil {
607+
if err := updateIssueCols(e, issue, "is_closed", "closed_unix"); err != nil {
604608
return nil, err
605609
}
606610

607611
// Update issue count of labels
608-
if err = issue.getLabels(e); err != nil {
612+
if err := issue.getLabels(e); err != nil {
609613
return nil, err
610614
}
611615
for idx := range issue.Labels {
612-
if err = updateLabelCols(e, issue.Labels[idx], "num_issues", "num_closed_issue"); err != nil {
616+
if err := updateLabelCols(e, issue.Labels[idx], "num_issues", "num_closed_issue"); err != nil {
613617
return nil, err
614618
}
615619
}
@@ -1607,28 +1611,59 @@ func SearchIssueIDsByKeyword(kw string, repoIDs []int64, limit, start int) (int6
16071611
}
16081612

16091613
// UpdateIssueByAPI updates all allowed fields of given issue.
1610-
func UpdateIssueByAPI(issue *Issue) error {
1614+
// If the issue status is changed a statusChangeComment is returned
1615+
// similarly if the title is changed the titleChanged bool is set to true
1616+
func UpdateIssueByAPI(issue *Issue, doer *User) (statusChangeComment *Comment, titleChanged bool, err error) {
16111617
sess := x.NewSession()
16121618
defer sess.Close()
16131619
if err := sess.Begin(); err != nil {
1614-
return err
1620+
return nil, false, err
1621+
}
1622+
1623+
if err := issue.loadRepo(sess); err != nil {
1624+
return nil, false, fmt.Errorf("loadRepo: %v", err)
1625+
}
1626+
1627+
// Reload the issue
1628+
currentIssue, err := getIssueByID(sess, issue.ID)
1629+
if err != nil {
1630+
return nil, false, err
16151631
}
16161632

16171633
if _, err := sess.ID(issue.ID).Cols(
1618-
"name", "is_closed", "content", "milestone_id", "priority",
1619-
"deadline_unix", "updated_unix", "closed_unix", "is_locked").
1634+
"name", "content", "milestone_id", "priority",
1635+
"deadline_unix", "updated_unix", "is_locked").
16201636
Update(issue); err != nil {
1621-
return err
1637+
return nil, false, err
16221638
}
16231639

1624-
if err := issue.loadPoster(sess); err != nil {
1625-
return err
1640+
titleChanged = currentIssue.Title != issue.Title
1641+
if titleChanged {
1642+
var opts = &CreateCommentOptions{
1643+
Type: CommentTypeChangeTitle,
1644+
Doer: doer,
1645+
Repo: issue.Repo,
1646+
Issue: issue,
1647+
OldTitle: currentIssue.Title,
1648+
NewTitle: issue.Title,
1649+
}
1650+
_, err := createComment(sess, opts)
1651+
if err != nil {
1652+
return nil, false, fmt.Errorf("createComment: %v", err)
1653+
}
16261654
}
16271655

1628-
if err := issue.addCrossReferences(sess, issue.Poster, true); err != nil {
1629-
return err
1656+
if currentIssue.IsClosed != issue.IsClosed {
1657+
statusChangeComment, err = issue.doChangeStatus(sess, doer, false)
1658+
if err != nil {
1659+
return nil, false, err
1660+
}
16301661
}
1631-
return sess.Commit()
1662+
1663+
if err := issue.addCrossReferences(sess, doer, true); err != nil {
1664+
return nil, false, err
1665+
}
1666+
return statusChangeComment, titleChanged, sess.Commit()
16321667
}
16331668

16341669
// UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it.

routers/api/v1/repo/issue.go

+18-11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"code.gitea.io/gitea/modules/convert"
1818
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
1919
"code.gitea.io/gitea/modules/log"
20+
"code.gitea.io/gitea/modules/notification"
2021
"code.gitea.io/gitea/modules/setting"
2122
api "code.gitea.io/gitea/modules/structs"
2223
"code.gitea.io/gitea/modules/timeutil"
@@ -544,6 +545,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
544545
return
545546
}
546547

548+
oldTitle := issue.Title
547549
if len(form.Title) > 0 {
548550
issue.Title = form.Title
549551
}
@@ -598,20 +600,25 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
598600
return
599601
}
600602
}
601-
602-
if err = models.UpdateIssueByAPI(issue); err != nil {
603-
ctx.Error(http.StatusInternalServerError, "UpdateIssueByAPI", err)
604-
return
605-
}
606603
if form.State != nil {
607-
if err = issue_service.ChangeStatus(issue, ctx.User, api.StateClosed == api.StateType(*form.State)); err != nil {
608-
if models.IsErrDependenciesLeft(err) {
609-
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies")
610-
return
611-
}
612-
ctx.Error(http.StatusInternalServerError, "ChangeStatus", err)
604+
issue.IsClosed = (api.StateClosed == api.StateType(*form.State))
605+
}
606+
statusChangeComment, titleChanged, err := models.UpdateIssueByAPI(issue, ctx.User)
607+
if err != nil {
608+
if models.IsErrDependenciesLeft(err) {
609+
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies")
613610
return
614611
}
612+
ctx.Error(http.StatusInternalServerError, "UpdateIssueByAPI", err)
613+
return
614+
}
615+
616+
if titleChanged {
617+
notification.NotifyIssueChangeTitle(ctx.User, issue, oldTitle)
618+
}
619+
620+
if statusChangeComment != nil {
621+
notification.NotifyIssueChangeStatus(ctx.User, issue, statusChangeComment, issue.IsClosed)
615622
}
616623

617624
// Refetch from database to assign some automatic values

routers/api/v1/repo/pull.go

+18-10
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"code.gitea.io/gitea/modules/convert"
1717
"code.gitea.io/gitea/modules/git"
1818
"code.gitea.io/gitea/modules/log"
19+
"code.gitea.io/gitea/modules/notification"
1920
api "code.gitea.io/gitea/modules/structs"
2021
"code.gitea.io/gitea/modules/timeutil"
2122
"code.gitea.io/gitea/routers/api/v1/utils"
@@ -409,6 +410,7 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
409410
return
410411
}
411412

413+
oldTitle := issue.Title
412414
if len(form.Title) > 0 {
413415
issue.Title = form.Title
414416
}
@@ -485,19 +487,25 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
485487
}
486488
}
487489

488-
if err = models.UpdateIssueByAPI(issue); err != nil {
489-
ctx.Error(http.StatusInternalServerError, "UpdateIssueByAPI", err)
490-
return
491-
}
492490
if form.State != nil {
493-
if err = issue_service.ChangeStatus(issue, ctx.User, api.StateClosed == api.StateType(*form.State)); err != nil {
494-
if models.IsErrDependenciesLeft(err) {
495-
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies")
496-
return
497-
}
498-
ctx.Error(http.StatusInternalServerError, "ChangeStatus", err)
491+
issue.IsClosed = (api.StateClosed == api.StateType(*form.State))
492+
}
493+
statusChangeComment, titleChanged, err := models.UpdateIssueByAPI(issue, ctx.User)
494+
if err != nil {
495+
if models.IsErrDependenciesLeft(err) {
496+
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies")
499497
return
500498
}
499+
ctx.Error(http.StatusInternalServerError, "UpdateIssueByAPI", err)
500+
return
501+
}
502+
503+
if titleChanged {
504+
notification.NotifyIssueChangeTitle(ctx.User, issue, oldTitle)
505+
}
506+
507+
if statusChangeComment != nil {
508+
notification.NotifyIssueChangeStatus(ctx.User, issue, statusChangeComment, issue.IsClosed)
501509
}
502510

503511
// Refetch from database

0 commit comments

Comments
 (0)