Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
f4182abcb6
commit
458209640c
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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}`"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
@ -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 }) %>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Email user on admin account approval
|
||||
merge_request: 45947
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Include aggregated git-write usage counts
|
||||
merge_request: 47511
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add Redis version to admin page
|
||||
merge_request: 47242
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -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."
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
21245809e056dfefedc4d2c6a8e2bf642bfcee480a863f8707ba6fa6b748a2e0
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ Keep the following in mind when submitting merge requests:
|
|||
reviewers.
|
||||
- If the code quality is found to not meet GitLab’s 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 code’s overall quality. When there is a reservation,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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/).
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)**
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
#
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ""
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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', () => {
|
||||
|
|
|
|||
|
|
@ -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', () => {
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ ci_pipelines:
|
|||
- vulnerability_findings
|
||||
- pipeline_config
|
||||
- security_scans
|
||||
- security_findings
|
||||
- daily_build_group_report_results
|
||||
- latest_builds
|
||||
- daily_report_results
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
|
|||
Loading…
Reference in New Issue