Skip to content
Snippets Groups Projects
Commit 914ea32e authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 3546e1bb
No related branches found
No related tags found
No related merge requests found
Showing
with 399 additions and 201 deletions
Loading
Loading
@@ -52,9 +52,15 @@ module Ci
 
has_many :auto_canceled_pipelines, class_name: 'Ci::Pipeline', foreign_key: 'auto_canceled_by_id'
has_many :auto_canceled_jobs, class_name: 'CommitStatus', foreign_key: 'auto_canceled_by_id'
has_many :sourced_pipelines, class_name: 'Ci::Sources::Pipeline', foreign_key: :source_pipeline_id
 
has_one :source_pipeline, class_name: 'Ci::Sources::Pipeline', inverse_of: :pipeline
has_one :chat_data, class_name: 'Ci::PipelineChatData'
 
has_many :triggered_pipelines, through: :sourced_pipelines, source: :pipeline
has_one :triggered_by_pipeline, through: :source_pipeline, source: :source_pipeline
has_one :source_job, through: :source_pipeline, source: :source_job
accepts_nested_attributes_for :variables, reject_if: :persisted?
 
delegate :id, to: :project, prefix: true
Loading
Loading
Loading
Loading
@@ -22,6 +22,7 @@ module Ci
schedule: 4,
api: 5,
external: 6,
pipeline: 7,
chat: 8,
merge_request_event: 10,
external_pull_request_event: 11
Loading
Loading
# frozen_string_literal: true
module Ci
module Sources
class Pipeline < ApplicationRecord
self.table_name = "ci_sources_pipelines"
belongs_to :project, class_name: "Project"
belongs_to :pipeline, class_name: "Ci::Pipeline", inverse_of: :source_pipeline
belongs_to :source_project, class_name: "Project", foreign_key: :source_project_id
belongs_to :source_job, class_name: "CommitStatus", foreign_key: :source_job_id
belongs_to :source_pipeline, class_name: "Ci::Pipeline", foreign_key: :source_pipeline_id
validates :project, presence: true
validates :pipeline, presence: true
validates :source_project, presence: true
validates :source_job, presence: true
validates :source_pipeline, presence: true
end
end
end
::Ci::Sources::Pipeline.prepend_if_ee('::EE::Ci::Sources::Pipeline')
Loading
Loading
@@ -259,6 +259,10 @@ class Group < Namespace
members_with_parents.maintainers.exists?(user_id: user)
end
 
def has_container_repositories?
container_repositories.exists?
end
# @deprecated
alias_method :has_master?, :has_maintainer?
 
Loading
Loading
Loading
Loading
@@ -297,6 +297,9 @@ class Project < ApplicationRecord
 
has_many :external_pull_requests, inverse_of: :project
 
has_many :sourced_pipelines, class_name: 'Ci::Sources::Pipeline', foreign_key: :source_project_id
has_many :source_pipelines, class_name: 'Ci::Sources::Pipeline', foreign_key: :project_id
has_one :pages_metadatum, class_name: 'ProjectPagesMetadatum', inverse_of: :project
 
accepts_nested_attributes_for :variables, allow_destroy: true
Loading
Loading
Loading
Loading
@@ -10,6 +10,7 @@ class PipelineDetailsEntity < PipelineEntity
expose :manual_actions, using: BuildActionEntity
expose :scheduled_actions, using: BuildActionEntity
end
end
 
