Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-11-12 21:09:19 +00:00
parent f4182abcb6
commit 458209640c
54 changed files with 2625 additions and 2056 deletions

View File

@ -30,9 +30,6 @@ Graphql/IDType:
- 'app/graphql/mutations/boards/issues/issue_move_list.rb'
- 'app/graphql/mutations/issues/update.rb'
- 'app/graphql/mutations/metrics/dashboard/annotations/delete.rb'
- 'app/graphql/mutations/snippets/destroy.rb'
- 'app/graphql/mutations/snippets/mark_as_spam.rb'
- 'app/graphql/mutations/snippets/update.rb'
- 'app/graphql/resolvers/design_management/design_at_version_resolver.rb'
- 'app/graphql/resolvers/design_management/design_resolver.rb'
- 'app/graphql/resolvers/design_management/designs_resolver.rb'
@ -42,7 +39,6 @@ Graphql/IDType:
- 'app/graphql/resolvers/design_management/versions_resolver.rb'
- 'app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb'
- 'app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb'
- 'app/graphql/resolvers/snippets_resolver.rb'
- 'app/graphql/resolvers/user_merge_requests_resolver.rb'
Graphql/ResolverType:

View File

@ -11,7 +11,12 @@ import Modal from './modal.vue';
import createStore from '../store';
import Tracking from '~/tracking';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { summaryTextBuilder, reportTextBuilder, statusIcon } from '../store/utils';
import {
summaryTextBuilder,
reportTextBuilder,
statusIcon,
recentFailuresTextBuilder,
} from '../store/utils';
export default {
name: 'GroupedTestReportsApp',
@ -86,6 +91,12 @@ export default {
return reportTextBuilder(name, summary);
},
hasRecentFailures(summary) {
return this.glFeatures.testFailureHistory && summary?.recentlyFailed > 0;
},
recentFailuresText(summary) {
return recentFailuresTextBuilder(summary);
},
getReportIcon(report) {
return statusIcon(report.status);
},
@ -134,14 +145,22 @@ export default {
{{ s__('ciReport|View full report') }}
</gl-button>
</template>
<template v-if="hasRecentFailures(summary)" #subHeading>
{{ recentFailuresText(summary) }}
</template>
<template #body>
<div class="mr-widget-grouped-section report-block">
<template v-for="(report, i) in reports">
<summary-row
:key="`summary-row-${i}`"
:summary="reportText(report)"
:status-icon="getReportIcon(report)"
/>
<summary-row :key="`summary-row-${i}`" :status-icon="getReportIcon(report)">
<template #summary>
<div class="gl-display-inline-flex gl-flex-direction-column">
<div>{{ reportText(report) }}</div>
<div v-if="hasRecentFailures(report.summary)">
{{ recentFailuresText(report.summary) }}
</div>
</div>
</template>
</summary-row>
<issues-list
v-if="shouldRenderIssuesList(report)"
:key="`issues-list-${i}`"

View File

@ -1,8 +1,15 @@
<script>
import { mapActions } from 'vuex';
import { GlBadge } from '@gitlab/ui';
import { n__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'TestIssueBody',
components: {
GlBadge,
},
mixins: [glFeatureFlagsMixin()],
props: {
issue: {
type: Object,
@ -19,8 +26,20 @@ export default {
default: false,
},
},
computed: {
showRecentFailures() {
return this.glFeatures.testFailureHistory && this.issue.recent_failures;
},
},
methods: {
...mapActions(['openModal']),
recentFailuresText(count) {
return n__(
'Failed %d time in the last 14 days',
'Failed %d times in the last 14 days',
count,
);
},
},
};
</script>
@ -32,7 +51,10 @@ export default {
class="btn-link btn-blank text-left break-link vulnerability-name-button"
@click="openModal({ issue })"
>
<div v-if="isNew" class="badge badge-danger gl-mr-2">{{ s__('New') }}</div>
<gl-badge v-if="isNew" variant="danger" class="gl-mr-2">{{ s__('New') }}</gl-badge>
<gl-badge v-if="showRecentFailures" variant="warning" class="gl-mr-2">
{{ recentFailuresText(issue.recent_failures) }}
</gl-badge>
{{ issue.name }}
</button>
</div>

View File

@ -1,4 +1,5 @@
import * as types from './mutation_types';
import { countRecentlyFailedTests } from './utils';
export default {
[types.SET_ENDPOINT](state, endpoint) {
@ -16,9 +17,15 @@ export default {
state.summary.resolved = response.summary.resolved;
state.summary.failed = response.summary.failed;
state.summary.errored = response.summary.errored;
state.summary.recentlyFailed = countRecentlyFailedTests(response.suites);
state.status = response.status;
state.reports = response.suites;
state.reports.forEach((report, i) => {
if (!state.reports[i].summary) return;
state.reports[i].summary.recentlyFailed = countRecentlyFailedTests(report);
});
},
[types.RECEIVE_REPORTS_ERROR](state) {
state.isLoading = false;
@ -30,6 +37,7 @@ export default {
resolved: 0,
failed: 0,
errored: 0,
recentlyFailed: 0,
};
state.status = null;
},

View File

@ -48,6 +48,48 @@ export const reportTextBuilder = (name = '', results = {}) => {
return sprintf(__('%{name} found %{resultsString}'), { name, resultsString });
};
export const recentFailuresTextBuilder = (summary = {}) => {
const { failed, recentlyFailed } = summary;
if (!failed || !recentlyFailed) return '';
if (failed < 2) {
return sprintf(
s__(
'Reports|%{recentlyFailed} out of %{failed} failed test has failed more than once in the last 14 days',
),
{ recentlyFailed, failed },
);
}
return sprintf(
n__(
s__(
'Reports|%{recentlyFailed} out of %{failed} failed tests has failed more than once in the last 14 days',
),
s__(
'Reports|%{recentlyFailed} out of %{failed} failed tests have failed more than once in the last 14 days',
),
recentlyFailed,
),
{ recentlyFailed, failed },
);
};
export const countRecentlyFailedTests = subject => {
// handle either a single report or an array of reports
const reports = !subject.length ? [subject] : subject;
return reports
.map(report => {
return (
[report.new_failures, report.existing_failures, report.resolved_failures]
// only count tests which have failed more than once
.map(failureArray => failureArray.filter(failure => failure.recent_failures > 1).length)
.reduce((total, count) => total + count, 0)
);
})
.reduce((total, count) => total + count, 0);
};
export const statusIcon = status => {
if (status === STATUS_FAILED) {
return ICON_WARNING;

View File

@ -16,6 +16,7 @@ class Admin::DashboardController < Admin::ApplicationController
@groups = Group.order_id_desc.with_route.limit(10)
@notices = Gitlab::ConfigChecker::PumaRuggedChecker.check
@notices += Gitlab::ConfigChecker::ExternalDatabaseChecker.check
@redis_versions = [Gitlab::Redis::Queues, Gitlab::Redis::SharedState, Gitlab::Redis::Cache].map(&:version).uniq
end
# rubocop: enable CodeReuse/ActiveRecord

View File

@ -42,6 +42,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:default_merge_ref_for_diffs, @project)
push_frontend_feature_flag(:core_security_mr_widget, @project, default_enabled: true)
push_frontend_feature_flag(:remove_resolve_note, @project, default_enabled: true)
push_frontend_feature_flag(:test_failure_history, @project)
record_experiment_user(:invite_members_version_a)
record_experiment_user(:invite_members_version_b)

View File

@ -13,6 +13,10 @@ class DeviseMailer < Devise::Mailer
devise_mail(record, :password_change_by_admin, opts)
end
def user_admin_approval(record, opts = {})
devise_mail(record, :user_admin_approval, opts)
end
protected
def subject_for(key)

View File

@ -24,6 +24,10 @@ class DeviseMailerPreview < ActionMailer::Preview
DeviseMailer.password_change(unsaved_user, {})
end
def user_admin_approval
DeviseMailer.user_admin_approval(unsaved_user, {})
end
private
def unsaved_user

View File

@ -15,6 +15,7 @@ module Users
# Please see Devise's implementation of `resend_confirmation_instructions` for detail.
user.resend_confirmation_instructions
user.accept_pending_invitations! if user.active_for_authentication?
DeviseMailer.user_admin_approval(user).deliver_later
success
else

View File

@ -139,6 +139,10 @@
= Gitlab::Database.human_adapter_name
%span.float-right
= Gitlab::Database.version
%p
= _('Redis')
%span.float-right
= @redis_versions&.join(", ")
%p
= link_to _("Gitaly Servers"), admin_gitaly_servers_path
.row

View File

@ -0,0 +1,8 @@
= email_default_heading(say_hi(@resource))
%p
= _('Your GitLab account request has been approved!')
%p
= _('Your username is %{username}.') % { username: @resource.username }
%p
= _('Your sign-in page is %{url}.').html_safe % { url: link_to(Gitlab.config.gitlab.url, Gitlab.config.gitlab.url) }

View File

@ -0,0 +1,7 @@
<%= say_hi(@resource) %>
<%= _('Your GitLab account request has been approved!') %>
<%= _('Your username is %{username}.' % { username: @resource.username }) %>
<%= _('Your sign-in page is %{url}.' % { url: Gitlab.config.gitlab.url }) %>

View File

@ -0,0 +1,5 @@
---
title: Email user on admin account approval
merge_request: 45947
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Include aggregated git-write usage counts
merge_request: 47511
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Add Redis version to admin page
merge_request: 47242
author:
type: added

View File

@ -30,6 +30,8 @@ en:
subject: "Password Changed"
password_change_by_admin:
subject: "Password changed by administrator"
user_admin_approval:
subject: "Welcome to GitLab!"
omniauth_callbacks:
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
success: "Successfully authenticated from %{kind} account."

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class CreatedIndexForVulnerabilityOccurrencesOnProjectFingerprint < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
INDEX_NAME = 'index_vulnerability_occurrences_on_project_fingerprint'
disable_ddl_transaction!
def up
add_concurrent_index :vulnerability_occurrences, :project_fingerprint, name: INDEX_NAME
end
def down
remove_concurrent_index_by_name :vulnerability_occurrences, INDEX_NAME
end
end

View File

@ -0,0 +1 @@
21245809e056dfefedc4d2c6a8e2bf642bfcee480a863f8707ba6fa6b748a2e0

View File

@ -22211,6 +22211,8 @@ CREATE INDEX index_vulnerability_occurrences_for_issue_links_migration ON vulner
CREATE INDEX index_vulnerability_occurrences_on_primary_identifier_id ON vulnerability_occurrences USING btree (primary_identifier_id);
CREATE INDEX index_vulnerability_occurrences_on_project_fingerprint ON vulnerability_occurrences USING btree (project_fingerprint);
CREATE INDEX index_vulnerability_occurrences_on_scanner_id ON vulnerability_occurrences USING btree (scanner_id);
CREATE UNIQUE INDEX index_vulnerability_occurrences_on_unique_keys ON vulnerability_occurrences USING btree (project_id, primary_identifier_id, location_fingerprint, scanner_id);

View File

@ -12,6 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Available action types for the `action` parameter are:
- `approved`
- `created`
- `updated`
- `closed`

View File

@ -173,7 +173,7 @@ See [database guidelines](database/index.md).
## Documentation guides
- [Writing documentation](documentation/index.md)
- [Documentation style guide](documentation/styleguide.md)
- [Documentation style guide](documentation/styleguide/index.md)
- [Markdown](../user/markdown.md)
## Internationalization (i18n) guides

View File

@ -146,7 +146,7 @@ Keep the following in mind when submitting merge requests:
reviewers.
- If the code quality is found to not meet GitLabs standards, the merge request reviewer will
provide guidance and refer the author to our:
- [Documentation](../documentation/styleguide.md) style guide.
- [Documentation](../documentation/styleguide/index.md) style guide.
- Code style guides.
- Sometimes style guides will be followed but the code will lack structural integrity, or the
reviewer will have reservations about the codes overall quality. When there is a reservation,

View File

@ -122,7 +122,7 @@ We're following [Ciro Santilli's Markdown Style Guide](https://cirosantilli.com/
## Documentation
See the dedicated [Documentation Style Guide](../documentation/styleguide.md).
See the dedicated [Documentation Style Guide](../documentation/styleguide/index.md).
## Python

View File

@ -30,7 +30,7 @@ See how to document them below, according to the state of the flag:
- [Features that can be enabled or disabled for a single project](#features-enabled-by-project).
- [Features with the feature flag removed](#features-with-flag-removed).
The [`**(CORE ONLY)**`](styleguide.md#product-badges) badge or equivalent for
The [`**(CORE ONLY)**`](styleguide/index.md#product-badges) badge or equivalent for
the feature's tier should be added to the line and heading that refers to
enabling/disabling feature flags as Admin access is required to do so,
therefore, it indicates that it cannot be done by regular users of GitLab.com.

View File

@ -67,7 +67,7 @@ Set up the section with the following:
```
- Include a screenshot of the result in the GraphiQL explorer. Follow the naming
convention described in the [Save the image](styleguide.md#save-the-image) section of the Documentation style guide.
convention described in the [Save the image](styleguide/index.md#save-the-image) section of the Documentation style guide.
- Follow up with an example of what you can do with the output. Make sure the
example is something that readers can do on their own deployments.
- Include a link to the [GraphQL API resources](../../api/graphql/reference/index.md).

View File

@ -11,7 +11,7 @@ GitLab's documentation is [intended as the single source of truth (SSOT)](https:
In addition to this page, the following resources can help you craft and contribute to documentation:
- [Style Guide](styleguide.md) - What belongs in the docs, language guidelines, Markdown standards to follow, links, and more.
- [Style Guide](styleguide/index.md) - What belongs in the docs, language guidelines, Markdown standards to follow, links, and more.
- [Structure and template](structure.md) - Learn the typical parts of a doc page and how to write each one.
- [Documentation process](workflow.md).
- [Markdown Guide](../../user/markdown.md) - A reference for all Markdown syntax supported by GitLab.
@ -64,11 +64,11 @@ However, anyone can contribute [documentation improvements](workflow.md) that ar
[GitLab docs](https://gitlab.com/gitlab-org/gitlab-docs) uses [GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown)
as its Markdown rendering engine. See the [GitLab Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/) for a complete Kramdown reference.
Adhere to the [Documentation Style Guide](styleguide.md). If a style standard is missing, you are welcome to suggest one via a merge request.
Adhere to the [Documentation Style Guide](styleguide/index.md). If a style standard is missing, you are welcome to suggest one via a merge request.
## Folder structure and files
See the [Structure](styleguide.md#structure) section of the [Documentation Style Guide](styleguide.md).
See the [Structure](styleguide/index.md#structure) section of the [Documentation Style Guide](styleguide/index.md).
## Metadata
@ -229,7 +229,7 @@ Things to note:
it in for `workflow/lfs/lfs_administration` and `lfs/lfs_administration`
and will print the file and the line where this file is mentioned.
You may ask why the two greps. Since [we use relative paths to link to
documentation](styleguide.md#links), sometimes it might be useful to search a path deeper.
documentation](styleguide/index.md#links), sometimes it might be useful to search a path deeper.
- The `*.md` extension is not used when a document is linked to GitLab's
built-in help page, which is why we omit it in `git grep`.
- Use the checklist on the "Change documentation location" MR description template.

View File

@ -105,8 +105,8 @@ you can use in the API documentation.
CAUTION: **Caution:**
Do not use information for real users, URLs, or tokens. For documentation, refer to our
relevant style guide sections on [Fake user information](styleguide.md#fake-user-information),
[Fake URLs](styleguide.md#fake-urls), and [Fake tokens](styleguide.md#fake-tokens).
relevant style guide sections on [Fake user information](styleguide/index.md#fake-user-information),
[Fake URLs](styleguide/index.md#fake-urls), and [Fake tokens](styleguide/index.md#fake-tokens).
### Simple cURL command

View File

@ -10,7 +10,7 @@ description: What to include in GitLab documentation pages.
Use these standards to contribute content to the GitLab documentation.
Before getting started, familiarize yourself with [GitLab's Documentation guidelines](index.md)
and the [Documentation Style Guide](styleguide.md).
and the [Documentation Style Guide](styleguide/index.md).
## Components of a documentation page
@ -39,7 +39,7 @@ pre-deployment and post-deployment tasks.
## Template for new docs
Follow the [folder structure and file name guidelines](styleguide.md#folder-structure-overview)
Follow the [folder structure and file name guidelines](styleguide/index.md#folder-structure-overview)
and create a new topic by using this template:
```markdown
@ -160,9 +160,9 @@ commented out to help encourage others to add to it in the future. -->
Notes:
- (1): Apply the [tier badges](styleguide.md#product-badges) accordingly.
- (1): Apply the [tier badges](styleguide/index.md#product-badges) accordingly.
- (2): Apply the correct format for the
[GitLab version that introduces the feature](styleguide.md#gitlab-versions-and-tiers).
[GitLab version that introduces the feature](styleguide/index.md#gitlab-versions-and-tiers).
```
## Help and feedback section

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -122,7 +122,7 @@ and you should make sure your version matches the version used by GitLab.
## Local linters
To help adhere to the [documentation style guidelines](styleguide.md), and improve the content
To help adhere to the [documentation style guidelines](styleguide/index.md), and improve the content
added to documentation, [install documentation linters](#install-linters) and
[integrate them with your code editor](#configure-editors).
@ -137,7 +137,7 @@ At GitLab, we mostly use:
[certain rules](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md#rules), and is
used by the `docs-lint` test.
Our [Documentation Style Guide](styleguide.md#markdown) and
Our [Documentation Style Guide](styleguide/index.md#markdown) and
[Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/) elaborate on which choices must
be made when selecting Markdown syntax for GitLab documentation. This tool helps catch deviations
from those guidelines.

View File

@ -58,7 +58,7 @@ To update GitLab documentation:
[GitLab Documentation guidelines](index.md) page.
1. Follow the described standards and processes listed on the page, including:
- The [Structure and template](structure.md) page.
- The [Style Guide](styleguide.md).
- The [Style Guide](styleguide/index.md).
- The [Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/).
1. Follow GitLab's [Merge Request Guidelines](../contributing/merge_request_workflow.md#merge-request-guidelines).
@ -87,7 +87,7 @@ Anyone with Maintainer access to the relevant GitLab project can merge documenta
Maintainers must make a good-faith effort to ensure that the content:
- Is clear and sufficiently easy for the intended audience to navigate and understand.
- Meets the [Documentation Guidelines](index.md) and [Style Guide](styleguide.md).
- Meets the [Documentation Guidelines](index.md) and [Style Guide](styleguide/index.md).
If the author or reviewer has any questions, they can mention the writer who is assigned to the relevant
[DevOps stage group](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
@ -154,15 +154,15 @@ Remember:
Ensure the following if skipping an initial Technical Writer review:
- That [product badges](styleguide.md#product-badges) are applied.
- That the GitLab [version](styleguide.md#text-for-documentation-requiring-version-text) that
- That [product badges](styleguide/index.md#product-badges) are applied.
- That the GitLab [version](styleguide/index.md#text-for-documentation-requiring-version-text) that
introduced the feature has been included.
- That changes to headings don't affect in-app hyperlinks.
- Specific [user permissions](../../user/permissions.md) are documented.
- That new documents are linked from higher-level indexes, for discoverability.
- Style guide is followed:
- For [directories and files](styleguide.md#work-with-directories-and-files).
- For [images](styleguide.md#images).
- For [directories and files](styleguide/index.md#work-with-directories-and-files).
- For [images](styleguide/index.md#images).
Merge requests that change the location of documentation must always be reviewed by a Technical
Writer prior to merging.

View File

@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
- **Write the code and the tests.**: As with any code, EE features should have
good test coverage to prevent regressions.
- **Write documentation.**: Add documentation to the `doc/` directory. Describe
the feature and include screenshots, if applicable. Indicate [what editions](documentation/styleguide.md#product-badges)
the feature and include screenshots, if applicable. Indicate [what editions](documentation/styleguide/index.md#product-badges)
the feature applies to.
- **Submit a MR to the `www-gitlab-com` project.**: Add the new feature to the
[EE features list](https://about.gitlab.com/features/).

View File

@ -312,6 +312,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
- `aggregation`: aggregation `:daily` or `:weekly`. The argument defines how we build the Redis
keys for data storage. For `daily` we keep a key for metric per day of the year, for `weekly` we
keep a key for metric per week of the year.
- `feature_flag`: optional. For details, see our [GitLab internal Feature flags](../feature_flags/) documentation.
1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, feature:, feature_default_enabled: false)`.
@ -402,7 +403,7 @@ Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PF
| `event` | string | yes | The event name it should be tracked |
Response
w
Return 200 if tracking failed for any reason.
- `200` if event was tracked or any errors
@ -454,6 +455,20 @@ Recommendations:
- Use a [feature flag](../../operations/feature_flags.md) to have a control over the impact when
adding new metrics.
##### Enable/Disable Redis HLL tracking
Events are tracked behind [feature flags](../feature_flags/index.md) due to concerns for Redis performance and scalability.
For a full list of events and coresponding feature flags see, [known_events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/) files.
To enable or disable tracking for specific event within <https://gitlab.com> or <https://staging.gitlab.com>, run commands such as the following to
[enable or disable the corresponding feature](../feature_flags/index.md).
```shell
/chatops run feature set <feature_name> true
/chatops run feature set <feature_name> false
```
##### Known events in usage data payload
All events added in [`known_events/common.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml) are automatically added to usage data generation under the `redis_hll_counters` key. This column is stored in [version-app as a JSON](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L209).

View File

@ -8,51 +8,87 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Project integrations can be configured and enabled by project administrators. As a GitLab instance
administrator, you can set default configuration parameters for a given integration that all projects
can inherit and use. This enables the integration for all projects that are not already using custom
can inherit and use, enabling the integration for all projects that are not already using custom
settings.
You can update these default settings at any time, changing the settings used for all projects that
are set to use instance-level defaults. Updating the default settings also enables the integration
are set to use instance-level or group-level defaults. Updating the default settings also enables the integration
for all projects that didn't have it already enabled.
Only the complete settings for an integration can be inherited. Per-field inheritance is
[planned](https://gitlab.com/groups/gitlab-org/-/epics/2137) as is
[group-level management](https://gitlab.com/groups/gitlab-org/-/epics/2543) of integration settings.
Only the complete settings for an integration can be inherited. Per-field inheritance is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137).
## Manage instance-level default settings for a project integration **(CORE ONLY)**
> [Introduced in](https://gitlab.com/groups/gitlab-org/-/epics/2137) GitLab 13.3.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2137) in GitLab 13.3 for project-level integrations.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6 for group-level integrations.
1. Navigate to **Admin Area > Settings > Integrations**.
1. Select a project integration.
1. Select an integration.
1. Enter configuration details and click **Save changes**.
CAUTION: **Caution:**
This may affect all or most of the projects on your GitLab instance. Please review the details
This may affect all or most of the groups and projects on your GitLab instance. Please review the details
below.
If this is the first time you are setting up instance-level settings for an integration:
- The integration is enabled for all projects that don't already have this integration configured,
- The integration is enabled for all groups and projects that don't already have this integration configured,
if you have the **Enable integration** toggle turned on in the instance-level settings.
- Projects that already have the integration configured are not affected, but can choose to use the
- Groups and projects that already have the integration configured are not affected, but can choose to use the
inherited settings at any time.
When you make further changes to the instance defaults:
- They are immediately applied to all projects that have the integration set to use default settings.
- They are immediately applied to newer projects, created since you last saved defaults for the
- They are immediately applied to all groups and projects that have the integration set to use default settings.
- They are immediately applied to newer groups and projects, created since you last saved defaults for the
integration. If your instance-level default setting has the **Enable integration** toggle turned
on, the integration is automatically enabled for all such projects.
- Projects with custom settings selected for the integration are not immediately affected and may
on, the integration is automatically enabled for all such groups and projects.
- Groups and projects with custom settings selected for the integration are not immediately affected and may
choose to use the latest defaults at any time.
Only the complete settings for an integration can be inherited. Per-field inheritance
is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137). This would allow
administrators to update settings inherited by projects without enabling the
integration on all non-configured projects by default.
administrators to update settings inherited by groups and projects without enabling the
integration on all non-configured groups and projects by default.
## Use instance-level default settings for a project integration
## Manage group-level default settings for a project integration
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6.
1. Navigate to the group's **Settings > Integrations**.
1. Select an integration.
1. Enter configuration details and click **Save changes**.
CAUTION: **Caution:**
This may affect all or most of the subgroups and projects belonging to the group. Please review the details below.
If this is the first time you are setting up group-level settings for an integration:
- The integration is enabled for all subgroups and projects belonging to the group that don't already have
this integration configured, if you have the **Enable integration** toggle turned on in the group-level
settings.
- Subgroups and projects that already have the integration configured are not affected, but can choose to use
the inherited settings at any time.
When you make further changes to the group defaults:
- They are immediately applied to all subgroups and projects belonging to the group that have the integration
set to use default settings.
- They are immediately applied to newer subgroups and projects, created since you last saved defaults for the
integration. If your group-level default setting has the **Enable integration** toggle turned on,
the integration is automatically enabled for all such subgroups and projects.
- Subgroups and projects with custom settings selected for the integration are not immediately affected and
may choose to use the latest defaults at any time.
Only the complete settings for an integration can be inherited. Per-field inheritance
is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137). This would allow
administrators to update settings inherited by subgroups and projects without enabling the
integration on all non-configured groups and projects by default.
## Use instance-level or group-level default settings for a project integration
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6 for group-level settings.
1. Navigate to **Project > Settings > Integrations**.
1. Choose the integration you want to enable or update.
@ -60,9 +96,9 @@ integration on all non-configured projects by default.
1. Ensure the toggle is set to **Enable integration**.
1. Click **Save changes**.
## Use custom settings for a project integration
## Use custom settings for a group or project integration
1. Navigate to project's **Settings > Integrations**.
1. Navigate to project or group's **Settings > Integrations**.
1. Choose the integration you want to enable or update.
1. From the drop-down, select **Use custom settings**.
1. Ensure the toggle is set to **Enable integration** and enter all required settings.

View File

@ -745,6 +745,7 @@ To enable prevent project forking:
- **Audit Events**: View [Audit Events](../../administration/audit_events.md)
for the group. **(STARTER ONLY)**
- **Pipelines quota**: Keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group.
- **Integrations**: Configure [integrations](../admin_area/settings/project_integration_management.md) for your group.
#### Storage usage quota **(STARTER)**

View File

@ -18,6 +18,10 @@ module Gitlab
pool.with { |redis| yield redis }
end
def version
with { |redis| redis.info['redis_version'] }
end
def pool
@pool ||= ConnectionPool.new(size: pool_size) { ::Redis.new(params) }
end

View File

@ -765,7 +765,8 @@ module Gitlab
data = {
action_monthly_active_users_project_repo: Gitlab::UsageDataCounters::TrackUniqueEvents::PUSH_ACTION,
action_monthly_active_users_design_management: Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION,
action_monthly_active_users_wiki_repo: Gitlab::UsageDataCounters::TrackUniqueEvents::WIKI_ACTION
action_monthly_active_users_wiki_repo: Gitlab::UsageDataCounters::TrackUniqueEvents::WIKI_ACTION,
action_monthly_active_users_git_write: Gitlab::UsageDataCounters::TrackUniqueEvents::GIT_WRITE_ACTION
}
data.each do |key, event|

View File

@ -35,6 +35,7 @@ module Gitlab
# category: compliance # Group events in categories
# expiry: 29 # Optional expiration time in days, default value 29 days for daily and 6.weeks for weekly
# aggregation: daily # Aggregation level, keys are stored daily or weekly
# feature_flag: # The event feature flag
#
# Usage:
#

View File

@ -4,114 +4,141 @@
redis_slot: compliance
category: compliance
aggregation: weekly
feature_flag: track_unique_visits
- name: g_compliance_audit_events
category: compliance
redis_slot: compliance
aggregation: weekly
feature_flag: track_unique_visits
- name: i_compliance_audit_events
category: compliance
redis_slot: compliance
aggregation: weekly
feature_flag: track_unique_visits
- name: i_compliance_credential_inventory
category: compliance
redis_slot: compliance
aggregation: weekly
feature_flag: track_unique_visits
- name: a_compliance_audit_events_api
category: compliance
redis_slot: compliance
aggregation: weekly
feature_flag: usage_data_a_compliance_audit_events_api
# Analytics category
- name: g_analytics_contribution
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: g_analytics_insights
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: g_analytics_issues
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: g_analytics_productivity
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: g_analytics_valuestream
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: p_analytics_pipelines
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: p_analytics_code_reviews
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: p_analytics_valuestream
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: p_analytics_insights
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: p_analytics_issues
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: p_analytics_repo
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: i_analytics_cohorts
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: i_analytics_dev_ops_score
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: g_analytics_merge_request
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: p_analytics_merge_request
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: i_analytics_instance_statistics
category: analytics
redis_slot: analytics
aggregation: weekly
feature_flag: track_unique_visits
- name: g_edit_by_web_ide
category: ide_edit
redis_slot: edit
expiry: 29
aggregation: daily
feature_flag: track_editor_edit_actions
- name: g_edit_by_sfe
category: ide_edit
redis_slot: edit
expiry: 29
aggregation: daily
feature_flag: track_editor_edit_actions
- name: g_edit_by_snippet_ide
category: ide_edit
redis_slot: edit
expiry: 29
aggregation: daily
feature_flag: track_editor_edit_actions
- name: i_search_total
category: search
redis_slot: search
aggregation: weekly
feature_flag: search_track_unique_users
- name: i_search_advanced
category: search
redis_slot: search
aggregation: weekly
feature_flag: search_track_unique_users
- name: i_search_paid
category: search
redis_slot: search
aggregation: weekly
feature_flag: search_track_unique_users
- name: wiki_action
category: source_code
aggregation: daily
@ -121,6 +148,9 @@
- name: project_action
category: source_code
aggregation: daily
- name: git_write_action
category: source_code
aggregation: daily
- name: merge_request_action
category: source_code
aggregation: daily
@ -133,194 +163,242 @@
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_alert_status_changed
- name: incident_management_alert_assigned
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_alert_assigned
- name: incident_management_alert_todo
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_alert_todo
- name: incident_management_incident_created
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_incident_created
- name: incident_management_incident_reopened
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_incident_reopened
- name: incident_management_incident_closed
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_incident_closed
- name: incident_management_incident_assigned
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_incident_assigned
- name: incident_management_incident_todo
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_incident_todo
- name: incident_management_incident_comment
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_incident_comment
- name: incident_management_incident_zoom_meeting
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_incident_zoom_meeting
- name: incident_management_incident_published
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_incident_published
- name: incident_management_incident_relate
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_incident_relate
- name: incident_management_incident_unrelate
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_incident_unrelate
- name: incident_management_incident_change_confidential
redis_slot: incident_management
category: incident_management
aggregation: weekly
feature_flag: usage_data_incident_management_incident_change_confidential
# Testing category
- name: i_testing_test_case_parsed
category: testing
redis_slot: testing
aggregation: weekly
feature_flag: usage_data_i_testing_test_case_parsed
# Project Management group
- name: g_project_management_issue_title_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_description_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_assignee_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_made_confidential
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_made_visible
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_created
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_closed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_reopened
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_label_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_milestone_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_iteration_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_weight_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_cross_referenced
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_moved
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_related
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_unrelated
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_marked_as_duplicate
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_locked
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_unlocked
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_added_to_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_removed_from_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_changed_epic
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_designs_added
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_designs_modified
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_designs_removed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_due_date_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_time_estimate_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_time_spent_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_comment_added
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_comment_edited
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_comment_removed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
- name: g_project_management_issue_health_status_changed
category: issues_edit
redis_slot: project_management
aggregation: daily
feature_flag: track_issue_activity_actions
# Secrets Management
- name: i_ci_secrets_management_vault_build_created
category: ci_secrets_management
redis_slot: ci_secrets_management
aggregation: weekly
feature_flag: usage_data_i_ci_secrets_management_vault_build_created

View File

@ -8,6 +8,9 @@ module Gitlab
PUSH_ACTION = :project_action
MERGE_REQUEST_ACTION = :merge_request_action
GIT_WRITE_ACTIONS = [WIKI_ACTION, DESIGN_ACTION, PUSH_ACTION].freeze
GIT_WRITE_ACTION = :git_write_action
ACTION_TRANSFORMATIONS = HashWithIndifferentAccess.new({
wiki: {
created: WIKI_ACTION,
@ -41,6 +44,8 @@ module Gitlab
return unless Gitlab::UsageDataCounters::HLLRedisCounter.known_event?(transformed_action.to_s)
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(author_id, transformed_action.to_s, time)
track_git_write_action(author_id, transformed_action, time)
end
def count_unique_events(event_action:, date_from:, date_to:)
@ -64,6 +69,12 @@ module Gitlab
def valid_action?(action)
Event.actions.key?(action)
end
def track_git_write_action(author_id, transformed_action, time)
return unless GIT_WRITE_ACTIONS.include?(transformed_action)
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(author_id, GIT_WRITE_ACTION, time)
end
end
end
end

View File

@ -11208,6 +11208,11 @@ msgstr ""
msgid "Failed"
msgstr ""
msgid "Failed %d time in the last 14 days"
msgid_plural "Failed %d times in the last 14 days"
msgstr[0] ""
msgstr[1] ""
msgid "Failed Jobs"
msgstr ""
@ -22186,6 +22191,9 @@ msgstr ""
msgid "Redirect to SAML provider to test configuration"
msgstr ""
msgid "Redis"
msgstr ""
msgid "Reduce project visibility"
msgstr ""
@ -22688,6 +22696,15 @@ msgstr ""
msgid "Reports|%{combinedString} and %{resolvedString}"
msgstr ""
msgid "Reports|%{recentlyFailed} out of %{failed} failed test has failed more than once in the last 14 days"
msgstr ""
msgid "Reports|%{recentlyFailed} out of %{failed} failed tests has failed more than once in the last 14 days"
msgstr ""
msgid "Reports|%{recentlyFailed} out of %{failed} failed tests have failed more than once in the last 14 days"
msgstr ""
msgid "Reports|Accessibility scanning detected %d issue for the source branch only"
msgid_plural "Reports|Accessibility scanning detected %d issues for the source branch only"
msgstr[0] ""
@ -31188,6 +31205,9 @@ msgstr ""
msgid "Your GPG keys (%{count})"
msgstr ""
msgid "Your GitLab account request has been approved!"
msgstr ""
msgid "Your GitLab group"
msgstr ""
@ -31386,6 +31406,9 @@ msgstr ""
msgid "Your search didn't match any commits. Try a different query."
msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
msgid "Your subscription expired!"
msgstr ""
@ -31395,6 +31418,9 @@ msgstr ""
msgid "Your subscription will expire in %{remaining_days}."
msgstr ""
msgid "Your username is %{username}."
msgstr ""
msgid "Zoom meeting added"
msgstr ""

View File

@ -4,12 +4,20 @@ require 'spec_helper'
RSpec.describe Admin::DashboardController do
describe '#index' do
before do
sign_in(create(:admin))
end
it 'retrieves Redis versions' do
get :index
expect(assigns[:redis_versions].length).to eq(1)
end
context 'with pending_delete projects' do
render_views
it 'does not retrieve projects that are pending deletion' do
sign_in(create(:admin))
project = create(:project)
pending_delete_project = create(:project, pending_delete: true)

View File

@ -116,6 +116,11 @@ RSpec.describe Admin::UsersController do
expect(user).to be_active
expect(flash[:notice]).to eq('Successfully approved')
end
it 'emails the user on approval' do
expect(DeviseMailer).to receive(:user_admin_approval).with(user).and_call_original
expect { subject }.to have_enqueued_mail(DeviseMailer, :user_admin_approval)
end
end
context 'when unsuccessful' do
@ -133,6 +138,10 @@ RSpec.describe Admin::UsersController do
user.reload
expect(user).not_to be_active
end
it 'does not email the pending user' do
expect { subject }.not_to have_enqueued_mail(DeviseMailer, :user_admin_approval)
end
end
end

View File

@ -7,6 +7,7 @@ import { getStoreConfig } from '~/reports/store';
import { failedReport } from '../mock_data/mock_data';
import successTestReports from '../mock_data/no_failures_report.json';
import newFailedTestReports from '../mock_data/new_failures_report.json';
import recentFailuresTestReports from '../mock_data/recent_failures_report.json';
import newErrorsTestReports from '../mock_data/new_errors_report.json';
import mixedResultsTestReports from '../mock_data/new_and_fixed_failures_report.json';
import resolvedFailures from '../mock_data/resolved_failures.json';
@ -21,7 +22,7 @@ describe('Grouped test reports app', () => {
let wrapper;
let mockStore;
const mountComponent = ({ props = { pipelinePath } } = {}) => {
const mountComponent = ({ props = { pipelinePath }, testFailureHistory = false } = {}) => {
wrapper = mount(Component, {
store: mockStore,
localVue,
@ -30,6 +31,11 @@ describe('Grouped test reports app', () => {
pipelinePath,
...props,
},
provide: {
glFeatures: {
testFailureHistory,
},
},
});
};
@ -234,6 +240,77 @@ describe('Grouped test reports app', () => {
});
});
describe('recent failures counts', () => {
describe('with recent failures counts', () => {
beforeEach(() => {
setReports(recentFailuresTestReports);
});
describe('with feature flag enabled', () => {
beforeEach(() => {
mountComponent({ testFailureHistory: true });
});
it('renders the recently failed tests summary', () => {
expect(findHeader().text()).toContain(
'2 out of 3 failed tests have failed more than once in the last 14 days',
);
});
it('renders the recently failed count on the test suite', () => {
expect(findSummaryDescription().text()).toContain(
'1 out of 2 failed tests has failed more than once in the last 14 days',
);
});
it('renders the recent failures count on the test case', () => {
expect(findIssueDescription().text()).toContain('Failed 8 times in the last 14 days');
});
});
describe('with feature flag disabled', () => {
beforeEach(() => {
mountComponent({ testFailureHistory: false });
});
it('does not render the recently failed tests summary', () => {
expect(findHeader().text()).not.toContain('failed more than once in the last 14 days');
});
it('does not render the recently failed count on the test suite', () => {
expect(findSummaryDescription().text()).not.toContain(
'failed more than once in the last 14 days',
);
});
it('renders the recent failures count on the test case', () => {
expect(findIssueDescription().text()).not.toContain('in the last 14 days');
});
});
});
describe('without recent failures counts', () => {
beforeEach(() => {
setReports(mixedResultsTestReports);
mountComponent();
});
it('does not render the recently failed tests summary', () => {
expect(findHeader().text()).not.toContain('failed more than once in the last 14 days');
});
it('does not render the recently failed count on the test suite', () => {
expect(findSummaryDescription().text()).not.toContain(
'failed more than once in the last 14 days',
);
});
it('does not render the recent failures count on the test case', () => {
expect(findIssueDescription().text()).not.toContain('in the last 14 days');
});
});
});
describe('with a report that failed to load', () => {
beforeEach(() => {
setReports(failedReport);

View File

@ -0,0 +1,46 @@
{
"summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 3, "recentlyFailed": 2 },
"suites": [
{
"name": "rspec:pg",
"summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 2, "recentlyFailed": 1 },
"new_failures": [
{
"result": "failure",
"name": "Test#sum when a is 1 and b is 2 returns summary",
"execution_time": 0.009411,
"system_output": "Failure/Error: is_expected.to eq(3)\n\n expected: 3\n got: -1\n\n (compared using ==)\n./spec/test_spec.rb:12:in `block (4 levels) in <top (required)>'",
"recent_failures": 8
},
{
"result": "failure",
"name": "Test#sum when a is 100 and b is 200 returns summary",
"execution_time": 0.000162,
"system_output": "Failure/Error: is_expected.to eq(300)\n\n expected: 300\n got: -100\n\n (compared using ==)\n./spec/test_spec.rb:21:in `block (4 levels) in <top (required)>'"
}
],
"resolved_failures": [],
"existing_failures": [],
"new_errors": [],
"resolved_errors": [],
"existing_errors": []
},
{
"name": "java ant",
"summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 1, "recentlyFailed": 1 },
"new_failures": [
{
"result": "failure",
"name": "Test#sum when a is 100 and b is 200 returns summary",
"execution_time": 0.000562,
"recent_failures": 3
}
],
"resolved_failures": [],
"existing_failures": [],
"new_errors": [],
"resolved_errors": [],
"existing_errors": []
}
]
}

View File

@ -46,6 +46,7 @@ describe('Reports Store Mutations', () => {
name: 'StringHelper#concatenate when a is git and b is lab returns summary',
execution_time: 0.0092435,
system_output: "Failure/Error: is_expected.to eq('gitlab')",
recent_failures: 4,
},
],
resolved_failures: [
@ -82,6 +83,7 @@ describe('Reports Store Mutations', () => {
expect(stateCopy.summary.total).toEqual(mockedResponse.summary.total);
expect(stateCopy.summary.resolved).toEqual(mockedResponse.summary.resolved);
expect(stateCopy.summary.failed).toEqual(mockedResponse.summary.failed);
expect(stateCopy.summary.recentlyFailed).toEqual(1);
});
it('should set reports', () => {

View File

@ -168,6 +168,54 @@ describe('Reports store utils', () => {
});
});
describe('recentFailuresTextBuilder', () => {
it.each`
recentlyFailed | failed | expected
${0} | ${1} | ${''}
${1} | ${1} | ${'1 out of 1 failed test has failed more than once in the last 14 days'}
${1} | ${2} | ${'1 out of 2 failed tests has failed more than once in the last 14 days'}
${2} | ${3} | ${'2 out of 3 failed tests have failed more than once in the last 14 days'}
`(
'should render summary for $recentlyFailed out of $failed failures',
({ recentlyFailed, failed, expected }) => {
const result = utils.recentFailuresTextBuilder({ recentlyFailed, failed });
expect(result).toBe(expected);
},
);
});
describe('countRecentlyFailedTests', () => {
it('counts tests with more than one recent failure in a report', () => {
const report = {
new_failures: [{ recent_failures: 2 }],
existing_failures: [{ recent_failures: 1 }],
resolved_failures: [{ recent_failures: 20 }, { recent_failures: 5 }],
};
const result = utils.countRecentlyFailedTests(report);
expect(result).toBe(3);
});
it('counts tests with more than one recent failure in an array of reports', () => {
const reports = [
{
new_failures: [{ recent_failures: 2 }],
existing_failures: [{ recent_failures: 20 }, { recent_failures: 5 }],
resolved_failures: [{ recent_failures: 2 }],
},
{
new_failures: [{ recent_failures: 8 }, { recent_failures: 14 }],
existing_failures: [{ recent_failures: 1 }],
resolved_failures: [{ recent_failures: 7 }, { recent_failures: 5 }],
},
];
const result = utils.countRecentlyFailedTests(reports);
expect(result).toBe(8);
});
});
describe('statusIcon', () => {
describe('with failed status', () => {
it('returns ICON_WARNING', () => {

View File

@ -243,6 +243,7 @@ ci_pipelines:
- vulnerability_findings
- pipeline_config
- security_scans
- security_findings
- daily_build_group_report_results
- latest_builds
- daily_report_results

View File

@ -26,6 +26,12 @@ RSpec.describe Gitlab::Redis::Wrapper do
end
end
describe '.version' do
it 'returns a version' do
expect(described_class.version).to be_present
end
end
describe '.instrumentation_class' do
it 'raises a NotImplementedError' do
expect(described_class).to receive(:instrumentation_class).and_call_original

View File

@ -1085,6 +1085,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
let(:user1) { build(:user, id: 1) }
let(:user2) { build(:user, id: 2) }
let(:user3) { build(:user, id: 3) }
let(:user4) { build(:user, id: 4) }
before do
counter = Gitlab::UsageDataCounters::TrackUniqueEvents
@ -1099,6 +1100,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
counter.track_event(event_action: :pushed, event_target: project, author_id: 4, time: time - 3.days)
counter.track_event(event_action: :created, event_target: wiki, author_id: 3)
counter.track_event(event_action: :created, event_target: design, author_id: 3)
counter.track_event(event_action: :created, event_target: design, author_id: 4)
counter = Gitlab::UsageDataCounters::EditorUniqueCounter
@ -1118,9 +1120,10 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
it 'returns the distinct count of user actions within the specified time period' do
expect(described_class.action_monthly_active_users(time_period)).to eq(
{
action_monthly_active_users_design_management: 1,
action_monthly_active_users_design_management: 2,
action_monthly_active_users_project_repo: 3,
action_monthly_active_users_wiki_repo: 1,
action_monthly_active_users_git_write: 4,
action_monthly_active_users_web_ide_edit: 2,
action_monthly_active_users_sfe_edit: 2,
action_monthly_active_users_snippet_editor_edit: 2,

View File

@ -64,4 +64,34 @@ RSpec.describe DeviseMailer do
is_expected.to have_body_text /#{Gitlab.config.gitlab.url}/
end
end
describe '#user_admin_approval' do
subject { described_class.user_admin_approval(user) }
let_it_be(:user) { create(:user) }
it_behaves_like 'an email sent from GitLab'
it_behaves_like 'it should not have Gmail Actions links'
it_behaves_like 'a user cannot unsubscribe through footer link'
it 'is sent to the user' do
is_expected.to deliver_to user.email
end
it 'has the correct subject' do
is_expected.to have_subject 'Welcome to GitLab!'
end
it 'greets the user' do
is_expected.to have_body_text /Hi #{user.name}!/
end
it 'includes the correct content' do
is_expected.to have_body_text /Your GitLab account request has been approved!/
end
it 'includes a link to GitLab' do
is_expected.to have_link(Gitlab.config.gitlab.url)
end
end
end

View File

@ -61,6 +61,11 @@ RSpec.describe Users::ApproveService do
expect(user.reload).to be_active
end
it 'emails the user on approval' do
expect(DeviseMailer).to receive(:user_admin_approval).with(user).and_call_original
expect { subject }.to have_enqueued_mail(DeviseMailer, :user_admin_approval)
end
context 'email confirmation status' do
context 'user is unconfirmed' do
let(:user) { create(:user, :blocked_pending_approval, :unconfirmed) }