Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-07-28 21:08:53 +00:00
parent a66948df0c
commit 112fe349cb
81 changed files with 548 additions and 257 deletions

View file

@ -1031,6 +1031,7 @@ Gitlab/NamespacedClass:
- 'app/finders/joined_groups_finder.rb'
- 'app/finders/keys_finder.rb'
- 'app/finders/labels_finder.rb'
- 'app/finders/lfs_pointers_finder.rb'
- 'app/finders/license_template_finder.rb'
- 'app/finders/members_finder.rb'
- 'app/finders/merge_request_target_project_finder.rb'

View file

@ -28,6 +28,10 @@ export default {
GlLoadingIcon,
GlIcon,
UserAccessRoleBadge,
ComplianceFrameworkLabel: () =>
import(
'ee_component/vue_shared/components/compliance_framework_label/compliance_framework_label.vue'
),
itemCaret,
itemTypeIcon,
itemStats,
@ -67,6 +71,9 @@ export default {
hasAvatar() {
return this.group.avatarUrl !== null;
},
hasComplianceFramework() {
return Boolean(this.group.complianceFramework?.name);
},
isGroup() {
return this.group.type === 'group';
},
@ -82,6 +89,9 @@ export default {
microdata() {
return this.group.microdata || {};
},
complianceFramework() {
return this.group.complianceFramework;
},
},
methods: {
onClickRowGroup(e) {
@ -167,6 +177,13 @@ export default {
<user-access-role-badge v-if="group.permission" class="gl-mt-3">
{{ group.permission }}
</user-access-role-badge>
<compliance-framework-label
v-if="hasComplianceFramework"
class="gl-mt-3"
:name="complianceFramework.name"
:color="complianceFramework.color"
:description="complianceFramework.description"
/>
</div>
<div v-if="group.description" class="description">
<span

View file

@ -1,4 +1,5 @@
import { normalizeHeaders, parseIntPagination } from '../../lib/utils/common_utils';
import { isEmpty } from 'lodash';
import { normalizeHeaders, parseIntPagination } from '~/lib/utils/common_utils';
import { getGroupItemMicrodata } from './utils';
export default class GroupsStore {
@ -70,7 +71,7 @@ export default class GroupsStore {
? rawGroupItem.subgroup_count
: rawGroupItem.children_count;
return {
const groupItem = {
id: rawGroupItem.id,
name: rawGroupItem.name,
fullName: rawGroupItem.full_name,
@ -98,6 +99,16 @@ export default class GroupsStore {
pendingRemoval: rawGroupItem.marked_for_deletion,
microdata: this.showSchemaMarkup ? getGroupItemMicrodata(rawGroupItem) : {},
};
if (!isEmpty(rawGroupItem.compliance_management_framework)) {
groupItem.complianceFramework = {
name: rawGroupItem.compliance_management_framework.name,
color: rawGroupItem.compliance_management_framework.color,
description: rawGroupItem.compliance_management_framework.description,
};
}
return groupItem;
}
removeGroup(group, parentGroup) {

View file

@ -35,7 +35,6 @@ import GlFieldErrors from './gl_field_errors';
import initUserPopovers from './user_popovers';
import initBroadcastNotifications from './broadcast_notification';
import { initTopNav } from './nav';
import navEventHub, { EVENT_RESPONSIVE_TOGGLE } from './nav/event_hub';
import 'ee_else_ce/main_ee';
@ -203,11 +202,7 @@ $body.on('ajax:complete, ajax:beforeSend, submit', 'form', function ajaxComplete
});
$('.navbar-toggler').on('click', () => {
// The order is important. The `menu-expanded` is used as a source of truth for now.
// This can be simplified when the :combined_menu feature flag is removed.
// https://gitlab.com/gitlab-org/gitlab/-/issues/333180
$('.header-content').toggleClass('menu-expanded');
navEventHub.$emit(EVENT_RESPONSIVE_TOGGLE);
document.body.classList.toggle('top-nav-responsive-open');
});
/**

View file

@ -2,8 +2,7 @@
import { FREQUENT_ITEMS_PROJECTS, FREQUENT_ITEMS_GROUPS } from '~/frequent_items/constants';
import { BV_DROPDOWN_SHOW, BV_DROPDOWN_HIDE } from '~/lib/utils/constants';
import KeepAliveSlots from '~/vue_shared/components/keep_alive_slots.vue';
import eventHub, { EVENT_RESPONSIVE_TOGGLE } from '../event_hub';
import { resetMenuItemsActive, hasMenuExpanded } from '../utils';
import { resetMenuItemsActive } from '../utils';
import ResponsiveHeader from './responsive_header.vue';
import ResponsiveHome from './responsive_home.vue';
import TopNavContainerView from './top_nav_container_view.vue';
@ -33,25 +32,14 @@ export default {
},
},
created() {
eventHub.$on(EVENT_RESPONSIVE_TOGGLE, this.updateResponsiveOpen);
this.$root.$on(BV_DROPDOWN_SHOW, this.showMobileOverlay);
this.$root.$on(BV_DROPDOWN_HIDE, this.hideMobileOverlay);
this.updateResponsiveOpen();
},
beforeDestroy() {
eventHub.$off(EVENT_RESPONSIVE_TOGGLE, this.onToggle);
this.$root.$off(BV_DROPDOWN_SHOW, this.showMobileOverlay);
this.$root.$off(BV_DROPDOWN_HIDE, this.hideMobileOverlay);
},
methods: {
updateResponsiveOpen() {
if (hasMenuExpanded()) {
document.body.classList.add('top-nav-responsive-open');
} else {
document.body.classList.remove('top-nav-responsive-open');
}
},
onMenuItemClick({ view }) {
if (view) {
this.activeView = view;

View file

@ -1,5 +0,0 @@
import eventHubFactory from '~/helpers/event_hub_factory';
export const EVENT_RESPONSIVE_TOGGLE = 'top-nav-responsive-toggle';
export default eventHubFactory();

View file

@ -1,2 +0,0 @@
export const hasMenuExpanded = () =>
Boolean(document.querySelector('.header-content.menu-expanded'));

View file

@ -1,2 +1 @@
export * from './has_menu_expanded';
export * from './reset_menu_items_active';

View file

@ -162,6 +162,9 @@ export const IMAGE_STATUS_ALERT_TYPE = {
[DELETE_FAILED]: 'warning',
};
export const PACKAGE_DELETE_HELP_PAGE_PATH = helpPagePath('user/packages/container_registry', {
anchor: 'delete-images',
});
export const PACKAGE_DELETE_HELP_PAGE_PATH = helpPagePath(
'user/packages/container_registry/index',
{
anchor: 'delete-images',
},
);

View file

@ -188,7 +188,7 @@ export default {
<partial-cleanup-alert
v-if="showPartialCleanupWarning"
:run-cleanup-policies-help-page-path="config.runCleanupPoliciesHelpPagePath"
:cleanup-policies-help-page-path="config.cleanupPoliciesHelpPagePath"
:cleanup-policies-help-page-path="config.expirationPolicyHelpPagePath"
@dismiss="dismissPartialCleanupWarning"
/>

View file

@ -1,6 +1,13 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlFormGroup, GlButton, GlModal, GlToast, GlToggle, GlLink } from '@gitlab/ui';
import {
GlFormGroup,
GlButton,
GlModal,
GlToast,
GlToggle,
GlLink,
GlSafeHtmlDirective,
} from '@gitlab/ui';
import Vue from 'vue';
import { mapState, mapActions } from 'vuex';
import { helpPagePath } from '~/helpers/help_page_helper';
@ -18,6 +25,9 @@ export default {
GlToggle,
GlLink,
},
directives: {
SafeHtml: GlSafeHtmlDirective,
},
formLabels: {
createProject: __('Self monitoring'),
},
@ -137,7 +147,7 @@ export default {
</div>
<div class="settings-content">
<form name="self-monitoring-form">
<p ref="selfMonitoringFormText" v-html="selfMonitoringFormText"></p>
<p ref="selfMonitoringFormText" v-safe-html="selfMonitoringFormText"></p>
<gl-form-group>
<gl-toggle
v-model="selfMonitorEnabled"

View file

@ -27,17 +27,6 @@ $top-nav-hover-bg: var(--indigo-900-alpha-008, $indigo-900-alpha-008) !important
display: none;
}
.menu-expanded {
.more-icon {
display: none;
}
.close-icon {
display: block;
margin: auto;
}
}
.header-content {
width: 100%;
display: flex;
@ -103,18 +92,6 @@ $top-nav-hover-bg: var(--indigo-900-alpha-008, $indigo-900-alpha-008) !important
.navbar-collapse > ul.nav > li:not(.d-none) {
margin: 0 2px;
}
&.menu-expanded {
@include media-breakpoint-down(xs) {
.hide-when-menu-expanded {
display: none;
}
.navbar-collapse {
display: flex;
}
}
}
}
.navbar-collapse {
@ -673,19 +650,30 @@ $top-nav-hover-bg: var(--indigo-900-alpha-008, $indigo-900-alpha-008) !important
}
.top-nav-responsive-open {
.hide-when-top-nav-responsive-open {
@include media-breakpoint-down(xs) {
.more-icon {
display: none;
}
.close-icon {
display: block;
margin: auto;
}
@include media-breakpoint-down(xs) {
.navbar-collapse {
display: flex;
}
.hide-when-top-nav-responsive-open {
display: none !important;
}
}
.top-nav-responsive {
@include media-breakpoint-down(xs) {
.top-nav-responsive {
@include gl-display-block;
}
}
.navbar-gitlab .header-content .title-container {
flex: 0;
.navbar-gitlab .header-content .title-container {
flex: 0;
}
}
}

View file

@ -0,0 +1,36 @@
# frozen_string_literal: true
class LfsPointersFinder
def initialize(repository, path)
@repository = repository
@path = path
end
def execute
return [] unless ref
blob_ids = tree.blobs.map(&:id)
# When current endpoint is a Blob then `tree.blobs` will be empty, it means we need to analyze
# the current Blob in order to determine if it's a LFS object
blob_ids = Array.wrap(current_blob&.id) if blob_ids.empty?
Gitlab::Git::Blob.batch_lfs_pointers(repository, blob_ids).map(&:id)
end
private
attr_reader :repository, :path
def ref
repository.root_ref
end
def tree
repository.tree(ref, path)
end
def current_blob
repository.blob_at(ref, path)
end
end

View file

@ -59,8 +59,8 @@ module Projects
# @return [Array<[user_id, access_level]>]
def user_ids_and_access_levels_from_all_memberships
strong_memoize(:user_ids_and_access_levels_from_all_memberships) do
all_possible_avenues_of_membership.flat_map do |relation|
relation.pluck(*USER_ID_AND_ACCESS_LEVEL) # rubocop: disable CodeReuse/ActiveRecord
all_possible_avenues_of_membership.flat_map do |members|
apply_scopes(members).pluck(*USER_ID_AND_ACCESS_LEVEL) # rubocop: disable CodeReuse/ActiveRecord
end
end
end
@ -86,7 +86,7 @@ module Projects
members << Member.from_union(members_per_batch)
end
members.flatten
Member.from_union(members)
end
def project_owner_acting_as_maintainer
@ -120,6 +120,10 @@ module Projects
Arel.sql(column_alias)
)
end
def apply_scopes(members)
members
end
end
end
end

View file

@ -0,0 +1,20 @@
# frozen_string_literal: true
module Projects
module Members
class EffectiveAccessLevelPerUserFinder < EffectiveAccessLevelFinder
def initialize(project, user)
@project = project
@user = user
end
private
attr_reader :user
def apply_scopes(members)
super.where(user_id: user.id) # rubocop: disable CodeReuse/ActiveRecord
end
end
end
end

View file

@ -0,0 +1,22 @@
# frozen_string_literal: true
module AuthorizedProjectUpdate
class ProjectRecalculatePerUserService < ProjectRecalculateService
def initialize(project, user)
@project = project
@user = user
end
private
attr_reader :user
def apply_scopes(project_authorizations)
super.where(user_id: user.id) # rubocop: disable CodeReuse/ActiveRecord
end
def effective_access_levels
Projects::Members::EffectiveAccessLevelPerUserFinder.new(project, user).execute
end
end
end

View file

@ -26,7 +26,7 @@ module AuthorizedProjectUpdate
def current_authorizations
strong_memoize(:current_authorizations) do
project.project_authorizations
apply_scopes(project.project_authorizations)
.pluck(:user_id, :access_level) # rubocop: disable CodeReuse/ActiveRecord
end
end
@ -35,8 +35,7 @@ module AuthorizedProjectUpdate
strong_memoize(:fresh_authorizations) do
result = []
Projects::Members::EffectiveAccessLevelFinder.new(project)
.execute
effective_access_levels
.each_batch(of: BATCH_SIZE, column: :user_id) do |member_batch|
result += member_batch.pluck(:user_id, 'MAX(access_level)') # rubocop: disable CodeReuse/ActiveRecord
end
@ -76,5 +75,13 @@ module AuthorizedProjectUpdate
end
end
end
def apply_scopes(project_authorizations)
project_authorizations
end
def effective_access_levels
Projects::Members::EffectiveAccessLevelFinder.new(project).execute
end
end
end

View file

@ -5,7 +5,7 @@
%a.gl-sr-only.gl-accessibility{ href: "#content-body" } Skip to content
.container-fluid
.header-content
.title-container.hide-when-menu-expanded
.title-container.hide-when-top-nav-responsive-open
%h1.title
%span.gl-sr-only GitLab
= link_to root_path, title: _('Dashboard'), id: 'logo', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation') do

View file

@ -161,7 +161,7 @@ If the **primary** and **secondary** nodes have a checksum verification mismatch
![Project administration page](img/checksum-differences-admin-project-page.png)
1. Go to the project's repository directory on both **primary** and **secondary** nodes
(the path is usually `/var/opt/gitlab/git-data/repositories`). Note that if `git_data_dirs`
(the path is usually `/var/opt/gitlab/git-data/repositories`). If `git_data_dirs`
is customized, check the directory layout on your server to be sure:
```shell

View file

@ -94,7 +94,7 @@ follow these steps to avoid unnecessary data loss:
1. Until a [read-only mode](https://gitlab.com/gitlab-org/gitlab/-/issues/14609)
is implemented, updates must be prevented from happening manually to the
**primary**. Note that your **secondary** node still needs read-only
**primary**. Your **secondary** node still needs read-only
access to the **primary** node during the maintenance window:
1. At the scheduled time, using your cloud provider or your node's firewall, block

View file

@ -79,7 +79,7 @@ follow these steps to avoid unnecessary data loss:
1. Until a [read-only mode](https://gitlab.com/gitlab-org/gitlab/-/issues/14609)
is implemented, updates must be prevented from happening manually to the
**primary**. Note that your **secondary** node still needs read-only
**primary**. Your **secondary** node still needs read-only
access to the **primary** node during the maintenance window:
1. At the scheduled time, using your cloud provider or your node's firewall, block

View file

@ -101,12 +101,12 @@ From the perspective of a user performing Git operations:
- The **primary** site behaves as a full read-write GitLab instance.
- **Secondary** sites are read-only but proxy Git push operations to the **primary** site. This makes **secondary** sites appear to support push operations themselves.
To simplify the diagram, some necessary components are omitted. Note that:
To simplify the diagram, some necessary components are omitted.
- Git over SSH requires [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell) and OpenSSH.
- Git over HTTPS required [`gitlab-workhorse`](https://gitlab.com/gitlab-org/gitlab-workhorse).
Note that a **secondary** site needs two different PostgreSQL databases:
A **secondary** site needs two different PostgreSQL databases:
- A read-only database instance that streams data from the main GitLab database.
- [Another database instance](#geo-tracking-database) used internally by the **secondary** site to record what data has been replicated.

View file

@ -286,9 +286,9 @@ The two most obvious issues that can become apparent in the dashboard are:
- You are using a custom certificate or custom CA (see the [troubleshooting document](troubleshooting.md)).
- The instance is firewalled (check your firewall rules).
Please note that disabling a **secondary** site stops the synchronization process.
Disabling a **secondary** site stops the synchronization process.
Please note that if `git_data_dirs` is customized on the **primary** site for multiple
If `git_data_dirs` is customized on the **primary** site for multiple
repository shards you must duplicate the same configuration on each **secondary** site.
Point your users to the [Using a Geo Site guide](usage.md).

View file

@ -204,7 +204,7 @@ successfully, you must replicate their data using some other means.
|[Server-side Git hooks](../../server_hooks.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | No | |
|[Elasticsearch integration](../../../integration/elasticsearch.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | |
|[GitLab Pages](../../pages/index.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/589) | No | Via Object Storage provider if supported. **No** native Geo support (Beta). | |
|[Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/259694) | No | No | Blocked on [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). Note that replication of this cache is not needed for Disaster Recovery purposes because it can be recreated from external sources. |
|[Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/259694) | No | No | Blocked on [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). Replication of this cache is not needed for Disaster Recovery purposes because it can be recreated from external sources. |
|[Vulnerability Export](../../../user/application_security/vulnerability_report/#export-vulnerability-details) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | | Not planned because they are ephemeral and sensitive. They can be regenerated on demand. |
#### Limitation of verification for files in Object Storage

View file

@ -154,7 +154,7 @@ the **primary** database. Use the following as a guide.
1. Generate an MD5 hash of the desired password for the database user that the
GitLab application uses to access the read-replica database:
Note that the username (`gitlab` by default) is incorporated into the hash.
The username (`gitlab` by default) is incorporated into the hash.
```shell
gitlab-ctl pg-password-md5 gitlab
@ -203,7 +203,7 @@ the **primary** database. Use the following as a guide.
geo_postgresql['enable'] = false
##
## Disable all other services that aren't needed. Note that we had to enable
## Disable all other services that aren't needed. We had to enable
## geo_secondary_role to cause some configuration changes to postgresql, but
## the role enables single-node services by default.
##
@ -241,7 +241,7 @@ Configure the tracking database.
1. Generate an MD5 hash of the desired password for the database user that the
GitLab application uses to access the tracking database:
Note that the username (`gitlab_geo` by default) is incorporated into the
The username (`gitlab_geo` by default) is incorporated into the
hash.
```shell

View file

@ -242,7 +242,7 @@ the tracking database on port 5432.
1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
1. The reconfigure should automatically create the database. If needed, you can perform this task manually. Note that this task (whether run by itself or during reconfigure) requires the database user to be a superuser.
1. The reconfigure should automatically create the database. If needed, you can perform this task manually. This task (whether run by itself or during reconfigure) requires the database user to be a superuser.
```shell
gitlab-rake geo:db:create

View file

@ -952,7 +952,7 @@ result as you did at the start. For example:
{enforced="true",status="ok"} 4424.985419441742
```
Note that `enforced="true"` means that authentication is being enforced.
`enforced="true"` means that authentication is being enforced.
## Pack-objects cache **(FREE SELF)**
@ -1076,7 +1076,7 @@ cache hit and the average amount of storage used by cache files.
Entries older than `max_age` get evicted from the in-memory metadata
store, and deleted from disk.
Note that eviction does not interfere with ongoing requests, so it is OK
Eviction does not interfere with ongoing requests, so it is OK
for `max_age` to be less than the time it takes to do a fetch over a
slow connection. This is because Unix filesystems do not truly delete
a file until all processes that are reading the deleted file have

View file

@ -195,7 +195,7 @@ instructions only work on Omnibus-provided PostgreSQL:
```
Replace `<PRAEFECT_SQL_PASSWORD_HASH>` with the hash of the password you generated in the
preparation step. Note that it is prefixed with `md5` literal.
preparation step. It is prefixed with `md5` literal.
1. The PgBouncer that is shipped with Omnibus is configured to use [`auth_query`](https://www.pgbouncer.org/config.html#generic-settings)
and uses `pg_shadow_lookup` function. You need to create this function in `praefect_production`

View file

@ -80,7 +80,7 @@ GitLab displays your link in the **Menu > Admin > Monitoring > Metrics Dashboard
When setting up Grafana through the process above, no scope shows in the screen at
**Menu >** **{admin}** **Admin > Applications > GitLab Grafana**. However, the `read_user` scope is
required and is provided to the application automatically. Note that setting any scope other than
required and is provided to the application automatically. Setting any scope other than
`read_user` without also including `read_user` leads to this error when you try to log in using
GitLab as the OAuth provider:

View file

@ -48,7 +48,7 @@ lookups via database lookup.
As part of [setting up Geo](../geo/index.md#setup-instructions),
you are required to follow the steps outlined below for both the primary and
secondary nodes, but note that the `Write to "authorized keys" file` checkbox
secondary nodes, but the `Write to "authorized keys" file` checkbox
only needs to be unchecked on the primary node since it is reflected
automatically on the secondary if database replication is working.

View file

@ -41,7 +41,7 @@ which you can set it up:
the Pages daemon is installed, so you must share it through the network.
- Run the Pages daemon in the same server as GitLab, listening on the same IP
but on different ports. In that case, you must proxy the traffic with
a load balancer. If you choose that route note that you should use TCP load
a load balancer. If you choose that route, you should use TCP load
balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing), the
pages can't be served with user-provided certificates. For
HTTP it's OK to use HTTP or TCP load balancing.

View file

@ -41,7 +41,7 @@ which you can set it up:
the Pages daemon is installed, so you must share it through the network.
1. Run the Pages daemon in the same server as GitLab, listening on the same IP
but on different ports. In that case, you must proxy the traffic with
a load balancer. If you choose that route, note that you should use TCP load
a load balancer. If you choose that route, you should use TCP load
balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing), the
pages aren't able to be served with user-provided certificates. For
HTTP, it's OK to use HTTP or TCP load balancing.

View file

@ -889,7 +889,7 @@ with:
sudo gitlab-ctl stop patroni
```
Note that stopping or restarting Patroni service on the leader node will trigger the automatic failover. If you
Stopping or restarting Patroni service on the leader node will trigger the automatic failover. If you
want to signal Patroni to reload its configuration or restart PostgreSQL process without triggering the failover, you
must use the `reload` or `restart` sub-commands of `gitlab-ctl patroni` instead. These two sub-commands are wrappers of
the same `patronictl` commands.
@ -1015,7 +1015,7 @@ Here are a few key facts that you must consider before upgrading PostgreSQL:
- Upgrading PostgreSQL creates a new data directory with a new control data. From Patroni's perspective
this is a new cluster that needs to be bootstrapped again. Therefore, as part of the upgrade procedure,
the cluster state (stored in Consul) is wiped out. Once the upgrade is completed, Patroni
bootstraps a new cluster. **Note that this changes your _cluster ID_**.
bootstraps a new cluster. **This changes your _cluster ID_**.
- The procedures for upgrading leader and replicas are not the same. That is why it is important to use the
right procedure on each node.

View file

@ -21,7 +21,7 @@ There are 3 things that are checked to determine integrity.
1. Check for `config.lock` in the repository directory.
1. Check for any branch/references lock files in `refs/heads`.
It's important to note that the existence of `config.lock` or reference locks
The existence of `config.lock` or reference locks
alone do not necessarily indicate a problem. Lock files are routinely created
and removed as Git and GitLab perform operations on the repository. They serve
to prevent data integrity issues. However, if a Git operation is interrupted these

View file

@ -683,8 +683,6 @@ To make this work with Sentinel:
]
```
Note that:
- Redis URLs should be in the format: `redis://:PASSWORD@SENTINEL_PRIMARY_NAME`, where:
- `PASSWORD` is the plaintext password for the Redis instance.
- `SENTINEL_PRIMARY_NAME` is the Sentinel primary name set with `redis['master_name']`,
@ -731,7 +729,7 @@ redis_master_role['enable'] = true # enable only one of them
redis_replica_role['enable'] = true # enable only one of them
# When Redis primary or Replica role are enabled, the following services are
# enabled/disabled. Note that if Redis and Sentinel roles are combined, both
# enabled/disabled. If Redis and Sentinel roles are combined, both
# services are enabled.
# The following services are disabled

View file

@ -345,7 +345,7 @@ Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`.
The Internal Load Balancer is used to balance any internal connections the GitLab environment requires
such as connections to [PgBouncer](#configure-pgbouncer) and [Praefect](#configure-praefect) (Gitaly Cluster).
Note that it's a separate node from the External Load Balancer and shouldn't have any access externally.
It's a separate node from the External Load Balancer and shouldn't have any access externally.
The following IP will be used as an example:

View file

@ -347,7 +347,7 @@ Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`.
The Internal Load Balancer is used to balance any internal connections the GitLab environment requires
such as connections to [PgBouncer](#configure-pgbouncer) and [Praefect](#configure-praefect) (Gitaly Cluster).
Note that it's a separate node from the External Load Balancer and shouldn't have any access externally.
It's a separate node from the External Load Balancer and shouldn't have any access externally.
The following IP will be used as an example:

View file

@ -346,7 +346,7 @@ Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`.
The Internal Load Balancer is used to balance any internal connections the GitLab environment requires
such as connections to [PgBouncer](#configure-pgbouncer) and [Praefect](#configure-praefect) (Gitaly Cluster).
Note that it's a separate node from the External Load Balancer and shouldn't have any access externally.
It's a separate node from the External Load Balancer and shouldn't have any access externally.
The following IP will be used as an example:
@ -2086,7 +2086,7 @@ but with smaller performance requirements, several modifications can be consider
- Combining select nodes: Some nodes can be combined to reduce complexity at the cost of some performance:
- GitLab Rails and Sidekiq: Sidekiq nodes can be removed and the component instead enabled on the GitLab Rails nodes.
- PostgreSQL and PgBouncer: PgBouncer nodes can be removed and the component instead enabled on PostgreSQL with the Internal Load Balancer pointing to them instead.
- Reducing the node counts: Some node types do not need consensus and can run with fewer nodes (but more than one for redundancy). Note that this will also lead to reduced performance.
- Reducing the node counts: Some node types do not need consensus and can run with fewer nodes (but more than one for redundancy). This will also lead to reduced performance.
- GitLab Rails and Sidekiq: Stateless services don't have a minimum node count. Two are enough for redundancy.
- Gitaly and Praefect: A quorum is not strictly necessary. Two Gitaly nodes and two Praefect nodes are enough for redundancy.
- Running select components in reputable Cloud PaaS solutions: Select components of the GitLab setup can instead be run on Cloud Provider PaaS solutions. By doing this, additional dependent components can also be removed:

View file

@ -354,7 +354,7 @@ Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`.
The Internal Load Balancer is used to balance any internal connections the GitLab environment requires
such as connections to [PgBouncer](#configure-pgbouncer) and [Praefect](#configure-praefect) (Gitaly Cluster).
Note that it's a separate node from the External Load Balancer and shouldn't have any access externally.
It's a separate node from the External Load Balancer and shouldn't have any access externally.
The following IP will be used as an example:

View file

@ -338,7 +338,7 @@ Configure DNS for an alternate SSH hostname such as `altssh.gitlab.example.com`.
The Internal Load Balancer is used to balance any internal connections the GitLab environment requires
such as connections to [PgBouncer](#configure-pgbouncer) and [Praefect](#configure-praefect) (Gitaly Cluster).
Note that it's a separate node from the External Load Balancer and shouldn't have any access externally.
It's a separate node from the External Load Balancer and shouldn't have any access externally.
The following IP will be used as an example:

View file

@ -45,7 +45,7 @@ session by running:
ActiveRecord::Base.connection.execute('SET statement_timeout TO 0')
```
Note that this change only affects the current Rails console session and will
This change only affects the current Rails console session and will
not be persisted in the GitLab production environment or in the next Rails
console session.
@ -213,7 +213,7 @@ downtime. Otherwise skip to the next section.
exit
```
Note that if the Puma process terminates before you are able to run these
If the Puma process terminates before you are able to run these
commands, GDB will report an error. To buy more time, you can always raise the
Puma worker timeout. For omnibus users, you can edit `/etc/gitlab/gitlab.rb` and
increase it from 60 seconds to 600:

View file

@ -22,7 +22,7 @@ guidance of a Support Engineer, or running them in a test environment with a
backup of the instance ready to be restored, just in case.
WARNING:
Please also note that as GitLab changes, changes to the code are inevitable,
As GitLab changes, changes to the code are inevitable,
and so some scripts may not work as they once used to. These are not kept
up-to-date as these scripts/commands were added as they were found/needed. As
mentioned above, we recommend running these scripts under the supervision of a

View file

@ -135,7 +135,7 @@ and they will assist you with any issues you are having.
# source-style commands should also work
cd /srv/gitlab && bundle exec rake gitlab:check RAILS_ENV=production
# run GitLab check. Note that the output can be confusing and invalid because of the specific structure of GitLab installed via helm chart
# run GitLab check. The output can be confusing and invalid because of the specific structure of GitLab installed via helm chart
/usr/local/bin/gitlab-rake gitlab:check
# open console without entering pod

View file

@ -265,7 +265,7 @@ user.save!(validate: false)
This is not recommended, as validations are usually put in place to ensure the
integrity and consistency of user-provided data.
Note that a validation error will prevent the entire object from being saved to
A validation error will prevent the entire object from being saved to
the database. We'll see a little of this in the next section. If you're getting
a mysterious red banner in the GitLab UI when submitting a form, this can often
be the fastest way to get to the root of the problem.

View file

@ -199,7 +199,7 @@ To fix this problem:
git config --global http.sslCAInfo ~/.ssl/gitlab.domain.tld.crt
```
- Disable SSL verification in your Git client. Note that this intended as a
- Disable SSL verification in your Git client. This is intended as a
temporary measure, as it could be considered a security risk.
```shell

View file

@ -57,7 +57,7 @@ Available types for the `action` parameter, and the resources that might be affe
- Design
- Wiki page
Note that these options are in lower case.
These options are in lowercase.
### Target Types
@ -71,7 +71,7 @@ Available target types for the `target_type` parameter are:
- `snippet`
- `user`
Note that these options are in lower case.
These options are in lowercase.
### Date formatting

View file

@ -130,7 +130,7 @@ POST /features/:name
| `project` | string | no | A projects path, for example `gitlab-org/gitlab-foss` |
| `force` | boolean | no | Skip feature flag validation checks, such as a YAML definition |
Note that you can enable or disable a feature for a `feature_group`, a `user`,
You can enable or disable a feature for a `feature_group`, a `user`,
a `group`, and a `project` in a single API call.
```shell

View file

@ -33,7 +33,7 @@ To use this in a [`script` definition](../ci/yaml/index.md#script) inside
- The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable.
For example, the following job downloads the artifacts of the job with ID
`42`. Note that the command is wrapped into single quotes because it contains a
`42`. The command is wrapped in single quotes because it contains a
colon (`:`):
```yaml
@ -98,7 +98,7 @@ To use this in a [`script` definition](../ci/yaml/index.md#script) inside
- The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable.
For example, the following job downloads the artifacts of the `test` job
of the `main` branch. Note that the command is wrapped into single quotes
of the `main` branch. The command is wrapped in single quotes
because it contains a colon (`:`):
```yaml

View file

@ -85,7 +85,7 @@ Supported attributes:
## Get a blob from repository
Allows you to receive information about blob in repository like size and
content. Note that blob content is Base64 encoded. This endpoint can be accessed
content. Blob content is Base64 encoded. This endpoint can be accessed
without authentication if the repository is publicly accessible.
```plaintext
@ -149,7 +149,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/pr
## Compare branches, tags or commits
This endpoint can be accessed without authentication if the repository is
publicly accessible. Note that diffs could have an empty diff string if [diff limits](../development/diffs.md#diff-limits) are reached.
publicly accessible. Diffs can have an empty diff string if [diff limits](../development/diffs.md#diff-limits) are reached.
```plaintext
GET /projects/:id/repository/compare
@ -607,7 +607,7 @@ template: |
{% end %}
```
Note that when specifying the template you should use `template: |` and not
When specifying the template you should use `template: |` and not
`template: >`, as the latter doesn't preserve newlines in the template.
### Template data

View file

@ -24,7 +24,7 @@ in the following table.
## Get file from repository
Allows you to receive information about file in repository like name, size,
content. Note that file content is Base64 encoded. This endpoint can be accessed
content. File content is Base64 encoded. This endpoint can be accessed
without authentication if the repository is publicly accessible.
```plaintext

View file

@ -259,7 +259,7 @@ GET /projects/:id/services/buildkite
## Campfire
Send notifications about push events to Campfire chat rooms.
Note that [new users can no longer sign up for Campfire](https://basecamp.com/retired/campfire).
[New users can no longer sign up for Campfire](https://basecamp.com/retired/campfire).
### Create/Edit Campfire service

View file

@ -408,7 +408,7 @@ users. Either `password`, `reset_password`, or `force_random_password`
must be specified. If `reset_password` and `force_random_password` are
both `false`, then `password` is required.
Note that `force_random_password` and `reset_password` take priority
`force_random_password` and `reset_password` take priority
over `password`. In addition, `reset_password` and
`force_random_password` can be used together.
@ -1600,7 +1600,7 @@ Example response:
> Requires admin permissions.
> Token values are returned once. Make sure you save it - you can't access it again.
It creates a new impersonation token. Note that only administrators can do this.
It creates a new impersonation token. Only administrators can do this.
You are only able to create impersonation tokens to impersonate the user and perform
both API calls and Git reads and writes. The user can't see these tokens in their profile
settings page.

View file

@ -8,7 +8,7 @@ group: database
This document is a proposal to work towards reducing and limiting table sizes on GitLab.com. We establish a **measurable target** by limiting table size to a certain threshold. This will be used as an indicator to drive database focus and decision making. With GitLab.com growing, we continuously re-evaluate which tables need to be worked on to prevent or otherwise fix violations.
Note that this is not meant to be a hard rule but rather a strong indication that work needs to be done to break a table apart or otherwise reduce its size.
This is not meant to be a hard rule but rather a strong indication that work needs to be done to break a table apart or otherwise reduce its size.
This is meant to be read in context with the [Database Sharding blueprint](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64115),
which paints the bigger picture. This proposal here is thought to be part of the "debloating step" below, as we aim to reduce storage requirements and improve data modeling. Partitioning is part of the standard tool-belt: where possible, we can already use partitioning as a solution to cut physical table sizes significantly. Both will help to prepare efforts like decomposition (database usage is already optimized) and sharding (database is already partitioned along an identified data access dimension).
@ -124,7 +124,7 @@ In order to maintain and improve operational stability and lessen development bu
1. Indexes are smaller, can be maintained more efficiently and fit better into memory
1. Data migrations are easier to reason about, take less time to implement and execute
Note that this target is *pragmatic*: We understand table sizes depend on feature usage, code changes and other factors - which all change over time. We may not always find solutions where we can tightly limit the size of physical tables once and for all. That is acceptable though and we primarily aim to keep the situation on GitLab.com under control. We adapt our efforts to the situation present on GitLab.com and will re-evaluate frequently.
This target is *pragmatic*: We understand table sizes depend on feature usage, code changes and other factors - which all change over time. We may not always find solutions where we can tightly limit the size of physical tables once and for all. That is acceptable though and we primarily aim to keep the situation on GitLab.com under control. We adapt our efforts to the situation present on GitLab.com and will re-evaluate frequently.
While there are changes we can make that lead to a constant maximum physical table size over time, this doesn't need to be the case necessarily. Consider for example hash partitioniong, which breaks a table down into a static number of partitions. With data growth over time, individual partitions will also grow in size and may eventually reach the threshold size again. We strive to get constant table sizes, but it is acceptable to ship easier solutions that don't have this characteristic but improve the situation for a considerable amount of time.

View file

@ -64,7 +64,7 @@ We already use Database Lab from [postgres.ai](https://postgres.ai/), which is a
Internally, this is based on ZFS and implements a "thin-cloning technology". That is, ZFS snapshots are being used to clone the data and it exposes a full read/write PostgreSQL cluster based on the cloned data. This is called a *thin clone*. It is rather short lived and is going to be destroyed again shortly after we are finished using it.
It is important to note that a thin clone is fully read/write. This allows us to execute migrations on top of it.
A thin clone is fully read/write. This allows us to execute migrations on top of it.
Database Lab provides an API we can interact with to manage thin clones. In order to automate the migration and query testing, we add steps to the `gitlab/gitlab-org` CI pipeline. This triggers automation that performs the following steps for a given merge request:

View file

@ -79,7 +79,7 @@ GitLab CI/CD supports numerous configuration options:
| [Optimize GitLab and GitLab Runner for large repositories](large_repositories/index.md) | Recommended strategies for handling large repositories. |
| [`.gitlab-ci.yml` full reference](yaml/index.md) | All the attributes you can use with GitLab CI/CD. |
Note that certain operations can only be performed according to the
Certain operations can only be performed according to the
[user](../user/permissions.md#gitlab-cicd-permissions) and [job](../user/permissions.md#job-permissions) permissions.
## Feature set

View file

@ -73,6 +73,13 @@ Do not use **Developer permissions**. A user who is assigned the Developer role
See [the Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/d/disable-disabled) for guidance.
Use **inactive** or **off** instead. ([Vale](../testing.md#vale) rule: [`InclusionAbleism.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionAbleism.yml))
## earlier
Use when talking about version numbers.
- Avoid: In GitLab 14.1 and lower.
- Use instead: In GitLab 14.1 and earlier.
## easily
Do not use. If the user doesn't find the process to be easy, we lose their trust.
@ -151,6 +158,13 @@ Do not use. If the user doesn't find the feature or process to be handy, we lose
Do not use. Instead, direct readers to the GitLab [reference architectures](../../../administration/reference_architectures/index.md) for information about configuring GitLab for handling greater amounts of users.
## higher
Do not use when talking about version numbers.
- Avoid: In GitLab 14.1 and higher.
- Use instead: In GitLab 14.1 and later.
## I
Do not use first-person singular. Use **you**, **we**, or **us** instead. ([Vale](../testing.md#vale) rule: [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml))
@ -171,10 +185,24 @@ Lowercase.
Lowercase.
## later
Use when talking about version numbers.
- Avoid: In GitLab 14.1 and higher.
- Use instead: In GitLab 14.1 and later.
## log in, log on
Do not use. Use [sign in](#sign-in) instead. If the user interface has **Log in**, you can use it.
## lower
Do not use when talking about version numbers.
- Avoid: In GitLab 14.1 and lower.
- Use instead: In GitLab 14.1 and earlier.
## Maintainer
When writing about the Maintainer role:

View file

@ -6,9 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Akismet **(FREE)**
GitLab leverages [Akismet](https://akismet.com/) to protect against spam.
GitLab uses Akismet to prevent the creation of spam issues on public projects. Issues
created through the web UI or the API can be submitted to Akismet for review.
GitLab uses [Akismet](https://akismet.com/) to prevent the creation of
spam issues on public projects. Issues created through the web UI or the API can be submitted to
Akismet for review.
Detected spam is rejected, and an entry is added in the **Spam Log** section of the
Admin page.
@ -19,7 +19,10 @@ NOTE:
In GitLab 8.11 and later, all issues are submitted to Akismet.
In earlier GitLab versions, this only applied to API and non-project members.
## Configuration
Akismet configuration is available to users on self-managed GitLab. Akismet is already enabled on
GitLab SaaS (GitLab.com), where it's configuration and management are handled by GitLab Inc.
## Configuration **(FREE SELF)**
To use Akismet:
@ -35,7 +38,7 @@ To use Akismet:
![Screenshot of Akismet settings](img/akismet_settings.png)
## Training
## Training **(FREE SELF)**
To better differentiate between spam and ham, you can train the Akismet
filter whenever there is a false positive or false negative.

View file

@ -0,0 +1,35 @@
---
stage: none
group: unassigned
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
---
# Developer Certificate of Origin Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors, 1 Letterman Drive, Suite D4700, San Francisco, CA 94129, USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or
(b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or
(c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.
(d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.
## License
All documentation content is licensed to this project under [Creative Commons: CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
All contributions to this project are licensed under the following license:
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -36,13 +36,13 @@ If you receive a license file from GitLab (for example a new trial), you can upl
The first time you visit your GitLab EE installation signed in as an administrator,
you should see a note urging you to upload a license with a link that takes you
to the **License** area.
to the **Subscriptions** area.
Otherwise, to manually go to the **License** area:
Otherwise, to manually go to the **Subscriptions** area:
1. On the top bar, select **Menu >** **{admin}** **Admin**.
1. On the left sidebar, select **License**, and select **Upload New License**.
1. Sign in to your GitLab self-managed instance.
1. From the top menu, select the Admin Area **{admin}**.
1. From the left sidebar, select **Subscriptions**, and select **Upload a license file**.
- *If you've received a `.gitlab-license` file:*
1. Download the license file to your local machine.
@ -91,7 +91,7 @@ is active until the end of the license period. When that period ends, the
instance will [fall back](#what-happens-when-your-license-expires) to Free-only
functionality.
You can review the license details at any time by going to **Admin Area > License**.
You can review the license details at any time by going to **Admin Area > Subscription**.
## Notification before the license expires
@ -111,12 +111,12 @@ before this occurs.
- To resume functionality, upload a new license.
- To fall back to Free features, delete all expired licenses.
### Remove a license
### Remove a license file
To remove a license from a self-managed instance:
To remove a license file from a self-managed instance:
1. On the top bar, select **Menu >** **{admin}** **Admin** to go to the [Admin Area](index.md).
1. On the left sidebar, select **License**.
1. From the top menu, select the Admin Area **{admin}**.
1. From the left sidebar, select **Subscriptions**
1. Select **Remove license**.
These steps may need to be repeated to completely remove all licenses, including those applied in the past.
@ -134,7 +134,7 @@ The banner disappears after the new license becomes active.
## Troubleshooting
### There is no License tab in the Admin Area
### There is no Subscription tab in the Admin Area
If you originally installed Community Edition rather than Enterprise Edition you must
[upgrade to Enterprise Edition](../../update/index.md#community-to-enterprise-edition)

View file

@ -423,6 +423,21 @@ CLI (`dotnet`):
- `nuget install`: Install a package from the registry.
- `dotnet add`: Install a package from the registry.
## Example project
For an example, see the Guided Exploration project
[Utterly Automated Software and Artifact Versioning with GitVersion](https://gitlab.com/guided-explorations/devops-patterns/utterly-automated-versioning).
This project:
- Generates NuGet packages by the `msbuild` method.
- Generates NuGet packages by the `nuget.exe` method.
- Uses GitLab releases and `release-cli` in connection with NuGet packaging.
- Uses a tool called [GitVersion](https://gitversion.net/)
to automatically determine and increment versions for the NuGet package in complex repositories.
You can copy this example project to your own group or instance for testing. See the project page
for more details on what other GitLab CI patterns are demonstrated.
## Troubleshooting
To improve performance, NuGet caches files related to a package. If you encounter issues, clear the

View file

@ -47,16 +47,6 @@ module ExtractsPath
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
def lfs_blob_ids
blob_ids = tree.blobs.map(&:id)
# When current endpoint is a Blob then `tree.blobs` will be empty, it means we need to analyze
# the current Blob in order to determine if it's a LFS object
blob_ids = Array.wrap(@repo.blob_at(@commit.id, @path)&.id) if blob_ids.empty? # rubocop:disable Gitlab/ModuleWithInstanceVariables
@lfs_blob_ids = Gitlab::Git::Blob.batch_lfs_pointers(repository_container.repository, blob_ids).map(&:id) # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
private
# Override in controllers to determine which actions are subject to the redirect

View file

@ -24,10 +24,13 @@ module Gitlab
end
def log_error!(extra_context = {})
error = LimitExceededError.new(message)
# TODO: change this to Gitlab::ErrorTracking.log_exception(error, extra_context)
# https://gitlab.com/gitlab-org/gitlab/issues/32906
::Gitlab::ErrorTracking.track_exception(error, extra_context)
::Gitlab::ErrorTracking.log_exception(limit_exceeded_error, extra_context)
end
protected
def limit_exceeded_error
LimitExceededError.new(message)
end
end
end

View file

@ -24,7 +24,7 @@ module Gitlab
name = :gitlab_ci_pipeline_size_builds
comment = 'Pipeline size'
labels = { source: nil }
buckets = [0, 1, 5, 10, 20, 50, 100, 200, 500, 1000]
buckets = [0, 1, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 3000]
::Gitlab::Metrics.histogram(name, comment, labels, buckets)
end

View file

@ -14,8 +14,8 @@ module Gitlab
@observations = []
end
def observe(migration, &block)
observation = Observation.new(migration)
def observe(version:, name:, &block)
observation = Observation.new(version, name)
observation.success = true
exception = nil

View file

@ -4,7 +4,8 @@ module Gitlab
module Database
module Migrations
Observation = Struct.new(
:migration,
:version,
:name,
:walltime,
:success,
:total_database_size_change,

View file

@ -23,7 +23,7 @@ module Gitlab
end
def record(observation)
File.rename(@file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.migration}-query-details.json"))
File.rename(@file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}-query-details.json"))
end
def record_sql_event(_name, started, finished, _unique_id, payload)

View file

@ -18,7 +18,7 @@ module Gitlab
end
def record(observation)
File.rename(@log_file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.migration}.log"))
File.rename(@log_file_path, File.join(Instrumentation::RESULT_DIR, "#{observation.version}_#{observation.name}.log"))
end
end
end

View file

@ -220,7 +220,7 @@ namespace :gitlab do
instrumentation = Gitlab::Database::Migrations::Instrumentation.new
pending_migrations.each do |migration|
instrumentation.observe(migration.version) do
instrumentation.observe(version: migration.version, name: migration.name) do
ActiveRecord::Migrator.new(:up, ctx.migrations, ctx.schema_migration, migration.version).run
end
end

View file

@ -0,0 +1,44 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe LfsPointersFinder do
subject(:finder) { described_class.new(repository, path) }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:repository) { project.repository }
let(:path) { nil }
describe '#execute' do
subject { finder.execute }
let(:expected_blob_id) { '0c304a93cb8430108629bbbcaa27db3343299bc0' }
context 'when path has no LFS files' do
it { is_expected.to eq([]) }
end
context 'when path points to LFS file' do
let(:path) { 'files/lfs/lfs_object.iso' }
it 'returns LFS blob ids' do
is_expected.to eq([expected_blob_id])
end
end
context 'when path points to directory with LFS files' do
let(:path) { 'files/lfs/' }
it 'returns LFS blob ids' do
is_expected.to eq([expected_blob_id])
end
end
context 'when repository is empty' do
let(:project) { create(:project, :empty_repo) }
it { is_expected.to eq([]) }
end
end
end

View file

@ -0,0 +1,38 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Projects::Members::EffectiveAccessLevelPerUserFinder, '#execute' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:user) { create(:user) }
# The result set is being converted to json just for the ease of testing.
subject { described_class.new(project, user).execute.as_json }
context 'a combination of all possible avenues of membership' do
let_it_be(:another_user) { create(:user) }
let_it_be(:shared_with_group) { create(:group) }
before do
create(:project_group_link, :maintainer, project: project, group: shared_with_group)
create(:group_group_link, :reporter, shared_group: project.group, shared_with_group: shared_with_group)
shared_with_group.add_maintainer(user)
shared_with_group.add_maintainer(another_user)
group.add_guest(user)
group.add_guest(another_user)
project.add_developer(user)
project.add_developer(another_user)
end
it 'includes the highest access level from all avenues of memberships for the specific user alone' do
expect(subject).to eq(
[{
'user_id' => user.id,
'access_level' => Gitlab::Access::MAINTAINER, # From project_group_link
'id' => nil
}]
)
end
end
end

View file

@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import GroupFolder from '~/groups/components/group_folder.vue';
import GroupItem from '~/groups/components/group_item.vue';
import ItemActions from '~/groups/components/item_actions.vue';
@ -22,8 +22,7 @@ describe('GroupItemComponent', () => {
beforeEach(() => {
wrapper = createComponent();
return Vue.nextTick();
return waitForPromises();
});
afterEach(() => {

View file

@ -3,16 +3,10 @@ import ResponsiveApp from '~/nav/components/responsive_app.vue';
import ResponsiveHeader from '~/nav/components/responsive_header.vue';
import ResponsiveHome from '~/nav/components/responsive_home.vue';
import TopNavContainerView from '~/nav/components/top_nav_container_view.vue';
import eventHub, { EVENT_RESPONSIVE_TOGGLE } from '~/nav/event_hub';
import { resetMenuItemsActive } from '~/nav/utils/reset_menu_items_active';
import KeepAliveSlots from '~/vue_shared/components/keep_alive_slots.vue';
import { TEST_NAV_DATA } from '../mock_data';
const HTML_HEADER_CONTENT = '<div class="header-content"></div>';
const HTML_MENU_EXPANDED = '<div class="menu-expanded"></div>';
const HTML_HEADER_WITH_MENU_EXPANDED =
'<div></div><div class="header-content menu-expanded"></div>';
describe('~/nav/components/responsive_app.vue', () => {
let wrapper;
@ -26,13 +20,10 @@ describe('~/nav/components/responsive_app.vue', () => {
},
});
};
const triggerResponsiveToggle = () => eventHub.$emit(EVENT_RESPONSIVE_TOGGLE);
const findHome = () => wrapper.findComponent(ResponsiveHome);
const findMobileOverlay = () => wrapper.find('[data-testid="mobile-overlay"]');
const findSubviewHeader = () => wrapper.findComponent(ResponsiveHeader);
const findSubviewContainer = () => wrapper.findComponent(TopNavContainerView);
const hasBodyResponsiveOpen = () => document.body.classList.contains('top-nav-responsive-open');
const hasMobileOverlayVisible = () => findMobileOverlay().classes('mobile-nav-open');
beforeEach(() => {
@ -57,23 +48,6 @@ describe('~/nav/components/responsive_app.vue', () => {
});
});
it.each`
bodyHtml | expectation
${''} | ${false}
${HTML_HEADER_CONTENT} | ${false}
${HTML_MENU_EXPANDED} | ${false}
${HTML_HEADER_WITH_MENU_EXPANDED} | ${true}
`(
'with responsive toggle event and html set to $bodyHtml, responsive open = $expectation',
({ bodyHtml, expectation }) => {
document.body.innerHTML = bodyHtml;
triggerResponsiveToggle();
expect(hasBodyResponsiveOpen()).toBe(expectation);
},
);
it.each`
events | expectation
${[]} | ${false}
@ -96,17 +70,6 @@ describe('~/nav/components/responsive_app.vue', () => {
);
});
describe('with menu expanded in body', () => {
beforeEach(() => {
document.body.innerHTML = HTML_HEADER_WITH_MENU_EXPANDED;
createComponent();
});
it('sets the body responsive open', () => {
expect(hasBodyResponsiveOpen()).toBe(true);
});
});
const projectsContainerProps = {
containerClass: 'gl-px-3',
frequentItemsDropdownType: ResponsiveApp.FREQUENT_ITEMS_PROJECTS.namespace,
@ -159,17 +122,4 @@ describe('~/nav/components/responsive_app.vue', () => {
});
});
});
describe('when destroyed', () => {
beforeEach(() => {
createComponent();
wrapper.destroy();
});
it('responsive toggle event does nothing', () => {
triggerResponsiveToggle();
expect(hasBodyResponsiveOpen()).toBe(false);
});
});
});

View file

@ -335,7 +335,7 @@ describe('Details Page', () => {
describe('Partial Cleanup Alert', () => {
const config = {
runCleanupPoliciesHelpPagePath: 'foo',
cleanupPoliciesHelpPagePath: 'bar',
expirationPolicyHelpPagePath: 'bar',
userCalloutsPath: 'call_out_path',
userCalloutId: 'call_out_id',
showUnfinishedTagCleanupCallout: true,
@ -367,7 +367,7 @@ describe('Details Page', () => {
expect(findPartialCleanupAlert().props()).toEqual({
runCleanupPoliciesHelpPagePath: config.runCleanupPoliciesHelpPagePath,
cleanupPoliciesHelpPagePath: config.cleanupPoliciesHelpPagePath,
cleanupPoliciesHelpPagePath: config.expirationPolicyHelpPagePath,
});
});

View file

@ -213,20 +213,4 @@ RSpec.describe ExtractsPath do
expect(extract_ref_without_atom('foo.atom')).to eq(nil)
end
end
describe '#lfs_blob_ids' do
let(:tag) { @project.repository.add_tag(@project.owner, 'my-annotated-tag', 'master', 'test tag') }
let(:ref) { tag.target }
let(:params) { { ref: ref, path: 'README.md' } }
before do
@project = create(:project, :repository)
end
it 'handles annotated tags' do
assign_ref_vars
expect(lfs_blob_ids).to eq([])
end
end
end

View file

@ -85,7 +85,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Chain::Limit::Deployments do
end
it 'logs the error' do
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
instance_of(Gitlab::Ci::Limit::LimitExceededError),
project_id: project.id, plan: namespace.actual_plan_name
)

View file

@ -5,14 +5,15 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
describe '#observe' do
subject { described_class.new }
let(:migration) { 1234 }
let(:migration_name) { 'test' }
let(:migration_version) { '12345' }
it 'executes the given block' do
expect { |b| subject.observe(migration, &b) }.to yield_control
expect { |b| subject.observe(version: migration_version, name: migration_name, &b) }.to yield_control
end
context 'behavior with observers' do
subject { described_class.new(observers).observe(migration) {} }
subject { described_class.new(observers).observe(version: migration_version, name: migration_name) {} }
let(:observers) { [observer] }
let(:observer) { instance_double('Gitlab::Database::Migrations::Observers::MigrationObserver', before: nil, after: nil, record: nil) }
@ -21,7 +22,7 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
expect(observer).to receive(:before).ordered
expect(observer).to receive(:after).ordered
expect(observer).to receive(:record).ordered do |observation|
expect(observation.migration).to eq(migration)
expect(observation.version).to eq(migration_version)
end
subject
@ -47,7 +48,7 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
end
context 'on successful execution' do
subject { described_class.new.observe(migration) {} }
subject { described_class.new.observe(version: migration_version, name: migration_name) {} }
it 'records walltime' do
expect(subject.walltime).not_to be_nil
@ -58,12 +59,16 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
end
it 'records the migration version' do
expect(subject.migration).to eq(migration)
expect(subject.version).to eq(migration_version)
end
it 'records the migration name' do
expect(subject.name).to eq(migration_name)
end
end
context 'upon failure' do
subject { described_class.new.observe(migration) { raise 'something went wrong' } }
subject { described_class.new.observe(version: migration_version, name: migration_name) { raise 'something went wrong' } }
it 'raises the exception' do
expect { subject }.to raise_error(/something went wrong/)
@ -73,7 +78,7 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
subject { instance.observations.first }
before do
instance.observe(migration) { raise 'something went wrong' }
instance.observe(version: migration_version, name: migration_name) { raise 'something went wrong' }
rescue StandardError
# ignore
end
@ -89,7 +94,11 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
end
it 'records the migration version' do
expect(subject.migration).to eq(migration)
expect(subject.version).to eq(migration_version)
end
it 'records the migration name' do
expect(subject.name).to eq(migration_name)
end
end
end
@ -101,8 +110,8 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
let(:migration2) { double('migration2', call: nil) }
it 'records observations for all migrations' do
subject.observe('migration1') {}
subject.observe('migration2') { raise 'something went wrong' } rescue nil
subject.observe(version: migration_version, name: migration_name) {}
subject.observe(version: migration_version, name: migration_name) { raise 'something went wrong' } rescue nil
expect(subject.observations.size).to eq(2)
end

View file

@ -4,14 +4,15 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::QueryDetails do
subject { described_class.new }
let(:observation) { Gitlab::Database::Migrations::Observation.new(migration) }
let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
let(:connection) { ActiveRecord::Base.connection }
let(:query) { "select date_trunc('day', $1::timestamptz) + $2 * (interval '1 hour')" }
let(:query_binds) { [Time.current, 3] }
let(:directory_path) { Dir.mktmpdir }
let(:log_file) { "#{directory_path}/#{migration}-query-details.json" }
let(:log_file) { "#{directory_path}/#{migration_version}_#{migration_name}-query-details.json" }
let(:query_details) { Gitlab::Json.parse(File.read(log_file)) }
let(:migration) { 20210422152437 }
let(:migration_version) { 20210422152437 }
let(:migration_name) { 'test' }
before do
stub_const('Gitlab::Database::Migrations::Instrumentation::RESULT_DIR', directory_path)

View file

@ -4,12 +4,13 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::QueryLog do
subject { described_class.new }
let(:observation) { Gitlab::Database::Migrations::Observation.new(migration) }
let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
let(:connection) { ActiveRecord::Base.connection }
let(:query) { 'select 1' }
let(:directory_path) { Dir.mktmpdir }
let(:log_file) { "#{directory_path}/current.log" }
let(:migration) { 20210422152437 }
let(:migration_version) { 20210422152437 }
let(:migration_name) { 'test' }
before do
stub_const('Gitlab::Database::Migrations::Instrumentation::RESULT_DIR', directory_path)
@ -22,7 +23,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryLog do
it 'writes a file with the query log' do
observe
expect(File.read("#{directory_path}/#{migration}.log")).to include(query)
expect(File.read("#{directory_path}/#{migration_version}_#{migration_name}.log")).to include(query)
end
it 'does not change the default logger' do

View file

@ -0,0 +1,99 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe AuthorizedProjectUpdate::ProjectRecalculatePerUserService, '#execute' do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:another_user) { create(:user) }
subject(:execute) { described_class.new(project, user).execute }
it 'returns success' do
expect(execute.success?).to eq(true)
end
context 'when there are no changes to be made' do
it 'does not change authorizations' do
expect { execute }.not_to(change { ProjectAuthorization.count })
end
end
context 'when there are changes to be made' do
context 'when addition is required' do
before do
project.add_developer(user)
project.add_developer(another_user)
project.project_authorizations.where(user: [user, another_user]).delete_all
end
it 'adds a new authorization record for the specific user' do
expect { execute }.to(
change { project.project_authorizations.where(user: user).count }
.from(0).to(1)
)
end
it 'does not add a new authorization record for the other user' do
expect { execute }.not_to(
change { project.project_authorizations.where(user: another_user).count }
)
end
it 'adds a new authorization record with the correct access level for the specific user' do
execute
project_authorization = project.project_authorizations.where(
user: user,
access_level: Gitlab::Access::DEVELOPER
)
expect(project_authorization).to exist
end
end
context 'when removal is required' do
before do
create(:project_authorization, user: user, project: project)
create(:project_authorization, user: another_user, project: project)
end
it 'removes the authorization record for the specific user' do
expect { execute }.to(
change { project.project_authorizations.where(user: user).count }
.from(1).to(0)
)
end
it 'does not remove the authorization record for the other user' do
expect { execute }.not_to(
change { project.project_authorizations.where(user: another_user).count }
)
end
end
context 'when an update in access level is required' do
before do
project.add_developer(user)
project.add_developer(another_user)
project.project_authorizations.where(user: [user, another_user]).delete_all
create(:project_authorization, project: project, user: user, access_level: Gitlab::Access::GUEST)
create(:project_authorization, project: project, user: another_user, access_level: Gitlab::Access::GUEST)
end
it 'updates the authorization of the specific user to the correct access level' do
expect { execute }.to(
change { project.project_authorizations.find_by(user: user).access_level }
.from(Gitlab::Access::GUEST).to(Gitlab::Access::DEVELOPER)
)
end
it 'does not update the authorization of the other user to the correct access level' do
expect { execute }.not_to(
change { project.project_authorizations.find_by(user: another_user).access_level }
.from(Gitlab::Access::GUEST)
)
end
end
end
end

View file

@ -276,8 +276,8 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
let(:ctx) { double('ctx', migrations: all_migrations, schema_migration: double, get_all_versions: existing_versions) }
let(:instrumentation) { instance_double(Gitlab::Database::Migrations::Instrumentation, observations: observations) }
let(:existing_versions) { [1] }
let(:all_migrations) { [double('migration1', version: 1), pending_migration] }
let(:pending_migration) { double('migration2', version: 2) }
let(:all_migrations) { [double('migration1', version: 1, name: 'test'), pending_migration] }
let(:pending_migration) { double('migration2', version: 2, name: 'test') }
let(:filename) { Gitlab::Database::Migrations::Instrumentation::STATS_FILENAME }
let(:result_dir) { Dir.mktmpdir }
let(:observations) { %w[some data] }
@ -303,7 +303,7 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
end
it 'instruments the pending migration' do
expect(instrumentation).to receive(:observe).with(2).and_yield
expect(instrumentation).to receive(:observe).with(version: 2, name: 'test').and_yield
subject
end

View file

@ -15,7 +15,6 @@ RSpec.describe 'projects/tree/show' do
before do
assign(:project, project)
assign(:repository, repository)
assign(:lfs_blob_ids, [])
allow(view).to receive(:can?).and_return(true)
allow(view).to receive(:can_collaborate_with_project?).and_return(true)