Commit 8c8b94e7 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent eadb77d8
......@@ -31,7 +31,16 @@
}
}
.ci-status-icon-preparing,
.ci-status-icon-preparing {
svg {
fill: $gray-500;
}
&.add-border {
@include borderless-status-icon($gray-500);
}
}
.ci-status-icon-running {
svg {
fill: $blue-400;
......
......@@ -123,7 +123,7 @@ ul.content-list {
font-weight: $gl-font-weight-bold;
}
a {
a:not(.default-link-color) {
color: $gl-text-color;
}
......
......@@ -37,6 +37,10 @@
}
}
&.ci-preparing {
@include status-color($gray-100, $gray-500, $gray-600);
}
&.ci-pending,
&.ci-failed-with-warnings,
&.ci-success-with-warnings {
......@@ -44,7 +48,6 @@
}
&.ci-info,
&.ci-preparing,
&.ci-running {
@include status-color($blue-100, $blue-500, $blue-600);
}
......
......@@ -6,9 +6,9 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
before_action :set_application_setting
before_action :whitelist_query_limiting, only: [:usage_data]
VALID_SETTING_PANELS = %w(general integrations repository templates
VALID_SETTING_PANELS = %w(general integrations repository
ci_cd reporting metrics_and_profiling
network geo preferences).freeze
network preferences).freeze
VALID_SETTING_PANELS.each do |action|
define_method(action) { perform_update if submitted? }
......@@ -145,10 +145,15 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
end
def render_update_error
action = VALID_SETTING_PANELS.include?(action_name) ? action_name : :general
action = valid_setting_panels.include?(action_name) ? action_name : :general
render action
end
# overridden in EE
def valid_setting_panels
VALID_SETTING_PANELS
end
end
Admin::ApplicationSettingsController.prepend_if_ee('EE::Admin::ApplicationSettingsController')
......@@ -3,8 +3,20 @@
module CycleAnalyticsParams
extend ActiveSupport::Concern
def cycle_analytics_project_params
return {} unless params[:cycle_analytics].present?
params[:cycle_analytics].permit(:start_date, :created_after, :created_before, :branch_name)
end
def cycle_analytics_group_params
return {} unless params[:cycle_analytics].present?
params[:cycle_analytics].permit(:start_date, :created_after, :created_before, project_ids: [])
end
def options(params)
@options ||= { from: start_date(params), current_user: current_user }
@options ||= { from: start_date(params), current_user: current_user }.merge(date_range(params))
end
def start_date(params)
......@@ -17,6 +29,17 @@ module CycleAnalyticsParams
90.days.ago
end
end
def date_range(params)
{}.tap do |date_range_params|
date_range_params[:from] = to_utc_time(params[:created_after]).beginning_of_day if params[:created_after]
date_range_params[:to] = to_utc_time(params[:created_before]).end_of_day if params[:created_before]
end.compact
end
def to_utc_time(field)
Date.parse(field).to_time.utc
end
end
CycleAnalyticsParams.prepend_if_ee('EE::CycleAnalyticsParams')
......@@ -23,7 +23,7 @@ module Projects
end
def test
options(cycle_analytics_params)[:branch] = cycle_analytics_params[:branch_name]
options(cycle_analytics_project_params)[:branch] = cycle_analytics_project_params[:branch_name]
render_events(cycle_analytics[:test].events)
end
......@@ -50,13 +50,7 @@ module Projects
end
def cycle_analytics
@cycle_analytics ||= ::CycleAnalytics::ProjectLevel.new(project, options: options(cycle_analytics_params))
end
def cycle_analytics_params
return {} unless params[:cycle_analytics].present?
params[:cycle_analytics].permit(:start_date, :branch_name)
@cycle_analytics ||= ::CycleAnalytics::ProjectLevel.new(project, options: options(cycle_analytics_project_params))
end
end
end
......
......@@ -9,7 +9,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
before_action :authorize_read_cycle_analytics!
def show
@cycle_analytics = ::CycleAnalytics::ProjectLevel.new(@project, options: options(cycle_analytics_params))
@cycle_analytics = ::CycleAnalytics::ProjectLevel.new(@project, options: options(cycle_analytics_project_params))
@cycle_analytics_no_data = @cycle_analytics.no_stats?
......@@ -27,12 +27,6 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
private
def cycle_analytics_params
return {} unless params[:cycle_analytics].present?
params[:cycle_analytics].permit(:start_date)
end
def cycle_analytics_json
{
summary: @cycle_analytics.summary,
......
......@@ -77,6 +77,8 @@ module CiStatusHelper
'status_failed'
when 'pending'
'status_pending'
when 'preparing'
'status_preparing'
when 'running'
'status_running'
when 'play'
......
......@@ -13,6 +13,7 @@ module CycleAnalytics
def summary
@summary ||= ::Gitlab::CycleAnalytics::StageSummary.new(project,
from: options[:from],
to: options[:to],
current_user: options[:current_user]).data
end
......
- page_title _("Container Registry")
%section
.row.registry-placeholder.prepend-bottom-10
.col-12
......
......@@ -19,9 +19,15 @@
- else
%p
= s_("TagsPage|Can't find HEAD commit for this tag")
- if release && release.description.present?
.description.md.prepend-top-default
= markdown_field(release, :description)
- if release
.text-secondary
= icon('rocket')
= _("Release")
= link_to release.name, project_releases_path(@project, anchor: release.tag), class: 'default-link-color'
- if release.description.present?
.description.md.prepend-top-default
= markdown_field(release, :description)
.row-fixed-content.controls.flex-row
= render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name]
......
---
title: Add missing page title to projects/container-registry
merge_request: 18114
author:
type: changed
---
title: Add pipeline preparing status icons
merge_request: 17923
author:
type: added
......@@ -491,6 +491,9 @@ Gitlab.ee do
Settings.cron_jobs['historical_data_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['historical_data_worker']['cron'] ||= '0 12 * * *'
Settings.cron_jobs['historical_data_worker']['job_class'] = 'HistoricalDataWorker'
Settings.cron_jobs['import_software_licenses_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['import_software_licenses_worker']['cron'] ||= '0 3 * * 0'
Settings.cron_jobs['import_software_licenses_worker']['job_class'] = 'ImportSoftwareLicensesWorker'
Settings.cron_jobs['ldap_group_sync_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['ldap_group_sync_worker']['cron'] ||= '0 * * * *'
Settings.cron_jobs['ldap_group_sync_worker']['job_class'] = 'LdapAllGroupsSyncWorker'
......
......@@ -114,7 +114,7 @@ namespace :admin do
put :reset_registration_token
put :reset_health_check_token
put :clear_repository_check_states
match :general, :integrations, :repository, :templates, :ci_cd, :reporting, :metrics_and_profiling, :network, :geo, :preferences, via: [:get, :patch]
match :general, :integrations, :repository, :ci_cd, :reporting, :metrics_and_profiling, :network, :preferences, via: [:get, :patch]
get :lets_encrypt_terms_of_service
end
......
# frozen_string_literal: true
class AddSpdxIdToSoftwareLicenses < ActiveRecord::Migration[5.2]
DOWNTIME = false
def up
add_column :software_licenses, :spdx_identifier, :string, limit: 255
end
def down
remove_column :software_licenses, :spdx_identifier
end
end
# frozen_string_literal: true
class AddIndexToSoftwareLicensesOnSpdxId < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :software_licenses, :spdx_identifier
end
def down
remove_concurrent_index :software_licenses, :spdx_identifier
end
end
# frozen_string_literal: true
class BackfillSoftwareLicensesSpdxIdentifiers < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
CURRENT_LICENSES = {
'AGPL-1.0' => 'AGPL-1.0',
'AGPL-3.0' => 'AGPL-3.0',
'Apache 2.0' => 'Apache-2.0',
'Artistic-2.0' => 'Artistic-2.0',
'BSD' => 'BSD-4-Clause',
'CC0 1.0 Universal' => 'CC0-1.0',
'CDDL-1.0' => 'CDDL-1.0',
'CDDL-1.1' => 'CDDL-1.1',
'EPL-1.0' => 'EPL-1.0',
'EPL-2.0' => 'EPL-2.0',
'GPLv2' => 'GPL-2.0',
'GPLv3' => 'GPL-3.0',
'ISC' => 'ISC',
'LGPL' => 'LGPL-3.0-only',
'LGPL-2.1' => 'LGPL-2.1',
'MIT' => 'MIT',
'Mozilla Public License 2.0' => 'MPL-2.0',
'MS-PL' => 'MS-PL',
'MS-RL' => 'MS-RL',
'New BSD' => 'BSD-3-Clause',
'Python Software Foundation License' => 'Python-2.0',
'ruby' => 'Ruby',
'Simplified BSD' => 'BSD-2-Clause',
'WTFPL' => 'WTFPL',
'Zlib' => 'Zlib'
}.freeze
disable_ddl_transaction!
# 25 records to be updated on GitLab.com
def up
return unless Gitlab.ee?
say "Expect #{CURRENT_LICENSES.count} updates to the software_licenses table to occur"
CURRENT_LICENSES.each do |name, spdx_identifier|
# The following cop is disabled because of https://gitlab.com/gitlab-org/gitlab/issues/33470
# For more context see https://gitlab.com/gitlab-org/gitlab/merge_requests/17004#note_226264823
# rubocop:disable Migration/UpdateColumnInBatches
update_column_in_batches(:software_licenses, :spdx_identifier, spdx_identifier) do |table, query|
query.where(table[:name].eq(name))
end
end
end
def down
return unless Gitlab.ee?
update_column_in_batches(:software_licenses, :spdx_identifier, nil)
end
end
......@@ -3350,7 +3350,9 @@ ActiveRecord::Schema.define(version: 2019_09_29_180827) do
create_table "software_licenses", id: :serial, force: :cascade do |t|
t.string "name", null: false
t.string "spdx_identifier", limit: 255
t.index ["name"], name: "index_software_licenses_on_name"
t.index ["spdx_identifier"], name: "index_software_licenses_on_spdx_identifier"
end
create_table "spam_logs", id: :serial, force: :cascade do |t|
......
......@@ -15,7 +15,7 @@ module Gitlab
failed: '#e05d44',
running: '#dfb317',
pending: '#dfb317',
preparing: '#dfb317',
preparing: '#a7a7a7',
canceled: '#9f9f9f',
skipped: '#9f9f9f',
unknown: '#9f9f9f'
......
......@@ -12,20 +12,12 @@ module Gitlab
s_('CiStatusLabel|preparing')
end
##
# TODO: shared with 'created'
# until we get one for 'preparing'
#
def icon
'status_created'
'status_preparing'
end
##
# TODO: shared with 'created'
# until we get one for 'preparing'
#
def favicon
'favicon_status_created'
'favicon_status_preparing'
end
end
end
......
......@@ -23,6 +23,7 @@ module Gitlab
.project(routes_table[:path].as("namespace_path"))
query = limit_query(query, project_ids)
query = limit_query_by_date_range(query)
# Load merge_requests
......@@ -34,7 +35,12 @@ module Gitlab
def limit_query(query, project_ids)
query.where(issue_table[:project_id].in(project_ids))
.where(routes_table[:source_type].eq('Namespace'))
.where(issue_table[:created_at].gteq(options[:from]))
end
def limit_query_by_date_range(query)
query = query.where(issue_table[:created_at].gteq(options[:from]))
query = query.where(issue_table[:created_at].lteq(options[:to])) if options[:to]
query
end
def load_merge_requests(query)
......
......@@ -12,14 +12,12 @@ module Gitlab
.project(routes_table[:path].as("namespace_path"))
query = limit_query(query, project_ids)
query
limit_query_by_date_range(query)
end
def limit_query(query, project_ids)
query.where(issue_table[:project_id].in(project_ids))
.where(routes_table[:source_type].eq('Namespace'))
.where(issue_table[:created_at].gteq(options[:from]))
.where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
end
end
......
......@@ -14,12 +14,11 @@ module Gitlab
.where(routes_table[:source_type].eq('Namespace'))
query = limit_query(query)
query
limit_query_by_date_range(query)
end
def limit_query(query)
query.where(issue_table[:created_at].gteq(options[:from]))
.where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
query.where(issue_metrics_table[:first_added_to_board_at].not_eq(nil).or(issue_metrics_table[:first_associated_with_milestone_at].not_eq(nil)))
.where(issue_metrics_table[:first_mentioned_in_commit_at].not_eq(nil))
end
end
......
......@@ -3,16 +3,17 @@
module Gitlab
module CycleAnalytics
class StageSummary
def initialize(project, from:, current_user:)
def initialize(project, from:, to: nil, current_user:)
@project = project
@from = from
@to = to
@current_user = current_user
end
def data
[serialize(Summary::Issue.new(project: @project, from: @from, current_user: @current_user)),
serialize(Summary::Commit.new(project: @project, from: @from)),
serialize(Summary::Deploy.new(project: @project, from: @from))]
[serialize(Summary::Issue.new(project: @project, from: @from, to: @to, current_user: @current_user)),
serialize(Summary::Commit.new(project: @project, from: @from, to: @to)),
serialize(Summary::Deploy.new(project: @project, from: @from, to: @to))]
end
private
......
......@@ -4,9 +4,10 @@ module Gitlab
module CycleAnalytics
module Summary
class Base
def initialize(project:, from:)
def initialize(project:, from:, to: nil)
@project = project
@from = from
@to = to
end
def title
......
......@@ -21,7 +21,7 @@ module Gitlab
def count_commits
return unless ref
gitaly_commit_client.commit_count(ref, after: @from)
gitaly_commit_client.commit_count(ref, after: @from, before: @to)
end
def gitaly_commit_client
......
......@@ -4,12 +4,18 @@ module Gitlab
module CycleAnalytics
module Summary
class Deploy < Base
include Gitlab::Utils::StrongMemoize
def title
n_('Deploy', 'Deploys', value)
end
def value
@value ||= @project.deployments.where("created_at > ?", @from).count
strong_memoize(:value) do
query = @project.deployments.where("created_at >= ?", @from)
query = query.where("created_at <= ?", @to) if @to
query.count
end
end
end
end
......
......@@ -4,9 +4,10 @@ module Gitlab
module CycleAnalytics
module Summary
class Issue < Base
def initialize(project:, from:, current_user:)
def initialize(project:, from:, to: nil, current_user:)
@project = project
@from = from
@to = to
@current_user = current_user
end
......@@ -15,7 +16,7 @@ module Gitlab
end
def value
@value ||= IssuesFinder.new(@current_user, project_id: @project.id).execute.created_after(@from).count
@value ||= IssuesFinder.new(@current_user, project_id: @project.id, created_after: @from, created_before: @to).execute.count
end
end
end
......
......@@ -53,7 +53,7 @@ module Gitlab
@legacy_disk_path = File.expand_path(storage['path'], Rails.root) if storage['path']
storage['path'] = Deprecated
@hash = storage
@hash = storage.with_indifferent_access
end
def gitaly_address
......
......@@ -13117,6 +13117,9 @@ msgstr ""
msgid "Related merge requests"
msgstr ""
msgid "Release"
msgstr ""
msgid "Releases"
msgstr ""
......
......@@ -118,7 +118,7 @@ describe Admin::ApplicationSettingsController do
end
describe 'verify panel actions' do
(Admin::ApplicationSettingsController::VALID_SETTING_PANELS - %w(templates geo)).each do |valid_action|
Admin::ApplicationSettingsController::VALID_SETTING_PANELS.each do |valid_action|
it_behaves_like 'renders correct panels' do
let(:action) { valid_action }
end
......
......@@ -17,6 +17,11 @@ describe 'Container Registry', :js do
stub_container_registry_tags(repository: :any, tags: [])
end
it 'has a page title set' do
visit_container_registry
expect(page).to have_title(_('Container Registry'))
end
context 'when there are no image repositories' do
it 'user visits container registry main page' do
visit_container_registry
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -67,7 +67,7 @@ describe Gitlab::Badge::Pipeline::Template do
end
it 'has expected color' do
expect(template.value_color).to eq '#dfb317'
expect(template.value_color).to eq '#a7a7a7'
end
end
......
......@@ -16,11 +16,11 @@ describe Gitlab::Ci::Status::Preparing do
end
describe '#icon' do
it { expect(subject.icon).to eq 'status_created' }
it { expect(subject.icon).to eq 'status_preparing' }
end
describe '#favicon' do
it { expect(subject.favicon).to eq 'favicon_status_created' }
it { expect(subject.favicon).to eq 'favicon_status_preparing' }
end
describe '#group' do
......
......@@ -12,7 +12,8 @@ describe Gitlab::CycleAnalytics::CodeStage do
let(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) }
let(:mr_1) { create(:merge_request, source_project: project, created_at: 15.minutes.ago) }
let(:mr_2) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'A') }
let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
let(:stage_options) { { from: 2.days.ago, current_user: project.creator, project: project } }
let(:stage) { described_class.new(options: stage_options) }
before do
issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 45.minutes.ago)
......@@ -33,6 +34,8 @@ describe Gitlab::CycleAnalytics::CodeStage do
it 'counts median from issues with metrics' do
expect(stage.project_median).to eq(ISSUES_MEDIAN)
end
include_examples 'calculate #median with date range'
end
describe '#events' do
......
......@@ -10,7 +10,8 @@ describe Gitlab::CycleAnalytics::IssueStage do
let(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
let(:issue_3) { create(:issue, project: project, created_at: 30.minutes.ago) }
let!(:issue_without_milestone) { create(:issue, project: project, created_at: 1.minute.ago) }
let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
let(:stage_options) { { from: 2.days.ago, current_user: project.creator, project: project } }
let(:stage) { described_class.new(options: stage_options) }
before do
issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago )
......@@ -28,6 +29,8 @@ describe Gitlab::CycleAnalytics::IssueStage do
it 'counts median from issues with metrics' do
expect(stage.project_median).to eq(ISSUES_MEDIAN)
end
include_examples 'calculate #median with date range'
end
describe '#events' do
......
......@@ -10,7 +10,8 @@ describe Gitlab::CycleAnalytics::PlanStage do
let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) }
let!(:issue_3) { create(:issue, project: project, created_at: 30.minutes.ago) }
let!(:issue_without_milestone) { create(:issue, project: project, created_at: 1.minute.ago) }
let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
let(:stage_options) { { from: 2.days.ago, current_user: project.creator, project: project } }
let(:stage) { described_class.new(options: stage_options) }
before do
issue_1.metrics.update!(first_associated_with_milestone_at: 60.minutes.ago, first_mentioned_in_commit_at: 10.minutes.ago)
......@@ -28,6 +29,8 @@ describe Gitlab::CycleAnalytics::PlanStage do
it 'counts median from issues with metrics' do
expect(stage.project_median).to eq(ISSUES_MEDIAN)
end
include_examples 'calculate #median with date range'
end
describe '#events' do
......
......@@ -32,3 +32,23 @@ shared_examples 'base stage' do
expect(stage.events).not_to be_nil
end
end
shared_examples 'calculate #median with date range' do
context 'when valid date range is given' do
before do
stage_options[:from] = 5.days.ago
stage_options[:to] = 5.days.from_now
end
it { expect(stage.project_median).to eq(ISSUES_MEDIAN) }
end
context 'when records are out of the date range' do
before do
stage_options[:from] = 2.years.ago
stage_options[:to] = 1.year.ago
end
it { expect(stage.project_median).to eq(nil) }
end
end
......@@ -4,52 +4,98 @@ require 'spec_helper'
describe Gitlab::CycleAnalytics::StageSummary do
let(:project) { create(:project, :repository) }
let(:from) { 1.day.ago }
let(:options) { { from: 1.day.ago, current_user: user } }
let(:user) { create(:user, :admin) }
subject { described_class.new(project, from: Time.now, current_user: user).data }
let(:stage_summary) { described_class.new(project, options).data }
describe "#new_issues" do
subject { stage_summary.first[:value] }
it "finds the number of issues created after the 'from date'" do
Timecop.freeze(5.days.ago) { create(:issue, project: project) }
Timecop.freeze(5.days.from_now) { create(:issue, project: project) }
expect(subject.first[:value]).to eq(1)
expect(subject).to eq(1)
end
it "doesn't find issues from other projects" do
Timecop.freeze(5.days.from_now) { create(:issue, project: create(:project)) }
expect(subject.first[:value]).to eq(0)
expect(subject).to eq(0)
end
context 'when `to` parameter is given' do
before do
Timecop.freeze(5.days.ago) { create(:issue, project: project) }
Timecop.freeze(5.days.from_now) { create(:issue, project: project) }
end
it "doesn't find any record" do
options[:to] = Time.now
expect(subject).to eq(0)
end
it "finds records created between `from` and `to` range" do
options[:from] = 10.days.ago
options[:to] = 10.days.from_now
expect(subject).to eq(2)
end
end
end
describe "#commits" do
subject { stage_summary.second[:value] }
it "finds the number of commits created after the 'from date'" do
Timecop.freeze(5.days.ago) { create_commit("Test message", project, user, 'master') }
Timecop.freeze(5.days.from_now) { create_commit("Test message", project, user, 'master') }
expect(subject.second[:value]).to eq(1)
expect(subject).to eq(1)
end
it "doesn't find commits from other projects" do
Timecop.freeze(5.days.from_now) { create_commit("Test message", create(:project, :repository), user, 'master') }
expect(subject.second[:value]).to eq(0)
expect(subject).to eq(0)
end
it "finds a large (> 100) snumber of commits if present" do
Timecop.freeze(5.days.from_now) { create_commit("Test message", project, user, 'master', count: 100) }
expect(subject.second[:value]).to eq(100)
expect(subject).to eq(100)
end
context 'when `to` parameter is given' do
before do
Timecop.freeze(5.days.ago) { create_commit("Test message", project, user, 'master') }
Timecop.freeze(5.days.from_now) { create_commit("Test message", project, user, 'master') }
end
it "doesn't find any record" do
options[:to] = Time.now
expect(subject).to eq(0)
end
it "finds records created between `from` and `to` range" do
options[:from] = 10.days.ago
options[:to] = 10.days.from_now
expect(subject).to eq(2)
end
end
end
describe "#deploys" do
subject { stage_summary.third[:value] }
it "finds the number of deploys made created after the 'from date'" do
Timecop.freeze(5.days.ago) { create(:deployment, :success, project: project) }
Timecop.freeze(5.days.from_now) { create(:deployment, :success, project: project) }
expect(subject.third[:value]).to eq(1)
expect(subject).to eq(1)
end
it "doesn't find commits from other projects" do
......@@ -57,7 +103,27 @@ describe Gitlab::CycleAnalytics::StageSummary do
create(:deployment, :success, project: create(:project, :repository))
end
expect(subject.third[:value]).to eq(0)
expect(subject).to eq(0)
end
context 'when `to` parameter is given' do
before do
Timecop.freeze(5.days.ago) { create(:deployment, :success, project: project) }
Timecop.freeze(5.days.from_now) { create(:deployment, :success, project: project) }
end
it "doesn't find any record" do
options[:to] = Time.now
expect(subject).to eq(0)
end
it "finds records created between `from` and `to` range" do
options[:from] = 10.days.ago
options[:to] = 10.days.from_now
expect(subject).to eq(2)
end
end
end
end
......@@ -16,7 +16,8 @@ describe Gitlab::CycleAnalytics::StagingStage do
let(:build_1) { create(:ci_build, project: project) }
let(:build_2) { create(:ci_build, project: project) }
let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
let(:stage_options) { { from: 2.days.ago, current_user: project.creator, project: project } }
let(:stage) { described_class.new(options: stage_options) }
before do
mr_1.metrics.update!(merged_at: 80.minutes.ago, first_deployed_to_production_at: 50.minutes.ago, pipeline_id: build_1.commit_id)
......@@ -38,6 +39,8 @@ describe Gitlab::CycleAnalytics::StagingStage do
it 'counts median from issues with metrics' do
expect(stage.project_median).to eq(ISSUES_MEDIAN)
end
it_behaves_like 'calculate #median with date range'
end
describe '#events' do
......
......@@ -6,7 +6,8 @@ require 'lib/gitlab/cycle_analytics/shared_stage_spec'
describe Gitlab::CycleAnalytics::TestStage do
let(:stage_name) { :test }
let(:project) { create(:project) }
let(:stage) { described_class.new(options: { from: 2.days.ago, current_user: project.creator, project: project }) }
let(:stage_options) { { from: 2.days.ago, current_user: project.creator, project: project } }
let(:stage) { described_class.new(options: stage_options) }
it_behaves_like 'base stage'
......@@ -40,5 +41,7 @@ describe Gitlab::CycleAnalytics::TestStage do
it 'counts median from issues with metrics' do
expect(stage.project_median).to eq(ISSUES_MEDIAN)
end
include_examples 'calculate #median with date range'
end
end
......@@ -57,6 +57,7 @@ RSpec.describe Gitlab::Favicon, :request_store do
favicon_status_manual
favicon_status_not_found
favicon_status_pending
favicon_status_preparing
favicon_status_running
favicon_status_scheduled
favicon_status_skipped
......
......@@ -27,6 +27,38 @@ describe Gitlab::GitalyClient::StorageSettings do
end
end
describe '.gitaly_address' do
context 'when the storage settings have no gitaly address but one is requested' do
it 'raises an error' do
expect do
described_class.new("path" => Rails.root).gitaly_address
end.to raise_error("key not found: \"gitaly_address\"")
end
end
context 'when the storage settings have a gitaly address and one is requested' do
it 'returns the setting value' do
expect(described_class.new("path" => Rails.root, "gitaly_address" => "test").gitaly_address).to eq("test")
end
end
context 'when the storage settings have a gitaly address keyed symbolically' do
it 'raises no error' do
expect do
described_class.new("path" => Rails.root, :gitaly_address => "test").gitaly_address
end.not_to raise_error
end
end
context 'when the storage settings have a gitaly address keyed with a string' do
it 'raises no error' do
expect do
described_class.new("path" => Rails.root, "gitaly_address" => "test").gitaly_address
end.not_to raise_error
end
end
end
describe '.disk_access_denied?' do
context 'when Rugged is enabled', :enable_rugged do
it 'returns false' do
......
......@@ -23,6 +23,11 @@ describe 'projects/tags/index' do
expect(rendered).to have_button('Last updated')
end
it 'renders links to the Releases page for tags associated with a release' do
render
expect(rendered).to have_link(release.name, href: project_releases_path(project, anchor: release.tag))
end
context 'when the most recent build for a tag has artifacts' do
let!(:build) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
......
......@@ -990,10 +990,10 @@
dependencies:
vue-eslint-parser "^6.0.4"
"@gitlab/svgs@^1.75.0":
version "1.75.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.75.0.tgz#93f9e6bdef78dd84ac88d8273711dc1f25e4e5ac"
integrity sha512-hOCfF73++yG+KTYxaQNMkbDUg0XKije41g6XR2dgj7466rzZmebG/nt6pUXonmlqy/NLGaRUPBKs0zuM7tcLhA==
"@gitlab/svgs@^1.76.0":
version "1.76.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.76.0.tgz#2def3b5542d23259e81c889c75059a5d1f1e3f61"
integrity sha512-wTCNSq3CxNrEzrJdEbf8GwHfhzEsUMJNEuGTBGGhe1qc0sY5z/U3s3HG7tdAOrB5pec9JarRXzc7g5ax9bsopQ==
"@gitlab/ui@5.27.0":
version "5.27.0"
......
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