Skip to content

Commit 48d71b7

Browse files
authored
Add Feed for Releases and Tags (#21696)
Fixes #19091 Add Feed for Releases and Tags, can be accessed through `reponame/releases.rss`, `reponame/releases.atom`, `reponame/tags.rss`, and `reponame/tags.atom` Signed-off-by: Reo <[email protected]>
1 parent 9914b21 commit 48d71b7

File tree

6 files changed

+135
-2
lines changed

6 files changed

+135
-2
lines changed

options/locale/locale_en-US.ini

+2
Original file line numberDiff line numberDiff line change
@@ -2279,6 +2279,8 @@ release.downloads = Downloads
22792279
release.download_count = Downloads: %s
22802280
release.add_tag_msg = Use the title and content of release as tag message.
22812281
release.add_tag = Create Tag Only
2282+
release.releases_for = Releases for %s
2283+
release.tags_for = Tags for %s
22822284

22832285
branch.name = Branch Name
22842286
branch.search = Search branches

routers/web/feed/convert.go

+44
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"strings"
1313

1414
activities_model "code.gitea.io/gitea/models/activities"
15+
repo_model "code.gitea.io/gitea/models/repo"
1516
"code.gitea.io/gitea/modules/context"
1617
"code.gitea.io/gitea/modules/markup"
1718
"code.gitea.io/gitea/modules/markup/markdown"
@@ -268,3 +269,46 @@ func GetFeedType(name string, req *http.Request) (bool, string, string) {
268269

269270
return false, name, ""
270271
}
272+
273+
// feedActionsToFeedItems convert gitea's Repo's Releases to feeds Item
274+
func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release, isReleasesOnly bool) (items []*feeds.Item, err error) {
275+
for _, rel := range releases {
276+
err := rel.LoadAttributes(ctx)
277+
if err != nil {
278+
return nil, err
279+
}
280+
281+
var title, content string
282+
283+
if rel.IsTag {
284+
title = rel.TagName
285+
} else {
286+
title = rel.Title
287+
}
288+
289+
link := &feeds.Link{Href: rel.HTMLURL()}
290+
content, err = markdown.RenderString(&markup.RenderContext{
291+
Ctx: ctx,
292+
URLPrefix: rel.Repo.Link(),
293+
Metas: rel.Repo.ComposeMetas(),
294+
}, rel.Note)
295+
296+
if err != nil {
297+
return nil, err
298+
}
299+
300+
items = append(items, &feeds.Item{
301+
Title: title,
302+
Link: link,
303+
Created: rel.CreatedUnix.AsTime(),
304+
Author: &feeds.Author{
305+
Name: rel.Publisher.DisplayName(),
306+
Email: rel.Publisher.GetEmail(),
307+
},
308+
Id: fmt.Sprintf("%v: %v", strconv.FormatInt(rel.ID, 10), link.Href),
309+
Content: content,
310+
})
311+
}
312+
313+
return items, err
314+
}

routers/web/feed/release.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package feed
5+
6+
import (
7+
"time"
8+
9+
repo_model "code.gitea.io/gitea/models/repo"
10+
"code.gitea.io/gitea/modules/context"
11+
12+
"github.com/gorilla/feeds"
13+
)
14+
15+
// shows tags and/or releases on the repo as RSS / Atom feed
16+
func ShowReleaseFeed(ctx *context.Context, repo *repo_model.Repository, isReleasesOnly bool, formatType string) {
17+
releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{
18+
IncludeTags: !isReleasesOnly,
19+
})
20+
if err != nil {
21+
ctx.ServerError("GetReleasesByRepoID", err)
22+
return
23+
}
24+
25+
var title string
26+
var link *feeds.Link
27+
28+
if isReleasesOnly {
29+
title = ctx.Tr("repo.release.releases_for", repo.FullName())
30+
link = &feeds.Link{Href: repo.HTMLURL() + "/release"}
31+
} else {
32+
title = ctx.Tr("repo.release.tags_for", repo.FullName())
33+
link = &feeds.Link{Href: repo.HTMLURL() + "/tags"}
34+
}
35+
36+
feed := &feeds.Feed{
37+
Title: title,
38+
Link: link,
39+
Description: repo.Description,
40+
Created: time.Now(),
41+
}
42+
43+
feed.Items, err = releasesToFeedItems(ctx, releases, isReleasesOnly)
44+
if err != nil {
45+
ctx.ServerError("releasesToFeedItems", err)
46+
return
47+
}
48+
49+
writeFeed(ctx, feed, formatType)
50+
}

