Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-03-22 18:09:24 +00:00
parent 06d4ce7ee0
commit 9a643ab892
55 changed files with 482 additions and 130 deletions

View file

@ -1,5 +1,5 @@
<script>
import { GlButton, GlPopover } from '@gitlab/ui';
import { GlButton, GlPopover, GlSafeHtmlDirective } from '@gitlab/ui';
/**
* Render a button with a question mark icon
@ -11,6 +11,9 @@ export default {
GlButton,
GlPopover,
},
directives: {
SafeHtml: GlSafeHtmlDirective,
},
props: {
options: {
type: Object,
@ -24,13 +27,11 @@ export default {
<span>
<gl-button ref="popoverTrigger" variant="link" icon="question" tabindex="0" />
<gl-popover triggers="hover focus" :target="() => $refs.popoverTrigger.$el" v-bind="options">
<template #title>
<!-- eslint-disable-next-line vue/no-v-html -->
<span v-html="options.title"></span>
<template v-if="options.title" #title>
<span v-safe-html="options.title"></span>
</template>
<template #default>
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-html="options.content"></div>
<div v-safe-html="options.content"></div>
</template>
</gl-popover>
</span>

View file

@ -199,6 +199,8 @@ class User < ApplicationRecord
has_many :reviews, foreign_key: :author_id, inverse_of: :author
has_many :in_product_marketing_emails, class_name: '::Users::InProductMarketingEmail'
#
# Validations
#

View file

@ -0,0 +1,28 @@
# frozen_string_literal: true
module Users
class InProductMarketingEmail < ApplicationRecord
include BulkInsertSafe
belongs_to :user
validates :user, presence: true
validates :track, presence: true
validates :series, presence: true
validates :user_id, uniqueness: {
scope: [:track, :series],
message: 'has already been sent'
}
enum track: {
create: 0,
verify: 1,
trial: 2,
team: 3
}, _suffix: true
scope :without_track_or_series, -> (track, series) do
where.not(track: track).or(where.not(series: series))
end
end
end

View file

@ -23,20 +23,25 @@ module Namespaces
def initialize(track, interval)
@track = track
@interval = interval
@sent_email_user_ids = []
@current_batch_user_ids = []
@in_product_marketing_email_records = []
end
def execute
raise NotImplementedError, "Track #{track} not defined" unless TRACKS.key?(track)
groups_for_track.each_batch do |groups|
groups.each do |group|
send_email_for_group(group)
end
end
record_sent_emails
end
private
attr_reader :track, :interval, :sent_email_user_ids
attr_reader :track, :interval, :current_batch_user_ids, :in_product_marketing_email_records
def send_email_for_group(group)
experiment_enabled_for_group = experiment_enabled_for_group?(group)
@ -71,7 +76,12 @@ module Namespaces
def users_for_group(group)
group.users.where(email_opted_in: true)
.where.not(id: sent_email_user_ids)
.where.not(id: current_batch_user_ids)
.left_outer_joins(:in_product_marketing_emails)
.merge(
Users::InProductMarketingEmail.without_track_or_series(track, series)
.or(Users::InProductMarketingEmail.where(id: nil))
)
end
# rubocop: enable CodeReuse/ActiveRecord
@ -85,14 +95,13 @@ module Namespaces
user.can?(:start_trial, group)
when :team
user.can?(:admin_group_member, group)
else
raise NotImplementedError, "No ability defined for track #{track}"
end
end
def send_email(user, group)
NotificationService.new.in_product_marketing(user.id, group.id, track, series)
sent_email_user_ids << user.id
track_sent_email(user, group, track, series)
end
def completed_actions
@ -111,5 +120,21 @@ module Namespaces
def series
INTERVAL_DAYS.index(interval)
end
def record_sent_emails
Users::InProductMarketingEmail.bulk_insert!(in_product_marketing_email_records)
end
def track_sent_email(user, group, track, series)
current_batch_user_ids << user.id
in_product_marketing_email_records << Users::InProductMarketingEmail.new(
user: user,
track: track,
series: series,
created_at: Time.zone.now,
updated_at: Time.zone.now
)
end
end
end

View file

@ -25,5 +25,5 @@
- if !member?
.actions
= link_to _("Accept invitation"), accept_invite_url(@token), method: :post, class: "btn gl-button btn-success"
= link_to _("Accept invitation"), accept_invite_url(@token), method: :post, class: "btn gl-button btn-confirm"
= link_to _("Decline"), decline_invite_url(@token), method: :post, class: "btn gl-button btn-danger gl-ml-3"

View file

@ -0,0 +1,5 @@
---
title: Move to btn-confirm from btn-success in views/invites directory
merge_request: 55293
author: Yogi (@yo)
type: changed

View file

@ -0,0 +1,5 @@
---
title: Record sent in-product marketing emails and don't send the same email twice
merge_request: 55840
author:
type: changed

View file

@ -0,0 +1,5 @@
---
title: Do not render empty title in HelpPopover
merge_request: 57025
author:
type: fixed

View file

@ -0,0 +1,102 @@
- title: "Admin Mode: Re-authenticate for GitLab administration"
body: |
GitLab now includes Admin Mode, which helps admins work safely from one account. When Admin Mode is not active, admins have the same privileges as a regular user. Before running administrative commands, admin users must reverify their credentials. Admin mode increases instance security by protecting sensitive operations and data.
stage: Manage
self-managed: true
gitlab-com: false
packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/admin_area/settings/sign_in_restrictions.html#admin-mode
image_url: https://about.gitlab.com/images/13_10/manage_reauth_admin.png
published_at: 2021-03-22
release: 13.10
- title: "GitLab Runner for Red Hat OpenShift GA"
body: |
The GitLab Runner Operator is generally available in the [Red Hat OpenShift Container Platform](https://www.openshift.com/products/container-platform). To install GitLab Runner on OpenShift, you can use the [GitLab Runner Operator](https://gitlab.com/gitlab-org/gl-openshift/gitlab-runner-operator), which is available from the stable channel in the OperatorHub. The Container Platform is a web console for OpenShift cluster administrators to discover and select Operators to install on their cluster. We are also developing an [Operator](https://gitlab.com/groups/gitlab-org/-/epics/3444) for GitLab, so stay tuned to future release posts for those announcements.
stage: Verify
self-managed: true
gitlab-com: true
packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/runner/install/openshift.html
image_url: https://img.youtube.com/vi/ZNBc_QnDUu4/hqdefault.jpg
published_at: 2021-03-22
release: 13.10
- title: "View epics on a board (MVC)"
body: |
If you work on epics in GitLab, it can be tough to visualize your epics' workflow status. Often, when drafting or writing epics, you might want to use labels (like `Open`, `Doing`, or `Done`) to keep tabs on the next steps when creating your project plan.
In this release, we took our awesome [Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html) feature and optimized it for viewing epics. You can now visualize the workflow status of your epics on an epic board by applying [labels](https://docs.gitlab.com/ee/user/project/labels.html#label-management) or [scoped labels](https://docs.gitlab.com/ee/user/project/labels.html#scoped-labels) to them.
We are releasing this early version of Epic Boards in 13.10, so we can start [gathering customer feedback](https://gitlab.com/gitlab-org/gitlab/-/issues/324677). We will follow it up with [MVC 2](https://gitlab.com/groups/gitlab-org/-/epics/5069) and [MVC 3](https://gitlab.com/groups/gitlab-org/-/epics/5079), which will achieve parity with Issue Boards. Please leave feedback about your experience in the [feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324677).
stage: Plan
self-managed: true
gitlab-com: true
packages: [Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/group/epics/epic_boards.html
image_url: https://about.gitlab.com/images/13_10/view-epics-on-a-board-mvc-1.png
published_at: 2021-03-22
release: 13.10
- title: "View Jira issue details in GitLab"
body: |
Users of our Jira issue list feature can now view the details of an issue directly inside of GitLab! This MVC enables developers to see the details, labels, and comments on an issue, giving them the ability to stay in GitLab while working on Jira issues.
Our goal is to empower developers to _stay inside of GitLab_ during the majority of their day, and this is now one less trip to Jira you'll have to make.
In GitLab 13.10, this feature is available if you [enable a feature flag](https://docs.gitlab.com/ee/user/project/integrations/jira.html#enable-or-disable-jira-issue-detail-view). This feature will be [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/299832) in GitLab 13.11.
stage: Create
self-managed: true
gitlab-com: true
packages: [Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/integrations/jira.html#view-a-jira-issue
image_url: https://about.gitlab.com/images/13_10/jira-detail-view.png
published_at: 2021-03-22
release: 13.10
- title: "DORA4-based lead time for changes"
body: |
Measuring the efficiency of your software development lifecycle is an important step to grow DevOps adoption for any organization. In the previous milestone, we added support for [DORA4-based Deployment Frequency](https://docs.gitlab.com/ee/api/dora4_project_analytics.html). In this release, we are excited to announce the support of a new API for lead time for changes (via merge requests) on the project level. The lead time for changes gives you an indication of how long it takes for code to be committed and deployed to your production environment. Understanding and tracking this data is a great starting point in your journey to continuous improvement in your DevOps process.
stage: Release
self-managed: true
gitlab-com: true
packages: [Ultimate]
url: https://docs.gitlab.com/ee/api/dora4_project_analytics.html#list-project-merge-request-lead-times
image_url: https://about.gitlab.com/images/13_10/api.png
published_at: 2021-03-22
release: 13.10
- title: "Create a release from an existing tag"
body: |
Previously, creating a release was supported only for new tags. In GitLab 13.10, you can now create a release by selecting an existing tag, something that will give you more flexibility when planning releases.
stage: Release
self-managed: true
gitlab-com: true
packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/project/releases/#create-a-release
image_url: https://about.gitlab.com/images/13_10/exiting_tags.png
published_at: 2021-03-22
release: 13.10
- title: "Integrate any IT alerting tool with GitLab"
body: |
Alert integrations are a critical part of your Incident Management workflows. It's difficult to manage integrations between tools, especially when several monitoring tools like Nagios, Solarwinds, etc. alert on your services. These integrations notify you and your team of incidents, so it's critical for them to be easy to set up and maintain.
In this version of GitLab, you can create multiple HTTP endpoints with unique auth tokens for each integrated monitoring tool. When you set up an HTTP endpoint with a unique auth token for each monitoring tool, your team can manage each tool separately without affecting alerts from other tools nor take down all of your alerting by resetting a single auth token!
stage: Monitor
self-managed: true
gitlab-com: true
packages: [Premium, Ultimate]
url: https://docs.gitlab.com/ee/operations/incident_management/integrations.html#http-endpoints
image_url: https://about.gitlab.com/images/13_10/integrate_alerts.png
published_at: 2021-03-22
release: 13.10
- title: "Merge Request test summary usability improvements"
body: |
Increasing the number of tests or custom metrics in a pipeline gives you additional confidence and information. However, increasing these to a large number has also come with a degraded visual experience of the Merge Request page. The Merge Request test summary widget has been improved so you can better differentiate between the different test jobs in the widget, making it easier to identify which job contains failed tests.
It has also been challenging to understand why a `junit.xml` file was not parsed without errors being presented. Now you can see parsing errors in the Test Summary widget, as well as the Unit Test report, to identify and resolve structural issues and see test results in GitLab.
The [Metrics Reports](https://docs.gitlab.com/ee/ci/metrics_reports.html) widget [(Premium and Ultimate)](https://about.gitlab.com/pricing/) is now sorted so new, changed, and unchanged metrics are all together, making the experience of finding metrics that have changed as part of the Merge Request more intuitive.
stage: Verify
self-managed: true
gitlab-com: true
packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/ci/unit_test_reports.html
image_url: https://about.gitlab.com/images/13_10/test_summary_ux_improvements.png
published_at: 2021-03-22
release: 13.10

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
class CreateInProductMarketingEmails < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
UNIQUE_INDEX_NAME = 'index_in_product_marketing_emails_on_user_track_series'
disable_ddl_transaction!
def up
with_lock_retries do
create_table :in_product_marketing_emails do |t|
t.bigint :user_id, null: false
t.datetime_with_timezone :cta_clicked_at
t.integer :track, null: false, limit: 2
t.integer :series, null: false, limit: 2
t.timestamps_with_timezone
end
end
add_index :in_product_marketing_emails, :user_id
add_index :in_product_marketing_emails, [:user_id, :track, :series], unique: true, name: UNIQUE_INDEX_NAME
end
def down
with_lock_retries do
drop_table :in_product_marketing_emails
end
end
end

View file

@ -0,0 +1,19 @@
# frozen_string_literal: true
class AddUserForeignKeyToInProductMarketingEmails < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_foreign_key :in_product_marketing_emails, :users, column: :user_id, on_delete: :cascade
end
def down
with_lock_retries do
remove_foreign_key :in_product_marketing_emails, column: :user_id
end
end
end

View file

@ -0,0 +1 @@
c502a539a50ef1b8f07a8c22426a23cf974ee663fc80a99abe0d658e2a07f52b

View file

@ -0,0 +1 @@
64675f43f66d90158147c62699c0d2a48dc74d017c81b30ce3847408d0dad3cb

View file

@ -13460,6 +13460,25 @@ CREATE SEQUENCE import_failures_id_seq
ALTER SEQUENCE import_failures_id_seq OWNED BY import_failures.id;
CREATE TABLE in_product_marketing_emails (
id bigint NOT NULL,
user_id bigint NOT NULL,
cta_clicked_at timestamp with time zone,
track smallint NOT NULL,
series smallint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);
CREATE SEQUENCE in_product_marketing_emails_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE in_product_marketing_emails_id_seq OWNED BY in_product_marketing_emails.id;
CREATE TABLE incident_management_oncall_participants (
id bigint NOT NULL,
oncall_rotation_id bigint NOT NULL,
@ -19367,6 +19386,8 @@ ALTER TABLE ONLY import_export_uploads ALTER COLUMN id SET DEFAULT nextval('impo
ALTER TABLE ONLY import_failures ALTER COLUMN id SET DEFAULT nextval('import_failures_id_seq'::regclass);
ALTER TABLE ONLY in_product_marketing_emails ALTER COLUMN id SET DEFAULT nextval('in_product_marketing_emails_id_seq'::regclass);
ALTER TABLE ONLY incident_management_oncall_participants ALTER COLUMN id SET DEFAULT nextval('incident_management_oncall_participants_id_seq'::regclass);
ALTER TABLE ONLY incident_management_oncall_rotations ALTER COLUMN id SET DEFAULT nextval('incident_management_oncall_rotations_id_seq'::regclass);
@ -20670,6 +20691,9 @@ ALTER TABLE ONLY import_export_uploads
ALTER TABLE ONLY import_failures
ADD CONSTRAINT import_failures_pkey PRIMARY KEY (id);
ALTER TABLE ONLY in_product_marketing_emails
ADD CONSTRAINT in_product_marketing_emails_pkey PRIMARY KEY (id);
ALTER TABLE ONLY incident_management_oncall_shifts
ADD CONSTRAINT inc_mgmnt_no_overlapping_oncall_shifts EXCLUDE USING gist (rotation_id WITH =, tstzrange(starts_at, ends_at, '[)'::text) WITH &&);
@ -22740,6 +22764,10 @@ CREATE INDEX index_import_failures_on_project_id_not_null ON import_failures USI
CREATE INDEX index_imported_projects_on_import_type_creator_id_created_at ON projects USING btree (import_type, creator_id, created_at) WHERE (import_type IS NOT NULL);
CREATE INDEX index_in_product_marketing_emails_on_user_id ON in_product_marketing_emails USING btree (user_id);
CREATE UNIQUE INDEX index_in_product_marketing_emails_on_user_track_series ON in_product_marketing_emails USING btree (user_id, track, series);
CREATE INDEX index_inc_mgmnt_oncall_participants_on_oncall_user_id ON incident_management_oncall_participants USING btree (user_id);
CREATE UNIQUE INDEX index_inc_mgmnt_oncall_participants_on_user_id_and_rotation_id ON incident_management_oncall_participants USING btree (user_id, oncall_rotation_id);
@ -24679,6 +24707,9 @@ ALTER TABLE ONLY ci_group_variables
ALTER TABLE ONLY namespaces
ADD CONSTRAINT fk_3448c97865 FOREIGN KEY (push_rule_id) REFERENCES push_rules(id) ON DELETE SET NULL;
ALTER TABLE ONLY in_product_marketing_emails
ADD CONSTRAINT fk_35c9101b63 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_3654b61b03 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;

View file

@ -52,7 +52,7 @@ verification methods:
| Blobs | External Merge Request Diffs _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | External Merge Request Diffs _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
- (*1*): Redis replication can be used as part of HA with Redis sentinel. It's not used between Geo nodes.
- (*1*): Redis replication can be used as part of HA with Redis sentinel. It's not used between Geo sites.
- (*2*): Object storage replication can be performed by Geo or by your object storage provider/appliance
native replication feature.
@ -68,7 +68,7 @@ performance limitations when using a remote file system).
Communication is done via Gitaly's own gRPC API. There are three possible ways of synchronization:
- Using regular Git clone/fetch from one Geo node to another (with special authentication).
- Using regular Git clone/fetch from one Geo site to another (with special authentication).
- Using repository snapshots (for when the first method fails or repository is corrupt).
- Manual trigger from the Admin Area (a combination of both of the above).
@ -82,7 +82,7 @@ They all live in the same shard and share the same base name with a `-wiki` and
for Wiki and Design Repository cases.
Besides that, there are snippet repositories. They can be connected to a project or to some specific user.
Both types will be synced to a secondary node.
Both types will be synced to a secondary site.
### Blobs
@ -95,7 +95,7 @@ GitLab stores files and blobs such as Issue attachments or LFS objects into eith
- A Storage Appliance that exposes an Object Storage-compatible API.
When using the file system store instead of Object Storage, you need to use network mounted file systems
to run GitLab when using more than one server.
to run GitLab when using more than one node.
With respect to replication and verification:
@ -113,10 +113,10 @@ as well as permissions and credentials.
PostgreSQL can also hold some level of cached data like HTML rendered Markdown, cached merge-requests diff (this can
also be configured to be offloaded to object storage).
We use PostgreSQL's own replication functionality to replicate data from the **primary** to **secondary** nodes.
We use PostgreSQL's own replication functionality to replicate data from the **primary** to **secondary** sites.
We use Redis both as a cache store and to hold persistent data for our background jobs system. Because both
use-cases has data that are exclusive to the same Geo node, we don't replicate it between nodes.
use-cases have data that are exclusive to the same Geo site, we don't replicate it between sites.
Elasticsearch is an optional database, that can enable advanced searching capabilities, like improved Advanced Search
in both source-code level and user generated content in Issues / Merge-Requests and discussions. Currently it's not
@ -125,7 +125,7 @@ supported in Geo.
## Limitations on replication/verification
The following table lists the GitLab features along with their replication
and verification status on a **secondary** node.
and verification status on a **secondary** site.
You can keep track of the progress to implement the missing items in
these epics/issues:
@ -165,9 +165,9 @@ Feature.enable(:geo_package_file_replication)
WARNING:
Features not on this list, or with **No** in the **Replicated** column,
are not replicated on the **secondary** node. Failing over without manually
are not replicated to a **secondary** site. Failing over without manually
replicating data from those features will cause the data to be **lost**.
If you wish to use those features on a **secondary** node, or to execute a failover
If you wish to use those features on a **secondary** site, or to execute a failover
successfully, you must replicate their data using some other means.
| Feature | Replicated (added in GitLab version) | Verified (added in GitLab version) | Object Storage replication (see [Geo with Object Storage](object_storage.md)) | Notes |
@ -176,12 +176,12 @@ successfully, you must replicate their data using some other means.
| [Project repository](../../../user/project/repository/) | **Yes** (10.2) | **Yes** (10.7) | No | |
| [Project wiki repository](../../../user/project/wiki/) | **Yes** (10.2) | **Yes** (10.7) | No |
| [Group wiki repository](../../../user/group/index.md#group-wikis) | [**Yes** (13.10)](https://gitlab.com/gitlab-org/gitlab/-/issues/208147) | No | No | Behind feature flag `geo_group_wiki_repository_replication`, enabled by default |
| [Uploads](../../uploads.md) | **Yes** (10.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | No | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both nodes and comparing the output between them. |
| [LFS objects](../../lfs/index.md) | **Yes** (10.2) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8922) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both nodes and comparing the output between them. GitLab versions 11.11.x and 12.0.x are affected by [a bug that prevents any new LFS objects from replicating](https://gitlab.com/gitlab-org/gitlab/-/issues/32696). |
| [Uploads](../../uploads.md) | **Yes** (10.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | No | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them. |
| [LFS objects](../../lfs/index.md) | **Yes** (10.2) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8922) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them. GitLab versions 11.11.x and 12.0.x are affected by [a bug that prevents any new LFS objects from replicating](https://gitlab.com/gitlab-org/gitlab/-/issues/32696). |
| [Personal snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
| [Project snippets](../../../user/snippets.md) | **Yes** (10.2) | **Yes** (10.2) | No | |
| [CI job artifacts (other than Job Logs)](../../../ci/pipelines/job_artifacts.md) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Via Object Storage provider if supported. Native Geo support (Beta) . | Verified only manually using [Integrity Check Rake Task](../../raketasks/check.md) on both nodes and comparing the output between them |
| [Job logs](../../job_logs.md) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both nodes and comparing the output between them |
| [CI job artifacts (other than Job Logs)](../../../ci/pipelines/job_artifacts.md) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Via Object Storage provider if supported. Native Geo support (Beta) . | Verified only manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them |
| [Job logs](../../job_logs.md) | **Yes** (10.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/8923) | Via Object Storage provider if supported. Native Geo support (Beta). | Verified only on transfer or manually using [Integrity Check Rake Task](../../raketasks/check.md) on both sites and comparing the output between them |
| [Object pools for forked project deduplication](../../../development/git_object_deduplication.md) | **Yes** | No | No | |
| [Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | No | Disabled by default. See [instructions](docker_registry.md) to enable. |
| [Content in object storage (beta)](object_storage.md) | **Yes** (12.4) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/13845) | No | |

View file

@ -753,7 +753,7 @@ The default value for Omnibus installations is `nil`.
If left unchanged, GitLab Pages tries to use any available source (either `gitlab` or `disk`). The
preferred source is `gitlab`, which uses [API-based configuration](#gitlab-api-based-configuration).
On large GitLab instances, using the API-based configuration will significantly improve the pages daemon startup time, as there is no need to load all custom domains configuration into memory.
On large GitLab instances, using the API-based configuration will significantly improve the pages daemon startup time, as there is no need to load all custom domains configuration into memory.
For more details see this [blog post](https://about.gitlab.com/blog/2020/08/03/how-gitlab-pages-uses-the-gitlab-api-to-serve-content/).
@ -816,7 +816,7 @@ or persistent errors, or the Pages Daemon serving old content.
NOTE:
Expiry, interval and timeout flags use [Golang's duration formatting](https://golang.org/pkg/time/#ParseDuration).
A duration string is a possibly signed sequence of decimal numbers,
each with optional fraction and a unit suffix, such as "300ms", "1.5h" or "2h45m".
each with optional fraction and a unit suffix, such as "300ms", "1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
Examples:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -808,7 +808,7 @@ apollo: {
},
```
Then, becasue Etags depend on the request being a `GET` instead of GraphQL's usual `POST`, but our default link library does not support `GET` we need to let our defaut Apollo client know to use a different library.
Then, becasue Etags depend on the request being a `GET` instead of GraphQL's usual `POST`, but our default link library does not support `GET` we need to let our defaut Apollo client know to use a different library.
```javascript
/* componentMountIndex.js */
@ -825,7 +825,7 @@ const apolloProvider = new VueApollo({
Keep in mind, this means your app will not batch queries.
Once subscriptions are mature, this process can be replaced by using them and we can remove the separate link library and return to batching queries.
Once subscriptions are mature, this process can be replaced by using them and we can remove the separate link library and return to batching queries.
### Testing

View file

@ -536,21 +536,23 @@ The pre-clone step works by using the `CI_PRE_CLONE_SCRIPT` variable
The `CI_PRE_CLONE_SCRIPT` is currently defined as a project CI/CD variable:
```shell
echo "Downloading archived master..."
wget -O /tmp/gitlab.tar.gz https://storage.googleapis.com/gitlab-ci-git-repo-cache/project-278964/gitlab-master-shallow.tar.gz
if [ ! -f /tmp/gitlab.tar.gz ]; then
echo "Repository cache not available, cloning a new directory..."
exit
fi
rm -rf $CI_PROJECT_DIR
echo "Extracting tarball into $CI_PROJECT_DIR..."
mkdir -p $CI_PROJECT_DIR
cd $CI_PROJECT_DIR
tar xzf /tmp/gitlab.tar.gz
rm -f /tmp/gitlab.tar.gz
chmod a+w $CI_PROJECT_DIR
(
echo "Downloading archived master..."
wget -O /tmp/gitlab.tar.gz https://storage.googleapis.com/gitlab-ci-git-repo-cache/project-278964/gitlab-master-shallow.tar.gz
if [ ! -f /tmp/gitlab.tar.gz ]; then
echo "Repository cache not available, cloning a new directory..."
exit
fi
rm -rf $CI_PROJECT_DIR
echo "Extracting tarball into $CI_PROJECT_DIR..."
mkdir -p $CI_PROJECT_DIR
cd $CI_PROJECT_DIR
tar xzf /tmp/gitlab.tar.gz
rm -f /tmp/gitlab.tar.gz
chmod a+w $CI_PROJECT_DIR
)
```
The first step of the script downloads `gitlab-master.tar.gz` from

View file

@ -930,7 +930,7 @@ WARNING:
This feature is intended solely for internal GitLab use.
To add data for aggregated metrics into Usage Ping payload you should add corresponding definition at [`lib/gitlab/usage_data_counters/aggregated_metrics/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics/) for metrics available at Community Edition and at [`ee/lib/gitlab/usage_data_counters/aggregated_metrics/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/gitlab/usage_data_counters/aggregated_metrics/) for Enterprise Edition ones.
Each aggregate definition includes following parts:
- `name`: Unique name under which the aggregate metric is added to the Usage Ping payload.
@ -999,7 +999,7 @@ Aggregated metrics collected in `7d` and `28d` time frames are added into Usage
}
```
Aggregated metrics for `all` time frame are present in the `count` top level key, with the `aggregate_` prefix added to their name.
Aggregated metrics for `all` time frame are present in the `count` top level key, with the `aggregate_` prefix added to their name.
For example:
@ -1007,7 +1007,7 @@ For example:
Becomes:
`counts.aggregate_example_metrics_intersection`
`counts.aggregate_example_metrics_intersection`
```ruby
{

View file

@ -91,12 +91,12 @@ Since Elasticsearch can read and use indices created in the previous major versi
The only thing worth noting is that if you have created your current index before GitLab 13.0, you might want to reindex from scratch (which will implicitly create an alias) in order to use some features, for example [Zero downtime reindexing](#zero-downtime-reindexing). Once you do that, you'll be able to perform zero-downtime reindexing and will benefit from any future features that make use of the alias.
If you are unsure when your current index was created,
you can check whether it was created after GitLab 13.0 by using the
[Elasticsearch cat aliases API](https://www.elastic.co/guide/en/elasticsearch/reference/7.11/cat-alias.html).
If the list of aliases returned contains an entry for `gitlab-production` that points to an index
named `gitlab-production-<numerical timestamp>`, your index was created after GitLab 13.0.
If the `gitlab-production` alias is missing, you'll need to reindex from scratch to use
If you are unsure when your current index was created,
you can check whether it was created after GitLab 13.0 by using the
[Elasticsearch cat aliases API](https://www.elastic.co/guide/en/elasticsearch/reference/7.11/cat-alias.html).
If the list of aliases returned contains an entry for `gitlab-production` that points to an index
named `gitlab-production-<numerical timestamp>`, your index was created after GitLab 13.0.
If the `gitlab-production` alias is missing, you'll need to reindex from scratch to use
features such as Zero-downtime reindexing.
## Elasticsearch repository indexer

View file

@ -4,24 +4,17 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# GitLab Jira Development Panel integration **(FREE)**
# GitLab Jira Development panel integration **(FREE)**
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/233149) to GitLab Free in 13.4.
The Jira Development Panel integration allows you to reference Jira issues in GitLab, displaying
The Jira Development panel integration allows you to reference Jira issues in GitLab, displaying
activity in the [Development panel](https://support.atlassian.com/jira-software-cloud/docs/view-development-information-for-an-issue/)
in the issue.
It complements the [GitLab Jira integration](../user/project/integrations/jira.md). You may choose
to configure both integrations to take advantage of both sets of features. See a
[feature comparison](../user/project/integrations/jira_integrations.md#feature-comparison).
Depending on your environment, you can enable this integration by either:
- Configuring [the Jira DVCS connector](#jira-dvcs-configuration).
- Using the [GitLab for Jira app](#gitlab-for-jira-app) in the Atlassian Marketplace.
See the [Configuration](#configuration) section for details.
[feature comparison](../user/project/integrations/jira_integrations.md).
## Features
@ -46,19 +39,16 @@ This differs from the [Jira integration](../user/project/integrations/jira.md),
## Configuration
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see [Agile Management - GitLab-Jira Development Panel Integration](https://www.youtube.com/watch?v=VjVTOmMl85M&feature=youtu.be).
If you're using:
- GitLab.com and Jira Cloud, we recommend you enable this integration by installing the
[GitLab for Jira app](#gitlab-for-jira-app) from the Atlassian Marketplace, which offers a real-time
sync between GitLab and Jira.
- Self-managed GitLab, self-managed Jira, or both, configure the integration using
[Jira's DVCS Connector](#jira-dvcs-configuration), which syncs data hourly.
For an overview of how to configure Jira Development panel integration, see [Agile Management - GitLab Jira Development panel integration](https://www.youtube.com/watch?v=VjVTOmMl85M&feature=youtu.be).
We recommend that a GitLab group maintainer or group owner, or instance administrator (in the case of
self-managed GitLab) set up the integration to simplify administration.
| If you use Jira on: | GitLab.com customers need: | GitLab self-managed customers need: |
|-|-|-|
| [Atlassian cloud](https://www.atlassian.com/cloud) | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview) application installed from the [Atlassian Marketplace](https://marketplace.atlassian.com). This offers real-time sync between GitLab and Jira. | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview), using a workaround process. See a [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/268278) for more information. |
| Your own server | The Jira DVCS (distributed version control system) connector. This syncs data hourly. | The Jira DVCS connector. |
### Jira DVCS configuration
If you're using GitLab.com and Jira Cloud, use the
@ -169,7 +159,7 @@ If there was an issue with SSL/TLS, this error message is generated.
TLS issues that arise from a private certificate authority or self-signed
certificate [are resolved on the GitLab server](https://docs.gitlab.com/omnibus/settings/ssl.html#other-certificate-authorities),
as GitLab is the TLS client.
- The Jira Development Panel integration requires Jira to connect to GitLab, which
- The Jira Development panel integration requires Jira to connect to GitLab, which
causes Jira to be the TLS client. If your GitLab server's certificate is not
issued by a public certificate authority, the Java Truststore on Jira's server
needs to have the appropriate certificate added to it (such as your organization's

View file

@ -77,7 +77,7 @@ The following assumes you already have Vault installed and running.
This configuration is saved under the name of the role you are creating. In this case, we are creating a `demo` role. Later, we show how you can access this role through the Vault CLI.
WARNING:
If you're using a public GitLab instance (GitLab.com or any other instance publicly
If you're using a public GitLab instance (GitLab.com or any other instance publicly
accessible), it's paramount to specify the `bound_claims` to allow access only to
members of your group/project. Otherwise, anyone with a public account can access
your Vault instance.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -219,9 +219,21 @@ To upgrade your [GitLab tier](https://about.gitlab.com/pricing/):
When the purchase has been processed, you receive confirmation of your new subscription tier.
## See your billable users list
## See your subscription and billable users in GitLab.com
To see a list of your billable users on your GitLab group page go to **Settings > Billing**. This page provides information about your subscription and occupied seats for your group which is the list of billable users for your particular group.
To view information about your subscription and occupied seats:
1. Go to your group's **Settings > Billing** page.
1. In the **Seats currently in use** area, select **See usage**.
### Remove billable user
To remove a billable user:
1. Go to your group's **Settings > Billing** page.
1. In the **Seats currently in use** area, select **See usage**.
1. In the row for the user you want to remove, on the right side, select the ellipsis and **Remove user**.
1. Re-type the username and select **Remove user**.
## Subscription expiry

View file

@ -11,8 +11,8 @@ type: howto
GitLab administrators are responsible for the overall security of their instance. To assist, GitLab provides a Credentials inventory to keep track of all the credentials that can be used to access their self-managed instance.
Using Credentials inventory, you can see all the personal access tokens (PAT), SSH keys, and GPG keys
that exist in your GitLab instance. In addition, you can [revoke](#revoke-a-users-personal-access-token)
Using Credentials inventory, you can see all the personal access tokens (PAT), SSH keys, and GPG keys
that exist in your GitLab instance. In addition, you can [revoke](#revoke-a-users-personal-access-token)
and [delete](#delete-a-users-ssh-key) and see:
- Who they belong to.
@ -65,7 +65,7 @@ The instance then notifies the user.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
You can view all existing GPG in your GitLab instance by navigating to the
You can view all existing GPG in your GitLab instance by navigating to the
credentials inventory GPG Keys tab, as well as the following properties:
- Who the GPG key belongs to.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -311,7 +311,7 @@ request created to automatically solve the issue.
If this action is available:
1. Select the **Resolve with merge request** dropdown, then select **Resolve with merge request**.
![Create merge request from vulnerability](img/create_mr_from_vulnerability_v13_4.png)
A merge request is created. It that applies the solution to the source branch.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -263,6 +263,16 @@ npm publish
To view the package, go to your project's **Packages & Registries**.
You can also define `"publishConfig"` for your project in `package.json`. For example:
```json
{
"publishConfig": { "@foo:registry":" https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/" }
}
```
This forces the package to publish only to the specified registry.
If you try to publish a package [with a name that already exists](#publishing-packages-with-the-same-name-or-version) within
a given scope, you get a `403 Forbidden!` error.
@ -402,6 +412,9 @@ Due to a bug in npm 6.9.0, deleting distribution tags fails. Make sure your npm
## Troubleshooting
When troubleshooting npm issues, first run the same command with the `--verbose` flag to confirm
what registry you are hitting.
### Error running Yarn with the Package Registry for npm registry
If you are using [Yarn](https://classic.yarnpkg.com/en/) with the npm registry, you may get
@ -471,6 +484,8 @@ If you get this error, ensure that:
- Your token is not expired and has appropriate permissions.
- [Your token does not begin with `-`](https://gitlab.com/gitlab-org/gitlab/-/issues/235473).
- A package with the same name or version doesn't already exist within the given scope.
- Your NPM package name does not contain a dot `.`. This is a [known issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/10248)
in GitLab 11.9 and earlier.
- The scoped packages URL includes a trailing slash:
- Correct: `//gitlab.example.com/api/v4/packages/npm/`
- Incorrect: `//gitlab.example.com/api/v4/packages/npm`

View file

@ -330,7 +330,7 @@ project and should only have access to that project.
External users:
- Cannot create projects (including forks), groups, or personal snippets.
- Cannot create projects (including forks), groups, or snippets.
- Can only access public projects and projects to which they are explicitly granted access,
thus hiding all other internal or private ones from them (like being
logged out).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -6,51 +6,29 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Jira integrations **(FREE)**
GitLab can be integrated with [Jira](https://www.atlassian.com/software/jira).
If your organization uses [Jira](https://www.atlassian.com/software/jira) issues,
you can [migrate](../../../user/project/import/jira.md) your issues from Jira and work
exclusively in GitLab.
[Issues](../issues/index.md) are a tool for discussing ideas, and planning and tracking work.
However, your organization may already use Jira for these purposes, with extensive, established data
and business processes they rely on.
However, if you'd like to continue to use Jira, you can integrate it with GitLab.
Although you can [migrate](../../../user/project/import/jira.md) your Jira issues and work
exclusively in GitLab, you can also continue to use Jira by using the GitLab Jira integrations.
There are two ways to use GitLab with Jira:
## Integration types
- [Jira integration](jira.md). Connect a GitLab project
to a Jira instance. The Jira instance can be hosted by you or in [Atlassian cloud](https://www.atlassian.com/cloud).
- [Jira Development panel integration](../../../integration/jira_development_panel.md).
Connect all GitLab projects under a group or personal namespace.
There are two different Jira integrations that allow different types of cross-referencing between
GitLab activity and Jira issues, with additional features:
The integration you choose depends on the capabilities you require.
You can also install both at the same time.
- [Jira integration](jira.md), built in to GitLab. In a given GitLab project, it can be configured
to connect to any Jira instance, either hosted by you or hosted in
[Atlassian cloud](https://www.atlassian.com/cloud).
- [Jira development panel integration](../../../integration/jira_development_panel.md). Connects all
GitLab projects under a specified group or personal namespace.
Jira development panel integration configuration depends on whether:
- You're using GitLab.com or a self-managed GitLab instance.
- You're using Jira on [Atlassian cloud](https://www.atlassian.com/cloud) or on your own server.
| You use Jira on: | For the Jira development panel integration, GitLab.com customers need: | For the Jira development panel integration, GitLab self-managed customers need: |
|:-------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Atlassian cloud | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview) application installed from the [Atlassian Marketplace](https://marketplace.atlassian.com). | The [GitLab.com for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud?hosting=cloud&tab=overview), using a workaround process. See a [relevant issue](https://gitlab.com/gitlab-org/gitlab/-/issues/268278) for more information. |
| Your own server | The [Jira DVCS connector](../../../integration/jira_development_panel.md). | The [Jira DVCS connector](../../../integration/jira_development_panel.md). |
NOTE:
DVCS means distributed version control system.
## Feature comparison
The integration to use depends on the capabilities your require. You can install both at the same
time.
| Capability | Jira integration | Jira Development Panel integration |
|:----------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
| Mention of Jira issue ID in GitLab is automatically linked to that issue | Yes | No |
| Mention of Jira issue ID in GitLab issue/MR is reflected in the Jira issue | Yes, as a Jira comment with the GitLab issue/MR title and a link back to it. Its first mention also adds the GitLab page to the Jira issue under "Web links". | Yes, in the issue's Development panel |
| Mention of Jira issue ID in GitLab commit message is reflected in the issue | Yes. The entire commit message is added to the Jira issue as a comment and under "Web links", each with a link back to the commit in GitLab. | Yes, in the issue's Development panel and optionally with a custom comment on the Jira issue using Jira Smart Commits. |
| Mention of Jira issue ID in GitLab branch names is reflected in Jira issue | No | Yes, in the issue's Development panel |
| Record Jira time tracking information against an issue | No | Yes. Time can be specified via Jira Smart Commits. |
| Transition or close a Jira issue with a Git commit or merge request | Yes. Only a single transition type, typically configured to close the issue by setting it to Done. | Yes. Transition to any state using Jira Smart Commits. |
| Display a list of Jira issues | Yes **(PREMIUM)** | No |
| Create a Jira issue from a vulnerability or finding **(ULTIMATE)** | Yes | No |
| Capability | Jira integration | Jira Development panel integration |
|-|-|-|
| Mention a Jira issue ID in GitLab and a link to the Jira issue is created. | Yes. | No. |
| Mention a Jira issue ID in GitLab and the Jira issue shows the GitLab issue or merge request. | Yes. A Jira comment with the GitLab issue or MR title links to GitLab. The first mention is also added to the Jira issue under **Web links**. | Yes, in the issue's Development panel. |
| Mention a Jira issue ID in a GitLab commit message and the Jira issue shows the commit message. | Yes. The entire commit message is displayed in the Jira issue as a comment and under **Web links**. Each message links back to the commit in GitLab. | Yes, in the issue's Development panel and optionally with a custom comment on the Jira issue using Jira Smart Commits. |
| Mention a Jira issue ID in a GitLab branch name and the Jira issue shows the branch name. | No. | Yes, in the issue's Development panel. |
| Add Jira time tracking to an issue. | No. | Yes. Time can be specified using Jira Smart Commits. |
| Use a Git commit or merge request to transition or close a Jira issue. | Yes. Only a single transition type, typically configured to close the issue by setting it to Done. | Yes. Transition to any state using Jira Smart Commits. |
| Display a list of Jira issues. | Yes. **(PREMIUM)** | No. |
| Create a Jira issue from a vulnerability or finding. **(ULTIMATE)** | Yes. | No. |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
FactoryBot.define do
factory :in_product_marketing_email, class: 'Users::InProductMarketingEmail' do
user
track { 'create' }
series { 0 }
end
end

View file

@ -27,7 +27,6 @@ describe('HelpPopover', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('renders a link button with an icon question', () => {
@ -54,6 +53,14 @@ describe('HelpPopover', () => {
expect(findPopover().find('b').exists()).toBe(true);
});
describe('without title', () => {
it('does not render title', () => {
buildWrapper({ title: null });
expect(findPopover().find('span').exists()).toBe(false);
});
});
it('binds other popover options to the popover instance', () => {
const placement = 'bottom';

View file

@ -108,6 +108,7 @@ RSpec.describe User do
it { is_expected.to have_many(:merge_request_assignees).inverse_of(:assignee) }
it { is_expected.to have_many(:merge_request_reviewers).inverse_of(:reviewer) }
it { is_expected.to have_many(:created_custom_emoji).inverse_of(:creator) }
it { is_expected.to have_many(:in_product_marketing_emails) }
describe "#user_detail" do
it 'does not persist `user_detail` by default' do

View file

@ -0,0 +1,43 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Users::InProductMarketingEmail, type: :model do
describe 'associations' do
it { is_expected.to belong_to(:user) }
end
describe 'validations' do
subject { build(:in_product_marketing_email) }
it { is_expected.to validate_presence_of(:user) }
it { is_expected.to validate_presence_of(:track) }
it { is_expected.to validate_presence_of(:series) }
it { is_expected.to validate_uniqueness_of(:user_id).scoped_to([:track, :series]).with_message('has already been sent') }
end
describe '.without_track_or_series' do
let(:track) { 0 }
let(:series) { 0 }
let_it_be(:in_product_marketing_email) { create(:in_product_marketing_email, series: 0, track: 0) }
subject(:without_track_or_series) { described_class.without_track_or_series(track, series) }
context 'for the same track and series' do
it { is_expected.to be_empty }
end
context 'for a different track' do
let(:track) { 1 }
it { is_expected.to eq([in_product_marketing_email])}
end
context 'for a different series' do
let(:series) { 1 }
it { is_expected.to eq([in_product_marketing_email])}
end
end
end

View file

@ -309,7 +309,7 @@ RSpec.describe DesignManagement::SaveDesignsService do
end
context 'when the user is not allowed to upload designs' do
let(:user) { build_stubbed(:user) }
let(:user) { build_stubbed(:user, id: non_existing_record_id) }
it_behaves_like 'a service error'
end

View file

@ -139,7 +139,7 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
it { is_expected.not_to send_in_product_marketing_email }
end
context 'when the user has already received a marketing email as part of another group' do
context 'when the user has already received any marketing email in this batch' do
before do
other_group = create(:group)
other_group.add_developer(user)
@ -150,14 +150,50 @@ RSpec.describe Namespaces::InProductMarketingEmailsService, '#execute' do
it { is_expected.to send_in_product_marketing_email(user.id, anything, :create, 0) }
end
context 'when user has already received a specific series in a track before' do
before do
described_class.new(:create, described_class::INTERVAL_DAYS.index(interval)).execute
end
# For any group Notify is called exactly once
it { is_expected.to send_in_product_marketing_email(user.id, anything, :create, described_class::INTERVAL_DAYS.index(interval)) }
context 'when different series' do
let(:interval) { 5 }
let(:actions_completed) { { created_at: frozen_time - 6.days } }
it { is_expected.to send_in_product_marketing_email(user.id, anything, :create, described_class::INTERVAL_DAYS.index(interval)) }
end
context 'when different track' do
let(:track) { :verify }
let(:interval) { 1 }
let(:actions_completed) { { created_at: frozen_time - 2.days, git_write_at: frozen_time - 2.days } }
it { is_expected.to send_in_product_marketing_email(user.id, anything, :verify, described_class::INTERVAL_DAYS.index(interval)) }
end
end
it 'records sent emails' do
expect { subject }.to change { Users::InProductMarketingEmail.count }.by(1)
expect(
Users::InProductMarketingEmail.where(
user: user,
track: Users::InProductMarketingEmail.tracks[:create],
series: 0
)
).to exist
end
context 'when invoked with a non existing track' do
let(:track) { :foo }
before do
stub_const("#{described_class}::TRACKS", { foo: :git_write })
stub_const("#{described_class}::TRACKS", { bar: :git_write })
end
it { expect { subject }.to raise_error(NotImplementedError, 'No ability defined for track foo') }
it { expect { subject }.to raise_error(NotImplementedError, 'Track foo not defined') }
end
context 'when group is a sub-group' do