summaryrefslogtreecommitdiff
path: root/app/models
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/blob_viewer/gitlab_ci_yml.rb8
-rw-r--r--app/models/ci/build.rb52
-rw-r--r--app/models/ci/build_metadata.rb12
-rw-r--r--app/models/ci/pipeline.rb10
-rw-r--r--app/models/ci/runner.rb4
-rw-r--r--app/models/clusters/applications/knative.rb11
-rw-r--r--app/models/clusters/platforms/kubernetes.rb2
-rw-r--r--app/models/list.rb2
-rw-r--r--app/models/project.rb67
-rw-r--r--app/models/release.rb14
-rw-r--r--app/models/releases/link.rb22
-rw-r--r--app/models/releases/source.rb35
12 files changed, 192 insertions, 47 deletions
diff --git a/app/models/blob_viewer/gitlab_ci_yml.rb b/app/models/blob_viewer/gitlab_ci_yml.rb
index 655241c2808..11228e620c9 100644
--- a/app/models/blob_viewer/gitlab_ci_yml.rb
+++ b/app/models/blob_viewer/gitlab_ci_yml.rb
@@ -10,16 +10,16 @@ module BlobViewer
self.file_types = %i(gitlab_ci)
self.binary = false
- def validation_message(project, sha)
+ def validation_message(opts)
return @validation_message if defined?(@validation_message)
prepare!
- @validation_message = Gitlab::Ci::YamlProcessor.validation_message(blob.data, { project: project, sha: sha })
+ @validation_message = Gitlab::Ci::YamlProcessor.validation_message(blob.data, opts)
end
- def valid?(project, sha)
- validation_message(project, sha).blank?
+ def valid?(opts)
+ validation_message(opts).blank?
end
end
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index aeb35538d67..dc6f8ae1a7f 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -8,10 +8,15 @@ module Ci
include ObjectStorage::BackgroundMove
include Presentable
include Importable
+ include IgnorableColumn
include Gitlab::Utils::StrongMemoize
include Deployable
include HasRef
+ BuildArchivedError = Class.new(StandardError)
+
+ ignore_column :commands
+
belongs_to :project, inverse_of: :builds
belongs_to :runner
belongs_to :trigger_request
@@ -31,7 +36,7 @@ module Ci
has_one :"job_artifacts_#{key}", -> { where(file_type: value) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id
end
- has_one :metadata, class_name: 'Ci::BuildMetadata'
+ has_one :metadata, class_name: 'Ci::BuildMetadata', autosave: true
has_one :runner_session, class_name: 'Ci::BuildRunnerSession', validate: true, inverse_of: :build
accepts_nested_attributes_for :runner_session
@@ -273,11 +278,14 @@ module Ci
# degenerated build is one that cannot be run by Runner
def degenerated?
- self.options.nil?
+ self.options.blank?
end
def degenerate!
- self.update!(options: nil, yaml_variables: nil, commands: nil)
+ Build.transaction do
+ self.update!(options: nil, yaml_variables: nil)
+ self.metadata&.destroy
+ end
end
def archived?
@@ -624,11 +632,23 @@ module Ci
end
def when
- read_attribute(:when) || build_attributes_from_config[:when] || 'on_success'
+ read_attribute(:when) || 'on_success'
+ end
+
+ def options
+ read_metadata_attribute(:options, :config_options, {})
end
def yaml_variables
- read_attribute(:yaml_variables) || build_attributes_from_config[:yaml_variables] || []
+ read_metadata_attribute(:yaml_variables, :config_variables, [])
+ end
+
+ def options=(value)
+ write_metadata_attribute(:options, :config_options, value)
+ end
+
+ def yaml_variables=(value)
+ write_metadata_attribute(:yaml_variables, :config_variables, value)
end
def user_variables
@@ -904,8 +924,11 @@ module Ci
# have the old integer only format. This method returns the retry option
# normalized as a hash in 11.5+ format.
def normalized_retry
- value = options&.dig(:retry)
- value.is_a?(Integer) ? { max: value } : value.to_h
+ strong_memoize(:normalized_retry) do
+ value = options&.dig(:retry)
+ value = value.is_a?(Integer) ? { max: value } : value.to_h
+ value.with_indifferent_access
+ end
end
def build_attributes_from_config
@@ -929,5 +952,20 @@ module Ci
def project_destroyed?
project.pending_delete?
end
+
+ def read_metadata_attribute(legacy_key, metadata_key, default_value = nil)
+ read_attribute(legacy_key) || metadata&.read_attribute(metadata_key) || default_value
+ end
+
+ def write_metadata_attribute(legacy_key, metadata_key, value)
+ # save to metadata or this model depending on the state of feature flag
+ if Feature.enabled?(:ci_build_metadata_config)
+ ensure_metadata.write_attribute(metadata_key, value)
+ write_attribute(legacy_key, nil)
+ else
+ write_attribute(legacy_key, value)
+ metadata&.write_attribute(metadata_key, nil)
+ end
+ end
end
end
diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb
index 9d588b862bd..38390f49217 100644
--- a/app/models/ci/build_metadata.rb
+++ b/app/models/ci/build_metadata.rb
@@ -13,8 +13,12 @@ module Ci
belongs_to :build, class_name: 'Ci::Build'
belongs_to :project
+ before_create :set_build_project
+
validates :build, presence: true
- validates :project, presence: true
+
+ serialize :config_options, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :config_variables, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize
chronic_duration_attr_reader :timeout_human_readable, :timeout
@@ -33,5 +37,11 @@ module Ci
update(timeout: timeout, timeout_source: timeout_source)
end
+
+ private
+
+ def set_build_project
+ self.project_id ||= self.build.project_id
+ end
end
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 5b446e649a9..30a957b4117 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -509,7 +509,7 @@ module Ci
return @config_processor if defined?(@config_processor)
@config_processor ||= begin
- ::Gitlab::Ci::YamlProcessor.new(ci_yaml_file, { project: project, sha: sha })
+ ::Gitlab::Ci::YamlProcessor.new(ci_yaml_file, { project: project, sha: sha, user: user })
rescue Gitlab::Ci::YamlProcessor::ValidationError => e
self.yaml_errors = e.message
nil
@@ -648,7 +648,7 @@ module Ci
def all_merge_requests
@all_merge_requests ||=
if merge_request?
- project.merge_requests.where(id: merge_request.id)
+ project.merge_requests.where(id: merge_request_id)
else
project.merge_requests.where(source_branch: ref)
end
@@ -727,6 +727,12 @@ module Ci
def git_ref
if merge_request?
+ ##
+ # In the future, we're going to change this ref to
+ # merge request's merged reference, such as "refs/merge-requests/:iid/merge".
+ # In order to do that, we have to update GitLab-Runner's source pulling
+ # logic.
+ # See https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/1092
Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s
else
super
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 8249199e76f..5aae31de6e2 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -256,6 +256,10 @@ module Ci
end
end
+ def uncached_contacted_at
+ read_attribute(:contacted_at)
+ end
+
private
def cleanup_runner_queue
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index 0a3168afe68..c572c8bff44 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -19,6 +19,13 @@ module Clusters
self.reactive_cache_key = ->(knative) { [knative.class.model_name.singular, knative.id] }
+ def set_initial_status
+ return unless not_installable?
+ return unless verify_cluster?
+
+ self.status = 'installable'
+ end
+
state_machine :status do
after_transition any => [:installed] do |application|
application.run_after_commit do
@@ -99,6 +106,10 @@ module Clusters
def install_knative_metrics
["kubectl apply -f #{METRICS_CONFIG}"] if cluster.application_prometheus_available?
end
+
+ def verify_cluster?
+ cluster&.application_helm_available? && cluster&.platform_kubernetes_rbac?
+ end
end
end
end
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 0dc0c4f80d6..1cc170c8c4d 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -65,6 +65,8 @@ module Clusters
abac: 2
}
+ default_value_for :authorization_type, :rbac
+
def actual_namespace
if namespace.present?
namespace
diff --git a/app/models/list.rb b/app/models/list.rb
index 029685be927..682af761ba0 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -54,6 +54,6 @@ class List < ActiveRecord::Base
private
def can_be_destroyed
- destroyable?
+ throw(:abort) unless destroyable?
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index cd558752080..e2f010a0432 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -330,8 +330,8 @@ class Project < ActiveRecord::Base
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
validate :check_repository_path_availability, on: :update, if: ->(project) { project.renamed? }
- validate :visibility_level_allowed_by_group
- validate :visibility_level_allowed_as_fork
+ validate :visibility_level_allowed_by_group, if: -> { changes.has_key?(:visibility_level) }
+ validate :visibility_level_allowed_as_fork, if: -> { changes.has_key?(:visibility_level) }
validate :check_wiki_path_conflict
validate :validate_pages_https_only, if: -> { changes.has_key?(:pages_https_only) }
validates :repository_storage,
@@ -912,11 +912,16 @@ class Project < ActiveRecord::Base
def new_issuable_address(author, address_type)
return unless Gitlab::IncomingEmail.supports_issue_creation? && author
+ # check since this can come from a request parameter
+ return unless %w(issue merge_request).include?(address_type)
+
author.ensure_incoming_email_token!
- suffix = address_type == 'merge_request' ? '+merge-request' : ''
- Gitlab::IncomingEmail.reply_address(
- "#{full_path}#{suffix}+#{author.incoming_email_token}")
+ suffix = address_type.dasherize
+
+ # example: incoming+h5bp-html5-boilerplate-8-1234567890abcdef123456789-issue@localhost.com
+ # example: incoming+h5bp-html5-boilerplate-8-1234567890abcdef123456789-merge-request@localhost.com
+ Gitlab::IncomingEmail.reply_address("#{full_path_slug}-#{project_id}-#{author.incoming_email_token}-#{suffix}")
end
def build_commit_note(commit)
@@ -1700,6 +1705,13 @@ class Project < ActiveRecord::Base
.append(key: 'CI_PROJECT_VISIBILITY', value: visibility)
.concat(container_registry_variables)
.concat(auto_devops_variables)
+ .concat(api_variables)
+ end
+
+ def api_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables.append(key: 'CI_API_V4_URL', value: API::Helpers::Version.new('v4').root_url)
+ end
end
def container_registry_variables
@@ -1928,23 +1940,15 @@ class Project < ActiveRecord::Base
.where('project_authorizations.project_id = merge_requests.target_project_id')
.limit(1)
.select(1)
- source_of_merge_requests.opened
- .where(allow_collaboration: true)
- .where('EXISTS (?)', developer_access_exists)
+ merge_requests_allowing_collaboration.where('EXISTS (?)', developer_access_exists)
end
- def branch_allows_collaboration?(user, branch_name)
- return false unless user
-
- cache_key = "user:#{user.id}:#{branch_name}:branch_allows_push"
-
- memoized_results = strong_memoize(:branch_allows_collaboration) do
- Hash.new do |result, cache_key|
- result[cache_key] = fetch_branch_allows_collaboration?(user, branch_name)
- end
- end
+ def any_branch_allows_collaboration?(user)
+ fetch_branch_allows_collaboration(user)
+ end
- memoized_results[cache_key]
+ def branch_allows_collaboration?(user, branch_name)
+ fetch_branch_allows_collaboration(user, branch_name)
end
def licensed_features
@@ -2018,6 +2022,12 @@ class Project < ActiveRecord::Base
private
+ def merge_requests_allowing_collaboration(source_branch = nil)
+ relation = source_of_merge_requests.opened.where(allow_collaboration: true)
+ relation = relation.where(source_branch: source_branch) if source_branch
+ relation
+ end
+
def create_new_pool_repository
pool = begin
create_pool_repository!(shard: Shard.by_name(repository_storage), source_project: self)
@@ -2142,26 +2152,19 @@ class Project < ActiveRecord::Base
raise ex
end
- def fetch_branch_allows_collaboration?(user, branch_name)
- check_access = -> do
- next false if empty_repo?
+ def fetch_branch_allows_collaboration(user, branch_name = nil)
+ return false unless user
- merge_requests = source_of_merge_requests.opened
- .where(allow_collaboration: true)
+ Gitlab::SafeRequestStore.fetch("project-#{id}:branch-#{branch_name}:user-#{user.id}:branch_allows_collaboration") do
+ next false if empty_repo?
# Issue for N+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/49322
Gitlab::GitalyClient.allow_n_plus_1_calls do
- if branch_name
- merge_requests.find_by(source_branch: branch_name)&.can_be_merged_by?(user)
- else
- merge_requests.any? { |merge_request| merge_request.can_be_merged_by?(user) }
+ merge_requests_allowing_collaboration(branch_name).any? do |merge_request|
+ merge_request.can_be_merged_by?(user)
end
end
end
-
- Gitlab::SafeRequestStore.fetch("project-#{id}:branch-#{branch_name}:user-#{user.id}:branch_allows_collaboration") do
- check_access.call
- end
end
def services_templates
diff --git a/app/models/release.rb b/app/models/release.rb
index df3dfe1cf2f..0dae5c90394 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -10,6 +10,10 @@ class Release < ActiveRecord::Base
# releases prior to 11.7 have no author
belongs_to :author, class_name: 'User'
+ has_many :links, class_name: 'Releases::Link'
+
+ accepts_nested_attributes_for :links, allow_destroy: true
+
validates :description, :project, :tag, presence: true
scope :sorted, -> { order(created_at: :desc) }
@@ -26,6 +30,16 @@ class Release < ActiveRecord::Base
actual_tag.nil?
end
+ def assets_count
+ links.count + sources.count
+ end
+
+ def sources
+ strong_memoize(:sources) do
+ Releases::Source.all(project, tag)
+ end
+ end
+
private
def actual_sha
diff --git a/app/models/releases/link.rb b/app/models/releases/link.rb
new file mode 100644
index 00000000000..766cb2efff2
--- /dev/null
+++ b/app/models/releases/link.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Releases
+ class Link < ActiveRecord::Base
+ self.table_name = 'release_links'
+
+ belongs_to :release
+
+ validates :url, presence: true, url: true
+ validates :name, presence: true, uniqueness: { scope: :release }
+
+ scope :sorted, -> { order(created_at: :desc) }
+
+ def internal?
+ url.start_with?(release.project.web_url)
+ end
+
+ def external?
+ !internal?
+ end
+ end
+end
diff --git a/app/models/releases/source.rb b/app/models/releases/source.rb
new file mode 100644
index 00000000000..4d3d54457af
--- /dev/null
+++ b/app/models/releases/source.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Releases
+ class Source
+ include ActiveModel::Model
+
+ attr_accessor :project, :tag_name, :format
+
+ FORMATS = %w(zip tar.gz tar.bz2 tar).freeze
+
+ class << self
+ def all(project, tag_name)
+ Releases::Source::FORMATS.map do |format|
+ Releases::Source.new(project: project,
+ tag_name: tag_name,
+ format: format)
+ end
+ end
+ end
+
+ def url
+ Gitlab::Routing
+ .url_helpers
+ .project_archive_url(project,
+ id: File.join(tag_name, archive_prefix),
+ format: format)
+ end
+
+ private
+
+ def archive_prefix
+ "#{project.path}-#{tag_name.tr('/', '-')}"
+ end
+ end
+end