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-10-28 00:12:19 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-10-28 00:12:19 +0300
commitf3d0329fcb9c703757c4859b12d19c5c3fe42c40 (patch)
tree499c86fad4ab967a9ffdb2cddeead2afe792968c /app
parent7badd9fd55f9b877f2de8c8d0126c720a57e538d (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/ci/pipeline_details/constants.js1
-rw-r--r--app/assets/javascripts/ci/pipelines_page/components/pipeline_labels.vue16
-rw-r--r--app/assets/javascripts/ci/pipelines_page/components/pipeline_triggerer.vue4
-rw-r--r--app/assets/javascripts/ci/pipelines_page/constants.js2
-rw-r--r--app/controllers/groups/work_items_controller.rb7
-rw-r--r--app/controllers/groups_controller.rb3
-rw-r--r--app/graphql/mutations/container_registry/protection/rule/create.rb63
-rw-r--r--app/graphql/types/container_registry/protection/rule_access_level_enum.rb17
-rw-r--r--app/graphql/types/container_registry/protection/rule_type.rb41
-rw-r--r--app/graphql/types/mutation_type.rb1
-rw-r--r--app/policies/container_registry/protection/rule_policy.rb9
-rw-r--r--app/services/container_registry/protection/create_rule_service.rb40
-rw-r--r--app/views/projects/branch_rules/_show.html.haml2
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml2
-rw-r--r--app/views/projects/protected_tags/shared/_index.html.haml2
-rw-r--r--app/views/protected_branches/shared/_index.html.haml2
-rw-r--r--app/views/shared/deploy_tokens/_index.html.haml2
17 files changed, 202 insertions, 12 deletions
diff --git a/app/assets/javascripts/ci/pipeline_details/constants.js b/app/assets/javascripts/ci/pipeline_details/constants.js
index 70b758ae6b0..51d0e980e78 100644
--- a/app/assets/javascripts/ci/pipeline_details/constants.js
+++ b/app/assets/javascripts/ci/pipeline_details/constants.js
@@ -2,7 +2,6 @@ import { __, s__ } from '~/locale';
export const CANCEL_REQUEST = 'CANCEL_REQUEST';
export const SUPPORTED_FILTER_PARAMETERS = ['username', 'ref', 'status', 'source'];
-export const SCHEDULE_ORIGIN = 'schedule';
export const NEEDS_PROPERTY = 'needs';
export const EXPLICIT_NEEDS_PROPERTY = 'previousStageJobsOrNeeds';
diff --git a/app/assets/javascripts/ci/pipelines_page/components/pipeline_labels.vue b/app/assets/javascripts/ci/pipelines_page/components/pipeline_labels.vue
index 8f45094eb74..237f1a0306a 100644
--- a/app/assets/javascripts/ci/pipelines_page/components/pipeline_labels.vue
+++ b/app/assets/javascripts/ci/pipelines_page/components/pipeline_labels.vue
@@ -1,7 +1,7 @@
<script>
import { GlLink, GlPopover, GlSprintf, GlTooltipDirective, GlBadge } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
-import { SCHEDULE_ORIGIN } from '~/ci/pipeline_details/constants';
+import { SCHEDULE_ORIGIN, API_ORIGIN } from '../constants';
export default {
components: {
@@ -50,6 +50,9 @@ export default {
autoDevopsHelpPath() {
return helpPagePath('topics/autodevops/index.md');
},
+ isApi() {
+ return this.pipeline.source === API_ORIGIN;
+ },
},
};
</script>
@@ -64,7 +67,7 @@ export default {
variant="info"
size="sm"
data-testid="pipeline-url-scheduled"
- >{{ __('Scheduled') }}</gl-badge
+ >{{ __('scheduled') }}</gl-badge
>
<gl-badge
v-if="pipeline.flags.latest"
@@ -185,5 +188,14 @@ export default {
data-testid="pipeline-url-fork"
>{{ __('fork') }}</gl-badge
>
+ <gl-badge
+ v-if="isApi"
+ v-gl-tooltip
+ :title="__('This pipeline was triggered using the api')"
+ variant="info"
+ size="sm"
+ data-testid="pipeline-api-badge"
+ >{{ s__('Pipeline|api') }}</gl-badge
+ >
</div>
</template>
diff --git a/app/assets/javascripts/ci/pipelines_page/components/pipeline_triggerer.vue b/app/assets/javascripts/ci/pipelines_page/components/pipeline_triggerer.vue
index 2a73795db0a..a53c7cacae2 100644
--- a/app/assets/javascripts/ci/pipelines_page/components/pipeline_triggerer.vue
+++ b/app/assets/javascripts/ci/pipelines_page/components/pipeline_triggerer.vue
@@ -29,9 +29,5 @@ export default {
<gl-avatar-link v-if="user" v-gl-tooltip :href="user.path" :title="user.name" class="gl-ml-3">
<gl-avatar :size="32" :src="user.avatar_url" />
</gl-avatar-link>
-
- <span v-else class="gl-ml-3">
- {{ s__('Pipelines|API') }}
- </span>
</div>
</template>
diff --git a/app/assets/javascripts/ci/pipelines_page/constants.js b/app/assets/javascripts/ci/pipelines_page/constants.js
index aa6ef8a25ee..a576ce7f4f5 100644
--- a/app/assets/javascripts/ci/pipelines_page/constants.js
+++ b/app/assets/javascripts/ci/pipelines_page/constants.js
@@ -1,2 +1,4 @@
export const ANY_TRIGGER_AUTHOR = 'Any';
export const FILTER_PIPELINES_SEARCH_DELAY = 200;
+export const SCHEDULE_ORIGIN = 'schedule';
+export const API_ORIGIN = 'api';
diff --git a/app/controllers/groups/work_items_controller.rb b/app/controllers/groups/work_items_controller.rb
index bd85f12119b..ece279da778 100644
--- a/app/controllers/groups/work_items_controller.rb
+++ b/app/controllers/groups/work_items_controller.rb
@@ -4,6 +4,13 @@ module Groups
class WorkItemsController < Groups::ApplicationController
feature_category :team_planning
+ before_action do
+ push_force_frontend_feature_flag(:work_items, group&.work_items_feature_flag_enabled?)
+ push_force_frontend_feature_flag(:work_items_mvc, group&.work_items_mvc_feature_flag_enabled?)
+ push_force_frontend_feature_flag(:work_items_mvc_2, group&.work_items_mvc_2_feature_flag_enabled?)
+ push_force_frontend_feature_flag(:linked_work_items, group&.linked_work_items_feature_flag_enabled?)
+ end
+
def index
not_found unless Feature.enabled?(:namespace_level_work_items, group)
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 83c4efa5a42..72a5c4d3e69 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -36,6 +36,9 @@ class GroupsController < Groups::ApplicationController
push_frontend_feature_flag(:or_issuable_queries, group)
push_frontend_feature_flag(:frontend_caching, group)
push_force_frontend_feature_flag(:work_items, group.work_items_feature_flag_enabled?)
+ push_force_frontend_feature_flag(:work_items_mvc, group.work_items_mvc_feature_flag_enabled?)
+ push_force_frontend_feature_flag(:work_items_mvc_2, group.work_items_mvc_2_feature_flag_enabled?)
+ push_force_frontend_feature_flag(:linked_work_items, group.linked_work_items_feature_flag_enabled?)
push_frontend_feature_flag(:issues_grid_view)
push_frontend_feature_flag(:group_multi_select_tokens, group)
end
diff --git a/app/graphql/mutations/container_registry/protection/rule/create.rb b/app/graphql/mutations/container_registry/protection/rule/create.rb
new file mode 100644
index 00000000000..cf8416480a2
--- /dev/null
+++ b/app/graphql/mutations/container_registry/protection/rule/create.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module Mutations
+ module ContainerRegistry
+ module Protection
+ module Rule
+ class Create < ::Mutations::BaseMutation
+ graphql_name 'CreateContainerRegistryProtectionRule'
+ description 'Creates a protection rule to restrict access to a project\'s container registry. ' \
+ 'Available only when feature flag `container_registry_protected_containers` is enabled.'
+
+ include FindsProject
+
+ authorize :admin_container_image
+
+ argument :project_path,
+ GraphQL::Types::ID,
+ required: true,
+ description: 'Full path of the project where a protection rule is located.'
+
+ argument :container_path_pattern,
+ GraphQL::Types::String,
+ required: true,
+ description:
+ 'ContainerRegistryname protected by the protection rule. For example `@my-scope/my-container-*`. ' \
+ 'Wildcard character `*` allowed.'
+
+ argument :push_protected_up_to_access_level,
+ Types::ContainerRegistry::Protection::RuleAccessLevelEnum,
+ required: true,
+ description:
+ 'Max GitLab access level to prevent from pushing container images to the container registry. ' \
+ 'For example `DEVELOPER`, `MAINTAINER`, `OWNER`.'
+
+ argument :delete_protected_up_to_access_level,
+ Types::ContainerRegistry::Protection::RuleAccessLevelEnum,
+ required: true,
+ description:
+ 'Max GitLab access level to prevent from deleting container images in the container registry. ' \
+ 'For example `DEVELOPER`, `MAINTAINER`, `OWNER`.'
+
+ field :container_registry_protection_rule,
+ Types::ContainerRegistry::Protection::RuleType,
+ null: true,
+ description: 'Container registry protection rule after mutation.'
+
+ def resolve(project_path:, **kwargs)
+ project = authorized_find!(project_path)
+
+ if Feature.disabled?(:container_registry_protected_containers, project)
+ raise_resource_not_available_error!("'container_registry_protected_containers' feature flag is disabled")
+ end
+
+ response = ::ContainerRegistry::Protection::CreateRuleService.new(project, current_user, kwargs).execute
+
+ { container_registry_protection_rule: response.payload[:container_registry_protection_rule],
+ errors: response.errors }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/container_registry/protection/rule_access_level_enum.rb b/app/graphql/types/container_registry/protection/rule_access_level_enum.rb
new file mode 100644
index 00000000000..31e8cbe2e49
--- /dev/null
+++ b/app/graphql/types/container_registry/protection/rule_access_level_enum.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ module ContainerRegistry
+ module Protection
+ class RuleAccessLevelEnum < BaseEnum
+ graphql_name 'ContainerRegistryProtectionRuleAccessLevel'
+ description 'Access level of a container registry protection rule resource'
+
+ ::ContainerRegistry::Protection::Rule.push_protected_up_to_access_levels.each_key do |access_level_key|
+ value access_level_key.upcase, value: access_level_key.to_s,
+ description: "#{access_level_key.capitalize} access."
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/container_registry/protection/rule_type.rb b/app/graphql/types/container_registry/protection/rule_type.rb
new file mode 100644
index 00000000000..387f0202d2d
--- /dev/null
+++ b/app/graphql/types/container_registry/protection/rule_type.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Types
+ module ContainerRegistry
+ module Protection
+ class RuleType < ::Types::BaseObject
+ graphql_name 'ContainerRegistryProtectionRule'
+ description 'A container registry protection rule designed to prevent users with a certain ' \
+ 'access level or lower from altering the container registry.'
+
+ authorize :admin_container_image
+
+ field :id,
+ ::Types::GlobalIDType[::ContainerRegistry::Protection::Rule],
+ null: false,
+ description: 'ID of the container registry protection rule.'
+
+ field :container_path_pattern,
+ GraphQL::Types::String,
+ null: false,
+ description:
+ 'Container repository path pattern protected by the protection rule. ' \
+ 'For example `@my-scope/my-container-*`. Wildcard character `*` allowed.'
+
+ field :push_protected_up_to_access_level,
+ Types::ContainerRegistry::Protection::RuleAccessLevelEnum,
+ null: false,
+ description:
+ 'Max GitLab access level to prevent from pushing container images to the container registry. ' \
+ 'For example `DEVELOPER`, `MAINTAINER`, `OWNER`.'
+
+ field :delete_protected_up_to_access_level,
+ Types::ContainerRegistry::Protection::RuleAccessLevelEnum,
+ null: false,
+ description:
+ 'Max GitLab access level to prevent from pushing container images to the container registry. ' \
+ 'For example `DEVELOPER`, `MAINTAINER`, `OWNER`.'
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 475066e7279..4ff64d6f60c 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -134,6 +134,7 @@ module Types
mount_mutation Mutations::DesignManagement::Move
mount_mutation Mutations::DesignManagement::Update
mount_mutation Mutations::ContainerExpirationPolicies::Update
+ mount_mutation Mutations::ContainerRegistry::Protection::Rule::Create, alpha: { milestone: '16.6' }
mount_mutation Mutations::ContainerRepositories::Destroy
mount_mutation Mutations::ContainerRepositories::DestroyTags
mount_mutation Mutations::Ci::Catalog::Resources::Create, alpha: { milestone: '15.11' }
diff --git a/app/policies/container_registry/protection/rule_policy.rb b/app/policies/container_registry/protection/rule_policy.rb
new file mode 100644
index 00000000000..4dc8dba3276
--- /dev/null
+++ b/app/policies/container_registry/protection/rule_policy.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module ContainerRegistry
+ module Protection
+ class RulePolicy < BasePolicy
+ delegate { @subject.project }
+ end
+ end
+end
diff --git a/app/services/container_registry/protection/create_rule_service.rb b/app/services/container_registry/protection/create_rule_service.rb
new file mode 100644
index 00000000000..34ec6f42b19
--- /dev/null
+++ b/app/services/container_registry/protection/create_rule_service.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module ContainerRegistry
+ module Protection
+ class CreateRuleService < BaseService
+ ALLOWED_ATTRIBUTES = %i[
+ container_path_pattern
+ push_protected_up_to_access_level
+ delete_protected_up_to_access_level
+ ].freeze
+
+ def execute
+ unless can?(current_user, :admin_container_image, project)
+ error_message = _('Unauthorized to create a container registry protection rule')
+ return service_response_error(message: error_message)
+ end
+
+ container_registry_protection_rule =
+ project.container_registry_protection_rules.create(params.slice(*ALLOWED_ATTRIBUTES))
+
+ unless container_registry_protection_rule.persisted?
+ return service_response_error(message: container_registry_protection_rule.errors.full_messages.to_sentence)
+ end
+
+ ServiceResponse.success(payload: { container_registry_protection_rule: container_registry_protection_rule })
+ rescue StandardError => e
+ service_response_error(message: e.message)
+ end
+
+ private
+
+ def service_response_error(message:)
+ ServiceResponse.error(
+ message: message,
+ payload: { container_registry_protection_rule: nil }
+ )
+ end
+ end
+ end
+end
diff --git a/app/views/projects/branch_rules/_show.html.haml b/app/views/projects/branch_rules/_show.html.haml
index c16c03953c6..10cb91e35bd 100644
--- a/app/views/projects/branch_rules/_show.html.haml
+++ b/app/views/projects/branch_rules/_show.html.haml
@@ -3,7 +3,7 @@
- show_status_checks = @project.licensed_feature_available?(:external_status_checks)
- show_approvers = @project.licensed_feature_available?(:merge_request_approvers)
-%section.settings.no-animate#branch-rules{ class: ('expanded' if expanded), data: { qa_selector: 'branch_rules_content' } }
+%section.settings.no-animate#branch-rules{ class: ('expanded' if expanded), data: { testid: 'branch-rules-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Branch rules')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index 00837ce1c73..1083da5402b 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -3,7 +3,7 @@
- mirror_settings_enabled = can?(current_user, :admin_remote_mirror, @project)
- mirror_settings_class = "#{'expanded' if expanded} #{'js-mirror-settings' if mirror_settings_enabled}".strip
-%section.settings.project-mirror-settings.no-animate#js-push-remote-settings{ class: mirror_settings_class, data: { qa_selector: 'mirroring_repositories_settings_content' } }
+%section.settings.project-mirror-settings.no-animate#js-push-remote-settings{ class: mirror_settings_class, data: { testid: 'mirroring-repositories-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= _('Mirroring repositories')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
diff --git a/app/views/projects/protected_tags/shared/_index.html.haml b/app/views/projects/protected_tags/shared/_index.html.haml
index f71ecc3a7c5..5c810b55bec 100644
--- a/app/views/projects/protected_tags/shared/_index.html.haml
+++ b/app/views/projects/protected_tags/shared/_index.html.haml
@@ -1,6 +1,6 @@
- expanded = expanded_by_default?
-%section.settings.no-animate#js-protected-tags-settings{ class: ('expanded' if expanded), data: { qa_selector: 'protected_tag_settings_content' } }
+%section.settings.no-animate#js-protected-tags-settings{ class: ('expanded' if expanded), data: { testid: 'protected-tag-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_("ProtectedTag|Protected tags")
diff --git a/app/views/protected_branches/shared/_index.html.haml b/app/views/protected_branches/shared/_index.html.haml
index 8e72563182c..ce5b58ee189 100644
--- a/app/views/protected_branches/shared/_index.html.haml
+++ b/app/views/protected_branches/shared/_index.html.haml
@@ -1,7 +1,7 @@
- can_admin_entity = protected_branch_can_admin_entity?(protected_branch_entity)
- expanded = expanded_by_default?
-%section.settings.no-animate#js-protected-branches-settings{ class: ('expanded' if expanded), data: { qa_selector: 'protected_branches_settings_content' } }
+%section.settings.no-animate#js-protected-branches-settings{ class: ('expanded' if expanded), data: { testid: 'protected-branches-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
= s_("ProtectedBranch|Protected branches")
diff --git a/app/views/shared/deploy_tokens/_index.html.haml b/app/views/shared/deploy_tokens/_index.html.haml
index ccffc3ec923..74de71867b8 100644
--- a/app/views/shared/deploy_tokens/_index.html.haml
+++ b/app/views/shared/deploy_tokens/_index.html.haml
@@ -1,6 +1,6 @@
- expanded = expand_deploy_tokens_section?(@new_deploy_token, @created_deploy_token)
-%section.settings.no-animate#js-deploy-tokens{ class: ('expanded' if expanded), data: { qa_selector: 'deploy_tokens_settings_content' } }
+%section.settings.no-animate#js-deploy-tokens{ class: ('expanded' if expanded), data: { testid: 'deploy-tokens-settings-content' } }
.settings-header
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= s_('DeployTokens|Deploy tokens')
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do