mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-11 14:39:28 +02:00
feat(telegram): ability to choose msg format, mdv2escape (#4036)
this allows to choose parse mode between `HTML` and `Markdownv2`, and adds a new template function, `mdv2escape`, to escape the characters according to telegram docs: https://core.telegram.org/bots/api#formatting-options closes #4021
This commit is contained in:
parent
3bb9a9a5b3
commit
e0dabc1cb9
@ -11,7 +11,11 @@ import (
|
||||
"github.com/goreleaser/goreleaser/pkg/context"
|
||||
)
|
||||
|
||||
const defaultMessageTemplate = `{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}`
|
||||
const (
|
||||
defaultMessageTemplate = `{{ .ProjectName }} {{ mdv2escape .Tag }} is out! Check it out at {{ mdv2escape .ReleaseURL }}`
|
||||
parseModeHTML = "HTML"
|
||||
parseModeMarkdown = "MarkdownV2"
|
||||
)
|
||||
|
||||
type Pipe struct{}
|
||||
|
||||
@ -26,23 +30,19 @@ func (Pipe) Default(ctx *context.Context) error {
|
||||
if ctx.Config.Announce.Telegram.MessageTemplate == "" {
|
||||
ctx.Config.Announce.Telegram.MessageTemplate = defaultMessageTemplate
|
||||
}
|
||||
switch ctx.Config.Announce.Telegram.ParseMode {
|
||||
case parseModeHTML, parseModeMarkdown:
|
||||
break
|
||||
default:
|
||||
ctx.Config.Announce.Telegram.ParseMode = parseModeMarkdown
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (Pipe) Announce(ctx *context.Context) error {
|
||||
tpl := tmpl.New(ctx)
|
||||
msg, err := tpl.Apply(ctx.Config.Announce.Telegram.MessageTemplate)
|
||||
msg, chatID, err := getMessageDetails(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("telegram: %w", err)
|
||||
}
|
||||
|
||||
chatIDStr, err := tpl.Apply(ctx.Config.Announce.Telegram.ChatID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("telegram: %w", err)
|
||||
}
|
||||
chatID, err := strconv.ParseInt(chatIDStr, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("telegram: %w", err)
|
||||
return err
|
||||
}
|
||||
|
||||
var cfg Config
|
||||
@ -65,3 +65,20 @@ func (Pipe) Announce(ctx *context.Context) error {
|
||||
log.Debug("message sent")
|
||||
return nil
|
||||
}
|
||||
|
||||
func getMessageDetails(ctx *context.Context) (string, int64, error) {
|
||||
msg, err := tmpl.New(ctx).Apply(ctx.Config.Announce.Telegram.MessageTemplate)
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("telegram: %w", err)
|
||||
}
|
||||
chatIDStr, err := tmpl.New(ctx).Apply(ctx.Config.Announce.Telegram.ChatID)
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("telegram: %w", err)
|
||||
}
|
||||
chatID, err := strconv.ParseInt(chatIDStr, 10, 64)
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("telegram: %w", err)
|
||||
}
|
||||
|
||||
return msg, chatID, nil
|
||||
}
|
||||
|
@ -14,9 +14,24 @@ func TestStringer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
ctx := testctx.New()
|
||||
require.NoError(t, Pipe{}.Default(ctx))
|
||||
require.Equal(t, ctx.Config.Announce.Telegram.MessageTemplate, defaultMessageTemplate)
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
ctx := testctx.New()
|
||||
require.NoError(t, Pipe{}.Default(ctx))
|
||||
require.Equal(t, ctx.Config.Announce.Telegram.MessageTemplate, defaultMessageTemplate)
|
||||
require.Equal(t, ctx.Config.Announce.Telegram.ParseMode, parseModeMarkdown)
|
||||
})
|
||||
t.Run("markdownv2 parsemode", func(t *testing.T) {
|
||||
ctx := testctx.New()
|
||||
ctx.Config.Announce.Telegram.ParseMode = parseModeMarkdown
|
||||
require.NoError(t, Pipe{}.Default(ctx))
|
||||
require.Equal(t, ctx.Config.Announce.Telegram.ParseMode, parseModeMarkdown)
|
||||
})
|
||||
t.Run("html parsemode", func(t *testing.T) {
|
||||
ctx := testctx.New()
|
||||
ctx.Config.Announce.Telegram.ParseMode = parseModeHTML
|
||||
require.NoError(t, Pipe{}.Default(ctx))
|
||||
require.Equal(t, ctx.Config.Announce.Telegram.ParseMode, parseModeHTML)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAnnounceInvalidTemplate(t *testing.T) {
|
||||
@ -84,3 +99,23 @@ func TestSkip(t *testing.T) {
|
||||
require.False(t, Pipe{}.Skip(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetMessageDetails(t *testing.T) {
|
||||
t.Run("default message template", func(t *testing.T) {
|
||||
ctx := testctx.NewWithCfg(
|
||||
config.Project{
|
||||
ProjectName: "foo",
|
||||
Announce: config.Announce{
|
||||
Telegram: config.Telegram{
|
||||
ChatID: "1230212",
|
||||
},
|
||||
},
|
||||
},
|
||||
testctx.WithCurrentTag("v1.0.0"),
|
||||
)
|
||||
require.NoError(t, Pipe{}.Default(ctx))
|
||||
msg, _, err := getMessageDetails(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "foo v1\\.0\\.0 is out! Check it out at ", msg)
|
||||
})
|
||||
}
|
||||
|
@ -232,6 +232,7 @@ func (t *Template) Apply(s string) (string, error) {
|
||||
"incpatch": incPatch,
|
||||
"filter": filter(false),
|
||||
"reverseFilter": filter(true),
|
||||
"mdv2escape": mdv2Escape,
|
||||
}).
|
||||
Parse(s)
|
||||
if err != nil {
|
||||
@ -322,3 +323,26 @@ func filter(reverse bool) func(content, exp string) string {
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
}
|
||||
|
||||
func mdv2Escape(s string) string {
|
||||
return strings.NewReplacer(
|
||||
"_", "\\_",
|
||||
"*", "\\*",
|
||||
"[", "\\[",
|
||||
"]", "\\]",
|
||||
"(", "\\(",
|
||||
")", "\\)",
|
||||
"~", "\\~",
|
||||
"`", "\\`",
|
||||
">", "\\>",
|
||||
"#", "\\#",
|
||||
"+", "\\+",
|
||||
"-", "\\-",
|
||||
"=", "\\=",
|
||||
"|", "\\|",
|
||||
"{", "\\{",
|
||||
"}", "\\}",
|
||||
".", "\\.",
|
||||
"!", "\\!",
|
||||
).Replace(s)
|
||||
}
|
||||
|
@ -410,3 +410,10 @@ func TestBool(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestMdv2Escape(t *testing.T) {
|
||||
require.Equal(
|
||||
t,
|
||||
"aaa\\_\\*\\[\\]\\(\\)\\~\\`\\>\\#\\+\\-\\=\\|\\{\\}\\.\\!",
|
||||
mdv2Escape("aaa_*[]()~`>#+-=|{}.!"))
|
||||
}
|
||||
|
@ -1145,6 +1145,7 @@ type Telegram struct {
|
||||
Enabled bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
|
||||
MessageTemplate string `yaml:"message_template,omitempty" json:"message_template,omitempty"`
|
||||
ChatID string `yaml:"chat_id,omitempty" json:"chat_id,omitempty" jsonschema:"oneof_type=string;integer"`
|
||||
ParseMode string `yaml:"parse_mode,omitempty" json:"parse_mode,omitempty" jsonschema:"enum=MarkdownV2,enum=HTML,default=MarkdownV2"`
|
||||
}
|
||||
|
||||
type OpenCollective struct {
|
||||
|
@ -25,9 +25,17 @@ announce:
|
||||
|
||||
# Message template to use while publishing.
|
||||
#
|
||||
# Default: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
|
||||
# Default: '{{ .ProjectName }} {{ mdv2escape .Tag }} is out! Check it out at {{ mdv2escape .ReleaseURL }}'
|
||||
# Templates: allowed
|
||||
message_template: 'Awesome project {{.Tag}} is out!'
|
||||
|
||||
# Parse mode.
|
||||
#
|
||||
# Valid options are MarkdownV2 and HTML.
|
||||
#
|
||||
# Default: MarkdownV2
|
||||
# Since: v1.19
|
||||
parse_mode: HTML
|
||||
```
|
||||
|
||||
You can format your message using `MarkdownV2`, for reference, see the
|
||||
@ -35,3 +43,5 @@ You can format your message using `MarkdownV2`, for reference, see the
|
||||
|
||||
!!! tip
|
||||
Learn more about the [name template engine](/customization/templates/).
|
||||
In the specific case of `MarkdownV2`, you'll probably need the `mdv2escape`
|
||||
function.
|
||||
|
@ -143,6 +143,7 @@ Usage |Description
|
||||
`filter "text" "regex"` |keeps only the lines matching the given regex, analogous to `grep -E`. Since v1.6.
|
||||
`reverseFilter "text" "regex"`|keeps only the lines **not** matching the given regex, analogous to `grep -vE`. Since v1.6.
|
||||
`title "foo"` |"titlenize" the string using english as language. See [Title](https://pkg.go.dev/golang.org/x/text/cases#Title). Since v1.14.
|
||||
`mdv2escape "foo"` |escape characteres according to MarkdownV2, especially useful in the Telegram integration. Since v1.19.
|
||||
|
||||
With all those fields, you may be able to compose the name of your artifacts
|
||||
pretty much the way you want:
|
||||
|
Loading…
x
Reference in New Issue
Block a user