Template
1
0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo synced 2024-11-25 11:16:11 +01:00

Compare commits

...

9 commits

Author SHA1 Message Date
Marco De Araujo a4dd96a4c8 Merge branch 'forgejo' into escape_markdown_discord 2024-11-18 14:14:13 -04:00
Earl Warren 3c3c9b22a9 Merge pull request 'chore(ci): make release-notes-assistant job copy/pastable (part two)' (#6020) from earl-warren/forgejo:wip-ci-labels into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6020
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2024-11-18 18:10:13 +00:00
Earl Warren 73cb6c9204
chore(ci): make release-notes-assistant job copy/pastable (part two)
The event is pull_request_target

Refs: forgejo/forgejo#5999
2024-11-18 18:11:07 +01:00
Earl Warren 25354c03a5 Merge pull request 'chore(ci): make release-notes-assistant job copy/pastable' (#6019) from earl-warren/forgejo:wip-ci-labels into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6019
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2024-11-18 17:02:59 +00:00
Earl Warren 18cecf124f
chore(ci): make release-notes-assistant job copy/pastable
Refs: forgejo/forgejo#5999
2024-11-18 17:23:33 +01:00
Marco De Araujo bed0036d16 Merge branch 'forgejo' into escape_markdown_discord 2024-11-18 11:37:14 -04:00
Marco De Araujo 4d3560b937 Created Escape function on markdown package
[BUG] #3664

[BUG] Escaping specific markdown in
commit messages on Discord-type embeds #3664

Reformatted into a table driven test

Moved function escapeMarkdown to Discord webhooks;
Moved compile regex to outside function;
Using refactored eplacements for multiple values;
Using assertions from testify.

Fixed formatting

Moved string new replacer to outside function
2024-11-18 11:28:33 -04:00
Earl Warren 2f1b1d8b80 Merge pull request 'feat: use oci mirror for tonistiigi/xx image' (#5965) from viceice/feat/oci-mirror into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5965
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-11-18 14:54:05 +00:00
Michael Kriese c226b4d00a
feat: use oci mirror for tonistiigi/xx image 2024-11-15 00:55:43 +01:00
6 changed files with 166 additions and 10 deletions

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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)
}

View file

@ -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))
})
}
}

View file

@ -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",