diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-01 03:09:44 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-01 03:09:44 +0300 |
commit | 83e25d14371953c18ac41b3a0cc27aadefd9bc69 (patch) | |
tree | 69d4b7cc955c7a7c414baf4e60d53ad6f5647732 /app | |
parent | 5376a0c41d6264e6cc820b5d12220ae4ff79f2ae (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/forks/components/forks_button.vue | 86 | ||||
-rw-r--r-- | app/assets/javascripts/forks/init_forks_button.js | 41 | ||||
-rw-r--r-- | app/assets/javascripts/pages/projects/show/index.js | 4 | ||||
-rw-r--r-- | app/helpers/projects_helper.rb | 19 | ||||
-rw-r--r-- | app/models/packages/package.rb | 9 | ||||
-rw-r--r-- | app/services/deployments/create_for_job_service.rb | 40 | ||||
-rw-r--r-- | app/services/environments/create_for_job_service.rb | 28 | ||||
-rw-r--r-- | app/services/groups/update_service.rb | 25 | ||||
-rw-r--r-- | app/views/projects/buttons/_fork.html.haml | 15 |
9 files changed, 212 insertions, 55 deletions
diff --git a/app/assets/javascripts/forks/components/forks_button.vue b/app/assets/javascripts/forks/components/forks_button.vue new file mode 100644 index 00000000000..40cf74ff4cc --- /dev/null +++ b/app/assets/javascripts/forks/components/forks_button.vue @@ -0,0 +1,86 @@ +<script> +import { GlButtonGroup, GlButton, GlTooltipDirective } from '@gitlab/ui'; +import { s__ } from '~/locale'; + +export default { + components: { + GlButtonGroup, + GlButton, + }, + directives: { + GlTooltip: GlTooltipDirective, + }, + inject: { + forksCount: { + default: 0, + }, + projectFullPath: { + default: '', + }, + projectForksUrl: { + default: '', + }, + userForkUrl: { + default: '', + }, + newForkUrl: { + default: '', + }, + canReadCode: { + default: false, + }, + canCreateFork: { + default: false, + }, + canForkProject: { + default: false, + }, + }, + computed: { + forkButtonUrl() { + return this.userForkUrl || this.newForkUrl; + }, + userHasForkAccess() { + return Boolean(this.userForkUrl) && this.canReadCode; + }, + userCanFork() { + return this.canReadCode && this.canCreateFork && this.canForkProject; + }, + forkButtonEnabled() { + return this.userHasForkAccess || this.userCanFork; + }, + forkButtonTooltip() { + if (!this.canForkProject) { + return s__("ProjectOverview|You don't have permission to fork this project"); + } + + if (!this.canCreateFork) { + return s__('ProjectOverview|You have reached your project limit'); + } + + if (this.userHasForkAccess) { + return s__('ProjectOverview|Go to your fork'); + } + + return s__('ProjectOverview|Create new fork'); + }, + }, +}; +</script> + +<template> + <gl-button-group :vertical="false"> + <gl-button + v-gl-tooltip + data-testid="fork-button" + :disabled="!forkButtonEnabled" + :href="forkButtonUrl" + icon="fork" + :title="forkButtonTooltip" + >{{ s__('ProjectOverview|Forks') }}</gl-button + > + <gl-button data-testid="forks-count" :disabled="!canReadCode" :href="projectForksUrl">{{ + forksCount + }}</gl-button> + </gl-button-group> +</template> diff --git a/app/assets/javascripts/forks/init_forks_button.js b/app/assets/javascripts/forks/init_forks_button.js new file mode 100644 index 00000000000..b899d1c51db --- /dev/null +++ b/app/assets/javascripts/forks/init_forks_button.js @@ -0,0 +1,41 @@ +import Vue from 'vue'; +import { parseBoolean } from '~/lib/utils/common_utils'; +import ForksButton from './components/forks_button.vue'; + +const initForksButton = () => { + const el = document.getElementById('js-forks-button'); + + if (!el) { + return false; + } + + const { + forksCount, + projectFullPath, + projectForksUrl, + userForkUrl, + newForkUrl, + canReadCode, + canCreateFork, + canForkProject, + } = el.dataset; + + return new Vue({ + el, + provide: { + forksCount, + projectFullPath, + projectForksUrl, + userForkUrl, + newForkUrl, + canReadCode: parseBoolean(canReadCode), + canCreateFork: parseBoolean(canCreateFork), + canForkProject: parseBoolean(canForkProject), + }, + render(createElement) { + return createElement(ForksButton); + }, + }); +}; + +export default initForksButton; diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js index e17f5255c54..c43a0eb597c 100644 --- a/app/assets/javascripts/pages/projects/show/index.js +++ b/app/assets/javascripts/pages/projects/show/index.js @@ -8,6 +8,8 @@ import initTerraformNotification from '~/projects/terraform_notification'; import { initUploadFileTrigger } from '~/projects/upload_file'; import initReadMore from '~/read_more'; +import initForksButton from '~/forks/init_forks_button'; + // Project show page loads different overview content based on user preferences if (document.getElementById('js-tree-list')) { import(/* webpackChunkName: 'treeList' */ 'ee_else_ce/repository') @@ -57,3 +59,5 @@ if (document.querySelector('.js-autodevops-banner')) { }) .catch(() => {}); } + +initForksButton(); diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 109fa028f25..ff27c348106 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -464,14 +464,23 @@ module ProjectsHelper project.forking_enabled? && can?(user, :read_code, project) end - def fork_button_disabled_tooltip(project) + def fork_button_data_attributes(project) return unless current_user - if !current_user.can?(:fork_project, project) - s_("ProjectOverview|You don't have permission to fork this project") - elsif !current_user.can?(:create_fork) - s_('ProjectOverview|You have reached your project limit') + if current_user.already_forked?(project) && current_user.forkable_namespaces.size < 2 + user_fork_url = namespace_project_path(current_user, current_user.fork_of(project)) end + + { + forks_count: project.forks_count, + project_full_path: project.full_path, + project_forks_url: project_forks_path(project), + user_fork_url: user_fork_url, + new_fork_url: new_project_fork_path(project), + can_read_code: can?(current_user, :read_code, project).to_s, + can_fork_project: can?(current_user, :fork_project, project).to_s, + can_create_fork: can?(current_user, :create_fork).to_s + } end def import_from_bitbucket_message diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb index ee8a26e8f19..7dba8b42146 100644 --- a/app/models/packages/package.rb +++ b/app/models/packages/package.rb @@ -163,6 +163,14 @@ class Packages::Package < ApplicationRecord scope :preload_pypi_metadatum, -> { preload(:pypi_metadatum) } scope :preload_conan_metadatum, -> { preload(:conan_metadatum) } + scope :with_npm_scope, ->(scope) do + if Feature.enabled?(:npm_package_registry_fix_group_path_validation) + npm.where("position('/' in packages_packages.name) > 0 AND split_part(packages_packages.name, '/', 1) = :package_scope", package_scope: "@#{sanitize_sql_like(scope)}") + else + npm.where("name ILIKE :package_name", package_name: "@#{sanitize_sql_like(scope)}/%") + end + end + scope :without_nuget_temporary_name, -> { where.not(name: Packages::Nuget::TEMPORARY_PACKAGE_NAME) } scope :has_version, -> { where.not(version: nil) } @@ -184,7 +192,6 @@ class Packages::Package < ApplicationRecord scope :order_project_name, -> { joins(:project).reorder('projects.name ASC') } scope :order_project_name_desc, -> { joins(:project).reorder('projects.name DESC') } scope :order_by_package_file, -> { joins(:package_files).order('packages_package_files.created_at ASC') } - scope :with_npm_scope, ->(scope) { npm.where("name ILIKE :package_name", package_name: "@#{sanitize_sql_like(scope)}/%") } scope :order_project_path, -> do keyset_order = keyset_pagination_order(join_class: Project, column_name: :path, direction: :asc) diff --git a/app/services/deployments/create_for_job_service.rb b/app/services/deployments/create_for_job_service.rb index fe632794d99..e230515ce27 100644 --- a/app/services/deployments/create_for_job_service.rb +++ b/app/services/deployments/create_for_job_service.rb @@ -5,32 +5,32 @@ module Deployments class CreateForJobService DeploymentCreationError = Class.new(StandardError) - def execute(build) - return unless build.is_a?(::Ci::Processable) && build.persisted_environment.present? + def execute(job) + return unless job.is_a?(::Ci::Processable) && job.persisted_environment.present? - environment = build.actual_persisted_environment + environment = job.actual_persisted_environment - deployment = to_resource(build, environment) + deployment = to_resource(job, environment) return unless deployment deployment.save! - build.association(:deployment).target = deployment - build.association(:deployment).loaded! + job.association(:deployment).target = deployment + job.association(:deployment).loaded! deployment rescue ActiveRecord::RecordInvalid => e Gitlab::ErrorTracking.track_and_raise_for_dev_exception( - DeploymentCreationError.new(e.message), build_id: build.id) + DeploymentCreationError.new(e.message), job_id: job.id) end private - def to_resource(build, environment) - return build.deployment if build.deployment - return unless build.deployment_job? + def to_resource(job, environment) + return job.deployment if job.deployment + return unless job.deployment_job? - deployment = ::Deployment.new(attributes(build, environment)) + deployment = ::Deployment.new(attributes(job, environment)) # If there is a validation error on environment creation, such as # the name contains invalid character, the job will fall back to a @@ -42,7 +42,7 @@ module Deployments deployment.cluster_id = cluster.id deployment.deployment_cluster = ::DeploymentCluster.new( cluster_id: cluster.id, - kubernetes_namespace: cluster.kubernetes_namespace_for(deployment.environment, deployable: build) + kubernetes_namespace: cluster.kubernetes_namespace_for(deployment.environment, deployable: job) ) end @@ -53,16 +53,16 @@ module Deployments deployment end - def attributes(build, environment) + def attributes(job, environment) { - project: build.project, + project: job.project, environment: environment, - deployable: build, - user: build.user, - ref: build.ref, - tag: build.tag, - sha: build.sha, - on_stop: build.on_stop + deployable: job, + user: job.user, + ref: job.ref, + tag: job.tag, + sha: job.sha, + on_stop: job.on_stop } end end diff --git a/app/services/environments/create_for_job_service.rb b/app/services/environments/create_for_job_service.rb index 2a225c1ac91..02545ce03e0 100644 --- a/app/services/environments/create_for_job_service.rb +++ b/app/services/environments/create_for_job_service.rb @@ -3,16 +3,16 @@ module Environments # This class creates an environment record for a pipeline job. class CreateForJobService - def execute(build) - return unless build.is_a?(::Ci::Processable) && build.has_environment_keyword? + def execute(job) + return unless job.is_a?(::Ci::Processable) && job.has_environment_keyword? - environment = to_resource(build) + environment = to_resource(job) if environment.persisted? - build.persisted_environment = environment - build.assign_attributes(metadata_attributes: { expanded_environment_name: environment.name }) + job.persisted_environment = environment + job.assign_attributes(metadata_attributes: { expanded_environment_name: environment.name }) else - build.assign_attributes(status: :failed, failure_reason: :environment_creation_failure) + job.assign_attributes(status: :failed, failure_reason: :environment_creation_failure) end environment @@ -21,20 +21,20 @@ module Environments private # rubocop: disable Performance/ActiveRecordSubtransactionMethods - def to_resource(build) - build.project.environments.safe_find_or_create_by(name: build.expanded_environment_name) do |environment| + def to_resource(job) + job.project.environments.safe_find_or_create_by(name: job.expanded_environment_name) do |environment| # Initialize the attributes at creation - environment.auto_stop_in = expanded_auto_stop_in(build) - environment.tier = build.environment_tier_from_options - environment.merge_request = build.pipeline.merge_request + environment.auto_stop_in = expanded_auto_stop_in(job) + environment.tier = job.environment_tier_from_options + environment.merge_request = job.pipeline.merge_request end end # rubocop: enable Performance/ActiveRecordSubtransactionMethods - def expanded_auto_stop_in(build) - return unless build.environment_auto_stop_in + def expanded_auto_stop_in(job) + return unless job.environment_auto_stop_in - ExpandVariables.expand(build.environment_auto_stop_in, -> { build.simple_variables.sort_and_expand_all }) + ExpandVariables.expand(job.environment_auto_stop_in, -> { job.simple_variables.sort_and_expand_all }) end end end diff --git a/app/services/groups/update_service.rb b/app/services/groups/update_service.rb index df6ede87ef9..6e68cff6fa6 100644 --- a/app/services/groups/update_service.rb +++ b/app/services/groups/update_service.rb @@ -21,7 +21,7 @@ module Groups return false unless valid_share_with_group_lock_change? - return false unless valid_path_change_with_npm_packages? + return false unless valid_path_change? return false unless update_shared_runners @@ -46,6 +46,29 @@ module Groups private + def valid_path_change? + unless Feature.enabled?(:npm_package_registry_fix_group_path_validation) + return valid_path_change_with_npm_packages? + end + + return true unless group.packages_feature_enabled? + return true if params[:path].blank? + return true if group.has_parent? + return true if !group.has_parent? && group.path == params[:path] + + # we have a path change on a root group: + # check that we don't have any npm package with a scope set to the group path + npm_packages = ::Packages::GroupPackagesFinder.new(current_user, group, package_type: :npm, preload_pipelines: false) + .execute + .with_npm_scope(group.path) + + return true unless npm_packages.exists? + + group.errors.add(:path, s_('GroupSettings|cannot change when group contains projects with NPM packages')) + false + end + + # TODO: delete this function along with npm_package_registry_fix_group_path_validation def valid_path_change_with_npm_packages? return true unless group.packages_feature_enabled? return true if params[:path].blank? diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml index c9dcfaff8c6..963c416ed42 100644 --- a/app/views/projects/buttons/_fork.html.haml +++ b/app/views/projects/buttons/_fork.html.haml @@ -1,16 +1,3 @@ - unless @project.empty_repo? - if current_user - .count-badge.btn-group - - if current_user.already_forked?(@project) && current_user.forkable_namespaces.size < 2 - = link_button_to namespace_project_path(current_user, current_user.fork_of(@project)), title: s_('ProjectOverview|Go to your fork'), class: 'has-tooltip fork-btn', icon: 'fork' do - = s_('ProjectOverview|Fork') - - else - - disabled_tooltip = fork_button_disabled_tooltip(@project) - - count_class = 'disabled' unless can?(current_user, :read_code, @project) - - button_class = 'disabled' if disabled_tooltip - - %span.btn-group{ class: ('has-tooltip' if disabled_tooltip), title: disabled_tooltip } - = link_button_to new_project_fork_path(@project), class: "fork-btn #{button_class}", data: { qa_selector: 'fork_button' }, icon: 'fork' do - = s_('ProjectOverview|Fork') - = link_button_to project_forks_path(@project), title: n_(s_('ProjectOverview|Forks'), s_('ProjectOverview|Forks'), @project.forks_count), class: "count has-tooltip fork-count #{count_class}" do - = @project.forks_count + #js-forks-button{ data: fork_button_data_attributes(@project) } |