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>2022-09-15 09:12:51 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-09-15 09:12:51 +0300
commit9a0e0265e4fd6ef93e63c670adc66637dd6ff553 (patch)
treecccf72d3e3081367a39d224ba71a111bea5f9604
parent6eb95ccbe88e8e8db374079895549cf8c3f50a1c (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/package-and-test/variables.gitlab-ci.yml1
-rw-r--r--.gitlab/ci/review-apps/main.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/review-apps/qa.gitlab-ci.yml119
-rw-r--r--.gitlab/ci/review-apps/rules.gitlab-ci.yml80
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml50
-rw-r--r--app/assets/javascripts/user_popovers.js1
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/constants.js13
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue116
-rw-r--r--app/views/notify/repository_push_email.html.haml29
-rw-r--r--lib/gitlab/email/message/repository_push.rb6
-rw-r--r--locale/gitlab.pot47
-rw-r--r--qa/qa/scenario/test/instance/blocking.rb16
-rw-r--r--qa/qa/scenario/test/instance/review_blocking.rb16
-rw-r--r--qa/qa/scenario/test/instance/review_non_blocking.rb16
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb2
-rw-r--r--qa/qa/tools/ci/non_empty_suites.rb3
-rwxr-xr-xscripts/generate-e2e-pipeline8
-rw-r--r--spec/fast_spec_helper.rb7
-rw-r--r--spec/frontend/vue_shared/components/user_popover/user_popover_spec.js39
-rw-r--r--spec/spec_helper.rb6
-rw-r--r--spec/support/rspec.rb7
21 files changed, 364 insertions, 222 deletions
diff --git a/.gitlab/ci/package-and-test/variables.gitlab-ci.yml b/.gitlab/ci/package-and-test/variables.gitlab-ci.yml
index 36bb2f8d5f6..324092c80f4 100644
--- a/.gitlab/ci/package-and-test/variables.gitlab-ci.yml
+++ b/.gitlab/ci/package-and-test/variables.gitlab-ci.yml
@@ -4,7 +4,6 @@ variables:
RELEASE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/build/omnibus-gitlab-mirror/gitlab-ee:${CI_COMMIT_SHA}"
SKIP_REPORT_IN_ISSUES: "true"
OMNIBUS_GITLAB_CACHE_UPDATE: "false"
- COLORIZED_LOGS: "true"
QA_LOG_LEVEL: "info"
QA_TESTS: ""
QA_FEATURE_FLAGS: ""
diff --git a/.gitlab/ci/review-apps/main.gitlab-ci.yml b/.gitlab/ci/review-apps/main.gitlab-ci.yml
index 16bc8d39d15..7bb5fa258c2 100644
--- a/.gitlab/ci/review-apps/main.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/main.gitlab-ci.yml
@@ -11,6 +11,7 @@ stages:
include:
- local: .gitlab/ci/global.gitlab-ci.yml
- local: .gitlab/ci/rules.gitlab-ci.yml
+ - local: .gitlab/ci/review-apps/rules.gitlab-ci.yml
- local: .gitlab/ci/review-apps/qa.gitlab-ci.yml
- local: .gitlab/ci/review-apps/dast.gitlab-ci.yml
@@ -97,6 +98,7 @@ review-deploy:
- export GITALY_VERSION=$(<GITALY_SERVER_VERSION)
- export GITLAB_WORKHORSE_VERSION=$(<GITLAB_WORKHORSE_VERSION)
- echo "${CI_ENVIRONMENT_URL}" > environment_url.txt
+ - echo "QA_GITLAB_URL=${CI_ENVIRONMENT_URL}" > environment.env
- *base-before_script
script:
- check_kube_domain
@@ -112,6 +114,8 @@ review-deploy:
artifacts:
paths:
- environment_url.txt
+ reports:
+ dotenv: environment.env
expire_in: 7 days
when: always
diff --git a/.gitlab/ci/review-apps/qa.gitlab-ci.yml b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
index e664e556068..ee094a131f7 100644
--- a/.gitlab/ci/review-apps/qa.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
@@ -1,6 +1,6 @@
include:
- project: gitlab-org/quality/pipeline-common
- ref: 0.13.0
+ ref: 1.2.2
file:
- /ci/allure-report.yml
- /ci/knapsack-report.yml
@@ -8,7 +8,7 @@ include:
.test-variables:
variables:
QA_GENERATE_ALLURE_REPORT: "true"
- COLORIZED_LOGS: "true"
+ QA_CAN_TEST_PRAEFECT: "false"
GITLAB_USERNAME: "root"
GITLAB_PASSWORD: "${REVIEW_APPS_ROOT_PASSWORD}"
GITLAB_ADMIN_USERNAME: "root"
@@ -21,49 +21,31 @@ include:
- .qa-cache
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-bullseye-ruby-${RUBY_VERSION}:bundler-2.3
before_script:
- - export QA_GITLAB_URL="$(cat environment_url.txt)"
- cd qa && bundle install
.review-qa-base:
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-bullseye-ruby-${RUBY_VERSION}:bundler-2.3-git-2.33-lfs-2.9-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-gcloud-383-kubectl-1.23
extends:
- .use-docker-in-docker
- .bundle-base
- .test-variables
- image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-bullseye-ruby-${RUBY_VERSION}:bundler-2.3-git-2.33-lfs-2.9-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-gcloud-383-kubectl-1.23
stage: qa
needs:
- review-deploy
- download-knapsack-report
variables:
- DOCKER_HOST: tcp://docker:2376
- DOCKER_TLS_CERTDIR: /certs
- DOCKER_CERT_PATH: /certs/client
- DOCKER_TLS_VERIFY: 1
GIT_LFS_SKIP_SMUDGE: 1
WD_INSTALL_DIR: /usr/local/bin
- before_script:
- - !reference [.bundle-base, before_script]
+ RSPEC_REPORT_OPTS: --force-color --order random --format documentation --format RspecJunitFormatter --out tmp/rspec.xml
script:
- export EE_LICENSE="$(cat $REVIEW_APPS_EE_LICENSE_FILE)"
- - qa_run_status=0
+ - QA_COMMAND="bundle exec bin/qa ${QA_SCENARIO} ${QA_GITLAB_URL} -- ${QA_TESTS} ${RSPEC_REPORT_OPTS}"
+ - echo "Running - '${QA_COMMAND}'"
+ - eval "$QA_COMMAND"
+ after_script:
- |
- bundle exec rake "knapsack:rspec[\
- ${RSPEC_TAGS} \
- --tag ~orchestrated \
- --tag ~transient \
- --tag ~skip_signup_disabled \
- --tag ~requires_git_protocol_v2 \
- --tag ~requires_praefect \
- --force-color \
- --order random \
- --format documentation \
- --format RspecJunitFormatter --out tmp/rspec.xml \
- ]" || qa_run_status=$?
- - if [ ${qa_run_status} -ne 0 ]; then
- release_sha=$(echo "${CI_COMMIT_SHA}" | cut -c1-11);
- echo "Errors can be found at https://sentry.gitlab.net/gitlab/gitlab-review-apps/releases/${release_sha}/all-events/.";
- fi
- - exit ${qa_run_status}
+ echo "Sentry errors for the current review-app test run can be found via following url:"
+ echo "https://sentry.gitlab.net/gitlab/gitlab-review-apps/releases/$(echo "${CI_COMMIT_SHA}" | cut -c1-11)/all-events/."
artifacts:
paths:
- qa/tmp
@@ -72,20 +54,11 @@ include:
expire_in: 7 days
when: always
-.allure-report-base:
- extends: .generate-allure-report-base
- stage: post-qa
- variables:
- GITLAB_AUTH_TOKEN: $GITLAB_QA_MR_ALLURE_REPORT_TOKEN
- ALLURE_PROJECT_PATH: $CI_PROJECT_PATH
- ALLURE_MERGE_REQUEST_IID: $CI_MERGE_REQUEST_IID
- ALLURE_RESULTS_GLOB: qa/tmp/allure-results/*
-
# Store knapsack report as artifact so the same report is reused across all jobs
download-knapsack-report:
extends:
- .bundle-base
- - .review:rules:review-qa-reliable
+ - .rules:qa-framework-changes-or-review-scenarios
stage: prepare
script:
- bundle exec rake "knapsack:download[qa]"
@@ -98,30 +71,39 @@ download-knapsack-report:
review-qa-smoke:
extends:
- .review-qa-base
- - .review:rules:review-qa-smoke
- retry: 1
+ - .rules:qa-smoke
variables:
+ QA_SCENARIO: Test::Instance::Smoke
QA_RUN_TYPE: review-qa-smoke
- RSPEC_TAGS: --tag smoke
+ retry: 1
-review-qa-reliable:
+review-qa-blocking:
extends:
- .review-qa-base
- - .review:rules:review-qa-reliable
+ - .rules:qa-blocking
+ variables:
+ QA_SCENARIO: Test::Instance::ReviewBlocking
+ QA_RUN_TYPE: review-qa-blocking
retry: 1
+review-qa-blocking-parallel:
+ extends:
+ - review-qa-blocking
+ - .rules:qa-blocking-parallel
parallel: 10
- variables:
- QA_RUN_TYPE: review-qa-reliable
- RSPEC_TAGS: --tag reliable --tag sanity_feature_flags
-review-qa-all:
+review-qa-non-blocking:
extends:
- .review-qa-base
- - .review:rules:review-qa-all
- parallel: 5
+ - .rules:qa-non-blocking
variables:
- QA_RUN_TYPE: review-qa-all
- RSPEC_TAGS: --tag ~reliable --tag ~smoke --tag ~sanity_feature_flags
+ QA_SCENARIO: Test::Instance::ReviewNonBlocking
+ QA_RUN_TYPE: review-qa-non-blocking
+ allow_failure: true
+review-qa-non-blocking-parallel:
+ extends:
+ - review-qa-non-blocking
+ - .rules:qa-non-blocking-parallel
+ parallel: 5
review-performance:
extends:
@@ -149,27 +131,20 @@ review-performance:
performance: performance.json
expire_in: 31d
-# Generate single report for both smoke and reliable test jobs
-# Both job types are essentially the same:
-# * always executed
-# * always blocking
-allure-report-qa-blocking:
+e2e-test-report:
extends:
- - .allure-report-base
- - .review:rules:review-qa-blocking-report
- needs:
- - review-qa-smoke
- - review-qa-reliable
- variables:
- ALLURE_JOB_NAME: e2e-review-qa-blocking
-
-allure-report-qa-all:
- extends:
- - .allure-report-base
- - .review:rules:review-qa-all-report
- needs: ["review-qa-all"]
+ - .generate-allure-report-base
+ - .rules:qa-framework-changes-or-review-scenarios
+ stage: post-qa
variables:
- ALLURE_JOB_NAME: e2e-review-qa-all
+ ALLURE_JOB_NAME: e2e-review-qa
+ ALLURE_PROJECT_PATH: $CI_PROJECT_PATH
+ ALLURE_RESULTS_GLOB: qa/tmp/allure-results/*
+ ALLURE_MERGE_REQUEST_IID: $CI_MERGE_REQUEST_IID
+ GITLAB_AUTH_TOKEN: $GITLAB_QA_MR_ALLURE_REPORT_TOKEN
+ GIT_STRATEGY: none
+ allow_failure: true
+ when: always
upload-knapsack-report:
extends:
@@ -182,13 +157,13 @@ upload-knapsack-report:
delete-test-resources:
extends:
- .bundle-base
- - .review:rules:review-qa-cleanup
+ - .rules:qa-framework-changes-or-review-scenarios
stage: post-qa
variables:
QA_TEST_RESOURCES_FILE_PATTERN: $CI_PROJECT_DIR/qa/tmp/test-resources-*.json
GITLAB_QA_ACCESS_TOKEN: $REVIEW_APPS_ROOT_TOKEN
- COLORIZED_LOGS: "true"
script:
- export GITLAB_ADDRESS="$QA_GITLAB_URL"
- bundle exec rake "test_resources:delete[$QA_TEST_RESOURCES_FILE_PATTERN]"
allow_failure: true
+ when: always
diff --git a/.gitlab/ci/review-apps/rules.gitlab-ci.yml b/.gitlab/ci/review-apps/rules.gitlab-ci.yml
new file mode 100644
index 00000000000..86e46a953af
--- /dev/null
+++ b/.gitlab/ci/review-apps/rules.gitlab-ci.yml
@@ -0,0 +1,80 @@
+# Specific specs passed
+.specific-specs: &specific-specs
+ if: $QA_TESTS != ""
+
+# No specific specs passed
+.all-specs: &all-specs
+ if: $QA_TESTS == ""
+
+# No specific specs in mr pipeline
+.all-specs-mr: &all-specs-mr
+ if: $CI_MERGE_REQUEST_IID && $QA_TESTS == ""
+ when: manual
+
+# Triggered by change pattern
+.app-changes: &app-changes
+ if: $APP_CHANGE_TRIGGER == "true"
+
+# QA framework changes present
+.qa-framework-changes: &qa-framework-changes
+ if: $QA_FRAMEWORK_CHANGES == "true"
+
+.never-when-qa-framework-changes-or-no-specific-specs:
+ - <<: *qa-framework-changes
+ when: never
+ - <<: *all-specs
+ when: never
+
+.never-when-specific-specs-always-when-qa-framework-changes:
+ - <<: *specific-specs
+ when: never
+ - *qa-framework-changes
+
+# ------------------------------------------
+# Test
+# ------------------------------------------
+.rules:qa-smoke:
+ rules:
+ # always trigger smoke suite if review pipeline got triggered by specific changes in application code
+ - <<: *app-changes
+ variables:
+ QA_TESTS: "" # unset QA_TESTS even if specific tests were inferred from stage label
+ - *qa-framework-changes
+ - if: $QA_SUITES =~ /Test::Instance::Smoke/
+
+.rules:qa-blocking:
+ rules:
+ - <<: *app-changes
+ when: never
+ - !reference [.never-when-qa-framework-changes-or-no-specific-specs]
+ - if: $QA_SUITES =~ /Test::Instance::ReviewBlocking/
+.rules:qa-blocking-parallel:
+ rules:
+ # always trigger blocking suite if review pipeline got triggered by specific changes in application code
+ - <<: *app-changes
+ variables:
+ QA_TESTS: "" # unset QA_TESTS even if specific tests were inferred from stage label
+ - !reference [.never-when-specific-specs-always-when-qa-framework-changes]
+ - if: $QA_SUITES =~ /Test::Instance::ReviewBlocking/
+
+.rules:qa-non-blocking:
+ rules:
+ - !reference [.never-when-qa-framework-changes-or-no-specific-specs]
+ - if: $QA_SUITES =~ /Test::Instance::ReviewNonBlocking/
+.rules:qa-non-blocking-parallel:
+ rules:
+ - !reference [.never-when-specific-specs-always-when-qa-framework-changes]
+ - *all-specs-mr # set full suite to manual when no specific specs passed in mr
+ - if: $QA_SUITES =~ /Test::Instance::ReviewNonBlocking/
+
+# ------------------------------------------
+# Prepare/Report
+# ------------------------------------------
+# if no framework changes or QA_SUITES do not contain review scenarios, pipeline will not have e2e test jobs
+# so we need to skip knapsack, allure and test resource deletion jobs as well
+.rules:qa-framework-changes-or-review-scenarios:
+ rules:
+ - *qa-framework-changes
+ - if: $QA_SUITES =~ /Test::Instance::Smoke/
+ - if: $QA_SUITES =~ /Test::Instance::ReviewBlocking/
+ - if: $QA_SUITES =~ /Test::Instance::ReviewNonBlocking/
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index bb6ebaa42d5..30e779936d3 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -1667,6 +1667,9 @@
################
# Review rules #
################
+.review-change-pattern: &review-change-pattern
+ APP_CHANGE_TRIGGER: "true"
+
.review:rules:start-review-app-pipeline:
rules:
- <<: *if-not-ee
@@ -1678,12 +1681,16 @@
changes: *ci-review-patterns
- <<: *if-dot-com-gitlab-org-merge-request
changes: *frontend-build-patterns
+ variables: *review-change-pattern
- <<: *if-dot-com-gitlab-org-merge-request
changes: *controllers-patterns
+ variables: *review-change-pattern
- <<: *if-dot-com-gitlab-org-merge-request
changes: *models-patterns
+ variables: *review-change-pattern
- <<: *if-dot-com-gitlab-org-merge-request
changes: *lib-gitlab-patterns
+ variables: *review-change-pattern
- <<: *if-dot-com-gitlab-org-merge-request
changes: *qa-patterns
- <<: *if-dot-com-gitlab-org-merge-request
@@ -1717,49 +1724,6 @@
rules:
- when: on_success
-.review:rules:review-qa-smoke:
- rules:
- - when: on_success
-
-# If the needed job isn't allowed to fail, we need to use `when: always` in
-# order to keep the job always running after it.
-#
-# If the needed job is allowed to fail, we need to use both
-# `when: on_success` and `when: on_failure` in order to keep
-# the job always running after it.
-# Not that if the needed job has `when: on_success` we can use `when: always`
-# for the depending job.
-#
-# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76756
-
-.review:rules:review-qa-reliable:
- rules:
- - when: on_success
-
-# Since `review-qa-reliable` isn't allowed to fail, we need to use `when: always`for `review-qa-reliable-report`.
-.review:rules:review-qa-blocking-report:
- rules:
- - when: always
-
-.review:rules:review-qa-all:
- rules:
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-patterns
- when: manual
- allow_failure: true # manual jobs needs to be allowed to fail, otherwise they block the pipeline
- - when: on_success
- allow_failure: true
-
-# Since `review-qa-all` is allowed to fail (and potentially manual), we need to use `when: on_success` and `when: on_failure` for `review-qa-all-report`.
-.review:rules:review-qa-all-report:
- rules:
- - when: on_success
- - when: on_failure
-
-.review:rules:review-qa-cleanup:
- rules:
- - when: always
-
.review:rules:review-cleanup:
rules:
- <<: *if-not-ee
diff --git a/app/assets/javascripts/user_popovers.js b/app/assets/javascripts/user_popovers.js
index c2892fb8dac..ee5d6a22fc3 100644
--- a/app/assets/javascripts/user_popovers.js
+++ b/app/assets/javascripts/user_popovers.js
@@ -46,6 +46,7 @@ const populateUserInfo = (user) => {
pronouns: userData.pronouns,
localTime: userData.local_time,
isFollowed: userData.is_followed,
+ state: userData.state,
loaded: true,
});
}
diff --git a/app/assets/javascripts/vue_shared/components/user_popover/constants.js b/app/assets/javascripts/vue_shared/components/user_popover/constants.js
index 1d49aefd297..bcbe72b4b4f 100644
--- a/app/assets/javascripts/vue_shared/components/user_popover/constants.js
+++ b/app/assets/javascripts/vue_shared/components/user_popover/constants.js
@@ -1 +1,14 @@
+import { __ } from '~/locale';
+
export const USER_POPOVER_DELAY = 200;
+export const I18N_ERROR_FOLLOW = __(
+ 'An error occurred while trying to follow this user, please try again.',
+);
+export const I18N_ERROR_UNFOLLOW = __(
+ 'An error occurred while trying to unfollow this user, please try again.',
+);
+export const I18N_USER_BLOCKED = __('User is blocked');
+export const I18N_USER_BUSY = __('Busy');
+export const I18N_USER_LEARN = __('Learn more about %{name}');
+export const I18N_USER_FOLLOW = __('Follow');
+export const I18N_USER_UNFOLLOW = __('Unfollow');
diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
index 2b9804796ae..4b39a8e45bb 100644
--- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
@@ -9,23 +9,31 @@ import {
GlButton,
GlAvatarLabeled,
} from '@gitlab/ui';
-import { __ } from '~/locale';
import { glEmojiTag } from '~/emoji';
import createFlash from '~/flash';
import { followUser, unfollowUser } from '~/rest_api';
import { isUserBusy } from '~/set_status_modal/utils';
import Tracking from '~/tracking';
-import { USER_POPOVER_DELAY } from './constants';
+import {
+ I18N_ERROR_FOLLOW,
+ I18N_ERROR_UNFOLLOW,
+ I18N_USER_BLOCKED,
+ I18N_USER_BUSY,
+ I18N_USER_LEARN,
+ I18N_USER_FOLLOW,
+ I18N_USER_UNFOLLOW,
+ USER_POPOVER_DELAY,
+} from './constants';
const MAX_SKELETON_LINES = 4;
export default {
name: 'UserPopover',
maxSkeletonLines: MAX_SKELETON_LINES,
+ I18N_USER_BLOCKED,
+ I18N_USER_BUSY,
+ I18N_USER_LEARN,
USER_POPOVER_DELAY,
- i18n: {
- busy: __('Busy'),
- },
components: {
GlIcon,
GlLink,
@@ -94,7 +102,7 @@ export default {
toggleFollowButtonText() {
if (this.toggleFollowLoading) return null;
- return this.user?.isFollowed ? __('Unfollow') : __('Follow');
+ return this.user?.isFollowed ? I18N_USER_UNFOLLOW : I18N_USER_FOLLOW;
},
toggleFollowButtonVariant() {
return this.user?.isFollowed ? 'default' : 'confirm';
@@ -102,6 +110,9 @@ export default {
hasPronouns() {
return Boolean(this.user?.pronouns?.trim());
},
+ isBlocked() {
+ return this.user?.state === 'blocked';
+ },
isBusy() {
return isUserBusy(this.availabilityStatus);
},
@@ -129,7 +140,7 @@ export default {
this.$emit('follow');
} catch (error) {
createFlash({
- message: __('An error occurred while trying to follow this user, please try again.'),
+ message: I18N_ERROR_FOLLOW,
error,
captureError: true,
});
@@ -149,7 +160,7 @@ export default {
this.$emit('unfollow');
} catch (error) {
createFlash({
- message: __('An error occurred while trying to unfollow this user, please try again.'),
+ message: I18N_ERROR_UNFOLLOW,
error,
captureError: true,
});
@@ -189,16 +200,21 @@ export default {
:label="user.name"
:sub-label="username"
>
- <gl-button
- v-if="shouldRenderToggleFollowButton"
- class="gl-mt-3 gl-align-self-start"
- :variant="toggleFollowButtonVariant"
- :loading="toggleFollowLoading"
- size="small"
- data-testid="toggle-follow-button"
- @click="toggleFollow"
- >{{ toggleFollowButtonText }}</gl-button
- >
+ <template v-if="isBlocked">
+ <span class="gl-mt-4 gl-font-style-italic">{{ $options.I18N_USER_BLOCKED }}</span>
+ </template>
+ <template v-else>
+ <gl-button
+ v-if="shouldRenderToggleFollowButton"
+ class="gl-mt-3 gl-align-self-start"
+ :variant="toggleFollowButtonVariant"
+ :loading="toggleFollowLoading"
+ size="small"
+ data-testid="toggle-follow-button"
+ @click="toggleFollow"
+ >{{ toggleFollowButtonText }}</gl-button
+ >
+ </template>
<template #meta>
<span
@@ -208,7 +224,7 @@ export default {
>({{ user.pronouns }})</span
>
<span v-if="isBusy" class="gl-text-gray-500 gl-font-sm gl-font-weight-normal gl-p-1"
- >({{ $options.i18n.busy }})</span
+ >({{ $options.I18N_USER_BUSY }})</span
>
</template>
</gl-avatar-labeled>
@@ -223,39 +239,41 @@ export default {
/>
</template>
<template v-else>
- <div class="gl-text-gray-500">
- <div v-if="user.bio" class="gl-display-flex gl-mb-2">
- <gl-icon name="profile" class="gl-flex-shrink-0" />
- <span ref="bio" class="gl-ml-2">{{ user.bio }}</span>
+ <template v-if="!isBlocked">
+ <div class="gl-text-gray-500">
+ <div v-if="user.bio" class="gl-display-flex gl-mb-2">
+ <gl-icon name="profile" class="gl-flex-shrink-0" />
+ <span ref="bio" class="gl-ml-2">{{ user.bio }}</span>
+ </div>
+ <div v-if="user.workInformation" class="gl-display-flex gl-mb-2">
+ <gl-icon name="work" class="gl-flex-shrink-0" />
+ <span ref="workInformation" class="gl-ml-2">{{ user.workInformation }}</span>
+ </div>
+ <div v-if="user.location" class="gl-display-flex gl-mb-2">
+ <gl-icon name="location" class="gl-flex-shrink-0" />
+ <span class="gl-ml-2">{{ user.location }}</span>
+ </div>
+ <div
+ v-if="user.localTime && !user.bot"
+ class="gl-display-flex gl-mb-2"
+ data-testid="user-popover-local-time"
+ >
+ <gl-icon name="clock" class="gl-flex-shrink-0" />
+ <span class="gl-ml-2">{{ user.localTime }}</span>
+ </div>
</div>
- <div v-if="user.workInformation" class="gl-display-flex gl-mb-2">
- <gl-icon name="work" class="gl-flex-shrink-0" />
- <span ref="workInformation" class="gl-ml-2">{{ user.workInformation }}</span>
+ <div v-if="statusHtml" class="gl-mb-2" data-testid="user-popover-status">
+ <span v-safe-html:[$options.safeHtmlConfig]="statusHtml"></span>
</div>
- <div v-if="user.location" class="gl-display-flex gl-mb-2">
- <gl-icon name="location" class="gl-flex-shrink-0" />
- <span class="gl-ml-2">{{ user.location }}</span>
+ <div v-if="user.bot && user.websiteUrl" class="gl-text-blue-500">
+ <gl-icon name="question" />
+ <gl-link data-testid="user-popover-bot-docs-link" :href="user.websiteUrl">
+ <gl-sprintf :message="$options.I18N_USER_LEARN">
+ <template #name>{{ user.name }}</template>
+ </gl-sprintf>
+ </gl-link>
</div>
- <div
- v-if="user.localTime && !user.bot"
- class="gl-display-flex gl-mb-2"
- data-testid="user-popover-local-time"
- >
- <gl-icon name="clock" class="gl-flex-shrink-0" />
- <span class="gl-ml-2">{{ user.localTime }}</span>
- </div>
- </div>
- <div v-if="statusHtml" class="gl-mb-2" data-testid="user-popover-status">
- <span v-safe-html:[$options.safeHtmlConfig]="statusHtml"></span>
- </div>
- <div v-if="user.bot && user.websiteUrl" class="gl-text-blue-500">
- <gl-icon name="question" />
- <gl-link data-testid="user-popover-bot-docs-link" :href="user.websiteUrl">
- <gl-sprintf :message="__('Learn more about %{username}')">
- <template #username>{{ user.name }}</template>
- </gl-sprintf>
- </gl-link>
- </div>
+ </template>
</template>
</div>
</gl-popover>
diff --git a/app/views/notify/repository_push_email.html.haml b/app/views/notify/repository_push_email.html.haml
index 93806e6de8e..ee219914513 100644
--- a/app/views/notify/repository_push_email.html.haml
+++ b/app/views/notify/repository_push_email.html.haml
@@ -2,29 +2,30 @@
= stylesheet_link_tag 'mailers/highlighted_diff_email'
%h3
- #{@message.author_name} #{@message.action_name} #{@message.ref_type} #{@message.ref_name}
- at #{link_to(@message.project_name_with_namespace, project_url(@message.project))}
+ = s_('Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}').html_safe % {author_name: @message.author_name, action_name: @message.action_name, ref_type: @message.ref_type, ref_name: @message.ref_name, project_link: link_to(@message.project_name_with_namespace, strip_tags(project_url(@message.project)))}
- if @message.compare
- if @message.reverse_compare?
%p
- %strong WARNING:
- The push did not contain any new commits, but force pushed to delete the commits and changes below.
+ %strong
+ = _('WARNING:')
+ = s_('Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below.')
%h4
- = @message.reverse_compare? ? "Deleted commits:" : "Commits:"
+ = @message.reverse_compare? ? _("Deleted commits:") : _("Commits:")
%ul
- @message.commits.each do |commit|
%li
%strong= link_to(commit.short_id, project_commit_url(@message.project, commit))
%div
- %span by #{commit.author_name}
- %i at #{commit.committed_date.to_s(:iso8601)}
+ = html_escape(s_('Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}')) % {committed_by_start: '<span>'.html_safe, author_name: commit.author_name, committed_by_end: '</span>'.html_safe, committed_at_start: '<i>'.html_safe, committed_date: commit.committed_date.to_s(:iso8601), committed_at_end: '</i>'.html_safe}
%pre.commit-message
= commit.safe_message
- %h4 #{pluralize @message.diffs_count, "changed file"}:
+ %h4
+ - changed_files = n_('%d changed file', '%d changed files', @message.diffs_count) % @message.diffs_count
+ = s_('Notify|%{changed_files}:') % {changed_files: changed_files}
%ul
- @message.diffs.each do |diff_file|
@@ -47,9 +48,11 @@
- unless @message.disable_diffs?
- if @message.compare_timeout
- %h5 The diff was not included because it is too large.
+ %h5
+ = s_('Notify|The diff was not included because it is too large.')
- else
- %h4 Changes:
+ %h4
+ = _('Changes:')
- @message.diffs.each do |diff_file|
- file_hash = hexdigest(diff_file.file_path)
%li{ id: file_hash }
@@ -57,7 +60,7 @@
- if diff_file.deleted_file?
%strong<
= diff_file.old_path
- deleted
+ = s_('deleted')
- elsif diff_file.renamed_file?
%strong<
= diff_file.old_path
@@ -68,7 +71,7 @@
%strong<
= diff_file.new_path
- if diff_file.too_large?
- The diff for this file was not included because it is too large.
+ = s_('Notify|The diff for this file was not included because it is too large.')
- else
%hr
- blob = diff_file.blob
@@ -76,5 +79,5 @@
%table.code.white
= render partial: "projects/diffs/email_line", collection: diff_file.highlighted_diff_lines, as: :line, locals: { diff_file: diff_file }
- else
- No preview for this file type
+ = s_('Notify|No preview for this file type')
%br
diff --git a/lib/gitlab/email/message/repository_push.rb b/lib/gitlab/email/message/repository_push.rb
index d55cf3202a6..293aa3b53bf 100644
--- a/lib/gitlab/email/message/repository_push.rb
+++ b/lib/gitlab/email/message/repository_push.rb
@@ -79,11 +79,11 @@ module Gitlab
@action_name ||=
case @action
when :create
- 'pushed new'
+ s_('Notify|pushed new')
when :delete
- 'deleted'
+ s_('Notify|deleted')
else
- 'pushed to'
+ s_('Notify|pushed to')
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 6eb58c5e575..e432108c84d 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -7723,6 +7723,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changes:"
+msgstr ""
+
msgid "Changing any setting here requires an application restart"
msgstr ""
@@ -9620,6 +9623,9 @@ msgstr ""
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
msgstr ""
+msgid "Commits:"
+msgstr ""
+
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
@@ -12717,6 +12723,9 @@ msgstr ""
msgid "Deleted chat nickname: %{chat_name}!"
msgstr ""
+msgid "Deleted commits:"
+msgstr ""
+
msgid "Deleted projects cannot be restored!"
msgstr ""
@@ -23423,7 +23432,7 @@ msgstr ""
msgid "Learn more"
msgstr ""
-msgid "Learn more about %{username}"
+msgid "Learn more about %{name}"
msgstr ""
msgid "Learn more about Auto DevOps"
@@ -27039,12 +27048,21 @@ msgstr ""
msgid "Notify|%{author_link}'s issue %{issue_reference_link} is due soon."
msgstr ""
+msgid "Notify|%{author_name} %{action_name} %{ref_type} %{ref_name} at %{project_link}"
+msgstr ""
+
+msgid "Notify|%{changed_files}:"
+msgstr ""
+
msgid "Notify|%{commit_link} in %{mr_link}"
msgstr ""
msgid "Notify|%{commits_text} from branch `%{target_branch}`"
msgstr ""
+msgid "Notify|%{committed_by_start} by %{author_name} %{committed_by_end} %{committed_at_start} at %{committed_date} %{committed_at_end}"
+msgstr ""
+
msgid "Notify|%{invite_email}, now known as %{user_name}, has accepted your invitation to join the %{target_name} %{target_model_name}."
msgstr ""
@@ -27171,6 +27189,9 @@ msgstr ""
msgid "Notify|New issue: %{project_issue_url}"
msgstr ""
+msgid "Notify|No preview for this file type"
+msgstr ""
+
msgid "Notify|Pipeline %{pipeline_link} triggered by"
msgstr ""
@@ -27180,6 +27201,15 @@ msgstr ""
msgid "Notify|The Auto DevOps pipeline failed for pipeline %{pipeline_link} and has been disabled for %{project_link}. In order to use the Auto DevOps pipeline with your project, please review the %{supported_langs_link}, adjust your project accordingly, and turn on the Auto DevOps pipeline within your %{settings_link}."
msgstr ""
+msgid "Notify|The diff for this file was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The diff was not included because it is too large."
+msgstr ""
+
+msgid "Notify|The push did not contain any new commits, but force pushed to delete the commits and changes below."
+msgstr ""
+
msgid "Notify|This issue is due on: %{issue_due_date}"
msgstr ""
@@ -27204,6 +27234,15 @@ msgstr ""
msgid "Notify|currently supported languages"
msgstr ""
+msgid "Notify|deleted"
+msgstr ""
+
+msgid "Notify|pushed new"
+msgstr ""
+
+msgid "Notify|pushed to"
+msgstr ""
+
msgid "Notify|successfully completed %{jobs} in %{stages}."
msgstr ""
@@ -43051,6 +43090,9 @@ msgstr ""
msgid "User identity was successfully updated."
msgstr ""
+msgid "User is blocked"
+msgstr ""
+
msgid "User is not allowed to resolve thread"
msgstr ""
@@ -44194,6 +44236,9 @@ msgstr ""
msgid "Vulnerability|View training"
msgstr ""
+msgid "WARNING:"
+msgstr ""
+
msgid "WARNING: This snippet contains hidden files which might be used to mask malicious behavior. Exercise caution if cloning and executing code from this snippet."
msgstr ""
diff --git a/qa/qa/scenario/test/instance/blocking.rb b/qa/qa/scenario/test/instance/blocking.rb
deleted file mode 100644
index 0f03100f3d5..00000000000
--- a/qa/qa/scenario/test/instance/blocking.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Scenario
- module Test
- module Instance
- class Blocking < Template
- include Bootable
- include SharedAttributes
-
- tags :reliable, :smoke
- end
- end
- end
- end
-end
diff --git a/qa/qa/scenario/test/instance/review_blocking.rb b/qa/qa/scenario/test/instance/review_blocking.rb
new file mode 100644
index 00000000000..cb1b6c9cf10
--- /dev/null
+++ b/qa/qa/scenario/test/instance/review_blocking.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Instance
+ class ReviewBlocking < All
+ tags :reliable,
+ :sanity_feature_flags,
+ :"~orchestrated",
+ :"~skip_signup_disabled"
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/scenario/test/instance/review_non_blocking.rb b/qa/qa/scenario/test/instance/review_non_blocking.rb
new file mode 100644
index 00000000000..e295171eb0b
--- /dev/null
+++ b/qa/qa/scenario/test/instance/review_non_blocking.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Instance
+ class ReviewNonBlocking < All
+ tags :"~reliable",
+ :"~smoke",
+ :"~skip_signup_disabled",
+ *Specs::Runner::DEFAULT_SKIPPED_TAGS.map { |tag| :"~#{tag}" }
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
index ed271533f87..7e4a391c390 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
@@ -64,7 +64,7 @@ module QA
it(
'comments on an issue with an attachment',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347946',
- except: { job: 'review-qa-smoke' }
+ except: { job: 'review-qa-*' }
) do
Page::Project::Issue::Show.perform do |show|
show.comment('See attached image for scale', attachment: file_to_attach)
diff --git a/qa/qa/tools/ci/non_empty_suites.rb b/qa/qa/tools/ci/non_empty_suites.rb
index cdf06da6763..687c11a3e62 100644
--- a/qa/qa/tools/ci/non_empty_suites.rb
+++ b/qa/qa/tools/ci/non_empty_suites.rb
@@ -15,7 +15,8 @@ module QA
{ klass: "Test::Instance::All" },
{ klass: "Test::Instance::Smoke" },
{ klass: "Test::Instance::Reliable" },
- { klass: "Test::Instance::Blocking" },
+ { klass: "Test::Instance::ReviewBlocking" },
+ { klass: "Test::Instance::ReviewNonBlocking" },
{ klass: "Test::Instance::CloudActivation" },
{ klass: "Test::Instance::Integrations" },
{ klass: "Test::Instance::Jira" },
diff --git a/scripts/generate-e2e-pipeline b/scripts/generate-e2e-pipeline
index 8f5046ef32c..f541ae6665c 100755
--- a/scripts/generate-e2e-pipeline
+++ b/scripts/generate-e2e-pipeline
@@ -21,6 +21,7 @@ fi
variables=$(cat <<YML
variables:
GITLAB_VERSION: "$(cat VERSION)"
+ COLORIZED_LOGS: "true"
QA_TESTS: "$QA_TESTS"
QA_FEATURE_FLAGS: "${QA_FEATURE_FLAGS}"
QA_FRAMEWORK_CHANGES: "${QA_FRAMEWORK_CHANGES:-false}"
@@ -29,13 +30,10 @@ YML
)
echo "Using .gitlab/ci/review-apps/main.gitlab-ci.yml and .gitlab/ci/package-and-test/main.gitlab-ci.yml"
-
cp .gitlab/ci/review-apps/main.gitlab-ci.yml "$REVIEW_PIPELINE_YML"
echo "$variables" >>"$REVIEW_PIPELINE_YML"
-echo "Successfully generated review-app pipeline with following variables section:"
-echo "$variables"
-
cp .gitlab/ci/package-and-test/main.gitlab-ci.yml "$OMNIBUS_PIPELINE_YML"
echo "$variables" >>"$OMNIBUS_PIPELINE_YML"
-echo "Successfully generated package-and-test pipeline with following variables section:"
+
+echo "Successfully generated review-app and package-and-test pipeline with following variables section:"
echo "$variables"
diff --git a/spec/fast_spec_helper.rb b/spec/fast_spec_helper.rb
index 722c1e66f34..db4d9125e6e 100644
--- a/spec/fast_spec_helper.rb
+++ b/spec/fast_spec_helper.rb
@@ -32,13 +32,6 @@ end
ActiveSupport::XmlMini.backend = 'Nokogiri'
RSpec.configure do |config|
- unless ENV['CI']
- # Allow running `:focus` examples locally,
- # falling back to all tests when there is no `:focus` example.
- config.filter_run focus: true
- config.run_all_when_everything_filtered = true
- end
-
# Makes diffs show entire non-truncated values.
config.before(:each, unlimited_max_formatted_output_length: true) do |_example|
config.expect_with :rspec do |c|
diff --git a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
index ce9b7c5f061..6d48000beb0 100644
--- a/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
+++ b/spec/frontend/vue_shared/components/user_popover/user_popover_spec.js
@@ -1,8 +1,15 @@
import { GlSkeletonLoader, GlIcon } from '@gitlab/ui';
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
+import { sprintf } from '~/locale';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { AVAILABILITY_STATUS } from '~/set_status_modal/constants';
import UserPopover from '~/vue_shared/components/user_popover/user_popover.vue';
+import {
+ I18N_USER_BLOCKED,
+ I18N_USER_LEARN,
+ I18N_USER_FOLLOW,
+ I18N_USER_UNFOLLOW,
+} from '~/vue_shared/components/user_popover/constants';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import { followUser, unfollowUser } from '~/api/user_api';
@@ -310,7 +317,9 @@ describe('User Popover Component', () => {
const securityBotDocsLink = findSecurityBotDocsLink();
expect(securityBotDocsLink.exists()).toBe(true);
expect(securityBotDocsLink.attributes('href')).toBe(SECURITY_BOT_USER.websiteUrl);
- expect(securityBotDocsLink.text()).toBe('Learn more about GitLab Security Bot');
+ expect(securityBotDocsLink.text()).toBe(
+ sprintf(I18N_USER_LEARN, { name: SECURITY_BOT_USER.name }),
+ );
});
it("does not show a link to the bot's documentation if there is no website_url", () => {
@@ -320,9 +329,10 @@ describe('User Popover Component', () => {
});
it("doesn't escape user's name", () => {
- createWrapper({ user: { ...SECURITY_BOT_USER, name: '%<>\';"' } });
+ const name = '%<>\';"';
+ createWrapper({ user: { ...SECURITY_BOT_USER, name } });
const securityBotDocsLink = findSecurityBotDocsLink();
- expect(securityBotDocsLink.text()).toBe('Learn more about %<>\';"');
+ expect(securityBotDocsLink.text()).toBe(sprintf(I18N_USER_LEARN, { name }, false));
});
it('does not display local time', () => {
@@ -336,7 +346,7 @@ describe('User Popover Component', () => {
beforeEach(() => createWrapper());
it('renders the Follow button with the correct variant', () => {
- expect(findToggleFollowButton().text()).toBe('Follow');
+ expect(findToggleFollowButton().text()).toBe(I18N_USER_FOLLOW);
expect(findToggleFollowButton().props('variant')).toBe('confirm');
});
@@ -387,7 +397,7 @@ describe('User Popover Component', () => {
beforeEach(() => createWrapper({ user: { ...DEFAULT_PROPS.user, isFollowed: true } }));
it('renders the Unfollow button with the correct variant', () => {
- expect(findToggleFollowButton().text()).toBe('Unfollow');
+ expect(findToggleFollowButton().text()).toBe(I18N_USER_UNFOLLOW);
expect(findToggleFollowButton().props('variant')).toBe('default');
});
@@ -441,6 +451,25 @@ describe('User Popover Component', () => {
});
});
+ describe('when the user is blocked', () => {
+ const bio = 'My super interesting bio';
+ const status = 'My status';
+ beforeEach(() =>
+ createWrapper({
+ user: { ...DEFAULT_PROPS.user, state: 'blocked', bio, status: { message_html: status } },
+ }),
+ );
+
+ it('renders warning', () => {
+ expect(wrapper.text()).toContain(I18N_USER_BLOCKED);
+ });
+
+ it("doesn't show other information", () => {
+ expect(wrapper.text()).not.toContain(bio);
+ expect(wrapper.text()).not.toContain(status);
+ });
+ });
+
describe('when API does not support `isFollowed`', () => {
beforeEach(() => {
const user = {
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 18820eefe31..a40f19ecf7c 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -36,6 +36,7 @@ require 'rspec-parameterized'
require 'shoulda/matchers'
require 'test_prof/recipes/rspec/let_it_be'
require 'test_prof/factory_default'
+require 'test_prof/factory_prof/nate_heckler'
require 'parslet/rig/rspec'
rspec_profiling_is_configured =
@@ -109,11 +110,6 @@ RSpec.configure do |config|
warn `curl -s -o log/goroutines.log http://localhost:9236/debug/pprof/goroutine?debug=2`
end
end
- else
- # Allow running `:focus` examples locally,
- # falling back to all tests when there is no `:focus` example.
- config.filter_run focus: true
- config.run_all_when_everything_filtered = true
end
# Attempt to troubleshoot https://gitlab.com/gitlab-org/gitlab/-/issues/351531
diff --git a/spec/support/rspec.rb b/spec/support/rspec.rb
index 2d37501f7c6..6795d2f6d2a 100644
--- a/spec/support/rspec.rb
+++ b/spec/support/rspec.rb
@@ -14,6 +14,13 @@ RSpec.configure do |config|
# Re-run failures locally with `--only-failures`
config.example_status_persistence_file_path = ENV.fetch('RSPEC_LAST_RUN_RESULTS_FILE', './spec/examples.txt')
+ unless ENV['CI']
+ # Allow running `:focus` examples locally,
+ # falling back to all tests when there is no `:focus` example.
+ config.filter_run focus: true
+ config.run_all_when_everything_filtered = true
+ end
+
config.mock_with :rspec do |mocks|
mocks.verify_doubled_constant_names = true
end