diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index b17753222a0..7f2c3ca38ad 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -17,6 +17,11 @@ class Projects::TagsController < Projects::ApplicationController tag_names = @tags.map(&:name) @tags_pipelines = @project.pipelines.latest_successful_for_refs(tag_names) @releases = project.releases.where(tag: tag_names) + + respond_to do |format| + format.html + format.atom { render layout: 'xml.atom' } + end end def show diff --git a/app/views/projects/tags/_tag.atom.builder b/app/views/projects/tags/_tag.atom.builder new file mode 100644 index 00000000000..60d4b21b9d1 --- /dev/null +++ b/app/views/projects/tags/_tag.atom.builder @@ -0,0 +1,19 @@ +commit = @repository.commit(tag.dereferenced_target) +release = @releases.find { |r| r.tag == tag.name } +tag_url = project_tag_url(@project, tag.name) + +if commit + xml.entry do + xml.id tag_url + xml.link href: tag_url + xml.title truncate(tag.name, length: 80) + xml.summary strip_gpg_signature(tag.message) + xml.content markdown_field(release, :description), type: 'html' + xml.updated release.updated_at.xmlschema if release + xml.media :thumbnail, width: '40', height: '40', url: image_url(avatar_icon_for_email(commit.author_email)) + xml.author do |author| + xml.name commit.author_name + xml.email commit.author_email + end + end +end diff --git a/app/views/projects/tags/index.atom.builder b/app/views/projects/tags/index.atom.builder new file mode 100644 index 00000000000..b9b58b7beaa --- /dev/null +++ b/app/views/projects/tags/index.atom.builder @@ -0,0 +1,7 @@ +xml.title "#{@project.name} tags" +xml.link href: project_tags_url(@project, @ref, rss_url_options), rel: 'self', type: 'application/atom+xml' +xml.link href: project_tags_url(@project, @ref), rel: 'alternate', type: 'text/html' +xml.id project_tags_url(@project, @ref) +xml.updated @releases.first.updated_at.xmlschema if @releases.any? + +xml << render(partial: 'tag', collection: @tags) if @tags.any? diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index dab95ba09f2..20b4705521c 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -1,6 +1,8 @@ - @no_container = true - @sort ||= sort_value_recently_updated - page_title s_('TagsPage|Tags') += content_for :meta_tags do + = auto_discovery_link_tag(:atom, project_tags_url(@project, rss_url_options), title: "#{@project.name} tags") .flex-list{ class: container_class } .top-area.adjust @@ -25,6 +27,8 @@ - if can?(current_user, :push_code, @project) = link_to new_project_tag_path(@project), class: 'btn btn-create new-tag-btn' do = s_('TagsPage|New tag') + = link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn rss-btn has-tooltip' do + = icon("rss") = render_if_exists 'projects/commits/mirror_status' diff --git a/changelogs/unreleased/fj-2635-enable-rss-for-tags.yml b/changelogs/unreleased/fj-2635-enable-rss-for-tags.yml new file mode 100644 index 00000000000..ee197572385 --- /dev/null +++ b/changelogs/unreleased/fj-2635-enable-rss-for-tags.yml @@ -0,0 +1,5 @@ +--- +title: Added atom feed for tags +merge_request: 21428 +author: +type: added diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 2eb69695406..fad653908ab 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -5411,6 +5411,9 @@ msgstr[1] "" msgid "Tags" msgstr "" +msgid "Tags feed" +msgstr "" + msgid "Tags:" msgstr "" diff --git a/spec/features/projects/tags/user_views_tags_spec.rb b/spec/features/projects/tags/user_views_tags_spec.rb new file mode 100644 index 00000000000..f344b682715 --- /dev/null +++ b/spec/features/projects/tags/user_views_tags_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe 'User views tags', :feature do + context 'rss' do + shared_examples 'has access to the tags RSS feed' do + it do + visit project_tags_path(project, format: :atom) + + expect(page).to have_gitlab_http_status(200) + end + end + + shared_examples 'does not have access to the tags RSS feed' do + it do + visit project_tags_path(project, format: :atom) + + expect(page).to have_gitlab_http_status(401) + end + end + + context 'when project public' do + let(:project) { create(:project, :repository, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } + + context 'when user signed in' do + let(:user) { create(:user) } + + before do + project.add_developer(user) + sign_in(user) + visit project_tags_path(project) + end + + it_behaves_like "it has an RSS button with current_user's feed token" + it_behaves_like "an autodiscoverable RSS feed with current_user's feed token" + it_behaves_like 'has access to the tags RSS feed' + end + + context 'when user signed out' do + before do + visit project_tags_path(project) + end + + it_behaves_like 'it has an RSS button without a feed token' + it_behaves_like 'an autodiscoverable RSS feed without a feed token' + it_behaves_like 'has access to the tags RSS feed' + end + end + + context 'when project is not public' do + let(:project) { create(:project, :repository, visibility_level: Gitlab::VisibilityLevel::PRIVATE) } + + context 'when user signed in' do + let(:user) { create(:user) } + + before do + project.add_developer(user) + sign_in(user) + end + + it_behaves_like 'has access to the tags RSS feed' + end + + context 'when user signed out' do + it_behaves_like 'does not have access to the tags RSS feed' + end + end + end +end