Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-08-08 15:10:32 +00:00
parent 61cf5b32c5
commit 3de2ce7c6b
55 changed files with 452 additions and 316 deletions

View File

@ -1 +1 @@
448304d500ab91dca193a21094319d38e22f60a7
6bb5f6969910ce5010f1c894ee671a86e656e6da

View File

@ -292,7 +292,7 @@
"project": {
"description": "Path to the project, e.g. `group/project`, or `group/sub-group/project`.",
"type": "string",
"pattern": "\\S/\\S"
"pattern": "\\S/\\S|\\$(\\S+)"
},
"ref": {
"description": "Branch/Tag/Commit-hash for the target project.",

View File

@ -1,8 +1,8 @@
import { __ } from '~/locale';
import { __, s__ } from '~/locale';
export default (IssuableTokenKeys, disableTargetBranchFilter = false) => {
const reviewerToken = {
formattedKey: __('Reviewer'),
formattedKey: s__('SearchToken|Reviewer'),
key: 'reviewer',
type: 'string',
param: 'username',

View File

@ -1,5 +1,5 @@
import { flattenDeep } from 'lodash';
import { __ } from '~/locale';
import { __, s__ } from '~/locale';
import FilteredSearchTokenKeys from './filtered_search_token_keys';
export const tokenKeys = [
@ -13,7 +13,7 @@ export const tokenKeys = [
tag: '@author',
},
{
formattedKey: __('Assignee'),
formattedKey: s__('SearchToken|Assignee'),
key: 'assignee',
type: 'string',
param: 'username',

View File

@ -1,3 +0,0 @@
import { initCiSecureFiles } from '~/ci_secure_files';
initCiSecureFiles();

View File

@ -0,0 +1,27 @@
<script>
export default {
props: {
mr: {
type: Object,
required: true,
},
},
computed: {
widgets() {
return [].filter((w) => w);
},
},
};
</script>
<template>
<section role="region" :aria-label="__('Merge request reports')" data-testid="mr-widget-app">
<component
:is="widget"
v-for="(widget, index) in widgets"
:key="widget.name || index"
:mr="mr"
:class="{ 'mr-widget-border-top': index === 0 }"
/>
</section>
</template>

View File

@ -0,0 +1,148 @@
<script>
import * as Sentry from '@sentry/browser';
import { normalizeHeaders } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import Poll from '~/lib/utils/poll';
const FETCH_TYPE_COLLAPSED = 'collapsed';
// const FETCH_TYPE_EXPANDED = 'expanded';
export default {
props: {
/**
* @param {value.collapsed} Object
* @param {value.extended} Object
*/
value: {
type: Object,
required: true,
},
loadingText: {
type: String,
required: true,
},
errorText: {
type: String,
required: false,
default: __('Failed to load'),
},
fetchCollapsedData: {
type: Function,
required: true,
},
fetchExtendedData: {
type: Function,
required: false,
default: undefined,
},
// If the summary slot is not used, this value will be used as a fallback.
summary: {
type: String,
required: false,
default: undefined,
},
// If the content slot is not used, this value will be used as a fallback.
content: {
type: Object,
required: false,
default: undefined,
},
multiPolling: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
loading: false,
statusIcon: null,
error: null,
};
},
async mounted() {
this.loading = true;
try {
await this.fetch(this.fetchCollapsedData, FETCH_TYPE_COLLAPSED);
} catch {
this.error = this.errorText;
}
this.loading = false;
},
methods: {
fetch(handler, dataType) {
const requests = this.multiPolling ? handler() : [handler];
const allData = [];
const promises = requests.map((request) => {
return new Promise((resolve, reject) => {
const setData = (data) => {
this.$emit('input', { ...this.value, [dataType]: data });
resolve(data);
};
const poll = new Poll({
resource: {
fetchData: () => request(),
},
method: 'fetchData',
successCallback: (response) => {
const headers = normalizeHeaders(response.headers);
if (headers['POLL-INTERVAL']) {
return;
}
if (this.multiPolling) {
allData.push(response.data);
if (allData.length === requests.length) {
setData(allData);
}
return;
}
setData(response.data);
},
errorCallback: (e) => {
Sentry.captureException(e);
reject(e);
},
});
poll.makeRequest();
});
});
return Promise.all(promises);
},
},
};
</script>
<template>
<section class="media-section" data-testid="widget-extension">
<div class="media gl-p-5">
<!-- status icon will go here -->
<div
class="media-body gl-display-flex gl-flex-direction-row! gl-align-self-center"
data-testid="widget-extension-top-level"
>
<div class="gl-flex-grow-1" data-testid="widget-extension-top-level-summary">
<slot name="summary">{{ summary }}</slot>
</div>
<!-- actions will go here -->
<!-- toggle button will go here -->
</div>
</div>
<div
class="mr-widget-grouped-section gl-relative"
data-testid="widget-extension-collapsed-section"
>
<slot name="content">{{ content }}</slot>
</div>
</section>
</template>

View File

@ -1,7 +1,6 @@
<script>
import { GlSafeHtmlDirective } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import securityReportExtension from 'ee_else_ce/vue_merge_request_widget/extensions/security_reports';
import { registerExtension } from '~/vue_merge_request_widget/components/extensions';
import MrWidgetApprovals from 'ee_else_ce/vue_merge_request_widget/components/approvals/approvals.vue';
import MRWidgetService from 'ee_else_ce/vue_merge_request_widget/services/mr_widget_service';
@ -39,6 +38,7 @@ import ShaMismatch from './components/states/sha_mismatch.vue';
import UnresolvedDiscussionsState from './components/states/unresolved_discussions.vue';
import WorkInProgressState from './components/states/work_in_progress.vue';
import ExtensionsContainer from './components/extensions/container';
import WidgetContainer from './components/widget/app.vue';
import { STATE_MACHINE, stateToComponentMap } from './constants';
import eventHub from './event_hub';
import mergeRequestQueryVariablesMixin from './mixins/merge_request_query_variables';
@ -58,6 +58,7 @@ export default {
components: {
Loading,
ExtensionsContainer,
WidgetContainer,
'mr-widget-suggest-pipeline': WidgetSuggestPipeline,
MrWidgetPipelineContainer,
MrWidgetAlertMessage,
@ -262,11 +263,6 @@ export default {
this.registerTestReportExtension();
}
},
shouldRenderSecurityReport(newVal) {
if (newVal) {
this.registerSecurityReportExtension();
}
},
},
mounted() {
MRWidgetService.fetchInitialData()
@ -522,11 +518,6 @@ export default {
registerExtension(testReportExtension);
}
},
registerSecurityReportExtension() {
if (this.shouldRenderSecurityReport && this.shouldShowSecurityExtension) {
registerExtension(securityReportExtension);
}
},
},
};
</script>
@ -587,7 +578,11 @@ export default {
</template>
</mr-widget-alert-message>
</div>
<extensions-container :mr="mr" />
<widget-container v-if="mr" :mr="mr" />
<grouped-codequality-reports-app
v-if="shouldRenderCodeQuality && !shouldShowCodeQualityExtension"
:head-blob-path="mr.headBlobPath"

View File

@ -33,7 +33,6 @@ export default class MergeRequestStore {
this.setData(data);
this.initCodeQualityReport(data);
this.initSecurityReport(data);
this.setGitpodData(data);
}
@ -42,19 +41,6 @@ export default class MergeRequestStore {
this.codeQuality = data.codequality_reports_path;
}
initSecurityReport(data) {
// TODO: check if gl.mrWidgetData can be safely removed after we migrate to the
// widget extension.
this.securityReportPaths = {
apiFuzzingReportPath: data.api_fuzzing_comparison_path,
coverageFuzzingReportPath: data.coverage_fuzzing_comparison_path,
sastReportPath: data.sast_comparison_path,
dastReportPath: data.dast_comparison_path,
secretDetectionReportPath: data.secret_detection_comparison_path,
dependencyScanningReportPath: data.dependency_scanning_comparison_path,
};
}
setData(data, isRebased) {
this.initApprovals();

View File

@ -1,11 +0,0 @@
# frozen_string_literal: true
class Projects::Ci::SecureFilesController < Projects::ApplicationController
before_action :authorize_read_secure_files!
feature_category :pipeline_authoring
def show
render_404 unless Feature.enabled?(:ci_secure_files, project)
end
end

View File

@ -31,7 +31,7 @@ module Mutations
runners = find_all_runners_by_ids(model_ids_of(ids))
result = ::Ci::Runners::BulkDeleteRunnersService.new(runners: runners).execute
result.slice(:deleted_count, :deleted_ids).merge(errors: [])
result.payload.slice(:deleted_count, :deleted_ids).merge(errors: [])
else
{ errors: [] }
end

View File

@ -15,10 +15,10 @@ module Ci
def execute
if @runners
# Delete a few runners immediately
return delete_runners
return ServiceResponse.success(payload: delete_runners)
end
{ deleted_count: 0, deleted_ids: [] }
ServiceResponse.success(payload: { deleted_count: 0, deleted_ids: [] })
end
private

View File

@ -1,3 +0,0 @@
- page_title s_('Secure Files')
#js-ci-secure-files{ data: { project_id: @project.id, admin: can?(current_user, :admin_secure_files, @project).to_s, file_size_limit: Ci::SecureFile::FILE_SIZE_LIMIT.to_mb } }

View File

@ -1,8 +0,0 @@
---
name: highlight_diffs_optimize_memory_usage
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92456
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367890
milestone: '15.3'
type: development
group: group::source code
default_enabled: false

View File

@ -96,7 +96,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
namespace :ci do
resource :lint, only: [:show, :create]
resource :pipeline_editor, only: [:show], controller: :pipeline_editor, path: 'editor'
resource :secure_files, only: [:show], controller: :secure_files, path: 'secure_files'
resources :daily_build_group_report_results, only: [:index], constraints: { format: /(csv|json)/ }
namespace :prometheus_metrics do
resources :histograms, only: [:create], constraints: { format: 'json' }

View File

@ -0,0 +1,13 @@
---
# Error: gitlab.HeadingDepth
#
# Checks that there are no headings greater than 3 levels
#
# For a list of all options, see https://vale.sh/docs/topics/styles/
extends: existence
message: 'The subheading "%s" is nested too deeply. Headings deeper than H5 suggest the section or page should be refactored.'
link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#headings-in-markdown
level: warning
scope: raw
raw:
- '(?<=\n)#{5,}\s.*'

View File

@ -1202,8 +1202,8 @@ Before diving in to the following sections, here's some basic troubleshooting:
been synchronized (for example, via NTP).
1. If you are using an S3-backed Registry, double check that the IAM
permissions and the S3 credentials (including region) are correct. See [the
sample IAM policy](https://docs.docker.com/registry/storage-drivers/s3/)
permissions and the S3 credentials (including region) are correct. See
[the sample IAM policy](https://docs.docker.com/registry/storage-drivers/s3/)
for more details.
1. Check the Registry logs (for example `/var/log/gitlab/registry/current`) and the GitLab production logs
@ -1631,8 +1631,8 @@ wrong. However, since all communications between Docker clients and servers
are done over HTTPS, it's a bit difficult to decrypt the traffic quickly even
if you know the private key. What can we do instead?
One way would be to disable HTTPS by setting up an [insecure
Registry](https://docs.docker.com/registry/insecure/). This could introduce a
One way would be to disable HTTPS by setting up an
[insecure Registry](https://docs.docker.com/registry/insecure/). This could introduce a
security hole and is only recommended for local testing. If you have a
production system and can't or don't want to do this, there is another way:
use mitmproxy, which stands for Man-in-the-Middle Proxy.

View File

@ -933,8 +933,8 @@ The following settings are:
| `connection` | Various connection options described below. | |
NOTE:
If you want to stop using and disconnect the NFS server, you need to [explicitly disable
local storage](#disable-pages-local-storage), and it's only possible after upgrading to GitLab 13.11.
If you want to stop using and disconnect the NFS server, you need to
[explicitly disable local storage](#disable-pages-local-storage), and it's only possible after upgrading to GitLab 13.11.
#### S3-compatible connection settings

View File

@ -19,7 +19,7 @@ GET /projects/:id/jobs
| Attribute | Type | Required | Description |
|-----------|--------------------------------|------------------------|-------------|
| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, `waiting_for_resource`, or `manual`. All jobs are returned if `scope` is not provided. |
```shell
curl --globoff --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs?scope[]=pending&scope[]=running"
@ -167,7 +167,7 @@ GET /projects/:id/pipelines/:pipeline_id/jobs
|-------------------|--------------------------------|------------------------|-------------|
| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `pipeline_id` | integer | **{check-circle}** Yes | ID of a pipeline. Can also be obtained in CI jobs via the [predefined CI variable](../ci/variables/predefined_variables.md) `CI_PIPELINE_ID`. |
| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, `waiting_for_resource`, or `manual`. All jobs are returned if `scope` is not provided. |
| `include_retried` | boolean | **{dotted-circle}** No | Include retried jobs in the response. Defaults to `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/272627) in GitLab 13.9. |
```shell
@ -324,7 +324,7 @@ GET /projects/:id/pipelines/:pipeline_id/bridges
|---------------|--------------------------------|------------------------|-------------|
| `id` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `pipeline_id` | integer | **{check-circle}** Yes | ID of a pipeline. |
| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
| `scope` | string **or** array of strings | **{dotted-circle}** No | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, `waiting_for_resource`, or `manual`. All jobs are returned if `scope` is not provided. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipelines/6/bridges?scope[]=pending&scope[]=running"

View File

@ -11,7 +11,7 @@ Notes are comments on:
- Snippets
- Issues
- Merge requests
- Epics **(PREMIUM)**
- [Epics](../user/group/epics/index.md)
This includes system notes, which are notes about changes to the object (for example, when an
assignee changes, GitLab posts a system note).
@ -447,7 +447,7 @@ Parameters:
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/7/notes/1602"
```
## Epics **(ULTIMATE)**
## Epics **(PREMIUM)**
### List all epic notes

View File

@ -38,8 +38,8 @@ The examples in this document all use the instance-level prefix.
/packages/conan/v1
```
When using the instance-level routes, be aware that there is a [naming
restriction](../../user/packages/conan_repository/index.md#package-recipe-naming-convention-for-instance-remotes)
When using the instance-level routes, be aware that there is a
[naming restriction](../../user/packages/conan_repository/index.md#package-recipe-naming-convention-for-instance-remotes)
for Conan recipes.
### Project-level

View File

@ -342,9 +342,8 @@ tags using these formats:
- `vX.Y.Z`
- `X.Y.Z`
Where `X.Y.Z` is a version that follows [semantic
versioning](https://semver.org/). For example, consider a project with the
following tags:
Where `X.Y.Z` is a version that follows [semantic versioning](https://semver.org/).
For example, consider a project with the following tags:
- v1.0.0-pre1
- v1.0.0

View File

@ -32,6 +32,8 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
Example response:
<!-- vale gitlab.MultiLineLinks = NO -->
```json
[
{
@ -57,6 +59,8 @@ Example response:
]
```
<!-- vale gitlab.MultiLineLinks = YES -->
## Get a wiki page
Get a wiki page for a given project.

View File

@ -35,8 +35,8 @@ sequenceDiagram
Workhorse-->>-Runner: request results
```
1. The CI/CD job generates a document in an LSIF format (usually `dump.lsif`) using [an
indexer](https://lsif.dev) for the language of a project. The format
1. The CI/CD job generates a document in an LSIF format (usually `dump.lsif`) using
[an indexer](https://lsif.dev) for the language of a project. The format
[describes](https://github.com/sourcegraph/sourcegraph/blob/main/doc/code_intelligence/explanations/writing_an_indexer.md)
interactions between a method or function and its definitions or references. The
document is marked to be stored as an LSIF report artifact.

View File

@ -10,8 +10,8 @@ Ruby processes accessing the database through
ActiveRecord, automatically calculate the connection-pool size for the
process based on the concurrency.
Because of the way [Ruby on Rails manages database
connections](#connection-lifecycle), it is important that we have at
Because of the way [Ruby on Rails manages database connections](#connection-lifecycle),
it is important that we have at
least as many connections as we have threads. While there is a 'pool'
setting in [`database.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/database.yml.postgresql), it is not very practical because you need to
maintain it in tandem with the number of application threads. For this
@ -28,9 +28,8 @@ because connections are instantiated lazily.
## Troubleshooting connection-pool issues
The connection-pool usage can be seen per environment in the [connection-pool
saturation
dashboard](https://dashboards.gitlab.net/d/alerts-sat_rails_db_connection_pool/alerts-rails_db_connection_pool-saturation-detail?orgId=1).
The connection-pool usage can be seen per environment in the
[connection-pool saturation dashboard](https://dashboards.gitlab.net/d/alerts-sat_rails_db_connection_pool/alerts-rails_db_connection_pool-saturation-detail?orgId=1).
If the connection-pool is too small, this would manifest in
`ActiveRecord::ConnectionTimeoutError`s from the application. Because we alert
@ -41,8 +40,8 @@ hardcoded value (10).
At this point, we need to investigate what is using more connections
than we anticipated. To do that, we can use the
`gitlab_ruby_threads_running_threads` metric. For example, [this
graph](https://thanos.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=sum%20by%20(thread_name)%20(%20gitlab_ruby_threads_running_threads%7Buses_db_connection%3D%22yes%22%7D%20)&g0.tab=0)
`gitlab_ruby_threads_running_threads` metric. For example,
[this graph](https://thanos.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=sum%20by%20(thread_name)%20(%20gitlab_ruby_threads_running_threads%7Buses_db_connection%3D%22yes%22%7D%20)&g0.tab=0)
shows all running threads that connect to the database by their
name. Threads labeled `puma worker` or `sidekiq_worker_thread` are
the threads that define `Gitlab::Runtime.max_threads` so those are

View File

@ -221,8 +221,8 @@ ON DELETE CASCADE;
```
The migration must run after the `DELETE` trigger is installed and the loose
foreign key definition is deployed. As such, it must be a [post-deployment
migration](post_deployment_migrations.md) dated after the migration for the
foreign key definition is deployed. As such, it must be a
[post-deployment migration](post_deployment_migrations.md) dated after the migration for the
trigger. If the foreign key is deleted earlier, there is a good chance of
introducing data inconsistency which needs manual cleanup:

View File

@ -81,8 +81,8 @@ Execute a standard migration (not a post-migration):
when naming indexes, so there is a possibility that not all indexes are properly renamed. After running
the migration locally, check if there are inconsistently named indexes (`db/structure.sql`). Those can be
renamed manually in a separate migration, which can be also part of the release M.N+1.
- Foreign key columns might still contain the old table name. For smaller tables, follow our [standard column
rename process](avoiding_downtime_in_migrations.md#renaming-columns)
- Foreign key columns might still contain the old table name. For smaller tables, follow our
[standard column rename process](avoiding_downtime_in_migrations.md#renaming-columns)
- Avoid renaming database tables which are using with triggers.
- Table modifications (add or remove columns) are not allowed during the rename process, please make sure that all changes to the table happen before the rename migration is started (or in the next release).
- As the index names might change, verify that the model does not use bulk insert

View File

@ -148,8 +148,9 @@ to update the `title_html` with a title that has more than 1024 characters, the
a database error.
Adding or removing a constraint to an existing attribute requires that any application changes are
deployed _first_, [otherwise servers still in the old version of the application may try to update the
attribute with invalid values](../multi_version_compatibility.md#ci-artifact-uploads-were-failing).
deployed _first_,
otherwise servers still in the old version of the application
[may try to update the attribute with invalid values](../multi_version_compatibility.md#ci-artifact-uploads-were-failing).
For these reasons, `add_text_limit` should run in a post-deployment migration.
Still in our example, for the 13.0 milestone (current), consider that the following validation

View File

@ -252,8 +252,8 @@ A scan on an index that required retrieving some data from the table.
Bitmap scans fall between sequential scans and index scans. These are typically
used when we would read too much data from an index scan, but too little to
perform a sequential scan. A bitmap scan uses what is known as a [bitmap
index](https://en.wikipedia.org/wiki/Bitmap_index) to perform its work.
perform a sequential scan. A bitmap scan uses what is known as a
[bitmap index](https://en.wikipedia.org/wiki/Bitmap_index) to perform its work.
The [source code of PostgreSQL](https://gitlab.com/postgres/postgres/blob/REL_11_STABLE/src/include/nodes/plannodes.h#L441)
states the following on bitmap scans:
@ -794,8 +794,8 @@ Execution time: 0.113 ms
### ChatOps
[GitLab team members can also use our ChatOps solution, available in Slack using the
`/chatops` slash command](../chatops_on_gitlabcom.md).
GitLab team members can also use our ChatOps solution, available in Slack
using the [`/chatops` slash command](../chatops_on_gitlabcom.md).
NOTE:
While ChatOps is still available, the recommended way to generate execution plans is to use [Database Lab Engine](#database-lab-engine).

View File

@ -148,8 +148,8 @@ curl --request POST --header "Gitlab-Shared-Secret: <Base64 encoded token>" \
## Authorized Keys Check
This endpoint is called by the GitLab Shell authorized keys
check. Which is called by OpenSSH for [fast SSH key
lookup](../../administration/operations/fast_ssh_key_lookup.md).
check. Which is called by OpenSSH for
[fast SSH key lookup](../../administration/operations/fast_ssh_key_lookup.md).
| Attribute | Type | Required | Description |
|:----------|:-------|:---------|:------------|

View File

@ -13,10 +13,8 @@ Sometimes when a new resource type is added it's not clear if it should be only
"extension" of Issue (Issue Type) or if it should be a new first-class resource type
(similar to issue, epic, merge request, snippet).
The idea of Issue Types was first proposed in [this
issue](https://gitlab.com/gitlab-org/gitlab/-/issues/8767) and its usage was
discussed few times since then, for example in [incident
management](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55532).
The idea of Issue Types was first proposed in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/8767) and its usage was
discussed few times since then, for example in [incident management](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55532).
## What is an Issue Type

View File

@ -76,14 +76,13 @@ process, which writes the contents to the standard output.
1. The archive data is sent back to the client.
In step 7, the `gitaly-lfs-smudge` filter must talk to Workhorse, not to
Rails, or an invalid LFS blob is saved. To support this, GitLab
13.5 [changed the default Omnibus configuration to have Gitaly talk to
the Workhorse](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4592)
Rails, or an invalid LFS blob is saved. To support this, GitLab 13.5
[changed the default Omnibus configuration to have Gitaly talk to the Workhorse](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4592)
instead of Rails.
One side effect of this change: the correlation ID of the original
request is not preserved for the internal API requests made by Gitaly
(or `gitaly-lfs-smudge`), such as the one made in step 8. The
correlation IDs for those API requests are random values until [this
Workhorse issue](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/309) is
correlation IDs for those API requests are random values until
[this Workhorse issue](https://gitlab.com/gitlab-org/gitlab-workhorse/-/issues/309) is
resolved.

View File

@ -60,8 +60,8 @@ downstream services.
To mitigate this, ensure that the code establishing the new WebSocket connection
is feature flagged and defaulted to `off`. A careful, percentage-based roll-out
of the feature flag ensures that effects can be observed on the [WebSocket
dashboard](https://dashboards.gitlab.net/d/websockets-main/websockets-overview?orgId=1)
of the feature flag ensures that effects can be observed on the
[WebSocket dashboard](https://dashboards.gitlab.net/d/websockets-main/websockets-overview?orgId=1)
1. Create a
[feature flag roll-out](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20Flag%20Roll%20Out.md)

View File

@ -111,7 +111,7 @@ sequenceDiagram
1. Finally, the timing metadata information that is used for diagnostic purposes is submitted to the Versions application. It consists of a list of metric identifiers and the time it took to calculate the metrics:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911) in GitLab 15.0 [with a flag(../../user/feature_flags.md), enabled by default.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911) in GitLab 15.0 [with a flag](../../user/feature_flags.md), enabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/295289) in GitLab 15.2. [Feature flag `measure_service_ping_metric_collection`](https://gitlab.com/gitlab-org/gitlab/-/issues/358128) removed.
```ruby

View File

@ -79,8 +79,9 @@ ON table_name
USING GIN(column_name gin_trgm_ops);
```
The key here is the `GIN(column_name gin_trgm_ops)` part. This creates a [GIN
index](https://www.postgresql.org/docs/current/gin.html) with the operator class set to `gin_trgm_ops`. These indexes
The key here is the `GIN(column_name gin_trgm_ops)` part. This creates a
[GIN index](https://www.postgresql.org/docs/current/gin.html)
with the operator class set to `gin_trgm_ops`. These indexes
_can_ be used by `ILIKE` / `LIKE` and can lead to greatly improved performance.
One downside of these indexes is that they can easily get quite large (depending
on the amount of data indexed).

View File

@ -10,8 +10,8 @@ GitLab Workhorse is a smart reverse proxy for GitLab. It handles
"large" HTTP requests such as file downloads, file uploads, Git
push/pull and Git archive downloads.
Workhorse itself is not a feature, but there are [several features in
GitLab](gitlab_features.md) that would not work efficiently without Workhorse.
Workhorse itself is not a feature, but there are
[several features in GitLab](gitlab_features.md) that would not work efficiently without Workhorse.
The canonical source for Workhorse is
[`gitlab-org/gitlab/workhorse`](https://gitlab.com/gitlab-org/gitlab/tree/master/workhorse).

View File

@ -115,8 +115,7 @@ See the documentation on [File Locking](../../../user/project/file_lock.md).
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46572) in GitLab 13.6.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62539) in GitLab 14.0. Feature flag `include_lfs_blobs_in_archive` removed.
Prior to GitLab 13.5, [project source
downloads](../../../user/project/repository/index.md) would include Git
Prior to GitLab 13.5, [project source downloads](../../../user/project/repository/index.md) would include Git
LFS pointers instead of the actual objects. For example, LFS pointers
look like the following:

View File

@ -8,8 +8,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Instance-level analytics
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12077) in GitLab 12.2.
Instance-level analytics make it possible to aggregate analytics across
GitLab, so that users can view information across multiple projects and groups
in one place.
@ -18,8 +16,7 @@ in one place.
## Group-level analytics
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195979) in GitLab 12.8.
> - Moved to GitLab Premium in 13.9.
> Moved to GitLab Premium in 13.9.
GitLab provides several analytics features at the group level. Some of these features require you to use a higher tier than GitLab Free.

View File

@ -31,12 +31,12 @@ To view merge request analytics:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Analytics > Merge request**.
## View merge requests merged per month
## View the number of merge requests in a date range
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232651) in GitLab 13.3.
> - Filtering [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229266) in GitLab 13.4
To view the number of merge requests merged per month:
To view the number of merge requests merged during a specific date range:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Analytics > Merge request**.

View File

@ -169,7 +169,7 @@ You can also add, remove, or replace issue contacts using the
[GraphQL](../../api/graphql/reference/index.md#mutationissuesetcrmcontacts)
API.
## Autocomplete contacts **(FREE SELF)**
## Autocomplete contacts
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2256) in GitLab 14.8 [with a flag](../../administration/feature_flags.md) named `contacts_autocomplete`. Disabled by default.
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/352123) in GitLab 15.0.

View File

@ -23,5 +23,5 @@ ignored.
## Syntax Highlighting
The `.gitattributes` file can be used to define which language to use when
syntax highlighting files and diffs. See ["Syntax
Highlighting"](highlighting.md) for more information.
syntax highlighting files and diffs. See
["Syntax Highlighting"](highlighting.md) for more information.

View File

@ -420,10 +420,10 @@ Now GitLab CI/CD not only builds the website, but also:
For more information, see the following blog posts.
- [Use GitLab CI/CD `environments` to deploy your
web app to staging and production](https://about.gitlab.com/blog/2021/02/05/ci-deployment-and-environments/).
- Learn [how to run jobs sequentially,
in parallel, or build a custom pipeline](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/).
- Use GitLab CI/CD `environments` to
[deploy your web app to staging and production](https://about.gitlab.com/blog/2021/02/05/ci-deployment-and-environments/).
- Learn how to run jobs
[sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/blog/2016/07/29/the-basics-of-gitlab-ci/).
- Learn [how to pull specific directories from different projects](https://about.gitlab.com/blog/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/)
to deploy this website, <https://docs.gitlab.com>.
- Learn [how to use GitLab Pages to produce a code coverage report](https://about.gitlab.com/blog/2016/11/03/publish-code-coverage-report-with-gitlab-pages/).

View File

@ -95,15 +95,15 @@ git push -o merge_request.create -o merge_request.target=my-target-branch -o mer
## Useful Git aliases
As shown above, Git push options can cause Git commands to grow very long. If
you use the same push options frequently, it's useful to create [Git
aliases](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases). Git aliases
you use the same push options frequently, it's useful to create
[Git aliases](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases). Git aliases
are command line shortcuts for Git which can significantly simplify the use of
long Git commands.
### Merge when pipeline succeeds alias
To set up a Git alias for the [merge when pipeline succeeds Git push
option](#push-options-for-merge-requests):
To set up a Git alias for the
[merge when pipeline succeeds Git push option](#push-options-for-merge-requests):
```shell
git config --global alias.mwps "push -o merge_request.create -o merge_request.target=master -o merge_request.merge_when_pipeline_succeeds"

View File

@ -7,7 +7,6 @@ module Gitlab
include Gitlab::Utils::StrongMemoize
EXPIRATION = 1.day
PREVIOUS_EXPIRATION_PERIOD = 7.days
VERSION = 2
delegate :diffable, to: :@diff_collection
@ -75,28 +74,14 @@ module Gitlab
Feature.enabled?(:use_marker_ranges, diffable.project),
Feature.enabled?(:diff_line_syntax_highlighting, diffable.project)
]
options_for_key = OpenSSL::Digest::SHA256.hexdigest(options.join)
options_for_key =
if Feature.enabled?(:highlight_diffs_optimize_memory_usage, diffable.project)
[OpenSSL::Digest::SHA256.hexdigest(options.join)]
else
options
end
['highlighted-diff-files', diffable.cache_key, VERSION, *options_for_key].join(":")
['highlighted-diff-files', diffable.cache_key, VERSION, options_for_key].join(":")
end
end
private
def expiration_period
if Feature.enabled?(:highlight_diffs_optimize_memory_usage, diffable.project)
EXPIRATION
else
PREVIOUS_EXPIRATION_PERIOD
end
end
def set_highlighted_diff_lines(diff_file, content)
diff_file.highlighted_diff_lines = content.map do |line|
Gitlab::Diff::Line.safe_init_from_hash(line)
@ -153,7 +138,7 @@ module Gitlab
# HSETs have to have their expiration date manually updated
#
redis.expire(key, expiration_period)
redis.expire(key, EXPIRATION)
end
record_memory_usage(fetch_memory_usage(redis, key))

View File

@ -34571,6 +34571,12 @@ msgid_plural "SearchResults|wiki results"
msgstr[0] ""
msgstr[1] ""
msgid "SearchToken|Assignee"
msgstr ""
msgid "SearchToken|Reviewer"
msgstr ""
msgid "Searching by both author and message is currently not supported."
msgstr ""
@ -45727,9 +45733,15 @@ msgstr ""
msgid "ciReport|%{sameNum} same"
msgstr ""
msgid "ciReport|%{scanner} detected %{boldStart}%{number}%{boldEnd} new potential %{vulnStr}"
msgstr ""
msgid "ciReport|%{scanner} detected %{strong_start}%{number}%{strong_end} new potential %{vulnStr}"
msgstr ""
msgid "ciReport|%{scanner} detected no %{boldStart}new%{boldEnd} potential vulnerabilities"
msgstr ""
msgid "ciReport|%{scanner} detected no %{strong_start}new%{strong_end} %{vulnStr}"
msgstr ""

View File

@ -1,67 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Projects::Ci::SecureFilesController do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
subject(:show_request) { get :show, params: { namespace_id: project.namespace, project_id: project } }
describe 'GET #show' do
context 'when the :ci_secure_files feature flag is enabled' do
context 'with enough privileges' do
before do
stub_feature_flags(ci_secure_files: true)
sign_in(user)
project.add_developer(user)
show_request
end
it { expect(response).to have_gitlab_http_status(:ok) }
it 'renders show page' do
expect(response).to render_template :show
end
end
end
context 'when the :ci_secure_files feature flag is disabled' do
context 'with enough privileges' do
before do
stub_feature_flags(ci_secure_files: false)
sign_in(user)
project.add_developer(user)
show_request
end
it 'responds with 404' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
context 'without enough privileges' do
before do
sign_in(user)
project.add_reporter(user)
show_request
end
it 'responds with 404' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
context 'an unauthenticated user' do
before do
show_request
end
it 'redirects to sign in' do
expect(response).to have_gitlab_http_status(:found)
expect(response).to redirect_to('/users/sign_in')
end
end
end
end

View File

@ -1,61 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Secure Files', :js do
let(:project) { create(:project) }
let(:user) { create(:user) }
before do
stub_feature_flags(ci_secure_files_read_only: false)
project.add_maintainer(user)
sign_in(user)
end
it 'user sees the Secure Files list component' do
visit project_ci_secure_files_path(project)
expect(page).to have_content('There are no secure files yet.')
end
it 'prompts the user to confirm before deleting a file' do
file = create(:ci_secure_file, project: project)
visit project_ci_secure_files_path(project)
expect(page).to have_content(file.name)
find('button.btn-danger').click
expect(page).to have_content("Delete #{file.name}?")
click_on('Delete secure file')
visit project_ci_secure_files_path(project)
expect(page).not_to have_content(file.name)
end
it 'displays an uploaded file in the file list' do
visit project_ci_secure_files_path(project)
expect(page).to have_content('There are no secure files yet.')
page.attach_file('spec/fixtures/ci_secure_files/upload-keystore.jks') do
click_button 'Upload File'
end
expect(page).to have_content('upload-keystore.jks')
end
it 'displays an error when a duplicate file upload is attempted' do
create(:ci_secure_file, project: project, name: 'upload-keystore.jks')
visit project_ci_secure_files_path(project)
expect(page).to have_content('upload-keystore.jks')
page.attach_file('spec/fixtures/ci_secure_files/upload-keystore.jks') do
click_button 'Upload File'
end
expect(page).to have_content('A file with this name already exists.')
end
end

View File

@ -121,7 +121,7 @@ describe('gl_emoji', () => {
window.gon.emoji_sprites_css_path = testPath;
expect(document.head.querySelector(`link[href="${testPath}"]`)).toBe(null);
expect(window.gon.emoji_sprites_css_added).toBeFalsy();
expect(window.gon.emoji_sprites_css_added).toBe(undefined);
markupToDomElement(
'<gl-emoji data-fallback-sprite-class="emoji-bomb" data-name="bomb"></gl-emoji>',

View File

@ -402,7 +402,7 @@ describe('TrainingProviderList component', () => {
it('has disabled state for radio', () => {
findPrimaryProviderRadios().wrappers.forEach((radio) => {
expect(radio.attributes('disabled')).toBeTruthy();
expect(radio.attributes('disabled')).toBe('true');
});
});

View File

@ -0,0 +1,19 @@
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import App from '~/vue_merge_request_widget/components/widget/app.vue';
describe('MR Widget App', () => {
let wrapper;
const createComponent = () => {
wrapper = shallowMountExtended(App, {
propsData: {
mr: {},
},
});
};
it('mounts the component', () => {
createComponent();
expect(wrapper.findByTestId('mr-widget-app').exists()).toBe(true);
});
});

View File

@ -0,0 +1,134 @@
import * as Sentry from '@sentry/browser';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import Widget from '~/vue_merge_request_widget/components/widget/widget.vue';
describe('MR Widget', () => {
let wrapper;
const createComponent = ({ propsData, slots } = {}) => {
wrapper = shallowMountExtended(Widget, {
propsData: {
loadingText: 'Loading widget',
value: {
collapsed: null,
expanded: null,
},
...propsData,
},
slots,
});
};
afterEach(() => {
wrapper.destroy();
});
describe('on mount', () => {
it('fetches collapsed', async () => {
const fetchCollapsedData = jest
.fn()
.mockReturnValue(Promise.resolve({ headers: {}, status: 200, data: {} }));
createComponent({ propsData: { fetchCollapsedData } });
await waitForPromises();
expect(fetchCollapsedData).toHaveBeenCalled();
expect(wrapper.vm.error).toBe(null);
});
it('sets the error text when fetch method fails', async () => {
const fetchCollapsedData = jest.fn().mockReturnValue(() => Promise.reject());
createComponent({ propsData: { fetchCollapsedData } });
await waitForPromises();
expect(wrapper.vm.error).toBe('Failed to load');
});
});
describe('fetch', () => {
it('sets the data.collapsed property after a successfull call - multiPolling: false', async () => {
const mockData = { headers: {}, status: 200, data: { vulnerabilities: [] } };
createComponent({ propsData: { fetchCollapsedData: async () => mockData } });
await waitForPromises();
expect(wrapper.emitted('input')[0][0]).toEqual({ collapsed: mockData.data, expanded: null });
});
it('sets the data.collapsed property after a successfull call - multiPolling: true', async () => {
const mockData1 = { headers: {}, status: 200, data: { vulnerabilities: [{ vuln: 1 }] } };
const mockData2 = { headers: {}, status: 200, data: { vulnerabilities: [{ vuln: 2 }] } };
createComponent({
propsData: {
multiPolling: true,
fetchCollapsedData: () => [
() => Promise.resolve(mockData1),
() => Promise.resolve(mockData2),
],
},
});
await waitForPromises();
await waitForPromises();
expect(wrapper.emitted('input')[0][0]).toEqual({
collapsed: [mockData1.data, mockData2.data],
expanded: null,
});
});
it('calls sentry when failed', async () => {
const error = new Error('Something went wrong');
jest.spyOn(Sentry, 'captureException').mockImplementation();
createComponent({
propsData: {
fetchCollapsedData: async () => Promise.reject(error),
},
});
await waitForPromises();
expect(wrapper.emitted('input')).toBeUndefined();
expect(Sentry.captureException).toHaveBeenCalledWith(error);
});
});
describe('content', () => {
it('displays summary property when summary slot is not provided', () => {
createComponent({
propsData: {
summary: 'Hello world',
fetchCollapsedData: async () => Promise.resolve(),
},
});
expect(wrapper.findByTestId('widget-extension-top-level-summary').text()).toBe('Hello world');
});
it.todo('displays content property when content slot is not provided');
it('displays the summary slot when provided', () => {
createComponent({
propsData: {
fetchCollapsedData: async () => Promise.resolve(),
},
slots: {
summary: '<b>More complex summary</b>',
},
});
expect(wrapper.findByTestId('widget-extension-top-level-summary').text()).toBe(
'More complex summary',
);
});
it('displays the content slot when provided', () => {
createComponent({
propsData: {
fetchCollapsedData: async () => Promise.resolve(),
},
slots: {
content: '<b>More complex content</b>',
},
});
expect(wrapper.findByTestId('widget-extension-collapsed-section').text()).toBe(
'More complex content',
);
});
});
});

View File

@ -45,7 +45,7 @@ describe('vue_shared/components/dismissible_alert', () => {
});
it('emmits alertDismissed', () => {
expect(wrapper.emitted('alertDismissed')).toBeTruthy();
expect(wrapper.emitted()).toHaveProperty('alertDismissed');
});
});
});

View File

@ -127,20 +127,6 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
cache.write_if_empty
end
context 'when highlight_diffs_optimize_memory_usage is disabled' do
before do
stub_feature_flags(highlight_diffs_optimize_memory_usage: false)
end
it 'sets the previous expiration period' do
Gitlab::Redis::Cache.with do |redis|
expect(redis).to receive(:expire).with(cache.key, described_class::PREVIOUS_EXPIRATION_PERIOD)
end
cache.write_if_empty
end
end
end
describe '#write_if_empty' do
@ -304,15 +290,5 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{options_hash([cache.diff_options, true, false])}")
end
end
context 'when highlight_diffs_optimize_memory_usage is disabled' do
before do
stub_feature_flags(highlight_diffs_optimize_memory_usage: false)
end
it 'uses the options hash as a part of the cache key' do
is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true:true")
end
end
end
end

View File

@ -953,12 +953,6 @@ RSpec.describe 'project routing' do
end
end
describe Projects::Ci::SecureFilesController, 'routing' do
it 'to #show' do
expect(get('/gitlab/gitlabhq/-/ci/secure_files')).to route_to('projects/ci/secure_files#show', namespace_id: 'gitlab', project_id: 'gitlabhq')
end
end
context 'with a non-existent project' do
it 'routes to 404 with get request' do
expect(get: "/gitlab/not_exist").to route_to(

View File

@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe ::Ci::Runners::BulkDeleteRunnersService, '#execute' do
subject { described_class.new(**service_args).execute }
subject(:execute) { described_class.new(**service_args).execute }
let(:service_args) { { runners: runners_arg } }
let(:runners_arg) { }
@ -17,7 +17,8 @@ RSpec.describe ::Ci::Runners::BulkDeleteRunnersService, '#execute' do
it 'destroys runners', :aggregate_failures do
expect { subject }.to change { Ci::Runner.count }.by(-2)
is_expected.to eq({ deleted_count: 2, deleted_ids: [instance_runner.id, project_runner.id] })
is_expected.to be_success
expect(execute.payload).to eq({ deleted_count: 2, deleted_ids: [instance_runner.id, project_runner.id] })
expect(instance_runner[:errors]).to be_nil
expect(project_runner[:errors]).to be_nil
expect { project_runner.runner_projects.first.reload }.to raise_error(ActiveRecord::RecordNotFound)
@ -36,7 +37,8 @@ RSpec.describe ::Ci::Runners::BulkDeleteRunnersService, '#execute' do
it 'destroys runners and returns only deleted runners', :aggregate_failures do
expect { subject }.to change { Ci::Runner.count }.by(-1)
is_expected.to eq({ deleted_count: 1, deleted_ids: [project_runner.id] })
is_expected.to be_success
expect(execute.payload).to eq({ deleted_count: 1, deleted_ids: [project_runner.id] })
expect(instance_runner[:errors]).to be_nil
expect(project_runner[:errors]).to be_nil
expect { project_runner.reload }.to raise_error(ActiveRecord::RecordNotFound)
@ -51,7 +53,8 @@ RSpec.describe ::Ci::Runners::BulkDeleteRunnersService, '#execute' do
it 'deletes only first RUNNER_LIMIT runners' do
expect { subject }.to change { Ci::Runner.count }.by(-1)
is_expected.to eq({ deleted_count: 1, deleted_ids: [instance_runner.id] })
is_expected.to be_success
expect(execute.payload).to eq({ deleted_count: 1, deleted_ids: [instance_runner.id] })
end
end
end
@ -72,7 +75,8 @@ RSpec.describe ::Ci::Runners::BulkDeleteRunnersService, '#execute' do
let(:runners_arg) { nil }
it 'returns 0 deleted runners' do
is_expected.to eq({ deleted_count: 0, deleted_ids: [] })
is_expected.to be_success
expect(execute.payload).to eq({ deleted_count: 0, deleted_ids: [] })
end
end
end