PipelineDetailsEntity.prepend_if_ee('EE::PipelineDetailsEntity')
expose :triggered_by_pipeline, as: :triggered_by, with: TriggeredPipelineEntity
expose :triggered_pipelines, as: :triggered, using: TriggeredPipelineEntity
end
Loading
Loading
@@ -54,9 +54,9 @@ class PipelineSerializer < BaseSerializer
artifacts: {
project: [:route, { namespace: :route }]
}
}
},
{ triggered_by_pipeline: [:project, :user] },
{ triggered_pipelines: [:project, :user] }
]
end
end
PipelineSerializer.prepend_if_ee('EE::PipelineSerializer')
# frozen_string_literal: true
class TriggeredPipelineEntity < Grape::Entity
include RequestAwareEntity
MAX_EXPAND_DEPTH = 3
expose :id
expose :user, using: UserEntity
expose :active?, as: :active
expose :coverage
expose :source
expose :path do |pipeline|
project_pipeline_path(pipeline.project, pipeline)
end
expose :details do
expose :detailed_status, as: :status, with: DetailedStatusEntity
expose :ordered_stages,
as: :stages, using: StageEntity,
if: -> (_, opts) { can_read_details? && expand?(opts) }
end
expose :triggered_by_pipeline,
as: :triggered_by, with: TriggeredPipelineEntity,
if: -> (_, opts) { can_read_details? && expand_for_path?(opts) }
expose :triggered_pipelines,
as: :triggered, using: TriggeredPipelineEntity,
if: -> (_, opts) { can_read_details? && expand_for_path?(opts) }
expose :project, using: ProjectEntity
private
alias_method :pipeline, :object
def can_read_details?
can?(request.current_user, :read_pipeline, pipeline)
end
def detailed_status
pipeline.detailed_status(request.current_user)
end
def expand?(opts)
opts[:expanded].to_a.include?(pipeline.id)
end
def expand_for_path?(opts)
# The `opts[:attr_path]` holds a list of all `exposes` in path
# The check ensures that we always expand only `triggered_by`, `triggered_by`, ...
# but not the `triggered_by`, `triggered` which would result in dead loop
attr_path = opts[:attr_path]
current_expose = attr_path.last
# We expand at most to depth of MAX_DEPTH
# We ensure that we expand in one direction: triggered_by,... or triggered, ...
attr_path.length < MAX_EXPAND_DEPTH &&
attr_path.all?(current_expose) &&
expand?(opts)
end
end
Loading
Loading
@@ -38,11 +38,34 @@ module Ci
end
 
def create_pipeline_from_job(job)
# overridden in EE
# this check is to not leak the presence of the project if user cannot read it
return unless can?(job.user, :read_project, project)
return error("400 Job has to be running", 400) unless job.running?
pipeline = Ci::CreatePipelineService.new(project, job.user, ref: params[:ref])
.execute(:pipeline, ignore_skip_ci: true) do |pipeline|
source = job.sourced_pipelines.build(
source_pipeline: job.pipeline,
source_project: job.project,
pipeline: pipeline,
project: project)
pipeline.source_pipeline = source
pipeline.variables.build(variables)
end
if pipeline.persisted?
success(pipeline: pipeline)
else
error(pipeline.errors.messages, 400)
end
end
 
def job_from_token
# overridden in EE
strong_memoize(:job) do
Ci::Build.find_by_token(params[:token].to_s)
end
end
 
def variables
Loading
Loading
@@ -52,5 +75,3 @@ module Ci
end
end
end
Ci::PipelineTriggerService.prepend_if_ee('EE::Ci::PipelineTriggerService')
Loading
Loading
@@ -7,7 +7,8 @@ module Groups
namespace_with_same_path: s_('TransferGroup|The parent group already has a subgroup with the same path.'),
group_is_already_root: s_('TransferGroup|Group is already a root group.'),
same_parent_as_current: s_('TransferGroup|Group is already associated to the parent group.'),
invalid_policies: s_("TransferGroup|You don't have enough permissions.")
invalid_policies: s_("TransferGroup|You don't have enough permissions."),
group_contains_images: s_('TransferGroup|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again.')
}.freeze
 
TransferError = Class.new(StandardError)
Loading
Loading
@@ -46,6 +47,7 @@ module Groups
raise_transfer_error(:same_parent_as_current) if same_parent?
raise_transfer_error(:invalid_policies) unless valid_policies?
raise_transfer_error(:namespace_with_same_path) if namespace_with_same_path?
raise_transfer_error(:group_contains_images) if group_projects_contain_registry_images?
end
 
def group_is_already_root?
Loading
Loading
@@ -72,6 +74,10 @@ module Groups
end
# rubocop: enable CodeReuse/ActiveRecord
 
def group_projects_contain_registry_images?
@group.has_container_repositories?
end
def update_group_attributes
if @new_parent_group && @new_parent_group.visibility_level < @group.visibility_level
update_children_and_projects_visibility
Loading
Loading
Loading
Loading
@@ -8,6 +8,11 @@ module Groups
reject_parent_id!
remove_unallowed_params
 
if renaming_group_with_container_registry_images?
group.errors.add(:base, container_images_error)
return false
end
return false unless valid_visibility_level_change?(group, params[:visibility_level])
 
return false unless valid_share_with_group_lock_change?
Loading
Loading
@@ -35,6 +40,17 @@ module Groups
# overridden in EE
end
 
def renaming_group_with_container_registry_images?
new_path = params[:path]
new_path && new_path != group.path &&
group.has_container_repositories?
end
def container_images_error
s_("GroupSettings|Cannot update the path because there are projects under this group that contain Docker images in their Container Registry. Please remove the images from your projects first and try again.")
end
def after_update
if group.previous_changes.include?(:visibility_level) && group.private?
# don't enqueue immediately to prevent todos removal in case of a mistake
Loading
Loading
This diff is collapsed.
---
title: Prevents a group path change when a project inside the group has container
registry images
merge_request: 17583
author:
type: fixed
---
title: Allow cross-project pipeline triggering with CI_JOB_TOKEN in core
merge_request: 17251
author:
type: added
Loading
Loading
@@ -34,7 +34,9 @@ module Gitlab
@mutex.synchronize do
break thread if thread?
 
@thread = Thread.new { start_working }
if start_working
@thread = Thread.new { run_thread }
end
end
end
 
Loading
Loading
@@ -57,10 +59,18 @@ module Gitlab
 
private
 
# Executed in lock context before starting thread
# Needs to return success
def start_working
true
end
# Executed in separate thread
def run_thread
raise NotImplementedError
end
 
# Executed in lock context
def stop_working
# no-ops
end
Loading
Loading
# frozen_string_literal: true
require 'net/http'
require 'json'
module Gitlab
module Danger
module RequestHelper
HTTPError = Class.new(RuntimeError)
# @param [String] url
def self.http_get_json(url)
rsp = Net::HTTP.get_response(URI.parse(url))
unless rsp.is_a?(Net::HTTPOK)
raise HTTPError, "Failed to read #{url}: #{rsp.code} #{rsp.message}"
end
JSON.parse(rsp.body)
end
end
end
end
# frozen_string_literal: true
 
require 'net/http'
require 'json'
require 'cgi'
require_relative 'teammate'
 
module Gitlab
module Danger
module Roulette
ROULETTE_DATA_URL = 'https://about.gitlab.com/roulette.json'
HTTPError = Class.new(RuntimeError)
 
# Looks up the current list of GitLab team members and parses it into a
# useful form
Loading
Loading
@@ -19,7 +14,7 @@ module Gitlab
def team
@team ||=
begin
data = http_get_json(ROULETTE_DATA_URL)
data = Gitlab::Danger::RequestHelper.http_get_json(ROULETTE_DATA_URL)
data.map { |hash| ::Gitlab::Danger::Teammate.new(hash) }
rescue JSON::ParserError
raise "Failed to parse JSON response from #{ROULETTE_DATA_URL}"
Loading
Loading
@@ -44,6 +39,7 @@ module Gitlab
 
# Known issue: If someone is rejected due to OOO, and then becomes not OOO, the
# selection will change on next spin
# @param [Array<Teammate>] people
def spin_for_person(people, random:)
people.shuffle(random: random)
.find(&method(:valid_person?))
Loading
Loading
@@ -51,32 +47,17 @@ module Gitlab
 
private
 
# @param [Teammate] person
# @return [Boolean]
def valid_person?(person)
!mr_author?(person) && !out_of_office?(person)
!mr_author?(person) && !person.out_of_office?
end
 
# @param [Teammate] person
# @return [Boolean]
def mr_author?(person)
person.username == gitlab.mr_author
end
def out_of_office?(person)
username = CGI.escape(person.username)
api_endpoint = "https://gitlab.com/api/v4/users/#{username}/status"
response = http_get_json(api_endpoint)
response["message"]&.match?(/OOO/i)
rescue HTTPError, JSON::ParserError
false # this is no worse than not checking for OOO
end
def http_get_json(url)
rsp = Net::HTTP.get_response(URI.parse(url))
unless rsp.is_a?(Net::HTTPSuccess)
raise HTTPError, "Failed to read #{url}: #{rsp.code} #{rsp.message}"
end
JSON.parse(rsp.body)
end
end
end
end
# frozen_string_literal: true
 
require 'cgi'
module Gitlab
module Danger
class Teammate
Loading
Loading
@@ -34,6 +36,18 @@ module Gitlab
has_capability?(project, category, :maintainer, labels)
end
 
def status
api_endpoint = "https://gitlab.com/api/v4/users/#{CGI.escape(username)}/status"
@status ||= Gitlab::Danger::RequestHelper.http_get_json(api_endpoint)
rescue Gitlab::Danger::RequestHelper::HTTPError, JSON::ParserError
nil # better no status than a crashing Danger
end
# @return [Boolean]
def out_of_office?
status&.dig("message")&.match?(/OOO/i) || false
end
private
 
def has_capability?(project, category, kind, labels)
Loading
Loading
Loading
Loading
@@ -40,7 +40,14 @@ module Gitlab
::Gitlab::HealthChecks::Probes::Liveness.new, req, res)
end
server.mount '/', Rack::Handler::WEBrick, rack_app
server.start
true
end
def run_thread
server&.start
rescue IOError
# ignore forcibily closed servers
end
 
def stop_working
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