Commit 4e78d33c authored by Zack Cuddy's avatar Zack Cuddy Committed by Dylan Griffith

GitLab Version - Internal Endpoint

parent f4a90915
# frozen_string_literal: true
class Admin::VersionCheckController < Admin::ApplicationController
feature_category :not_owned
def version_check
response = VersionCheck.new.response
expires_in 1.minute if response
render json: response
end
end
......@@ -6,7 +6,7 @@ module VersionCheckHelper
return unless Gitlab::CurrentSettings.version_check_enabled
return if User.single_user&.requires_usage_stats_consent?
image_tag VersionCheck.url, class: 'js-version-status-badge'
image_tag VersionCheck.image_url, class: 'js-version-status-badge'
end
def link_to_version
......
......@@ -186,4 +186,6 @@ namespace :admin do
get '/dashboard/stats', to: 'dashboard#stats'
root to: 'dashboard#index'
get :version_check, to: 'version_check#version_check'
end
......@@ -2,22 +2,60 @@
require "base64"
# This class is used to build image URL to
# check if it is a new version for update
class VersionCheck
include ReactiveCaching
self.reactive_cache_work_type = :external_dependency
self.reactive_cache_worker_finder = ->(_id, *args) { from_cache }
def self.data
{ version: Gitlab::VERSION }
end
def self.url
def self.headers
{ "REFERER": Gitlab.config.gitlab.url }
end
# This is temporary and will be removed when the new UI is hooked up
# to the version_check.json endpoint.
def self.image_url
encoded_data = Base64.urlsafe_encode64(data.to_json)
"#{host}/check.svg?gitlab_info=#{encoded_data}"
end
def self.url
encoded_data = Base64.urlsafe_encode64(data.to_json)
"#{host}/check.json?gitlab_info=#{encoded_data}"
end
def self.host
'https://version.gitlab.com'
end
def self.from_cache(*)
new
end
def id
Gitlab::VERSION
end
def calculate_reactive_cache(*)
response = Gitlab::HTTP.try_get(self.class.url, headers: self.class.headers)
case response&.code
when 200
response.body
end
end
def response
with_reactive_cache do |data|
Gitlab::Json.parse(data) if data
end
end
end
VersionCheck.prepend_mod
......@@ -33,7 +33,7 @@ RSpec.describe 'Help Pages' do
stub_application_setting(version_check_enabled: true)
stub_rails_env('production')
allow(VersionCheck).to receive(:url).and_return('/version-check-url')
allow(VersionCheck).to receive(:image_url).and_return('/version-check-url')
sign_in(create(:user))
visit help_path
......
......@@ -15,7 +15,7 @@ RSpec.describe VersionCheckHelper do
before do
stub_rails_env('production')
allow(Gitlab::CurrentSettings.current_application_settings).to receive(:version_check_enabled) { true }
allow(VersionCheck).to receive(:url) { 'https://version.host.com/check.svg?gitlab_info=xxx' }
allow(VersionCheck).to receive(:image_url) { 'https://version.host.com/check.svg?gitlab_info=xxx' }
end
it 'returns an image tag' do
......@@ -27,7 +27,7 @@ RSpec.describe VersionCheckHelper do
.to match(/class="js-version-status-badge lazy"/)
end
it 'has a VersionCheck url as the src' do
it 'has a VersionCheck image_url as the src' do
expect(helper.version_status_badge)
.to include(%{src="https://version.host.com/check.svg?gitlab_info=xxx"})
end
......
......@@ -3,9 +3,67 @@
require 'spec_helper'
RSpec.describe VersionCheck do
describe '.image_url' do
it 'returns the correct URL' do
expect(described_class.image_url).to match(%r{\A#{Regexp.escape(described_class.host)}/check\.svg\?gitlab_info=\w+})
end
end
describe '.url' do
it 'returns the correct URL' do
expect(described_class.url).to match(%r{\A#{Regexp.escape(described_class.host)}/check\.svg\?gitlab_info=\w+})
expect(described_class.url).to match(%r{\A#{Regexp.escape(described_class.host)}/check\.json\?gitlab_info=\w+})
end
end
describe '#calculate_reactive_cache' do
context 'response code is 200' do
before do
stub_request(:get, described_class.url).to_return(status: 200, body: '{ "status": "success" }', headers: {})
end
it 'returns the response object' do
expect(described_class.new.calculate_reactive_cache).to eq("{ \"status\": \"success\" }")
end
end
context 'response code is not 200' do
before do
stub_request(:get, described_class.url).to_return(status: 500, body: nil, headers: {})
end
it 'returns nil' do
expect(described_class.new.calculate_reactive_cache).to be(nil)
end
end
end
describe '#response' do
context 'cache returns value' do
let(:response) { { "severity" => "success" }.to_json }
before do
allow_next_instance_of(described_class) do |instance|
allow(instance).to receive(:with_reactive_cache).and_return(response)
end
end
it 'returns the response object' do
expect(described_class.new.response).to be(response)
end
end
context 'cache returns nil' do
let(:response) { nil }
before do
allow_next_instance_of(described_class) do |instance|
allow(instance).to receive(:with_reactive_cache).and_return(response)
end
end
it 'returns nil' do
expect(described_class.new.response).to be(nil)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Admin::VersionCheckController, :enable_admin_mode do
let(:admin) { create(:admin) }
before do
sign_in(admin)
end
describe 'GET #version_check' do
context 'when VersionCheck.response is nil' do
before do
allow_next_instance_of(VersionCheck) do |instance|
allow(instance).to receive(:response).and_return(nil)
end
get admin_version_check_path
end
it 'returns nil' do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to be_nil
end
it 'sets no-cache headers' do
expect(response.headers['Cache-Control']).to eq('private, no-store')
end
end
context 'when VersionCheck.response is valid' do
before do
allow_next_instance_of(VersionCheck) do |instance|
allow(instance).to receive(:response).and_return({ "severity" => "success" })
end
get admin_version_check_path
end
it 'returns the valid data' do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to eq({ "severity" => "success" })
end
it 'sets proper cache headers' do
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/346999
# The Cache-Control header is not set correctly for tests
# expect(response.headers['Cache-Control']).to eq('max-age=60, private')
expect(response.headers['Cache-Control']).to eq('private, no-store')
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment