mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-11-25 11:16:11 +01:00
Compare commits
9 commits
05cba6def2
...
a4dd96a4c8
Author | SHA1 | Date | |
---|---|---|---|
a4dd96a4c8 | |||
3c3c9b22a9 | |||
73cb6c9204 | |||
25354c03a5 | |||
18cecf124f | |||
bed0036d16 | |||
4d3560b937 | |||
2f1b1d8b80 | |||
c226b4d00a |
|
@ -1,3 +1,5 @@
|
||||||
|
name: issue-labels
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types:
|
types:
|
||||||
|
@ -7,22 +9,31 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-notes:
|
release-notes:
|
||||||
if: ( vars.ROLE == 'forgejo-coding' ) && contains(github.event.pull_request.labels.*.name, 'worth a release-note')
|
if: >
|
||||||
|
vars.ROLE == 'forgejo-coding' &&
|
||||||
|
|
||||||
|
secrets.RELEASE_NOTES_ASSISTANT_TOKEN != '' &&
|
||||||
|
|
||||||
|
github.event_name == 'pull_request_target' &&
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'worth a release-note') &&
|
||||||
|
(
|
||||||
|
github.event.action == 'label_updated' ||
|
||||||
|
github.event.action == 'edited' ||
|
||||||
|
github.event.action == 'synchronized'
|
||||||
|
)
|
||||||
|
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
- name: Debug info
|
||||||
|
|
||||||
- name: event
|
|
||||||
run: |
|
run: |
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
${{ toJSON(github.event.pull_request.labels.*.name) }}
|
${{ toJSON(github) }}
|
||||||
EOF
|
|
||||||
cat <<'EOF'
|
|
||||||
${{ toJSON(github.event) }}
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
|
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v5
|
- uses: https://code.forgejo.org/actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version-file: "go.mod"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/xx AS xx
|
||||||
|
|
||||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.20 as build-env
|
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.20 as build-env
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/xx AS xx
|
||||||
|
|
||||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.20 as build-env
|
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.20 as build-env
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
@ -202,6 +203,9 @@ func (d discordConvertor) Push(p *api.PushPayload) (DiscordPayload, error) {
|
||||||
// limit the commit message display to just the summary, otherwise it would be hard to read
|
// limit the commit message display to just the summary, otherwise it would be hard to read
|
||||||
message := strings.TrimRight(strings.SplitN(commit.Message, "\n", 1)[0], "\r")
|
message := strings.TrimRight(strings.SplitN(commit.Message, "\n", 1)[0], "\r")
|
||||||
|
|
||||||
|
// Escaping markdown character
|
||||||
|
message = escapeMarkdown(message)
|
||||||
|
|
||||||
// a limit of 50 is set because GitHub does the same
|
// a limit of 50 is set because GitHub does the same
|
||||||
if utf8.RuneCountInString(message) > 50 {
|
if utf8.RuneCountInString(message) > 50 {
|
||||||
message = fmt.Sprintf("%.47s...", message)
|
message = fmt.Sprintf("%.47s...", message)
|
||||||
|
@ -365,3 +369,40 @@ func (d discordConvertor) createPayload(s *api.User, title, text, url string, co
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var orderedListPattern = regexp.MustCompile(`(\d+)\.`)
|
||||||
|
|
||||||
|
var markdownPatterns = map[string]*regexp.Regexp{
|
||||||
|
"~": regexp.MustCompile(`\~(.*?)\~`),
|
||||||
|
"*": regexp.MustCompile(`\*(.*?)\*`),
|
||||||
|
"_": regexp.MustCompile(`\_(.*?)\_`),
|
||||||
|
}
|
||||||
|
|
||||||
|
var markdownToEscape = strings.NewReplacer(
|
||||||
|
"* ", "\\* ",
|
||||||
|
"`", "\\`",
|
||||||
|
"[", "\\[",
|
||||||
|
"]", "\\]",
|
||||||
|
"(", "\\(",
|
||||||
|
")", "\\)",
|
||||||
|
"#", "\\#",
|
||||||
|
"+ ", "\\+ ",
|
||||||
|
"- ", "\\- ",
|
||||||
|
"---", "\\---",
|
||||||
|
"!", "\\!",
|
||||||
|
"|", "\\|",
|
||||||
|
"<", "\\<",
|
||||||
|
">", "\\>",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Escape Markdown characters
|
||||||
|
func escapeMarkdown(input string) string {
|
||||||
|
// Escaping ordered list
|
||||||
|
output := orderedListPattern.ReplaceAllString(input, "$1\\.")
|
||||||
|
|
||||||
|
for char, pattern := range markdownPatterns {
|
||||||
|
output = pattern.ReplaceAllString(output, fmt.Sprintf(`\%s$1\%s`, char, char))
|
||||||
|
}
|
||||||
|
|
||||||
|
return markdownToEscape.Replace(output)
|
||||||
|
}
|
||||||
|
|
|
@ -94,6 +94,20 @@ func TestDiscordPayload(t *testing.T) {
|
||||||
assert.Equal(t, p.Sender.AvatarURL, pl.Embeds[0].Author.IconURL)
|
assert.Equal(t, p.Sender.AvatarURL, pl.Embeds[0].Author.IconURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("PushWithMarkdownCharactersInCommitMessage", func(t *testing.T) {
|
||||||
|
p := pushTestEscapeCommitMessagePayload()
|
||||||
|
|
||||||
|
pl, err := dc.Push(p)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Len(t, pl.Embeds, 1)
|
||||||
|
assert.Equal(t, "[test/repo:test] 2 new commits", pl.Embeds[0].Title)
|
||||||
|
assert.Equal(t, "[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778) \\# conflicts\n\\# \\- some/conflicting/file.txt - user1\n[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778) \\# conflicts\n\\# \\- some/conflicting/file.txt - user1", pl.Embeds[0].Description)
|
||||||
|
assert.Equal(t, p.Sender.UserName, pl.Embeds[0].Author.Name)
|
||||||
|
assert.Equal(t, setting.AppURL+p.Sender.UserName, pl.Embeds[0].Author.URL)
|
||||||
|
assert.Equal(t, p.Sender.AvatarURL, pl.Embeds[0].Author.IconURL)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("Issue", func(t *testing.T) {
|
t.Run("Issue", func(t *testing.T) {
|
||||||
p := issueTestPayload()
|
p := issueTestPayload()
|
||||||
|
|
||||||
|
@ -346,3 +360,89 @@ func TestDiscordJSONPayload(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778) commit message - user1\n[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778) commit message - user1", body.Embeds[0].Description)
|
assert.Equal(t, "[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778) commit message - user1\n[2020558](http://localhost:3000/test/repo/commit/2020558fe2e34debb818a514715839cabd25e778) commit message - user1", body.Embeds[0].Description)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var escapedMarkdownTests = map[string]struct {
|
||||||
|
input string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
"Escape heading level 1": {
|
||||||
|
input: "# Heading level 1",
|
||||||
|
expected: "\\# Heading level 1",
|
||||||
|
},
|
||||||
|
"Escape heading level 2": {
|
||||||
|
input: "## Heading level 2",
|
||||||
|
expected: "\\#\\# Heading level 2",
|
||||||
|
},
|
||||||
|
"Escape heading level 3": {
|
||||||
|
input: "### Heading level 3",
|
||||||
|
expected: "\\#\\#\\# Heading level 3",
|
||||||
|
},
|
||||||
|
"Escape bold text": {
|
||||||
|
input: "**bold text**",
|
||||||
|
expected: "\\*\\*bold text\\*\\*",
|
||||||
|
},
|
||||||
|
"Escape italic text": {
|
||||||
|
input: "*italic text*",
|
||||||
|
expected: "\\*italic text\\*",
|
||||||
|
},
|
||||||
|
"Escape italic text underline": {
|
||||||
|
input: "_italic text_",
|
||||||
|
expected: "\\_italic text\\_",
|
||||||
|
},
|
||||||
|
"Escape strikethrough": {
|
||||||
|
input: "~~strikethrough~~",
|
||||||
|
expected: "\\~\\~strikethrough\\~\\~",
|
||||||
|
},
|
||||||
|
"Escape Ordered list item": {
|
||||||
|
input: "1. Ordered list item\n2. Second ordered list item\n999999999999. 999999999999 ordered list item",
|
||||||
|
expected: "1\\. Ordered list item\n2\\. Second ordered list item\n999999999999\\. 999999999999 ordered list item",
|
||||||
|
},
|
||||||
|
"Escape Unordered list item": {
|
||||||
|
input: "- Unordered list\n + using plus",
|
||||||
|
expected: "\\- Unordered list\n \\+ using plus",
|
||||||
|
},
|
||||||
|
"Escape bullet list item": {
|
||||||
|
input: "* Bullet list item",
|
||||||
|
expected: "\\* Bullet list item",
|
||||||
|
},
|
||||||
|
"Escape table": {
|
||||||
|
input: "| Table | Example |\n|-|-|\n| Lorem | Ipsum |",
|
||||||
|
expected: "\\| Table \\| Example \\|\n\\|-\\|-\\|\n\\| Lorem \\| Ipsum \\|",
|
||||||
|
},
|
||||||
|
"Escape link": {
|
||||||
|
input: "[Link to Forgejo](https://forgejo.org/)",
|
||||||
|
expected: "\\[Link to Forgejo\\]\\(https://forgejo.org/\\)",
|
||||||
|
},
|
||||||
|
"Escape Alt text for an image": {
|
||||||
|
input: "![Alt text for an image](https://forgejo.org/_astro/mascot-dark.1omhhgvT_Zm0N2n.webp)",
|
||||||
|
expected: "\\!\\[Alt text for an image\\]\\(https://forgejo.org/\\_astro/mascot-dark.1omhhgvT\\_Zm0N2n.webp\\)",
|
||||||
|
},
|
||||||
|
"Escape URL if it has markdown character": {
|
||||||
|
input: "https://forgejo.org/_astro/mascot-dark.1omhhgvT_Zm0N2n.webp",
|
||||||
|
expected: "https://forgejo.org/\\_astro/mascot-dark.1omhhgvT\\_Zm0N2n.webp",
|
||||||
|
},
|
||||||
|
"Escape blockquote text": {
|
||||||
|
input: "> Blockquote text.",
|
||||||
|
expected: "\\> Blockquote text.",
|
||||||
|
},
|
||||||
|
"Escape inline code": {
|
||||||
|
input: "`Inline code`",
|
||||||
|
expected: "\\`Inline code\\`",
|
||||||
|
},
|
||||||
|
"Escape multiple code": {
|
||||||
|
input: "```\nCode block\nwith multiple lines\n```\n",
|
||||||
|
expected: "\\`\\`\\`\nCode block\nwith multiple lines\n\\`\\`\\`\n",
|
||||||
|
},
|
||||||
|
"Escape horizontal rule": {
|
||||||
|
input: "---",
|
||||||
|
expected: "\\---",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEscapeMarkdownChar(t *testing.T) {
|
||||||
|
for name, test := range escapedMarkdownTests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
assert.Equal(t, test.expected, escapeMarkdown(test.input))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -72,6 +72,10 @@ func pushTestMultilineCommitMessagePayload() *api.PushPayload {
|
||||||
return pushTestPayloadWithCommitMessage("This is a commit summary ⚠️⚠️⚠️⚠️ containing 你好 ⚠️⚠️️\n\nThis is the message body.")
|
return pushTestPayloadWithCommitMessage("This is a commit summary ⚠️⚠️⚠️⚠️ containing 你好 ⚠️⚠️️\n\nThis is the message body.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pushTestEscapeCommitMessagePayload() *api.PushPayload {
|
||||||
|
return pushTestPayloadWithCommitMessage("# conflicts\n# - some/conflicting/file.txt")
|
||||||
|
}
|
||||||
|
|
||||||
func pushTestPayloadWithCommitMessage(message string) *api.PushPayload {
|
func pushTestPayloadWithCommitMessage(message string) *api.PushPayload {
|
||||||
commit := &api.PayloadCommit{
|
commit := &api.PayloadCommit{
|
||||||
ID: "2020558fe2e34debb818a514715839cabd25e778",
|
ID: "2020558fe2e34debb818a514715839cabd25e778",
|
||||||
|
|
Loading…
Reference in a new issue