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 <reo_999@proton.me>
This commit is contained in:
		
					parent
					
						
							
								9914b21493
							
						
					
				
			
			
				commit
				
					
						48d71b7d6b
					
				
			
		
					 6 changed files with 135 additions and 2 deletions
				
			
		| 
						 | 
					@ -2279,6 +2279,8 @@ release.downloads = Downloads
 | 
				
			||||||
release.download_count = Downloads: %s
 | 
					release.download_count = Downloads: %s
 | 
				
			||||||
release.add_tag_msg = Use the title and content of release as tag message.
 | 
					release.add_tag_msg = Use the title and content of release as tag message.
 | 
				
			||||||
release.add_tag = Create Tag Only
 | 
					release.add_tag = Create Tag Only
 | 
				
			||||||
 | 
					release.releases_for = Releases for %s
 | 
				
			||||||
 | 
					release.tags_for = Tags for %s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
branch.name = Branch Name
 | 
					branch.name = Branch Name
 | 
				
			||||||
branch.search = Search branches
 | 
					branch.search = Search branches
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@ import (
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	activities_model "code.gitea.io/gitea/models/activities"
 | 
						activities_model "code.gitea.io/gitea/models/activities"
 | 
				
			||||||
 | 
						repo_model "code.gitea.io/gitea/models/repo"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/markup"
 | 
						"code.gitea.io/gitea/modules/markup"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/markup/markdown"
 | 
						"code.gitea.io/gitea/modules/markup/markdown"
 | 
				
			||||||
| 
						 | 
					@ -268,3 +269,46 @@ func GetFeedType(name string, req *http.Request) (bool, string, string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return false, name, ""
 | 
						return false, name, ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// feedActionsToFeedItems convert gitea's Repo's Releases to feeds Item
 | 
				
			||||||
 | 
					func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release, isReleasesOnly bool) (items []*feeds.Item, err error) {
 | 
				
			||||||
 | 
						for _, rel := range releases {
 | 
				
			||||||
 | 
							err := rel.LoadAttributes(ctx)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var title, content string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if rel.IsTag {
 | 
				
			||||||
 | 
								title = rel.TagName
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								title = rel.Title
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							link := &feeds.Link{Href: rel.HTMLURL()}
 | 
				
			||||||
 | 
							content, err = markdown.RenderString(&markup.RenderContext{
 | 
				
			||||||
 | 
								Ctx:       ctx,
 | 
				
			||||||
 | 
								URLPrefix: rel.Repo.Link(),
 | 
				
			||||||
 | 
								Metas:     rel.Repo.ComposeMetas(),
 | 
				
			||||||
 | 
							}, rel.Note)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							items = append(items, &feeds.Item{
 | 
				
			||||||
 | 
								Title:   title,
 | 
				
			||||||
 | 
								Link:    link,
 | 
				
			||||||
 | 
								Created: rel.CreatedUnix.AsTime(),
 | 
				
			||||||
 | 
								Author: &feeds.Author{
 | 
				
			||||||
 | 
									Name:  rel.Publisher.DisplayName(),
 | 
				
			||||||
 | 
									Email: rel.Publisher.GetEmail(),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								Id:      fmt.Sprintf("%v: %v", strconv.FormatInt(rel.ID, 10), link.Href),
 | 
				
			||||||
 | 
								Content: content,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return items, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										50
									
								
								routers/web/feed/release.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								routers/web/feed/release.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,50 @@
 | 
				
			||||||
 | 
					// Copyright 2022 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package feed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						repo_model "code.gitea.io/gitea/models/repo"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gorilla/feeds"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// shows tags and/or releases on the repo as RSS / Atom feed
 | 
				
			||||||
 | 
					func ShowReleaseFeed(ctx *context.Context, repo *repo_model.Repository, isReleasesOnly bool, formatType string) {
 | 
				
			||||||
 | 
						releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{
 | 
				
			||||||
 | 
							IncludeTags: !isReleasesOnly,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("GetReleasesByRepoID", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var title string
 | 
				
			||||||
 | 
						var link *feeds.Link
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if isReleasesOnly {
 | 
				
			||||||
 | 
							title = ctx.Tr("repo.release.releases_for", repo.FullName())
 | 
				
			||||||
 | 
							link = &feeds.Link{Href: repo.HTMLURL() + "/release"}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							title = ctx.Tr("repo.release.tags_for", repo.FullName())
 | 
				
			||||||
 | 
							link = &feeds.Link{Href: repo.HTMLURL() + "/tags"}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						feed := &feeds.Feed{
 | 
				
			||||||
 | 
							Title:       title,
 | 
				
			||||||
 | 
							Link:        link,
 | 
				
			||||||
 | 
							Description: repo.Description,
 | 
				
			||||||
 | 
							Created:     time.Now(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						feed.Items, err = releasesToFeedItems(ctx, releases, isReleasesOnly)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("releasesToFeedItems", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						writeFeed(ctx, feed, formatType)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ import (
 | 
				
			||||||
	"code.gitea.io/gitea/modules/upload"
 | 
						"code.gitea.io/gitea/modules/upload"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/util"
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/web"
 | 
						"code.gitea.io/gitea/modules/web"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/routers/web/feed"
 | 
				
			||||||
	"code.gitea.io/gitea/services/forms"
 | 
						"code.gitea.io/gitea/services/forms"
 | 
				
			||||||
	releaseservice "code.gitea.io/gitea/services/release"
 | 
						releaseservice "code.gitea.io/gitea/services/release"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -199,6 +200,30 @@ func releasesOrTags(ctx *context.Context, isTagList bool) {
 | 
				
			||||||
	ctx.HTML(http.StatusOK, tplReleases)
 | 
						ctx.HTML(http.StatusOK, tplReleases)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ReleasesFeedRSS get feeds for releases in RSS format
 | 
				
			||||||
 | 
					func ReleasesFeedRSS(ctx *context.Context) {
 | 
				
			||||||
 | 
						releasesOrTagsFeed(ctx, true, "rss")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TagsListFeedRSS get feeds for tags in RSS format
 | 
				
			||||||
 | 
					func TagsListFeedRSS(ctx *context.Context) {
 | 
				
			||||||
 | 
						releasesOrTagsFeed(ctx, false, "rss")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ReleasesFeedAtom get feeds for releases in Atom format
 | 
				
			||||||
 | 
					func ReleasesFeedAtom(ctx *context.Context) {
 | 
				
			||||||
 | 
						releasesOrTagsFeed(ctx, true, "atom")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TagsListFeedAtom get feeds for tags in RSS format
 | 
				
			||||||
 | 
					func TagsListFeedAtom(ctx *context.Context) {
 | 
				
			||||||
 | 
						releasesOrTagsFeed(ctx, false, "atom")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func releasesOrTagsFeed(ctx *context.Context, isReleasesOnly bool, formatType string) {
 | 
				
			||||||
 | 
						feed.ShowReleaseFeed(ctx, ctx.Repo.Repository, isReleasesOnly, formatType)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SingleRelease renders a single release's page
 | 
					// SingleRelease renders a single release's page
 | 
				
			||||||
func SingleRelease(ctx *context.Context) {
 | 
					func SingleRelease(ctx *context.Context) {
 | 
				
			||||||
	ctx.Data["Title"] = ctx.Tr("repo.release.releases")
 | 
						ctx.Data["Title"] = ctx.Tr("repo.release.releases")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1087,12 +1087,21 @@ func RegisterRoutes(m *web.Route) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Releases
 | 
						// Releases
 | 
				
			||||||
	m.Group("/{username}/{reponame}", func() {
 | 
						m.Group("/{username}/{reponame}", func() {
 | 
				
			||||||
		m.Get("/tags", repo.TagsList, repo.MustBeNotEmpty,
 | 
							m.Group("/tags", func() {
 | 
				
			||||||
			reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag))
 | 
								m.Get("", repo.TagsList)
 | 
				
			||||||
 | 
								m.Get(".rss", feedEnabled, repo.TagsListFeedRSS)
 | 
				
			||||||
 | 
								m.Get(".atom", feedEnabled, repo.TagsListFeedAtom)
 | 
				
			||||||
 | 
							}, func(ctx *context.Context) {
 | 
				
			||||||
 | 
								ctx.Data["EnableFeed"] = setting.EnableFeed
 | 
				
			||||||
 | 
							}, repo.MustBeNotEmpty, reqRepoCodeReader, context.RepoRefByType(context.RepoRefTag, true))
 | 
				
			||||||
		m.Group("/releases", func() {
 | 
							m.Group("/releases", func() {
 | 
				
			||||||
			m.Get("/", repo.Releases)
 | 
								m.Get("/", repo.Releases)
 | 
				
			||||||
			m.Get("/tag/*", repo.SingleRelease)
 | 
								m.Get("/tag/*", repo.SingleRelease)
 | 
				
			||||||
			m.Get("/latest", repo.LatestRelease)
 | 
								m.Get("/latest", repo.LatestRelease)
 | 
				
			||||||
 | 
								m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS)
 | 
				
			||||||
 | 
								m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom)
 | 
				
			||||||
 | 
							}, func(ctx *context.Context) {
 | 
				
			||||||
 | 
								ctx.Data["EnableFeed"] = setting.EnableFeed
 | 
				
			||||||
		}, repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag, true))
 | 
							}, repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag, true))
 | 
				
			||||||
		m.Get("/releases/attachments/{uuid}", repo.GetAttachment, repo.MustBeNotEmpty, reqRepoReleaseReader)
 | 
							m.Get("/releases/attachments/{uuid}", repo.GetAttachment, repo.MustBeNotEmpty, reqRepoReleaseReader)
 | 
				
			||||||
		m.Group("/releases", func() {
 | 
							m.Group("/releases", func() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,9 @@
 | 
				
			||||||
				<a class="{{if .PageIsTagList}}active {{end}}item" href="{{.RepoLink}}/tags">{{.locale.Tr "repo.release.tags"}}</a>
 | 
									<a class="{{if .PageIsTagList}}active {{end}}item" href="{{.RepoLink}}/tags">{{.locale.Tr "repo.release.tags"}}</a>
 | 
				
			||||||
			{{end}}
 | 
								{{end}}
 | 
				
			||||||
		</h2>
 | 
							</h2>
 | 
				
			||||||
 | 
							{{if .EnableFeed}}
 | 
				
			||||||
 | 
								<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>
 | 
				
			||||||
 | 
							{{end}}
 | 
				
			||||||
		{{if (and .CanCreateRelease (not .PageIsTagList))}}
 | 
							{{if (and .CanCreateRelease (not .PageIsTagList))}}
 | 
				
			||||||
			<a class="ui right small green button" href="{{$.RepoLink}}/releases/new">
 | 
								<a class="ui right small green button" href="{{$.RepoLink}}/releases/new">
 | 
				
			||||||
				{{.locale.Tr "repo.release.new_release"}}
 | 
									{{.locale.Tr "repo.release.new_release"}}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue