Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmit Rathi <amit@hypertrack.io>2018-11-12 09:36:59 +0300
committerAmit Rathi <amit@hypertrack.io>2018-11-12 09:36:59 +0300
commitc2407dab3e3ba1471ccebc008179f829d21fe3ce (patch)
treeb6f7165dbe4abb93dab5dde04fd4d6403a273eb0 /app/services
parent8837519445c319a699e0f3ced1c6912c839f3389 (diff)
parentec1d4243b2dbca7df6b793b412717f9b5b3db998 (diff)
Merge branch 'master' into certmanager-temp
Diffstat (limited to 'app/services')
-rw-r--r--app/services/auth/container_registry_authentication_service.rb2
-rw-r--r--app/services/boards/issues/move_service.rb4
-rw-r--r--app/services/ci/register_job_service.rb5
-rw-r--r--app/services/clusters/applications/check_installation_progress_service.rb6
-rw-r--r--app/services/clusters/applications/create_service.rb14
-rw-r--r--app/services/clusters/applications/install_service.rb8
-rw-r--r--app/services/clusters/create_service.rb26
-rw-r--r--app/services/clusters/gcp/finalize_creation_service.rb23
-rw-r--r--app/services/clusters/gcp/kubernetes.rb11
-rw-r--r--app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb52
-rw-r--r--app/services/clusters/gcp/kubernetes/create_service_account_service.rb78
-rw-r--r--app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb8
-rw-r--r--app/services/commits/change_service.rb8
-rw-r--r--app/services/commits/commit_patch_service.rb61
-rw-r--r--app/services/commits/create_service.rb7
-rw-r--r--app/services/create_deployment_service.rb74
-rw-r--r--app/services/issuable_base_service.rb12
-rw-r--r--app/services/issues/update_service.rb14
-rw-r--r--app/services/keys/destroy_service.rb2
-rw-r--r--app/services/members/base_service.rb2
-rw-r--r--app/services/merge_requests/build_service.rb6
-rw-r--r--app/services/merge_requests/get_urls_service.rb4
-rw-r--r--app/services/merge_requests/refresh_service.rb23
-rw-r--r--app/services/merge_requests/reload_diffs_service.rb5
-rw-r--r--app/services/merge_requests/update_service.rb14
-rw-r--r--app/services/milestones/destroy_service.rb2
-rw-r--r--app/services/notification_service.rb41
-rw-r--r--app/services/projects/move_project_authorizations_service.rb2
-rw-r--r--app/services/projects/move_project_group_links_service.rb2
-rw-r--r--app/services/projects/move_project_members_service.rb2
-rw-r--r--app/services/quick_actions/interpret_service.rb8
-rw-r--r--app/services/search/group_service.rb2
-rw-r--r--app/services/submodules/update_service.rb38
-rw-r--r--app/services/update_deployment_service.rb53
34 files changed, 468 insertions, 151 deletions
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index 893b37b831a..f764536e762 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -99,7 +99,7 @@ module Auth
##
# Because we do not have two way communication with registry yet,
# we create a container repository image resource when push to the
- # registry is successfuly authorized.
+ # registry is successfully authorized.
#
def ensure_container_repository!(path, actions)
return if path.has_repository?
diff --git a/app/services/boards/issues/move_service.rb b/app/services/boards/issues/move_service.rb
index 7dd87034410..43a26f4264e 100644
--- a/app/services/boards/issues/move_service.rb
+++ b/app/services/boards/issues/move_service.rb
@@ -70,10 +70,8 @@ module Boards
label_ids =
if moving_to_list.movable?
moving_from_list.label_id
- elsif board.group_board?
- ::Label.on_group_boards(parent.id).pluck(:label_id)
else
- ::Label.on_project_boards(parent.id).pluck(:label_id)
+ ::Label.on_board(board.id).pluck(:label_id)
end
Array(label_ids).compact
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index 5a7be921389..e06f1c05843 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -82,6 +82,11 @@ module Ci
return false
end
+ if build.archived?
+ build.drop!(:archived_failure)
+ return false
+ end
+
build.run!
true
end
diff --git a/app/services/clusters/applications/check_installation_progress_service.rb b/app/services/clusters/applications/check_installation_progress_service.rb
index 5959a337489..8231eaa324f 100644
--- a/app/services/clusters/applications/check_installation_progress_service.rb
+++ b/app/services/clusters/applications/check_installation_progress_service.rb
@@ -14,7 +14,8 @@ module Clusters
else
check_timeout
end
- rescue Kubeclient::HttpError
+ rescue Kubeclient::HttpError => e
+ Rails.logger.error "Kubernetes error: #{e.class.name} #{e.message}"
app.make_errored!("Kubernetes error") unless app.errored?
end
@@ -53,7 +54,8 @@ module Clusters
def remove_installation_pod
helm_api.delete_pod!(install_command.pod_name)
- rescue
+ rescue => e
+ Rails.logger.error "Kubernetes error: #{e.class.name} #{e.message}"
# no-op
end
diff --git a/app/services/clusters/applications/create_service.rb b/app/services/clusters/applications/create_service.rb
index 933f9ad1bd2..8f1b247343d 100644
--- a/app/services/clusters/applications/create_service.rb
+++ b/app/services/clusters/applications/create_service.rb
@@ -47,10 +47,20 @@ module Clusters
{
"helm" => -> (cluster) { cluster.application_helm || cluster.build_application_helm },
"ingress" => -> (cluster) { cluster.application_ingress || cluster.build_application_ingress },
- "cert_manager" => -> (cluster) { cluster.application_cert_manager || cluster.build_application_cert_manager },
+ "cert_manager" => -> (cluster) { cluster.application_cert_manager || cluster.build_application_cert_manager }
+ }.tap do |hash|
+ hash.merge!(project_builders) if cluster.project_type?
+ end
+ end
+
+ # These applications will need extra configuration to enable them to work
+ # with groups of projects
+ def project_builders
+ {
"prometheus" => -> (cluster) { cluster.application_prometheus || cluster.build_application_prometheus },
"runner" => -> (cluster) { cluster.application_runner || cluster.build_application_runner },
- "jupyter" => -> (cluster) { cluster.application_jupyter || cluster.build_application_jupyter }
+ "jupyter" => -> (cluster) { cluster.application_jupyter || cluster.build_application_jupyter },
+ "knative" => -> (cluster) { cluster.application_knative || cluster.build_application_knative }
}
end
diff --git a/app/services/clusters/applications/install_service.rb b/app/services/clusters/applications/install_service.rb
index cf2c5952ad6..8c477fd14f3 100644
--- a/app/services/clusters/applications/install_service.rb
+++ b/app/services/clusters/applications/install_service.rb
@@ -15,14 +15,10 @@ module Clusters
ClusterWaitForAppInstallationWorker.perform_in(
ClusterWaitForAppInstallationWorker::INTERVAL, app.name, app.id)
rescue Kubeclient::HttpError => e
- Gitlab::AppLogger.info('HttpError---- IN execute installing ----')
- Gitlab::AppLogger.error(e)
- Gitlab::AppLogger.error(e.backtrace.join("\n"))
+ Rails.logger.error "Kubernetes error: #{e.class.name} #{e.message}"
app.make_errored!("Kubernetes error.")
rescue StandardError => e
- Gitlab::AppLogger.info('StandardError---- IN execute installing ----')
- Gitlab::AppLogger.error(e)
- Gitlab::AppLogger.error(e.backtrace.join("\n"))
+ Rails.logger.error "Can't start installation process: #{e.class.name} #{e.message}"
app.make_errored!("Can't start installation process.")
end
end
diff --git a/app/services/clusters/create_service.rb b/app/services/clusters/create_service.rb
index cd843b8ffa8..5a9da053780 100644
--- a/app/services/clusters/create_service.rb
+++ b/app/services/clusters/create_service.rb
@@ -8,10 +8,11 @@ module Clusters
@current_user, @params = user, params.dup
end
- def execute(project:, access_token: nil)
- raise ArgumentError, _('Instance does not support multiple Kubernetes clusters') unless can_create_cluster?(project)
+ def execute(access_token: nil)
+ raise ArgumentError, 'Unknown clusterable provided' unless clusterable
+ raise ArgumentError, _('Instance does not support multiple Kubernetes clusters') unless can_create_cluster?
- cluster_params = params.merge(user: current_user, cluster_type: :project_type, projects: [project])
+ cluster_params = params.merge(user: current_user).merge(clusterable_params)
cluster_params[:provider_gcp_attributes].try do |provider|
provider[:access_token] = access_token
end
@@ -27,9 +28,24 @@ module Clusters
Clusters::Cluster.create(cluster_params)
end
+ def clusterable
+ @clusterable ||= params.delete(:clusterable)
+ end
+
+ def clusterable_params
+ case clusterable
+ when ::Project
+ { cluster_type: :project_type, projects: [clusterable] }
+ when ::Group
+ { cluster_type: :group_type, groups: [clusterable] }
+ else
+ raise NotImplementedError
+ end
+ end
+
# EE would override this method
- def can_create_cluster?(project)
- project.clusters.empty?
+ def can_create_cluster?
+ clusterable.clusters.empty?
end
end
end
diff --git a/app/services/clusters/gcp/finalize_creation_service.rb b/app/services/clusters/gcp/finalize_creation_service.rb
index 6ee63db8eb9..3df43657fa0 100644
--- a/app/services/clusters/gcp/finalize_creation_service.rb
+++ b/app/services/clusters/gcp/finalize_creation_service.rb
@@ -11,8 +11,9 @@ module Clusters
configure_provider
create_gitlab_service_account!
configure_kubernetes
-
cluster.save!
+ configure_project_service_account
+
rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
provider.make_errored!("Failed to request to CloudPlatform; #{e.message}")
rescue Kubeclient::HttpError => e
@@ -24,7 +25,10 @@ module Clusters
private
def create_gitlab_service_account!
- Clusters::Gcp::Kubernetes::CreateServiceAccountService.new(kube_client, rbac: create_rbac_cluster?).execute
+ Clusters::Gcp::Kubernetes::CreateServiceAccountService.gitlab_creator(
+ kube_client,
+ rbac: create_rbac_cluster?
+ ).execute
end
def configure_provider
@@ -44,7 +48,20 @@ module Clusters
end
def request_kubernetes_token
- Clusters::Gcp::Kubernetes::FetchKubernetesTokenService.new(kube_client).execute
+ Clusters::Gcp::Kubernetes::FetchKubernetesTokenService.new(
+ kube_client,
+ Clusters::Gcp::Kubernetes::GITLAB_ADMIN_TOKEN_NAME,
+ Clusters::Gcp::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAMESPACE
+ ).execute
+ end
+
+ def configure_project_service_account
+ kubernetes_namespace = cluster.find_or_initialize_kubernetes_namespace(cluster.cluster_project)
+
+ Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService.new(
+ cluster: cluster,
+ kubernetes_namespace: kubernetes_namespace
+ ).execute
end
def authorization_type
diff --git a/app/services/clusters/gcp/kubernetes.rb b/app/services/clusters/gcp/kubernetes.rb
index d014d73b3e8..90ed529670c 100644
--- a/app/services/clusters/gcp/kubernetes.rb
+++ b/app/services/clusters/gcp/kubernetes.rb
@@ -3,11 +3,12 @@
module Clusters
module Gcp
module Kubernetes
- SERVICE_ACCOUNT_NAME = 'gitlab'
- SERVICE_ACCOUNT_NAMESPACE = 'default'
- SERVICE_ACCOUNT_TOKEN_NAME = 'gitlab-token'
- CLUSTER_ROLE_BINDING_NAME = 'gitlab-admin'
- CLUSTER_ROLE_NAME = 'cluster-admin'
+ GITLAB_SERVICE_ACCOUNT_NAME = 'gitlab'
+ GITLAB_SERVICE_ACCOUNT_NAMESPACE = 'default'
+ GITLAB_ADMIN_TOKEN_NAME = 'gitlab-token'
+ GITLAB_CLUSTER_ROLE_BINDING_NAME = 'gitlab-admin'
+ GITLAB_CLUSTER_ROLE_NAME = 'cluster-admin'
+ PROJECT_CLUSTER_ROLE_NAME = 'edit'
end
end
end
diff --git a/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb b/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb
new file mode 100644
index 00000000000..2b607681082
--- /dev/null
+++ b/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Gcp
+ module Kubernetes
+ class CreateOrUpdateNamespaceService
+ def initialize(cluster:, kubernetes_namespace:)
+ @cluster = cluster
+ @kubernetes_namespace = kubernetes_namespace
+ @platform = cluster.platform
+ end
+
+ def execute
+ configure_kubernetes_namespace
+ create_project_service_account
+ configure_kubernetes_token
+
+ kubernetes_namespace.save!
+ end
+
+ private
+
+ attr_reader :cluster, :kubernetes_namespace, :platform
+
+ def configure_kubernetes_namespace
+ kubernetes_namespace.configure_predefined_credentials
+ end
+
+ def create_project_service_account
+ Clusters::Gcp::Kubernetes::CreateServiceAccountService.namespace_creator(
+ platform.kubeclient,
+ service_account_name: kubernetes_namespace.service_account_name,
+ service_account_namespace: kubernetes_namespace.namespace,
+ rbac: platform.rbac?
+ ).execute
+ end
+
+ def configure_kubernetes_token
+ kubernetes_namespace.service_account_token = fetch_service_account_token
+ end
+
+ def fetch_service_account_token
+ Clusters::Gcp::Kubernetes::FetchKubernetesTokenService.new(
+ platform.kubeclient,
+ kubernetes_namespace.token_name,
+ kubernetes_namespace.namespace
+ ).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/clusters/gcp/kubernetes/create_service_account_service.rb b/app/services/clusters/gcp/kubernetes/create_service_account_service.rb
index d17744591e6..dfc4bf7a358 100644
--- a/app/services/clusters/gcp/kubernetes/create_service_account_service.rb
+++ b/app/services/clusters/gcp/kubernetes/create_service_account_service.rb
@@ -4,46 +4,96 @@ module Clusters
module Gcp
module Kubernetes
class CreateServiceAccountService
- attr_reader :kubeclient, :rbac
-
- def initialize(kubeclient, rbac:)
+ def initialize(kubeclient, service_account_name:, service_account_namespace:, token_name:, rbac:, namespace_creator: false, role_binding_name: nil)
@kubeclient = kubeclient
+ @service_account_name = service_account_name
+ @service_account_namespace = service_account_namespace
+ @token_name = token_name
@rbac = rbac
+ @namespace_creator = namespace_creator
+ @role_binding_name = role_binding_name
+ end
+
+ def self.gitlab_creator(kubeclient, rbac:)
+ self.new(
+ kubeclient,
+ service_account_name: Clusters::Gcp::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAME,
+ service_account_namespace: Clusters::Gcp::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAMESPACE,
+ token_name: Clusters::Gcp::Kubernetes::GITLAB_ADMIN_TOKEN_NAME,
+ rbac: rbac
+ )
+ end
+
+ def self.namespace_creator(kubeclient, service_account_name:, service_account_namespace:, rbac:)
+ self.new(
+ kubeclient,
+ service_account_name: service_account_name,
+ service_account_namespace: service_account_namespace,
+ token_name: "#{service_account_namespace}-token",
+ rbac: rbac,
+ namespace_creator: true,
+ role_binding_name: "gitlab-#{service_account_namespace}"
+ )
end
def execute
+ ensure_project_namespace_exists if namespace_creator
kubeclient.create_service_account(service_account_resource)
kubeclient.create_secret(service_account_token_resource)
- kubeclient.create_cluster_role_binding(cluster_role_binding_resource) if rbac
+ create_role_or_cluster_role_binding if rbac
end
private
+ attr_reader :kubeclient, :service_account_name, :service_account_namespace, :token_name, :rbac, :namespace_creator, :role_binding_name
+
+ def ensure_project_namespace_exists
+ Gitlab::Kubernetes::Namespace.new(
+ service_account_namespace,
+ kubeclient
+ ).ensure_exists!
+ end
+
+ def create_role_or_cluster_role_binding
+ if namespace_creator
+ kubeclient.create_role_binding(role_binding_resource)
+ else
+ kubeclient.create_cluster_role_binding(cluster_role_binding_resource)
+ end
+ end
+
def service_account_resource
- Gitlab::Kubernetes::ServiceAccount.new(service_account_name, service_account_namespace).generate
+ Gitlab::Kubernetes::ServiceAccount.new(
+ service_account_name,
+ service_account_namespace
+ ).generate
end
def service_account_token_resource
Gitlab::Kubernetes::ServiceAccountToken.new(
- SERVICE_ACCOUNT_TOKEN_NAME, service_account_name, service_account_namespace).generate
+ token_name,
+ service_account_name,
+ service_account_namespace
+ ).generate
end
def cluster_role_binding_resource
subjects = [{ kind: 'ServiceAccount', name: service_account_name, namespace: service_account_namespace }]
Gitlab::Kubernetes::ClusterRoleBinding.new(
- CLUSTER_ROLE_BINDING_NAME,
- CLUSTER_ROLE_NAME,
+ Clusters::Gcp::Kubernetes::GITLAB_CLUSTER_ROLE_BINDING_NAME,
+ Clusters::Gcp::Kubernetes::GITLAB_CLUSTER_ROLE_NAME,
subjects
).generate
end
- def service_account_name
- SERVICE_ACCOUNT_NAME
- end
-
- def service_account_namespace
- SERVICE_ACCOUNT_NAMESPACE
+ def role_binding_resource
+ Gitlab::Kubernetes::RoleBinding.new(
+ name: role_binding_name,
+ role_name: Clusters::Gcp::Kubernetes::PROJECT_CLUSTER_ROLE_NAME,
+ namespace: service_account_namespace,
+ service_account_name: service_account_name
+ ).generate
end
end
end
diff --git a/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb b/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb
index 9e09345c8dc..277cc4b788d 100644
--- a/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb
+++ b/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb
@@ -4,10 +4,12 @@ module Clusters
module Gcp
module Kubernetes
class FetchKubernetesTokenService
- attr_reader :kubeclient
+ attr_reader :kubeclient, :service_account_token_name, :namespace
- def initialize(kubeclient)
+ def initialize(kubeclient, service_account_token_name, namespace)
@kubeclient = kubeclient
+ @service_account_token_name = service_account_token_name
+ @namespace = namespace
end
def execute
@@ -18,7 +20,7 @@ module Clusters
private
def get_secret
- kubeclient.get_secret(SERVICE_ACCOUNT_TOKEN_NAME, SERVICE_ACCOUNT_NAMESPACE).as_json
+ kubeclient.get_secret(service_account_token_name, namespace).as_json
rescue Kubeclient::HttpError => err
raise err unless err.error_code == 404
diff --git a/app/services/commits/change_service.rb b/app/services/commits/change_service.rb
index 2fbd442fc2e..fbf71f02837 100644
--- a/app/services/commits/change_service.rb
+++ b/app/services/commits/change_service.rb
@@ -24,8 +24,12 @@ module Commits
start_project: @start_project,
start_branch_name: @start_branch)
rescue Gitlab::Git::Repository::CreateTreeError
- error_msg = "Sorry, we cannot #{action.to_s.dasherize} this #{@commit.change_type_title(current_user)} automatically.
- This #{@commit.change_type_title(current_user)} may already have been #{action.to_s.dasherize}ed, or a more recent commit may have updated some of its content."
+ act = action.to_s.dasherize
+ type = @commit.change_type_title(current_user)
+
+ error_msg = "Sorry, we cannot #{act} this #{type} automatically. " \
+ "This #{type} may already have been #{act}ed, or a more recent " \
+ "commit may have updated some of its content."
raise ChangeError, error_msg
end
end
diff --git a/app/services/commits/commit_patch_service.rb b/app/services/commits/commit_patch_service.rb
new file mode 100644
index 00000000000..9253cfaac20
--- /dev/null
+++ b/app/services/commits/commit_patch_service.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Commits
+ class CommitPatchService < CreateService
+ # Requires:
+ # - project: `Project` to be committed into
+ # - user: `User` that will be the committer
+ # - params:
+ # - branch_name: `String` the branch that will be committed into
+ # - start_branch: `String` the branch that will will started from
+ # - patches: `Gitlab::Git::Patches::Collection` that contains the patches
+ def initialize(*args)
+ super
+
+ @patches = Gitlab::Git::Patches::Collection.new(Array(params[:patches]))
+ end
+
+ private
+
+ def new_branch?
+ !repository.branch_exists?(@branch_name)
+ end
+
+ def create_commit!
+ if @start_branch && new_branch?
+ prepare_branch!
+ end
+
+ Gitlab::Git::Patches::CommitPatches
+ .new(current_user, project.repository, @branch_name, @patches)
+ .commit
+ end
+
+ def prepare_branch!
+ branch_result = CreateBranchService.new(project, current_user)
+ .execute(@branch_name, @start_branch)
+
+ if branch_result[:status] != :success
+ raise ChangeError, branch_result[:message]
+ end
+ end
+
+ # Overridden from the Commits::CreateService, to skip some validations we
+ # don't need:
+ # - validate_on_branch!
+ # Not needed, the patches are applied on top of HEAD if the branch did not
+ # exist
+ # - validate_branch_existence!
+ # Not needed because we continue applying patches on the branch if it
+ # already existed, and create it if it did not exist.
+ def validate!
+ validate_patches!
+ validate_new_branch_name! if new_branch?
+ validate_permissions!
+ end
+
+ def validate_patches!
+ raise_error("Patches are too big") unless @patches.valid_size?
+ end
+ end
+end
diff --git a/app/services/commits/create_service.rb b/app/services/commits/create_service.rb
index 3ce9acc833c..34593e12bd5 100644
--- a/app/services/commits/create_service.rb
+++ b/app/services/commits/create_service.rb
@@ -19,7 +19,12 @@ module Commits
new_commit = create_commit!
success(result: new_commit)
- rescue ValidationError, ChangeError, Gitlab::Git::Index::IndexError, Gitlab::Git::CommitError, Gitlab::Git::PreReceiveError => ex
+ rescue ValidationError,
+ ChangeError,
+ Gitlab::Git::Index::IndexError,
+ Gitlab::Git::CommitError,
+ Gitlab::Git::PreReceiveError,
+ Gitlab::Git::CommandError => ex
error(ex.message)
end
diff --git a/app/services/create_deployment_service.rb b/app/services/create_deployment_service.rb
deleted file mode 100644
index bb3f605da28..00000000000
--- a/app/services/create_deployment_service.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDeploymentService
- attr_reader :job
-
- delegate :expanded_environment_name,
- :variables,
- :project,
- to: :job
-
- def initialize(job)
- @job = job
- end
-
- def execute
- return unless executable?
-
- ActiveRecord::Base.transaction do
- environment.external_url = expanded_environment_url if
- expanded_environment_url
-
- environment.fire_state_event(action)
-
- break unless environment.save
- break if environment.stopped?
-
- deploy.tap(&:update_merge_request_metrics!)
- end
- end
-
- private
-
- def executable?
- project && job.environment.present? && environment
- end
-
- def deploy
- project.deployments.create(
- environment: environment,
- ref: job.ref,
- tag: job.tag,
- sha: job.sha,
- user: job.user,
- deployable: job,
- on_stop: on_stop)
- end
-
- def environment
- @environment ||= job.persisted_environment
- end
-
- def environment_options
- @environment_options ||= job.options&.dig(:environment) || {}
- end
-
- def expanded_environment_url
- return @expanded_environment_url if defined?(@expanded_environment_url)
-
- @expanded_environment_url =
- ExpandVariables.expand(environment_url, variables) if environment_url
- end
-
- def environment_url
- environment_options[:url]
- end
-
- def on_stop
- environment_options[:on_stop]
- end
-
- def action
- environment_options[:action] || 'start'
- end
-end
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 3e8b9f84042..e32e262ac31 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -3,6 +3,14 @@
class IssuableBaseService < BaseService
private
+ attr_accessor :params, :skip_milestone_email
+
+ def initialize(project, user = nil, params = {})
+ super
+
+ @skip_milestone_email = @params.delete(:skip_milestone_email)
+ end
+
def filter_params(issuable)
ability_name = :"admin_#{issuable.to_ability_name}"
@@ -118,12 +126,12 @@ class IssuableBaseService < BaseService
merge_quick_actions_into_params!(issuable)
end
- def merge_quick_actions_into_params!(issuable)
+ def merge_quick_actions_into_params!(issuable, only: nil)
original_description = params.fetch(:description, issuable.description)
description, command_params =
QuickActions::InterpretService.new(project, current_user)
- .execute(original_description, issuable)
+ .execute(original_description, issuable, only: only)
# Avoid a description already set on an issuable to be overwritten by a nil
params[:description] = description if description
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index b54b0bf6ef6..fba252b0bae 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -48,6 +48,8 @@ module Issues
notification_service.async.relabeled_issue(issue, added_labels, current_user)
end
+ handle_milestone_change(issue)
+
added_mentions = issue.mentioned_users - old_mentioned_users
if added_mentions.present?
@@ -91,6 +93,18 @@ module Issues
private
+ def handle_milestone_change(issue)
+ return if skip_milestone_email
+
+ return unless issue.previous_changes.include?('milestone_id')
+
+ if issue.milestone.nil?
+ notification_service.async.removed_milestone_issue(issue, current_user)
+ else
+ notification_service.async.changed_milestone_issue(issue, issue.milestone, current_user)
+ end
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def get_issue_if_allowed(id, board_group_id = nil)
return unless id
diff --git a/app/services/keys/destroy_service.rb b/app/services/keys/destroy_service.rb
index e2ae4047941..159455f80f3 100644
--- a/app/services/keys/destroy_service.rb
+++ b/app/services/keys/destroy_service.rb
@@ -6,7 +6,7 @@ module Keys
key.destroy if destroy_possible?(key)
end
- # overriden in EE::Keys::DestroyService
+ # overridden in EE::Keys::DestroyService
def destroy_possible?(key)
true
end
diff --git a/app/services/members/base_service.rb b/app/services/members/base_service.rb
index 8248f1441d7..d734571f835 100644
--- a/app/services/members/base_service.rb
+++ b/app/services/members/base_service.rb
@@ -10,7 +10,7 @@ module Members
end
def after_execute(args)
- # overriden in EE::Members modules
+ # overridden in EE::Members modules
end
private
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 0e76d2cc3ab..6c69452e2ab 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -6,8 +6,12 @@ module MergeRequests
def execute
@params_issue_iid = params.delete(:issue_iid)
+ self.merge_request = MergeRequest.new
+ # TODO: this should handle all quick actions that don't have side effects
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/53658
+ merge_quick_actions_into_params!(merge_request, only: [:target_branch])
+ merge_request.assign_attributes(params)
- self.merge_request = MergeRequest.new(params)
merge_request.author = current_user
merge_request.compare_commits = []
merge_request.source_project = find_source_project
diff --git a/app/services/merge_requests/get_urls_service.rb b/app/services/merge_requests/get_urls_service.rb
index 35a22449e34..7c88c9abb41 100644
--- a/app/services/merge_requests/get_urls_service.rb
+++ b/app/services/merge_requests/get_urls_service.rb
@@ -50,8 +50,8 @@ module MergeRequests
end
def url_for_new_merge_request(branch_name)
- url = Gitlab::Routing.url_helpers.project_new_merge_request_url(project, branch_name)
-
+ merge_request_params = { source_branch: branch_name }
+ url = Gitlab::Routing.url_helpers.project_new_merge_request_url(project, merge_request: merge_request_params)
{ branch_name: branch_name, url: url, new_merge_request: true }
end
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index f01872b205e..5fe48da1cd6 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -2,18 +2,18 @@
module MergeRequests
class RefreshService < MergeRequests::BaseService
+ attr_reader :push
+
def execute(oldrev, newrev, ref)
- push = Gitlab::Git::Push.new(@project, oldrev, newrev, ref)
- return true unless push.branch_push?
+ @push = Gitlab::Git::Push.new(@project, oldrev, newrev, ref)
+ return true unless @push.branch_push?
- refresh_merge_requests!(push)
+ refresh_merge_requests!
end
private
- def refresh_merge_requests!(push)
- @push = push
-
+ def refresh_merge_requests!
Gitlab::GitalyClient.allow_n_plus_1_calls(&method(:find_new_commits))
# Be sure to close outstanding MRs before reloading them to avoid generating an
# empty diff during a manual merge
@@ -87,11 +87,8 @@ module MergeRequests
filter_merge_requests(merge_requests).each do |merge_request|
if branch_and_project_match?(merge_request) || @push.force_push?
merge_request.reload_diff(current_user)
- else
- mr_commit_ids = merge_request.commit_shas
- push_commit_ids = @commits.map(&:id)
- matches = mr_commit_ids & push_commit_ids
- merge_request.reload_diff(current_user) if matches.any?
+ elsif merge_request.includes_any_commits?(push_commit_ids)
+ merge_request.reload_diff(current_user)
end
merge_request.mark_as_unchecked
@@ -104,6 +101,10 @@ module MergeRequests
end
# rubocop: enable CodeReuse/ActiveRecord
+ def push_commit_ids
+ @push_commit_ids ||= @commits.map(&:id)
+ end
+
def branch_and_project_match?(merge_request)
merge_request.source_project == @project &&
merge_request.source_branch == @push.branch_name
diff --git a/app/services/merge_requests/reload_diffs_service.rb b/app/services/merge_requests/reload_diffs_service.rb
index b4d48fe92ad..b47d8f3f63a 100644
--- a/app/services/merge_requests/reload_diffs_service.rb
+++ b/app/services/merge_requests/reload_diffs_service.rb
@@ -36,7 +36,10 @@ module MergeRequests
# Remove cache for all diffs on this MR. Do not use the association on the
# model, as that will interfere with other actions happening when
# reloading the diff.
- MergeRequestDiff.where(merge_request: merge_request).each do |merge_request_diff|
+ MergeRequestDiff
+ .where(merge_request: merge_request)
+ .preload(merge_request: :target_project)
+ .find_each do |merge_request_diff|
next if merge_request_diff == new_diff
cacheable_collection(merge_request_diff).clear_cache
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index b112edbce7f..aacaf10d09c 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -58,6 +58,8 @@ module MergeRequests
merge_request.mark_as_unchecked
end
+ handle_milestone_change(merge_request)
+
added_labels = merge_request.labels - old_labels
if added_labels.present?
notification_service.async.relabeled_merge_request(
@@ -105,6 +107,18 @@ module MergeRequests
private
+ def handle_milestone_change(merge_request)
+ return if skip_milestone_email
+
+ return unless merge_request.previous_changes.include?('milestone_id')
+
+ if merge_request.milestone.nil?
+ notification_service.async.removed_milestone_merge_request(merge_request, current_user)
+ else
+ notification_service.async.changed_milestone_merge_request(merge_request, merge_request.milestone, current_user)
+ end
+ end
+
def create_branch_change_note(issuable, branch_type, old_branch, new_branch)
SystemNoteService.change_branch(
issuable, issuable.project, current_user, branch_type,
diff --git a/app/services/milestones/destroy_service.rb b/app/services/milestones/destroy_service.rb
index 7cda802c120..87c7a282081 100644
--- a/app/services/milestones/destroy_service.rb
+++ b/app/services/milestones/destroy_service.rb
@@ -4,7 +4,7 @@ module Milestones
class DestroyService < Milestones::BaseService
def execute(milestone)
Milestone.transaction do
- update_params = { milestone: nil }
+ update_params = { milestone: nil, skip_milestone_email: true }
milestone.issues.each do |issue|
Issues::UpdateService.new(parent, current_user, update_params).execute(issue)
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 50fa373025b..fb9c18ea75d 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -129,6 +129,14 @@ class NotificationService
relabeled_resource_email(issue, added_labels, current_user, :relabeled_issue_email)
end
+ def removed_milestone_issue(issue, current_user)
+ removed_milestone_resource_email(issue, current_user, :removed_milestone_issue_email)
+ end
+
+ def changed_milestone_issue(issue, new_milestone, current_user)
+ changed_milestone_resource_email(issue, new_milestone, current_user, :changed_milestone_issue_email)
+ end
+
# When create a merge request we should send an email to:
#
# * mr author
@@ -138,7 +146,6 @@ class NotificationService
# * users with custom level checked with "new merge request"
#
# In EE, approvers of the merge request are also included
- #
def new_merge_request(merge_request, current_user)
new_resource_email(merge_request, :new_merge_request_email)
end
@@ -208,6 +215,14 @@ class NotificationService
relabeled_resource_email(merge_request, added_labels, current_user, :relabeled_merge_request_email)
end
+ def removed_milestone_merge_request(merge_request, current_user)
+ removed_milestone_resource_email(merge_request, current_user, :removed_milestone_merge_request_email)
+ end
+
+ def changed_milestone_merge_request(merge_request, new_milestone, current_user)
+ changed_milestone_resource_email(merge_request, new_milestone, current_user, :changed_milestone_merge_request_email)
+ end
+
def close_mr(merge_request, current_user)
close_resource_email(merge_request, current_user, :closed_merge_request_email)
end
@@ -500,6 +515,30 @@ class NotificationService
end
end
+ def removed_milestone_resource_email(target, current_user, method)
+ recipients = NotificationRecipientService.build_recipients(
+ target,
+ current_user,
+ action: 'removed_milestone'
+ )
+
+ recipients.each do |recipient|
+ mailer.send(method, recipient.user.id, target.id, current_user.id).deliver_later
+ end
+ end
+
+ def changed_milestone_resource_email(target, milestone, current_user, method)
+ recipients = NotificationRecipientService.build_recipients(
+ target,
+ current_user,
+ action: 'changed_milestone'
+ )
+
+ recipients.each do |recipient|
+ mailer.send(method, recipient.user.id, target.id, milestone, current_user.id).deliver_later
+ end
+ end
+
def reopen_resource_email(target, current_user, method, status)
recipients = NotificationRecipientService.build_recipients(target, current_user, action: "reopen")
diff --git a/app/services/projects/move_project_authorizations_service.rb b/app/services/projects/move_project_authorizations_service.rb
index 2060a263751..2985ba89014 100644
--- a/app/services/projects/move_project_authorizations_service.rb
+++ b/app/services/projects/move_project_authorizations_service.rb
@@ -3,7 +3,7 @@
# NOTE: This service cannot be used directly because it is part of a
# a bigger process. Instead, use the service MoveAccessService which moves
# project memberships, project group links, authorizations and refreshes
-# the authorizations if neccessary
+# the authorizations if necessary
module Projects
class MoveProjectAuthorizationsService < BaseMoveRelationsService
def execute(source_project, remove_remaining_elements: true)
diff --git a/app/services/projects/move_project_group_links_service.rb b/app/services/projects/move_project_group_links_service.rb
index fb395ecb9a1..36afcd0c503 100644
--- a/app/services/projects/move_project_group_links_service.rb
+++ b/app/services/projects/move_project_group_links_service.rb
@@ -3,7 +3,7 @@
# NOTE: This service cannot be used directly because it is part of a
# a bigger process. Instead, use the service MoveAccessService which moves
# project memberships, project group links, authorizations and refreshes
-# the authorizations if neccessary
+# the authorizations if necessary
module Projects
class MoveProjectGroupLinksService < BaseMoveRelationsService
def execute(source_project, remove_remaining_elements: true)
diff --git a/app/services/projects/move_project_members_service.rb b/app/services/projects/move_project_members_service.rb
index f28f44adc03..faf389241d2 100644
--- a/app/services/projects/move_project_members_service.rb
+++ b/app/services/projects/move_project_members_service.rb
@@ -3,7 +3,7 @@
# NOTE: This service cannot be used directly because it is part of a
# a bigger process. Instead, use the service MoveAccessService which moves
# project memberships, project group links, authorizations and refreshes
-# the authorizations if neccessary
+# the authorizations if necessary
module Projects
class MoveProjectMembersService < BaseMoveRelationsService
def execute(source_project, remove_remaining_elements: true)
diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb
index 751aae2696d..9c81de7e90e 100644
--- a/app/services/quick_actions/interpret_service.rb
+++ b/app/services/quick_actions/interpret_service.rb
@@ -23,13 +23,13 @@ module QuickActions
# Takes a text and interprets the commands that are extracted from it.
# Returns the content without commands, and hash of changes to be applied to a record.
- def execute(content, issuable)
+ def execute(content, issuable, only: nil)
return [content, {}] unless current_user.can?(:use_quick_actions)
@issuable = issuable
@updates = {}
- content, commands = extractor.extract_commands(content)
+ content, commands = extractor.extract_commands(content, only: only)
extract_updates(commands)
[content, @updates]
@@ -433,14 +433,14 @@ module QuickActions
end
end
- desc 'Add or substract spent time'
+ desc 'Add or subtract spent time'
explanation do |time_spent, time_spent_date|
if time_spent
if time_spent > 0
verb = 'Adds'
value = time_spent
else
- verb = 'Substracts'
+ verb = 'Subtracts'
value = -time_spent
end
diff --git a/app/services/search/group_service.rb b/app/services/search/group_service.rb
index 00372887985..34803d005e3 100644
--- a/app/services/search/group_service.rb
+++ b/app/services/search/group_service.rb
@@ -11,13 +11,11 @@ module Search
@group = group
end
- # rubocop: disable CodeReuse/ActiveRecord
def projects
return Project.none unless group
return @projects if defined? @projects
@projects = super.inside_path(group.full_path)
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/app/services/submodules/update_service.rb b/app/services/submodules/update_service.rb
new file mode 100644
index 00000000000..a6011a920bd
--- /dev/null
+++ b/app/services/submodules/update_service.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Submodules
+ class UpdateService < Commits::CreateService
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(*args)
+ super
+
+ @start_branch = @branch_name
+ @commit_sha = params[:commit_sha].presence
+ @submodule = params[:submodule].presence
+ @commit_message = params[:commit_message].presence || "Update submodule #{@submodule} with oid #{@commit_sha}"
+ end
+
+ def validate!
+ super
+
+ raise ValidationError, 'The repository is empty' if repository.empty?
+ end
+
+ def execute
+ super
+ rescue StandardError => e
+ error(e.message)
+ end
+
+ def create_commit!
+ repository.update_submodule(current_user,
+ @submodule,
+ @commit_sha,
+ message: @commit_message,
+ branch: @branch_name)
+ rescue ArgumentError, TypeError
+ raise ValidationError, 'Invalid parameters'
+ end
+ end
+end
diff --git a/app/services/update_deployment_service.rb b/app/services/update_deployment_service.rb
new file mode 100644
index 00000000000..aa7fcca1e2a
--- /dev/null
+++ b/app/services/update_deployment_service.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+class UpdateDeploymentService
+ attr_reader :deployment
+ attr_reader :deployable
+
+ delegate :environment, to: :deployment
+ delegate :variables, to: :deployable
+
+ def initialize(deployment)
+ @deployment = deployment
+ @deployable = deployment.deployable
+ end
+
+ def execute
+ deployment.create_ref
+ deployment.invalidate_cache
+
+ ActiveRecord::Base.transaction do
+ environment.external_url = expanded_environment_url if
+ expanded_environment_url
+
+ environment.fire_state_event(action)
+
+ break unless environment.save
+ break if environment.stopped?
+
+ deployment.tap(&:update_merge_request_metrics!)
+ end
+ end
+
+ private
+
+ def environment_options
+ @environment_options ||= deployable.options&.dig(:environment) || {}
+ end
+
+ def expanded_environment_url
+ return @expanded_environment_url if defined?(@expanded_environment_url)
+ return unless environment_url
+
+ @expanded_environment_url =
+ ExpandVariables.expand(environment_url, variables)
+ end
+
+ def environment_url
+ environment_options[:url]
+ end
+
+ def action
+ environment_options[:action] || 'start'
+ end
+end