mirror of https://github.com/gogs/gogs.git
hook: fix email not sent after push (#4430)
Turns out mail service was not initialized at all, also mail must be sent in sync in hook mode before program exits.pull/4649/merge
parent
643c85e9c8
commit
6bc11c4450
10
cmd/hook.go
10
cmd/hook.go
|
@ -11,6 +11,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -22,7 +23,9 @@ import (
|
||||||
|
|
||||||
"github.com/gogits/gogs/models"
|
"github.com/gogits/gogs/models"
|
||||||
"github.com/gogits/gogs/pkg/httplib"
|
"github.com/gogits/gogs/pkg/httplib"
|
||||||
|
"github.com/gogits/gogs/pkg/mailer"
|
||||||
"github.com/gogits/gogs/pkg/setting"
|
"github.com/gogits/gogs/pkg/setting"
|
||||||
|
"github.com/gogits/gogs/pkg/template"
|
||||||
http "github.com/gogits/gogs/routes/repo"
|
http "github.com/gogits/gogs/routes/repo"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -184,6 +187,13 @@ func runHookPostReceive(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
setup(c, "hooks/post-receive.log", true)
|
setup(c, "hooks/post-receive.log", true)
|
||||||
|
|
||||||
|
// Post-receive hook does more than just gather Git information,
|
||||||
|
// so we need to setup additional services for email notifications.
|
||||||
|
setting.NewPostReceiveHookServices()
|
||||||
|
mailer.NewContext()
|
||||||
|
mailer.InitMailRender(path.Join(setting.StaticRootPath, "templates/mail"),
|
||||||
|
path.Join(setting.CustomPath, "templates/mail"), template.NewFuncMap())
|
||||||
|
|
||||||
isWiki := strings.Contains(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/")
|
isWiki := strings.Contains(os.Getenv(http.ENV_REPO_CUSTOM_HOOKS_PATH), ".wiki.git/")
|
||||||
|
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
|
|
2
gogs.go
2
gogs.go
|
@ -16,7 +16,7 @@ import (
|
||||||
"github.com/gogits/gogs/pkg/setting"
|
"github.com/gogits/gogs/pkg/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
const APP_VER = "0.11.28.0718"
|
const APP_VER = "0.11.29.0727"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
setting.AppVer = APP_VER
|
setting.AppVer = APP_VER
|
||||||
|
|
|
@ -379,8 +379,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
|
||||||
if ref[0] == '#' {
|
if ref[0] == '#' {
|
||||||
ref = fmt.Sprintf("%s%s", repo.FullName(), ref)
|
ref = fmt.Sprintf("%s%s", repo.FullName(), ref)
|
||||||
} else if !strings.Contains(ref, "/") {
|
} else if !strings.Contains(ref, "/") {
|
||||||
// We don't support User#ID syntax yet
|
// FIXME: We don't support User#ID syntax yet
|
||||||
// return ErrNotImplemented
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ func (cmt *Comment) mailParticipants(e Engine, opType ActionType, issue *Issue)
|
||||||
issue.Content = fmt.Sprintf("Reopened #%d", issue.Index)
|
issue.Content = fmt.Sprintf("Reopened #%d", issue.Index)
|
||||||
}
|
}
|
||||||
if err = mailIssueCommentToParticipants(issue, cmt.Poster, mentions); err != nil {
|
if err = mailIssueCommentToParticipants(issue, cmt.Poster, mentions); err != nil {
|
||||||
log.Error(4, "mailIssueCommentToParticipants: %v", err)
|
log.Error(2, "mailIssueCommentToParticipants: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -290,10 +290,10 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
|
||||||
// Notify watchers for whatever action comes in, ignore if no action type.
|
// Notify watchers for whatever action comes in, ignore if no action type.
|
||||||
if act.OpType > 0 {
|
if act.OpType > 0 {
|
||||||
if err = notifyWatchers(e, act); err != nil {
|
if err = notifyWatchers(e, act); err != nil {
|
||||||
log.Error(4, "notifyWatchers: %v", err)
|
log.Error(2, "notifyWatchers: %v", err)
|
||||||
}
|
}
|
||||||
if err = comment.mailParticipants(e, act.OpType, opts.Issue); err != nil {
|
if err = comment.mailParticipants(e, act.OpType, opts.Issue); err != nil {
|
||||||
log.Error(4, "MailParticipants: %v", err)
|
log.Error(2, "MailParticipants: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,6 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string)
|
||||||
tos = append(tos, mentions[i])
|
tos = append(tos, mentions[i])
|
||||||
}
|
}
|
||||||
mailer.SendIssueMentionMail(NewMailerIssue(issue), NewMailerRepo(issue.Repo), NewMailerUser(doer), GetUserEmailsByNames(tos))
|
mailer.SendIssueMentionMail(NewMailerIssue(issue), NewMailerRepo(issue.Repo), NewMailerUser(doer), GetUserEmailsByNames(tos))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +167,7 @@ func (issue *Issue) MailParticipants() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = mailIssueCommentToParticipants(issue, issue.Poster, mentions); err != nil {
|
if err = mailIssueCommentToParticipants(issue, issue.Poster, mentions); err != nil {
|
||||||
log.Error(4, "mailIssueCommentToParticipants: %v", err)
|
log.Error(2, "mailIssueCommentToParticipants: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -94,7 +94,7 @@ func SendUserMail(c *macaron.Context, u User, tpl, code, subject, info string) {
|
||||||
msg := NewMessage([]string{u.Email()}, subject, body)
|
msg := NewMessage([]string{u.Email()}, subject, body)
|
||||||
msg.Info = fmt.Sprintf("UID: %d, %s", u.ID(), info)
|
msg.Info = fmt.Sprintf("UID: %d, %s", u.ID(), info)
|
||||||
|
|
||||||
SendAsync(msg)
|
Send(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendActivateAccountMail(c *macaron.Context, u User) {
|
func SendActivateAccountMail(c *macaron.Context, u User) {
|
||||||
|
@ -122,7 +122,7 @@ func SendActivateEmailMail(c *macaron.Context, u User, email string) {
|
||||||
msg := NewMessage([]string{email}, c.Tr("mail.activate_email"), body)
|
msg := NewMessage([]string{email}, c.Tr("mail.activate_email"), body)
|
||||||
msg.Info = fmt.Sprintf("UID: %d, activate email", u.ID())
|
msg.Info = fmt.Sprintf("UID: %d, activate email", u.ID())
|
||||||
|
|
||||||
SendAsync(msg)
|
Send(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendRegisterNotifyMail triggers a notify e-mail by admin created a account.
|
// SendRegisterNotifyMail triggers a notify e-mail by admin created a account.
|
||||||
|
@ -139,7 +139,7 @@ func SendRegisterNotifyMail(c *macaron.Context, u User) {
|
||||||
msg := NewMessage([]string{u.Email()}, c.Tr("mail.register_notify"), body)
|
msg := NewMessage([]string{u.Email()}, c.Tr("mail.register_notify"), body)
|
||||||
msg.Info = fmt.Sprintf("UID: %d, registration notify", u.ID())
|
msg.Info = fmt.Sprintf("UID: %d, registration notify", u.ID())
|
||||||
|
|
||||||
SendAsync(msg)
|
Send(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendCollaboratorMail sends mail notification to new collaborator.
|
// SendCollaboratorMail sends mail notification to new collaborator.
|
||||||
|
@ -160,7 +160,7 @@ func SendCollaboratorMail(u, doer User, repo Repository) {
|
||||||
msg := NewMessage([]string{u.Email()}, subject, body)
|
msg := NewMessage([]string{u.Email()}, subject, body)
|
||||||
msg.Info = fmt.Sprintf("UID: %d, add collaborator", u.ID())
|
msg.Info = fmt.Sprintf("UID: %d, add collaborator", u.ID())
|
||||||
|
|
||||||
SendAsync(msg)
|
Send(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func composeTplData(subject, body, link string) map[string]interface{} {
|
func composeTplData(subject, body, link string) map[string]interface{} {
|
||||||
|
@ -192,7 +192,7 @@ func SendIssueCommentMail(issue Issue, repo Repository, doer User, tos []string)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
SendAsync(composeIssueMessage(issue, repo, doer, MAIL_ISSUE_COMMENT, tos, "issue comment"))
|
Send(composeIssueMessage(issue, repo, doer, MAIL_ISSUE_COMMENT, tos, "issue comment"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendIssueMentionMail composes and sends issue mention emails to target receivers.
|
// SendIssueMentionMail composes and sends issue mention emails to target receivers.
|
||||||
|
@ -200,5 +200,5 @@ func SendIssueMentionMail(issue Issue, repo Repository, doer User, tos []string)
|
||||||
if len(tos) == 0 {
|
if len(tos) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
SendAsync(composeIssueMessage(issue, repo, doer, MAIL_ISSUE_MENTION, tos, "issue mention"))
|
Send(composeIssueMessage(issue, repo, doer, MAIL_ISSUE_MENTION, tos, "issue mention"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
type Message struct {
|
type Message struct {
|
||||||
Info string // Message information for log purpose.
|
Info string // Message information for log purpose.
|
||||||
*gomail.Message
|
*gomail.Message
|
||||||
|
confirmChan chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMessageFrom creates new mail message object with custom From header.
|
// NewMessageFrom creates new mail message object with custom From header.
|
||||||
|
@ -48,9 +49,9 @@ func NewMessageFrom(to []string, from, subject, htmlBody string) *Message {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msg.SetBody(contentType, body)
|
msg.SetBody(contentType, body)
|
||||||
|
|
||||||
return &Message{
|
return &Message{
|
||||||
Message: msg,
|
Message: msg,
|
||||||
|
confirmChan: make(chan struct{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,12 +205,14 @@ func processMailQueue() {
|
||||||
} else {
|
} else {
|
||||||
log.Trace("E-mails sent %s: %s", msg.GetHeader("To"), msg.Info)
|
log.Trace("E-mails sent %s: %s", msg.GetHeader("To"), msg.Info)
|
||||||
}
|
}
|
||||||
|
msg.confirmChan <- struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var mailQueue chan *Message
|
var mailQueue chan *Message
|
||||||
|
|
||||||
|
// NewContext initializes settings for mailer.
|
||||||
func NewContext() {
|
func NewContext() {
|
||||||
// Need to check if mailQueue is nil because in during reinstall (user had installed
|
// Need to check if mailQueue is nil because in during reinstall (user had installed
|
||||||
// before but swithed install lock off), this function will be called again
|
// before but swithed install lock off), this function will be called again
|
||||||
|
@ -222,8 +225,18 @@ func NewContext() {
|
||||||
go processMailQueue()
|
go processMailQueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendAsync(msg *Message) {
|
// Send puts new message object into mail queue.
|
||||||
|
// It returns without confirmation (mail processed asynchronously) in normal cases,
|
||||||
|
// but waits/blocks under hook mode to make sure mail has been sent.
|
||||||
|
func Send(msg *Message) {
|
||||||
|
mailQueue <- msg
|
||||||
|
|
||||||
|
if setting.HookMode {
|
||||||
|
<-msg.confirmChan
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
mailQueue <- msg
|
<-msg.confirmChan
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
|
@ -832,9 +832,10 @@ var (
|
||||||
MailService *Mailer
|
MailService *Mailer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// newMailService initializes mail service options from configuration.
|
||||||
|
// No non-error log will be printed in hook mode.
|
||||||
func newMailService() {
|
func newMailService() {
|
||||||
sec := Cfg.Section("mailer")
|
sec := Cfg.Section("mailer")
|
||||||
// Check mailer setting.
|
|
||||||
if !sec.Key("ENABLED").MustBool() {
|
if !sec.Key("ENABLED").MustBool() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -863,6 +864,9 @@ func newMailService() {
|
||||||
MailService.FromEmail = parsed.Address
|
MailService.FromEmail = parsed.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if HookMode {
|
||||||
|
return
|
||||||
|
}
|
||||||
log.Info("Mail Service Enabled")
|
log.Info("Mail Service Enabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,6 +881,8 @@ func newRegisterMailService() {
|
||||||
log.Info("Register Mail Service Enabled")
|
log.Info("Register Mail Service Enabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newNotifyMailService initializes notification email service options from configuration.
|
||||||
|
// No non-error log will be printed in hook mode.
|
||||||
func newNotifyMailService() {
|
func newNotifyMailService() {
|
||||||
if !Cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").MustBool() {
|
if !Cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").MustBool() {
|
||||||
return
|
return
|
||||||
|
@ -885,6 +891,10 @@ func newNotifyMailService() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Service.EnableNotifyMail = true
|
Service.EnableNotifyMail = true
|
||||||
|
|
||||||
|
if HookMode {
|
||||||
|
return
|
||||||
|
}
|
||||||
log.Info("Notify Mail Service Enabled")
|
log.Info("Notify Mail Service Enabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -901,3 +911,15 @@ func NewServices() {
|
||||||
newRegisterMailService()
|
newRegisterMailService()
|
||||||
newNotifyMailService()
|
newNotifyMailService()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HookMode indicates whether program starts as Git server-side hook callback.
|
||||||
|
var HookMode bool
|
||||||
|
|
||||||
|
// NewPostReceiveHookServices initializes all services that are needed by
|
||||||
|
// Git server-side post-receive hook callback.
|
||||||
|
func NewPostReceiveHookServices() {
|
||||||
|
HookMode = true
|
||||||
|
newService()
|
||||||
|
newMailService()
|
||||||
|
newNotifyMailService()
|
||||||
|
}
|
||||||
|
|
|
@ -22,11 +22,12 @@ import (
|
||||||
"gopkg.in/editorconfig/editorconfig-core-go.v1"
|
"gopkg.in/editorconfig/editorconfig-core-go.v1"
|
||||||
|
|
||||||
"github.com/gogits/gogs/models"
|
"github.com/gogits/gogs/models"
|
||||||
"github.com/gogits/gogs/pkg/tool"
|
|
||||||
"github.com/gogits/gogs/pkg/markup"
|
"github.com/gogits/gogs/pkg/markup"
|
||||||
"github.com/gogits/gogs/pkg/setting"
|
"github.com/gogits/gogs/pkg/setting"
|
||||||
|
"github.com/gogits/gogs/pkg/tool"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: only initialize map once and save to a local variable to reduce copies.
|
||||||
func NewFuncMap() []template.FuncMap {
|
func NewFuncMap() []template.FuncMap {
|
||||||
return []template.FuncMap{map[string]interface{}{
|
return []template.FuncMap{map[string]interface{}{
|
||||||
"GoVer": func() string {
|
"GoVer": func() string {
|
||||||
|
@ -91,13 +92,13 @@ func NewFuncMap() []template.FuncMap {
|
||||||
}
|
}
|
||||||
return str[start:end]
|
return str[start:end]
|
||||||
},
|
},
|
||||||
"Join": strings.Join,
|
"Join": strings.Join,
|
||||||
"EllipsisString": tool.EllipsisString,
|
"EllipsisString": tool.EllipsisString,
|
||||||
"DiffTypeToStr": DiffTypeToStr,
|
"DiffTypeToStr": DiffTypeToStr,
|
||||||
"DiffLineTypeToStr": DiffLineTypeToStr,
|
"DiffLineTypeToStr": DiffLineTypeToStr,
|
||||||
"Sha1": Sha1,
|
"Sha1": Sha1,
|
||||||
"ShortSHA1": tool.ShortSHA1,
|
"ShortSHA1": tool.ShortSHA1,
|
||||||
"MD5": tool.MD5,
|
"MD5": tool.MD5,
|
||||||
"ActionContent2Commits": ActionContent2Commits,
|
"ActionContent2Commits": ActionContent2Commits,
|
||||||
"EscapePound": EscapePound,
|
"EscapePound": EscapePound,
|
||||||
"RenderCommitMessage": RenderCommitMessage,
|
"RenderCommitMessage": RenderCommitMessage,
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.11.28.0718
|
0.11.29.0727
|
Loading…
Reference in New Issue