routers/web/repo/release.go

+25
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"code.gitea.io/gitea/modules/upload"
2424
"code.gitea.io/gitea/modules/util"
2525
"code.gitea.io/gitea/modules/web"
26+
"code.gitea.io/gitea/routers/web/feed"
2627
"code.gitea.io/gitea/services/forms"
2728
releaseservice "code.gitea.io/gitea/services/release"
2829
)
@@ -199,6 +200,30 @@ func releasesOrTags(ctx *context.Context, isTagList bool) {
199200
ctx.HTML(http.StatusOK, tplReleases)
200201
}
201202

203+
// ReleasesFeedRSS get feeds for releases in RSS format
204+
func ReleasesFeedRSS(ctx *context.Context) {
205+
releasesOrTagsFeed(ctx, true, "rss")
206+
}
207+
208+
// TagsListFeedRSS get feeds for tags in RSS format
209+
func TagsListFeedRSS(ctx *context.Context) {
210+
releasesOrTagsFeed(ctx, false, "rss")
211+
}
212+
213+
// ReleasesFeedAtom get feeds for releases in Atom format
214+
func ReleasesFeedAtom(ctx *context.Context) {
215+
releasesOrTagsFeed(ctx, true, "atom")
216+
}
217+
218+
// TagsListFeedAtom get feeds for tags in RSS format
219+
func TagsListFeedAtom(ctx *context.Context) {
220+
releasesOrTagsFeed(ctx, false, "atom")
221+
}
222+
223+
func releasesOrTagsFeed(ctx *context.Context, isReleasesOnly bool, formatType string) {
224+
feed.ShowReleaseFeed(ctx, ctx.Repo.Repository, isReleasesOnly, formatType)
225+
}
226+
202227
// SingleRelease renders a single release's page
203228
func SingleRelease(ctx *context.Context) {
204229
ctx.Data["Title"] = ctx.Tr("repo.release.releases")

routers/web/web.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -1087,12 +1087,21 @@ func RegisterRoutes(m *web.Route) {
10871087

10881088
// Releases
10891089
m.Group("/{username}/{reponame}", func() {
1090-
m.Get("/tags", repo.TagsList, repo.MustBeNotEmpty,
1091-
reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag))
1090+
m.Group("/tags", func() {
1091+
m.Get("", repo.TagsList)
1092+
m.Get(".rss", feedEnabled, repo.TagsListFeedRSS)
1093+
m.Get(".atom", feedEnabled, repo.TagsListFeedAtom)
1094+
}, func(ctx *context.Context) {
1095+
ctx.Data["EnableFeed"] = setting.EnableFeed
1096+
}, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true))
10921097
m.Group("/releases", func() {
10931098
m.Get("/", repo.Releases)
10941099
m.Get("/tag/*", repo.SingleRelease)
10951100
m.Get("/latest", repo.LatestRelease)
1101+
m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS)
1102+
m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom)
1103+
}, func(ctx *context.Context) {
1104+
ctx.Data["EnableFeed"] = setting.EnableFeed
10961105
}, repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag, true))
10971106
m.Get("/releases/attachments/{uuid}", repo.GetAttachment, repo.MustBeNotEmpty, reqRepoReleaseReader)
10981107
m.Group("/releases", func() {

templates/repo/release/list.tmpl

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
<a class="{{if .PageIsTagList}}active {{end}}item" href="{{.RepoLink}}/tags">{{.locale.Tr "repo.release.tags"}}</a>
1212
{{end}}
1313
</h2>
14+
{{if .EnableFeed}}
15+
<a href="{{.RepoLink}}/{{if .PageIsTagList}}tags{{else}}releases{{end}}.rss"><i class="ui grey icon tooltip ml-3" data-content="{{.locale.Tr "rss_feed"}}" data-position="top center">{{svg "octicon-rss" 18}}</i></a>
16+
{{end}}
1417
{{if (and .CanCreateRelease (not .PageIsTagList))}}
1518
<a class="ui right small green button" href="{{$.RepoLink}}/releases/new">
1619
{{.locale.Tr "repo.release.new_release"}}

0 commit comments

Comments
 (0)