From cc281afb27365adef2d24c85f83686cc8b829187 Mon Sep 17 00:00:00 2001 From: Brandon Labuschagne Date: Mon, 14 Jan 2019 16:10:19 +0000 Subject: [PATCH] Resolve "Add "What's new" menu item in top navigation" --- app/helpers/release_blog_post_helper.rb | 7 ++ .../layouts/header/_help_dropdown.html.haml | 6 +- ...what-s-new-menu-item-in-top-navigation.yml | 5 + lib/gitlab.rb | 48 +++++++-- lib/gitlab/release_blog_post.rb | 40 ++++++++ lib/gitlab/version_info.rb | 8 ++ locale/gitlab.pot | 3 + spec/features/dashboard/help_spec.rb | 22 +++-- spec/lib/gitlab/release_blog_post_spec.rb | 97 +++++++++++++++++++ spec/lib/gitlab_spec.rb | 77 +++++++++++++++ spec/spec_helper.rb | 5 + 11 files changed, 303 insertions(+), 15 deletions(-) create mode 100644 app/helpers/release_blog_post_helper.rb create mode 100644 changelogs/unreleased/25341-add-what-s-new-menu-item-in-top-navigation.yml create mode 100644 lib/gitlab/release_blog_post.rb create mode 100644 spec/lib/gitlab/release_blog_post_spec.rb diff --git a/app/helpers/release_blog_post_helper.rb b/app/helpers/release_blog_post_helper.rb new file mode 100644 index 00000000000..31b5b7edc39 --- /dev/null +++ b/app/helpers/release_blog_post_helper.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module ReleaseBlogPostHelper + def blog_post_url + Gitlab::ReleaseBlogPost.instance.blog_post_url + end +end diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml index 04409408ce0..513902890af 100644 --- a/app/views/layouts/header/_help_dropdown.html.haml +++ b/app/views/layouts/header/_help_dropdown.html.haml @@ -1,9 +1,13 @@ +- show_blog_link = current_user_menu?(:help) && blog_post_url.present? %ul - if current_user_menu?(:help) %li = link_to _("Help"), help_path %li.divider + - if show_blog_link %li - = link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback" + = link_to _("What's new?"), blog_post_url + %li + = link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback" - if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile) = render 'shared/user_dropdown_contributing_link' diff --git a/changelogs/unreleased/25341-add-what-s-new-menu-item-in-top-navigation.yml b/changelogs/unreleased/25341-add-what-s-new-menu-item-in-top-navigation.yml new file mode 100644 index 00000000000..da1777827cb --- /dev/null +++ b/changelogs/unreleased/25341-add-what-s-new-menu-item-in-top-navigation.yml @@ -0,0 +1,5 @@ +--- +title: Resolve Add What's new menu item in top navigation +merge_request: 23186 +author: +type: added diff --git a/lib/gitlab.rb b/lib/gitlab.rb index 2ef54658a11..074d04fc32a 100644 --- a/lib/gitlab.rb +++ b/lib/gitlab.rb @@ -27,12 +27,52 @@ module Gitlab end end + def self.version_info + Gitlab::VersionInfo.parse(Gitlab::VERSION) + end + COM_URL = 'https://gitlab.com'.freeze APP_DIRS_PATTERN = %r{^/?(app|config|ee|lib|spec|\(\w*\))} SUBDOMAIN_REGEX = %r{\Ahttps://[a-z0-9]+\.gitlab\.com\z} VERSION = File.read(root.join("VERSION")).strip.freeze INSTALLATION_TYPE = File.read(root.join("INSTALLATION_TYPE")).strip.freeze + def self.pre_release? + VERSION.include?('pre') + end + + def self.final_release? + !VERSION.include?('rc') && !pre_release? + end + + def self.minor_release + "#{version_info.major}.#{version_info.minor}" + end + + def self.prev_minor_release + "#{version_info.major}.#{version_info.minor - 1}" + end + + def self.prev_major_release + "#{version_info.major.to_i - 1}" + end + + def self.new_major_release? + version_info.minor.to_i.zero? + end + + def self.previous_release + if version_info.minor_version? + if version_info.patch_version? + minor_release + else + prev_minor_release + end + else + prev_major_release + end + end + def self.com? # Check `gl_subdomain?` as well to keep parity with gitlab.com Gitlab.config.gitlab.url == COM_URL || gl_subdomain? @@ -49,12 +89,4 @@ module Gitlab def self.dev_env_or_com? Rails.env.development? || org? || com? end - - def self.pre_release? - VERSION.include?('pre') - end - - def self.version_info - Gitlab::VersionInfo.parse(Gitlab::VERSION) - end end diff --git a/lib/gitlab/release_blog_post.rb b/lib/gitlab/release_blog_post.rb new file mode 100644 index 00000000000..639aee61464 --- /dev/null +++ b/lib/gitlab/release_blog_post.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +require 'singleton' + +module Gitlab + class ReleaseBlogPost + include Singleton + + RELEASE_RSS_URL = 'https://about.gitlab.com/releases.xml' + + def blog_post_url + @url ||= fetch_blog_post_url + end + + private + + def fetch_blog_post_url + installed_version = Gitlab.final_release? ? Gitlab.minor_release : Gitlab.previous_release + response = Gitlab::HTTP.get(RELEASE_RSS_URL, verify: false) + + return unless response.code == 200 + + blog_entry = find_installed_blog_entry(response, installed_version) + blog_entry['id'] if blog_entry + end + + def find_installed_blog_entry(response, installed_version) + response['feed']['entry'].find do |entry| + entry['release'] == installed_version || matches_previous_release_post(entry['release'], installed_version) + end + end + + def should_match_previous_release_post? + Gitlab.new_major_release? && !Gitlab.final_release? + end + + def matches_previous_release_post(rss_release_version, installed_version) + should_match_previous_release_post? && rss_release_version[/\d+/] == installed_version + end + end +end diff --git a/lib/gitlab/version_info.rb b/lib/gitlab/version_info.rb index aa6d5310161..142ead12c08 100644 --- a/lib/gitlab/version_info.rb +++ b/lib/gitlab/version_info.rb @@ -20,6 +20,14 @@ module Gitlab @patch = patch end + def minor_version? + minor.to_i > 0 + end + + def patch_version? + patch.to_i > 0 + end + def <=>(other) return unless other.is_a? VersionInfo return unless valid? && other.valid? diff --git a/locale/gitlab.pot b/locale/gitlab.pot index e7aa7e453bd..d94daea9164 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -7659,6 +7659,9 @@ msgstr "" msgid "Web terminal" msgstr "" +msgid "What's new?" +msgstr "" + msgid "When a runner is locked, it cannot be assigned to other projects" msgstr "" diff --git a/spec/features/dashboard/help_spec.rb b/spec/features/dashboard/help_spec.rb index 68bfbf22736..fa12cecc984 100644 --- a/spec/features/dashboard/help_spec.rb +++ b/spec/features/dashboard/help_spec.rb @@ -5,13 +5,23 @@ RSpec.describe 'Dashboard Help' do sign_in(create(:user)) end - it 'renders correctly markdown' do - visit help_page_path("administration/raketasks/maintenance") + context 'help dropdown' do + it 'shows the "What\'s new?" menu item' do + visit root_dashboard_path - expect(page).to have_content('Gather information about GitLab and the system it runs on') + expect(page.find('.header-help .dropdown-menu')).to have_text("What's new?") + end + end - node = find('.documentation h2 a#user-content-check-gitlab-configuration') - expect(node[:href]).to eq '#check-gitlab-configuration' - expect(find(:xpath, "#{node.path}/..").text).to eq 'Check GitLab configuration' + context 'documentation' do + it 'renders correctly markdown' do + visit help_page_path("administration/raketasks/maintenance") + + expect(page).to have_content('Gather information about GitLab and the system it runs on') + + node = find('.documentation h2 a#user-content-check-gitlab-configuration') + expect(node[:href]).to eq '#check-gitlab-configuration' + expect(find(:xpath, "#{node.path}/..").text).to eq 'Check GitLab configuration' + end end end diff --git a/spec/lib/gitlab/release_blog_post_spec.rb b/spec/lib/gitlab/release_blog_post_spec.rb new file mode 100644 index 00000000000..2c987df3767 --- /dev/null +++ b/spec/lib/gitlab/release_blog_post_spec.rb @@ -0,0 +1,97 @@ +require 'spec_helper' + +describe Gitlab::ReleaseBlogPost do + describe '.blog_post_url' do + let(:releases_xml) do + <<~EOS + + + + 11.2 + https://about.gitlab.com/2018/08/22/gitlab-11-2-released/ + + + 11.1 + https://about.gitlab.com/2018/07/22/gitlab-11-1-released/ + + + 11.0 + https://about.gitlab.com/2018/06/22/gitlab-11-0-released/ + + + 10.8 + https://about.gitlab.com/2018/05/22/gitlab-10-8-released/ + + + EOS + end + + subject { described_class.send(:new).blog_post_url } + + before do + stub_request(:get, 'https://about.gitlab.com/releases.xml') + .to_return(status: 200, headers: { 'content-type' => ['text/xml'] }, body: releases_xml) + end + + context 'matches GitLab version to blog post url' do + it 'returns the correct url for major pre release' do + stub_const('Gitlab::VERSION', '11.0.0-pre') + + expect(subject).to eql('https://about.gitlab.com/2018/05/22/gitlab-10-8-released/') + end + + it 'returns the correct url for major release candidate' do + stub_const('Gitlab::VERSION', '11.0.0-rc3') + + expect(subject).to eql('https://about.gitlab.com/2018/05/22/gitlab-10-8-released/') + end + + it 'returns the correct url for major release' do + stub_const('Gitlab::VERSION', '11.0.0') + + expect(subject).to eql('https://about.gitlab.com/2018/06/22/gitlab-11-0-released/') + end + + it 'returns the correct url for minor pre release' do + stub_const('Gitlab::VERSION', '11.2.0-pre') + + expect(subject).to eql('https://about.gitlab.com/2018/07/22/gitlab-11-1-released/') + end + + it 'returns the correct url for minor release candidate' do + stub_const('Gitlab::VERSION', '11.2.0-rc3') + + expect(subject).to eql('https://about.gitlab.com/2018/07/22/gitlab-11-1-released/') + end + + it 'returns the correct url for minor release' do + stub_const('Gitlab::VERSION', '11.2.0') + + expect(subject).to eql('https://about.gitlab.com/2018/08/22/gitlab-11-2-released/') + end + + it 'returns the correct url for patch pre release' do + stub_const('Gitlab::VERSION', '11.2.1-pre') + expect(subject).to eql('https://about.gitlab.com/2018/08/22/gitlab-11-2-released/') + end + + it 'returns the correct url for patch release candidate' do + stub_const('Gitlab::VERSION', '11.2.1-rc3') + + expect(subject).to eql('https://about.gitlab.com/2018/08/22/gitlab-11-2-released/') + end + + it 'returns the correct url for patch release' do + stub_const('Gitlab::VERSION', '11.2.1') + + expect(subject).to eql('https://about.gitlab.com/2018/08/22/gitlab-11-2-released/') + end + + it 'returns nil when no blog post is matched' do + stub_const('Gitlab::VERSION', '9.0.0') + + expect(subject).to be(nil) + end + end + end +end diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb index d63f448883b..6ac3d115bc6 100644 --- a/spec/lib/gitlab_spec.rb +++ b/spec/lib/gitlab_spec.rb @@ -8,6 +8,7 @@ describe Gitlab do expect(described_class.root).to eq(Pathname.new(File.expand_path('../..', __dir__))) end end + describe '.revision' do let(:cmd) { %W[#{described_class.config.git.bin_path} log --pretty=format:%h -n 1] } @@ -69,6 +70,82 @@ describe Gitlab do end end + describe '.final_release?' do + subject { described_class.final_release? } + + context 'returns the corrent boolean value' do + it 'is false for a pre release' do + stub_const('Gitlab::VERSION', '11.0.0-pre') + + expect(subject).to be false + end + + it 'is false for a release candidate' do + stub_const('Gitlab::VERSION', '11.0.0-rc2') + + expect(subject).to be false + end + + it 'is true for a final release' do + stub_const('Gitlab::VERSION', '11.0.2') + + expect(subject).to be true + end + end + end + + describe '.minor_release' do + subject { described_class.minor_release } + + it 'returns the minor release of the full GitLab version' do + stub_const('Gitlab::VERSION', '11.0.1-rc3') + + expect(subject).to eql '11.0' + end + end + + describe '.previous_release' do + subject { described_class.previous_release } + + context 'it should return the previous release' do + it 'returns the previous major version when GitLab major version is not final' do + stub_const('Gitlab::VERSION', '11.0.1-pre') + + expect(subject).to eql '10' + end + + it 'returns the current minor version when the GitLab patch version is RC and > 0' do + stub_const('Gitlab::VERSION', '11.2.1-rc3') + + expect(subject).to eql '11.2' + end + + it 'returns the previous minor version when the GitLab patch version is RC and 0' do + stub_const('Gitlab::VERSION', '11.2.0-rc3') + + expect(subject).to eql '11.1' + end + end + end + + describe '.new_major_release?' do + subject { described_class.new_major_release? } + + context 'returns the corrent boolean value' do + it 'is true when the minor version is 0 and the patch is a pre release' do + stub_const('Gitlab::VERSION', '11.0.1-pre') + + expect(subject).to be true + end + + it 'is false when the minor version is above 0' do + stub_const('Gitlab::VERSION', '11.2.1-rc3') + + expect(subject).to be false + end + end + end + describe '.com?' do it 'is true when on GitLab.com' do stub_config_setting(url: 'https://gitlab.com') diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 89357056c93..ca977effcb6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -127,6 +127,11 @@ RSpec.configure do |config| .and_return(false) end + config.before(:suite) do + # Set latest release blog post URL for "What's new?" link + Gitlab::ReleaseBlogPost.instance.instance_variable_set(:@url, 'https://about.gitlab.com') + end + config.before(:example, :request_store) do RequestStore.begin! end