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:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-09-07 21:09:15 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-09-07 21:09:15 +0300
commit1869c23b11aeda0f8183dd324ebadf59505846f0 (patch)
treef38d6363d0a0962837b0d479df064e8bd8e49d34
parent06c9acad67a086a66f1d63aa1b79fc77a19cc646 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo/layout/line_length.yml1
-rw-r--r--.rubocop_todo/style/format_string.yml1
-rw-r--r--.rubocop_todo/style/redundant_freeze.yml1
-rw-r--r--.rubocop_todo/style/redundant_self.yml1
-rw-r--r--.rubocop_todo/style/string_literals_in_interpolation.yml1
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/commit/commit_form.vue2
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue2
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_editor_header.vue50
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_status.vue17
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/header/validation_segment.vue2
-rw-r--r--app/assets/javascripts/merge_request_tabs.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue2
-rw-r--r--app/assets/stylesheets/page_bundles/merge_requests.scss8
-rw-r--r--app/controllers/groups/runners_controller.rb2
-rw-r--r--app/finders/ci/runners_finder.rb3
-rw-r--r--app/graphql/resolvers/ci/runners_resolver.rb6
-rw-r--r--app/graphql/types/query_type.rb3
-rw-r--r--app/mailers/emails/service_desk.rb6
-rw-r--r--app/models/integrations/campfire.rb28
-rw-r--r--app/services/concerns/service_desk/custom_emails/logger.rb8
-rw-r--r--config/initializers/00_deprecations.rb2
-rw-r--r--db/migrate/20230906175220_replace_sbom_occurrences_component_id_index.rb18
-rw-r--r--db/schema_migrations/202309061752201
-rw-r--r--db/structure.sql2
-rw-r--r--doc/api/api_resources.md2
-rw-r--r--doc/api/code_suggestions.md4
-rw-r--r--doc/api/graphql/reference/index.md2
-rw-r--r--doc/api/members.md4
-rw-r--r--doc/architecture/blueprints/ai_gateway/index.md12
-rw-r--r--doc/ci/environments/kubernetes_dashboard.md4
-rw-r--r--doc/development/ai_architecture.md2
-rw-r--r--doc/development/ai_features/duo_chat.md10
-rw-r--r--doc/development/ai_features/index.md35
-rw-r--r--doc/development/code_suggestions/index.md8
-rw-r--r--doc/development/internal_api/index.md10
-rw-r--r--doc/update/versions/gitlab_16_changes.md38
-rw-r--r--doc/user/discussions/index.md2
-rw-r--r--doc/user/packages/package_registry/supported_functionality.md25
-rw-r--r--doc/user/project/merge_requests/approvals/rules.md7
-rw-r--r--doc/user/project/merge_requests/reviews/index.md2
-rw-r--r--doc/user/project/push_options.md136
-rw-r--r--doc/user/project/repository/code_suggestions/index.md8
-rw-r--r--doc/user/project/repository/code_suggestions/saas.md4
-rw-r--r--doc/user/project/repository/code_suggestions/self_managed.md8
-rw-r--r--doc/user/project/repository/code_suggestions/troubleshooting.md6
-rw-r--r--doc/user/project/repository/jupyter_notebooks/index.md2
-rw-r--r--lib/gitlab/github_import/attachments_downloader.rb28
-rw-r--r--lib/gitlab/github_import/importer/note_attachments_importer.rb17
-rw-r--r--lib/gitlab/github_import/markdown/attachment.rb13
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/controllers/groups/runners_controller_spec.rb11
-rw-r--r--spec/finders/ci/runners_finder_spec.rb88
-rw-r--r--spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_header_spec.js4
-rw-r--r--spec/frontend/merge_request_tabs_spec.js16
-rw-r--r--spec/graphql/resolvers/ci/group_runners_resolver_spec.rb20
-rw-r--r--spec/graphql/resolvers/ci/project_runners_resolver_spec.rb16
-rw-r--r--spec/graphql/resolvers/ci/runners_resolver_spec.rb30
-rw-r--r--spec/lib/gitlab/github_import/attachments_downloader_spec.rb37
-rw-r--r--spec/lib/gitlab/github_import/importer/note_attachments_importer_spec.rb22
-rw-r--r--spec/lib/gitlab/github_import/markdown/attachment_spec.rb24
-rw-r--r--spec/mailers/emails/service_desk_spec.rb4
-rw-r--r--spec/requests/api/graphql/ci/runner_web_url_edge_spec.rb20
-rw-r--r--spec/requests/api/graphql/group_query_spec.rb2
-rw-r--r--spec/requests/api/graphql/groups_query_spec.rb2
-rw-r--r--spec/requests/api/graphql/packages/package_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/merge_request_spec.rb8
-rw-r--r--spec/requests/api/graphql/project/runners_spec.rb14
67 files changed, 565 insertions, 316 deletions
diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml
index c6a4690317f..9fd3d47d8f0 100644
--- a/.rubocop_todo/layout/line_length.yml
+++ b/.rubocop_todo/layout/line_length.yml
@@ -345,7 +345,6 @@ Layout/LineLength:
- 'app/models/integrations/base_chat_notification.rb'
- 'app/models/integrations/base_issue_tracker.rb'
- 'app/models/integrations/bugzilla.rb'
- - 'app/models/integrations/campfire.rb'
- 'app/models/integrations/chat_message/deployment_message.rb'
- 'app/models/integrations/chat_message/merge_message.rb'
- 'app/models/integrations/chat_message/note_message.rb'
diff --git a/.rubocop_todo/style/format_string.yml b/.rubocop_todo/style/format_string.yml
index c5cfe255b96..ed360ae6183 100644
--- a/.rubocop_todo/style/format_string.yml
+++ b/.rubocop_todo/style/format_string.yml
@@ -80,7 +80,6 @@ Style/FormatString:
- 'app/models/integrations/asana.rb'
- 'app/models/integrations/bamboo.rb'
- 'app/models/integrations/bugzilla.rb'
- - 'app/models/integrations/campfire.rb'
- 'app/models/integrations/chat_message/pipeline_message.rb'
- 'app/models/integrations/confluence.rb'
- 'app/models/integrations/custom_issue_tracker.rb'
diff --git a/.rubocop_todo/style/redundant_freeze.yml b/.rubocop_todo/style/redundant_freeze.yml
index 75bc9add5e1..2a6ace4f090 100644
--- a/.rubocop_todo/style/redundant_freeze.yml
+++ b/.rubocop_todo/style/redundant_freeze.yml
@@ -24,7 +24,6 @@ Style/RedundantFreeze:
- 'app/models/error_tracking/project_error_tracking_setting.rb'
- 'app/models/hooks/web_hook.rb'
- 'app/models/integrations/apple_app_store.rb'
- - 'app/models/integrations/campfire.rb'
- 'app/models/integrations/chat_message/base_message.rb'
- 'app/models/integrations/confluence.rb'
- 'app/models/integrations/datadog.rb'
diff --git a/.rubocop_todo/style/redundant_self.yml b/.rubocop_todo/style/redundant_self.yml
index 466b3aac2c5..3dd497248bc 100644
--- a/.rubocop_todo/style/redundant_self.yml
+++ b/.rubocop_todo/style/redundant_self.yml
@@ -87,7 +87,6 @@ Style/RedundantSelf:
- 'app/models/integrations/base_ci.rb'
- 'app/models/integrations/base_issue_tracker.rb'
- 'app/models/integrations/base_slash_commands.rb'
- - 'app/models/integrations/campfire.rb'
- 'app/models/integrations/emails_on_push.rb'
- 'app/models/integrations/jira.rb'
- 'app/models/integrations/pipelines_email.rb'
diff --git a/.rubocop_todo/style/string_literals_in_interpolation.yml b/.rubocop_todo/style/string_literals_in_interpolation.yml
index 30a649cb4fa..c8cd3c9f074 100644
--- a/.rubocop_todo/style/string_literals_in_interpolation.yml
+++ b/.rubocop_todo/style/string_literals_in_interpolation.yml
@@ -6,7 +6,6 @@ Style/StringLiteralsInInterpolation:
- 'app/helpers/colors_helper.rb'
- 'app/models/application_setting_implementation.rb'
- 'app/models/ci/namespace_mirror.rb'
- - 'app/models/integrations/campfire.rb'
- 'app/models/integrations/jira.rb'
- 'app/services/draft_notes/publish_service.rb'
- 'app/services/projects/create_service.rb'
diff --git a/app/assets/javascripts/ci/pipeline_editor/components/commit/commit_form.vue b/app/assets/javascripts/ci/pipeline_editor/components/commit/commit_form.vue
index 1885694187b..baf3dbfa090 100644
--- a/app/assets/javascripts/ci/pipeline_editor/components/commit/commit_form.vue
+++ b/app/assets/javascripts/ci/pipeline_editor/components/commit/commit_form.vue
@@ -108,7 +108,6 @@ export default {
<gl-form-group
id="commit-group"
:label="$options.i18n.commitMessage"
- label-cols-sm="2"
label-for="commit-message"
>
<gl-form-textarea
@@ -122,7 +121,6 @@ export default {
<gl-form-group
id="source-branch-group"
:label="$options.i18n.sourceBranch"
- label-cols-sm="2"
label-for="source-branch-field"
>
<gl-form-input
diff --git a/app/assets/javascripts/ci/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue b/app/assets/javascripts/ci/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
index 7368d1a3a91..da165413341 100644
--- a/app/assets/javascripts/ci/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
+++ b/app/assets/javascripts/ci/pipeline_editor/components/file_nav/pipeline_editor_file_nav.vue
@@ -52,7 +52,7 @@ export default {
};
</script>
<template>
- <div class="gl-mb-4 gl-display-flex gl-flex-wrap gl-gap-3">
+ <div class="gl-display-flex gl-flex-wrap gl-gap-3">
<gl-button
v-if="showFileTreeToggle"
id="file-tree-toggle"
diff --git a/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_editor_header.vue b/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_editor_header.vue
index ec6ee52b6b2..eecf8e42f4b 100644
--- a/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_editor_header.vue
+++ b/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_editor_header.vue
@@ -1,30 +1,11 @@
<script>
+import { GlCard } from '@gitlab/ui';
import PipelineStatus from './pipeline_status.vue';
import ValidationSegment from './validation_segment.vue';
-const baseClasses = ['gl-p-5', 'gl-bg-gray-10', 'gl-border-solid', 'gl-border-gray-100'];
-
-const pipelineStatusClasses = [
- ...baseClasses,
- 'gl-border-1',
- 'gl-border-b-0!',
- 'gl-rounded-top-base',
-];
-
-const validationSegmentClasses = [...baseClasses, 'gl-border-1', 'gl-rounded-base'];
-
-const validationSegmentWithPipelineStatusClasses = [
- ...baseClasses,
- 'gl-border-1',
- 'gl-rounded-bottom-left-base',
- 'gl-rounded-bottom-right-base',
-];
-
export default {
- pipelineStatusClasses,
- validationSegmentClasses,
- validationSegmentWithPipelineStatusClasses,
components: {
+ GlCard,
PipelineStatus,
ValidationSegment,
},
@@ -47,24 +28,19 @@ export default {
showPipelineStatus() {
return !this.isNewCiConfigFile;
},
- // make sure corners are rounded correctly depending on if
- // pipeline status is rendered
- validationStyling() {
- return this.showPipelineStatus
- ? this.$options.validationSegmentWithPipelineStatusClasses
- : this.$options.validationSegmentClasses;
- },
},
};
</script>
<template>
- <div class="gl-mb-5">
- <pipeline-status
- v-if="showPipelineStatus"
- :commit-sha="commitSha"
- :class="$options.pipelineStatusClasses"
- v-on="$listeners"
- />
- <validation-segment :class="validationStyling" :ci-config="ciConfigData" />
- </div>
+ <gl-card
+ class="gl-new-card gl-mb-3"
+ header-class="gl-new-card-header"
+ body-class="gl-new-card-body gl-py-4 gl-px-5"
+ >
+ <template v-if="showPipelineStatus" #header>
+ <pipeline-status :commit-sha="commitSha" v-on="$listeners" />
+ </template>
+
+ <validation-segment :ci-config="ciConfigData" />
+ </gl-card>
</template>
diff --git a/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_status.vue b/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_status.vue
index 5ce3c645145..58b5c0004e0 100644
--- a/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_status.vue
+++ b/app/assets/javascripts/ci/pipeline_editor/components/header/pipeline_status.vue
@@ -138,7 +138,9 @@ export default {
</script>
<template>
- <div class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-flex-wrap">
+ <div
+ class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-flex-wrap gl-w-full"
+ >
<template v-if="showLoadingState">
<div>
<gl-loading-icon class="gl-mr-auto gl-display-inline-block" size="sm" />
@@ -146,13 +148,15 @@ export default {
</div>
</template>
<template v-else-if="hasError">
- <gl-icon class="gl-mr-auto" name="warning-solid" />
- <span data-testid="pipeline-error-msg">{{ $options.i18n.fetchError }}</span>
+ <div>
+ <gl-icon class="gl-mr-auto" name="warning-solid" />
+ <span data-testid="pipeline-error-msg">{{ $options.i18n.fetchError }}</span>
+ </div>
</template>
<template v-else>
<div class="gl-text-truncate gl-md-max-w-50p gl-mr-1">
<a :href="status.detailsPath" class="gl-mr-auto">
- <ci-icon :status="status" :size="16" data-testid="pipeline-status-icon" />
+ <ci-icon :status="status" :size="16" data-testid="pipeline-status-icon" class="gl-mr-2" />
</a>
<span class="gl-font-weight-bold">
<gl-sprintf :message="$options.i18n.pipelineInfo">
@@ -182,9 +186,8 @@ export default {
/>
<pipeline-editor-mini-graph v-else :pipeline="pipeline" v-on="$listeners" />
<gl-button
- class="gl-ml-3"
- category="secondary"
- variant="confirm"
+ class="gl-ml-3 gl-align-self-center"
+ size="small"
:href="status.detailsPath"
data-testid="pipeline-view-btn"
>
diff --git a/app/assets/javascripts/ci/pipeline_editor/components/header/validation_segment.vue b/app/assets/javascripts/ci/pipeline_editor/components/header/validation_segment.vue
index cc0bbeaa71b..d54ad78b3d3 100644
--- a/app/assets/javascripts/ci/pipeline_editor/components/header/validation_segment.vue
+++ b/app/assets/javascripts/ci/pipeline_editor/components/header/validation_segment.vue
@@ -113,7 +113,7 @@ export default {
</template>
<span v-else data-testid="validation-segment">
<span class="gl-max-w-full">
- <gl-icon :name="icon" />
+ <gl-icon :name="icon" class="gl-mr-2" />
<gl-sprintf :message="message">
<template v-if="hasLink" #link="{ content }">
<gl-link :href="helpPath">{{ content }}</gl-link>
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index f0f141c8961..9279e7ca935 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -579,10 +579,12 @@ export default class MergeRequestTabs {
expandViewContainer() {
this.contentWrapper.classList.remove('container-limited');
+ this.contentWrapper.classList.add('diffs-container-limited');
}
resetViewContainer() {
this.contentWrapper.classList.toggle('container-limited', this.isFixedLayoutPreferred);
+ this.contentWrapper.classList.remove('diffs-container-limited');
}
// Expand the issuable sidebar unless the user explicitly collapsed it
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
index 206b6c7699e..903f946e1c6 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -183,7 +183,7 @@ export default {
v-gl-tooltip
:href="ciTroubleshootingDocsPath"
target="_blank"
- :title="__('About this feature')"
+ :title="__('Get more information about troubleshooting pipelines')"
class="gl-display-flex gl-align-items-center gl-ml-2"
>
<gl-icon
diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss
index 14c23c2b7a9..0ab56e35e2d 100644
--- a/app/assets/stylesheets/page_bundles/merge_requests.scss
+++ b/app/assets/stylesheets/page_bundles/merge_requests.scss
@@ -985,6 +985,14 @@ $tabs-holder-z-index: 250;
}
}
+.container-fluid.diffs-container-limited {
+ .flash-container {
+ @include gl-mx-auto;
+ @include gl-max-w-container-xl;
+ @include gl-px-5;
+ }
+}
+
.submit-review-dropdown {
&.show .dropdown-menu {
width: calc(100vw - 20px);
diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb
index b3539da8429..3600a0fbed5 100644
--- a/app/controllers/groups/runners_controller.rb
+++ b/app/controllers/groups/runners_controller.rb
@@ -42,6 +42,8 @@ class Groups::RunnersController < Groups::ApplicationController
@runner ||= Ci::RunnersFinder.new(current_user: current_user, params: group_params).execute
.except(:limit, :offset)
.find(params[:id])
+ rescue Gitlab::Access::AccessDeniedError
+ nil
end
def runner_params
diff --git a/app/finders/ci/runners_finder.rb b/app/finders/ci/runners_finder.rb
index 630be17e64b..331f732bff7 100644
--- a/app/finders/ci/runners_finder.rb
+++ b/app/finders/ci/runners_finder.rb
@@ -24,9 +24,6 @@ module Ci
request_tag_list!
@runners
-
- rescue Gitlab::Access::AccessDeniedError
- Ci::Runner.none
end
def sort_key
diff --git a/app/graphql/resolvers/ci/runners_resolver.rb b/app/graphql/resolvers/ci/runners_resolver.rb
index 4878c0b366a..3289f1d0056 100644
--- a/app/graphql/resolvers/ci/runners_resolver.rb
+++ b/app/graphql/resolvers/ci/runners_resolver.rb
@@ -46,10 +46,16 @@ module Resolvers
::Ci::RunnersFinder
.new(current_user: current_user, params: runners_finder_params(args))
.execute)
+ rescue Gitlab::Access::AccessDeniedError
+ handle_access_denied_error!
end
protected
+ def handle_access_denied_error!
+ raise_resource_not_available_error!
+ end
+
def runners_finder_params(params)
# Give preference to paused argument over the deprecated 'active' argument
paused = params.fetch(:paused, params[:active] ? !params[:active] : nil)
diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb
index e3dd0211029..d02b3e4136f 100644
--- a/app/graphql/types/query_type.rb
+++ b/app/graphql/types/query_type.rb
@@ -128,7 +128,8 @@ module Types
field :runners, Types::Ci::RunnerType.connection_type,
null: true,
resolver: Resolvers::Ci::RunnersResolver,
- description: "Find runners visible to the current user."
+ description: "Get all runners in the GitLab instance (project and shared). " \
+ "Access is restricted to users with administrator access."
field :snippets,
Types::SnippetType.connection_type,
null: true,
diff --git a/app/mailers/emails/service_desk.rb b/app/mailers/emails/service_desk.rb
index b5c04e55146..9f3611df2cc 100644
--- a/app/mailers/emails/service_desk.rb
+++ b/app/mailers/emails/service_desk.rb
@@ -4,6 +4,7 @@ module Emails
module ServiceDesk
extend ActiveSupport::Concern
include MarkupHelper
+ include ::ServiceDesk::CustomEmails::Logger
EMAIL_ATTACHMENTS_SIZE_LIMIT = 10.megabytes.freeze
@@ -61,6 +62,7 @@ module Emails
def service_desk_custom_email_verification_email(service_desk_setting)
@service_desk_setting = service_desk_setting
+ @project = @service_desk_setting.project
email_sender = sender(
Users::Internal.support_bot.id,
@@ -73,7 +75,7 @@ module Emails
subject = format(s_("Notify|Verify custom email address %{email} for %{project_name}"),
email: @service_desk_setting.custom_email,
- project_name: @service_desk_setting.project.name
+ project_name: @project.name
)
options = {
@@ -142,6 +144,8 @@ module Emails
# Only set custom email reply address if it's enabled, not when we force it.
inject_service_desk_custom_email_reply_address unless force
+ log_info(project: @project)
+
mail.delivery_method(::Mail::SMTP, @service_desk_setting.custom_email_credential.delivery_options)
end
diff --git a/app/models/integrations/campfire.rb b/app/models/integrations/campfire.rb
index e21f7d94b5e..8b5797a9d24 100644
--- a/app/models/integrations/campfire.rb
+++ b/app/models/integrations/campfire.rb
@@ -2,7 +2,7 @@
module Integrations
class Campfire < Integration
- SUBDOMAIN_REGEXP = %r{\A[a-z](?:[a-z0-9-]*[a-z0-9])?\z}i.freeze
+ SUBDOMAIN_REGEXP = %r{\A[a-z](?:[a-z0-9-]*[a-z0-9])?\z}i
validates :token, presence: true, if: :activated?
validates :room,
@@ -26,12 +26,9 @@ module Integrations
placeholder: '',
exposes_secrets: true,
help: -> do
- ERB::Util.html_escape(
+ format(ERB::Util.html_escape(
s_('CampfireService|The %{code_open}.campfirenow.com%{code_close} subdomain.')
- ) % {
- code_open: '<code>'.html_safe,
- code_close: '</code>'.html_safe
- }
+ ), code_open: '<code>'.html_safe, code_close: '</code>'.html_safe)
end
field :room,
@@ -48,13 +45,16 @@ module Integrations
end
def help
- docs_link = ActionController::Base.helpers.link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('api/services', anchor: 'campfire'), target: '_blank', rel: 'noopener noreferrer'
-
- ERB::Util.html_escape(
+ docs_link = ActionController::Base.helpers.link_to(
+ _('Learn more.'),
+ Rails.application.routes.url_helpers.help_page_url('api/integrations', anchor: 'campfire'),
+ target: '_blank',
+ rel: 'noopener noreferrer'
+ )
+
+ format(ERB::Util.html_escape(
s_('CampfireService|Send notifications about push events to Campfire chat rooms. %{docs_link}')
- ) % {
- docs_link: docs_link.html_safe
- }
+ ), docs_link: docs_link.html_safe)
end
def self.to_param
@@ -69,7 +69,7 @@ module Integrations
return unless supported_events.include?(data[:object_kind])
message = create_message(data)
- speak(self.room, message, auth)
+ speak(room, message, auth)
end
private
@@ -96,7 +96,7 @@ module Integrations
room = rooms(auth).find { |r| r["name"] == room_name }
return unless room
- path = "/room/#{room["id"]}/speak.json"
+ path = "/room/#{room['id']}/speak.json"
body = {
body: {
message: {
diff --git a/app/services/concerns/service_desk/custom_emails/logger.rb b/app/services/concerns/service_desk/custom_emails/logger.rb
index f00fb8658ac..1817933c3d0 100644
--- a/app/services/concerns/service_desk/custom_emails/logger.rb
+++ b/app/services/concerns/service_desk/custom_emails/logger.rb
@@ -11,17 +11,17 @@ module ServiceDesk
end
end
- def log_info(error_message: nil)
- with_context do
+ def log_info(error_message: nil, project: nil)
+ with_context(project: project) do
Gitlab::AppLogger.info(build_log_message(error_message: error_message))
end
end
- def with_context(&block)
+ def with_context(project: nil, &block)
Gitlab::ApplicationContext.with_context(
related_class: self.class.to_s,
user: current_user,
- project: project,
+ project: project || self.project,
&block
)
end
diff --git a/config/initializers/00_deprecations.rb b/config/initializers/00_deprecations.rb
index 120e818e49a..e254da5b8c6 100644
--- a/config/initializers/00_deprecations.rb
+++ b/config/initializers/00_deprecations.rb
@@ -45,10 +45,12 @@ else
/Merging .* no longer maintain both conditions, and will be replaced by the latter in Rails 7\.0/,
# https://gitlab.com/gitlab-org/gitlab/-/issues/415890
/(Date|Time|TimeWithZone)#to_s.+ is deprecated/,
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/129686
/Sum of non-numeric elements requires an initial argument/
]
view_component_3_warnings = [
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/408988
/Setting a slot with `#\w+` is deprecated and will be removed from ViewComponent 3.0.0/
]
ActiveSupport::Deprecation.disallowed_warnings = rails7_deprecation_warnings + view_component_3_warnings
diff --git a/db/migrate/20230906175220_replace_sbom_occurrences_component_id_index.rb b/db/migrate/20230906175220_replace_sbom_occurrences_component_id_index.rb
new file mode 100644
index 00000000000..9f377675b80
--- /dev/null
+++ b/db/migrate/20230906175220_replace_sbom_occurrences_component_id_index.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class ReplaceSbomOccurrencesComponentIdIndex < Gitlab::Database::Migration[2.1]
+ REMOVED_INDEX_NAME = "index_sbom_occurrences_on_component_id"
+ ADDED_INDEX_NAME = "index_sbom_occurrences_on_component_id_and_id"
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :sbom_occurrences, %i[component_id id], name: ADDED_INDEX_NAME
+ remove_concurrent_index_by_name :sbom_occurrences, name: REMOVED_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :sbom_occurrences, :component_id, name: REMOVED_INDEX_NAME
+ remove_concurrent_index_by_name :sbom_occurrences, name: ADDED_INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20230906175220 b/db/schema_migrations/20230906175220
new file mode 100644
index 00000000000..d063f2fb57f
--- /dev/null
+++ b/db/schema_migrations/20230906175220
@@ -0,0 +1 @@
+70e07f9790b7a9011fce37cc1376d61d84c98ef677fcce534dd97a78f892af86 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 14b61af7aa2..e036032874f 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -33459,7 +33459,7 @@ CREATE UNIQUE INDEX index_sbom_components_on_component_type_name_and_purl_type O
CREATE INDEX index_sbom_occurrences_for_input_file_path_search ON sbom_occurrences USING btree (project_id, component_id, input_file_path);
-CREATE INDEX index_sbom_occurrences_on_component_id ON sbom_occurrences USING btree (component_id);
+CREATE INDEX index_sbom_occurrences_on_component_id_and_id ON sbom_occurrences USING btree (component_id, id);
CREATE INDEX index_sbom_occurrences_on_component_version_id ON sbom_occurrences USING btree (component_version_id);
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index 9c8e15f7614..a764a59e869 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -156,7 +156,7 @@ The following API resources are available outside of project and group contexts
| [Avatar](avatar.md) | `/avatar` |
| [Broadcast messages](broadcast_messages.md) | `/broadcast_messages` |
| [Code snippets](snippets.md) | `/snippets` |
-| [Code suggestions](code_suggestions.md) | `/code_suggestions` |
+| [Code Suggestions](code_suggestions.md) | `/code_suggestions` |
| [Custom attributes](custom_attributes.md) | `/users/:id/custom_attributes` (also available for groups and projects) |
| [Deploy keys](deploy_keys.md) | `/deploy_keys` (also available for projects) |
| [Deploy tokens](deploy_tokens.md) | `/deploy_tokens` (also available for projects and groups) |
diff --git a/doc/api/code_suggestions.md b/doc/api/code_suggestions.md
index 7b59b91254e..d9fc4de3c8e 100644
--- a/doc/api/code_suggestions.md
+++ b/doc/api/code_suggestions.md
@@ -1,6 +1,6 @@
---
-stage: Manage
-group: AI assisted
+stage: Create
+group: Code Creation
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 433e0ddbe63..555cf559f0b 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -649,7 +649,7 @@ Returns [`RunnerSetup`](#runnersetup).
### `Query.runners`
-Find runners visible to the current user.
+Get all runners in the GitLab instance (project and shared). Access is restricted to users with administrator access.
Returns [`CiRunnerConnection`](#cirunnerconnection).
diff --git a/doc/api/members.md b/doc/api/members.md
index 189c6321b3a..7e085a101bb 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -519,7 +519,7 @@ POST /projects/:id/members
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](rest/index.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer/string | yes | The user ID of the new member or multiple IDs separated by commas |
-| `access_level` | integer | yes | A valid access level |
+| `access_level` | integer | yes | [A valid access level](access_requests.md#valid-access-levels) |
| `expires_at` | string | no | A date string in the format `YEAR-MONTH-DAY` |
| `invite_source` | string | no | The source of the invitation that starts the member creation process. GitLab team members can view more information in this confidential issue: `https://gitlab.com/gitlab-org/gitlab/-/issues/327120>`. |
| `tasks_to_be_done` | array of strings | no | Tasks the inviter wants the member to focus on. The tasks are added as issues to a specified project. The possible values are: `ci`, `code` and `issues`. If specified, requires `tasks_project_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `invite_members_for_task`. Disabled by default. |
@@ -571,7 +571,7 @@ PUT /projects/:id/members/:user_id
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](rest/index.md#namespaced-path-encoding) owned by the authenticated user |
| `user_id` | integer | yes | The user ID of the member |
-| `access_level` | integer | yes | A valid access level |
+| `access_level` | integer | yes | A [valid access level](access_requests.md#valid-access-levels) |
| `expires_at` | string | no | A date string in the format `YEAR-MONTH-DAY` |
| `member_role_id` | integer | no | The ID of a member role **(ULTIMATE ALL)** |
diff --git a/doc/architecture/blueprints/ai_gateway/index.md b/doc/architecture/blueprints/ai_gateway/index.md
index ef1020f836a..08cd8b691d4 100644
--- a/doc/architecture/blueprints/ai_gateway/index.md
+++ b/doc/architecture/blueprints/ai_gateway/index.md
@@ -46,7 +46,7 @@ connect to 3rd party providers.
## Language: Python
The AI-Gateway was originally started as the "model-gateway" that
-handled requests from IDEs to provide code suggestions. It was written
+handled requests from IDEs to provide Code Suggestions. It was written
in Python.
Python is an object oriented language that is familiar enough for
@@ -96,7 +96,7 @@ GitLab instances, they differ on these items:
| + Strict protocol definition that is easier to evolve versionless | - No strict schema, so the implementation needs to take good care of supporting multiple versions |
| + A new Ruby-gRPC server for vscode: likely faster because we can limit dependencies to load ([modular monolith](https://gitlab.com/gitlab-org/gitlab/-/issues/365293)) | - Existing Grape API for vscode: meaning slow boot time and unneeded resources loaded |
| + Bi-directional streaming | - Straight forward way to stream requests and responses (could still be added) |
-| - A new Python-gRPC server: we don't have experience running gRPC-Python servers | + Existing Python fastapi server, already running for code suggestions to extend |
+| - A new Python-gRPC server: we don't have experience running gRPC-Python servers | + Existing Python fastapi server, already running for Code Suggestions to extend |
| - Hard to pass on unknown messages from vscode through GitLab to ai-gateway | + Easier support for newer vscode + newer ai-gatway, through old GitLab instance |
| - Unknown support for gRPC in other clients (vscode, jetbrains, other editors) | + Support in all external clients |
| - Possible protocol mismatch (VSCode --REST--> Rails --gRPC--> AI gateway) | + Same protocol across the stack |
@@ -116,7 +116,7 @@ with a stable API over the [provider API we expose](#exposing-ai-providers)
as a direct proxy.
Some features will have specific endpoints, while others can share
-endpoints. For example, code suggestions or chat could have their own
+endpoints. For example, Code Suggestions or chat could have their own
endpoint, while several features that summarize issues or merge
requests could use the same endpoint but make the distinction on what
information is provided in the payload.
@@ -215,9 +215,9 @@ what is in the payload.
To document and validate the content of `payload` we can specify their
format using [JSON-schema](https://json-schema.org/).
-#### Example feature: code suggestions
+#### Example feature: Code Suggestions
-For example, a rough code suggestions service could look like this:
+For example, a rough Code Suggestions service could look like this:
```plaintext
POST /internal/code-suggestions/completions
@@ -281,7 +281,7 @@ The `metadata` field contains information that could be used in a
telemetry endpoint on the AI-gateway where we could count
suggestion-acceptance rates among other things.
-The way we will receive telemetry for code suggestions is being
+The way we will receive telemetry for Code Suggestions is being
discussed in [#415745](https://gitlab.com/gitlab-org/gitlab/-/issues/415745).
We will try to come up with an architecture for all AI-related features.
diff --git a/doc/ci/environments/kubernetes_dashboard.md b/doc/ci/environments/kubernetes_dashboard.md
index f2e8d1f3c89..f8b127cd011 100644
--- a/doc/ci/environments/kubernetes_dashboard.md
+++ b/doc/ci/environments/kubernetes_dashboard.md
@@ -38,7 +38,7 @@ Prerequisites:
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Operate > Environments**.
-1. Select the environment to be associated with the Kubernetes.
+1. Select the environment to be associated with the agent for Kubernetes.
1. Select **Edit**.
1. Select a GitLab agent for Kubernetes.
1. Optional. From the **Kubernetes namespace** dropdown list, select a namespace.
@@ -62,7 +62,7 @@ To view a configured dashboard:
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Operate > Environments**.
-1. Expand the environment associated with GitLab agent for Kubernetes.
+1. Expand the environment associated with the agent for Kubernetes.
1. Expand **Kubernetes overview**.
### Flux sync status
diff --git a/doc/development/ai_architecture.md b/doc/development/ai_architecture.md
index de4ea0ac380..005254db7ee 100644
--- a/doc/development/ai_architecture.md
+++ b/doc/development/ai_architecture.md
@@ -98,7 +98,7 @@ The following table documents functionality that Code Suggestions offers today,
#### Code Suggestions Latency
-Code Suggestions acceptance rates are _highly_ sensitive to latency. While writing code with an AI assistant, a user will pause only for a short duration before continuing on with manually typing out a block of code. As soon as the user has pressed a subsequent keypress, the existing suggestion will be invalidated and a new request will need to be issued to the code suggestions endpoint. In turn, this request will also be highly sensitive to latency.
+Code Suggestions acceptance rates are _highly_ sensitive to latency. While writing code with an AI assistant, a user will pause only for a short duration before continuing on with manually typing out a block of code. As soon as the user has pressed a subsequent keypress, the existing suggestion will be invalidated and a new request will need to be issued to the Code Suggestions endpoint. In turn, this request will also be highly sensitive to latency.
In a worst case with sufficient latency, the IDE could be issuing a string of requests, each of which is then ignored as the user proceeds without waiting for the response. This adds no value for the user, while still putting load on our services.
diff --git a/doc/development/ai_features/duo_chat.md b/doc/development/ai_features/duo_chat.md
index 0dd95ba609a..33d50ab329d 100644
--- a/doc/development/ai_features/duo_chat.md
+++ b/doc/development/ai_features/duo_chat.md
@@ -127,3 +127,13 @@ REAL_AI_REQUEST=1 rspec ee/spec/lib/gitlab/llm/chain/agents/zero_shot/executor_s
When you need to update the test questions that require documentation embeddings,
make sure a new fixture is generated and committed together with the change.
+
+## GraphQL Subscription
+
+The GraphQL Subscription for chat behaves slightly different because it's user-centric. A user could have the chat open on multiple browser tabs, or also on their IDE.
+We therefore need to broadcast messages to multiple clients to keep them in sync. The `aiAction` mutation with the `chat` action behaves the following:
+
+1. All complete chat messages (including messages from the user) are broadcasted with the `userId` and the `resourceId` from the mutation as identifier, ignoring the `clientSubscriptionId`.
+1. Chunks from streamed chat messages are broadcasted with the `userId`, `resourceId`, and `clientSubscriptionId` as identifier.
+
+To truly sync messages between all clients of a user, we need to remove the `resourceId` as well, which will be fixed by [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/420296).
diff --git a/doc/development/ai_features/index.md b/doc/development/ai_features/index.md
index f60ac480dc6..b319e57cae9 100644
--- a/doc/development/ai_features/index.md
+++ b/doc/development/ai_features/index.md
@@ -230,20 +230,41 @@ Remember that other clients are available and you should not use OpenAI.
#### How to receive a response
-As the OpenAI API requests are handled in a background job, we do not keep the request alive and
-the response is sent through the `aiCompletionResponse` subscription:
+The API requests to AI providers are handled in a background job. We therefore do not keep the request alive and the Frontend needs to match the request to the response from the subscription.
-```mutation
-subscription aiCompletionResponse($userId: UserID, $resourceId: AiModelID!) {
- aiCompletionResponse(userId: $userId, resourceId: $resourceId) {
+WARNING:
+Determining the right response to a request can cause problems when only `userId` and `resourceId` are used. For example, when two AI features use the same `userId` and `resourceId` both subscriptions will receive the response from each other. To prevent this intereference, we introduced the `clientSubscriptionId`.
+
+To match a response on the `aiCompletionResponse` subscription, you can provide a `clientSubscriptionId` to the `aiAction` mutation.
+
+- The `clientSubscriptionId` should be unique per feature and within a page to not interfere with other AI features. We recommend to use a `UUID`.
+- Only when the `clientSubscriptionId` is provided as part of the `aiAction` mutation, it will be used for broadcasting the `aiCompletionResponse`.
+- If the `clientSubscriptionId` is not provided, only `userId` and `resourceId` are used for the `aiCompletionResponse`.
+
+As an example mutation for summarizing comments, we provide a `randomId` as part of the mutation:
+
+```graphql
+mutation {
+ aiAction(input: {summarizeComments: {resourceId: "gid://gitlab/Issue/52"}, clientSubscriptionId: "randomId"}) {
+ clientMutationId
+ }
+}
+```
+
+In our component, we then listen on the `aiCompletionResponse` using the `userId`, `resourceId` and `clientSubscriptionId` (`"randomId"`):
+
+```graphql
+subscription aiCompletionResponse($userId: UserID, $resourceId: AiModelID, $clientSubscriptionId: String) {
+ aiCompletionResponse(userId: $userId, resourceId: $resourceId, clientSubscriptionId: $clientSubscriptionId) {
responseBody
errors
}
}
```
-WARNING:
-You should only subscribe to the subscription once the mutation is sent. If multiple subscriptions are active on the same page, they currently all receive updates as our identifier is the user and the resource. To mitigate this, you should only subscribe when the mutation is sent. You can use [`skip()`](You can use [`skip()`](https://apollo.vuejs.org/guide/apollo/subscriptions.html#skipping-the-subscription)) for this case. To prevent this problem in the future, we implement a [request identifier](https://gitlab.com/gitlab-org/gitlab/-/issues/408196).
+Note that the [subscription for chat](duo_chat.md#graphql-subscription) behaves differently.
+
+To not have many concurrent subscriptions, you should also only subscribe to the subscription once the mutation is sent by using [`skip()`](https://apollo.vuejs.org/guide/apollo/subscriptions.html#skipping-the-subscription).
#### Current abstraction layer flow
diff --git a/doc/development/code_suggestions/index.md b/doc/development/code_suggestions/index.md
index 2f598c7b831..5bda95acb87 100644
--- a/doc/development/code_suggestions/index.md
+++ b/doc/development/code_suggestions/index.md
@@ -4,11 +4,11 @@ group: Code Creation
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
-# Code suggestions development guidelines
+# Code Suggestions development guidelines
-## Code suggestions development setup
+## Code Suggestions development setup
-The recommended setup for locally developing and debugging code suggestions is to have all 3 different components running:
+The recommended setup for locally developing and debugging Code Suggestions is to have all 3 different components running:
- IDE Extension (e.g. VSCode Extension)
- Main application configured correctly
@@ -19,7 +19,7 @@ This should enable everyone to see locally any change in an IDE being sent to th
### Setup instructions
1. Install and run locally the [VSCode Extension](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/CONTRIBUTING.md#configuring-development-environment)
- 1. Add the ```"gitlab.debug": true,``` info to the code suggestions development config
+ 1. Add the ```"gitlab.debug": true,``` info to the Code Suggestions development config
1. In VSCode navigate to the Extensions page and find "GitLab Workflow" in the list
1. Open the extension settings by clicking a small cog icon and select "Extension Settings" option
1. Check a "GitLab: Debug" checkbox.
diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md
index bf43546237f..156df31192b 100644
--- a/doc/development/internal_api/index.md
+++ b/doc/development/internal_api/index.md
@@ -822,7 +822,7 @@ Example response:
## Subscription add-on purchases (excluding storage and compute packs)
-The subscription add-on purchase endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`) to apply subscription add-on purchases like code suggestions for personal namespaces, or top-level groups within GitLab.com. It is not used to apply storage and compute pack purchases.
+The subscription add-on purchase endpoint is used by [CustomersDot](https://gitlab.com/gitlab-org/customers-gitlab-com) (`customers.gitlab.com`) to apply subscription add-on purchases like Code Suggestions for personal namespaces, or top-level groups within GitLab.com. It is not used to apply storage and compute pack purchases.
### Create a subscription add-on purchase
@@ -834,9 +834,9 @@ POST /namespaces/:id/subscription_add_on_purchase/:add_on_name
| Attribute | Type | Required | Description |
|:------------|:--------|:---------|:------------|
-| `quantity` | integer | yes | Amount of units in the subscription add-on purchase (Example: Number of seats for a code suggestions add-on) |
+| `quantity` | integer | yes | Amount of units in the subscription add-on purchase (Example: Number of seats for a Code Suggestions add-on) |
| `expires_on` | date | yes | Expiration date of the subscription add-on purchase |
-| `purchase_xid` | string | yes | Identifier for the subscription add-on purchase (Example: Subscription name for a code suggestions add-on) |
+| `purchase_xid` | string | yes | Identifier for the subscription add-on purchase (Example: Subscription name for a Code Suggestions add-on) |
Example request:
@@ -867,9 +867,9 @@ PUT /namespaces/:id/subscription_add_on_purchase/:add_on_name
| Attribute | Type | Required | Description |
|:------------|:--------|:---------|:------------|
-| `quantity` | integer | no | Amount of units in the subscription add-on purchase (Example: Number of seats for a code suggestions add-on) |
+| `quantity` | integer | no | Amount of units in the subscription add-on purchase (Example: Number of seats for a Code Suggestions add-on) |
| `expires_on` | date | yes | Expiration date of the subscription add-on purchase |
-| `purchase_xid` | string | no | Identifier for the subscription add-on purchase (Example: Subscription name for a code suggestions add-on) |
+| `purchase_xid` | string | no | Identifier for the subscription add-on purchase (Example: Subscription name for a Code Suggestions add-on) |
Example request:
diff --git a/doc/update/versions/gitlab_16_changes.md b/doc/update/versions/gitlab_16_changes.md
index 1d03f431629..c57a0072ebd 100644
--- a/doc/update/versions/gitlab_16_changes.md
+++ b/doc/update/versions/gitlab_16_changes.md
@@ -36,6 +36,44 @@ For more information about upgrading GitLab Helm Chart, see [the release notes f
server-side custom hooks.
1. Remove the `[gitlab-shell] dir` configuration.
+- You might encounter the following error while upgrading to GitLab 16.4 or later:
+
+ ```plaintext
+ main: == 20230830084959 ValidatePushRulesConstraints: migrating =====================
+ main: -- execute("SET statement_timeout TO 0")
+ main: -> 0.0002s
+ main: -- execute("ALTER TABLE push_rules VALIDATE CONSTRAINT force_push_regex_size_constraint;")
+ main: -> 0.0004s
+ main: -- execute("RESET statement_timeout")
+ main: -> 0.0003s
+ main: -- execute("ALTER TABLE push_rules VALIDATE CONSTRAINT delete_branch_regex_size_constraint;")
+ rails aborted!
+ StandardError: An error has occurred, all later migrations canceled:
+
+ PG::CheckViolation: ERROR: check constraint "delete_branch_regex_size_constraint" of relation "push_rules" is violated by some row
+ ```
+
+ These constraints might return an error:
+
+ - `author_email_regex_size_constraint`
+ - `branch_name_regex_size_constraint`
+ - `commit_message_negative_regex_size_constraint`
+ - `commit_message_regex_size_constraint`
+ - `delete_branch_regex_size_constraint`
+ - `file_name_regex_size_constraint`
+ - `force_push_regex_size_constraint`
+
+ To fix the error, find the records in the `push_rules` table that exceed the 511
+ character limit.
+
+ ```sql
+ ;; replace `delete_branch_regex` with a name of the field used in constraint
+ SELECT id FROM push_rules WHERE LENGTH(delete_branch_regex) > 511;
+ ```
+
+ Reduce the value length of the regex field for affected push rules records, then
+ retry the migration.
+
## 16.3.0
- For Go applications, [`crypto/tls`: verifying certificate chains containing large RSA keys is slow (CVE-2023-29409)](https://github.com/golang/go/issues/61460)
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index 0bdbfe79775..1cd6857d703 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -13,7 +13,7 @@ type: reference, howto
> - Paginated merge request discussions [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/370075) in GitLab 15.8. Feature flag `paginated_mr_discussions` removed.
GitLab encourages communication through comments, threads, and
-[code suggestions](../project/merge_requests/reviews/suggestions.md).
+[Code Suggestions](../project/merge_requests/reviews/suggestions.md).
Two types of comments are available:
diff --git a/doc/user/packages/package_registry/supported_functionality.md b/doc/user/packages/package_registry/supported_functionality.md
index d3aa522f780..3e8852da808 100644
--- a/doc/user/packages/package_registry/supported_functionality.md
+++ b/doc/user/packages/package_registry/supported_functionality.md
@@ -39,7 +39,7 @@ Packages can be pulled from your project, group, or instance.
| [Maven (with `mvn`)](../maven_repository/index.md) | Y | Y | Y |
| [Maven (with `gradle`)](../maven_repository/index.md) | Y | Y | Y |
| [Maven (with `sbt`)](../maven_repository/index.md) | Y | Y | Y |
-| [npm](../npm_registry/index.md) | Y | N | Y |
+| [npm](../npm_registry/index.md) | Y | Y | Y |
| [NuGet](../nuget_repository/index.md) | Y | Y | N |
| [PyPI](../pypi_repository/index.md) | Y | Y | N |
| [Generic packages](../generic_packages/index.md) | Y | N | N |
@@ -72,7 +72,7 @@ Requests for packages not found in your GitLab project are forwarded to the publ
| [Go](../go_proxy/index.md) | N |
| [Ruby gems](../rubygems_registry/index.md) | N |
-### Deleting packages
+## Deleting packages
When package requests are forwarded to a public registry, deleting packages can
be a [dependency confusion vulnerability](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610).
@@ -89,6 +89,27 @@ To reduce the associated security risks, before deleting a package you can:
- Instance administrators can disable forwarding in the [**Continuous Integration** section](../../../administration/settings/continuous_integration.md#package-registry-configuration) of the Admin Area.
- Group owners can disable forwarding in the **Packages and Registries** section of the group settings.
+## Importing packages from other repositories
+
+You can use GitLab pipelines to import packages from other repositories, such as Maven Central or Artifactory with the [package importer tool](https://gitlab.com/gitlab-org/ci-cd/package-stage/pkgs_importer).
+
+| Package type | Importer available? |
+|-------------------------------------------------------|---------------------|
+| [Maven (with `mvn`)](../maven_repository/index.md) | Y |
+| [Maven (with `gradle`)](../maven_repository/index.md) | Y |
+| [Maven (with `sbt`)](../maven_repository/index.md) | Y |
+| [npm](../npm_registry/index.md) | Y |
+| [NuGet](../nuget_repository/index.md) | Y |
+| [PyPI](../pypi_repository/index.md) | Y |
+| [Generic packages](../generic_packages/index.md) | N |
+| [Terraform](../terraform_module_registry/index.md) | N |
+| [Composer](../composer_repository/index.md) | N |
+| [Conan](../conan_repository/index.md) | N |
+| [Helm](../helm_repository/index.md) | N |
+| [Debian](../debian_repository/index.md) | N |
+| [Go](../go_proxy/index.md) | N |
+| [Ruby gems](../rubygems_registry/index.md) | N |
+
## Allow or prevent duplicates **(FREE ALL)**
By default, the GitLab package registry either allows or prevents duplicates based on the default of that specific package manager format.
diff --git a/doc/user/project/merge_requests/approvals/rules.md b/doc/user/project/merge_requests/approvals/rules.md
index cbbeac17355..3d7ab45f683 100644
--- a/doc/user/project/merge_requests/approvals/rules.md
+++ b/doc/user/project/merge_requests/approvals/rules.md
@@ -261,12 +261,9 @@ For more information, see [Coverage check approval rule](../../../../ci/testing/
## Security Approvals **(ULTIMATE ALL)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/357021) in GitLab 15.0.
+> - Security approvals moved to merge request approvals settings [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/357021) in GitLab 15.0.
> - Bot comment for approvals [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/411656) in GitLab 16.2 [with a flag](../../../../administration/feature_flags.md) named `security_policy_approval_notification`. Enabled by default.
-
-FLAG:
-On self-managed GitLab, by default the bot comment for approvals is available. To hide the feature, an administrator can [disable the feature flag](../../../../administration/feature_flags.md) named `security_policy_approval_notification`.
-On GitLab.com, the bot comment for approvals is available.
+> - Bot comment for approvals [generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/130827) in GitLab 16.3. Feature flag `security_policy_approval_notification` removed.
You can use [scan result policies](../../../application_security/policies/scan-result-policies.md#scan-result-policy-editor) to define security approvals based on the status of vulnerabilities in the merge request and the default branch.
Details for each security policy is shown in the Security Approvals section of your Merge Request configuration.
diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md
index 734c2e399f0..3b8b3009c38 100644
--- a/doc/user/project/merge_requests/reviews/index.md
+++ b/doc/user/project/merge_requests/reviews/index.md
@@ -10,7 +10,7 @@ type: index, reference
[Merge requests](../index.md) are the primary method of making changes to files in a
GitLab project. [Create and submit a merge request](../creating_merge_requests.md)
to propose changes. Your team leaves [comments](../../../discussions/index.md) on
-your merge request, and makes [code suggestions](suggestions.md) you can accept
+your merge request, and makes [Code Suggestions](suggestions.md) you can accept
from the user interface. When your work is reviewed, your team members can choose
to accept or reject it.
diff --git a/doc/user/project/push_options.md b/doc/user/project/push_options.md
index d0a938e054d..e8451e3049d 100644
--- a/doc/user/project/push_options.md
+++ b/doc/user/project/push_options.md
@@ -6,119 +6,97 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Push options **(FREE ALL)**
-GitLab supports using client-side [Git push options](https://git-scm.com/docs/git-push#Documentation/git-push.txt--oltoptiongt)
-to perform various actions at the same time as pushing changes. Additionally, [Push Rules](repository/push_rules.md) offer server-side control and enforcement options.
+When you push changes to a branch, you can use client-side
+[Git push options](https://git-scm.com/docs/git-push#Documentation/git-push.txt--oltoptiongt).
+In Git 2.10 and later, use Git push options to:
-Currently, there are push options available for:
+- [Skip CI jobs](#push-options-for-gitlab-cicd)
+- [Push to merge requests](#push-options-for-merge-requests)
-- [Skipping CI jobs](#push-options-for-gitlab-cicd)
-- [Merge requests](#push-options-for-merge-requests)
-
-NOTE:
-Git push options are only available with Git 2.10 or newer.
-
-For Git versions 2.10 to 2.17 use `--push-option`:
+In Git 2.18 and later, you can use either the long format (`--push-option`) or the shorter `-o`:
```shell
-git push --push-option=<push_option>
+git push -o <push_option>
```
-For version 2.18 and later, you can use the above format, or the shorter `-o`:
+In Git 2.10 to 2.17, you must use the long format:
```shell
-git push -o <push_option>
+git push --push-option=<push_option>
```
+For server-side controls and enforcement of best practices, see
+[push rules](repository/push_rules.md) and [server hooks](../../administration/server_hooks.md).
+
## Push options for GitLab CI/CD
You can use push options to skip a CI/CD pipeline, or pass CI/CD variables.
-| Push option | Description | Introduced in version |
-| ------------------------------ | ------------------------------------------------------------------------------------------- |---------------------- |
-| `ci.skip` | Do not create a CI pipeline for the latest push. Only skips branch pipelines and not [merge request pipelines](../../ci/pipelines/merge_request_pipelines.md). This does not skip pipelines for CI integrations, such as Jenkins. | [11.7](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15643) |
-| `ci.variable="<name>=<value>"` | Provide [CI/CD variables](../../ci/variables/index.md) to be used in a CI pipeline, if one is created due to the push. Only passes variables to branch pipelines and not [merge request pipelines](../../ci/pipelines/merge_request_pipelines.md). | [12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/27983) |
-| `integrations.skip_ci` | Skip push events for CI integrations, such as Atlassian Bamboo, Buildkite, Drone, Jenkins, and JetBrains TeamCity. | [16.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123837) |
+| Push option | Description | Example |
+|--------------------------------|-------------|---------|
+| `ci.skip` | Do not create a CI/CD pipeline for the latest push. Skips only branch pipelines and not [merge request pipelines](../../ci/pipelines/merge_request_pipelines.md). This does not skip pipelines for CI/CD integrations, such as Jenkins. | `git push -o ci.skip` |
+| `ci.variable="<name>=<value>"` | Provide [CI/CD variables](../../ci/variables/index.md) to the CI/CD pipeline, if one is created due to the push. Passes variables only to branch pipelines and not [merge request pipelines](../../ci/pipelines/merge_request_pipelines.md). | `git push -o ci.variable="MAX_RETRIES=10" -o ci.variable="MAX_TIME=600"` |
+| `integrations.skip_ci` | Skip push events for CI/CD integrations, such as Atlassian Bamboo, Buildkite, Drone, Jenkins, and JetBrains TeamCity. Introduced in [GitLab 16.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123837). | `git push -o integrations.skip_ci` |
-An example of using `ci.skip`:
-
-```shell
-git push -o ci.skip
-```
-
-An example of passing some CI/CD variables for a pipeline:
-
-```shell
-git push -o ci.variable="MAX_RETRIES=10" -o ci.variable="MAX_TIME=600"
-```
+## Push options for merge requests
-An example of using `integrations.skip_ci`:
+Git push options can perform actions for merge requests while pushing changes:
-```shell
-git push -o integrations.skip_ci
-```
+| Push option | Description |
+|----------------------------------------------|-------------|
+| `merge_request.create` | Create a new merge request for the pushed branch. |
+| `merge_request.target=<branch_name>` | Set the target of the merge request to a particular branch or upstream project, such as: `git push -o merge_request.target=project_path/branch`. |
+| `merge_request.merge_when_pipeline_succeeds` | Set the merge request to [merge when its pipeline succeeds](merge_requests/merge_when_pipeline_succeeds.md). |
+| `merge_request.remove_source_branch` | Set the merge request to remove the source branch when it's merged. |
+| `merge_request.title="<title>"` | Set the title of the merge request. For example: `git push -o merge_request.title="The title I want"`. |
+| `merge_request.description="<description>"` | Set the description of the merge request. For example: `git push -o merge_request.description="The description I want"`. |
+| `merge_request.draft` | Mark the merge request as a draft. For example: `git push -o merge_request.draft`. Introduced in [GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/296673). |
+| `merge_request.milestone="<milestone>"` | Set the milestone of the merge request. For example: `git push -o merge_request.milestone="3.0"`. Introduced in [GitLab 14.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63960). |
+| `merge_request.label="<label>"` | Add labels to the merge request. If the label does not exist, it is created. For example, for two labels: `git push -o merge_request.label="label1" -o merge_request.label="label2"`. |
+| `merge_request.unlabel="<label>"` | Remove labels from the merge request. For example, for two labels: `git push -o merge_request.unlabel="label1" -o merge_request.unlabel="label2"`. |
+| `merge_request.assign="<user>"` | Assign users to the merge request. Accepts username or user ID. For example, for two users: `git push -o merge_request.assign="user1" -o merge_request.assign="user2"`. Support for usernames added in [GitLab 15.5](https://gitlab.com/gitlab-org/gitlab/-/issues/344276). |
+| `merge_request.unassign="<user>"` | Remove assigned users from the merge request. Accepts username or user ID. For example, for two users: `git push -o merge_request.unassign="user1" -o merge_request.unassign="user2"`. Support for usernames added in [GitLab 15.5](https://gitlab.com/gitlab-org/gitlab/-/issues/344276). |
-## Push options for merge requests
+## Formats for push options
-You can use Git push options to perform certain actions for merge requests at the same
-time as pushing changes:
-
-| Push option | Description | Introduced in version |
-| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | --------------------- |
-| `merge_request.create` | Create a new merge request for the pushed branch. | [11.10](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26752) |
-| `merge_request.target=<branch_name>` | Set the target of the merge request to a particular branch or upstream project, such as: `git push -o merge_request.target=project_path/branch` | [11.10](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26752) |
-| `merge_request.merge_when_pipeline_succeeds` | Set the merge request to [merge when its pipeline succeeds](merge_requests/merge_when_pipeline_succeeds.md). | [11.10](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26752) |
-| `merge_request.remove_source_branch` | Set the merge request to remove the source branch when it's merged. | [12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64320) |
-| `merge_request.title="<title>"` | Set the title of the merge request. For example: `git push -o merge_request.title="The title I want"`. | [12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64320) |
-| `merge_request.description="<description>"` | Set the description of the merge request. For example: `git push -o merge_request.description="The description I want"`. | [12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64320) |
-| `merge_request.draft` | Mark the merge request as a draft. For example: `git push -o merge_request.draft`. | [15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/296673) |
-| `merge_request.milestone="<milestone>"` | Set the milestone of the merge request. For example: `git push -o merge_request.milestone="3.0"`. | [14.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63960) |
-| `merge_request.label="<label>"` | Add labels to the merge request. If the label does not exist, it is created. For example, for two labels: `git push -o merge_request.label="label1" -o merge_request.label="label2"`. | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) |
-| `merge_request.unlabel="<label>"` | Remove labels from the merge request. For example, for two labels: `git push -o merge_request.unlabel="label1" -o merge_request.unlabel="label2"`. | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) |
-| `merge_request.assign="<user>"` | Assign users to the merge request. Accepts username or user ID. For example, for two users: `git push -o merge_request.assign="user1" -o merge_request.assign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904), support for usernames added in [15.5](https://gitlab.com/gitlab-org/gitlab/-/issues/344276) |
-| `merge_request.unassign="<user>"` | Remove assigned users from the merge request. Accepts username or user ID.For example, for two users: `git push -o merge_request.unassign="user1" -o merge_request.unassign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904), support for usernames added in [15.5](https://gitlab.com/gitlab-org/gitlab/-/issues/344276) |
-
-If you use a push option that requires text with spaces in it, you need to enclose it
-in quotes (`"`). You can omit the quotes if there are no spaces. Some examples:
+If your push option requires text containing spaces, enclose the text in
+double quotes (`"`). You can omit the quotes if there are no spaces. Some examples:
```shell
git push -o merge_request.label="Label with spaces"
git push -o merge_request.label=Label-with-no-spaces
```
-You can combine push options to accomplish multiple tasks at once, by using
-multiple `-o` (or `--push-option`) flags. For example, if you want to create a new
-merge request, and target a branch named `my-target-branch`:
+To combine push options to accomplish multiple tasks at once, use
+multiple `-o` (or `--push-option`) flags. This command creates a
+new merge request, targets a branch (`my-target-branch`), and sets auto-merge:
```shell
-git push -o merge_request.create -o merge_request.target=my-target-branch
+git push -o merge_request.create -o merge_request.target=my-target-branch -o merge_request.merge_when_pipeline_succeeds
```
-Additionally if you want the merge request to merge as soon as the pipeline succeeds you can do:
+## Create Git aliases for common commands
-```shell
-git push -o merge_request.create -o merge_request.target=my-target-branch -o merge_request.merge_when_pipeline_succeeds
-```
+Adding push options to Git commands can create very long commands. If
+you use the same push options frequently, create Git aliases for them.
+Git aliases are command-line shortcuts for longer Git commands.
-## Useful Git aliases
+To create and use a Git alias for the
+[merge when pipeline succeeds Git push option](#push-options-for-merge-requests):
-As shown above, Git push options can cause Git commands to grow very long. If
-you use the same push options frequently, it's useful to create
-[Git aliases](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases). Git aliases
-are command line shortcuts for Git which can significantly simplify the use of
-long Git commands.
+1. In your terminal window, run this command:
-### Merge when pipeline succeeds alias
+ ```shell
+ git config --global alias.mwps "push -o merge_request.create -o merge_request.target=main -o merge_request.merge_when_pipeline_succeeds"
+ ```
-To set up a Git alias for the
-[merge when pipeline succeeds Git push option](#push-options-for-merge-requests):
+1. To use the alias to push a local branch that targets the default branch (`main`)
+ and auto-merges, run this command:
-```shell
-git config --global alias.mwps "push -o merge_request.create -o merge_request.target=master -o merge_request.merge_when_pipeline_succeeds"
-```
+ ```shell
+ git mwps origin <local-branch-name>
+ ```
-Then to quickly push a local branch that targets the default branch and merges when the
-pipeline succeeds:
+## Related topics
-```shell
-git mwps origin <local-branch-name>
-```
+- [Git aliases](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases) in the Git documentation
diff --git a/doc/user/project/repository/code_suggestions/index.md b/doc/user/project/repository/code_suggestions/index.md
index d0ef6df48b8..fd0d99b5a84 100644
--- a/doc/user/project/repository/code_suggestions/index.md
+++ b/doc/user/project/repository/code_suggestions/index.md
@@ -1,6 +1,6 @@
---
-stage: AI-powered
-group: AI Model Validation
+stage: Create
+group: Code Creation
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
@@ -135,7 +135,7 @@ Learn more about Google Vertex AI [`code-gecko`](https://cloud.google.com/vertex
### Training data
-Code suggestions are routed through Google Vertex AI Codey APIs. Learn more about Google Vertex AI Codey APIs [Data Governance](https://cloud.google.com/vertex-ai/docs/generative-ai/data-governance) and [Responsible AI](https://cloud.google.com/vertex-ai/docs/generative-ai/learn/responsible-ai).
+Code Suggestions are routed through Google Vertex AI Codey APIs. Learn more about Google Vertex AI Codey APIs [Data Governance](https://cloud.google.com/vertex-ai/docs/generative-ai/data-governance) and [Responsible AI](https://cloud.google.com/vertex-ai/docs/generative-ai/learn/responsible-ai).
Google Vertex AI Codey APIs are not trained on private non-public GitLab customer or user data.
@@ -167,7 +167,7 @@ We strongly encourage all beta users to leverage GitLab native
[Security Scanning](../../../application_security/index.md) capabilities.
GitLab currently does not retrain Google Vertex AI Codey APIs. GitLab makes no claims
-to the accuracy or quality of code suggestions generated by Google Vertex AI Codey API.
+to the accuracy or quality of Code Suggestions generated by Google Vertex AI Codey API.
Read more about [Google Vertex AI foundation model capabilities](https://cloud.google.com/vertex-ai/docs/generative-ai/learn/models).
## Known limitations
diff --git a/doc/user/project/repository/code_suggestions/saas.md b/doc/user/project/repository/code_suggestions/saas.md
index 6210786259a..1eea8dde6ed 100644
--- a/doc/user/project/repository/code_suggestions/saas.md
+++ b/doc/user/project/repository/code_suggestions/saas.md
@@ -1,6 +1,6 @@
---
-stage: AI-powered
-group: AI Model Validation
+stage: Create
+group: Code Creation
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
diff --git a/doc/user/project/repository/code_suggestions/self_managed.md b/doc/user/project/repository/code_suggestions/self_managed.md
index 7c88937dac9..51bb65b5be3 100644
--- a/doc/user/project/repository/code_suggestions/self_managed.md
+++ b/doc/user/project/repository/code_suggestions/self_managed.md
@@ -1,6 +1,6 @@
---
-stage: AI-powered
-group: AI Model Validation
+stage: Create
+group: Code Creation
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
@@ -56,7 +56,7 @@ To enable Code Suggestions for your self-managed GitLab instance:
This setting is visible only in self-managed GitLab instances.
WARNING:
-In GitLab 16.2 and earlier, if you clear the **Turn on code suggestions for this instance** checkbox, the users in your instance can still use Code Suggestions for up to one hour, until the issued JSON web token (JWT) expires.
+In GitLab 16.2 and earlier, if you clear the **Turn on Code Suggestions for this instance** checkbox, the users in your instance can still use Code Suggestions for up to one hour, until the issued JSON web token (JWT) expires.
To make sure Code Suggestions works immediately, you must [manually synchronize your subscription](#manually-synchronize-your-subscription).
@@ -101,7 +101,7 @@ To enable Code Suggestions for your self-managed GitLab instance:
This setting is visible only in self-managed GitLab instances.
WARNING:
-If you clear the **Turn on code suggestions for this instance** checkbox, the users in your instance can still use Code Suggestions for up to one hour, until the issued JSON web token (JWT) expires.
+If you clear the **Turn on Code Suggestions for this instance** checkbox, the users in your instance can still use Code Suggestions for up to one hour, until the issued JSON web token (JWT) expires.
#### Request access to Code Suggestions
diff --git a/doc/user/project/repository/code_suggestions/troubleshooting.md b/doc/user/project/repository/code_suggestions/troubleshooting.md
index 69cca42e877..4c4c672c2a8 100644
--- a/doc/user/project/repository/code_suggestions/troubleshooting.md
+++ b/doc/user/project/repository/code_suggestions/troubleshooting.md
@@ -1,6 +1,6 @@
---
-stage: AI-powered
-group: AI Model Validation
+stage: Create
+group: Code Creation
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: index, reference
---
@@ -66,4 +66,4 @@ specifically the token system. To resolve the issue:
1. Remove the existing personal access token from your GitLab account settings.
1. Reauthorize your GitLab account in VS Code using OAuth.
-1. Test the code suggestions feature with different file extensions to verify if the issue is resolved.
+1. Test the Code Suggestions feature with different file extensions to verify if the issue is resolved.
diff --git a/doc/user/project/repository/jupyter_notebooks/index.md b/doc/user/project/repository/jupyter_notebooks/index.md
index 70ee841a991..2a1fc0cddf8 100644
--- a/doc/user/project/repository/jupyter_notebooks/index.md
+++ b/doc/user/project/repository/jupyter_notebooks/index.md
@@ -37,7 +37,7 @@ When commits include changes to Jupyter Notebook files, GitLab:
- Enables switching between raw and rendered diffs on the Commit and Compare pages. (Not available on merge request pages.)
- Renders images on the diffs.
-Code suggestions are not available on diffs and merge requests for `.ipynb` files.
+Code Suggestions are not available on diffs and merge requests for `.ipynb` files.
Cleaner notebook diffs are not generated when the notebook is too large.
diff --git a/lib/gitlab/github_import/attachments_downloader.rb b/lib/gitlab/github_import/attachments_downloader.rb
index b71d5f753f2..7dc04f21dd6 100644
--- a/lib/gitlab/github_import/attachments_downloader.rb
+++ b/lib/gitlab/github_import/attachments_downloader.rb
@@ -12,11 +12,13 @@ module Gitlab
FILENAME_SIZE_LIMIT = 255 # chars before the extension
DEFAULT_FILE_SIZE_LIMIT = 25.megabytes
TMP_DIR = File.join(Dir.tmpdir, 'github_attachments').freeze
+ GITHUB_ASSETS_URL_REGEX = %r{#{Regexp.escape(::Gitlab::GithubImport::MarkdownText.github_url)}/.*/assets/}
- attr_reader :file_url, :filename, :file_size_limit
+ attr_reader :file_url, :filename, :file_size_limit, :options
- def initialize(file_url, file_size_limit: DEFAULT_FILE_SIZE_LIMIT)
+ def initialize(file_url, options: {}, file_size_limit: DEFAULT_FILE_SIZE_LIMIT)
@file_url = file_url
+ @options = options
@file_size_limit = file_size_limit
filename = URI(file_url).path.split('/').last
@@ -27,7 +29,9 @@ module Gitlab
validate_content_length
validate_filepath
- file = download
+ redirection_url = get_download_redirection_url
+ file = download_from(redirection_url)
+
validate_symlink
file
end
@@ -47,9 +51,23 @@ module Gitlab
Gitlab::HTTP.perform_request(Net::HTTP::Head, file_url, {}).headers
end
- def download
+ # Github /assets redirection link will redirect to aws which has its own authorization.
+ # Keeping our bearer token will cause request rejection
+ # eg. Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter,
+ # Signature query string parameter or the Authorization header should be specified.
+ def get_download_redirection_url
+ return file_url unless file_url.starts_with?(GITHUB_ASSETS_URL_REGEX)
+
+ options[:follow_redirects] = false
+ response = Gitlab::HTTP.perform_request(Net::HTTP::Get, file_url, options)
+ raise_error("expected a redirect response, got #{response.code}") unless response.redirection?
+
+ response.headers[:location]
+ end
+
+ def download_from(url)
file = File.open(filepath, 'wb')
- Gitlab::HTTP.perform_request(Net::HTTP::Get, file_url, stream_body: true) { |batch| file.write(batch) }
+ Gitlab::HTTP.perform_request(Net::HTTP::Get, url, stream_body: true) { |batch| file.write(batch) }
file
end
diff --git a/lib/gitlab/github_import/importer/note_attachments_importer.rb b/lib/gitlab/github_import/importer/note_attachments_importer.rb
index 266ee2938ba..f9173f9a9ba 100644
--- a/lib/gitlab/github_import/importer/note_attachments_importer.rb
+++ b/lib/gitlab/github_import/importer/note_attachments_importer.rb
@@ -4,14 +4,15 @@ module Gitlab
module GithubImport
module Importer
class NoteAttachmentsImporter
- attr_reader :note_text, :project
+ attr_reader :note_text, :project, :client
# note_text - An instance of `Gitlab::GithubImport::Representation::NoteText`.
# project - An instance of `Project`.
# client - An instance of `Gitlab::GithubImport::Client`.
- def initialize(note_text, project, _client = nil)
+ def initialize(note_text, project, client)
@note_text = note_text
@project = project
+ @client = client
end
def execute
@@ -33,7 +34,7 @@ module Gitlab
if attachment.part_of_project_blob?(project_import_source)
convert_project_content_link(attachment.url, project_import_source)
- elsif attachment.media? || attachment.doc_belongs_to_project?(project_import_source)
+ elsif attachment.media?(project_import_source) || attachment.doc_belongs_to_project?(project_import_source)
download_attachment(attachment)
else # url to other GitHub project
attachment.url
@@ -53,7 +54,7 @@ module Gitlab
# in: an instance of Gitlab::GithubImport::Markdown::Attachment
# out: gitlab attachment markdown url
def download_attachment(attachment)
- downloader = ::Gitlab::GithubImport::AttachmentsDownloader.new(attachment.url)
+ downloader = ::Gitlab::GithubImport::AttachmentsDownloader.new(attachment.url, options: options)
file = downloader.perform
uploader = UploadService.new(project, file, FileUploader).execute
uploader.to_h[:url]
@@ -61,6 +62,14 @@ module Gitlab
downloader&.delete
end
+ def options
+ {
+ headers: {
+ 'Authorization' => "Bearer #{client.octokit.access_token}"
+ }
+ }
+ end
+
def update_note_record(text)
case note_text.record_type
when ::Release.name
diff --git a/lib/gitlab/github_import/markdown/attachment.rb b/lib/gitlab/github_import/markdown/attachment.rb
index e270cfba619..0d8f3196719 100644
--- a/lib/gitlab/github_import/markdown/attachment.rb
+++ b/lib/gitlab/github_import/markdown/attachment.rb
@@ -57,7 +57,8 @@ module Gitlab
def github_url?(url, docs: false, media: false)
if media
- url.start_with?(::Gitlab::GithubImport::MarkdownText::GITHUB_MEDIA_CDN)
+ url.start_with?(::Gitlab::GithubImport::MarkdownText.github_url,
+ ::Gitlab::GithubImport::MarkdownText::GITHUB_MEDIA_CDN)
elsif docs
url.start_with?(::Gitlab::GithubImport::MarkdownText.github_url)
end
@@ -65,6 +66,9 @@ module Gitlab
def whitelisted_type?(url, docs: false, media: false)
if media
+ # We do not know the file extension type from the /assets markdown
+ return true if url.start_with?(::Gitlab::GithubImport::MarkdownText.github_url)
+
MEDIA_TYPES.any? { |type| url.end_with?(type) }
elsif docs
DOC_TYPES.any? { |type| url.end_with?(type) }
@@ -91,8 +95,11 @@ module Gitlab
)
end
- def media?
- url.start_with?(::Gitlab::GithubImport::MarkdownText::GITHUB_MEDIA_CDN)
+ def media?(import_source)
+ url.start_with?(
+ "#{::Gitlab::GithubImport::MarkdownText.github_url}/#{import_source}/assets",
+ ::Gitlab::GithubImport::MarkdownText::GITHUB_MEDIA_CDN
+ )
end
def inspect
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 857d53488ea..5c5bd0f917e 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -21256,6 +21256,9 @@ msgstr ""
msgid "Get a support subscription"
msgstr ""
+msgid "Get more information about troubleshooting pipelines"
+msgstr ""
+
msgid "Get started"
msgstr ""
diff --git a/spec/controllers/groups/runners_controller_spec.rb b/spec/controllers/groups/runners_controller_spec.rb
index e427b7c9572..a4e55a89f41 100644
--- a/spec/controllers/groups/runners_controller_spec.rb
+++ b/spec/controllers/groups/runners_controller_spec.rb
@@ -3,8 +3,9 @@
require 'spec_helper'
RSpec.describe Groups::RunnersController, feature_category: :runner_fleet do
- let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:namespace_settings) { create(:namespace_settings, runner_registration_enabled: true) }
+ let_it_be(:group) { create(:group, namespace_settings: namespace_settings) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:runner) { create(:ci_runner, :group, groups: [group]) }
@@ -226,6 +227,12 @@ RSpec.describe Groups::RunnersController, feature_category: :runner_fleet do
expect(response).to render_template(:edit)
end
+ it 'renders 404 for non-existing runner' do
+ get :edit, params: { group_id: group, id: non_existing_record_id }
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
it 'renders 404 for instance runner' do
get :edit, params: { group_id: group, id: instance_runner }
diff --git a/spec/finders/ci/runners_finder_spec.rb b/spec/finders/ci/runners_finder_spec.rb
index be1c96594fb..5d249ddb391 100644
--- a/spec/finders/ci/runners_finder_spec.rb
+++ b/spec/finders/ci/runners_finder_spec.rb
@@ -222,12 +222,14 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
end
shared_examples 'executes as normal user' do
- it 'returns no runners' do
+ it 'raises Gitlab::Access::AccessDeniedError' do
user = create :user
create :ci_runner, active: true
create :ci_runner, active: false
- expect(described_class.new(current_user: user, params: {}).execute).to be_empty
+ expect do
+ described_class.new(current_user: user, params: {}).execute
+ end.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
@@ -250,12 +252,14 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
end
context 'when user is nil' do
- it 'returns no runners' do
+ it 'raises Gitlab::Access::AccessDeniedError' do
user = nil
create :ci_runner, active: true
create :ci_runner, active: false
- expect(described_class.new(current_user: user, params: {}).execute).to be_empty
+ expect do
+ described_class.new(current_user: user, params: {}).execute
+ end.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
end
@@ -306,10 +310,11 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
shared_examples 'membership equal to :descendants' do
it 'returns all descendant runners' do
- expect(subject).to eq([runner_project_7, runner_project_6, runner_project_5,
- runner_project_4, runner_project_3, runner_project_2,
- runner_project_1, runner_sub_group_4, runner_sub_group_3,
- runner_sub_group_2, runner_sub_group_1, runner_group])
+ is_expected.to contain_exactly(
+ runner_project_7, runner_project_6, runner_project_5,
+ runner_project_4, runner_project_3, runner_project_2,
+ runner_project_1, runner_sub_group_4, runner_sub_group_3,
+ runner_sub_group_2, runner_sub_group_1, runner_group)
end
end
@@ -340,7 +345,7 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
let(:membership) { :direct }
it 'returns runners belonging to group' do
- expect(subject).to eq([runner_group])
+ is_expected.to contain_exactly(runner_group)
end
end
@@ -348,10 +353,11 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
let(:membership) { :all_available }
it 'returns runners available to group' do
- expect(subject).to match_array([runner_project_7, runner_project_6, runner_project_5,
- runner_project_4, runner_project_3, runner_project_2,
- runner_project_1, runner_sub_group_4, runner_sub_group_3,
- runner_sub_group_2, runner_sub_group_1, runner_group, runner_instance])
+ is_expected.to contain_exactly(
+ runner_project_7, runner_project_6, runner_project_5,
+ runner_project_4, runner_project_3, runner_project_2,
+ runner_project_1, runner_sub_group_4, runner_sub_group_3,
+ runner_sub_group_2, runner_sub_group_1, runner_group, runner_instance)
end
end
@@ -366,9 +372,9 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
context 'with nil group' do
let(:target_group) { nil }
- it 'returns no runners' do
- # Query should run against all runners, however since user is not admin, query returns no results
- expect(subject).to eq([])
+ it 'raises Gitlab::Access::AccessDeniedError' do
+ # Query should run against all runners, however since user is not admin, we raise an error
+ expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
@@ -443,23 +449,23 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
context 'with :sub_group_1 as target group' do
let(:target_group) { sub_group_1 }
- it 'returns no runners' do
- is_expected.to be_empty
+ it 'raises Gitlab::Access::AccessDeniedError' do
+ expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
context 'with :group as target group' do
let(:target_group) { group }
- it 'returns no runners' do
- is_expected.to be_empty
+ it 'raises Gitlab::Access::AccessDeniedError' do
+ expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end
context 'with :all_available membership' do
let(:membership) { :all_available }
- it 'returns no runners' do
- expect(subject).to be_empty
+ it 'raises Gitlab::Access::AccessDeniedError' do
+ expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
end
@@ -467,35 +473,31 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
end
context 'when user has no access' do
- it 'returns no runners' do
- expect(subject).to be_empty
+ it 'raises Gitlab::Access::AccessDeniedError' do
+ expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
context 'when user is nil' do
- let_it_be(:user) { nil }
+ let(:user) { nil }
- it 'returns no runners' do
- expect(subject).to be_empty
+ it 'raises Gitlab::Access::AccessDeniedError' do
+ expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
end
describe '#sort_key' do
- subject { described_class.new(current_user: user, params: params.merge(group: group)).sort_key }
+ subject(:sort_key) { described_class.new(current_user: user, params: params.merge(group: group)).sort_key }
context 'without params' do
- it 'returns created_at_desc' do
- expect(subject).to eq('created_at_desc')
- end
+ it { is_expected.to eq('created_at_desc') }
end
context 'with params' do
let(:extra_params) { { sort: 'contacted_asc' } }
- it 'returns contacted_asc' do
- expect(subject).to eq('contacted_asc')
- end
+ it { is_expected.to eq('contacted_asc') }
end
end
end
@@ -510,7 +512,7 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
let(:params) { { project: project }.merge(extra_params).reject { |_, v| v.nil? } }
describe '#execute' do
- subject { described_class.new(current_user: user, params: params).execute }
+ subject(:execute) { described_class.new(current_user: user, params: params).execute }
context 'with user as project admin' do
before do
@@ -521,7 +523,7 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
let_it_be(:runner_project) { create(:ci_runner, :project, contacted_at: 7.minutes.ago, projects: [project]) }
it 'returns runners available to project' do
- expect(subject).to match_array([runner_project])
+ is_expected.to match_array([runner_project])
end
end
@@ -530,7 +532,7 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
let_it_be(:runner_group) { create(:ci_runner, :group, contacted_at: 12.minutes.ago, groups: [group]) }
it 'returns runners available to project' do
- expect(subject).to match_array([runner_instance, runner_group])
+ is_expected.to match_array([runner_instance, runner_group])
end
end
@@ -616,24 +618,24 @@ RSpec.describe Ci::RunnersFinder, feature_category: :runner_fleet do
project.add_developer(user)
end
- it 'returns no runners' do
- expect(subject).to be_empty
+ it 'raises Gitlab::Access::AccessDeniedError' do
+ expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
context 'when user is nil' do
let_it_be(:user) { nil }
- it 'returns no runners' do
- expect(subject).to be_empty
+ it 'raises Gitlab::Access::AccessDeniedError' do
+ expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
context 'with nil project_full_path' do
let(:project_full_path) { nil }
- it 'returns no runners' do
- expect(subject).to be_empty
+ it 'raises Gitlab::Access::AccessDeniedError' do
+ expect { execute }.to raise_error(Gitlab::Access::AccessDeniedError)
end
end
end
diff --git a/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_header_spec.js b/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_header_spec.js
index a651664851e..655bfe538c6 100644
--- a/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_header_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/header/pipeline_editor_header_spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
+import { GlCard } from '@gitlab/ui';
import PipelineEditorHeader from '~/ci/pipeline_editor/components/header/pipeline_editor_header.vue';
import PipelineStatus from '~/ci/pipeline_editor/components/header/pipeline_status.vue';
import ValidationSegment from '~/ci/pipeline_editor/components/header/validation_segment.vue';
@@ -20,6 +21,9 @@ describe('Pipeline editor header', () => {
isNewCiConfigFile: false,
...props,
},
+ stubs: {
+ GlCard,
+ },
});
};
diff --git a/spec/frontend/merge_request_tabs_spec.js b/spec/frontend/merge_request_tabs_spec.js
index 3b8c9dd3bf3..6c4ea7063ad 100644
--- a/spec/frontend/merge_request_tabs_spec.js
+++ b/spec/frontend/merge_request_tabs_spec.js
@@ -281,6 +281,14 @@ describe('MergeRequestTabs', () => {
testContext.class.expandViewContainer();
expect($('.content-wrapper .container-limited')).toHaveLength(0);
});
+
+ it('adds the diff-specific width-limiter', () => {
+ testContext.class.expandViewContainer();
+
+ expect(testContext.class.contentWrapper.classList.contains('diffs-container-limited')).toBe(
+ true,
+ );
+ });
});
describe('resetViewContainer', () => {
@@ -302,6 +310,14 @@ describe('MergeRequestTabs', () => {
expect($('.content-wrapper .container-limited')).toHaveLength(1);
});
+
+ it('removes the diff-specific width-limiter', () => {
+ testContext.class.resetViewContainer();
+
+ expect(testContext.class.contentWrapper.classList.contains('diffs-container-limited')).toBe(
+ false,
+ );
+ });
});
describe('tabShown', () => {
diff --git a/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb b/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb
index ff343f3f43d..fedae5c86a8 100644
--- a/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Resolvers::Ci::GroupRunnersResolver, feature_category: :runner_fl
include GraphqlHelpers
describe '#resolve' do
- subject do
+ subject(:resolve_scope) do
resolve(described_class, obj: obj, ctx: { current_user: user }, args: args,
arg_style: :internal)
end
@@ -18,8 +18,10 @@ RSpec.describe Resolvers::Ci::GroupRunnersResolver, feature_category: :runner_fl
# First, we can do a couple of basic real tests to verify common cases. That ensures that the code works.
context 'when user cannot see runners' do
- it 'returns no runners' do
- expect(subject.items.to_a).to eq([])
+ it 'returns Gitlab::Graphql::Errors::ResourceNotAvailable' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
+ resolve_scope
+ end
end
end
@@ -29,14 +31,16 @@ RSpec.describe Resolvers::Ci::GroupRunnersResolver, feature_category: :runner_fl
end
it 'returns all the runners' do
- expect(subject.items.to_a).to contain_exactly(inactive_project_runner, offline_project_runner, group_runner, subgroup_runner)
+ expect(resolve_scope.items.to_a).to contain_exactly(
+ inactive_project_runner, offline_project_runner, group_runner, subgroup_runner
+ )
end
context 'with membership direct' do
let(:args) { { membership: :direct } }
it 'returns only direct runners' do
- expect(subject.items.to_a).to contain_exactly(group_runner)
+ expect(resolve_scope.items.to_a).to contain_exactly(group_runner)
end
end
end
@@ -46,7 +50,7 @@ RSpec.describe Resolvers::Ci::GroupRunnersResolver, feature_category: :runner_fl
let(:obj) { nil }
it 'raises an error' do
- expect { subject }.to raise_error('Expected group missing')
+ expect { resolve_scope }.to raise_error('Expected group missing')
end
end
@@ -54,7 +58,7 @@ RSpec.describe Resolvers::Ci::GroupRunnersResolver, feature_category: :runner_fl
let(:obj) { build(:project) }
it 'raises an error' do
- expect { subject }.to raise_error('Expected group missing')
+ expect { resolve_scope }.to raise_error('Expected group missing')
end
end
@@ -90,7 +94,7 @@ RSpec.describe Resolvers::Ci::GroupRunnersResolver, feature_category: :runner_fl
allow(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder)
allow(finder).to receive(:execute).once.and_return([:execute_return_value])
- expect(subject.items.to_a).to eq([:execute_return_value])
+ expect(resolve_scope.items.to_a).to eq([:execute_return_value])
end
end
end
diff --git a/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb b/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb
index 83435db2ea7..55a98106baf 100644
--- a/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Resolvers::Ci::ProjectRunnersResolver, feature_category: :runner_
include GraphqlHelpers
describe '#resolve' do
- subject do
+ subject(:resolve_scope) do
resolve(described_class, obj: obj, ctx: { current_user: user }, args: args,
arg_style: :internal)
end
@@ -17,8 +17,10 @@ RSpec.describe Resolvers::Ci::ProjectRunnersResolver, feature_category: :runner_
let(:args) { {} }
context 'when user cannot see runners' do
- it 'returns no runners' do
- expect(subject.items.to_a).to eq([])
+ it 'returns Gitlab::Graphql::Errors::ResourceNotAvailable' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
+ resolve_scope
+ end
end
end
@@ -30,7 +32,7 @@ RSpec.describe Resolvers::Ci::ProjectRunnersResolver, feature_category: :runner_
let(:available_runners) { [inactive_project_runner, offline_project_runner, group_runner, instance_runner] }
it 'returns all runners available to the project' do
- expect(subject.items.to_a).to match_array(available_runners)
+ expect(resolve_scope.items.to_a).to match_array(available_runners)
end
end
@@ -38,7 +40,7 @@ RSpec.describe Resolvers::Ci::ProjectRunnersResolver, feature_category: :runner_
let(:obj) { nil }
it 'raises an error' do
- expect { subject }.to raise_error('Expected project missing')
+ expect { resolve_scope }.to raise_error('Expected project missing')
end
end
@@ -46,7 +48,7 @@ RSpec.describe Resolvers::Ci::ProjectRunnersResolver, feature_category: :runner_
let(:obj) { build(:group) }
it 'raises an error' do
- expect { subject }.to raise_error('Expected project missing')
+ expect { resolve_scope }.to raise_error('Expected project missing')
end
end
@@ -79,7 +81,7 @@ RSpec.describe Resolvers::Ci::ProjectRunnersResolver, feature_category: :runner_
params: expected_params).once.and_return(finder)
allow(finder).to receive(:execute).once.and_return([:execute_return_value])
- expect(subject.items.to_a).to eq([:execute_return_value])
+ expect(resolve_scope.items.to_a).to contain_exactly(:execute_return_value)
end
end
end
diff --git a/spec/graphql/resolvers/ci/runners_resolver_spec.rb b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
index 02fc7d28255..35831579799 100644
--- a/spec/graphql/resolvers/ci/runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
@@ -20,8 +20,10 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet d
context 'when user cannot see runners' do
let(:user) { build(:user) }
- it 'returns no runners' do
- expect(subject.items.to_a).to eq([])
+ it 'returns Gitlab::Graphql::Errors::ResourceNotAvailable' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
+ resolve_scope
+ end
end
end
@@ -30,20 +32,26 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet d
context 'when admin mode setting is disabled', :do_not_mock_admin_mode_setting do
it 'returns all the runners' do
- expect(subject.items.to_a).to contain_exactly(inactive_project_runner, offline_project_runner, group_runner, subgroup_runner, instance_runner)
+ expect(resolve_scope.items.to_a).to contain_exactly(
+ inactive_project_runner, offline_project_runner, group_runner, subgroup_runner, instance_runner
+ )
end
end
context 'when admin mode setting is enabled' do
context 'when in admin mode', :enable_admin_mode do
it 'returns all the runners' do
- expect(subject.items.to_a).to contain_exactly(inactive_project_runner, offline_project_runner, group_runner, subgroup_runner, instance_runner)
+ expect(resolve_scope.items.to_a).to contain_exactly(
+ inactive_project_runner, offline_project_runner, group_runner, subgroup_runner, instance_runner
+ )
end
end
context 'when not in admin mode' do
- it 'returns no runners' do
- expect(subject.items.to_a).to eq([])
+ it 'returns Gitlab::Graphql::Errors::ResourceNotAvailable' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
+ resolve_scope
+ end
end
end
end
@@ -54,7 +62,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet d
let(:obj) { build(:project) }
it 'raises an error' do
- expect { subject }.to raise_error(a_string_including('Unexpected parent type'))
+ expect { resolve_scope }.to raise_error(a_string_including('Unexpected parent type'))
end
end
@@ -93,7 +101,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet d
expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder)
allow(finder).to receive(:execute).once.and_return([:execute_return_value])
- expect(subject.items.to_a).to eq([:execute_return_value])
+ expect(resolve_scope.items.to_a).to contain_exactly :execute_return_value
end
end
@@ -116,7 +124,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet d
expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder)
allow(finder).to receive(:execute).once.and_return([:execute_return_value])
- expect(subject.items.to_a).to eq([:execute_return_value])
+ expect(resolve_scope.items.to_a).to contain_exactly :execute_return_value
end
end
@@ -136,7 +144,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet d
expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder)
allow(finder).to receive(:execute).once.and_return([:execute_return_value])
- expect(subject.items.to_a).to eq([:execute_return_value])
+ expect(resolve_scope.items.to_a).to contain_exactly :execute_return_value
end
end
@@ -153,7 +161,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet d
expect(::Ci::RunnersFinder).to receive(:new).with(current_user: user, params: expected_params).once.and_return(finder)
allow(finder).to receive(:execute).once.and_return([:execute_return_value])
- expect(subject.items.to_a).to eq([:execute_return_value])
+ expect(resolve_scope.items.to_a).to contain_exactly :execute_return_value
end
end
end
diff --git a/spec/lib/gitlab/github_import/attachments_downloader_spec.rb b/spec/lib/gitlab/github_import/attachments_downloader_spec.rb
index 086aa4be17e..27007e09ba4 100644
--- a/spec/lib/gitlab/github_import/attachments_downloader_spec.rb
+++ b/spec/lib/gitlab/github_import/attachments_downloader_spec.rb
@@ -93,6 +93,43 @@ RSpec.describe Gitlab::GithubImport::AttachmentsDownloader, feature_category: :i
expect(File.basename(file)).to eq('av.png')
end
end
+
+ context 'when attachment is behind a redirect' do
+ let_it_be(:file_url) { "https://github.com/test/project/assets/142635249/4b9f9c90-f060-4845-97cf-b24c558bcb11" }
+ let(:redirect_url) { "https://https://github-production-user-asset-6210df.s3.amazonaws.com/142635249/740edb05293e.jpg" }
+ let(:sample_response) do
+ instance_double(HTTParty::Response, redirection?: true, headers: { location: redirect_url })
+ end
+
+ it 'gets redirection url' do
+ expect(Gitlab::HTTP).to receive(:perform_request)
+ .with(Net::HTTP::Get, file_url, { follow_redirects: false })
+ .and_return sample_response
+
+ expect(Gitlab::HTTP).to receive(:perform_request)
+ .with(Net::HTTP::Get, redirect_url, stream_body: true).and_yield(chunk_double)
+
+ file = downloader.perform
+
+ expect(File.exist?(file.path)).to eq(true)
+ end
+
+ context 'when url is not a redirection' do
+ let(:sample_response) do
+ instance_double(HTTParty::Response, code: 200, redirection?: false)
+ end
+
+ before do
+ allow(Gitlab::HTTP).to receive(:perform_request)
+ .with(Net::HTTP::Get, file_url, { follow_redirects: false })
+ .and_return sample_response
+ end
+
+ it 'raises upon unsuccessful redirection' do
+ expect { downloader.perform }.to raise_error("expected a redirect response, got #{sample_response.code}")
+ end
+ end
+ end
end
describe '#delete' do
diff --git a/spec/lib/gitlab/github_import/importer/note_attachments_importer_spec.rb b/spec/lib/gitlab/github_import/importer/note_attachments_importer_spec.rb
index 450ebe9a719..ffd68c92caf 100644
--- a/spec/lib/gitlab/github_import/importer/note_attachments_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/note_attachments_importer_spec.rb
@@ -53,6 +53,19 @@ RSpec.describe Gitlab::GithubImport::Importer::NoteAttachmentsImporter, feature_
record.reload
expect(record.description).to include("[link to other project blob file](#{other_project_blob_url})")
end
+
+ context 'with new github image format' do
+ let(:image_url) { 'https://github.com/nickname/public-test-repo/assets/142635249/4b9f9c90-f060-4845-97cf-b24c558bcb11' }
+ let(:image_tag_url) { 'https://github.com/nickname/public-test-repo/assets/142635249/4b9f9c90-f060-4845-97cf-b24c558bcb11' }
+
+ it 'changes image attachment links' do
+ importer.execute
+
+ record.reload
+ expect(record.description).to include('![image.jpeg](/uploads/')
+ expect(record.description).to include('<img width="248" alt="tag-image" src="/uploads')
+ end
+ end
end
describe '#execute' do
@@ -60,16 +73,19 @@ RSpec.describe Gitlab::GithubImport::Importer::NoteAttachmentsImporter, feature_
let(:tmp_stub_doc) { Tempfile.create('attachment_download_test.txt') }
let(:tmp_stub_image) { Tempfile.create('image.jpeg') }
let(:tmp_stub_image_tag) { Tempfile.create('image-tag.jpeg') }
+ let(:access_token) { 'exampleGitHubToken' }
+ let(:options) { { headers: { 'Authorization' => "Bearer #{access_token}" } } }
before do
- allow(Gitlab::GithubImport::AttachmentsDownloader).to receive(:new).with(doc_url)
+ allow(Gitlab::GithubImport::AttachmentsDownloader).to receive(:new).with(doc_url, options: options)
.and_return(downloader_stub)
- allow(Gitlab::GithubImport::AttachmentsDownloader).to receive(:new).with(image_url)
+ allow(Gitlab::GithubImport::AttachmentsDownloader).to receive(:new).with(image_url, options: options)
.and_return(downloader_stub)
- allow(Gitlab::GithubImport::AttachmentsDownloader).to receive(:new).with(image_tag_url)
+ allow(Gitlab::GithubImport::AttachmentsDownloader).to receive(:new).with(image_tag_url, options: options)
.and_return(downloader_stub)
allow(downloader_stub).to receive(:perform).and_return(tmp_stub_doc, tmp_stub_image, tmp_stub_image_tag)
allow(downloader_stub).to receive(:delete).exactly(3).times
+ allow(client).to receive_message_chain(:octokit, :access_token).and_return(access_token)
end
context 'when importing release attachments' do
diff --git a/spec/lib/gitlab/github_import/markdown/attachment_spec.rb b/spec/lib/gitlab/github_import/markdown/attachment_spec.rb
index 84b0886ebcc..5b9d077aac9 100644
--- a/spec/lib/gitlab/github_import/markdown/attachment_spec.rb
+++ b/spec/lib/gitlab/github_import/markdown/attachment_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Markdown::Attachment, feature_category: :importers do
let(:name) { FFaker::Lorem.word }
let(:url) { FFaker::Internet.uri('https') }
+ let(:import_source) { 'nickname/public-test-repo' }
describe '.from_markdown' do
context "when it's a doc attachment" do
@@ -75,6 +76,17 @@ RSpec.describe Gitlab::GithubImport::Markdown::Attachment, feature_category: :im
it { expect(described_class.from_markdown(markdown_node)).to eq nil }
end
+
+ context 'when image attachment is in the new format' do
+ let(:url) { "https://github.com/#{import_source}/assets/142635249/4b9f9c90-f060-4845-97cf-b24c558bcb11" }
+
+ it 'returns instance with attachment info' do
+ attachment = described_class.from_markdown(markdown_node)
+
+ expect(attachment.name).to eq name
+ expect(attachment.url).to eq url
+ end
+ end
end
context "when it's an inline html node" do
@@ -103,7 +115,6 @@ RSpec.describe Gitlab::GithubImport::Markdown::Attachment, feature_category: :im
describe '#part_of_project_blob?' do
let(:attachment) { described_class.new('test', url) }
- let(:import_source) { 'nickname/public-test-repo' }
context 'when url is a part of project blob' do
let(:url) { "https://github.com/#{import_source}/blob/main/example.md" }
@@ -120,7 +131,6 @@ RSpec.describe Gitlab::GithubImport::Markdown::Attachment, feature_category: :im
describe '#doc_belongs_to_project?' do
let(:attachment) { described_class.new('test', url) }
- let(:import_source) { 'nickname/public-test-repo' }
context 'when url relates to this project' do
let(:url) { "https://github.com/#{import_source}/files/9020437/git-cheat-sheet.txt" }
@@ -147,13 +157,19 @@ RSpec.describe Gitlab::GithubImport::Markdown::Attachment, feature_category: :im
context 'when it is a media link' do
let(:url) { 'https://user-images.githubusercontent.com/6833842/0cf366b61ef2.jpeg' }
- it { expect(attachment.media?).to eq true }
+ it { expect(attachment.media?(import_source)).to eq true }
+
+ context 'when it is a new media link' do
+ let(:url) { "https://github.com/#{import_source}/assets/142635249/4b9f9c90-f060-4845-97cf-b24c558bcb11" }
+
+ it { expect(attachment.media?(import_source)).to eq true }
+ end
end
context 'when it is not a media link' do
let(:url) { 'https://github.com/nickname/public-test-repo/files/9020437/git-cheat-sheet.txt' }
- it { expect(attachment.media?).to eq false }
+ it { expect(attachment.media?(import_source)).to eq false }
end
end
diff --git a/spec/mailers/emails/service_desk_spec.rb b/spec/mailers/emails/service_desk_spec.rb
index 857d95631be..e3fe36237df 100644
--- a/spec/mailers/emails/service_desk_spec.rb
+++ b/spec/mailers/emails/service_desk_spec.rb
@@ -172,10 +172,14 @@ RSpec.describe Emails::ServiceDesk, feature_category: :service_desk do
project.reset
service_desk_setting.update!(custom_email_enabled: true) unless service_desk_setting.custom_email_enabled?
+
+ allow(Gitlab::AppLogger).to receive(:info)
end
it 'uses SMTP delivery method and custom email settings' do
expect_service_desk_custom_email_delivery_options(service_desk_setting)
+
+ expect(Gitlab::AppLogger).to have_received(:info).with({ category: 'custom_email' })
end
it 'generates Reply-To address from custom email' do
diff --git a/spec/requests/api/graphql/ci/runner_web_url_edge_spec.rb b/spec/requests/api/graphql/ci/runner_web_url_edge_spec.rb
index e84a1ca4cc4..76e2dda4ce2 100644
--- a/spec/requests/api/graphql/ci/runner_web_url_edge_spec.rb
+++ b/spec/requests/api/graphql/ci/runner_web_url_edge_spec.rb
@@ -25,16 +25,22 @@ RSpec.describe 'RunnerWebUrlEdge', feature_category: :runner_fleet do
GQL
end
- before do
+ subject(:request) do
post_graphql(query, current_user: user, variables: { path: group.full_path })
end
context 'with an authorized user' do
let(:user) { create_default(:user, :admin) }
- it_behaves_like 'a working graphql query'
+ it_behaves_like 'a working graphql query' do
+ before do
+ request
+ end
+ end
it 'returns correct URLs' do
+ request
+
expect(edges_graphql_data).to match_array [
{
'editUrl' => Gitlab::Routing.url_helpers.edit_group_runner_url(group, group_runner),
@@ -47,10 +53,14 @@ RSpec.describe 'RunnerWebUrlEdge', feature_category: :runner_fleet do
context 'with an unauthorized user' do
let(:user) { create(:user) }
- it_behaves_like 'a working graphql query'
+ it 'returns nil runners and an error' do
+ request
- it 'returns no edges' do
- expect(edges_graphql_data).to be_empty
+ expect(graphql_data.dig('group', 'runners')).to be_nil
+ expect(graphql_errors).to contain_exactly(a_hash_including(
+ 'message' => a_string_including("you don't have permission to perform this action"),
+ 'path' => %w[group runners]
+ ))
end
end
end
diff --git a/spec/requests/api/graphql/group_query_spec.rb b/spec/requests/api/graphql/group_query_spec.rb
index 6debe2d3d67..1dcbc44c587 100644
--- a/spec/requests/api/graphql/group_query_spec.rb
+++ b/spec/requests/api/graphql/group_query_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe 'getting group information', :with_license, feature_category: :gr
# similar to the API "GET /groups/:id"
describe "Query group(fullPath)" do
def group_query(group)
- fields = all_graphql_fields_for('Group')
+ fields = all_graphql_fields_for('Group', excluded: %w[runners])
# TODO: Set required timelogs args elsewhere https://gitlab.com/gitlab-org/gitlab/-/issues/325499
fields.selection['timelogs(startDate: "2021-03-01" endDate: "2021-03-30")'] = fields.selection.delete('timelogs')
diff --git a/spec/requests/api/graphql/groups_query_spec.rb b/spec/requests/api/graphql/groups_query_spec.rb
index 460cb40b68a..7310382553f 100644
--- a/spec/requests/api/graphql/groups_query_spec.rb
+++ b/spec/requests/api/graphql/groups_query_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'searching groups', :with_license, feature_category: :groups_and_
let(:fields) do
<<~FIELDS
nodes {
- #{all_graphql_fields_for('Group')}
+ #{all_graphql_fields_for('Group', excluded: %w[runners])}
}
FIELDS
end
diff --git a/spec/requests/api/graphql/packages/package_spec.rb b/spec/requests/api/graphql/packages/package_spec.rb
index 7610a4aaac1..c8cef07c4ff 100644
--- a/spec/requests/api/graphql/packages/package_spec.rb
+++ b/spec/requests/api/graphql/packages/package_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'package details', feature_category: :package_registry do
end
let(:depth) { 3 }
- let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles] }
+ let(:excluded) { %w[metadata apiFuzzingCiConfiguration pipeline packageFiles runners] }
let(:metadata) { query_graphql_fragment('ComposerMetadata') }
let(:package_files) { all_graphql_fields_for('PackageFile') }
let(:package_global_id) { global_id_of(composer_package) }
diff --git a/spec/requests/api/graphql/project/merge_request_spec.rb b/spec/requests/api/graphql/project/merge_request_spec.rb
index 28aadf850f0..9ca5df95d30 100644
--- a/spec/requests/api/graphql/project/merge_request_spec.rb
+++ b/spec/requests/api/graphql/project/merge_request_spec.rb
@@ -21,9 +21,11 @@ RSpec.describe 'getting merge request information nested in a project', feature_
end
it_behaves_like 'a working graphql query' do
- # we exclude Project.pipeline because it needs arguments
- # and codequalityReportsComparer because no pipeline exist yet
- let(:mr_fields) { all_graphql_fields_for('MergeRequest', excluded: %w[jobs pipeline codequalityReportsComparer]) }
+ # we exclude Project.pipeline because it needs arguments,
+ # codequalityReportsComparer because no pipeline exist yet
+ # and runners because the user is not an admin and therefore has no access
+ let(:excluded) { %w[jobs pipeline runners codequalityReportsComparer] }
+ let(:mr_fields) { all_graphql_fields_for('MergeRequest', excluded: excluded) }
before do
post_graphql(query, current_user: current_user)
diff --git a/spec/requests/api/graphql/project/runners_spec.rb b/spec/requests/api/graphql/project/runners_spec.rb
index bee7ce2e372..68e95de49bc 100644
--- a/spec/requests/api/graphql/project/runners_spec.rb
+++ b/spec/requests/api/graphql/project/runners_spec.rb
@@ -28,6 +28,8 @@ RSpec.describe 'Project.runners', feature_category: :runner do
)
end
+ subject(:request) { post_graphql(query, current_user: user) }
+
context 'when the user is a project admin' do
before do
project.add_maintainer(user)
@@ -36,7 +38,7 @@ RSpec.describe 'Project.runners', feature_category: :runner do
let(:expected_ids) { [project_runner, group_runner, instance_runner].map { |g| g.to_global_id.to_s } }
it 'returns all runners available to project' do
- post_graphql(query, current_user: user)
+ request
expect(graphql_data_at(:project, :runners, :nodes).pluck('id')).to match_array(expected_ids)
end
@@ -47,10 +49,14 @@ RSpec.describe 'Project.runners', feature_category: :runner do
project.add_developer(user)
end
- it 'returns no runners' do
- post_graphql(query, current_user: user)
+ it 'returns nil runners and an error' do
+ request
- expect(graphql_data_at(:project, :runners, :nodes)).to be_empty
+ expect(graphql_data_at(:project, :runners)).to be_nil
+ expect(graphql_errors).to contain_exactly(a_hash_including(
+ 'message' => a_string_including("you don't have permission to perform this action"),
+ 'path' => %w[project runners]
+ ))
end
end
end