Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
b1c4066c6b
commit
8d96319c80
|
@ -1,19 +1,27 @@
|
|||
<script>
|
||||
import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
|
||||
import SnippetHeader from './snippet_header.vue';
|
||||
import SnippetTitle from './snippet_title.vue';
|
||||
import SnippetBlob from './snippet_blob_view.vue';
|
||||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
|
||||
import { getSnippetMixin } from '../mixins/snippets';
|
||||
import { SNIPPET_VISIBILITY_PUBLIC } from '~/snippets/constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BlobEmbeddable,
|
||||
SnippetHeader,
|
||||
SnippetTitle,
|
||||
GlLoadingIcon,
|
||||
SnippetBlob,
|
||||
},
|
||||
mixins: [getSnippetMixin],
|
||||
computed: {
|
||||
embeddable() {
|
||||
return this.snippet.visibilityLevel === SNIPPET_VISIBILITY_PUBLIC;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
|
@ -27,7 +35,10 @@ export default {
|
|||
<template v-else>
|
||||
<snippet-header :snippet="snippet" />
|
||||
<snippet-title :snippet="snippet" />
|
||||
<snippet-blob :snippet="snippet" />
|
||||
<blob-embeddable v-if="embeddable" class="gl-mb-5" :url="snippet.webUrl" />
|
||||
<div v-for="blob in blobs" :key="blob.path">
|
||||
<snippet-blob :snippet="snippet" :blob="blob" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
<script>
|
||||
import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
|
||||
import { SNIPPET_VISIBILITY_PUBLIC } from '../constants';
|
||||
import BlobHeader from '~/blob/components/blob_header.vue';
|
||||
import BlobContent from '~/blob/components/blob_content.vue';
|
||||
import CloneDropdownButton from '~/vue_shared/components/clone_dropdown.vue';
|
||||
|
@ -16,7 +14,6 @@ import {
|
|||
|
||||
export default {
|
||||
components: {
|
||||
BlobEmbeddable,
|
||||
BlobHeader,
|
||||
BlobContent,
|
||||
CloneDropdownButton,
|
||||
|
@ -49,21 +46,19 @@ export default {
|
|||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
blob: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
blob: this.snippet.blob,
|
||||
blobContent: '',
|
||||
activeViewerType:
|
||||
this.snippet.blob?.richViewer && !window.location.hash
|
||||
? RICH_BLOB_VIEWER
|
||||
: SIMPLE_BLOB_VIEWER,
|
||||
this.blob?.richViewer && !window.location.hash ? RICH_BLOB_VIEWER : SIMPLE_BLOB_VIEWER,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
embeddable() {
|
||||
return this.snippet.visibilityLevel === SNIPPET_VISIBILITY_PUBLIC;
|
||||
},
|
||||
isContentLoading() {
|
||||
return this.$apollo.queries.blobContent.loading;
|
||||
},
|
||||
|
@ -92,33 +87,30 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<blob-embeddable v-if="embeddable" class="mb-3" :url="snippet.webUrl" />
|
||||
<article class="file-holder snippet-file-content">
|
||||
<blob-header
|
||||
:blob="blob"
|
||||
:active-viewer-type="viewer.type"
|
||||
:has-render-error="hasRenderError"
|
||||
@viewer-changed="switchViewer"
|
||||
>
|
||||
<template #actions>
|
||||
<clone-dropdown-button
|
||||
v-if="canBeCloned"
|
||||
class="mr-2"
|
||||
:ssh-link="snippet.sshUrlToRepo"
|
||||
:http-link="snippet.httpUrlToRepo"
|
||||
data-qa-selector="clone_button"
|
||||
/>
|
||||
</template>
|
||||
</blob-header>
|
||||
<blob-content
|
||||
:loading="isContentLoading"
|
||||
:content="blobContent"
|
||||
:active-viewer="viewer"
|
||||
:blob="blob"
|
||||
@[$options.BLOB_RENDER_EVENT_LOAD]="forceQuery"
|
||||
@[$options.BLOB_RENDER_EVENT_SHOW_SOURCE]="switchViewer"
|
||||
/>
|
||||
</article>
|
||||
</div>
|
||||
<article class="file-holder snippet-file-content">
|
||||
<blob-header
|
||||
:blob="blob"
|
||||
:active-viewer-type="viewer.type"
|
||||
:has-render-error="hasRenderError"
|
||||
@viewer-changed="switchViewer"
|
||||
>
|
||||
<template #actions>
|
||||
<clone-dropdown-button
|
||||
v-if="canBeCloned"
|
||||
class="gl-mr-3"
|
||||
:ssh-link="snippet.sshUrlToRepo"
|
||||
:http-link="snippet.httpUrlToRepo"
|
||||
data-qa-selector="clone_button"
|
||||
/>
|
||||
</template>
|
||||
</blob-header>
|
||||
<blob-content
|
||||
:loading="isContentLoading"
|
||||
:content="blobContent"
|
||||
:active-viewer="viewer"
|
||||
:blob="blob"
|
||||
@[$options.BLOB_RENDER_EVENT_LOAD]="forceQuery"
|
||||
@[$options.BLOB_RENDER_EVENT_SHOW_SOURCE]="switchViewer"
|
||||
/>
|
||||
</article>
|
||||
</template>
|
||||
|
|
|
@ -65,14 +65,17 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
snippetHasBinary() {
|
||||
return Boolean(this.snippet.blobs.find(blob => blob.binary));
|
||||
},
|
||||
personalSnippetActions() {
|
||||
return [
|
||||
{
|
||||
condition: this.snippet.userPermissions.updateSnippet,
|
||||
text: __('Edit'),
|
||||
href: this.editLink,
|
||||
disabled: this.snippet.blob.binary,
|
||||
title: this.snippet.blob.binary
|
||||
disabled: this.snippetHasBinary,
|
||||
title: this.snippetHasBinary
|
||||
? __('Snippets with non-text files can only be edited via Git.')
|
||||
: undefined,
|
||||
},
|
||||
|
|
|
@ -11,7 +11,7 @@ fragment SnippetBase on Snippet {
|
|||
webUrl
|
||||
httpUrlToRepo
|
||||
sshUrlToRepo
|
||||
blob {
|
||||
blobs {
|
||||
binary
|
||||
name
|
||||
path
|
||||
|
|
|
@ -11,6 +11,7 @@ export const getSnippetMixin = {
|
|||
},
|
||||
update: data => data.snippets.edges[0]?.node,
|
||||
result(res) {
|
||||
this.blobs = res.data.snippets.edges[0].node.blobs;
|
||||
if (this.onSnippetFetch) {
|
||||
this.onSnippetFetch(res);
|
||||
}
|
||||
|
@ -27,6 +28,7 @@ export const getSnippetMixin = {
|
|||
return {
|
||||
snippet: {},
|
||||
newSnippet: false,
|
||||
blobs: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
|
@ -100,26 +100,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.onboarding-popover {
|
||||
box-shadow: 0 2px 4px $dropdown-shadow-color;
|
||||
max-width: 280px;
|
||||
|
||||
.popover-body {
|
||||
font-size: $gl-font-size;
|
||||
line-height: $gl-line-height;
|
||||
padding: $gl-padding;
|
||||
}
|
||||
|
||||
.popover-header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.accept-mr-label {
|
||||
background-color: $accepting-mr-label-color;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* user_popover component
|
||||
*/
|
||||
|
@ -132,13 +112,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.onboarding-welcome-page {
|
||||
.popover {
|
||||
min-width: auto;
|
||||
max-width: 40%;
|
||||
}
|
||||
}
|
||||
|
||||
.suggest-gitlab-ci-yml {
|
||||
margin-top: -1em;
|
||||
|
||||
|
|
|
@ -549,41 +549,6 @@ img.emoji {
|
|||
}
|
||||
}
|
||||
|
||||
.onboarding-helper-container {
|
||||
bottom: 40px;
|
||||
right: 40px;
|
||||
font-size: $gl-font-size-small;
|
||||
background: $gray-50;
|
||||
width: 200px;
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 2px 4px $issue-boards-card-shadow;
|
||||
z-index: 10000;
|
||||
|
||||
.collapsible {
|
||||
max-height: 0;
|
||||
transition: max-height 0.5s cubic-bezier(0, 1, 0, 1);
|
||||
}
|
||||
|
||||
&.expanded {
|
||||
border-bottom-right-radius: $border-radius-default;
|
||||
border-bottom-left-radius: $border-radius-default;
|
||||
|
||||
.collapsible {
|
||||
max-height: 1000px;
|
||||
transition: max-height 1s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
border-color: darken($gray-normal, 10%);
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.gl-font-sm { font-size: $gl-font-size-small; }
|
||||
.gl-font-lg { font-size: $gl-font-size-large; }
|
||||
.gl-font-base { font-size: $gl-font-size-14; }
|
||||
|
|
|
@ -711,7 +711,6 @@ $input-lg-width: 320px;
|
|||
*/
|
||||
$document-index-color: #888;
|
||||
$help-shortcut-header-color: #333;
|
||||
$accepting-mr-label-color: #69d100;
|
||||
|
||||
/*
|
||||
* Issues
|
||||
|
|
|
@ -12,5 +12,6 @@ module Types
|
|||
field :build_artifacts_size, GraphQL::FLOAT_TYPE, null: false, description: 'The CI artifacts size in bytes'
|
||||
field :packages_size, GraphQL::FLOAT_TYPE, null: false, description: 'The packages size in bytes'
|
||||
field :wiki_size, GraphQL::FLOAT_TYPE, null: false, description: 'The wiki size in bytes'
|
||||
field :snippets_size, GraphQL::FLOAT_TYPE, null: false, description: 'The snippets size in bytes'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,6 +13,4 @@
|
|||
= render 'layouts/page', sidebar: sidebar, nav: nav
|
||||
= footer_message
|
||||
|
||||
= render_if_exists "shared/onboarding_guide"
|
||||
|
||||
= yield :scripts_body
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
= link_to _("Help"), help_path
|
||||
%li.d-md-none
|
||||
= link_to _("Support"), support_url
|
||||
= render_if_exists "shared/learn_gitlab_menu_item"
|
||||
%li.d-md-none
|
||||
= link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback"
|
||||
- if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile)
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
%button.js-shortcuts-modal-trigger{ type: "button" }
|
||||
= _("Keyboard shortcuts")
|
||||
%span.text-secondary.float-right{ "aria-hidden": true }= '?'.html_safe
|
||||
= render_if_exists "shared/learn_gitlab_menu_item"
|
||||
%li.divider
|
||||
%li
|
||||
= link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Accept multiple blobs in snippets
|
||||
merge_request: 35605
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add snippets_size to RootStorageStatisticsType
|
||||
merge_request: 35586
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add instrumentation to Gitaly streamed responses
|
||||
merge_request: 35283
|
||||
author:
|
||||
type: fixed
|
|
@ -159,7 +159,7 @@ successfully, you must replicate their data using some other means.
|
|||
| [Composer Repository](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | No | |
|
||||
| [External merge request diffs](../../merge_request_diffs.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/33817) | No | |
|
||||
| [Terraform State](../../terraform_state.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/3112)(*3*) | No | |
|
||||
| [Vulnerability Export](../../../user/application_security/security_dashboard/#export-vulnerabilities-1) | [No](https://gitlab.com/groups/gitlab-org/-/epics/3111)(*3*) | No | | |
|
||||
| [Vulnerability Export](../../../user/application_security/security_dashboard/#export-vulnerabilities) | [No](https://gitlab.com/groups/gitlab-org/-/epics/3111)(*3*) | No | | |
|
||||
| Content in object storage | **Yes** (12.4) | No | |
|
||||
|
||||
- (*1*): The integrity can be verified manually using
|
||||
|
|
|
@ -11244,6 +11244,11 @@ type RootStorageStatistics {
|
|||
"""
|
||||
repositorySize: Float!
|
||||
|
||||
"""
|
||||
The snippets size in bytes
|
||||
"""
|
||||
snippetsSize: Float!
|
||||
|
||||
"""
|
||||
The total storage in bytes
|
||||
"""
|
||||
|
|
|
@ -33011,6 +33011,24 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "snippetsSize",
|
||||
"description": "The snippets size in bytes",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Float",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "storageSize",
|
||||
"description": "The total storage in bytes",
|
||||
|
|
|
@ -1623,6 +1623,7 @@ Counts of requirements by their state.
|
|||
| `lfsObjectsSize` | Float! | The LFS objects size in bytes |
|
||||
| `packagesSize` | Float! | The packages size in bytes |
|
||||
| `repositorySize` | Float! | The Git repository size in bytes |
|
||||
| `snippetsSize` | Float! | The snippets size in bytes |
|
||||
| `storageSize` | Float! | The total storage in bytes |
|
||||
| `wikiSize` | Float! | The wiki size in bytes |
|
||||
|
||||
|
|
|
@ -35,16 +35,20 @@ Use shared Runners when you have multiple jobs with similar requirements. Rather
|
|||
having multiple Runners idling for many projects, you can have a few Runners that handle
|
||||
multiple projects.
|
||||
|
||||
If you are using a self-managed instance of GitLab, your administrator can create
|
||||
shared Runners and configure them to use the
|
||||
[executor](https://docs.gitlab.com/runner/executors/README.html) you want.
|
||||
The administrator can also configure a maximum number of Shared Runner [pipeline minutes for
|
||||
each group](../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota-starter-only).
|
||||
If you are using a self-managed instance of GitLab:
|
||||
|
||||
If you are using GitLab.com, you can select from a list of
|
||||
[shared Runners that GitLab maintains](../../user/gitlab_com/index.md#shared-runners).
|
||||
When you use the GitLab.com shared Runners, they consume the
|
||||
[pipelines minutes](../../subscriptions/index.md#ci-pipeline-minutes) included with your account.
|
||||
- Your administrator can
|
||||
[install](https://docs.gitlab.com/runner/install/index.html)
|
||||
and [register](https://docs.gitlab.com/runner/register/index.html) shared Runners,
|
||||
and configure them to use the [executor](https://docs.gitlab.com/runner/executors/README.html) you want.
|
||||
- The administrator can also configure a maximum number of shared Runner [pipeline minutes for
|
||||
each group](../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota-starter-only).
|
||||
|
||||
If you are using GitLab.com:
|
||||
|
||||
- You can select from a list of [shared Runners that GitLab maintains](../../user/gitlab_com/index.md#shared-runners).
|
||||
- The shared Runners consume the [pipelines minutes](../../subscriptions/index.md#ci-pipeline-minutes)
|
||||
included with your account.
|
||||
|
||||
#### How shared Runners pick jobs
|
||||
|
||||
|
@ -101,7 +105,9 @@ The fair usage algorithm assigns jobs in this order:
|
|||
|
||||
#### Enable a shared Runner
|
||||
|
||||
By default, all projects can use shared Runners, and they are enabled by default.
|
||||
On GitLab.com, or after a self-managed GitLab administrator has installed and
|
||||
registered them, [shared Runners](#shared-runners) are enabled in all projects by
|
||||
default.
|
||||
|
||||
However, you can enable or disable shared Runners for individual projects.
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 53 KiB |
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
|
@ -12,7 +12,7 @@ vulnerabilities in your groups, projects and pipelines.
|
|||
|
||||
You can also drill down into a vulnerability and get extra information, see which
|
||||
project it comes from, the file it's in, and various metadata to help you analyze
|
||||
the risk. You can also action these vulnerabilities by creating an issue for them,
|
||||
the risk. You can also take actions on vulnerabilities by creating an issue for them,
|
||||
or by dismissing them.
|
||||
|
||||
To benefit from the Security Dashboard you must first configure one of the
|
||||
|
@ -54,56 +54,52 @@ A pipeline consists of multiple jobs, including SAST and DAST scanning. If any j
|
|||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6165) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.1.
|
||||
|
||||
At the project level, the Security Dashboard displays the latest security reports for your project.
|
||||
Use it to find and fix vulnerabilities.
|
||||
At the project level, the Security Dashboard displays the vulnerabilities merged into your project's
|
||||
[default branch](../../project/repository/branches/index.md#default-branch). Access it by navigating
|
||||
to **Security & Compliance > Security Dashboard**.
|
||||
|
||||
![Project Security Dashboard](img/project_security_dashboard_v13_0.png)
|
||||
The Security Dashboard first displays the total number of vulnerabilities by severity (for example,
|
||||
Critical, High, Medium, Low). Below this, a table displays each vulnerability's status, severity,
|
||||
and description. Clicking a vulnerability takes you to its [Vulnerability Details](../vulnerabilities)
|
||||
page to view more information about that vulnerability.
|
||||
|
||||
### Export vulnerabilities
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/197494) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
|
||||
|
||||
You can export all your project's vulnerabilities as CSV by clicking on the export button located at top right of the Project Security Dashboard. This will initiate the process, and once complete, the CSV report will be downloaded. The report will contain all vulnerabilities in the project as filters won't apply.
|
||||
|
||||
NOTE: **Note:**
|
||||
It may take several minutes for the download to start if your project consists
|
||||
of thousands of vulnerabilities. Do not close the page until the download finishes.
|
||||
|
||||
![CSV Export Button](img/project_security_dashboard_export_csv_v12_10.png)
|
||||
|
||||
## Group Security Dashboard
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6709) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5.
|
||||
|
||||
The group Security Dashboard gives an overview of the vulnerabilities of all the
|
||||
projects in a group and its subgroups.
|
||||
|
||||
First, navigate to the Security Dashboard found under your group's
|
||||
**Security** tab.
|
||||
|
||||
Once you're on the dashboard, at the top you should see a series of filters for:
|
||||
You can filter the vulnerabilities by:
|
||||
|
||||
- Status
|
||||
- Severity
|
||||
- Report type
|
||||
|
||||
You can also dismiss vulnerabilities in the table:
|
||||
|
||||
1. Select the checkbox for each vulnerability you want to dismiss.
|
||||
1. In the menu that appears, select the reason for dismissal and click **Dismiss Selected**.
|
||||
|
||||
![Project Security Dashboard](img/project_security_dashboard_v13_2_noNav.png)
|
||||
|
||||
## Group Security Dashboard
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6709) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5.
|
||||
|
||||
The group Security Dashboard gives an overview of the vulnerabilities in the default branches of the
|
||||
projects in a group and its subgroups. Access it by navigating to **Security > Security Dashboard**
|
||||
for your group.
|
||||
|
||||
NOTE: **Note:**
|
||||
The dashboard only shows projects with [security reports](#supported-reports) enabled in a group.
|
||||
The Security Dashboard only shows projects with [security reports](#supported-reports) enabled in a
|
||||
group.
|
||||
|
||||
![Dashboard with action buttons and metrics](img/group_security_dashboard_v13_2.png)
|
||||
![Dashboard with action buttons and metrics](img/group_security_dashboard_v13_2_noNav.png)
|
||||
|
||||
Selecting one or more filters will filter the results in this page.
|
||||
You can filter which vulnerabilities the Security Dashboard displays by:
|
||||
|
||||
The main section is a list of all the vulnerabilities in the group, sorted by severity.
|
||||
In that list, you can see the severity of the vulnerability, its name, its
|
||||
confidence (likelihood of the vulnerability to be a positive one), and the project
|
||||
it's from.
|
||||
- Status
|
||||
- Severity
|
||||
- Report type
|
||||
- Project
|
||||
|
||||
If you hover over a row, the following actions appear:
|
||||
|
||||
- More info
|
||||
- Create issue
|
||||
- Dismiss vulnerability
|
||||
A table lists the vulnerabilities, sorted by severity. The table shows each vulnerability's status,
|
||||
severity, and description. Clicking a vulnerability takes you to its [Vulnerability Details](../vulnerabilities)
|
||||
page to view more information about that vulnerability.
|
||||
|
||||
Next to the list is a timeline chart that shows how many open
|
||||
vulnerabilities your projects had at various points in time. You can filter among 30, 60, and
|
||||
|
@ -123,28 +119,14 @@ vulnerabilities are not included either.
|
|||
|
||||
Read more on how to [interact with the vulnerabilities](../index.md#interacting-with-the-vulnerabilities).
|
||||
|
||||
### Export vulnerabilities
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213013) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1.
|
||||
|
||||
You can export all your vulnerabilities as CSV by clicking the **{upload}** **Export** button
|
||||
located at the top right of the **Group Security Dashboard**. After the report builds, the CSV
|
||||
report downloads to your local machine. The report contains all vulnerabilities for the projects
|
||||
defined in the **Group Security Dashboard**, as filters don't apply to the export function.
|
||||
|
||||
NOTE: **Note:**
|
||||
It may take several minutes for the download to start if your project contains thousands of
|
||||
vulnerabilities. Don't close the page until the download finishes.
|
||||
|
||||
![CSV Export Button](img/group_security_dashboard_export_csv_v13_1.png)
|
||||
|
||||
## Instance Security Dashboard
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6953) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.8.
|
||||
|
||||
At the instance level, the Security Dashboard displays the vulnerabilities
|
||||
present in all of the projects that you have added to it. It includes all
|
||||
of the features of the [group security dashboard](#group-security-dashboard).
|
||||
At the instance level, the Security Dashboard displays the vulnerabilities present in the default
|
||||
branches of all the projects you configure to display on the dashboard. It includes all the
|
||||
[group Security Dashboard's](#group-security-dashboard)
|
||||
features.
|
||||
|
||||
You can access the Instance Security Dashboard from the menu
|
||||
bar at the top of the page. Under **More**, select **Security**.
|
||||
|
@ -159,27 +141,25 @@ To add projects to the dashboard:
|
|||
1. Search for and add one or more projects using the **Search your projects** field.
|
||||
1. Click the **Add projects** button.
|
||||
|
||||
Once added, the dashboard will display the vulnerabilities found in your chosen
|
||||
projects.
|
||||
Once added, the Security Dashboard displays the vulnerabilities found in your chosen projects'
|
||||
default branches.
|
||||
|
||||
![Instance Security Dashboard with projects](img/instance_security_dashboard_with_projects_v13_2.png)
|
||||
![Instance Security Dashboard with projects](img/instance_security_dashboard_with_projects_v13_2_sm.png)
|
||||
|
||||
### Export vulnerabilities
|
||||
## Export vulnerabilities
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213014) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0.
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213014) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
|
||||
|
||||
You can export all your vulnerabilities as CSV by clicking the **{upload}** **Export**
|
||||
button located at top right of the **Instance Security Dashboard**. After the report
|
||||
You can export all your vulnerabilities in CSV format by clicking the **{upload}** **Export**
|
||||
button located at top right of the **Security Dashboard**. After the report
|
||||
is built, the CSV report downloads to your local machine. The report contains all
|
||||
vulnerabilities for the projects defined in the **Instance Security Dashboard**,
|
||||
vulnerabilities for the projects defined in the **Security Dashboard**,
|
||||
as filters don't apply to the export function.
|
||||
|
||||
NOTE: **Note:**
|
||||
It may take several minutes for the download to start if your project contains
|
||||
thousands of vulnerabilities. Do not close the page until the download finishes.
|
||||
|
||||
![CSV Export Button](img/instance_security_dashboard_export_csv_v13_0.png)
|
||||
|
||||
## Keeping the dashboards up to date
|
||||
|
||||
The Security Dashboard displays information from the results of the most recent
|
||||
|
@ -205,7 +185,8 @@ to configure daily security scans.
|
|||
|
||||
## Vulnerability list
|
||||
|
||||
Each dashboard's vulnerability list contains new vulnerabilities discovered in the latest scans.
|
||||
Each dashboard's vulnerability list contains vulnerabilities from the latest scans that were merged
|
||||
into the default branch.
|
||||
Click any vulnerability in the table to see more information on that vulnerability. To create an
|
||||
issue associated with the vulnerability, click the **Create Issue** button.
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ Google Kubernetes Engine Integration. All you have to do is [follow this link](h
|
|||
Before [adding a Kubernetes cluster](#create-new-cluster) using GitLab, you need:
|
||||
|
||||
- GitLab itself. Either:
|
||||
- A GitLab.com [account](https://about.gitlab.com/pricing/#gitlab-com).
|
||||
- A [GitLab.com account](https://about.gitlab.com/pricing/#gitlab-com).
|
||||
- A [self-managed installation](https://about.gitlab.com/pricing/#self-managed) with GitLab version
|
||||
12.5 or later. This will ensure the GitLab UI can be used for cluster creation.
|
||||
- The following GitLab access:
|
||||
|
@ -131,7 +131,7 @@ arbitrary images as they effectively have root access.
|
|||
If you don't want to use GitLab Runner in privileged mode, either:
|
||||
|
||||
- Use shared Runners on GitLab.com. They don't have this security issue.
|
||||
- Set up your own Runners using configuration described at
|
||||
- Set up your own Runners using the configuration described at
|
||||
[Shared Runners](../../gitlab_com/index.md#shared-runners). This involves:
|
||||
1. Making sure that you don't have it installed via
|
||||
[the applications](index.md#installing-applications).
|
||||
|
@ -140,10 +140,18 @@ If you don't want to use GitLab Runner in privileged mode, either:
|
|||
|
||||
## Create new cluster
|
||||
|
||||
New clusters can be created using GitLab for:
|
||||
New clusters can be created using GitLab on Google Kubernetes Engine (GKE) or
|
||||
Amazon Elastic Kubernetes Service (EKS) at the project, group, or instance level:
|
||||
|
||||
- [Google Kubernetes Engine (GKE)](add_gke_clusters.md).
|
||||
- [Amazon Elastic Kubernetes Service (EKS)](add_eks_clusters.md).
|
||||
1. Navigate to your:
|
||||
- Project's **{cloud-gear}** **Operations > Kubernetes** page, for a project-level cluster.
|
||||
- Group's **{cloud-gear}** **Kubernetes** page, for a group-level cluster.
|
||||
- **{admin}** **Admin Area >** **{cloud-gear}** **Kubernetes** page, for an instance-level cluster.
|
||||
1. Click **Add Kubernetes cluster**.
|
||||
1. Click the **Create new cluster** tab.
|
||||
1. Click either **Amazon EKS** or **Google GKE**, and follow the instructions for your desired service:
|
||||
- [Amazon EKS](add_eks_clusters.md#new-eks-cluster).
|
||||
- [Google GKE](add_gke_clusters.md#creating-the-cluster-on-gke).
|
||||
|
||||
## Add existing cluster
|
||||
|
||||
|
@ -156,7 +164,7 @@ For more information, see information for adding an:
|
|||
|
||||
NOTE: **Note:**
|
||||
Kubernetes integration is not supported for arm64 clusters. See the issue
|
||||
[Helm Tiller fails to install on arm64 cluster](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64044) for details.
|
||||
[Helm Tiller fails to install on arm64 cluster](https://gitlab.com/gitlab-org/gitlab/-/issues/29838) for details.
|
||||
|
||||
### Existing Kubernetes cluster
|
||||
|
||||
|
@ -302,12 +310,12 @@ to install some [pre-defined applications](index.md#installing-applications).
|
|||
|
||||
When connecting a cluster via GitLab integration, you may specify whether the
|
||||
cluster is RBAC-enabled or not. This will affect how GitLab interacts with the
|
||||
cluster for certain operations. If you **did not** check the "RBAC-enabled cluster"
|
||||
cluster for certain operations. If you did *not* check the **RBAC-enabled cluster**
|
||||
checkbox at creation time, GitLab will assume RBAC is disabled for your cluster
|
||||
when interacting with it. If so, you must disable RBAC on your cluster for the
|
||||
integration to work properly.
|
||||
|
||||
![rbac](img/rbac.png)
|
||||
![rbac](img/rbac_v13_1.png)
|
||||
|
||||
NOTE: **Note**: Disabling RBAC means that any application running in the cluster,
|
||||
or user who can authenticate to the cluster, has full API access. This is a
|
||||
|
@ -325,17 +333,20 @@ kubectl create clusterrolebinding permissive-binding \
|
|||
|
||||
## Enabling or disabling integration
|
||||
|
||||
After you have successfully added your cluster information, you can enable the
|
||||
Kubernetes cluster integration:
|
||||
The Kubernetes cluster integration enables after you have successfully either created
|
||||
a new cluster or added an existing one. To disable Kubernetes cluster integration:
|
||||
|
||||
1. Click the **Enabled/Disabled** switch
|
||||
1. Hit **Save** for the changes to take effect
|
||||
|
||||
To disable the Kubernetes cluster integration, follow the same procedure.
|
||||
1. Navigate to your:
|
||||
- Project's **{cloud-gear}** **Operations > Kubernetes** page, for a project-level cluster.
|
||||
- Group's **{cloud-gear}** **Kubernetes** page, for a group-level cluster.
|
||||
- **{admin}** **Admin Area >** **{cloud-gear}** **Kubernetes** page, for an instance-level cluster.
|
||||
1. Click on the name of the cluster.
|
||||
1. Click the **GitLab Integration** toggle.
|
||||
1. Click **Save changes**.
|
||||
|
||||
## Removing integration
|
||||
|
||||
To remove the Kubernetes cluster integration from your project, either:
|
||||
To remove the Kubernetes cluster integration from your project, first navigate to the **Advanced Settings** tab of the cluster details page and either:
|
||||
|
||||
- Select **Remove integration**, to remove only the Kubernetes integration.
|
||||
- [From GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/26815), select
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
|
@ -166,20 +166,7 @@ module Gitlab
|
|||
# "gitaly-2 is at network address tcp://10.0.1.2:8075".
|
||||
#
|
||||
def self.call(storage, service, rpc, request, remote_storage: nil, timeout: default_timeout, &block)
|
||||
self.measure_timings(service, rpc, request) do
|
||||
self.execute(storage, service, rpc, request, remote_storage: remote_storage, timeout: timeout, &block)
|
||||
end
|
||||
end
|
||||
|
||||
# This method is like GitalyClient.call but should be used with
|
||||
# Gitaly streaming RPCs. It measures how long the the RPC took to
|
||||
# produce the full response, not just the initial response.
|
||||
def self.streaming_call(storage, service, rpc, request, remote_storage: nil, timeout: default_timeout)
|
||||
self.measure_timings(service, rpc, request) do
|
||||
response = self.execute(storage, service, rpc, request, remote_storage: remote_storage, timeout: timeout)
|
||||
|
||||
yield(response)
|
||||
end
|
||||
Gitlab::GitalyClient::Call.new(storage, service, rpc, request, remote_storage, timeout).call(&block)
|
||||
end
|
||||
|
||||
def self.execute(storage, service, rpc, request, remote_storage:, timeout:)
|
||||
|
@ -192,23 +179,6 @@ module Gitlab
|
|||
stub(service, storage).__send__(rpc, request, kwargs) # rubocop:disable GitlabSecurity/PublicSend
|
||||
end
|
||||
|
||||
def self.measure_timings(service, rpc, request)
|
||||
start = Gitlab::Metrics::System.monotonic_time
|
||||
|
||||
yield
|
||||
ensure
|
||||
duration = Gitlab::Metrics::System.monotonic_time - start
|
||||
request_hash = request.is_a?(Google::Protobuf::MessageExts) ? request.to_h : {}
|
||||
|
||||
# Keep track, separately, for the performance bar
|
||||
self.add_query_time(duration)
|
||||
|
||||
if Gitlab::PerformanceBar.enabled_for_request?
|
||||
add_call_details(feature: "#{service}##{rpc}", duration: duration, request: request_hash, rpc: rpc,
|
||||
backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller))
|
||||
end
|
||||
end
|
||||
|
||||
def self.query_time
|
||||
query_time = Gitlab::SafeRequestStore[:gitaly_query_time] || 0
|
||||
query_time.round(Gitlab::InstrumentationHelper::DURATION_PRECISION)
|
||||
|
|
|
@ -15,9 +15,8 @@ module Gitlab
|
|||
oid: oid,
|
||||
limit: limit
|
||||
)
|
||||
GitalyClient.streaming_call(@gitaly_repo.storage_name, :blob_service, :get_blob, request, timeout: GitalyClient.fast_timeout) do |response|
|
||||
consume_blob_response(response)
|
||||
end
|
||||
response = GitalyClient.call(@gitaly_repo.storage_name, :blob_service, :get_blob, request, timeout: GitalyClient.fast_timeout)
|
||||
consume_blob_response(response)
|
||||
end
|
||||
|
||||
def batch_lfs_pointers(blob_ids)
|
||||
|
@ -28,9 +27,8 @@ module Gitlab
|
|||
blob_ids: blob_ids
|
||||
)
|
||||
|
||||
GitalyClient.streaming_call(@gitaly_repo.storage_name, :blob_service, :get_lfs_pointers, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
map_lfs_pointers(response)
|
||||
end
|
||||
response = GitalyClient.call(@gitaly_repo.storage_name, :blob_service, :get_lfs_pointers, request, timeout: GitalyClient.medium_timeout)
|
||||
map_lfs_pointers(response)
|
||||
end
|
||||
|
||||
def get_blobs(revision_paths, limit = -1)
|
||||
|
@ -46,15 +44,14 @@ module Gitlab
|
|||
limit: limit
|
||||
)
|
||||
|
||||
GitalyClient.streaming_call(
|
||||
response = GitalyClient.call(
|
||||
@gitaly_repo.storage_name,
|
||||
:blob_service,
|
||||
:get_blobs,
|
||||
request,
|
||||
timeout: GitalyClient.fast_timeout
|
||||
) do |response|
|
||||
GitalyClient::BlobsStitcher.new(response)
|
||||
end
|
||||
timeout: GitalyClient.fast_timeout)
|
||||
|
||||
GitalyClient::BlobsStitcher.new(response)
|
||||
end
|
||||
|
||||
def get_blob_types(revision_paths, limit = -1)
|
||||
|
@ -70,15 +67,14 @@ module Gitlab
|
|||
limit: limit
|
||||
)
|
||||
|
||||
GitalyClient.streaming_call(
|
||||
response = GitalyClient.call(
|
||||
@gitaly_repo.storage_name,
|
||||
:blob_service,
|
||||
:get_blobs,
|
||||
request,
|
||||
timeout: GitalyClient.fast_timeout
|
||||
) do |response|
|
||||
map_blob_types(response)
|
||||
end
|
||||
)
|
||||
map_blob_types(response)
|
||||
end
|
||||
|
||||
def get_new_lfs_pointers(revision, limit, not_in, dynamic_timeout = nil)
|
||||
|
@ -101,15 +97,14 @@ module Gitlab
|
|||
GitalyClient.medium_timeout
|
||||
end
|
||||
|
||||
GitalyClient.streaming_call(
|
||||
response = GitalyClient.call(
|
||||
@gitaly_repo.storage_name,
|
||||
:blob_service,
|
||||
:get_new_lfs_pointers,
|
||||
request,
|
||||
timeout: timeout
|
||||
) do |response|
|
||||
map_lfs_pointers(response)
|
||||
end
|
||||
)
|
||||
map_lfs_pointers(response)
|
||||
end
|
||||
|
||||
def get_all_lfs_pointers
|
||||
|
@ -117,9 +112,8 @@ module Gitlab
|
|||
repository: @gitaly_repo
|
||||
)
|
||||
|
||||
GitalyClient.streaming_call(@gitaly_repo.storage_name, :blob_service, :get_all_lfs_pointers, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
map_lfs_pointers(response)
|
||||
end
|
||||
response = GitalyClient.call(@gitaly_repo.storage_name, :blob_service, :get_all_lfs_pointers, request, timeout: GitalyClient.medium_timeout)
|
||||
map_lfs_pointers(response)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module GitalyClient
|
||||
class Call
|
||||
def initialize(storage, service, rpc, request, remote_storage, timeout)
|
||||
@storage = storage
|
||||
@service = service
|
||||
@rpc = rpc
|
||||
@request = request
|
||||
@remote_storage = remote_storage
|
||||
@timeout = timeout
|
||||
@duration = 0
|
||||
end
|
||||
|
||||
def call(&block)
|
||||
response = recording_request do
|
||||
GitalyClient.execute(@storage, @service, @rpc, @request, remote_storage: @remote_storage, timeout: @timeout, &block)
|
||||
end
|
||||
|
||||
if response.is_a?(Enumerator)
|
||||
# When the given response is an enumerator (coming from streamed
|
||||
# responses), we wrap it in order to properly measure the stream
|
||||
# consumption as it happens.
|
||||
#
|
||||
# store_timings is not called in that scenario as needs to be
|
||||
# handled lazily in the custom Enumerator context.
|
||||
instrument_stream(response)
|
||||
else
|
||||
store_timings
|
||||
response
|
||||
end
|
||||
rescue => err
|
||||
store_timings
|
||||
raise err
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def instrument_stream(response)
|
||||
Enumerator.new do |yielder|
|
||||
loop do
|
||||
value = recording_request { response.next }
|
||||
|
||||
yielder.yield(value)
|
||||
end
|
||||
ensure
|
||||
store_timings
|
||||
end
|
||||
end
|
||||
|
||||
def recording_request
|
||||
start = Gitlab::Metrics::System.monotonic_time
|
||||
|
||||
yield
|
||||
ensure
|
||||
@duration += Gitlab::Metrics::System.monotonic_time - start
|
||||
end
|
||||
|
||||
def store_timings
|
||||
GitalyClient.add_query_time(@duration)
|
||||
|
||||
return unless Gitlab::PerformanceBar.enabled_for_request?
|
||||
|
||||
request_hash = @request.is_a?(Google::Protobuf::MessageExts) ? @request.to_h : {}
|
||||
|
||||
GitalyClient.add_call_details(feature: "#{@service}##{@rpc}", duration: @duration, request: request_hash, rpc: @rpc,
|
||||
backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -13,15 +13,14 @@ module Gitlab
|
|||
end
|
||||
|
||||
def apply_bfg_object_map_stream(io, &blk)
|
||||
GitalyClient.streaming_call(
|
||||
response = GitalyClient.call(
|
||||
storage,
|
||||
:cleanup_service,
|
||||
:apply_bfg_object_map_stream,
|
||||
build_object_map_enum(io),
|
||||
timeout: GitalyClient.long_timeout
|
||||
) do |response|
|
||||
response.each(&blk)
|
||||
end
|
||||
)
|
||||
response.each(&blk)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -72,9 +72,8 @@ module Gitlab
|
|||
|
||||
def commit_deltas(commit)
|
||||
request = Gitaly::CommitDeltaRequest.new(diff_from_parent_request_params(commit))
|
||||
GitalyClient.streaming_call(@repository.storage, :diff_service, :commit_delta, request, timeout: GitalyClient.fast_timeout) do |response|
|
||||
response.flat_map { |msg| msg.deltas }
|
||||
end
|
||||
response = GitalyClient.call(@repository.storage, :diff_service, :commit_delta, request, timeout: GitalyClient.fast_timeout)
|
||||
response.flat_map { |msg| msg.deltas }
|
||||
end
|
||||
|
||||
def tree_entry(ref, path, limit = nil)
|
||||
|
@ -202,9 +201,8 @@ module Gitlab
|
|||
to: to
|
||||
)
|
||||
|
||||
GitalyClient.streaming_call(@repository.storage, :commit_service, :commits_between, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
consume_commits_response(response)
|
||||
end
|
||||
response = GitalyClient.call(@repository.storage, :commit_service, :commits_between, request, timeout: GitalyClient.medium_timeout)
|
||||
consume_commits_response(response)
|
||||
end
|
||||
|
||||
def diff_stats(left_commit_sha, right_commit_sha)
|
||||
|
@ -214,9 +212,8 @@ module Gitlab
|
|||
right_commit_id: right_commit_sha
|
||||
)
|
||||
|
||||
GitalyClient.streaming_call(@repository.storage, :diff_service, :diff_stats, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
response.flat_map(&:stats)
|
||||
end
|
||||
response = GitalyClient.call(@repository.storage, :diff_service, :diff_stats, request, timeout: GitalyClient.medium_timeout)
|
||||
response.flat_map(&:stats)
|
||||
end
|
||||
|
||||
def find_all_commits(opts = {})
|
||||
|
@ -228,9 +225,8 @@ module Gitlab
|
|||
)
|
||||
request.order = opts[:order].upcase if opts[:order].present?
|
||||
|
||||
GitalyClient.streaming_call(@repository.storage, :commit_service, :find_all_commits, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
consume_commits_response(response)
|
||||
end
|
||||
response = GitalyClient.call(@repository.storage, :commit_service, :find_all_commits, request, timeout: GitalyClient.medium_timeout)
|
||||
consume_commits_response(response)
|
||||
end
|
||||
|
||||
def list_commits_by_oid(oids)
|
||||
|
@ -238,9 +234,8 @@ module Gitlab
|
|||
|
||||
request = Gitaly::ListCommitsByOidRequest.new(repository: @gitaly_repo, oid: oids)
|
||||
|
||||
GitalyClient.streaming_call(@repository.storage, :commit_service, :list_commits_by_oid, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
consume_commits_response(response)
|
||||
end
|
||||
response = GitalyClient.call(@repository.storage, :commit_service, :list_commits_by_oid, request, timeout: GitalyClient.medium_timeout)
|
||||
consume_commits_response(response)
|
||||
rescue GRPC::NotFound # If no repository is found, happens mainly during testing
|
||||
[]
|
||||
end
|
||||
|
@ -256,9 +251,8 @@ module Gitlab
|
|||
global_options: parse_global_options!(literal_pathspec: literal_pathspec)
|
||||
)
|
||||
|
||||
GitalyClient.streaming_call(@repository.storage, :commit_service, :commits_by_message, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
consume_commits_response(response)
|
||||
end
|
||||
response = GitalyClient.call(@repository.storage, :commit_service, :commits_by_message, request, timeout: GitalyClient.medium_timeout)
|
||||
consume_commits_response(response)
|
||||
end
|
||||
|
||||
def languages(ref = nil)
|
||||
|
@ -334,9 +328,8 @@ module Gitlab
|
|||
|
||||
request.paths = encode_repeated(Array(options[:path])) if options[:path].present?
|
||||
|
||||
GitalyClient.streaming_call(@repository.storage, :commit_service, :find_commits, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
consume_commits_response(response)
|
||||
end
|
||||
response = GitalyClient.call(@repository.storage, :commit_service, :find_commits, request, timeout: GitalyClient.medium_timeout)
|
||||
consume_commits_response(response)
|
||||
end
|
||||
|
||||
def filter_shas_with_signatures(shas)
|
||||
|
@ -352,10 +345,9 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
GitalyClient.streaming_call(@repository.storage, :commit_service, :filter_shas_with_signatures, enum, timeout: GitalyClient.fast_timeout) do |response|
|
||||
response.flat_map do |msg|
|
||||
msg.shas.map { |sha| EncodingHelper.encode!(sha) }
|
||||
end
|
||||
response = GitalyClient.call(@repository.storage, :commit_service, :filter_shas_with_signatures, enum, timeout: GitalyClient.fast_timeout)
|
||||
response.flat_map do |msg|
|
||||
msg.shas.map { |sha| EncodingHelper.encode!(sha) }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -423,9 +415,8 @@ module Gitlab
|
|||
request_params.merge!(Gitlab::Git::DiffCollection.limits(options).to_h)
|
||||
|
||||
request = Gitaly::CommitDiffRequest.new(request_params)
|
||||
GitalyClient.streaming_call(@repository.storage, :diff_service, :commit_diff, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
GitalyClient::DiffStitcher.new(response)
|
||||
end
|
||||
response = GitalyClient.call(@repository.storage, :diff_service, :commit_diff, request, timeout: GitalyClient.medium_timeout)
|
||||
GitalyClient::DiffStitcher.new(response)
|
||||
end
|
||||
|
||||
def diff_from_parent_request_params(commit, options = {})
|
||||
|
|
|
@ -20,9 +20,8 @@ module Gitlab
|
|||
our_commit_oid: @our_commit_oid,
|
||||
their_commit_oid: @their_commit_oid
|
||||
)
|
||||
GitalyClient.streaming_call(@repository.storage, :conflicts_service, :list_conflict_files, request, timeout: GitalyClient.long_timeout) do |response|
|
||||
GitalyClient::ConflictFilesStitcher.new(response, @gitaly_repo)
|
||||
end
|
||||
response = GitalyClient.call(@repository.storage, :conflicts_service, :list_conflict_files, request, timeout: GitalyClient.long_timeout)
|
||||
GitalyClient::ConflictFilesStitcher.new(response, @gitaly_repo)
|
||||
end
|
||||
|
||||
def conflicts?
|
||||
|
|
|
@ -14,16 +14,14 @@ module Gitlab
|
|||
|
||||
def branches
|
||||
request = Gitaly::FindAllBranchesRequest.new(repository: @gitaly_repo)
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :find_all_branches, request, timeout: GitalyClient.fast_timeout) do |response|
|
||||
consume_find_all_branches_response(response)
|
||||
end
|
||||
response = GitalyClient.call(@storage, :ref_service, :find_all_branches, request, timeout: GitalyClient.fast_timeout)
|
||||
consume_find_all_branches_response(response)
|
||||
end
|
||||
|
||||
def remote_branches(remote_name)
|
||||
request = Gitaly::FindAllRemoteBranchesRequest.new(repository: @gitaly_repo, remote_name: remote_name)
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :find_all_remote_branches, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
consume_find_all_remote_branches_response(remote_name, response)
|
||||
end
|
||||
response = GitalyClient.call(@storage, :ref_service, :find_all_remote_branches, request, timeout: GitalyClient.medium_timeout)
|
||||
consume_find_all_remote_branches_response(remote_name, response)
|
||||
end
|
||||
|
||||
def merged_branches(branch_names = [])
|
||||
|
@ -32,9 +30,8 @@ module Gitlab
|
|||
merged_only: true,
|
||||
merged_branches: branch_names.map { |s| encode_binary(s) }
|
||||
)
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :find_all_branches, request, timeout: GitalyClient.fast_timeout) do |response|
|
||||
consume_find_all_branches_response(response)
|
||||
end
|
||||
response = GitalyClient.call(@storage, :ref_service, :find_all_branches, request, timeout: GitalyClient.fast_timeout)
|
||||
consume_find_all_branches_response(response)
|
||||
end
|
||||
|
||||
def default_branch_name
|
||||
|
@ -45,16 +42,14 @@ module Gitlab
|
|||
|
||||
def branch_names
|
||||
request = Gitaly::FindAllBranchNamesRequest.new(repository: @gitaly_repo)
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :find_all_branch_names, request, timeout: GitalyClient.fast_timeout) do |response|
|
||||
consume_refs_response(response) { |name| Gitlab::Git.branch_name(name) }
|
||||
end
|
||||
response = GitalyClient.call(@storage, :ref_service, :find_all_branch_names, request, timeout: GitalyClient.fast_timeout)
|
||||
consume_refs_response(response) { |name| Gitlab::Git.branch_name(name) }
|
||||
end
|
||||
|
||||
def tag_names
|
||||
request = Gitaly::FindAllTagNamesRequest.new(repository: @gitaly_repo)
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :find_all_tag_names, request, timeout: GitalyClient.fast_timeout) do |response|
|
||||
consume_refs_response(response) { |name| Gitlab::Git.tag_name(name) }
|
||||
end
|
||||
response = GitalyClient.call(@storage, :ref_service, :find_all_tag_names, request, timeout: GitalyClient.fast_timeout)
|
||||
consume_refs_response(response) { |name| Gitlab::Git.tag_name(name) }
|
||||
end
|
||||
|
||||
def find_ref_name(commit_id, ref_prefix)
|
||||
|
@ -75,11 +70,10 @@ module Gitlab
|
|||
|
||||
commits = []
|
||||
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :list_new_commits, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
response.each do |msg|
|
||||
msg.commits.each do |c|
|
||||
commits << Gitlab::Git::Commit.new(@repository, c)
|
||||
end
|
||||
response = GitalyClient.call(@storage, :ref_service, :list_new_commits, request, timeout: GitalyClient.medium_timeout)
|
||||
response.each do |msg|
|
||||
msg.commits.each do |c|
|
||||
commits << Gitlab::Git::Commit.new(@repository, c)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -100,12 +94,11 @@ module Gitlab
|
|||
GitalyClient.medium_timeout
|
||||
end
|
||||
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :list_new_blobs, request, timeout: timeout) do |response|
|
||||
response.flat_map do |msg|
|
||||
# Returns an Array of Gitaly::NewBlobObject objects
|
||||
# Available methods are: #size, #oid and #path
|
||||
msg.new_blob_objects
|
||||
end
|
||||
response = GitalyClient.call(@storage, :ref_service, :list_new_blobs, request, timeout: timeout)
|
||||
response.flat_map do |msg|
|
||||
# Returns an Array of Gitaly::NewBlobObject objects
|
||||
# Available methods are: #size, #oid and #path
|
||||
msg.new_blob_objects
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -120,16 +113,14 @@ module Gitlab
|
|||
def local_branches(sort_by: nil)
|
||||
request = Gitaly::FindLocalBranchesRequest.new(repository: @gitaly_repo)
|
||||
request.sort_by = sort_by_param(sort_by) if sort_by
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :find_local_branches, request, timeout: GitalyClient.fast_timeout) do |response|
|
||||
consume_find_local_branches_response(response)
|
||||
end
|
||||
response = GitalyClient.call(@storage, :ref_service, :find_local_branches, request, timeout: GitalyClient.fast_timeout)
|
||||
consume_find_local_branches_response(response)
|
||||
end
|
||||
|
||||
def tags
|
||||
request = Gitaly::FindAllTagsRequest.new(repository: @gitaly_repo)
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :find_all_tags, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
consume_tags_response(response)
|
||||
end
|
||||
response = GitalyClient.call(@storage, :ref_service, :find_all_tags, request, timeout: GitalyClient.medium_timeout)
|
||||
consume_tags_response(response)
|
||||
end
|
||||
|
||||
def ref_exists?(ref_name)
|
||||
|
@ -174,9 +165,8 @@ module Gitlab
|
|||
limit: limit
|
||||
)
|
||||
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :list_tag_names_containing_commit, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
consume_ref_contains_sha_response(response, :tag_names)
|
||||
end
|
||||
response = GitalyClient.call(@storage, :ref_service, :list_tag_names_containing_commit, request, timeout: GitalyClient.medium_timeout)
|
||||
consume_ref_contains_sha_response(response, :tag_names)
|
||||
end
|
||||
|
||||
# Limit: 0 implies no limit, thus all tag names will be returned
|
||||
|
@ -187,9 +177,8 @@ module Gitlab
|
|||
limit: limit
|
||||
)
|
||||
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :list_branch_names_containing_commit, request, timeout: GitalyClient.medium_timeout) do |response|
|
||||
consume_ref_contains_sha_response(response, :branch_names)
|
||||
end
|
||||
response = GitalyClient.call(@storage, :ref_service, :list_branch_names_containing_commit, request, timeout: GitalyClient.medium_timeout)
|
||||
consume_ref_contains_sha_response(response, :branch_names)
|
||||
end
|
||||
|
||||
def get_tag_messages(tag_ids)
|
||||
|
@ -197,12 +186,11 @@ module Gitlab
|
|||
messages = Hash.new { |h, k| h[k] = +''.b }
|
||||
current_tag_id = nil
|
||||
|
||||
GitalyClient.streaming_call(@storage, :ref_service, :get_tag_messages, request, timeout: GitalyClient.fast_timeout) do |response|
|
||||
response.each do |rpc_message|
|
||||
current_tag_id = rpc_message.tag_id if rpc_message.tag_id.present?
|
||||
response = GitalyClient.call(@storage, :ref_service, :get_tag_messages, request, timeout: GitalyClient.fast_timeout)
|
||||
response.each do |rpc_message|
|
||||
current_tag_id = rpc_message.tag_id if rpc_message.tag_id.present?
|
||||
|
||||
messages[current_tag_id] << rpc_message.message
|
||||
end
|
||||
messages[current_tag_id] << rpc_message.message
|
||||
end
|
||||
|
||||
messages
|
||||
|
|
|
@ -334,9 +334,8 @@ module Gitlab
|
|||
|
||||
def search_files_by_content(ref, query, options = {})
|
||||
request = Gitaly::SearchFilesByContentRequest.new(repository: @gitaly_repo, ref: ref, query: query)
|
||||
GitalyClient.streaming_call(@storage, :repository_service, :search_files_by_content, request, timeout: GitalyClient.default_timeout) do |response|
|
||||
search_results_from_response(response, options)
|
||||
end
|
||||
response = GitalyClient.call(@storage, :repository_service, :search_files_by_content, request, timeout: GitalyClient.default_timeout)
|
||||
search_results_from_response(response, options)
|
||||
end
|
||||
|
||||
def disconnect_alternates
|
||||
|
@ -403,15 +402,14 @@ module Gitlab
|
|||
|
||||
def gitaly_fetch_stream_to_file(save_path, rpc_name, request_class, timeout)
|
||||
request = request_class.new(repository: @gitaly_repo)
|
||||
GitalyClient.streaming_call(
|
||||
response = GitalyClient.call(
|
||||
@storage,
|
||||
:repository_service,
|
||||
rpc_name,
|
||||
request,
|
||||
timeout: timeout
|
||||
) do |response|
|
||||
write_stream_to_file(response, save_path)
|
||||
end
|
||||
)
|
||||
write_stream_to_file(response, save_path)
|
||||
end
|
||||
|
||||
def write_stream_to_file(response, save_path)
|
||||
|
|
|
@ -3424,9 +3424,6 @@ msgstr ""
|
|||
msgid "Badges|e.g. %{exampleUrl}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Badge|New"
|
||||
msgstr ""
|
||||
|
||||
msgid "Balsamiq file could not be loaded."
|
||||
msgstr ""
|
||||
|
||||
|
@ -3562,9 +3559,6 @@ msgstr ""
|
|||
msgid "Blog"
|
||||
msgstr ""
|
||||
|
||||
msgid "Blue helpers indicate an action to be taken."
|
||||
msgstr ""
|
||||
|
||||
msgid "Board name"
|
||||
msgstr ""
|
||||
|
||||
|
@ -8078,9 +8072,6 @@ msgstr ""
|
|||
msgid "Don't show again"
|
||||
msgstr ""
|
||||
|
||||
msgid "Don't worry, you can access this tour by clicking on the help icon in the top right corner and choose <strong>Learn GitLab</strong>."
|
||||
msgstr ""
|
||||
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
|
||||
|
@ -11039,9 +11030,6 @@ msgstr ""
|
|||
msgid "Go to your snippets"
|
||||
msgstr ""
|
||||
|
||||
msgid "Golden Tanuki"
|
||||
msgstr ""
|
||||
|
||||
msgid "Google Cloud Platform"
|
||||
msgstr ""
|
||||
|
||||
|
@ -15302,9 +15290,6 @@ msgstr ""
|
|||
msgid "No, directly import the existing email addresses and usernames."
|
||||
msgstr ""
|
||||
|
||||
msgid "No, not interested right now"
|
||||
msgstr ""
|
||||
|
||||
msgid "No. of commits"
|
||||
msgstr ""
|
||||
|
||||
|
@ -15350,9 +15335,6 @@ msgstr ""
|
|||
msgid "Not found."
|
||||
msgstr ""
|
||||
|
||||
msgid "Not helpful"
|
||||
msgstr ""
|
||||
|
||||
msgid "Not now"
|
||||
msgstr ""
|
||||
|
||||
|
@ -15578,9 +15560,6 @@ msgstr ""
|
|||
msgid "Oh no!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Ok let's go"
|
||||
msgstr ""
|
||||
|
||||
msgid "Oldest first"
|
||||
msgstr ""
|
||||
|
||||
|
@ -15638,9 +15617,6 @@ msgstr ""
|
|||
msgid "OnDemandScans|Target URL"
|
||||
msgstr ""
|
||||
|
||||
msgid "Onboarding"
|
||||
msgstr ""
|
||||
|
||||
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
|
||||
msgstr ""
|
||||
|
||||
|
@ -21019,9 +20995,6 @@ msgstr ""
|
|||
msgid "Skip outdated deployment jobs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Skip this for now"
|
||||
msgstr ""
|
||||
|
||||
msgid "Skipped"
|
||||
msgstr ""
|
||||
|
||||
|
@ -24942,150 +24915,6 @@ msgstr ""
|
|||
msgid "UserList|created %{timeago}"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|%{activeTour}/%{totalTours}"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|%{completed}/%{total} steps completed"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|%{emphasisStart}Well done!%{emphasisEnd}%{lineBreak}%{lineBreak}That's it for our guided tour, congratulations for making it all the way to the end!%{lineBreak}%{lineBreak}We hope this gave you a good overview of GitLab and how it can help you. We'll now show you how to create your own project and invite your colleagues."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Adding other members to a project is done through Project Settings. Click on %{emphasisStart}Settings%{emphasisEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Alright, that's it for Commits. Let's take a look at the %{emphasisStart}Branches%{emphasisEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Awesome! Now click on %{emphasisStart}Members%{emphasisEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Click on one of the %{emphasisStart}Compare%{emphasisEnd} buttons to compare a branch to master."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Click on one of the %{emphasisStart}pipeline IDs%{emphasisEnd} to see the details of a pipeline."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Click to open the latest commit to see its details."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Close 'Learn GitLab'"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Commits are shown in chronological order and can be filtered by the commit message or by the branch."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Create a project"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Exit 'Learn GitLab'"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Got it"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Great job! %{clapHands} We hope the tour was helpful and that you learned how to use GitLab.%{lineBreak}%{lineBreak}We'd love to get your feedback on this tour.%{lineBreak}%{lineBreak}%{emphasisStart}How helpful would you say this guided tour was?%{emphasisEnd}%{lineBreak}%{lineBreak}"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Guided GitLab Tour"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Here you can compare the changes of this branch to another one. Changes are divided by files so that it's easier to see what was changed where."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Here you can create a project from scratch, start with a template or import a repository from other platforms. Whatever you choose, we'll guide you through the process.%{lineBreak}%{lineBreak}Fill in your new project information and click on %{emphasisStart}Create Project%{emphasisEnd} to progress to the next step."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Here you can see the breakdown of the pipelines: its stages and jobs in each of the stages and their status.%{lineBreak}%{lineBreak}Our CI/CD pipelines are quite complex, most of our users have fewer and simpler pipelines."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Here you can see the current members of the project (just you at the moment) and invite new members.%{lineBreak}%{lineBreak}You can invite multiple members at once (existing GitLab users or invite by email) and you can also set their roles and permissions.%{lineBreak}%{lineBreak}Add a few members and click on %{emphasisStart}Add to project%{emphasisEnd} to complete this step."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Here you can see what changes were made with this commit, on what branch and if there's a related merge request. The status of the pipeline will also show up if CI/CD is set up.%{lineBreak}%{lineBreak}You can also comment on the lines of code that were changed and start a discussion with your colleagues!"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Here's an overview of branches in the %{emphasisStart}%{projectName}%{emphasisEnd} project. They're split into Active and Stale.%{lineBreak}%{lineBreak}From here, you can create a new merge request from a branch, or compare the branch to any other branch in the project. By default, it will compare it to the master branch."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Invite colleagues"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Issues are great for communicating and keeping track of progress in GitLab. These are all issues that are open in the %{emphasisStart}%{projectName}%{emphasisEnd}.%{lineBreak}%{lineBreak}You can help us improve GitLab by contributing work to issues that are labeled <span class=\"badge color-label accept-mr-label\">Accepting merge requests</span>.%{lineBreak}%{lineBreak}This list can be filtered by labels, milestones, assignees, authors... We'll show you how it looks when the list is filtered by a label."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Learn GitLab"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Let's take a closer look at a merge request. Click on the title of one."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Let's take a closer look at all the commits. Click on %{emphasisStart}Commits%{emphasisEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Let's take a closer look at the repository of this project. Click on %{emphasisStart}Repository%{emphasisEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|No thanks"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Ok, let's go"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Ok, show me"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Open one of the issues by clicking on its title."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Restart this step"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Skip this step"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Sweet! Your project was created and is ready to be used.%{lineBreak}%{lineBreak}You can start adding files to the repository or clone it. One last thing we want to show you is how to invite your colleagues to your new project."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Take a look. Here's a nifty menu for quickly creating issues, merge requests, snippets, projects and groups. Click on it and select \"New project\" from the \"GitLab\" section to get started."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Thanks for taking the guided tour. Remember, if you want to go through it again, you can start %{emphasisStart}Learn GitLab%{emphasisEnd} in the help menu on the top right."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Thanks for the feedback! %{thumbsUp}"
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|That's it for issues. Let'st take a look at %{emphasisStart}Merge Requests%{emphasisEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|That's it for merge requests. Now for the final part of this guided tour - the %{emphasisStart}CI/CD%{emphasisEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|That's it for the Repository. Let's take a look at the %{emphasisStart}Issues%{emphasisEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|The structure of this page is very similar to issues. Status, description, discussion and the sidebar are all here.%{lineBreak}%{lineBreak}But take a look below the description and you'll notice that there's more information about the merge request, the CI/CD pipeline and the options for approving it.%{lineBreak}%{lineBreak}Alongside the discussion you can also see more information about commits in this merge request, the status of pipelines and review all changes that were made."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|There's a lot of information here but don't worry, we'll go through it.%{lineBreak}%{lineBreak}On the top you can see the status of the issue and when it was opened and by whom. Directly below it is the issue description and below that are other %{emphasisStart}related issues%{emphasisEnd} and %{emphasisStart}merge requests%{emphasisEnd} (if any). Then below that is the %{emphasisStart}discussion%{emphasisEnd}, that's where most of the communication happens.%{lineBreak}%{lineBreak}On the right, there's a sidebar where you can view/change the %{emphasisStart}assignee, milestone, due date, labels, weight%{emphasisEnd}, etc."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|These are all the CI/CD pipelines we have for our %{emphasisStart}%{projectName}%{emphasisEnd} project.%{lineBreak}%{lineBreak}Here you can see the status of each pipeline, for what commit it's running for, its stages and the status for them."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|These are all the issues that are available for community contributions. Let's take a closer look at one of them."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|This is an overview of all merge requests in this project. Similarly to the issues overview it can be filtered down by things like labels, milestones, authors, assignees, etc."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|This is the repository for the %{emphasisStart}%{projectName}%{emphasisEnd} project. All our code is stored here. Feel free to explore and take a closer look at folders and files.%{lineBreak}%{lineBreak}Above the file structure you can see the latest commit, who the author is and the status of the CI/CD pipeline.%{lineBreak}%{lineBreak}If you scroll down below the file structure, you'll find the Readme of this project. This is defined in the README.md file at the root of the repository."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserOnboardingTour|Welcome to the project overview of the %{emphasisStart}%{projectName}%{emphasisEnd} project. This is the project that we use to work on GitLab. At first, a project seems like a simple repository, but at GitLab, a project is so much more.%{lineBreak}%{lineBreak}You can create projects for hosting your codebase, use it as an issue tracker, collaborate on code, and continuously build, test, and deploy your app with built-in GitLab CI/CD."
|
||||
msgstr ""
|
||||
|
||||
msgid "UserProfile|Activity"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25323,9 +25152,6 @@ msgstr ""
|
|||
msgid "Versions"
|
||||
msgstr ""
|
||||
|
||||
msgid "Very helpful"
|
||||
msgstr ""
|
||||
|
||||
msgid "View Documentation"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25693,9 +25519,6 @@ msgstr ""
|
|||
msgid "We couldn't reach the Prometheus server. Either the server no longer exists or the configuration details need updating."
|
||||
msgstr ""
|
||||
|
||||
msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You will be guided by two types of helpers, best recognized by their color."
|
||||
msgstr ""
|
||||
|
||||
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
|
||||
msgstr ""
|
||||
|
||||
|
@ -25792,9 +25615,6 @@ msgstr ""
|
|||
msgid "Welcome to GitLab.com<br>@%{name}!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Welcome to the Guided GitLab Tour"
|
||||
msgstr ""
|
||||
|
||||
msgid "Welcome to the guided GitLab tour"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25842,9 +25662,6 @@ msgstr ""
|
|||
msgid "While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you please double check your settings to make sure you've set up your dashboard correctly."
|
||||
msgstr ""
|
||||
|
||||
msgid "White helpers give contextual information."
|
||||
msgstr ""
|
||||
|
||||
msgid "Who can be an approver?"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
"@babel/plugin-syntax-import-meta": "^7.10.1",
|
||||
"@babel/preset-env": "^7.10.1",
|
||||
"@gitlab/at.js": "1.5.5",
|
||||
"@gitlab/svgs": "1.144.0",
|
||||
"@gitlab/ui": "17.9.0",
|
||||
"@gitlab/svgs": "1.146.0",
|
||||
"@gitlab/ui": "17.10.1",
|
||||
"@gitlab/visual-review-tools": "1.6.1",
|
||||
"@rails/actioncable": "^6.0.3-1",
|
||||
"@sentry/browser": "^5.10.2",
|
||||
|
|
|
@ -165,8 +165,6 @@ module QA
|
|||
terms.accept_terms if terms.visible?
|
||||
end
|
||||
|
||||
skip_onboarding if respond_to?(:skip_onboarding)
|
||||
|
||||
Page::Main::Menu.validate_elements_present! unless skip_page_validation
|
||||
end
|
||||
|
||||
|
@ -181,5 +179,3 @@ module QA
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
QA::Page::Main::Login.prepend_if_ee('QA::EE::Page::Main::Login')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
context 'Plan' do
|
||||
context 'Plan', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/225409', type: :bug } do
|
||||
describe 'Jira issue import', :jira, :orchestrated, :requires_admin do
|
||||
let(:jira_project_key) { "JITD" }
|
||||
let(:jira_issue_title) { "[#{jira_project_key}-1] Jira to GitLab Test Issue" }
|
||||
|
|
|
@ -32,6 +32,20 @@ export const Blob = {
|
|||
},
|
||||
};
|
||||
|
||||
export const BinaryBlob = {
|
||||
binary: true,
|
||||
name: 'dummy.png',
|
||||
path: 'foo/bar/dummy.png',
|
||||
rawPath: '/flightjs/flight/snippets/51/raw',
|
||||
size: 75,
|
||||
simpleViewer: {
|
||||
...SimpleViewerMock,
|
||||
},
|
||||
richViewer: {
|
||||
...RichViewerMock,
|
||||
},
|
||||
};
|
||||
|
||||
export const RichBlobContentMock = {
|
||||
richData: '<h1>Rich</h1>',
|
||||
};
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import SnippetApp from '~/snippets/components/show.vue';
|
||||
import BlobEmbeddable from '~/blob/components/blob_embeddable.vue';
|
||||
import SnippetHeader from '~/snippets/components/snippet_header.vue';
|
||||
import SnippetTitle from '~/snippets/components/snippet_title.vue';
|
||||
import SnippetBlob from '~/snippets/components/snippet_blob_view.vue';
|
||||
import { GlLoadingIcon } from '@gitlab/ui';
|
||||
import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
|
||||
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { SNIPPET_VISIBILITY_PUBLIC } from '~/snippets/constants';
|
||||
|
||||
describe('Snippet view app', () => {
|
||||
let wrapper;
|
||||
|
@ -12,7 +15,7 @@ describe('Snippet view app', () => {
|
|||
snippetGid: 'gid://gitlab/PersonalSnippet/42',
|
||||
};
|
||||
|
||||
function createComponent({ props = defaultProps, loading = false } = {}) {
|
||||
function createComponent({ props = defaultProps, data = {}, loading = false } = {}) {
|
||||
const $apollo = {
|
||||
queries: {
|
||||
snippet: {
|
||||
|
@ -26,6 +29,9 @@ describe('Snippet view app', () => {
|
|||
propsData: {
|
||||
...props,
|
||||
},
|
||||
data() {
|
||||
return data;
|
||||
},
|
||||
});
|
||||
}
|
||||
afterEach(() => {
|
||||
|
@ -37,10 +43,33 @@ describe('Snippet view app', () => {
|
|||
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders all components after the query is finished', () => {
|
||||
it('renders all simple components after the query is finished', () => {
|
||||
createComponent();
|
||||
expect(wrapper.find(SnippetHeader).exists()).toBe(true);
|
||||
expect(wrapper.find(SnippetTitle).exists()).toBe(true);
|
||||
expect(wrapper.find(SnippetBlob).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders embeddable component if visibility allows', () => {
|
||||
createComponent({
|
||||
data: {
|
||||
snippet: {
|
||||
visibilityLevel: SNIPPET_VISIBILITY_PUBLIC,
|
||||
webUrl: 'http://foo.bar',
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(wrapper.contains(BlobEmbeddable)).toBe(true);
|
||||
});
|
||||
|
||||
it('renders correct snippet-blob components', () => {
|
||||
createComponent({
|
||||
data: {
|
||||
blobs: [Blob, BinaryBlob],
|
||||
},
|
||||
});
|
||||
const blobs = wrapper.findAll(SnippetBlob);
|
||||
expect(blobs.length).toBe(2);
|
||||
expect(blobs.at(0).props('blob')).toEqual(Blob);
|
||||
expect(blobs.at(1).props('blob')).toEqual(BinaryBlob);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,13 +23,17 @@ describe('Blob Embeddable', () => {
|
|||
id: 'gid://foo.bar/snippet',
|
||||
webUrl: 'https://foo.bar',
|
||||
visibilityLevel: SNIPPET_VISIBILITY_PUBLIC,
|
||||
blob: BlobMock,
|
||||
};
|
||||
const dataMock = {
|
||||
activeViewerType: SimpleViewerMock.type,
|
||||
};
|
||||
|
||||
function createComponent(props = {}, data = dataMock, contentLoading = false) {
|
||||
function createComponent({
|
||||
snippetProps = {},
|
||||
data = dataMock,
|
||||
blob = BlobMock,
|
||||
contentLoading = false,
|
||||
} = {}) {
|
||||
const $apollo = {
|
||||
queries: {
|
||||
blobContent: {
|
||||
|
@ -44,8 +48,9 @@ describe('Blob Embeddable', () => {
|
|||
propsData: {
|
||||
snippet: {
|
||||
...snippet,
|
||||
...props,
|
||||
...snippetProps,
|
||||
},
|
||||
blob,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -63,7 +68,6 @@ describe('Blob Embeddable', () => {
|
|||
describe('rendering', () => {
|
||||
it('renders correct components', () => {
|
||||
createComponent();
|
||||
expect(wrapper.find(BlobEmbeddable).exists()).toBe(true);
|
||||
expect(wrapper.find(BlobHeader).exists()).toBe(true);
|
||||
expect(wrapper.find(BlobContent).exists()).toBe(true);
|
||||
});
|
||||
|
@ -72,19 +76,14 @@ describe('Blob Embeddable', () => {
|
|||
'does not render blob-embeddable by default',
|
||||
visibilityLevel => {
|
||||
createComponent({
|
||||
visibilityLevel,
|
||||
snippetProps: {
|
||||
visibilityLevel,
|
||||
},
|
||||
});
|
||||
expect(wrapper.find(BlobEmbeddable).exists()).toBe(false);
|
||||
},
|
||||
);
|
||||
|
||||
it('does render blob-embeddable for public snippet', () => {
|
||||
createComponent({
|
||||
visibilityLevel: SNIPPET_VISIBILITY_PUBLIC,
|
||||
});
|
||||
expect(wrapper.find(BlobEmbeddable).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('sets simple viewer correctly', () => {
|
||||
createComponent();
|
||||
expect(wrapper.find(SimpleViewer).exists()).toBe(true);
|
||||
|
@ -92,7 +91,9 @@ describe('Blob Embeddable', () => {
|
|||
|
||||
it('sets rich viewer correctly', () => {
|
||||
const data = { ...dataMock, activeViewerType: RichViewerMock.type };
|
||||
createComponent({}, data);
|
||||
createComponent({
|
||||
data,
|
||||
});
|
||||
expect(wrapper.find(RichViewer).exists()).toBe(true);
|
||||
});
|
||||
|
||||
|
@ -137,7 +138,9 @@ describe('Blob Embeddable', () => {
|
|||
});
|
||||
|
||||
it('renders simple viewer by default if URL contains hash', () => {
|
||||
createComponent({}, {});
|
||||
createComponent({
|
||||
data: {},
|
||||
});
|
||||
|
||||
expect(wrapper.vm.activeViewerType).toBe(SimpleViewerMock.type);
|
||||
expect(wrapper.find(SimpleViewer).exists()).toBe(true);
|
||||
|
@ -183,12 +186,11 @@ describe('Blob Embeddable', () => {
|
|||
});
|
||||
|
||||
it(`sets '${SimpleViewerMock.type}' as active on ${BLOB_RENDER_EVENT_SHOW_SOURCE} event`, () => {
|
||||
createComponent(
|
||||
{},
|
||||
{
|
||||
createComponent({
|
||||
data: {
|
||||
activeViewerType: RichViewerMock.type,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
findContentEl().vm.$emit(BLOB_RENDER_EVENT_SHOW_SOURCE);
|
||||
expect(wrapper.vm.activeViewerType).toEqual(SimpleViewerMock.type);
|
||||
|
|
|
@ -3,6 +3,7 @@ import DeleteSnippetMutation from '~/snippets/mutations/deleteSnippet.mutation.g
|
|||
import { ApolloMutation } from 'vue-apollo';
|
||||
import { GlButton, GlModal } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
|
||||
|
||||
describe('Snippet header component', () => {
|
||||
let wrapper;
|
||||
|
@ -20,9 +21,7 @@ describe('Snippet header component', () => {
|
|||
author: {
|
||||
name: 'Thor Odinson',
|
||||
},
|
||||
blob: {
|
||||
binary: false,
|
||||
},
|
||||
blobs: [Blob],
|
||||
};
|
||||
const mutationVariables = {
|
||||
mutation: DeleteSnippetMutation,
|
||||
|
@ -49,7 +48,6 @@ describe('Snippet header component', () => {
|
|||
mutationRes = mutationTypes.RESOLVE,
|
||||
snippetProps = {},
|
||||
} = {}) {
|
||||
// const defaultProps = Object.assign({}, snippet, snippetProps);
|
||||
const defaultProps = Object.assign(snippet, snippetProps);
|
||||
if (permissions) {
|
||||
Object.assign(defaultProps.userPermissions, {
|
||||
|
@ -131,15 +129,18 @@ describe('Snippet header component', () => {
|
|||
expect(wrapper.find(GlModal).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('renders Edit button as disabled for binary snippets', () => {
|
||||
it.each`
|
||||
blobs | isDisabled | condition
|
||||
${[Blob]} | ${false} | ${'no binary'}
|
||||
${[Blob, BinaryBlob]} | ${true} | ${'several blobs. incl. a binary'}
|
||||
${[BinaryBlob]} | ${true} | ${'binary'}
|
||||
`('renders Edit button when snippet contains $condition file', ({ blobs, isDisabled }) => {
|
||||
createComponent({
|
||||
snippetProps: {
|
||||
blob: {
|
||||
binary: true,
|
||||
},
|
||||
blobs,
|
||||
},
|
||||
});
|
||||
expect(wrapper.find('[href*="edit"]').props('disabled')).toBe(true);
|
||||
expect(wrapper.find('[href*="edit"]').props('disabled')).toBe(isDisabled);
|
||||
});
|
||||
|
||||
describe('Delete mutation', () => {
|
||||
|
|
|
@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['RootStorageStatistics'] do
|
|||
|
||||
it 'has all the required fields' do
|
||||
expect(described_class).to have_graphql_fields(:storage_size, :repository_size, :lfs_objects_size,
|
||||
:build_artifacts_size, :packages_size, :wiki_size)
|
||||
:build_artifacts_size, :packages_size, :wiki_size, :snippets_size)
|
||||
end
|
||||
|
||||
specify { expect(described_class).to require_graphql_authorizations(:read_statistics) }
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::GitalyClient::Call do
|
||||
describe '#call', :request_store do
|
||||
let(:client) { Gitlab::GitalyClient }
|
||||
let(:storage) { 'default' }
|
||||
let(:remote_storage) { nil }
|
||||
let(:request) { Gitaly::FindLocalBranchesRequest.new }
|
||||
let(:rpc) { :find_local_branches }
|
||||
let(:service) { :ref_service }
|
||||
let(:timeout) { client.long_timeout }
|
||||
|
||||
subject do
|
||||
described_class.new(storage, service, rpc, request, remote_storage, timeout).call
|
||||
end
|
||||
|
||||
before do
|
||||
allow(client).to receive(:execute) { response }
|
||||
allow(Gitlab::PerformanceBar).to receive(:enabled_for_request?) { true }
|
||||
end
|
||||
|
||||
def expect_call_details_to_match(duration_higher_than: 0)
|
||||
expect(client.list_call_details.size).to eq(1)
|
||||
expect(client.list_call_details.first)
|
||||
.to match a_hash_including(feature: "#{service}##{rpc}",
|
||||
duration: a_value > duration_higher_than,
|
||||
request: an_instance_of(Hash),
|
||||
rpc: rpc,
|
||||
backtrace: an_instance_of(Array))
|
||||
end
|
||||
|
||||
context 'when the response is not an enumerator' do
|
||||
let(:response) do
|
||||
Gitaly::FindLocalBranchesResponse.new
|
||||
end
|
||||
|
||||
it 'returns the response' do
|
||||
expect(subject).to eq(response)
|
||||
end
|
||||
|
||||
it 'stores timings and call details' do
|
||||
subject
|
||||
|
||||
expect(client.query_time).to be > 0
|
||||
expect_call_details_to_match
|
||||
end
|
||||
|
||||
context 'when err' do
|
||||
before do
|
||||
allow(client).to receive(:execute).and_raise(StandardError)
|
||||
end
|
||||
|
||||
it 'stores timings and call details' do
|
||||
expect { subject }.to raise_error(StandardError)
|
||||
|
||||
expect(client.query_time).to be > 0
|
||||
expect_call_details_to_match
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the response is an enumerator' do
|
||||
let(:response) do
|
||||
Enumerator.new do |yielder|
|
||||
yielder << 1
|
||||
yielder << 2
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns a consumable enumerator' do
|
||||
instrumented_response = subject
|
||||
|
||||
expect(instrumented_response).to be_a(Enumerator)
|
||||
expect(instrumented_response.to_a).to eq([1, 2])
|
||||
end
|
||||
|
||||
context 'time measurements' do
|
||||
let(:response) do
|
||||
Enumerator.new do |yielder|
|
||||
sleep 0.1
|
||||
yielder << 1
|
||||
sleep 0.2
|
||||
yielder << 2
|
||||
end
|
||||
end
|
||||
|
||||
it 'records full rpc stream consumption' do
|
||||
subject.to_a
|
||||
|
||||
expect(client.query_time).to be > 0.3
|
||||
expect_call_details_to_match(duration_higher_than: 0.3)
|
||||
end
|
||||
|
||||
it 'records partial rpc stream consumption' do
|
||||
subject.first
|
||||
|
||||
expect(client.query_time).to be > 0.1
|
||||
expect_call_details_to_match(duration_higher_than: 0.1)
|
||||
end
|
||||
|
||||
context 'when err' do
|
||||
let(:response) do
|
||||
Enumerator.new do |yielder|
|
||||
sleep 0.2
|
||||
yielder << 1
|
||||
raise StandardError
|
||||
end
|
||||
end
|
||||
|
||||
it 'records partial rpc stream consumption' do
|
||||
expect { subject.to_a }.to raise_error(StandardError)
|
||||
|
||||
expect(client.query_time).to be > 0.2
|
||||
expect_call_details_to_match(duration_higher_than: 0.2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -22,11 +22,5 @@ RSpec.describe Gitlab::GitalyClient::CleanupService do
|
|||
|
||||
client.apply_bfg_object_map_stream(StringIO.new)
|
||||
end
|
||||
|
||||
it 'is wrapped as a streaming call' do
|
||||
expect(Gitlab::GitalyClient).to receive(:streaming_call).with(anything, :cleanup_service, :apply_bfg_object_map_stream, anything, anything)
|
||||
|
||||
client.apply_bfg_object_map_stream(StringIO.new)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -521,8 +521,6 @@ RSpec.describe Gitlab::GitalyClient do
|
|||
|
||||
context 'when the request store is active', :request_store do
|
||||
it 'records call details if a RPC is called' do
|
||||
expect(described_class).to receive(:measure_timings).and_call_original
|
||||
|
||||
gitaly_server.server_version
|
||||
|
||||
expect(described_class.list_call_details).not_to be_empty
|
||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -843,15 +843,15 @@
|
|||
eslint-plugin-vue "^6.2.1"
|
||||
vue-eslint-parser "^7.0.0"
|
||||
|
||||
"@gitlab/svgs@1.144.0":
|
||||
version "1.144.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.144.0.tgz#ee0ec58516405391cbaef00f5a660da6edf27538"
|
||||
integrity sha512-ejcsxoyfYwXyG8naOnn7QnY0oxrRNcWRBuH9VHrGL9/FXBJWq2NLXENi+v0TjcWvSsc2fBx/nk5V8Au96g0yEg==
|
||||
"@gitlab/svgs@1.146.0":
|
||||
version "1.146.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.146.0.tgz#c74118a3f1ab47ae77211d42597f553f395deb5d"
|
||||
integrity sha512-2/k9pAZPgHpZ5Ad0fz9i1109sWcShDE4XcjrjzltNNksbi86lqCKbsSe580ujtlG8KShgGMkDkmUa6AHZi64Xw==
|
||||
|
||||
"@gitlab/ui@17.9.0":
|
||||
version "17.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-17.9.0.tgz#fc5dcdb69910aa4aadd0905b718c0dd785ca9df6"
|
||||
integrity sha512-zbgs73ioxrOLigb9CIJXOkMQ80CUPnarurv/j2Oo2sN9cY5yWK+ci0eogx3j2dKQKF0HnTBAVgliTR6T3BHBcQ==
|
||||
"@gitlab/ui@17.10.1":
|
||||
version "17.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-17.10.1.tgz#b78f39e4f1ee72ac6c8cdf6824f2703e6dd9fc6d"
|
||||
integrity sha512-k7jsB+Qc0WlS3Hy8F5456TV2uuOwOR07Qn6PlSI8AB2q3XgT9x95mAV6G6bZ4f2WDNYDrEWPkj+5ySds/IQjfQ==
|
||||
dependencies:
|
||||
"@babel/standalone" "^7.0.0"
|
||||
"@gitlab/vue-toasted" "^1.3.0"
|
||||
|
|
Loading…
Reference in New Issue