summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/CODEOWNERS4
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail/description.vue8
-rw-r--r--app/assets/javascripts/pages/projects/environments/show/index.js2
-rw-r--r--app/assets/javascripts/static_site_editor/components/front_matter_controls.vue57
-rw-r--r--app/controllers/application_controller.rb4
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/controllers/registrations_controller.rb14
-rw-r--r--app/finders/issues_finder.rb2
-rw-r--r--app/models/concerns/issuable.rb4
-rw-r--r--app/models/user.rb4
-rw-r--r--app/serializers/job_entity.rb3
-rw-r--r--app/views/projects/empty.html.haml121
-rw-r--r--app/views/projects/environments/show.html.haml2
-rw-r--r--app/views/projects/show.html.haml25
-rw-r--r--app/views/shared/issuable/_form.html.haml3
-rw-r--r--app/views/shared/issuable/form/_metadata.html.haml3
-rw-r--r--app/views/shared/issuable/form/_type_selector.html.haml10
-rw-r--r--changelogs/unreleased/216480-ide-multiproject-pipelines.yml5
-rw-r--r--changelogs/unreleased/235004-shortcut-deploy-to-is-shrinked.yml5
-rw-r--r--changelogs/unreleased/246904-drop-limit-container-width-from-projects.yml5
-rw-r--r--changelogs/unreleased/app-logger-19.yml5
-rw-r--r--changelogs/unreleased/drop-limit-container-width-from-project.yml5
-rw-r--r--changelogs/unreleased/nicolasdular-introduce-welcome-page.yml5
-rw-r--r--doc/development/cicd/templates.md6
-rw-r--r--doc/integration/elasticsearch.md2
-rw-r--r--doc/raketasks/cleanup.md2
-rw-r--r--doc/user/admin_area/credentials_inventory.md19
-rw-r--r--doc/user/admin_area/img/credentials_inventory_v13_2.pngbin96526 -> 0 bytes
-rw-r--r--doc/user/admin_area/img/credentials_inventory_v13_4.pngbin0 -> 28945 bytes
-rw-r--r--lib/gitlab/auth/ldap/person.rb4
-rw-r--r--lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb2
-rw-r--r--lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml249
-rw-r--r--locale/gitlab.pot18
-rw-r--r--package.json4
-rw-r--r--spec/controllers/application_controller_spec.rb55
-rw-r--r--spec/controllers/registrations_controller_spec.rb55
-rw-r--r--spec/features/invites_spec.rb12
-rw-r--r--spec/features/users/signup_spec.rb82
-rw-r--r--spec/frontend/ide/components/jobs/detail/description_spec.js8
-rw-r--r--spec/frontend/ide/mock_data.js3
-rw-r--r--spec/frontend/static_site_editor/components/front_matter_controls_spec.js78
-rw-r--r--spec/models/concerns/issuable_spec.rb17
-rw-r--r--spec/serializers/job_entity_spec.rb12
-rw-r--r--yarn.lock18
44 files changed, 705 insertions, 239 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 2cf8db04bb9..06a2046859d 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -195,9 +195,11 @@ Dangerfile @gl-quality/eng-prod
# Secure & Threat Management ownership delineation
# https://about.gitlab.com/handbook/engineering/development/threat-management/delineate-secure-threat-management.html#technical-boundaries
[Secure]
-/ee/app/models/vulnerability.rb @gitlab-org/secure/threat-insights-backend-team
+/ee/app/finders/security/ @gitlab-org/secure/threat-insights-backend-team
/ee/app/models/security/ @gitlab-org/secure/threat-insights-backend-team
/ee/app/models/vulnerabilities/ @gitlab-org/secure/threat-insights-backend-team
+/ee/app/models/vulnerability.rb @gitlab-org/secure/threat-insights-backend-team
+/ee/lib/api/vulnerabilit*.rb @gitlab-org/secure/threat-insights-backend-team
/ee/lib/gitlab/ci/parsers/license_compliance/ @gitlab-org/secure/composition-analysis-be
/ee/lib/gitlab/ci/parsers/security/ @gitlab-org/secure/composition-analysis-be @gitlab-org/secure/dynamic-analysis-be @gitlab-org/secure/static-analysis-be @gitlab-org/secure/fuzzing-be
/ee/lib/gitlab/ci/reports/coverage_fuzzing/ @gitlab-org/secure/fuzzing-be
diff --git a/app/assets/javascripts/ide/components/jobs/detail/description.vue b/app/assets/javascripts/ide/components/jobs/detail/description.vue
index 50ea9423489..9eaeabad5ef 100644
--- a/app/assets/javascripts/ide/components/jobs/detail/description.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail/description.vue
@@ -26,7 +26,13 @@ export default {
<ci-icon :status="job.status" :borderless="true" :size="24" class="d-flex" />
<span class="gl-ml-3">
{{ job.name }}
- <a :href="job.path" target="_blank" class="ide-external-link position-relative">
+ <a
+ v-if="job.path"
+ :href="job.path"
+ target="_blank"
+ class="ide-external-link gl-relative"
+ data-testid="description-detail-link"
+ >
{{ jobId }} <gl-icon :size="12" name="external-link" />
</a>
</span>
diff --git a/app/assets/javascripts/pages/projects/environments/show/index.js b/app/assets/javascripts/pages/projects/environments/show/index.js
index 10e3e28f024..5d3a153cbd1 100644
--- a/app/assets/javascripts/pages/projects/environments/show/index.js
+++ b/app/assets/javascripts/pages/projects/environments/show/index.js
@@ -1,3 +1,3 @@
import initShowEnvironment from '~/environments/mount_show';
-document.addEventListener('DOMContentLoaded', () => initShowEnvironment());
+document.addEventListener('DOMContentLoaded', initShowEnvironment);
diff --git a/app/assets/javascripts/static_site_editor/components/front_matter_controls.vue b/app/assets/javascripts/static_site_editor/components/front_matter_controls.vue
new file mode 100644
index 00000000000..dad3907c3ff
--- /dev/null
+++ b/app/assets/javascripts/static_site_editor/components/front_matter_controls.vue
@@ -0,0 +1,57 @@
+<script>
+import { GlForm, GlFormInput, GlFormGroup } from '@gitlab/ui';
+import { humanize } from '~/lib/utils/text_utility';
+
+export default {
+ components: {
+ GlForm,
+ GlFormInput,
+ GlFormGroup,
+ },
+ props: {
+ settings: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ editableSettings: { ...this.settings },
+ };
+ },
+ methods: {
+ getId(type, key) {
+ return `sse-front-matter-${type}-${key}`;
+ },
+ getIsSupported(val) {
+ return ['string', 'number'].includes(typeof val);
+ },
+ getLabel(str) {
+ return humanize(str);
+ },
+ onUpdate() {
+ this.$emit('updateSettings', { ...this.editableSettings });
+ },
+ },
+};
+</script>
+<template>
+ <gl-form>
+ <template v-for="(value, key) of editableSettings">
+ <gl-form-group
+ v-if="getIsSupported(value)"
+ :id="getId('form-group', key)"
+ :key="key"
+ :label="getLabel(key)"
+ :label-for="getId('control', key)"
+ >
+ <gl-form-input
+ :id="getId('control', key)"
+ v-model.lazy="editableSettings[key]"
+ type="text"
+ @input="onUpdate"
+ />
+ </gl-form-group>
+ </template>
+ </gl-form>
+</template>
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 2595b646964..5f05337e59e 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -551,13 +551,9 @@ class ApplicationController < ActionController::Base
"#{self.class.name}##{action_name}"
end
- # A user requires a role and have the setup_for_company attribute set when they are part of the experimental signup
- # flow (executed by the Growth team). Users are redirected to the welcome page when their role is required and the
- # experiment is enabled for the current user.
def required_signup_info
return unless current_user
return unless current_user.role_required?
- return unless experiment_enabled?(:signup_flow)
store_location_for :user, request.fullpath
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 99bb80619b1..e447ac874df 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -103,8 +103,6 @@ class Projects::BlobController < Projects::ApplicationController
end
def diff
- apply_diff_view_cookie!
-
@form = Blobs::UnfoldPresenter.new(blob, diff_params)
# keep only json rendering when
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index dfa67f042e2..26891d34734 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -35,9 +35,9 @@ class RegistrationsController < Devise::RegistrationsController
yield new_user if block_given?
end
- # Do not show the signed_up notice message when the signup_flow experiment is enabled.
- # Instead, show it after successfully updating the role.
- flash[:notice] = nil if experiment_enabled?(:signup_flow)
+ # Devise sets a flash message on `create` for a successful signup,
+ # we want to show this message after the welcome page.
+ flash[:notice] = nil
rescue Gitlab::Access::AccessDeniedError
redirect_to(new_user_session_path)
end
@@ -89,7 +89,7 @@ class RegistrationsController < Devise::RegistrationsController
end
def set_role_required(new_user)
- new_user.set_role_required! if new_user.persisted? && experiment_enabled?(:signup_flow)
+ new_user.set_role_required! if new_user.persisted?
end
def destroy_confirmation_valid?
@@ -115,9 +115,7 @@ class RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(user)
Gitlab::AppLogger.info(user_created_message(confirmed: user.confirmed?))
- return users_sign_up_welcome_path if experiment_enabled?(:signup_flow)
-
- path_for_signed_in_user(user)
+ users_sign_up_welcome_path
end
def after_inactive_sign_up_path_for(resource)
@@ -215,7 +213,7 @@ class RegistrationsController < Devise::RegistrationsController
# Part of an experiment to build a new sign up flow. Will be resolved
# with https://gitlab.com/gitlab-org/growth/engineering/issues/64
def choose_layout
- if experiment_enabled?(:signup_flow)
+ if %w(welcome update_registration).include?(action_name) || experiment_enabled?(:signup_flow)
'devise_experimental_separate_sign_up_flow'
else
'devise'
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index 263cd245436..32be5bee0db 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -41,7 +41,7 @@ class IssuesFinder < IssuableFinder
# rubocop: enable CodeReuse/ActiveRecord
def params_class
- IssuesFinder::Params
+ self.class.const_get(:Params, false)
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index a4090a1d61d..09b1dbaba58 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -189,6 +189,10 @@ module Issuable
is_a?(Issue) && super
end
+ def supports_issue_type?
+ is_a?(Issue)
+ end
+
def severity
return IssuableSeverity::DEFAULT unless incident?
diff --git a/app/models/user.rb b/app/models/user.rb
index 0b5c6b9a7ab..9c4af91ad7e 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1715,9 +1715,6 @@ class User < ApplicationRecord
[last_activity, last_sign_in].compact.max
end
- # Below is used for the signup_flow experiment. Should be removed
- # when experiment finishes.
- # See https://gitlab.com/gitlab-org/growth/engineering/issues/64
REQUIRES_ROLE_VALUE = 99
def role_required?
@@ -1727,7 +1724,6 @@ class User < ApplicationRecord
def set_role_required!
update_column(:role, REQUIRES_ROLE_VALUE)
end
- # End of signup_flow experiment methods
def dismissed_callout?(feature_name:, ignore_dismissal_earlier_than: nil)
callouts = self.callouts.with_feature_name(feature_name)
diff --git a/app/serializers/job_entity.rb b/app/serializers/job_entity.rb
index d0099ae77f2..d05b500b140 100644
--- a/app/serializers/job_entity.rb
+++ b/app/serializers/job_entity.rb
@@ -9,7 +9,8 @@ class JobEntity < Grape::Entity
expose :started?, as: :started
expose :archived?, as: :archived
- expose :build_path do |build|
+ # bridge jobs don't have build detail pages
+ expose :build_path, if: ->(build) { !build.is_a?(Ci::Bridge) } do |build|
build_path(build)
end
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index bfb22aa8025..c9edc3c12ec 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -5,72 +5,71 @@
= render partial: 'flash_messages', locals: { project: @project }
-%div{ class: [("limit-container-width" unless fluid_layout)] }
- = render "home_panel"
+= render "home_panel"
- %h4.gl-mt-0.gl-mb-3
- = _('The repository for this project is empty')
+%h4.gl-mt-0.gl-mb-3
+ = _('The repository for this project is empty')
- - if @project.can_current_user_push_code?
- %p.gl-mb-0
- = _('You can get started by cloning the repository or start adding files to it with one of the following options.')
+- if @project.can_current_user_push_code?
+ %p.gl-mb-0
+ = _('You can get started by cloning the repository or start adding files to it with one of the following options.')
- .project-buttons.qa-quick-actions
- .project-clone-holder.d-block.d-md-none.mt-2.mr-2
- = render "shared/mobile_clone_panel"
+.project-buttons.qa-quick-actions
+ .project-clone-holder.d-block.d-md-none.mt-2.mr-2
+ = render "shared/mobile_clone_panel"
- .project-clone-holder.d-none.d-md-inline-block.mt-2.mr-2.float-left
- = render "projects/buttons/clone"
- = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons
+ .project-clone-holder.d-none.d-md-inline-block.mt-2.mr-2.float-left
+ = render "projects/buttons/clone"
+ = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons
- - if can?(current_user, :push_code, @project)
- .empty-wrapper.gl-mt-7
- %h3#repo-command-line-instructions.page-title-empty
- = _('Command line instructions')
- %p
- = _('You can also upload existing files from your computer using the instructions below.')
- .git-empty.js-git-empty
- %fieldset
- %h5= _('Git global setup')
- %pre.bg-light
- :preserve
- git config --global user.name "#{h git_user_name}"
- git config --global user.email "#{h git_user_email}"
+- if can?(current_user, :push_code, @project)
+ .empty-wrapper.gl-mt-7
+ %h3#repo-command-line-instructions.page-title-empty
+ = _('Command line instructions')
+ %p
+ = _('You can also upload existing files from your computer using the instructions below.')
+ .git-empty.js-git-empty
+ %fieldset
+ %h5= _('Git global setup')
+ %pre.bg-light
+ :preserve
+ git config --global user.name "#{h git_user_name}"
+ git config --global user.email "#{h git_user_email}"
- %fieldset
- %h5= _('Create a new repository')
- %pre.bg-light
- :preserve
- git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
- cd #{h @project.path}
- touch README.md
- git add README.md
- git commit -m "add README"
- - if @project.can_current_user_push_to_default_branch?
- %span><
- git push -u origin #{ default_branch_name }
+ %fieldset
+ %h5= _('Create a new repository')
+ %pre.bg-light
+ :preserve
+ git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+ cd #{h @project.path}
+ touch README.md
+ git add README.md
+ git commit -m "add README"
+ - if @project.can_current_user_push_to_default_branch?
+ %span><
+ git push -u origin #{ default_branch_name }
- %fieldset
- %h5= _('Push an existing folder')
- %pre.bg-light
- :preserve
- cd existing_folder
- git init
- git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
- git add .
- git commit -m "Initial commit"
- - if @project.can_current_user_push_to_default_branch?
- %span><
- git push -u origin #{ default_branch_name }
+ %fieldset
+ %h5= _('Push an existing folder')
+ %pre.bg-light
+ :preserve
+ cd existing_folder
+ git init
+ git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+ git add .
+ git commit -m "Initial commit"
+ - if @project.can_current_user_push_to_default_branch?
+ %span><
+ git push -u origin #{ default_branch_name }
- %fieldset
- %h5= _('Push an existing Git repository')
- %pre.bg-light
- :preserve
- cd existing_repo
- git remote rename origin old-origin
- git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
- - if @project.can_current_user_push_to_default_branch?
- %span><
- git push -u origin --all
- git push -u origin --tags
+ %fieldset
+ %h5= _('Push an existing Git repository')
+ %pre.bg-light
+ :preserve
+ cd existing_repo
+ git remote rename origin old-origin
+ git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
+ - if @project.can_current_user_push_to_default_branch?
+ %span><
+ git push -u origin --all
+ git push -u origin --tags
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index 2e665a12a0a..929015023d2 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -69,7 +69,7 @@
.text-center
= link_to _("Read more"), help_page_path("ci/environments"), class: "btn btn-success"
- else
- .table-holder
+ .table-holder.gl-overflow-visible
.ci-table.environments{ role: 'grid' }
.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-15{ role: 'columnheader' }= _('Status')
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 4a521f2f46e..67bdcd0d9d6 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -7,22 +7,21 @@
= render partial: 'flash_messages', locals: { project: @project }
-%div{ class: [("limit-container-width" unless fluid_layout)] }
- = render "projects/last_push"
+= render "projects/last_push"
- = render "home_panel"
+= render "home_panel"
- - if can?(current_user, :download_code, @project) && @project.repository_languages.present?
- = repository_languages_bar(@project.repository_languages)
+- if can?(current_user, :download_code, @project) && @project.repository_languages.present?
+ = repository_languages_bar(@project.repository_languages)
- = render "archived_notice", project: @project
- = render_if_exists "projects/marked_for_deletion_notice", project: @project
- = render_if_exists "projects/ancestor_group_marked_for_deletion_notice", project: @project
+= render "archived_notice", project: @project
+= render_if_exists "projects/marked_for_deletion_notice", project: @project
+= render_if_exists "projects/ancestor_group_marked_for_deletion_notice", project: @project
- - view_path = @project.default_view
+- view_path = @project.default_view
- - if show_auto_devops_callout?(@project)
- = render 'shared/auto_devops_callout'
+- if show_auto_devops_callout?(@project)
+ = render 'shared/auto_devops_callout'
- %div{ class: project_child_container_class(view_path) }
- = render view_path, is_project_overview: true
+%div{ class: project_child_container_class(view_path) }
+ = render view_path, is_project_overview: true
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index c38fb4efaa0..5c7fb963179 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -22,8 +22,7 @@
= render 'shared/form_elements/apply_template_warning'
-- if issuable.is_a?(Issuable) && @issue
- = render 'shared/issuable/form/type_selector', issuable: issuable, form: form, type: @issue[:issue_type]
+= render 'shared/issuable/form/type_selector', issuable: issuable, form: form
= render 'shared/form_elements/description', model: issuable, form: form, project: project
diff --git a/app/views/shared/issuable/form/_metadata.html.haml b/app/views/shared/issuable/form/_metadata.html.haml
index 79e6f043b64..b6088a77be7 100644
--- a/app/views/shared/issuable/form/_metadata.html.haml
+++ b/app/views/shared/issuable/form/_metadata.html.haml
@@ -32,8 +32,7 @@
- if has_due_date
.col-lg-6
- - if @issue[:issue_type] != 'incident'
- = render_if_exists "shared/issuable/form/weight", issuable: issuable, form: form
+ = render_if_exists "shared/issuable/form/weight", issuable: issuable, form: form
.form-group.row
= form.label :due_date, "Due date", class: "col-form-label col-md-2 col-lg-4"
.col-8
diff --git a/app/views/shared/issuable/form/_type_selector.html.haml b/app/views/shared/issuable/form/_type_selector.html.haml
index 668b4e90bef..67f0826def1 100644
--- a/app/views/shared/issuable/form/_type_selector.html.haml
+++ b/app/views/shared/issuable/form/_type_selector.html.haml
@@ -1,3 +1,5 @@
+- return unless issuable.supports_issue_type?
+
.form-group.row.gl-mb-0
= form.label :type, 'Type', class: 'col-form-label col-sm-2'
.col-sm-10
@@ -5,7 +7,7 @@
.dropdown.js-issuable-type-filter-dropdown-wrap
%button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
%span.dropdown-toggle-text.is-default
- = type.capitalize || _("Select type")
+ = issuable.issue_type.capitalize || _("Select type")
= icon('chevron-down')
.dropdown-menu.dropdown-menu-selectable.dropdown-select
.dropdown-title
@@ -15,12 +17,12 @@
.dropdown-content
%ul
%li.js-filter-issuable-type
- = link_to new_project_issue_path(@project), class: ("is-active" if type === 'issue') do
+ = link_to new_project_issue_path(@project), class: ("is-active" if issuable.issue?) do
= _("Issue")
%li.js-filter-issuable-type
- = link_to new_project_issue_path(@project, { issuable_template: 'incident', issue: { issue_type: 'incident' } }), class: ("is-active" if type === 'incident') do
+ = link_to new_project_issue_path(@project, { issuable_template: 'incident', issue: { issue_type: 'incident' } }), class: ("is-active" if issuable.incident?) do
= _("Incident")
- - if type === 'incident'
+ - if issuable.incident?
%p.form-text.text-muted
- incident_docs_url = help_page_path('operations/incident_management/incidents.md', anchor: 'create-and-manage-incidents-in-gitlab')
- incident_docs_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: incident_docs_url }
diff --git a/changelogs/unreleased/216480-ide-multiproject-pipelines.yml b/changelogs/unreleased/216480-ide-multiproject-pipelines.yml
new file mode 100644
index 00000000000..e41d4401359
--- /dev/null
+++ b/changelogs/unreleased/216480-ide-multiproject-pipelines.yml
@@ -0,0 +1,5 @@
+---
+title: Multi-project pipelines in Web IDE lead to 404
+merge_request: 41082
+author:
+type: fixed
diff --git a/changelogs/unreleased/235004-shortcut-deploy-to-is-shrinked.yml b/changelogs/unreleased/235004-shortcut-deploy-to-is-shrinked.yml
new file mode 100644
index 00000000000..42f8680a38b
--- /dev/null
+++ b/changelogs/unreleased/235004-shortcut-deploy-to-is-shrinked.yml
@@ -0,0 +1,5 @@
+---
+title: Remove height limit on environments table
+merge_request: 41688
+author:
+type: fixed
diff --git a/changelogs/unreleased/246904-drop-limit-container-width-from-projects.yml b/changelogs/unreleased/246904-drop-limit-container-width-from-projects.yml
new file mode 100644
index 00000000000..2c375567a50
--- /dev/null
+++ b/changelogs/unreleased/246904-drop-limit-container-width-from-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Drop one of duplicated classname from Projects
+merge_request: 41831
+author: Takuya Noguchi
+type: performance
diff --git a/changelogs/unreleased/app-logger-19.yml b/changelogs/unreleased/app-logger-19.yml
new file mode 100644
index 00000000000..8d308cd3155
--- /dev/null
+++ b/changelogs/unreleased/app-logger-19.yml
@@ -0,0 +1,5 @@
+---
+title: Use GitLab AppLogger in files in lib/gitlab/*
+merge_request: 41302
+author: Rajendra Kadam
+type: other
diff --git a/changelogs/unreleased/drop-limit-container-width-from-project.yml b/changelogs/unreleased/drop-limit-container-width-from-project.yml
new file mode 100644
index 00000000000..6a488fc5912
--- /dev/null
+++ b/changelogs/unreleased/drop-limit-container-width-from-project.yml
@@ -0,0 +1,5 @@
+---
+title: Drop one of duplicated classname from Project
+merge_request: 41830
+author: Takuya Noguchi
+type: performance
diff --git a/changelogs/unreleased/nicolasdular-introduce-welcome-page.yml b/changelogs/unreleased/nicolasdular-introduce-welcome-page.yml
new file mode 100644
index 00000000000..49c6aae05a3
--- /dev/null
+++ b/changelogs/unreleased/nicolasdular-introduce-welcome-page.yml
@@ -0,0 +1,5 @@
+---
+title: Show welcome page after sign up
+merge_request: 41662
+author:
+type: added
diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md
index 891555d93fc..77cedc9814e 100644
--- a/doc/development/cicd/templates.md
+++ b/doc/development/cicd/templates.md
@@ -106,7 +106,8 @@ GitLab v14.0 could be so different that a user will want to continue using the v
after upgrading to GitLab 14.0.
You can add a note in the template or in documentation explaining how to use `include:remote`
-to include older template versions:
+to include older template versions. If other templates are included with `include: template`,
+they can be combined with the `include: remote`:
```yaml
# To use the v13 stable template, which is not included in v14, fetch the specifc
@@ -114,7 +115,8 @@ to include older template versions:
# If you fetch from the GitLab canonical project, use the following URL format:
# https://gitlab.com/gitlab-org/gitlab/-/raw/<version>/lib/gitlab/ci/templates/<template-name>
include:
- remote: https://gitlab.com/gitlab-org/gitlab/-/raw/v13.0.1-ee/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
+ - template: Auto-DevOps.gitlab-ci.yml
+ - remote: https://gitlab.com/gitlab-org/gitlab/-/raw/v13.0.1-ee/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml
```
### Further reading
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index f788c2ca5cc..0aa14367241 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -219,7 +219,7 @@ The following Elasticsearch settings are available:
| `Number of Elasticsearch shards` | Elasticsearch indexes are split into multiple shards for performance reasons. In general, larger indexes need to have more shards. Changes to this value do not take effect until the index is recreated. You can read more about tradeoffs in the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/scalability.html). |
| `Number of Elasticsearch replicas` | Each Elasticsearch shard can have a number of replicas. These are a complete copy of the shard, and can provide increased query performance or resilience against hardware failure. Increasing this value will greatly increase total disk space required by the index. |
| `Limit namespaces and projects that can be indexed` | Enabling this will allow you to select namespaces and projects to index. All other namespaces and projects will use database search instead. Please note that if you enable this option but do not select any namespaces or projects, none will be indexed. [Read more below](#limiting-namespaces-and-projects).
-| `Using AWS hosted Elasticsearch with IAM credentials` | Sign your Elasticsearch requests using [AWS IAM authorization](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html), [AWS EC2 Instance Profile Credentials](https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html#getting-started-create-iam-instance-profile-cli), or [AWS ECS Tasks Credentials](https://docs.aws.amazon.com/AmazonECS/latest/userguide/task-iam-roles.html). The policies must be configured to allow `es:*` actions. |
+| `Using AWS hosted Elasticsearch with IAM credentials` | Sign your Elasticsearch requests using [AWS IAM authorization](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html), [AWS EC2 Instance Profile Credentials](https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html#getting-started-create-iam-instance-profile-cli), or [AWS ECS Tasks Credentials](https://docs.aws.amazon.com/AmazonECS/latest/userguide/task-iam-roles.html). Please refer to [Identity and Access Management in Amazon Elasticsearch Service](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-ac.html) for details of AWS hosted Elasticsearch domain access policy configuration. |
| `AWS Region` | The AWS region in which your Elasticsearch service is located. |
| `AWS Access Key` | The AWS access key. |
| `AWS Secret Access Key` | The AWS secret access key. |
diff --git a/doc/raketasks/cleanup.md b/doc/raketasks/cleanup.md
index 340f58057a6..23091f40430 100644
--- a/doc/raketasks/cleanup.md
+++ b/doc/raketasks/cleanup.md
@@ -11,7 +11,7 @@ Do not run this within 12 hours of a GitLab upgrade. This is to ensure that all
have finished, which otherwise may lead to data loss.
CAUTION: **WARNING:**
-Removing LFS files from a project with forks is currently unsafe. The rake task
+Removing LFS files from a project with forks is currently unsafe. The Rake task
will refuse to run on projects with forks.
When you remove LFS files from a repository's history, they become orphaned and continue to consume
diff --git a/doc/user/admin_area/credentials_inventory.md b/doc/user/admin_area/credentials_inventory.md
index 9259c93cfa3..7f2d49dafea 100644
--- a/doc/user/admin_area/credentials_inventory.md
+++ b/doc/user/admin_area/credentials_inventory.md
@@ -13,7 +13,7 @@ type: howto
GitLab administrators are responsible for the overall security of their instance. To assist, GitLab provides a Credentials inventory to keep track of all the credentials that can be used to access their self-managed instance.
-Using Credentials inventory, GitLab administrators can see all the personal access tokens and SSH keys that exist in their instance and:
+Using Credentials inventory, you can see all the personal access tokens (PAT) and SSH keys that exist in your GitLab instance. In addition, you can [revoke them](#revoke-a-users-personal-access-token) and see:
- Who they belong to.
- Their access scope.
@@ -25,4 +25,19 @@ To access the Credentials inventory, navigate to **Admin Area > Credentials**.
The following is an example of the Credentials inventory page:
-![Credentials inventory page](img/credentials_inventory_v13_2.png)
+![Credentials inventory page](img/credentials_inventory_v13_4.png)
+
+## Revoke a user's personal access token
+
+[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214811) in GitLab 13.4.
+
+If you see a **Revoke** button, you can revoke that user's PAT. Whether you see a **Revoke** button depends on the token state, and if an expiration date has been set. For more information, see the following table:
+
+| Token state | [Token expiry enforced?](settings/account_and_limit_settings.md#optional-enforcement-of-personal-access-token-expiry) | Show Revoke button? | Comments |
+|-------------|------------------------|--------------------|----------------------------------------------------------------------------|
+| Active | Yes | Yes | Allows administrators to revoke the PAT, such as for a compromised account |
+| Active | No | Yes | Allows administrators to revoke the PAT, such as for a compromised account |
+| Expired | Yes | No | PAT expires automatically |
+| Expired | No | Yes | The administrator may revoke the PAT to prevent indefinite use |
+| Revoked | Yes | No | Not applicable; token is already revoked |
+| Revoked | No | No | Not applicable; token is already revoked |
diff --git a/doc/user/admin_area/img/credentials_inventory_v13_2.png b/doc/user/admin_area/img/credentials_inventory_v13_2.png
deleted file mode 100644
index 5b56422a0a3..00000000000
--- a/doc/user/admin_area/img/credentials_inventory_v13_2.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/img/credentials_inventory_v13_4.png b/doc/user/admin_area/img/credentials_inventory_v13_4.png
new file mode 100644
index 00000000000..06925ea2f6f
--- /dev/null
+++ b/doc/user/admin_area/img/credentials_inventory_v13_4.png
Binary files differ
diff --git a/lib/gitlab/auth/ldap/person.rb b/lib/gitlab/auth/ldap/person.rb
index 0042a747ff4..102820d6bd5 100644
--- a/lib/gitlab/auth/ldap/person.rb
+++ b/lib/gitlab/auth/ldap/person.rb
@@ -57,13 +57,13 @@ module Gitlab
def self.normalize_uid(uid)
::Gitlab::Auth::Ldap::DN.normalize_value(uid)
rescue ::Gitlab::Auth::Ldap::DN::FormatError => e
- Rails.logger.info("Returning original UID \"#{uid}\" due to error during normalization attempt: #{e.message}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info("Returning original UID \"#{uid}\" due to error during normalization attempt: #{e.message}")
uid
end
def initialize(entry, provider)
- Rails.logger.debug { "Instantiating #{self.class.name} with LDIF:\n#{entry.to_ldif}" } # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.debug "Instantiating #{self.class.name} with LDIF:\n#{entry.to_ldif}"
@entry = entry
@provider = provider
end
diff --git a/lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb b/lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb
index c912628d0fc..5b9ee8a0ee2 100644
--- a/lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb
+++ b/lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb
@@ -9,7 +9,7 @@ module Gitlab
end
def perform(start_id, stop_id)
- Rails.logger.info("Setting commits_count for merge request diffs: #{start_id} - #{stop_id}") # rubocop:disable Gitlab/RailsLogger
+ Gitlab::AppLogger.info("Setting commits_count for merge request diffs: #{start_id} - #{stop_id}")
update = '
commits_count = (
diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
new file mode 100644
index 00000000000..829fd7a722f
--- /dev/null
+++ b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml
@@ -0,0 +1,249 @@
+.auto-deploy:
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v1.0.3"
+ dependencies: []
+
+review:
+ extends: .auto-deploy
+ stage: review
+ script:
+ - auto-deploy check_kube_domain
+ - auto-deploy download_chart
+ - auto-deploy ensure_namespace
+ - auto-deploy initialize_tiller
+ - auto-deploy create_secret
+ - auto-deploy deploy
+ - auto-deploy persist_environment_url
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ url: http://$CI_PROJECT_ID-$CI_ENVIRONMENT_SLUG.$KUBE_INGRESS_BASE_DOMAIN
+ on_stop: stop_review
+ artifacts:
+ paths: [environment_url.txt, tiller.log]
+ when: always
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: never
+ - if: '$REVIEW_DISABLED'
+ when: never
+ - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
+
+stop_review:
+ extends: .auto-deploy
+ stage: cleanup
+ variables:
+ GIT_STRATEGY: none
+ script:
+ - auto-deploy initialize_tiller
+ - auto-deploy delete
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ action: stop
+ allow_failure: true
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$CI_COMMIT_BRANCH == "master"'
+ when: never
+ - if: '$REVIEW_DISABLED'
+ when: never
+ - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH'
+ when: manual
+
+# Staging deploys are disabled by default since
+# continuous deployment to production is enabled by default
+# If you prefer to automatically deploy to staging and
+# only manually promote to production, enable this job by setting
+# STAGING_ENABLED.
+
+staging:
+ extends: .auto-deploy
+ stage: staging
+ script:
+ - auto-deploy check_kube_domain
+ - auto-deploy download_chart
+ - auto-deploy ensure_namespace
+ - auto-deploy initialize_tiller
+ - auto-deploy create_secret
+ - auto-deploy deploy
+ environment:
+ name: staging
+ url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_INGRESS_BASE_DOMAIN
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$CI_COMMIT_BRANCH != "master"'
+ when: never
+ - if: '$STAGING_ENABLED'
+
+# Canaries are disabled by default, but if you want them,
+# and know what the downsides are, you can enable this by setting
+# CANARY_ENABLED.
+
+canary:
+ extends: .auto-deploy
+ stage: canary
+ allow_failure: true
+ script:
+ - auto-deploy check_kube_domain
+ - auto-deploy download_chart
+ - auto-deploy ensure_namespace
+ - auto-deploy initialize_tiller
+ - auto-deploy create_secret
+ - auto-deploy deploy canary
+ environment:
+ name: production
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$CI_COMMIT_BRANCH != "master"'
+ when: never
+ - if: '$CANARY_ENABLED'
+ when: manual
+
+.production: &production_template
+ extends: .auto-deploy
+ stage: production
+ script:
+ - auto-deploy check_kube_domain
+ - auto-deploy download_chart
+ - auto-deploy ensure_namespace
+ - auto-deploy initialize_tiller
+ - auto-deploy create_secret
+ - auto-deploy deploy
+ - auto-deploy delete canary
+ - auto-deploy delete rollout
+ - auto-deploy persist_environment_url
+ environment:
+ name: production
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
+ artifacts:
+ paths: [environment_url.txt, tiller.log]
+ when: always
+
+production:
+ <<: *production_template
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$STAGING_ENABLED'
+ when: never
+ - if: '$CANARY_ENABLED'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_ENABLED'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_MODE'
+ when: never
+ - if: '$CI_COMMIT_BRANCH == "master"'
+
+production_manual:
+ <<: *production_template
+ allow_failure: false
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_ENABLED'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_MODE'
+ when: never
+ - if: '$CI_COMMIT_BRANCH == "master" && $STAGING_ENABLED'
+ when: manual
+ - if: '$CI_COMMIT_BRANCH == "master" && $CANARY_ENABLED'
+ when: manual
+
+# This job implements incremental rollout on for every push to `master`.
+
+.rollout: &rollout_template
+ extends: .auto-deploy
+ script:
+ - auto-deploy check_kube_domain
+ - auto-deploy download_chart
+ - auto-deploy ensure_namespace
+ - auto-deploy initialize_tiller
+ - auto-deploy create_secret
+ - auto-deploy deploy rollout $ROLLOUT_PERCENTAGE
+ - auto-deploy scale stable $((100-ROLLOUT_PERCENTAGE))
+ - auto-deploy delete canary
+ - auto-deploy persist_environment_url
+ environment:
+ name: production
+ url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
+ artifacts:
+ paths: [environment_url.txt, tiller.log]
+ when: always
+
+.manual_rollout_template: &manual_rollout_template
+ <<: *rollout_template
+ stage: production
+ resource_group: production
+ allow_failure: true
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_MODE == "timed"'
+ when: never
+ - if: '$CI_COMMIT_BRANCH != "master"'
+ when: never
+ # $INCREMENTAL_ROLLOUT_ENABLED is for compamtibilty with pre-GitLab 11.4 syntax
+ - if: '$INCREMENTAL_ROLLOUT_MODE == "manual" || $INCREMENTAL_ROLLOUT_ENABLED'
+ when: manual
+
+.timed_rollout_template: &timed_rollout_template
+ <<: *rollout_template
+ rules:
+ - if: '$CI_KUBERNETES_ACTIVE == null || $CI_KUBERNETES_ACTIVE == ""'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_MODE == "manual"'
+ when: never
+ - if: '$CI_COMMIT_BRANCH != "master"'
+ when: never
+ - if: '$INCREMENTAL_ROLLOUT_MODE == "timed"'
+ when: delayed
+ start_in: 5 minutes
+
+timed rollout 10%:
+ <<: *timed_rollout_template
+ stage: incremental rollout 10%
+ variables:
+ ROLLOUT_PERCENTAGE: 10
+
+timed rollout 25%:
+ <<: *timed_rollout_template
+ stage: incremental rollout 25%
+ variables:
+ ROLLOUT_PERCENTAGE: 25
+
+timed rollout 50%:
+ <<: *timed_rollout_template
+ stage: incremental rollout 50%
+ variables:
+ ROLLOUT_PERCENTAGE: 50
+
+timed rollout 100%:
+ <<: *timed_rollout_template
+ <<: *production_template
+ stage: incremental rollout 100%
+ variables:
+ ROLLOUT_PERCENTAGE: 100
+
+rollout 10%:
+ <<: *manual_rollout_template
+ variables:
+ ROLLOUT_PERCENTAGE: 10
+
+rollout 25%:
+ <<: *manual_rollout_template
+ variables:
+ ROLLOUT_PERCENTAGE: 25
+
+rollout 50%:
+ <<: *manual_rollout_template
+ variables:
+ ROLLOUT_PERCENTAGE: 50
+
+rollout 100%:
+ <<: *manual_rollout_template
+ <<: *production_template
+ allow_failure: false
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index c795c9869b5..a43e40daecf 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -7870,6 +7870,9 @@ msgstr ""
msgid "DastProfiles|No profiles created yet"
msgstr ""
+msgid "DastProfiles|Passive"
+msgstr ""
+
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
@@ -7885,6 +7888,9 @@ msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
+msgid "DastProfiles|Scan mode"
+msgstr ""
+
msgid "DastProfiles|Scanner Profile"
msgstr ""
@@ -17281,12 +17287,18 @@ msgstr ""
msgid "OnDemandScans|Attached branch is where the scan job runs."
msgstr ""
+msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch site profiles. Please refresh the page, or try again later."
msgstr ""
msgid "OnDemandScans|Could not run the scan. Please try again."
msgstr ""
+msgid "OnDemandScans|Create a new scanner profile"
+msgstr ""
+
msgid "OnDemandScans|Create a new site profile"
msgstr ""
@@ -17299,6 +17311,9 @@ msgstr ""
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
+msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed scanner profile."
+msgstr ""
+
msgid "OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile."
msgstr ""
@@ -17332,6 +17347,9 @@ msgstr ""
msgid "OnDemandScans|Site profiles"
msgstr ""
+msgid "OnDemandScans|Use existing scanner profile"
+msgstr ""
+
msgid "OnDemandScans|Use existing site profile"
msgstr ""
diff --git a/package.json b/package.json
index 8cf19efed07..53c980cc6e8 100644
--- a/package.json
+++ b/package.json
@@ -48,8 +48,8 @@
"@rails/actioncable": "^6.0.3-1",
"@sentry/browser": "^5.22.3",
"@sourcegraph/code-host-integration": "0.0.50",
- "@toast-ui/editor": "^2.3.1",
- "@toast-ui/vue-editor": "^2.3.1",
+ "@toast-ui/editor": "^2.4.0",
+ "@toast-ui/vue-editor": "^2.4.0",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.10",
"apollo-link": "^1.2.14",
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index f8d4690e9ce..188a4cb04af 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -795,13 +795,8 @@ RSpec.describe ApplicationController do
end
let(:user) { create(:user) }
- let(:experiment_enabled) { true }
- before do
- stub_experiment_for_user(signup_flow: experiment_enabled)
- end
-
- context 'experiment enabled and user with required role' do
+ context 'user with required role' do
before do
user.set_role_required!
sign_in(user)
@@ -811,7 +806,7 @@ RSpec.describe ApplicationController do
it { is_expected.to redirect_to users_sign_up_welcome_path }
end
- context 'experiment enabled and user without a required role' do
+ context 'user without a required role' do
before do
sign_in(user)
get :index
@@ -819,43 +814,31 @@ RSpec.describe ApplicationController do
it { is_expected.not_to redirect_to users_sign_up_welcome_path }
end
+ end
- context 'experiment disabled' do
- let(:experiment_enabled) { false }
+ describe 'rescue_from Gitlab::Auth::IpBlacklisted' do
+ controller(described_class) do
+ skip_before_action :authenticate_user!
- before do
- user.set_role_required!
- sign_in(user)
- get :index
+ def index
+ raise Gitlab::Auth::IpBlacklisted
end
-
- it { is_expected.not_to redirect_to users_sign_up_welcome_path }
end
- describe 'rescue_from Gitlab::Auth::IpBlacklisted' do
- controller(described_class) do
- skip_before_action :authenticate_user!
-
- def index
- raise Gitlab::Auth::IpBlacklisted
- end
- end
-
- it 'returns a 403 and logs the request' do
- expect(Gitlab::AuthLogger).to receive(:error).with({
- message: 'Rack_Attack',
- env: :blocklist,
- remote_ip: '1.2.3.4',
- request_method: 'GET',
- path: '/anonymous'
- })
+ it 'returns a 403 and logs the request' do
+ expect(Gitlab::AuthLogger).to receive(:error).with({
+ message: 'Rack_Attack',
+ env: :blocklist,
+ remote_ip: '1.2.3.4',
+ request_method: 'GET',
+ path: '/anonymous'
+ })
- request.remote_addr = '1.2.3.4'
+ request.remote_addr = '1.2.3.4'
- get :index
+ get :index
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ expect(response).to have_gitlab_http_status(:forbidden)
end
end
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 309f8d38f74..744f8ff153c 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -128,7 +128,7 @@ RSpec.describe RegistrationsController do
post(:create, params: user_params)
expect(ActionMailer::Base.deliveries.last.to.first).to eq(user_params[:user][:email])
- expect(response).to redirect_to(dashboard_projects_path)
+ expect(response).to redirect_to(users_sign_up_welcome_path)
end
end
end
@@ -164,10 +164,10 @@ RSpec.describe RegistrationsController do
expect(flash[:alert]).to eq(_('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'))
end
- it 'redirects to the dashboard when the reCAPTCHA is solved' do
+ it 'redirects to the welcome page when the reCAPTCHA is solved' do
post(:create, params: user_params)
- expect(flash[:notice]).to eq(I18n.t('devise.registrations.signed_up'))
+ expect(response).to redirect_to(users_sign_up_welcome_path)
end
end
@@ -464,42 +464,39 @@ RSpec.describe RegistrationsController do
describe '#welcome' do
subject { get :welcome }
- context 'signup_flow experiment enabled' do
- before do
- stub_experiment_for_user(signup_flow: true)
- end
+ it 'renders the devise_experimental_separate_sign_up_flow layout' do
+ sign_in(create(:user))
- it 'renders the devise_experimental_separate_sign_up_flow layout' do
- sign_in(create(:user))
+ expected_layout = Gitlab.ee? ? :checkout : :devise_experimental_separate_sign_up_flow
- expected_layout = Gitlab.ee? ? :checkout : :devise_experimental_separate_sign_up_flow
+ expect(subject).to render_template(expected_layout)
+ end
- expect(subject).to render_template(expected_layout)
+ context '2FA is required from group' do
+ before do
+ user = create(:user, require_two_factor_authentication_from_group: true)
+ sign_in(user)
end
- context '2FA is required from group' do
- before do
- user = create(:user, require_two_factor_authentication_from_group: true)
- sign_in(user)
- end
-
- it 'does not perform a redirect' do
- expect(subject).not_to redirect_to(profile_two_factor_auth_path)
- end
+ it 'does not perform a redirect' do
+ expect(subject).not_to redirect_to(profile_two_factor_auth_path)
end
end
+ end
- context 'signup_flow experiment disabled' do
- before do
- sign_in(create(:user))
- stub_experiment_for_user(signup_flow: false)
- end
+ describe '#update_registration' do
+ subject(:update_registration) do
+ patch :update_registration, params: { user: { role: 'software_developer', setup_for_company: 'false' } }
+ end
- it 'renders the devise layout' do
- expected_layout = Gitlab.ee? ? :checkout : :devise
+ before do
+ sign_in(create(:user))
+ end
- expect(subject).to render_template(expected_layout)
- end
+ it 'sets flash message' do
+ subject
+
+ expect(flash[:notice]).to eq(I18n.t('devise.registrations.signed_up'))
end
end
end
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index e7bcd7876ea..bbe0e64b422 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -38,6 +38,11 @@ RSpec.describe 'Invites', :aggregate_failures do
click_button 'Sign in'
end
+ def fill_in_welcome_form
+ select 'Software Developer', from: 'user_role'
+ click_button 'Get started!'
+ end
+
context 'when signed out' do
before do
visit invite_path(group_invite.raw_invite_token)
@@ -94,6 +99,7 @@ RSpec.describe 'Invites', :aggregate_failures do
it 'signs up and redirects to the dashboard page with all the projects/groups invitations automatically accepted' do
fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
expect(current_path).to eq(dashboard_projects_path)
expect(page).to have_content(project.full_name)
@@ -108,6 +114,7 @@ RSpec.describe 'Invites', :aggregate_failures do
it 'signs up and redirects to the invitation page' do
fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
expect(current_path).to eq(invite_path(group_invite.raw_invite_token))
end
@@ -126,6 +133,7 @@ RSpec.describe 'Invites', :aggregate_failures do
fill_in_sign_up_form(new_user)
confirm_email(new_user)
fill_in_sign_in_form(new_user)
+ fill_in_welcome_form
expect(current_path).to eq(root_path)
expect(page).to have_content(project.full_name)
@@ -143,6 +151,7 @@ RSpec.describe 'Invites', :aggregate_failures do
it 'signs up and redirects to root page with all the project/groups invitation automatically accepted' do
fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
confirm_email(new_user)
expect(current_path).to eq(root_path)
@@ -156,6 +165,7 @@ RSpec.describe 'Invites', :aggregate_failures do
it "doesn't accept invitations until the user confirms their email" do
fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
sign_in(owner)
visit project_project_members_path(project)
@@ -175,6 +185,7 @@ RSpec.describe 'Invites', :aggregate_failures do
fill_in_sign_up_form(new_user)
confirm_email(new_user)
fill_in_sign_in_form(new_user)
+ fill_in_welcome_form
expect(current_path).to eq(invite_path(group_invite.raw_invite_token))
end
@@ -188,6 +199,7 @@ RSpec.describe 'Invites', :aggregate_failures do
it 'signs up and redirects to the invitation page' do
fill_in_sign_up_form(new_user)
+ fill_in_welcome_form
expect(current_path).to eq(invite_path(group_invite.raw_invite_token))
end
diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb
index 522ad708f42..b9752f6676e 100644
--- a/spec/features/users/signup_spec.rb
+++ b/spec/features/users/signup_spec.rb
@@ -187,12 +187,7 @@ RSpec.shared_examples 'Signup' do
expect { click_button 'Register' }.to change { User.count }.by(1)
- if Gitlab::Experimentation.enabled?(:signup_flow)
- expect(current_path).to eq users_sign_up_welcome_path
- else
- expect(current_path).to eq dashboard_projects_path
- expect(page).to have_content("Please check your email (#{new_user.email}) to verify that you own this address and unlock the power of CI/CD.")
- end
+ expect(current_path).to eq users_sign_up_welcome_path
end
end
end
@@ -215,12 +210,7 @@ RSpec.shared_examples 'Signup' do
fill_in 'new_user_password', with: new_user.password
click_button "Register"
- if Gitlab::Experimentation.enabled?(:signup_flow)
- expect(current_path).to eq users_sign_up_welcome_path
- else
- expect(current_path).to eq dashboard_projects_path
- expect(page).to have_content("Welcome! You have signed up successfully.")
- end
+ expect(current_path).to eq users_sign_up_welcome_path
end
end
@@ -246,12 +236,7 @@ RSpec.shared_examples 'Signup' do
fill_in 'new_user_password', with: new_user.password
click_button "Register"
- if Gitlab::Experimentation.enabled?(:signup_flow)
- expect(current_path).to eq users_sign_up_welcome_path
- else
- expect(current_path).to eq dashboard_projects_path
- expect(page).to have_content("Welcome! You have signed up successfully.")
- end
+ expect(current_path).to eq users_sign_up_welcome_path
end
end
end
@@ -354,11 +339,7 @@ RSpec.shared_examples 'Signup' do
click_button "Register"
- if Gitlab::Experimentation.enabled?(:signup_flow)
- expect(current_path).to eq users_sign_up_welcome_path
- else
- expect(current_path).to eq dashboard_projects_path
- end
+ expect(current_path).to eq users_sign_up_welcome_path
end
end
@@ -425,6 +406,37 @@ RSpec.shared_examples 'Signup' do
end
end
end
+
+ it 'redirects to step 2 of the signup process, sets the role and redirects back' do
+ new_user = build_stubbed(:user)
+ visit new_user_registration_path
+
+ fill_in 'new_user_username', with: new_user.username
+ fill_in 'new_user_email', with: new_user.email
+
+ if Gitlab::Experimentation.enabled?(:signup_flow)
+ fill_in 'new_user_first_name', with: new_user.first_name
+ fill_in 'new_user_last_name', with: new_user.last_name
+ else
+ fill_in 'new_user_name', with: new_user.name
+ fill_in 'new_user_email_confirmation', with: new_user.email
+ end
+
+ fill_in 'new_user_password', with: new_user.password
+ click_button 'Register'
+ visit new_project_path
+
+ expect(page).to have_current_path(users_sign_up_welcome_path)
+
+ select 'Software Developer', from: 'user_role'
+ click_button 'Get started!'
+ new_user = User.find_by_username(new_user.username)
+
+ expect(new_user.software_developer_role?).to be_truthy
+ expect(new_user.setup_for_company).to be_nil
+ expect(page).to have_current_path(new_project_path)
+ expect(page).to have_content("Welcome! You have signed up successfully.")
+ end
end
RSpec.shared_examples 'Signup name validation' do |field, max_length|
@@ -485,30 +497,6 @@ RSpec.describe 'With experimental flow' do
it_behaves_like 'Signup name validation', 'new_user_first_name', 127
it_behaves_like 'Signup name validation', 'new_user_last_name', 127
- context 'when role is required' do
- it 'redirects to step 2 of the signup process, sets the role and redirects back' do
- new_user = build_stubbed(:user)
- visit new_user_registration_path
- fill_in 'new_user_first_name', with: new_user.first_name
- fill_in 'new_user_last_name', with: new_user.last_name
- fill_in 'new_user_username', with: new_user.username
- fill_in 'new_user_email', with: new_user.email
- fill_in 'new_user_password', with: new_user.password
- click_button 'Register'
- visit new_project_path
-
- expect(page).to have_current_path(users_sign_up_welcome_path)
-
- select 'Software Developer', from: 'user_role'
- click_button 'Get started!'
- new_user = User.find_by_username(new_user.username)
-
- expect(new_user.software_developer_role?).to be_truthy
- expect(new_user.setup_for_company).to be_nil
- expect(page).to have_current_path(new_project_path)
- end
- end
-
context 'when terms_opt_in experimental is enabled' do
include TermsHelper
diff --git a/spec/frontend/ide/components/jobs/detail/description_spec.js b/spec/frontend/ide/components/jobs/detail/description_spec.js
index 65b579105b0..5554738336a 100644
--- a/spec/frontend/ide/components/jobs/detail/description_spec.js
+++ b/spec/frontend/ide/components/jobs/detail/description_spec.js
@@ -27,4 +27,12 @@ describe('IDE job description', () => {
vm.$el.querySelector('.ci-status-icon [data-testid="status_success_borderless-icon"]'),
).not.toBe(null);
});
+
+ it('renders bridge job details without the job link', () => {
+ vm = mountComponent(Component, {
+ job: { ...jobs[0], path: undefined },
+ });
+
+ expect(vm.$el.querySelector('[data-testid="description-detail-link"]')).toBe(null);
+ });
});
diff --git a/spec/frontend/ide/mock_data.js b/spec/frontend/ide/mock_data.js
index 472516b6a2c..c8925e6745d 100644
--- a/spec/frontend/ide/mock_data.js
+++ b/spec/frontend/ide/mock_data.js
@@ -112,7 +112,8 @@ export const jobs = [
{
id: 4,
name: 'test 4',
- path: 'testing4',
+ // bridge jobs don't have details page and so there is no path attribute
+ // see https://gitlab.com/gitlab-org/gitlab/-/issues/216480
status: {
icon: 'status_failed',
text: 'failed',
diff --git a/spec/frontend/static_site_editor/components/front_matter_controls_spec.js b/spec/frontend/static_site_editor/components/front_matter_controls_spec.js
new file mode 100644
index 00000000000..82e8fad643e
--- /dev/null
+++ b/spec/frontend/static_site_editor/components/front_matter_controls_spec.js
@@ -0,0 +1,78 @@
+import { shallowMount } from '@vue/test-utils';
+
+import { GlFormGroup } from '@gitlab/ui';
+import { humanize } from '~/lib/utils/text_utility';
+
+import FrontMatterControls from '~/static_site_editor/components/front_matter_controls.vue';
+
+describe('~/static_site_editor/components/front_matter_controls.vue', () => {
+ let wrapper;
+
+ // TODO Refactor and update `sourceContentHeaderObjYAML` in mock_data when !41230 lands
+ const settings = {
+ layout: 'handbook-page-toc',
+ title: 'Handbook',
+ twitter_image: '/images/tweets/handbook-gitlab.png',
+ suppress_header: true,
+ extra_css: ['sales-and-free-trial-common.css', 'form-to-resource.css'],
+ };
+
+ const buildWrapper = (propsData = {}) => {
+ wrapper = shallowMount(FrontMatterControls, {
+ propsData: {
+ settings,
+ ...propsData,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ buildWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should render only the supported GlFormGroup types', () => {
+ expect(wrapper.findAll(GlFormGroup)).toHaveLength(3);
+ });
+
+ it.each`
+ key
+ ${'layout'}
+ ${'title'}
+ ${'twitter_image'}
+ `('renders field when key is $key', ({ key }) => {
+ const glFormGroup = wrapper.find(`#sse-front-matter-form-group-${key}`);
+ const glFormInput = wrapper.find(`#sse-front-matter-control-${key}`);
+
+ expect(glFormGroup.exists()).toBe(true);
+ expect(glFormGroup.attributes().label).toBe(humanize(key));
+
+ expect(glFormInput.exists()).toBe(true);
+ expect(glFormInput.attributes().value).toBe(settings[key]);
+ });
+
+ it.each`
+ key
+ ${'suppress_header'}
+ ${'extra_css'}
+ `('does not render field when key is $key', ({ key }) => {
+ const glFormInput = wrapper.find(`#sse-front-matter-control-${key}`);
+
+ expect(glFormInput.exists()).toBe(false);
+ });
+
+ it('emits updated settings when nested control updates', () => {
+ const elId = `#sse-front-matter-control-title`;
+ const glFormInput = wrapper.find(elId);
+ const newTitle = 'New title';
+
+ glFormInput.vm.$emit('input', newTitle);
+
+ const newSettings = { ...settings, title: newTitle };
+
+ expect(wrapper.emitted('updateSettings')[0][0]).toMatchObject(newSettings);
+ });
+});
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 5ed9eb6252a..ff574a2e2f4 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -855,6 +855,23 @@ RSpec.describe Issuable do
end
end
+ describe '#supports_issue_type?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:issuable_type, :supports_issue_type) do
+ :issue | true
+ :merge_request | false
+ end
+
+ with_them do
+ let(:issuable) { build_stubbed(issuable_type) }
+
+ subject { issuable.supports_issue_type? }
+
+ it { is_expected.to eq(supports_issue_type) }
+ end
+ end
+
describe '#severity' do
subject { issuable.severity }
diff --git a/spec/serializers/job_entity_spec.rb b/spec/serializers/job_entity_spec.rb
index adfda36a9dc..1cbf1914c0c 100644
--- a/spec/serializers/job_entity_spec.rb
+++ b/spec/serializers/job_entity_spec.rb
@@ -218,4 +218,16 @@ RSpec.describe JobEntity do
expect(subject).not_to include('recoverable')
end
end
+
+ context 'when job is a bridge' do
+ let(:job) { create(:ci_bridge) }
+
+ it 'does not include build path' do
+ expect(subject).not_to include(:build_path)
+ end
+
+ it 'does not include cancel path' do
+ expect(subject).not_to include(:cancel_path)
+ end
+ end
end
diff --git a/yarn.lock b/yarn.lock
index c3ddc6fce32..2a04ded94c6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1162,20 +1162,20 @@
dom-accessibility-api "^0.4.5"
pretty-format "^25.5.0"
-"@toast-ui/editor@^2.3.1":
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/@toast-ui/editor/-/editor-2.3.1.tgz#add692840011efcdbd9b4b6de93dda2da12c36a0"
- integrity sha512-0akQUnyCg24SBBb+weRX6VJ6ZjltxYEivBWOHft0birkrPF0YQgKjebPtFGPB9THBSUY+0qyr6k/KIN2rZqUog==
+"@toast-ui/editor@^2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@toast-ui/editor/-/editor-2.4.0.tgz#0ed082da7e0160162dbc8f69d00ad3ab2adf81bc"
+ integrity sha512-49YCYcDnCjv4mC9VVNlytJ23SA5t6ox540GnmysluJHJ8aGRdWcVoH8hiyCZi9ZVIXi90B/TU+2HUQ7mOCHHRQ==
dependencies:
"@types/codemirror" "0.0.71"
codemirror "^5.48.4"
-"@toast-ui/vue-editor@^2.3.1":
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/@toast-ui/vue-editor/-/vue-editor-2.3.1.tgz#ca8771a77513d1998123db717626a2ec4267b6f5"
- integrity sha512-vEElTwJ3CwUL2da2y3gxKVK7bRWC+d6SrUyOQNeCDtN95vEs/7MUNK4cUAxAGDZuDYg1KB2ZpBtc/dV1LkO9XQ==
+"@toast-ui/vue-editor@^2.4.0":
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/@toast-ui/vue-editor/-/vue-editor-2.4.0.tgz#18b6629006f2dac5bfef4a26388499931d5fa869"
+ integrity sha512-fj4H4jM+usW43mD0VEIfBeUpANY9/pQLB8GlXLQH2iAmpmJFX+xMZl6r7d/vw6TDJaHLfFxP/iXcYIfyJobepQ==
dependencies:
- "@toast-ui/editor" "^2.3.1"
+ "@toast-ui/editor" "^2.4.0"
"@types/babel__core@^7.1.0":
version "7.1.2"