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
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-08-01 03:09:44 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-08-01 03:09:44 +0300
commit83e25d14371953c18ac41b3a0cc27aadefd9bc69 (patch)
tree69d4b7cc955c7a7c414baf4e60d53ad6f5647732 /app
parent5376a0c41d6264e6cc820b5d12220ae4ff79f2ae (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/forks/components/forks_button.vue86
-rw-r--r--app/assets/javascripts/forks/init_forks_button.js41
-rw-r--r--app/assets/javascripts/pages/projects/show/index.js4
-rw-r--r--app/helpers/projects_helper.rb19
-rw-r--r--app/models/packages/package.rb9
-rw-r--r--app/services/deployments/create_for_job_service.rb40
-rw-r--r--app/services/environments/create_for_job_service.rb28
-rw-r--r--app/services/groups/update_service.rb25
-rw-r--r--app/views/projects/buttons/_fork.html.haml15
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) }