enhance(webhook): show sender avatar on Slack notifications (#39656)

Closes #39655
This commit is contained in:
Aradhya Jain authored and GitHub committed 2026-10-22 10:56:48 +00:00
1 parent d4ecd5eadf
commit bc5e896d35
3 files changed
+68 -21

No files matched your search

+5
View File
@@ -104,10 +104,12 @@ func pushTestPayloadWithCommitMessage(message string) *api.PushPayload {
Pusher: &api.User{
UserName: "user1",
AvatarURL: "http://localhost:3000/user1/avatar",
HTMLURL: "http://localhost:3000/user1",
},
Sender: &api.User{
UserName: "user1",
AvatarURL: "http://localhost:3000/user1/avatar",
HTMLURL: "http://localhost:3000/user1",
},
}
}
@@ -118,6 +120,7 @@ func issueTestPayload() *api.IssuePayload {
Sender: &api.User{
UserName: "user1",
AvatarURL: "http://localhost:3000/user1/avatar",
HTMLURL: "http://localhost:3000/user1",
},
Repository: &api.Repository{
HTMLURL: "http://localhost:3000/test/repo",
@@ -156,6 +159,7 @@ func issueCommentTestPayload() *api.IssueCommentPayload {
Sender: &api.User{
UserName: "user1",
AvatarURL: "http://localhost:3000/user1/avatar",
HTMLURL: "http://localhost:3000/user1",
},
Repository: &api.Repository{
HTMLURL: "http://localhost:3000/test/repo",
@@ -260,6 +264,7 @@ func pullRequestTestPayload() *api.PullRequestPayload {
Sender: &api.User{
UserName: "user1",
AvatarURL: "http://localhost:3000/user1/avatar",
HTMLURL: "http://localhost:3000/user1",
},
Repository: &api.Repository{
HTMLURL: "http://localhost:3000/test/repo",
+47 -21
View File
@@ -47,12 +47,26 @@ type SlackPayload struct {
}
// SlackAttachment contains the slack message
//
// This is Slack's "secondary message attachment" format, documented (as
// legacy, but still functional and with no newer replacement for this exact
// author-row layout) at:
// https://docs.slack.dev/legacy/legacy-messaging/legacy-secondary-message-attachments/
// Gitea has sent every Slack webhook notification through this same struct
// since Slack support was first added, so this predates and is unrelated to
// the author fields below.
type SlackAttachment struct {
Fallback string `json:"fallback"`
Color string `json:"color"`
Title string `json:"title"`
TitleLink string `json:"title_link"`
Text string `json:"text"`
Fallback string `json:"fallback"`
Color string `json:"color"`
// AuthorName, AuthorLink, and AuthorIcon render as a small avatar and a
// linked username in a row above the title (see the package doc above).
// Populated from the event's Sender (or Pusher, for push events).
AuthorName string `json:"author_name,omitempty"`
AuthorLink string `json:"author_link,omitempty"`
AuthorIcon string `json:"author_icon,omitempty"`
Title string `json:"title"`
TitleLink string `json:"title_link"`
Text string `json:"text"`
}
// SlackTextFormatter replaces &, <, > with HTML characters
@@ -124,10 +138,13 @@ func (s slackConvertor) Issue(p *api.IssuePayload) (SlackPayload, error) {
extraMarkdown = SlackTextFormatter(extraMarkdown)
issueTitle = SlackTextFormatter(issueTitle)
attachments = append(attachments, SlackAttachment{
Color: fmt.Sprintf("%x", color),
Title: issueTitle,
TitleLink: p.Issue.HTMLURL,
Text: extraMarkdown,
Color: fmt.Sprintf("%x", color),
AuthorName: p.Sender.UserName,
AuthorLink: p.Sender.HTMLURL,
AuthorIcon: p.Sender.AvatarURL,
Title: issueTitle,
TitleLink: p.Issue.HTMLURL,
Text: extraMarkdown,
})
}
@@ -139,10 +156,13 @@ func (s slackConvertor) IssueComment(p *api.IssueCommentPayload) (SlackPayload,
text, issueTitle, color := getIssueCommentPayloadInfo(p, SlackLinkFormatter, true)
return s.createPayload(text, []SlackAttachment{{
Color: fmt.Sprintf("%x", color),
Title: issueTitle,
TitleLink: p.Comment.HTMLURL,
Text: SlackTextFormatter(p.Comment.Body),
Color: fmt.Sprintf("%x", color),
AuthorName: p.Sender.UserName,
AuthorLink: p.Sender.HTMLURL,
AuthorIcon: p.Sender.AvatarURL,
Title: issueTitle,
TitleLink: p.Comment.HTMLURL,
Text: SlackTextFormatter(p.Comment.Body),
}}), nil
}
@@ -218,10 +238,13 @@ func (s slackConvertor) Push(p *api.PushPayload) (SlackPayload, error) {
}
return s.createPayload(text, []SlackAttachment{{
Color: s.Color,
Title: p.Repo.HTMLURL,
TitleLink: p.Repo.HTMLURL,
Text: attachmentText.String(),
Color: s.Color,
AuthorName: p.Pusher.UserName,
AuthorLink: p.Pusher.HTMLURL,
AuthorIcon: p.Pusher.AvatarURL,
Title: p.Repo.HTMLURL,
TitleLink: p.Repo.HTMLURL,
Text: attachmentText.String(),
}}), nil
}
@@ -234,10 +257,13 @@ func (s slackConvertor) PullRequest(p *api.PullRequestPayload) (SlackPayload, er
extraMarkdown = SlackTextFormatter(p.PullRequest.Body)
issueTitle = SlackTextFormatter(issueTitle)
attachments = append(attachments, SlackAttachment{
Color: fmt.Sprintf("%x", color),
Title: issueTitle,
TitleLink: p.PullRequest.HTMLURL,
Text: extraMarkdown,
Color: fmt.Sprintf("%x", color),
AuthorName: p.Sender.UserName,
AuthorLink: p.Sender.HTMLURL,
AuthorIcon: p.Sender.AvatarURL,
Title: issueTitle,
TitleLink: p.PullRequest.HTMLURL,
Text: extraMarkdown,
})
}
+16
View File
@@ -52,6 +52,10 @@ func TestSlackPayload(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "[<http://localhost:3000/test/repo|test/repo>:<http://localhost:3000/test/repo/src/branch/test|test>] 2 new commits pushed by user1", pl.Text)
require.Len(t, pl.Attachments, 1)
assert.Equal(t, "user1", pl.Attachments[0].AuthorName)
assert.Equal(t, "http://localhost:3000/user1/avatar", pl.Attachments[0].AuthorIcon)
assert.Equal(t, "http://localhost:3000/user1", pl.Attachments[0].AuthorLink)
})
t.Run("Issue", func(t *testing.T) {
@@ -62,6 +66,10 @@ func TestSlackPayload(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "[<http://localhost:3000/test/repo|test/repo>] Issue opened: <http://localhost:3000/test/repo/issues/2|#2 crash> by <https://try.gitea.io/user1|user1>", pl.Text)
require.Len(t, pl.Attachments, 1)
assert.Equal(t, "user1", pl.Attachments[0].AuthorName)
assert.Equal(t, "http://localhost:3000/user1/avatar", pl.Attachments[0].AuthorIcon)
assert.Equal(t, "http://localhost:3000/user1", pl.Attachments[0].AuthorLink)
p.Action = api.HookIssueClosed
pl, err = sc.Issue(p)
@@ -77,6 +85,10 @@ func TestSlackPayload(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "[<http://localhost:3000/test/repo|test/repo>] New comment on issue <http://localhost:3000/test/repo/issues/2|#2 crash> by <https://try.gitea.io/user1|user1>", pl.Text)
require.Len(t, pl.Attachments, 1)
assert.Equal(t, "user1", pl.Attachments[0].AuthorName)
assert.Equal(t, "http://localhost:3000/user1/avatar", pl.Attachments[0].AuthorIcon)
assert.Equal(t, "http://localhost:3000/user1", pl.Attachments[0].AuthorLink)
})
t.Run("PullRequest", func(t *testing.T) {
@@ -86,6 +98,10 @@ func TestSlackPayload(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, "[<http://localhost:3000/test/repo|test/repo>] Pull request opened: <http://localhost:3000/test/repo/pulls/12|#12 Fix bug> by <https://try.gitea.io/user1|user1>", pl.Text)
require.Len(t, pl.Attachments, 1)
assert.Equal(t, "user1", pl.Attachments[0].AuthorName)
assert.Equal(t, "http://localhost:3000/user1/avatar", pl.Attachments[0].AuthorIcon)
assert.Equal(t, "http://localhost:3000/user1", pl.Attachments[0].AuthorLink)
})
t.Run("PullRequestComment", func(t *testing.T) {