Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-06-10 09:11:12 +00:00
parent df9e161ad4
commit f42c4be1c0
34 changed files with 348 additions and 259 deletions

View File

@ -2,8 +2,6 @@ import { DEFAULT_PER_PAGE } from '~/api';
import axios from '../lib/utils/axios_utils';
import { buildApiUrl } from './api_utils';
export * from './alert_management_alerts_api';
const PROJECTS_PATH = '/api/:version/projects.json';
const PROJECT_IMPORT_MEMBERS_PATH = '/api/:version/projects/:id/import_project_members/:project_id';
const PROJECT_REPOSITORY_SIZE_PATH = '/api/:version/projects/:id/repository_size';

View File

@ -1,4 +1,5 @@
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import { throttle } from 'lodash';
import { isLoggedIn } from '~/lib/utils/common_utils';
import DesignOverlay from './design_overlay.vue';
@ -10,6 +11,7 @@ export default {
components: {
DesignImage,
DesignOverlay,
GlLoadingIcon,
},
props: {
image: {
@ -40,6 +42,10 @@ export default {
type: Boolean,
required: true,
},
isLoading: {
type: Boolean,
required: true,
},
},
data() {
return {
@ -299,7 +305,12 @@ export default {
@touchend="onPresentationMouseup"
@touchcancel="onPresentationMouseup"
>
<div class="gl-h-full gl-w-full gl-display-flex gl-align-items-center gl-relative">
<gl-loading-icon
v-if="isLoading"
size="xl"
class="gl-display-flex gl-h-full gl-align-items-center"
/>
<div v-else class="gl-h-full gl-w-full gl-display-flex gl-align-items-center gl-relative">
<design-image
v-if="image"
:image="image"

View File

@ -1,5 +1,5 @@
<script>
import { GlCollapse, GlButton, GlPopover } from '@gitlab/ui';
import { GlCollapse, GlButton, GlPopover, GlSkeletonLoader } from '@gitlab/ui';
import { getCookie, setCookie, parseBoolean, isLoggedIn } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
@ -20,6 +20,7 @@ export default {
GlCollapse,
GlButton,
GlPopover,
GlSkeletonLoader,
DesignTodoButton,
},
mixins: [glFeatureFlagsMixin()],
@ -50,6 +51,10 @@ export default {
type: String,
required: true,
},
isLoading: {
type: Boolean,
required: true,
},
},
data() {
return {
@ -65,11 +70,11 @@ export default {
issue() {
return {
...this.design.issue,
webPath: this.design.issue.webPath.substr(1),
webPath: this.design.issue?.webPath.substr(1),
};
},
discussionParticipants() {
return extractParticipants(this.issue.participants.nodes);
return extractParticipants(this.issue.participants?.nodes || []);
},
resolvedDiscussions() {
return this.discussions.filter((discussion) => discussion.resolved);
@ -142,91 +147,94 @@ export default {
:show-participant-label="false"
class="gl-mb-4"
/>
<h2
v-if="isLoggedIn && unresolvedDiscussions.length === 0"
class="new-discussion-disclaimer gl-font-base gl-m-0 gl-mb-4"
data-testid="new-discussion-disclaimer"
>
{{ s__("DesignManagement|Click the image where you'd like to start a new discussion") }}
</h2>
<design-note-signed-out
v-if="!isLoggedIn"
class="gl-mb-4"
:register-path="registerPath"
:sign-in-path="signInPath"
:is-add-discussion="true"
/>
<design-discussion
v-for="discussion in unresolvedDiscussions"
:key="discussion.id"
:discussion="discussion"
:design-id="$route.params.id"
:noteable-id="design.id"
:markdown-preview-path="markdownPreviewPath"
:register-path="registerPath"
:sign-in-path="signInPath"
:resolved-discussions-expanded="resolvedDiscussionsExpanded"
:discussion-with-open-form="discussionWithOpenForm"
data-testid="unresolved-discussion"
@create-note-error="$emit('onDesignDiscussionError', $event)"
@update-note-error="$emit('updateNoteError', $event)"
@resolve-discussion-error="$emit('resolveDiscussionError', $event)"
@click.native.stop="updateActiveDiscussion(discussion.notes[0].id)"
@open-form="updateDiscussionWithOpenForm"
/>
<template v-if="resolvedDiscussions.length > 0">
<gl-button
id="resolved-comments"
ref="resolvedComments"
data-testid="resolved-comments"
:icon="resolvedCommentsToggleIcon"
variant="link"
class="link-inherit-color gl-text-body gl-text-decoration-none gl-font-weight-bold gl-mb-4"
@click="$emit('toggleResolvedComments')"
>{{ $options.resolveCommentsToggleText }} ({{ resolvedDiscussions.length }})
</gl-button>
<gl-popover
v-if="!isResolvedCommentsPopoverHidden"
:show="!isResolvedCommentsPopoverHidden"
target="resolved-comments"
container="popovercontainer"
placement="top"
:title="s__('DesignManagement|Resolved Comments')"
<gl-skeleton-loader v-if="isLoading" />
<template v-else>
<h2
v-if="isLoggedIn && unresolvedDiscussions.length === 0"
class="new-discussion-disclaimer gl-font-base gl-m-0 gl-mb-4"
data-testid="new-discussion-disclaimer"
>
<p>
{{
s__(
'DesignManagement|Comments you resolve can be viewed and unresolved by going to the "Resolved Comments" section below',
)
}}
</p>
<a
href="https://docs.gitlab.com/ee/user/project/issues/design_management.html#resolve-design-threads"
rel="noopener noreferrer"
target="_blank"
>{{ s__('DesignManagement|Learn more about resolving comments') }}</a
{{ s__("DesignManagement|Click the image where you'd like to start a new discussion") }}
</h2>
<design-note-signed-out
v-if="!isLoggedIn"
class="gl-mb-4"
:register-path="registerPath"
:sign-in-path="signInPath"
:is-add-discussion="true"
/>
<design-discussion
v-for="discussion in unresolvedDiscussions"
:key="discussion.id"
:discussion="discussion"
:design-id="$route.params.id"
:noteable-id="design.id"
:markdown-preview-path="markdownPreviewPath"
:register-path="registerPath"
:sign-in-path="signInPath"
:resolved-discussions-expanded="resolvedDiscussionsExpanded"
:discussion-with-open-form="discussionWithOpenForm"
data-testid="unresolved-discussion"
@create-note-error="$emit('onDesignDiscussionError', $event)"
@update-note-error="$emit('updateNoteError', $event)"
@resolve-discussion-error="$emit('resolveDiscussionError', $event)"
@click.native.stop="updateActiveDiscussion(discussion.notes[0].id)"
@open-form="updateDiscussionWithOpenForm"
/>
<template v-if="resolvedDiscussions.length > 0">
<gl-button
id="resolved-comments"
ref="resolvedComments"
data-testid="resolved-comments"
:icon="resolvedCommentsToggleIcon"
variant="link"
class="link-inherit-color gl-text-body gl-text-decoration-none gl-font-weight-bold gl-mb-4"
@click="$emit('toggleResolvedComments')"
>{{ $options.resolveCommentsToggleText }} ({{ resolvedDiscussions.length }})
</gl-button>
<gl-popover
v-if="!isResolvedCommentsPopoverHidden"
:show="!isResolvedCommentsPopoverHidden"
target="resolved-comments"
container="popovercontainer"
placement="top"
:title="s__('DesignManagement|Resolved Comments')"
>
</gl-popover>
<gl-collapse :visible="resolvedDiscussionsExpanded" class="gl-mt-3">
<design-discussion
v-for="discussion in resolvedDiscussions"
:key="discussion.id"
:discussion="discussion"
:design-id="$route.params.id"
:noteable-id="design.id"
:markdown-preview-path="markdownPreviewPath"
:register-path="registerPath"
:sign-in-path="signInPath"
:resolved-discussions-expanded="resolvedDiscussionsExpanded"
:discussion-with-open-form="discussionWithOpenForm"
data-testid="resolved-discussion"
@error="$emit('onDesignDiscussionError', $event)"
@updateNoteError="$emit('updateNoteError', $event)"
@open-form="updateDiscussionWithOpenForm"
@click.native.stop="updateActiveDiscussion(discussion.notes[0].id)"
/>
</gl-collapse>
<p>
{{
s__(
'DesignManagement|Comments you resolve can be viewed and unresolved by going to the "Resolved Comments" section below',
)
}}
</p>
<a
href="https://docs.gitlab.com/ee/user/project/issues/design_management.html#resolve-design-threads"
rel="noopener noreferrer"
target="_blank"
>{{ s__('DesignManagement|Learn more about resolving comments') }}</a
>
</gl-popover>
<gl-collapse :visible="resolvedDiscussionsExpanded" class="gl-mt-3">
<design-discussion
v-for="discussion in resolvedDiscussions"
:key="discussion.id"
:discussion="discussion"
:design-id="$route.params.id"
:noteable-id="design.id"
:markdown-preview-path="markdownPreviewPath"
:register-path="registerPath"
:sign-in-path="signInPath"
:resolved-discussions-expanded="resolvedDiscussionsExpanded"
:discussion-with-open-form="discussionWithOpenForm"
data-testid="resolved-discussion"
@error="$emit('onDesignDiscussionError', $event)"
@updateNoteError="$emit('updateNoteError', $event)"
@open-form="updateDiscussionWithOpenForm"
@click.native.stop="updateActiveDiscussion(discussion.notes[0].id)"
/>
</gl-collapse>
</template>
<slot name="reply-form"></slot>
</template>
<slot name="reply-form"></slot>
</div>
</template>

View File

@ -1,5 +1,5 @@
<script>
import { GlButton, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { GlButton, GlIcon, GlTooltipDirective, GlSkeletonLoader } from '@gitlab/ui';
import permissionsQuery from 'shared_queries/design_management/design_permissions.query.graphql';
import { __, s__, sprintf } from '~/locale';
import timeagoMixin from '~/vue_shared/mixins/timeago';
@ -14,6 +14,7 @@ export default {
components: {
GlButton,
GlIcon,
GlSkeletonLoader,
DesignNavigation,
DeleteButton,
},
@ -61,6 +62,10 @@ export default {
type: String,
required: true,
},
isLoading: {
type: Boolean,
required: true,
},
},
data() {
return {
@ -113,7 +118,8 @@ export default {
<gl-icon name="close" />
</router-link>
<div class="gl-overflow-hidden gl-display-flex gl-align-items-center">
<h2 class="gl-m-0 str-truncated-100 gl-font-base">{{ filename }}</h2>
<gl-skeleton-loader v-if="isLoading" :lines="1" />
<h2 v-else class="gl-m-0 str-truncated-100 gl-font-base">{{ filename }}</h2>
<small v-if="updatedAt" class="gl-text-gray-500">{{ updatedText }}</small>
</div>
</div>

View File

@ -1,5 +1,5 @@
<script>
import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
import { GlAlert } from '@gitlab/ui';
import { isNull } from 'lodash';
import Mousetrap from 'mousetrap';
import { ApolloMutation } from 'vue-apollo';
@ -56,7 +56,6 @@ export default {
DesignScaler,
DesignDestroyer,
Toolbar,
GlLoadingIcon,
GlAlert,
DesignSidebar,
},
@ -118,10 +117,8 @@ export default {
},
},
computed: {
isFirstLoading() {
// We only want to show spinner on initial design load (when opened from a deep link to design)
// If we already have cached a design, loading shouldn't be indicated to user
return this.$apollo.queries.design.loading && !this.design.filename;
isLoading() {
return this.$apollo.queries.design.loading;
},
discussions() {
if (!this.design.discussions) {
@ -343,88 +340,88 @@ export default {
<div
class="design-detail js-design-detail fixed-top gl-w-full gl-bottom-0 gl-display-flex gl-justify-content-center gl-flex-direction-column gl-lg-flex-direction-row"
>
<gl-loading-icon v-if="isFirstLoading" size="xl" class="gl-align-self-center" />
<template v-else>
<div
class="gl-display-flex gl-overflow-hidden gl-flex-grow-1 gl-flex-direction-column gl-relative"
<div
class="gl-display-flex gl-overflow-hidden gl-flex-grow-1 gl-flex-direction-column gl-relative"
>
<design-destroyer
:filenames="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ [
design.filename,
] /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
:project-path="projectPath"
:iid="issueIid"
@done="$router.push({ name: $options.DESIGNS_ROUTE_NAME })"
@error="onDesignDeleteError"
>
<design-destroyer
:filenames="/* eslint-disable @gitlab/vue-no-new-non-primitive-in-template */ [
design.filename,
] /* eslint-enable @gitlab/vue-no-new-non-primitive-in-template */"
:project-path="projectPath"
:iid="issueIid"
@done="$router.push({ name: $options.DESIGNS_ROUTE_NAME })"
@error="onDesignDeleteError"
>
<template #default="{ mutate, loading }">
<toolbar
:id="id"
:is-deleting="loading"
:is-latest-version="isLatestVersion"
v-bind="design"
@delete="mutate"
/>
</template>
</design-destroyer>
<template #default="{ mutate, loading }">
<toolbar
:id="id"
:is-deleting="loading"
:is-latest-version="isLatestVersion"
:is-loading="isLoading"
v-bind="design"
@delete="mutate"
/>
</template>
</design-destroyer>
<div v-if="errorMessage" class="gl-p-5">
<gl-alert variant="danger" @dismiss="errorMessage = null">
{{ errorMessage }}
</gl-alert>
</div>
<design-presentation
:image="design.image"
:image-name="design.filename"
:discussions="discussions"
:is-annotating="isAnnotating"
:scale="scale"
:resolved-discussions-expanded="resolvedDiscussionsExpanded"
@openCommentForm="openCommentForm"
@closeCommentForm="closeCommentForm"
@moveNote="onMoveNote"
@setMaxScale="setMaxScale"
/>
<div
class="design-scaler-wrapper gl-absolute gl-mb-6 gl-display-flex gl-justify-content-center gl-align-items-center"
>
<design-scaler :max-scale="maxScale" @scale="scale = $event" />
</div>
<div v-if="errorMessage" class="gl-p-5">
<gl-alert variant="danger" @dismiss="errorMessage = null">
{{ errorMessage }}
</gl-alert>
</div>
<design-sidebar
:design="design"
<design-presentation
:image="design.image"
:image-name="design.filename"
:discussions="discussions"
:is-annotating="isAnnotating"
:scale="scale"
:resolved-discussions-expanded="resolvedDiscussionsExpanded"
:markdown-preview-path="markdownPreviewPath"
@onDesignDiscussionError="onDesignDiscussionError"
@onCreateImageDiffNoteError="onCreateImageDiffNoteError"
@updateNoteError="onUpdateNoteError"
@resolveDiscussionError="onResolveDiscussionError"
@toggleResolvedComments="toggleResolvedComments"
@todoError="onTodoError"
:is-loading="isLoading"
@openCommentForm="openCommentForm"
@closeCommentForm="closeCommentForm"
@moveNote="onMoveNote"
@setMaxScale="setMaxScale"
/>
<div
class="design-scaler-wrapper gl-absolute gl-mb-6 gl-display-flex gl-justify-content-center gl-align-items-center"
>
<template #reply-form>
<apollo-mutation
v-if="isAnnotating"
#default="{ mutate, loading }"
:mutation="$options.createImageDiffNoteMutation"
:variables="{
input: mutationPayload,
}"
:update="addImageDiffNoteToStore"
@done="closeCommentForm"
@error="onCreateImageDiffNoteError"
>
<design-reply-form
ref="newDiscussionForm"
v-model="comment"
:is-saving="loading"
:markdown-preview-path="markdownPreviewPath"
@submit-form="mutate"
@cancel-form="closeCommentForm"
/> </apollo-mutation
></template>
</design-sidebar>
</template>
<design-scaler :max-scale="maxScale" @scale="scale = $event" />
</div>
</div>
<design-sidebar
:design="design"
:resolved-discussions-expanded="resolvedDiscussionsExpanded"
:markdown-preview-path="markdownPreviewPath"
:is-loading="isLoading"
@onDesignDiscussionError="onDesignDiscussionError"
@onCreateImageDiffNoteError="onCreateImageDiffNoteError"
@updateNoteError="onUpdateNoteError"
@resolveDiscussionError="onResolveDiscussionError"
@toggleResolvedComments="toggleResolvedComments"
@todoError="onTodoError"
>
<template #reply-form>
<apollo-mutation
v-if="isAnnotating"
#default="{ mutate, loading }"
:mutation="$options.createImageDiffNoteMutation"
:variables="{
input: mutationPayload,
}"
:update="addImageDiffNoteToStore"
@done="closeCommentForm"
@error="onCreateImageDiffNoteError"
>
<design-reply-form
ref="newDiscussionForm"
v-model="comment"
:is-saving="loading"
:markdown-preview-path="markdownPreviewPath"
@submit-form="mutate"
@cancel-form="closeCommentForm"
/> </apollo-mutation
></template>
</design-sidebar>
</div>
</template>

View File

@ -5,6 +5,7 @@ export * from './api/markdown_api';
export * from './api/bulk_imports_api';
export * from './api/namespaces_api';
export * from './api/tags_api';
export * from './api/alert_management_alerts_api';
// Note: It's not possible to spy on methods imported from this file in
// Jest tests.

View File

@ -17,6 +17,5 @@ tier:
- free
- premium
- ultimate
performance_indicator_type:
- paid_gmau
performance_indicator_type: []
milestone: "<13.9"

View File

@ -17,9 +17,7 @@ tier:
- free
- premium
- ultimate
performance_indicator_type:
- gmau
- paid_gmau
performance_indicator_type: []
milestone: "<13.9"
milestone_removed: "15.1"
removed_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88485"

View File

@ -0,0 +1,22 @@
# frozen_string_literal: true
class RemoveInvalidIntegrations < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_main
BATCH_SIZE = 100
def up
loop do
deleted = Integration.where(type_new: nil).limit(BATCH_SIZE).delete_all
break if deleted < BATCH_SIZE
end
end
# Isolated version of the Integration model
class Integration < ApplicationRecord
self.table_name = 'integrations'
self.inheritance_column = :_type_disabled
end
end

View File

@ -0,0 +1 @@
cbbcc9c2439ff583489239afaadb6b18fc86286360745565af52b9baebbf436e

View File

@ -61,7 +61,7 @@ Some of these services have their own environment variables to override the log
| GitLab Export | `INFO` | `EXPORT_DEBUG` |
| GitLab Geo | `INFO` | |
| GitLab Import | `INFO` | `IMPORT_DEBUG` |
| GitLab QA Runtime | `ERROR` | `QA_DEBUG` |
| GitLab QA Runtime | `INFO` | `QA_LOG_LEVEL` |
| Google APIs | `INFO` | |
| Rack Timeout | `ERROR` | |
| Sidekiq (server) | `INFO` | |
@ -144,7 +144,8 @@ Line breaks were added to examples for legibility:
"db_duration_s":0.08,
"view_duration_s":2.39,
"duration_s":20.54,
"pid": 81836
"pid": 81836,
"worker_id":"puma_0"
}
```
@ -167,7 +168,8 @@ seconds:
- `redis_<instance>_duration_s`: Total time to retrieve data from a Redis instance
- `redis_<instance>_read_bytes`: Total bytes read from a Redis instance
- `redis_<instance>_write_bytes`: Total bytes written to a Redis instance
- `pid`: Process ID of the Puma worker
- `pid`: The worker's Linux process ID (changes when workers restart)
- `worker_id`: The worker's logical ID (does not change when workers restart)
User clone and fetch activity using HTTP transport appears in the log as `action: git_upload_pack`.
@ -240,6 +242,7 @@ Starting with GitLab 12.5, if an error occurs, an
"view_duration_s":2.39,
"duration_s":20.54,
"pid": 81836,
"worker_id": "puma_0",
"exception.class": "NameError",
"exception.message": "undefined local variable or method `adsf' for #<Admin::DashboardController:0x00007ff3c9648588>",
"exception.backtrace": [
@ -319,7 +322,10 @@ It helps you see requests made directly to the API. For example:
"username":"root",
"queue_duration":100.31,
"gitaly_calls":30,
"gitaly_duration":5.36
"gitaly_duration":5.36,
"pid": 81836,
"worker_id": "puma_0",
...
}
```
@ -546,6 +552,7 @@ Sidekiq. For example:
"created_at":"2018-04-03T22:57:21.930Z",
"enqueued_at":"2018-04-03T22:57:21.931Z",
"pid":10077,
"worker_id":"sidekiq_0",
"message":"UpdateAllMirrorsWorker JID-06aeaa3b0aadacf9981f368e: done: 0.139 sec",
"job_status":"done",
"duration":0.139,

View File

@ -180,13 +180,13 @@ could be merged sooner.
### Get your changes reviewed
When your merge request is ready for reviews you must assign
reviewers and then maintainers. Depending on the complexity of a change, you
might want to involve the people that know the most about the codebase area you are
changing. We do have many domain experts and maintainers in Verify and it is absolutely acceptable to
ask them to review your code when you are not certain if a reviewer or
maintainer assigned by the Reviewer Roulette has enough context about the
change.
When your merge request is ready for reviews you must assign reviewers and then
maintainers. Depending on the complexity of a change, you might want to involve
the people that know the most about the codebase area you are changing. We do
have many domain experts and maintainers in Verify and it is absolutely
acceptable to ask them to review your code when you are not certain if a
reviewer or maintainer assigned by the Reviewer Roulette has enough context
about the change.
The reviewer roulette offers useful suggestions, but as assigning the right
reviewers is important it should not be done automatically every time. It might
@ -195,9 +195,19 @@ updating, because their feedback might be limited to code style and syntax.
Depending on the complexity and impact of a change, assigning the right people
to review your changes might be very important.
If you don't know who to assign, consult `git blame` or ask in the `#verify`
If you don't know who to assign, consult `git blame` or ask in the `#s_verify`
Slack channel (GitLab team members only).
There are two kinds of changes / merge requests that require additional
attention from reviews and an additional reviewer:
1. Merge requests changing code around pipelines / stages / builds statuses.
1. Merge requests changing code around authentication / security features.
In both cases engineers are expected to request a review from a maintainer and
a domain expert. If maintainer is the domain expert, involving another person
is recommended.
### Incremental rollouts
After your merge request is merged by a maintainer, it is time to release it to

View File

@ -43,7 +43,7 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| `:requires_git_protocol_v2` | The test requires that Git protocol version 2 is enabled on the server. It's assumed to be enabled by default but if not the test can be skipped by setting `QA_CAN_TEST_GIT_PROTOCOL_V2` to `false`. |
| `:requires_praefect` | The test requires that the GitLab instance uses [Gitaly Cluster](../../../administration/gitaly/praefect.md) (a.k.a. Praefect) as the repository storage . It's assumed to be used by default but if not the test can be skipped by setting `QA_CAN_TEST_PRAEFECT` to `false`. |
| `:runner` | The test depends on and sets up a GitLab Runner instance, typically to run a pipeline. |
| `:sanity_feature_flags` | The test run in the `Test::Sanity::FeatureFlags` scenario to verify the functioning of the feature flag handling part of the test framework |
| `:sanity_feature_flags` | The test verifies the functioning of the feature flag handling part of the test framework |
| `:skip_live_env` | The test is excluded when run against live deployed environments such as Staging, Canary, and Production. |
| `:skip_fips_env` | The test is excluded when run against an environment in FIPS mode. |
| `:skip_signup_disabled` | The test uses UI to sign up a new user and is skipped in any environment that does not allow new user registration via the UI. |

View File

@ -274,7 +274,7 @@ Geo requires an EE license. To visit the Geo sites in your browser, you need a r
1. To run end-to-end tests from your local GDK, run the [`EE::Scenario::Test::Geo` scenario](https://gitlab.com/gitlab-org/gitlab/-/blob/f7272b77e80215c39d1ffeaed27794c220dbe03f/qa/qa/ee/scenario/test/geo.rb) from the [`gitlab/qa/` directory](https://gitlab.com/gitlab-org/gitlab/-/blob/f7272b77e80215c39d1ffeaed27794c220dbe03f/qa). Include `--without-setup` to skip the Geo configuration steps.
```shell
QA_DEBUG=true GITLAB_QA_ACCESS_TOKEN=[add token here] GITLAB_QA_ADMIN_ACCESS_TOKEN=[add token here] bundle exec bin/qa QA::EE::Scenario::Test::Geo \
QA_LOG_LEVEL=debug GITLAB_QA_ACCESS_TOKEN=[add token here] GITLAB_QA_ADMIN_ACCESS_TOKEN=[add token here] bundle exec bin/qa QA::EE::Scenario::Test::Geo \
--primary-address http://gitlab-primary.geo \
--secondary-address http://gitlab-secondary.geo \
--without-setup
@ -283,7 +283,7 @@ Geo requires an EE license. To visit the Geo sites in your browser, you need a r
If the containers need to be configured first (for example, if you used the `--no-tests` option in the previous step), run the `QA::EE::Scenario::Test::Geo scenario` as shown below to first do the Geo configuration steps, and then run Geo end-to-end tests. Make sure that `EE_LICENSE` is (still) defined in your shell session.
```shell
QA_DEBUG=true bundle exec bin/qa QA::EE::Scenario::Test::Geo \
QA_LOG_LEVEL=debug bundle exec bin/qa QA::EE::Scenario::Test::Geo \
--primary-address http://gitlab-primary.geo \
--primary-name gitlab-primary \
--secondary-address http://gitlab-secondary.geo \
@ -354,7 +354,7 @@ To run the LDAP tests on your local with TLS enabled, follow these steps:
1. Run an LDAP test from [`gitlab/qa`](https://gitlab.com/gitlab-org/gitlab/-/tree/d5447ebb5f99d4c72780681ddf4dc25b0738acba/qa) directory:
```shell
GITLAB_LDAP_USERNAME="tanuki" GITLAB_LDAP_PASSWORD="password" QA_DEBUG=true WEBDRIVER_HEADLESS=false bin/qa Test::Instance::All https://gitlab.test qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
GITLAB_LDAP_USERNAME="tanuki" GITLAB_LDAP_PASSWORD="password" QA_LOG_LEVEL=debug WEBDRIVER_HEADLESS=false bin/qa Test::Instance::All https://gitlab.test qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
```
### Running LDAP tests with TLS disabled
@ -382,7 +382,7 @@ To run the LDAP tests on your local with TLS disabled, follow these steps:
1. Run an LDAP test from [`gitlab/qa`](https://gitlab.com/gitlab-org/gitlab/-/tree/d5447ebb5f99d4c72780681ddf4dc25b0738acba/qa) directory:
```shell
GITLAB_LDAP_USERNAME="tanuki" GITLAB_LDAP_PASSWORD="password" QA_DEBUG=true WEBDRIVER_HEADLESS=false bin/qa Test::Instance::All http://localhost qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
GITLAB_LDAP_USERNAME="tanuki" GITLAB_LDAP_PASSWORD="password" QA_LOG_LEVEL=debug WEBDRIVER_HEADLESS=false bin/qa Test::Instance::All http://localhost qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
```
## Guide to the mobile suite

View File

@ -25,12 +25,12 @@ WEBDRIVER_HEADLESS=false bundle exec bin/qa Test::Instance::All http://localhost
Sometimes a test might fail and the failure stack trace doesn't provide enough
information to determine what went wrong. You can get more information by enabling
debug logs by setting `QA_DEBUG=true`, to see what the test framework is attempting.
debug logs by setting `QA_LOG_LEVEL=debug`, to see what the test framework is attempting.
For example:
```shell
cd gitlab/qa
QA_DEBUG=true bundle exec bin/qa Test::Instance::All http://localhost:3000
QA_LOG_LEVEL=debug bundle exec bin/qa Test::Instance::All http://localhost:3000
```
The test framework then outputs many logs showing the actions taken during

View File

@ -31,6 +31,7 @@ module Gitlab
instrument_thread_memory_allocations(payload)
instrument_load_balancing(payload)
instrument_pid(payload)
instrument_worker_id(payload)
instrument_uploads(payload)
instrument_rate_limiting_gates(payload)
end
@ -106,6 +107,10 @@ module Gitlab
payload[:pid] = Process.pid
end
def instrument_worker_id(payload)
payload[:worker_id] = ::Prometheus::PidProvider.worker_id
end
def instrument_thread_memory_allocations(payload)
counters = ::Gitlab::Memory::Instrumentation.measure_thread_memory_allocations(
::Gitlab::RequestContext.instance.thread_memory_allocations)

View File

@ -306,7 +306,7 @@ module Gitlab
types Issue
condition do
current_user.can?(:set_issue_crm_contacts, quick_action_target) &&
CustomerRelations::Contact.exists_for_group?(quick_action_target.project.root_ancestor)
quick_action_target.customer_relations_contacts.exists?
end
execution_message do
_('One or more contacts were successfully removed.')

View File

@ -118,7 +118,7 @@ GEM
gitlab (4.18.0)
httparty (~> 0.18)
terminal-table (>= 1.5.1)
gitlab-qa (7.32.0)
gitlab-qa (7.33.0)
activesupport (~> 6.1)
gitlab (~> 4.18.0)
http (~> 5.0)

View File

@ -61,10 +61,6 @@ module QA
ENV['CI_PROJECT_NAME']
end
def debug?
enabled?(ENV['QA_DEBUG'], default: false)
end
def generate_allure_report?
enabled?(ENV['QA_GENERATE_ALLURE_REPORT'], default: false)
end

View File

@ -14,7 +14,7 @@ module QA
# @return [ActiveSupport::Logger]
def self.logger
@logger ||= Gitlab::QA::TestLogger.logger(
level: Runtime::Env.debug? ? "DEBUG" : Gitlab::QA::Runtime::Env.log_level,
level: Gitlab::QA::Runtime::Env.log_level,
source: 'QA Tests',
path: File.expand_path('../../tmp', __dir__)
)

View File

@ -119,8 +119,6 @@ RSpec.describe QA::Resource::Base do
end
it 'logs the resource and build method' do
stub_env('QA_DEBUG', 'true')
subject.fabricate_via_api!('something', resource: resource, parents: [])
expect(QA::Runtime::Logger).to have_received(:info) do |&msg|
@ -159,8 +157,6 @@ RSpec.describe QA::Resource::Base do
end
it 'logs the resource and build method' do
stub_env('QA_DEBUG', 'true')
subject.fabricate_via_browser_ui!('something', resource: resource, parents: [])
expect(QA::Runtime::Logger).to have_received(:info) do |&msg|

View File

@ -47,13 +47,6 @@ RSpec.describe QA::Runtime::Env do
default: false
end
describe '.debug?' do
it_behaves_like 'boolean method',
method: :debug?,
env_key: 'QA_DEBUG',
default: false
end
describe '.webdriver_headless?' do
it_behaves_like 'boolean method',
method: :webdriver_headless?,

View File

@ -147,8 +147,8 @@ RSpec.describe ChaosController do
let(:gc_stat) { GC.stat.stringify_keys }
it 'runs a full GC on the current web worker' do
expect(Prometheus::PidProvider).to receive(:worker_id).and_return('worker-0')
expect(Gitlab::Chaos).to receive(:run_gc).and_return(gc_stat)
allow(Prometheus::PidProvider).to receive(:worker_id).and_return('worker-0')
allow(Gitlab::Chaos).to receive(:run_gc).and_return(gc_stat)
post :gc

View File

@ -94,8 +94,8 @@ RSpec.describe MetricsController, :request_store do
end
it 'renders system stats JSON' do
expect(Prometheus::PidProvider).to receive(:worker_id).and_return('worker-0')
expect(Gitlab::Metrics::System).to receive(:summary).and_return(summary)
allow(Prometheus::PidProvider).to receive(:worker_id).and_return('worker-0')
allow(Gitlab::Metrics::System).to receive(:summary).and_return(summary)
get :system

View File

@ -36,6 +36,7 @@ describe('Design management design presentation component', () => {
discussions,
isAnnotating,
resolvedDiscussionsExpanded,
isLoading: false,
},
stubs,
});

View File

@ -52,6 +52,7 @@ describe('Design management design sidebar component', () => {
design,
resolvedDiscussionsExpanded: false,
markdownPreviewPath: '',
isLoading: false,
...props,
},
mocks: {

View File

@ -99,7 +99,7 @@ exports[`Design management design index page renders design index 1`] = `
variant="link"
>
Resolved Comments (1)
</gl-button-stub>
<gl-popover-stub
@ -112,8 +112,8 @@ exports[`Design management design index page renders design index 1`] = `
>
<p>
Comments you resolve can be viewed and unresolved by going to the "Resolved Comments" section below
Comments you resolve can be viewed and unresolved by going to the "Resolved Comments" section below
</p>
<a
@ -144,19 +144,6 @@ exports[`Design management design index page renders design index 1`] = `
</div>
`;
exports[`Design management design index page sets loading state 1`] = `
<div
class="design-detail js-design-detail fixed-top gl-w-full gl-bottom-0 gl-display-flex gl-justify-content-center gl-flex-direction-column gl-lg-flex-direction-row"
>
<gl-loading-icon-stub
class="gl-align-self-center"
color="dark"
label="Loading"
size="xl"
/>
</div>
`;
exports[`Design management design index page with error GlAlert is rendered in correct position with correct content 1`] = `
<div
class="design-detail js-design-detail fixed-top gl-w-full gl-bottom-0 gl-display-flex gl-justify-content-center gl-flex-direction-column gl-lg-flex-direction-row"
@ -185,8 +172,8 @@ exports[`Design management design index page with error GlAlert is rendered in c
variant="danger"
>
woops
woops
</gl-alert-stub>
</div>

View File

@ -91,7 +91,12 @@ describe('Design management design index page', () => {
function createComponent(
{ loading = false } = {},
{ data = {}, intialRouteOptions = {}, provide = {} } = {},
{
data = {},
intialRouteOptions = {},
provide = {},
stubs = { ApolloMutation, DesignSidebar, DesignReplyForm },
} = {},
) {
const $apollo = {
queries: {
@ -109,11 +114,7 @@ describe('Design management design index page', () => {
wrapper = shallowMount(DesignIndex, {
propsData: { id: '1' },
mocks: { $apollo },
stubs: {
ApolloMutation,
DesignSidebar,
DesignReplyForm,
},
stubs,
provide: {
issueIid: '1',
projectPath: 'project-path',
@ -139,7 +140,7 @@ describe('Design management design index page', () => {
describe('when navigating to component', () => {
it('applies fullscreen layout class', () => {
jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockPageLayoutElement);
createComponent({ loading: true });
createComponent({}, { stubs: {} });
expect(mockPageLayoutElement.classList.add).toHaveBeenCalledTimes(1);
expect(mockPageLayoutElement.classList.add).toHaveBeenCalledWith(
@ -151,7 +152,7 @@ describe('Design management design index page', () => {
describe('when navigating within the component', () => {
it('`scale` prop of DesignPresentation component is 1', async () => {
jest.spyOn(utils, 'getPageLayoutElement').mockReturnValue(mockPageLayoutElement);
createComponent({ loading: false }, { data: { design, scale: 2 } });
createComponent({}, { data: { design, scale: 2 } });
await nextTick();
expect(findDesignPresentation().props('scale')).toBe(2);
@ -180,7 +181,8 @@ describe('Design management design index page', () => {
it('sets loading state', () => {
createComponent({ loading: true });
expect(wrapper.element).toMatchSnapshot();
expect(wrapper.find(DesignPresentation).props('isLoading')).toBe(true);
expect(wrapper.find(DesignSidebar).props('isLoading')).toBe(true);
});
it('renders design index', () => {
@ -197,6 +199,7 @@ describe('Design management design index page', () => {
design,
markdownPreviewPath: '/project-path/preview_markdown?target_type=Issue',
resolvedDiscussionsExpanded: false,
isLoading: false,
});
});

View File

@ -20,6 +20,8 @@ function factory(routeArg) {
return mount(App, {
router,
provide: { issueIid: '1' },
stubs: { Toolbar: true },
mocks: {
$apollo: {
queries: {

View File

@ -110,6 +110,14 @@ RSpec.describe Gitlab::InstrumentationHelper do
expect(payload).to include(:pid)
end
it 'logs the worker ID' do
expect(Prometheus::PidProvider).to receive(:worker_id).and_return('puma_1')
subject
expect(payload).to include(worker_id: 'puma_1')
end
context 'when logging memory allocations' do
include MemoryInstrumentationHelper

View File

@ -303,7 +303,8 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
'duration_s' => 0.0,
'completed_at' => timestamp.to_f,
'cpu_s' => 1.111112,
'rate_limiting_gates' => []
'rate_limiting_gates' => [],
'worker_id' => "process_#{Process.pid}"
)
end

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe RemoveInvalidIntegrations, :migration do
describe '#up' do
let!(:integrations) { table(:integrations) }
let!(:valid_integration) { integrations.create!(type_new: 'Foo') }
let!(:invalid_integration) { integrations.create! }
it 'removes invalid integrations', :aggregate_failures do
expect { migrate! }
.to change { integrations.pluck(:id) }.to(contain_exactly(valid_integration.id))
end
context 'when there are many invalid integrations' do
before do
stub_const('RemoveInvalidIntegrations::BATCH_SIZE', 3)
5.times { integrations.create! }
end
it 'removes them all' do
migrate!
expect(integrations.pluck(:type_new)).to all(be_present)
end
end
end
end

View File

@ -2866,12 +2866,6 @@ RSpec.describe QuickActions::InterpretService do
expect(explanations).to be_empty
end
it '/remove_contacts is not available' do
_, explanations = service.explain(remove_contacts, issue)
expect(explanations).to be_empty
end
end
context 'when group has contacts' do
@ -2883,10 +2877,22 @@ RSpec.describe QuickActions::InterpretService do
expect(explanations).to contain_exactly("Add customer relation contact(s).")
end
it '/remove_contacts is available' do
_, explanations = service.explain(remove_contacts, issue)
context 'when issue has no contacts' do
it '/remove_contacts is not available' do
_, explanations = service.explain(remove_contacts, issue)
expect(explanations).to contain_exactly("Remove customer relation contact(s).")
expect(explanations).to be_empty
end
end
context 'when issue has contacts' do
let!(:issue_contact) { create(:issue_customer_relations_contact, issue: issue, contact: contact) }
it '/remove_contacts is available' do
_, explanations = service.explain(remove_contacts, issue)
expect(explanations).to contain_exactly("Remove customer relation contact(s).")
end
end
end
end

View File

@ -64,7 +64,8 @@ RSpec.shared_context 'structured_logger' do
'duration_s' => 0.0,
'completed_at' => timestamp.to_f,
'cpu_s' => 1.111112,
'rate_limiting_gates' => []
'rate_limiting_gates' => [],
'worker_id' => "process_#{Process.pid}"
)
end