Skip to content
Snippets Groups Projects
Unverified Commit 56e2a291 authored by Marin Jankovski's avatar Marin Jankovski
Browse files

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce

parents 104b9e8b c384315a
No related branches found
No related tags found
No related merge requests found
Showing
with 169 additions and 87 deletions
# frozen_string_literal: true
 
module MergeRequestsHelper
include Gitlab::Utils::StrongMemoize
def new_mr_path_from_push_event(event)
target_project = event.project.default_merge_request_target
project_new_merge_request_path(
Loading
Loading
@@ -168,6 +170,12 @@ module MergeRequestsHelper
current_user.fork_of(project)
end
end
def mr_tabs_position_enabled?
strong_memoize(:mr_tabs_position_enabled) do
Feature.enabled?(:mr_tabs_position, @project, default_enabled: true)
end
end
end
 
MergeRequestsHelper.prepend_if_ee('EE::MergeRequestsHelper')
Loading
Loading
@@ -114,8 +114,10 @@ module ProjectsHelper
source = visible_fork_source(project)
 
if source
_('This will remove the fork relationship between this project and %{fork_source}.') %
msg = _('This will remove the fork relationship between this project and %{fork_source}.') %
{ fork_source: link_to(source.full_name, project_path(source)) }
msg.html_safe
else
_('This will remove the fork relationship between this project and other projects in the fork network.')
end
Loading
Loading
Loading
Loading
@@ -11,33 +11,9 @@ module SnippetsHelper
end
end
 
def reliable_snippet_path(snippet, opts = {})
reliable_snippet_url(snippet, opts.merge(only_path: true))
end
def reliable_raw_snippet_path(snippet, opts = {})
reliable_raw_snippet_url(snippet, opts.merge(only_path: true))
end
def reliable_snippet_url(snippet, opts = {})
if snippet.project_id?
project_snippet_url(snippet.project, snippet, nil, opts)
else
snippet_url(snippet, nil, opts)
end
end
def reliable_raw_snippet_url(snippet, opts = {})
if snippet.project_id?
raw_project_snippet_url(snippet.project, snippet, nil, opts)
else
raw_snippet_url(snippet, nil, opts)
end
end
def download_raw_snippet_button(snippet)
link_to(icon('download'),
reliable_raw_snippet_path(snippet, inline: false),
raw_snippet_path(snippet, inline: false),
target: '_blank',
rel: 'noopener noreferrer',
class: "btn btn-sm has-tooltip",
Loading
Loading
@@ -133,7 +109,7 @@ module SnippetsHelper
end
 
def snippet_embed_tag(snippet)
content_tag(:script, nil, src: reliable_snippet_url(snippet, format: :js, only_path: false))
content_tag(:script, nil, src: snippet_url(snippet, format: :js))
end
 
def snippet_badge(snippet)
Loading
Loading
@@ -158,7 +134,7 @@ module SnippetsHelper
return if blob.empty? || blob.binary? || blob.stored_externally?
 
link_to(external_snippet_icon('doc-code'),
reliable_raw_snippet_url(@snippet),
raw_snippet_url(@snippet),
class: 'btn',
target: '_blank',
rel: 'noopener noreferrer',
Loading
Loading
@@ -167,7 +143,7 @@ module SnippetsHelper
 
def embedded_snippet_download_button
link_to(external_snippet_icon('download'),
reliable_raw_snippet_url(@snippet, inline: false),
raw_snippet_url(@snippet, inline: false),
class: 'btn',
target: '_blank',
title: 'Download',
Loading
Loading
Loading
Loading
@@ -4,6 +4,7 @@ module UserCalloutsHelper
GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'
GCP_SIGNUP_OFFER = 'gcp_signup_offer'
SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
 
def show_gke_cluster_integration_callout?(project)
can?(current_user, :create_cluster, project) &&
Loading
Loading
@@ -25,6 +26,10 @@ module UserCalloutsHelper
!user_dismissed?(SUGGEST_POPOVER_DISMISSED)
end
 
def show_tabs_feature_highlight?
!user_dismissed?(TABS_POSITION_HIGHLIGHT) && !Rails.env.test?
end
private
 
def user_dismissed?(feature_name)
Loading
Loading
Loading
Loading
@@ -4,6 +4,7 @@ class ActiveSession
include ActiveModel::Model
 
SESSION_BATCH_SIZE = 200
ALLOWED_NUMBER_OF_ACTIVE_SESSIONS = 100
 
attr_accessor :created_at, :updated_at,
:session_id, :ip_address,
Loading
Loading
@@ -65,21 +66,22 @@ class ActiveSession
 
def self.destroy(user, session_id)
Gitlab::Redis::SharedState.with do |redis|
redis.srem(lookup_key_name(user.id), session_id)
destroy_sessions(redis, user, [session_id])
end
end
 
deleted_keys = redis.del(key_name(user.id, session_id))
def self.destroy_sessions(redis, user, session_ids)
key_names = session_ids.map {|session_id| key_name(user.id, session_id) }
session_names = session_ids.map {|session_id| "#{Gitlab::Redis::SharedState::SESSION_NAMESPACE}:#{session_id}" }
 
# only allow deleting the devise session if we could actually find a
# related active session. this prevents another user from deleting
# someone else's session.
if deleted_keys > 0
redis.del("#{Gitlab::Redis::SharedState::SESSION_NAMESPACE}:#{session_id}")
end
end
redis.srem(lookup_key_name(user.id), session_ids)
redis.del(key_names)
redis.del(session_names)
end
 
def self.cleanup(user)
Gitlab::Redis::SharedState.with do |redis|
clean_up_old_sessions(redis, user)
cleaned_up_lookup_entries(redis, user)
end
end
Loading
Loading
@@ -118,19 +120,39 @@ class ActiveSession
end
end
 
def self.raw_active_session_entries(session_ids, user_id)
def self.raw_active_session_entries(redis, session_ids, user_id)
return [] if session_ids.empty?
 
Gitlab::Redis::SharedState.with do |redis|
entry_keys = session_ids.map { |session_id| key_name(user_id, session_id) }
entry_keys = session_ids.map { |session_id| key_name(user_id, session_id) }
redis.mget(entry_keys)
end
 
redis.mget(entry_keys)
def self.active_session_entries(session_ids, user_id, redis)
return [] if session_ids.empty?
entry_keys = raw_active_session_entries(redis, session_ids, user_id)
entry_keys.compact.map do |raw_session|
Marshal.load(raw_session) # rubocop:disable Security/MarshalLoad
end
end
 
def self.clean_up_old_sessions(redis, user)
session_ids = session_ids_for_user(user.id)
return if session_ids.count <= ALLOWED_NUMBER_OF_ACTIVE_SESSIONS
# remove sessions if there are more than ALLOWED_NUMBER_OF_ACTIVE_SESSIONS.
sessions = active_session_entries(session_ids, user.id, redis)
sessions.sort_by! {|session| session.updated_at }.reverse!
sessions = sessions[ALLOWED_NUMBER_OF_ACTIVE_SESSIONS..-1].map { |session| session.session_id }
destroy_sessions(redis, user, sessions)
end
def self.cleaned_up_lookup_entries(redis, user)
session_ids = session_ids_for_user(user.id)
entries = raw_active_session_entries(session_ids, user.id)
entries = raw_active_session_entries(redis, session_ids, user.id)
 
# remove expired keys.
# only the single key entries are automatically expired by redis, the
Loading
Loading
Loading
Loading
@@ -5,12 +5,9 @@ class ApplicationSetting < ApplicationRecord
include CacheMarkdownField
include TokenAuthenticatable
include ChronicDurationAttribute
include IgnorableColumns
 
# Only remove this >= %12.6 and >= 2019-12-01
self.ignored_columns += %i[
pendo_enabled
pendo_url
]
ignore_columns :pendo_enabled, :pendo_url, remove_after: '2019-12-01', remove_with: '12.6'
 
add_authentication_token_field :runners_registration_token, encrypted: -> { Feature.enabled?(:application_settings_tokens_optional_encryption, default_enabled: true) ? :optional : :required }
add_authentication_token_field :health_check_access_token
Loading
Loading
@@ -229,6 +226,8 @@ class ApplicationSetting < ApplicationRecord
validates :push_event_activities_limit,
numericality: { greater_than_or_equal_to: 0 }
 
validates :snippet_size_limit, numericality: { only_integer: true, greater_than: 0 }
SUPPORTED_KEY_TYPES.each do |type|
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
end
Loading
Loading
Loading
Loading
@@ -26,7 +26,8 @@ module ApplicationSettingImplementation
'/users',
'/users/confirmation',
'/unsubscribes/',
'/import/github/personal_access_token'
'/import/github/personal_access_token',
'/admin/session'
].freeze
 
class_methods do
Loading
Loading
@@ -139,7 +140,8 @@ module ApplicationSettingImplementation
snowplow_app_id: nil,
snowplow_iglu_registry_url: nil,
custom_http_clone_url_root: nil,
productivity_analytics_start_date: Time.now
productivity_analytics_start_date: Time.now,
snippet_size_limit: 50.megabytes
}
end
 
Loading
Loading
Loading
Loading
@@ -20,7 +20,7 @@ class BroadcastMessage < ApplicationRecord
 
after_commit :flush_redis_cache
 
def self.current
def self.current(current_path = nil)
messages = cache.fetch(CACHE_KEY, as: BroadcastMessage, expires_in: cache_expires_in) do
current_and_future_messages
end
Loading
Loading
@@ -33,7 +33,7 @@ class BroadcastMessage < ApplicationRecord
# cache so we don't keep running this code all the time.
cache.expire(CACHE_KEY) if now_or_future.empty?
 
now_or_future.select(&:now?)
now_or_future.select(&:now?).select { |message| message.matches_current_path(current_path) }
end
 
def self.current_and_future_messages
Loading
Loading
@@ -72,6 +72,12 @@ class BroadcastMessage < ApplicationRecord
now? || future?
end
 
def matches_current_path(current_path)
return true if current_path.blank? || target_path.blank?
current_path.match(Regexp.escape(target_path).gsub('\\*', '.*'))
end
def flush_redis_cache
self.class.cache.expire(CACHE_KEY)
end
Loading
Loading
Loading
Loading
@@ -13,17 +13,11 @@ module Ci
include Importable
include Gitlab::Utils::StrongMemoize
include HasRef
include IgnorableColumns
 
BuildArchivedError = Class.new(StandardError)
 
self.ignored_columns += %i[
artifacts_file
artifacts_file_store
artifacts_metadata
artifacts_metadata_store
artifacts_size
commands
]
ignore_columns :artifacts_file, :artifacts_file_store, :artifacts_metadata, :artifacts_metadata_store, :artifacts_size, :commands, remove_after: '2019-12-15', remove_with: '12.7'
 
belongs_to :project, inverse_of: :builds
belongs_to :runner
Loading
Loading
@@ -53,7 +47,7 @@ module Ci
 
has_one :runner_session, class_name: 'Ci::BuildRunnerSession', validate: true, inverse_of: :build
 
accepts_nested_attributes_for :runner_session
accepts_nested_attributes_for :runner_session, update_only: true
accepts_nested_attributes_for :job_variables
 
delegate :url, to: :runner_session, prefix: true, allow_nil: true
Loading
Loading
Loading
Loading
@@ -22,7 +22,7 @@ module Ci
end
 
def create
return unless enabled? && !exist?
return unless enabled?
 
create_ref(sha, path)
rescue => e
Loading
Loading
Loading
Loading
@@ -299,11 +299,6 @@ module Ci
end
end
 
def self.latest_for_shas(shas)
max_id_per_sha = for_sha(shas).group(:sha).select("max(id)")
where(id: max_id_per_sha)
end
def self.latest_successful_ids_per_project
success.group(:project_id).select('max(id) as id')
end
Loading
Loading
Loading
Loading
@@ -8,6 +8,7 @@ module Ci
include ChronicDurationAttribute
include FromUnion
include TokenAuthenticatable
include IgnorableColumns
 
add_authentication_token_field :token, encrypted: -> { Feature.enabled?(:ci_runners_tokens_optional_encryption, default_enabled: true) ? :optional : :required }
 
Loading
Loading
@@ -35,7 +36,7 @@ module Ci
 
FORM_EDITABLE = %i[description tag_list active run_untagged locked access_level maximum_timeout_human_readable].freeze
 
self.ignored_columns += %i[is_shared]
ignore_column :is_shared, remove_after: '2019-12-15', remove_with: '12.6'
 
has_many :builds
has_many :runner_projects, inverse_of: :runner, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
Loading
Loading
Loading
Loading
@@ -17,11 +17,11 @@ module Clusters
include ::Clusters::Concerns::ApplicationData
include AfterCommitQueue
 
alias_method :original_set_initial_status, :set_initial_status
def set_initial_status
return unless not_installable?
return unless verify_cluster?
return unless cluster&.platform_kubernetes_rbac?
 
self.status = status_states[:installable]
original_set_initial_status
end
 
state_machine :status do
Loading
Loading
@@ -131,10 +131,6 @@ module Clusters
 
[Gitlab::Kubernetes::KubectlCmd.delete("--ignore-not-found", "-f", METRICS_CONFIG)]
end
def verify_cluster?
cluster&.application_helm_available? && cluster&.platform_kubernetes_rbac?
end
end
end
end
Loading
Loading
@@ -464,8 +464,20 @@ class Commit
"commit:#{sha}"
end
 
def expire_note_etag_cache
super
expire_note_etag_cache_for_related_mrs
end
private
 
def expire_note_etag_cache_for_related_mrs
MergeRequest.includes(target_project: :namespace).by_commit_sha(id).find_each do |mr|
mr.expire_note_etag_cache
end
end
def commit_reference(from, referable_commit_id, full: false)
reference = project.to_reference(from, full: full)
 
Loading
Loading
# frozen_string_literal: true
module IgnorableColumns
extend ActiveSupport::Concern
ColumnIgnore = Struct.new(:remove_after, :remove_with) do
def safe_to_remove?
Date.today > remove_after
end
def to_s
"(#{remove_after}, #{remove_with})"
end
end
class_methods do
# Ignore database columns in a model
#
# Indicate the earliest date and release we can stop ignoring the column with +remove_after+ (a date string) and +remove_with+ (a release)
def ignore_columns(*columns, remove_after:, remove_with:)
raise ArgumentError, 'Please indicate when we can stop ignoring columns with remove_after (date string YYYY-MM-DD), example: ignore_columns(:name, remove_after: \'2019-12-01\', remove_with: \'12.6\')' unless remove_after =~ Gitlab::Regex.utc_date_regex
raise ArgumentError, 'Please indicate in which release we can stop ignoring columns with remove_with, example: ignore_columns(:name, remove_after: \'2019-12-01\', remove_with: \'12.6\')' unless remove_with
self.ignored_columns += columns.flatten # rubocop:disable Cop/IgnoredColumns
columns.flatten.each do |column|
self.ignored_columns_details[column.to_sym] = ColumnIgnore.new(Date.parse(remove_after), remove_with)
end
end
alias_method :ignore_column, :ignore_columns
def ignored_columns_details
unless defined?(@ignored_columns_details)
IGNORE_COLUMN_MUTEX.synchronize do
@ignored_columns_details ||= superclass.try(:ignored_columns_details)&.dup || {}
end
end
@ignored_columns_details
end
IGNORE_COLUMN_MUTEX = Mutex.new
end
end
Loading
Loading
@@ -49,8 +49,7 @@ module UpdateProjectStatistics
attr = self.class.statistic_attribute
delta = read_attribute(attr).to_i - attribute_before_last_save(attr).to_i
 
update_project_statistics(delta)
schedule_namespace_aggregation_worker
schedule_update_project_statistic(delta)
end
 
def update_project_statistics_attribute_changed?
Loading
Loading
@@ -58,24 +57,35 @@ module UpdateProjectStatistics
end
 
def update_project_statistics_after_destroy
update_project_statistics(-read_attribute(self.class.statistic_attribute).to_i)
delta = -read_attribute(self.class.statistic_attribute).to_i
 
schedule_namespace_aggregation_worker
schedule_update_project_statistic(delta)
end
 
def project_destroyed?
project.pending_delete?
end
 
def update_project_statistics(delta)
ProjectStatistics.increment_statistic(project_id, self.class.project_statistics_name, delta)
end
def schedule_update_project_statistic(delta)
return if delta.zero?
if Feature.enabled?(:update_project_statistics_after_commit, default_enabled: true)
# Update ProjectStatistics after the transaction
run_after_commit do
ProjectStatistics.increment_statistic(
project_id, self.class.project_statistics_name, delta)
end
else
# Use legacy-way to update within transaction
ProjectStatistics.increment_statistic(
project_id, self.class.project_statistics_name, delta)
end
 
def schedule_namespace_aggregation_worker
run_after_commit do
next if project.nil?
 
Namespaces::ScheduleAggregationWorker.perform_async(project.namespace_id)
Namespaces::ScheduleAggregationWorker.perform_async(
project.namespace_id)
end
end
end
Loading
Loading
Loading
Loading
@@ -2,6 +2,7 @@
 
class DeployKey < Key
include FromUnion
include IgnorableColumns
 
has_many :deploy_keys_projects, inverse_of: :deploy_key, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :projects, through: :deploy_keys_projects
Loading
Loading
@@ -10,7 +11,7 @@ class DeployKey < Key
scope :are_public, -> { where(public: true) }
scope :with_projects, -> { includes(deploy_keys_projects: { project: [:route, :namespace] }) }
 
self.ignored_columns += %i[can_push]
ignore_column :can_push, remove_after: '2019-12-15', remove_with: '12.6'
 
accepts_nested_attributes_for :deploy_keys_projects
 
Loading
Loading
Loading
Loading
@@ -4,6 +4,8 @@ class Deployment < ApplicationRecord
include AtomicInternalId
include IidRoutes
include AfterCommitQueue
include UpdatedAtFilterable
include Gitlab::Utils::StrongMemoize
 
belongs_to :project, required: true
belongs_to :environment, required: true
Loading
Loading
@@ -125,6 +127,12 @@ class Deployment < ApplicationRecord
@scheduled_actions ||= deployable.try(:other_scheduled_actions)
end
 
def playable_build
strong_memoize(:playable_build) do
deployable.try(:playable?) ? deployable : nil
end
end
def includes_commit?(commit)
return false unless commit
 
Loading
Loading
# frozen_string_literal: true
 
module ConversationalDevelopmentIndex
module DevOpsScore
class Card
attr_accessor :metric, :title, :description, :feature, :blog, :docs
 
Loading
Loading
# frozen_string_literal: true
 
module ConversationalDevelopmentIndex
module DevOpsScore
class IdeaToProductionStep
attr_accessor :metric, :title, :features
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment