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:
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/rails/shared.gitlab-ci.yml2
-rw-r--r--app/assets/javascripts/abuse_reports/components/abuse_category_selector.vue6
-rw-r--r--app/assets/javascripts/admin/abuse_report/components/report_actions.vue6
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/drawer/pipeline_editor_drawer.vue7
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/constants.js2
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer.vue8
-rw-r--r--app/assets/javascripts/ci/runner/components/registration/platforms_drawer.vue6
-rw-r--r--app/assets/javascripts/diffs/components/shared/findings_drawer.vue6
-rw-r--r--app/views/admin/sessions/_signin_box.html.haml2
-rw-r--r--app/views/devise/sessions/_new_crowd.html.haml29
-rw-r--r--scripts/rspec_helpers.sh18
-rw-r--r--spec/support/formatters/json_formatter.rb100
13 files changed, 148 insertions, 46 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index bebb0a6f6ee..f17a5f77214 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -150,8 +150,6 @@ variables:
FLAKY_RSPEC_SUITE_REPORT_PATH: rspec/flaky/report-suite.json
FRONTEND_FIXTURES_MAPPING_PATH: crystalball/frontend_fixtures_mapping.json
GITLAB_WORKHORSE_FOLDER: "gitlab-workhorse"
- JUNIT_RESULT_FILE: rspec/junit_rspec.xml
- JUNIT_RETRY_FILE: rspec/junit_rspec-retry.xml
KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/report-master.json
RSPEC_CHANGED_FILES_PATH: rspec/changed_files.txt
RSPEC_FOSS_IMPACT_PIPELINE_TEMPLATE_YML: .gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb
diff --git a/.gitlab/ci/rails/shared.gitlab-ci.yml b/.gitlab/ci/rails/shared.gitlab-ci.yml
index 98cc4cc44c8..618c4e3b654 100644
--- a/.gitlab/ci/rails/shared.gitlab-ci.yml
+++ b/.gitlab/ci/rails/shared.gitlab-ci.yml
@@ -92,7 +92,7 @@ include:
- tmp/capybara/
- log/*.log
reports:
- junit: ${JUNIT_RESULT_FILE}
+ junit: "rspec/rspec-*.xml"
.rspec-base-migration:
script:
diff --git a/app/assets/javascripts/abuse_reports/components/abuse_category_selector.vue b/app/assets/javascripts/abuse_reports/components/abuse_category_selector.vue
index 4a7c12e5e51..266950e2769 100644
--- a/app/assets/javascripts/abuse_reports/components/abuse_category_selector.vue
+++ b/app/assets/javascripts/abuse_reports/components/abuse_category_selector.vue
@@ -60,11 +60,11 @@ export default {
};
},
computed: {
- drawerOffsetTop() {
+ getDrawerHeaderHeight() {
// avoid calculating this in advance because it causes layout thrashing
// https://gitlab.com/gitlab-org/gitlab/-/issues/331172#note_1269378396
if (!this.showDrawer) return '0';
- return getContentWrapperHeight('.content-wrapper');
+ return getContentWrapperHeight();
},
},
mounted() {
@@ -81,7 +81,7 @@ export default {
</script>
<template>
<gl-drawer
- :header-height="drawerOffsetTop"
+ :header-height="getDrawerHeaderHeight"
:z-index="300"
:open="showDrawer && mounted"
@close="closeDrawer"
diff --git a/app/assets/javascripts/admin/abuse_report/components/report_actions.vue b/app/assets/javascripts/admin/abuse_report/components/report_actions.vue
index bb6e022da54..25b22afbf84 100644
--- a/app/assets/javascripts/admin/abuse_report/components/report_actions.vue
+++ b/app/assets/javascripts/admin/abuse_report/components/report_actions.vue
@@ -56,9 +56,9 @@ export default {
};
},
computed: {
- drawerOffsetTop() {
+ getDrawerHeaderHeight() {
if (!this.showActionsDrawer || gon.use_new_navigation) return '0';
- return getContentWrapperHeight('.content-wrapper');
+ return getContentWrapperHeight();
},
isFormValid() {
return Object.values(this.validationState).every(Boolean);
@@ -124,7 +124,7 @@ export default {
</gl-button>
<gl-drawer
:open="showActionsDrawer"
- :header-height="drawerOffsetTop"
+ :header-height="getDrawerHeaderHeight"
:z-index="$options.DRAWER_Z_INDEX"
@close="toggleActionsDrawer"
>
diff --git a/app/assets/javascripts/ci/pipeline_editor/components/drawer/pipeline_editor_drawer.vue b/app/assets/javascripts/ci/pipeline_editor/components/drawer/pipeline_editor_drawer.vue
index 52c5f5f9b8e..b3befcf1cbc 100644
--- a/app/assets/javascripts/ci/pipeline_editor/components/drawer/pipeline_editor_drawer.vue
+++ b/app/assets/javascripts/ci/pipeline_editor/components/drawer/pipeline_editor_drawer.vue
@@ -3,7 +3,6 @@ import { GlDrawer } from '@gitlab/ui';
import { DRAWER_Z_INDEX } from '~/lib/utils/constants';
import { getContentWrapperHeight } from '~/lib/utils/dom_utils';
import { __ } from '~/locale';
-import { DRAWER_CONTAINER_CLASS } from '../job_assistant_drawer/constants';
import FirstPipelineCard from './cards/first_pipeline_card.vue';
import GettingStartedCard from './cards/getting_started_card.vue';
import PipelineConfigReferenceCard from './cards/pipeline_config_reference_card.vue';
@@ -36,8 +35,8 @@ export default {
},
},
computed: {
- drawerHeightOffset() {
- return getContentWrapperHeight(DRAWER_CONTAINER_CLASS);
+ getDrawerHeaderHeight() {
+ return getContentWrapperHeight();
},
},
methods: {
@@ -49,7 +48,7 @@ export default {
</script>
<template>
<gl-drawer
- :header-height="drawerHeightOffset"
+ :header-height="getDrawerHeaderHeight"
:open="isVisible"
:z-index="zIndex"
@close="closeDrawer"
diff --git a/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/constants.js b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/constants.js
index e93a9e84302..e650b88af5f 100644
--- a/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/constants.js
+++ b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/constants.js
@@ -1,7 +1,5 @@
import { __, s__ } from '~/locale';
-export const DRAWER_CONTAINER_CLASS = '.content-wrapper';
-
export const JOB_RULES_WHEN = {
onSuccess: {
value: 'on_success',
diff --git a/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer.vue b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer.vue
index a97b9ed8d5a..9eeaac32e95 100644
--- a/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer.vue
+++ b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer.vue
@@ -6,7 +6,7 @@ import { DRAWER_Z_INDEX } from '~/lib/utils/constants';
import { getContentWrapperHeight } from '~/lib/utils/dom_utils';
import eventHub, { SCROLL_EDITOR_TO_BOTTOM } from '~/ci/pipeline_editor/event_hub';
import getRunnerTags from '../../graphql/queries/runner_tags.query.graphql';
-import { DRAWER_CONTAINER_CLASS, JOB_TEMPLATE, JOB_RULES_WHEN, i18n } from './constants';
+import { JOB_TEMPLATE, JOB_RULES_WHEN, i18n } from './constants';
import { removeEmptyObj, trimFields, validateEmptyValue, validateStartIn } from './utils';
import JobSetupItem from './accordion_items/job_setup_item.vue';
import ImageItem from './accordion_items/image_item.vue';
@@ -79,8 +79,8 @@ export default {
};
});
},
- drawerHeightOffset() {
- return getContentWrapperHeight(DRAWER_CONTAINER_CLASS);
+ getDrawerHeaderHeight() {
+ return getContentWrapperHeight();
},
isJobValid() {
return this.isNameValid && this.isScriptValid && this.isStartValid;
@@ -173,7 +173,7 @@ export default {
<template>
<gl-drawer
class="job-assistant-drawer"
- :header-height="drawerHeightOffset"
+ :header-height="getDrawerHeaderHeight"
:open="isVisible"
:z-index="zIndex"
@close="closeDrawer"
diff --git a/app/assets/javascripts/ci/runner/components/registration/platforms_drawer.vue b/app/assets/javascripts/ci/runner/components/registration/platforms_drawer.vue
index ff182c61ccf..9cf2572c924 100644
--- a/app/assets/javascripts/ci/runner/components/registration/platforms_drawer.vue
+++ b/app/assets/javascripts/ci/runner/components/registration/platforms_drawer.vue
@@ -42,8 +42,8 @@ export default {
};
},
computed: {
- drawerHeightOffset() {
- return getContentWrapperHeight('.content-wrapper');
+ getDrawerHeaderHeight() {
+ return getContentWrapperHeight();
},
architectureOptions() {
return platformArchitectures({ platform: this.selectedPlatform });
@@ -86,7 +86,7 @@ export default {
<template>
<gl-drawer
:open="open"
- :header-height="drawerHeightOffset"
+ :header-height="getDrawerHeaderHeight"
:z-index="$options.DRAWER_Z_INDEX"
data-testid="runner-platforms-drawer"
@close="onClose"
diff --git a/app/assets/javascripts/diffs/components/shared/findings_drawer.vue b/app/assets/javascripts/diffs/components/shared/findings_drawer.vue
index da880c6f3ca..2cffe928d7b 100644
--- a/app/assets/javascripts/diffs/components/shared/findings_drawer.vue
+++ b/app/assets/javascripts/diffs/components/shared/findings_drawer.vue
@@ -30,8 +30,8 @@ export default {
ALLOWED_ATTR: ['href', 'rel'],
},
computed: {
- drawerOffsetTop() {
- return getContentWrapperHeight('.content-wrapper');
+ getDrawerHeaderHeight() {
+ return getContentWrapperHeight();
},
},
DRAWER_Z_INDEX,
@@ -47,7 +47,7 @@ export default {
</script>
<template>
<gl-drawer
- :header-height="drawerOffsetTop"
+ :header-height="getDrawerHeaderHeight"
:z-index="$options.DRAWER_Z_INDEX"
class="findings-drawer"
:open="Object.keys(drawer).length !== 0"
diff --git a/app/views/admin/sessions/_signin_box.html.haml b/app/views/admin/sessions/_signin_box.html.haml
index 15005bb9224..70cad880293 100644
--- a/app/views/admin/sessions/_signin_box.html.haml
+++ b/app/views/admin/sessions/_signin_box.html.haml
@@ -2,7 +2,7 @@
- if crowd_enabled?
.login-box.tab-pane{ id: "crowd", role: 'tabpanel', class: active_when(form_based_auth_provider_has_active_class?(:crowd)) }
.login-body
- = render 'devise/sessions/new_crowd'
+ = render 'devise/sessions/new_crowd', render_remember_me: false, submit_message: _('Enter admin mode')
- ldap_servers.each_with_index do |server, i|
.login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i == 0 && form_based_auth_provider_has_active_class?(:ldapmain)) }
diff --git a/app/views/devise/sessions/_new_crowd.html.haml b/app/views/devise/sessions/_new_crowd.html.haml
index 293e287371a..983b8160b69 100644
--- a/app/views/devise/sessions/_new_crowd.html.haml
+++ b/app/views/devise/sessions/_new_crowd.html.haml
@@ -1,13 +1,16 @@
-= form_tag(omniauth_authorize_path(:user, :crowd), id: 'new_crowd_user', class: 'gl-show-field-errors') do
- .form-group.gl-px-5.gl-pt-5
- = label_tag :username, _('Username or email')
- = text_field_tag :username, nil, { class: "form-control top", title: _("This field is required."), autofocus: "autofocus", required: true }
- .form-group.gl-px-5
- = label_tag :password
- = password_field_tag :password, nil, { class: 'form-control gl-form-input js-password', data: { id: 'password', name: 'password' } }
- - if remember_me_enabled?
- .remember-me.gl-px-5
- %label{ for: "remember_me" }
- = check_box_tag :remember_me, '1', false, id: 'remember_me'
- %span= _('Remember me')
- = submit_tag _("Sign in"), class: "gl-button btn-confirm btn gl-px-5"
+- render_remember_me = remember_me_enabled? && local_assigns.fetch(:render_remember_me, true)
+- submit_message = local_assigns.fetch(:submit_message, _('Sign in'))
+
+= gitlab_ui_form_for(:crowd, url: omniauth_authorize_path(:user, :crowd), html: { class: 'gl-p-5 gl-show-field-errors', aria: { live: 'assertive' }, data: { testid: 'new_crowd_user' }}) do |f|
+ .form-group
+ = f.label :username, _('Username or email')
+ = f.text_field :username, name: :username, autocomplete: :username, class: 'form-control gl-form-input', title: _('This field is required.'), autofocus: 'autofocus', required: true
+ .form-group
+ = f.label :password, _('Password')
+ = f.password_field :password, name: :password, autocomplete: :current_password, class: 'form-control gl-form-input js-password', data: { id: 'password', name: 'password' }
+
+ - if render_remember_me
+ = f.gitlab_ui_checkbox_component :remember_me, _('Remember me'), checkbox_options: { name: :remember_me, autocomplete: 'off' }
+
+ = render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true) do
+ = submit_message
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index 4e73bf48021..8be98cb6346 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -97,15 +97,16 @@ function retrieve_failed_tests() {
function rspec_args() {
local rspec_opts="${1}"
- local junit_report_file="${2:-${JUNIT_RESULT_FILE}}"
+ local json_report_file="${2:-rspec/rspec-${CI_JOB_ID}.json}"
+ local junit_report_file="${3:-rspec/rspec-${CI_JOB_ID}.xml}"
- echo "-Ispec -rspec_helper --color --failure-exit-code 1 --error-exit-code 2 --format documentation --format RspecJunitFormatter --out ${junit_report_file} ${rspec_opts}"
+ echo "-Ispec -rspec_helper --color --failure-exit-code 1 --error-exit-code 2 --format documentation --format Support::Formatters::JsonFormatter --out ${json_report_file} --format RspecJunitFormatter --out ${junit_report_file} ${rspec_opts}"
}
function rspec_simple_job() {
export NO_KNAPSACK="1"
- local rspec_cmd="bin/rspec $(rspec_args "${1}" "${2}")"
+ local rspec_cmd="bin/rspec $(rspec_args "${1}" "${2}" "${3}")"
echoinfo "Running RSpec command: ${rspec_cmd}"
eval "${rspec_cmd}"
@@ -114,7 +115,7 @@ function rspec_simple_job() {
function rspec_simple_job_with_retry () {
local rspec_run_status=0
- rspec_simple_job "${1}" "${2}" || rspec_run_status=$?
+ rspec_simple_job "${1}" "${2}" "${3}" || rspec_run_status=$?
handle_retry_rspec_in_new_process $rspec_run_status
}
@@ -265,13 +266,16 @@ function retry_failed_rspec_examples() {
local default_knapsack_pattern="{,ee/,jh/}spec/{,**/}*_spec.rb"
local knapsack_test_file_pattern="${KNAPSACK_TEST_FILE_PATTERN:-$default_knapsack_pattern}"
+ local json_retry_file="rspec/rspec-retry-${CI_JOB_ID}.json"
+ local junit_retry_file="rspec/rspec-retry-${CI_JOB_ID}.xml"
# Retry only the tests that failed on first try
- rspec_simple_job "--only-failures --pattern \"${knapsack_test_file_pattern}\"" "${JUNIT_RETRY_FILE}"
+ rspec_simple_job "--only-failures --pattern \"${knapsack_test_file_pattern}\"" "${json_retry_file}" "${junit_retry_file}"
rspec_run_status=$?
- # Merge the JUnit report from retry into the first-try report
- junit_merge "${JUNIT_RETRY_FILE}" "${JUNIT_RESULT_FILE}" --update-only
+ # Merge the reports from retry into the first-try report
+ scripts/merge-reports "rspec/rspec-${CI_JOB_ID}.json" "${json_retry_file}"
+ junit_merge "${junit_retry_file}" "rspec/rspec-${CI_JOB_ID}.xml" --update-only
if [[ $rspec_run_status -eq 0 ]]; then
# The test is flaky because it succeeded after being retried.
diff --git a/spec/support/formatters/json_formatter.rb b/spec/support/formatters/json_formatter.rb
new file mode 100644
index 00000000000..9ca1a538293
--- /dev/null
+++ b/spec/support/formatters/json_formatter.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'rspec/core/formatters'
+
+module Support
+ module Formatters
+ class JsonFormatter < RSpec::Core::Formatters::JsonFormatter
+ QA_SUPPORT_LOGLINKING_CONST = 'QA::Support::Loglinking'
+
+ RSpec::Core::Formatters.register self, :message, :dump_summary, :stop, :seed, :close
+
+ def dump_profile(profile)
+ # We don't currently use the profile info. This overrides the base
+ # implementation so that it's not included.
+ end
+
+ def stop(example_notification)
+ # Based on https://github.com/rspec/rspec-core/blob/main/lib/rspec/core/formatters/json_formatter.rb#L35
+ # But modified to include full details of multiple exceptions and to provide output similar to
+ # https://github.com/sj26/rspec_junit_formatter
+ @output_hash[:examples] = example_notification.notifications.map do |notification|
+ format_example(notification.example).tap do |hash|
+ e = notification.example.exception
+ if e
+ exceptions = e.respond_to?(:all_exceptions) ? e.all_exceptions : [e]
+ hash[:exceptions] = exceptions.map do |exception|
+ hash = {
+ class: exception.class.name,
+ message: exception.message,
+ message_lines: strip_ansi_codes(notification.message_lines),
+ backtrace: notification.formatted_backtrace
+ }
+
+ if loglinking
+ hash.merge!(
+ correlation_id: exception.message[match_data_after(loglinking::CORRELATION_ID_TITLE)],
+ sentry_url: exception.message[match_data_after(loglinking::SENTRY_URL_TITLE)],
+ kibana_discover_url: exception.message[match_data_after(loglinking::KIBANA_DISCOVER_URL_TITLE)],
+ kibana_dashboard_url: exception.message[match_data_after(loglinking::KIBANA_DASHBOARD_URL_TITLE)]
+ )
+ end
+
+ hash
+ end
+ end
+ end
+ end
+ end
+
+ private
+
+ def loglinking
+ return @loglinking if defined?(@loglinking)
+
+ @loglinking = Object.const_defined?(QA_SUPPORT_LOGLINKING_CONST) &&
+ Object.const_get(QA_SUPPORT_LOGLINKING_CONST, false)
+ end
+
+ def format_example(example)
+ file_path, line_number = location_including_shared_examples(example.metadata)
+
+ {
+ id: example.id,
+ description: example.description,
+ full_description: example.full_description,
+ status: example.execution_result.status.to_s,
+ file_path: file_path,
+ line_number: line_number.to_i,
+ run_time: example.execution_result.run_time,
+ pending_message: example.execution_result.pending_message,
+ testcase: example.metadata[:testcase],
+ quarantine: example.metadata[:quarantine],
+ screenshot: example.metadata[:screenshot],
+ product_group: example.metadata[:product_group],
+ feature_category: example.metadata[:feature_category],
+ ci_job_url: ENV['CI_JOB_URL']
+ }
+ end
+
+ def location_including_shared_examples(metadata)
+ if metadata[:shared_group_inclusion_backtrace].empty?
+ [metadata[:file_path], metadata[:line_number]]
+ else
+ # If there are nested shared examples, the outermost location is last in the array
+ metadata[:shared_group_inclusion_backtrace].last.formatted_inclusion_location.split(':')
+ end
+ end
+
+ def strip_ansi_codes(strings)
+ # The code below is from https://github.com/piotrmurach/pastel/blob/master/lib/pastel/color.rb
+ modified = Array(strings).map { |string| string.dup.gsub(/\x1b\[{1,2}[0-9;:?]*m/m, '') }
+ modified.size == 1 ? modified[0] : modified
+ end
+
+ def match_data_after(title)
+ /(?<=#{title} ).*/
+ end
+ end
+ end
+end