Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-09-22 12:15:04 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-09-22 12:15:04 +0300
commit2fa173410ad24b37aba6450ae4530ec231844d86 (patch)
tree8bb24a83b6240f1da43b6ab7b1f9b96181f26831
parent8cfb9f566dae84d7ff76cdc3c4afa864fca94737 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue6
-rw-r--r--app/assets/javascripts/boards/constants.js11
-rw-r--r--app/assets/javascripts/vue_shared/components/issuable_blocked_icon/constants.js12
-rw-r--r--app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_epics.query.graphql (renamed from app/assets/javascripts/boards/graphql/board_blocking_epics.query.graphql)2
-rw-r--r--app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_issues.query.graphql (renamed from app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql)2
-rw-r--r--app/assets/javascripts/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue (renamed from app/assets/javascripts/boards/components/board_blocked_icon.vue)21
-rw-r--r--app/views/shared/_file_highlight.html.haml3
-rw-r--r--doc/administration/raketasks/maintenance.md6
-rw-r--r--doc/architecture/blueprints/_template.md5
-rw-r--r--doc/update/index.md10
-rw-r--r--doc/user/group/roadmap/img/roadmap_blocked_icon_v15_5.pngbin0 -> 25453 bytes
-rw-r--r--doc/user/group/roadmap/index.md10
-rw-r--r--doc/user/project/merge_requests/reviews/data_usage.md44
-rw-r--r--doc/user/project/merge_requests/reviews/img/suggested_reviewers_v15_4.pngbin0 -> 20617 bytes
-rw-r--r--doc/user/project/merge_requests/reviews/index.md20
-rw-r--r--spec/features/issues/incident_issue_spec.rb8
-rw-r--r--spec/frontend/boards/board_card_inner_spec.js8
-rw-r--r--spec/frontend/vue_shared/issuable/__snapshots__/issuable_blocked_icon_spec.js.snap (renamed from spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap)12
-rw-r--r--spec/frontend/vue_shared/issuable/issuable_blocked_icon_spec.js (renamed from spec/frontend/boards/components/board_blocked_icon_spec.js)13
-rw-r--r--workhorse/internal/queueing/queue.go23
-rw-r--r--workhorse/internal/queueing/queue_test.go8
-rw-r--r--workhorse/internal/queueing/requests.go6
-rw-r--r--workhorse/internal/queueing/requests_test.go6
-rw-r--r--workhorse/internal/upload/destination/objectstore/s3_session.go13
-rw-r--r--workhorse/internal/upload/destination/objectstore/s3_session_test.go16
-rw-r--r--workhorse/internal/upstream/routes.go3
26 files changed, 181 insertions, 87 deletions
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index 92a623d65d4..956d62c29f3 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -17,9 +17,9 @@ import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/toolt
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue';
import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
+import IssuableBlockedIcon from '~/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue';
import { ListType } from '../constants';
import eventHub from '../eventhub';
-import BoardBlockedIcon from './board_blocked_icon.vue';
import IssueDueDate from './issue_due_date.vue';
import IssueTimeEstimate from './issue_time_estimate.vue';
@@ -34,7 +34,7 @@ export default {
IssueDueDate,
IssueTimeEstimate,
IssueCardWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
- BoardBlockedIcon,
+ IssuableBlockedIcon,
GlSprintf,
BoardCardMoveToPosition,
WorkItemTypeIcon,
@@ -218,7 +218,7 @@ export default {
<div>
<div class="gl-display-flex" dir="auto">
<h4 class="board-card-title gl-mb-0 gl-mt-0 gl-mr-3 gl-font-base gl-overflow-break-word">
- <board-blocked-icon
+ <issuable-blocked-icon
v-if="item.blocked"
:item="item"
:unique-id="`${item.id}${list.id}`"
diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js
index ed22a375271..91b7f5004ad 100644
--- a/app/assets/javascripts/boards/constants.js
+++ b/app/assets/javascripts/boards/constants.js
@@ -2,8 +2,6 @@ import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql
import { __ } from '~/locale';
import updateEpicSubscriptionMutation from '~/sidebar/queries/update_epic_subscription.mutation.graphql';
import updateEpicTitleMutation from '~/sidebar/queries/update_epic_title.mutation.graphql';
-import boardBlockingIssuesQuery from './graphql/board_blocking_issues.query.graphql';
-import boardBlockingEpicsQuery from './graphql/board_blocking_epics.query.graphql';
import destroyBoardListMutation from './graphql/board_list_destroy.mutation.graphql';
import updateBoardListMutation from './graphql/board_list_update.mutation.graphql';
@@ -67,15 +65,6 @@ export const listsQuery = {
},
};
-export const blockingIssuablesQueries = {
- [issuableTypes.issue]: {
- query: boardBlockingIssuesQuery,
- },
- [issuableTypes.epic]: {
- query: boardBlockingEpicsQuery,
- },
-};
-
export const updateListQueries = {
[issuableTypes.issue]: {
mutation: updateBoardListMutation,
diff --git a/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/constants.js b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/constants.js
new file mode 100644
index 00000000000..d80c1ff8b0c
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/constants.js
@@ -0,0 +1,12 @@
+import { issuableTypes } from '~/boards/constants';
+import blockingIssuesQuery from './graphql/blocking_issues.query.graphql';
+import blockingEpicsQuery from './graphql/blocking_epics.query.graphql';
+
+export const blockingIssuablesQueries = {
+ [issuableTypes.issue]: {
+ query: blockingIssuesQuery,
+ },
+ [issuableTypes.epic]: {
+ query: blockingEpicsQuery,
+ },
+};
diff --git a/app/assets/javascripts/boards/graphql/board_blocking_epics.query.graphql b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_epics.query.graphql
index 071a6d7410f..4b9a9243052 100644
--- a/app/assets/javascripts/boards/graphql/board_blocking_epics.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_epics.query.graphql
@@ -1,4 +1,4 @@
-query BoardBlockingEpics($fullPath: ID!, $iid: ID) {
+query BlockingEpics($fullPath: ID!, $iid: ID) {
group(fullPath: $fullPath) {
id
issuable: epic(iid: $iid) {
diff --git a/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_issues.query.graphql
index 01fab571733..279c2202740 100644
--- a/app/assets/javascripts/boards/graphql/board_blocking_issues.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/graphql/blocking_issues.query.graphql
@@ -1,4 +1,4 @@
-query BoardBlockingIssues($id: IssueID!) {
+query BlockingIssues($id: IssueID!) {
issuable: issue(id: $id) {
id
blockingIssuables: blockedByIssues {
diff --git a/app/assets/javascripts/boards/components/board_blocked_icon.vue b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue
index 3f8a596abd8..253aca8837d 100644
--- a/app/assets/javascripts/boards/components/board_blocked_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue
@@ -1,10 +1,11 @@
<script>
import { GlIcon, GlLink, GlPopover, GlLoadingIcon } from '@gitlab/ui';
-import { blockingIssuablesQueries, issuableTypes } from '~/boards/constants';
+import { issuableTypes } from '~/boards/constants';
import { TYPE_ISSUE, TYPE_EPIC } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { truncate } from '~/lib/utils/text_utility';
import { __, n__, s__, sprintf } from '~/locale';
+import { blockingIssuablesQueries } from './constants';
export default {
i18n: {
@@ -28,7 +29,6 @@ export default {
GlLink,
GlLoadingIcon,
},
- blockingIssuablesQueries,
props: {
item: {
type: Object,
@@ -169,8 +169,8 @@ export default {
:id="glIconId"
ref="icon"
:name="blockIcon"
- class="issue-blocked-icon gl-mr-2 gl-cursor-pointer gl-text-red-500"
- data-testid="issue-blocked-icon"
+ class="issuable-blocked-icon gl-mr-2 gl-cursor-pointer gl-text-red-500"
+ data-testid="issuable-blocked-icon"
@mouseenter="handleMouseEnter"
/>
<gl-popover :target="glIconId" placement="top">
@@ -182,12 +182,19 @@ export default {
<p class="gl-mt-4 gl-mb-0 gl-font-small">{{ loadingMessage }}</p>
</template>
<template v-else>
- <ul class="gl-list-style-none gl-p-0">
- <li v-for="issuable in displayedIssuables" :key="issuable.id">
+ <ul class="gl-list-style-none gl-p-0 gl-mb-0">
+ <li v-for="(issuable, index) in displayedIssuables" :key="issuable.id">
<gl-link :href="issuable.webUrl" class="gl-text-blue-500! gl-font-sm">{{
issuable.reference
}}</gl-link>
- <p class="gl-mb-3 gl-display-block!" data-testid="issuable-title">
+ <p
+ class="gl-display-block!"
+ :class="{
+ 'gl-mb-3': index < displayedIssuables.length - 1,
+ 'gl-mb-0': index === displayedIssuables.length - 1,
+ }"
+ data-testid="issuable-title"
+ >
{{ issuable.title }}
</p>
</li>
diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml
index 89be816fc76..73ace033dc6 100644
--- a/app/views/shared/_file_highlight.html.haml
+++ b/app/views/shared/_file_highlight.html.haml
@@ -4,11 +4,10 @@
- blame_path = project_blame_path(@project, tree_join(@ref, blob.path))
.line-numbers{ class: "gl-px-0!", data: { blame_path: blame_path } }
- if blob.data.present?
- - link = blob_link if defined?(blob_link)
- blob.data.each_line.each_with_index do |_, index|
- i = index + offset
-# We're not using `link_to` because it is too slow once we get to thousands of lines.
- %a.file-line-num.diff-line-num{ class: ("js-line-links" if Feature.enabled?(:file_line_blame)), href: "#{link}#L#{i}", id: "L#{i}", 'data-line-number' => i }
+ %a.file-line-num.diff-line-num{ class: ("js-line-links" if Feature.enabled?(:file_line_blame)), href: "#L#{i}", id: "L#{i}", 'data-line-number' => i }
= i
- highlight = defined?(highlight_line) && highlight_line ? highlight_line - offset : nil
.blob-content{ data: { blob_id: blob.id, path: blob.path, highlight_line: highlight, qa_selector: 'file_content' } }
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index 5e0a7fcaa24..293efb1b7ae 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -310,6 +310,12 @@ To check the status of specific migrations, you can use the following Rake task:
sudo gitlab-rake db:migrate:status
```
+To check the [tracking database on a Geo secondary site](../geo/setup/external_database.md#configure-the-tracking-database), you can use the following Rake task:
+
+```shell
+sudo gitlab-rake db:migrate:status:geo
+```
+
This outputs a table with a `Status` of `up` or `down` for
each Migration ID.
diff --git a/doc/architecture/blueprints/_template.md b/doc/architecture/blueprints/_template.md
index e99ce61970a..787f49bf5b8 100644
--- a/doc/architecture/blueprints/_template.md
+++ b/doc/architecture/blueprints/_template.md
@@ -52,7 +52,10 @@ good title can help communicate what the blueprint is and should be considered
as part of any review.
-->
-[[_TOC_]]
+<!--
+For long pages, consider creating a table of contents.
+The `[_TOC_]` function is not supported on docs.gitlab.com.
+-->
## Summary
diff --git a/doc/update/index.md b/doc/update/index.md
index cf84c7caae9..8990cdb7482 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -477,7 +477,7 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
### 15.3.0
-- [Incorrect deletion of object storage files on Geo secondary sites]((https://gitlab.com/gitlab-org/gitlab/-/issues/371397)) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
+- [Incorrect deletion of object storage files on Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/371397) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
- LFS transfers can [redirect to the primary from secondary site mid-session](https://gitlab.com/gitlab-org/gitlab/-/issues/371571) causing failed pull and clone requests when [Geo proxying](../administration/geo/secondary_proxy/index.md) is enabled. Geo proxying is enabled by default in GitLab 15.1 and later. See [Geo: LFS transfer redirect to primary from secondary site mid-session issue in GitLab 15.1.0 to 15.3.2](#geo-lfs-transfers-redirect-to-primary-from-secondary-site-mid-session-in-gitlab-1510-to-1532) for more details.
### 15.2.0
@@ -498,7 +498,7 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
1. Add `gitaly['runtime_dir'] = '<PATH_WITH_EXEC_PERM>'` to `/etc/gitlab/gitlab.rb` and specify a location without `noexec` set.
1. Run `sudo gitlab-ctl reconfigure`.
-- [Incorrect deletion of object storage files on Geo secondary sites]((https://gitlab.com/gitlab-org/gitlab/-/issues/371397)) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
+- [Incorrect deletion of object storage files on Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/371397) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
- LFS transfers can [redirect to the primary from secondary site mid-session](https://gitlab.com/gitlab-org/gitlab/-/issues/371571) causing failed pull and clone requests when [Geo proxying](../administration/geo/secondary_proxy/index.md) is enabled. Geo proxying is enabled by default in GitLab 15.1 and later. See [Geo: LFS transfer redirect to primary from secondary site mid-session issue in GitLab 15.1.0 to 15.3.2](#geo-lfs-transfers-redirect-to-primary-from-secondary-site-mid-session-in-gitlab-1510-to-1532) for more details.
### 15.1.0
@@ -518,7 +518,7 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
- Unauthenticated requests to the [`ciConfig` GraphQL field](../api/graphql/reference/index.md#queryciconfig) are no longer supported.
Before you upgrade to GitLab 15.1, add an [access token](../api/index.md#authentication) to your requests.
The user creating the token must have [permission](../user/permissions.md) to create pipelines in the project.
-- [Incorrect deletion of object storage files on Geo secondary sites]((https://gitlab.com/gitlab-org/gitlab/-/issues/371397)) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
+- [Incorrect deletion of object storage files on Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/371397) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
- LFS transfers can [redirect to the primary from secondary site mid-session](https://gitlab.com/gitlab-org/gitlab/-/issues/371571) causing failed pull and clone requests when [Geo proxying](../administration/geo/secondary_proxy/index.md) is enabled. Geo proxying is enabled by default in GitLab 15.1 and later. See [Geo: LFS transfer redirect to primary from secondary site mid-session issue in GitLab 15.1.0 to 15.3.2](#geo-lfs-transfers-redirect-to-primary-from-secondary-site-mid-session-in-gitlab-1510-to-1532) for more details.
### 15.0.0
@@ -534,7 +534,7 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
Gitaly. The previous implementation in GitLab Shell was removed in GitLab 15.0. With this change, global server hooks are stored only inside a subdirectory named after the
hook type. Global server hooks can no longer be a single hook file in the root of the custom hooks directory. For example, you must use `<custom_hooks_dir>/<hook_name>.d/*` rather
than `<custom_hooks_dir>/<hook_name>`.
-- [Incorrect deletion of object storage files on Geo secondary sites]((https://gitlab.com/gitlab-org/gitlab/-/issues/371397)) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
+- [Incorrect deletion of object storage files on Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/371397) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
- The `FF_GITLAB_REGISTRY_HELPER_IMAGE` [feature flag](../administration/feature_flags.md#enable-or-disable-the-feature) is removed and helper images are always pulled from GitLab Registry.
### 14.10.0
@@ -1183,7 +1183,7 @@ Read more [in the issue](https://gitlab.com/gitlab-org/gitlab/-/issues/364763).
### Geo: Incorrect object storage LFS file deletion on secondary sites in GitLab 15.0.0 to 15.3.2
-[Incorrect deletion of object storage files on Geo secondary sites]((https://gitlab.com/gitlab-org/gitlab/-/issues/371397))
+[Incorrect deletion of object storage files on Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/371397)
can occur in GitLab 15.0.0 to 15.3.2 in the following situations:
- GitLab-managed object storage replication is disabled, and LFS objects are created while importing a project with object storage enabled.
diff --git a/doc/user/group/roadmap/img/roadmap_blocked_icon_v15_5.png b/doc/user/group/roadmap/img/roadmap_blocked_icon_v15_5.png
new file mode 100644
index 00000000000..52130672e5a
--- /dev/null
+++ b/doc/user/group/roadmap/img/roadmap_blocked_icon_v15_5.png
Binary files differ
diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md
index e3143e661a9..623d5baf91c 100644
--- a/doc/user/group/roadmap/index.md
+++ b/doc/user/group/roadmap/index.md
@@ -146,6 +146,16 @@ the timeline header represent the days of the week.
The timeline bar indicates the approximate position of an epic or milestone based on its start and
due dates.
+## Blocked epics
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33587) in GitLab 15.5: View blocking epics when hovering over the “blocked” icon.
+
+If an epic is [blocked by another epic](../epics/linked_epics.md#blocking-epics), an icon appears next to its title to indicate its blocked status.
+
+When you hover over the blocked icon (**{issue-block}**), a detailed information popover is displayed.
+
+![Blocked epics](img/roadmap_blocked_icon_v15_5.png)
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/project/merge_requests/reviews/data_usage.md b/doc/user/project/merge_requests/reviews/data_usage.md
new file mode 100644
index 00000000000..0988e3f0042
--- /dev/null
+++ b/doc/user/project/merge_requests/reviews/data_usage.md
@@ -0,0 +1,44 @@
+---
+stage: ModelOps
+group: Applied ML
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: index, reference
+---
+
+# Suggested Reviewers Data Usage
+
+## How it works
+
+Suggested Reviewers is the first user-facing GitLab machine learning (ML) powered feature. It leverages a project's contribution graph to generate suggestions. This data already exists within GitLab including merge request metadata, source code files, and GitLab user account metadata.
+
+### Enabling the feature
+
+When a Project Maintainer or Owner enables Suggested Reviewers in project settings GitLab kicks off a data extraction job for the project which leverages the Merge Request API to understand pattern of review including recency, domain experience, and frequency to suggest an appropriate reviewer.
+
+This data extraction job can take a few hours to complete (possibly up to a day), which is largely dependent on the size of the project. The process is automated and no action is needed during this process. Once data extraction is complete, you will start getting suggestions in merge requests.
+
+### Generating suggestions
+
+Once Suggested Reviewers is enabled and the data extraction is complete, new merge requests or new commits to existing merge requests will automatically trigger a Suggested Reviewers ML model inference and generate up to 5 suggested reviewers. These suggestions are contextual to the changes in the merge request. Additional commits to merge requests may change the reviewer suggestions which will automatically update in the reviewer dropdown.
+
+## Progressive enhancement
+
+This feature is designed as a progressive enhancement to the existing GitLab Reviewers functionality. The GitLab Reviewer UI will only offer suggestions if the ML engine is able to provide a recommendation. In the event of an issue or model inference failure, the feature will gracefully degrade. At no point with the usage of Suggested Reviewers prevent a user from being able to manually set a reviewer.
+
+## Model Accuracy
+
+Organizations use many different processes for code review. Some focus on senior engineers reviewing junior engineer's code, others have hierarchical organizational structure based reviews. Suggested Reviewers is focused on contextual reviewers based on historical merge request activity by users. While we will continue evolving the underlying ML model to better serve various code review use cases and processes Suggested Reviewers does not replace the usage of other code review features like Code Owners and [Approval Rules](../approvals/rules.md). Reviewer selection is highly subjective therefore, we do not expect Suggested Reviewers to provide perfect suggestions everytime.
+
+Through analysis of beta customer usage, we find that the Suggested Reviewers ML model provides suggestions that are adopted in 60% of cases. We will be introducing a feedback mechanism into the Suggested Reviewers feature in the future to allow users to flag bad reviewer suggestions to help improve the model. Additionally we will be offering an opt-in feature in the future which will allow the model to use your project's data for training the underlying model.
+
+## Off by default
+
+Suggested Reviewers is off by default and requires a Project Owner or Admin to enable the feature.
+
+## Data privacy
+
+Suggested Reviewers operates completely within the GitLab.com infrastructure providing the same level of [privacy](https://about.gitlab.com/privacy/) and [security](https://about.gitlab.com/security/) of any other feature of GitLab.com.
+
+No new additional data is collected to enable this feature, simply GitLab is inferencing your merge request against a trained machine learning model. The content of your source code is not used as training data. Your data also never leaves GitLab.com, all training and inference is done within GitLab.com infrastructure.
+
+[Read more about the security of GitLab.com](https://about.gitlab.com/security/faq/)
diff --git a/doc/user/project/merge_requests/reviews/img/suggested_reviewers_v15_4.png b/doc/user/project/merge_requests/reviews/img/suggested_reviewers_v15_4.png
new file mode 100644
index 00000000000..aae75b0736c
--- /dev/null
+++ b/doc/user/project/merge_requests/reviews/img/suggested_reviewers_v15_4.png
Binary files differ
diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md
index ba20436bf30..b02ccde2589 100644
--- a/doc/user/project/merge_requests/reviews/index.md
+++ b/doc/user/project/merge_requests/reviews/index.md
@@ -21,6 +21,26 @@ You can review merge requests from the GitLab interface. If you install the
[GitLab Workflow VS Code extension](../../repository/vscode.md), you can also
review merge requests in Visual Studio Code.
+## Suggested reviewers **(ULTIMATE SAAS)**
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/modelops/applied-ml/review-recommender/-/epics/3) in GitLab 15.4.
+
+GitLab can recommend reviewers with Suggested Reviewers. Using the changes in a merge request and a project's contribution graph, machine learning powered suggestions appear in the reviewer section of the right merge request sidebar.
+
+![Suggested Reviewers](img/suggested_reviewers_v15_4.png)
+
+This feature is currently in [Open Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#open-beta) behind a [feature flag](https://gitlab.com/gitlab-org/gitlab/-/issues/368356).
+
+Learn more about [how suggested reviewers works and data privacy](data_usage.md).
+
+### Enable suggested reviewers
+
+Project Maintainers or Owners can enable suggested reviewers by visiting the [project settings](../../settings/index.md).
+
+Enabling suggested reviewers will trigger GitLab to create an ML model for your project that will be used to generate reviewers. The larger your project, the longer this can take, but usually, the model will be ready to generate suggestions within a few hours.
+
+No action is required once the feature is enabled. Once the model is ready, recommendations will populate the Reviewer dropdown in the right-hand sidebar of a merge request with new commits.
+
## Review a merge request
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4213) in GitLab 11.4.
diff --git a/spec/features/issues/incident_issue_spec.rb b/spec/features/issues/incident_issue_spec.rb
index 56be1493ed2..6afdb0bd379 100644
--- a/spec/features/issues/incident_issue_spec.rb
+++ b/spec/features/issues/incident_issue_spec.rb
@@ -67,13 +67,13 @@ RSpec.describe 'Incident Detail', :js do
expect(incident_tabs).to have_content('"yet.another": 73')
# does not show the linked issues and notes/comment components' do
- hidden_items = find_all('.js-issue-widgets')
+ hidden_items = find_all('.js-issue-widgets', wait: false)
# Linked Issues/MRs and comment box are hidden on page
expect(hidden_items.count).to eq(0)
# does not show the edit title and description button
- edit_button = find_all('[aria-label="Edit title and description"]')
+ edit_button = find_all('[aria-label="Edit title and description"]', wait: false)
expect(edit_button.count).to eq(0)
end
end
@@ -83,12 +83,14 @@ RSpec.describe 'Incident Detail', :js do
before do
visit project_issue_path(project, incident)
wait_for_requests
+
click_link 'Timeline'
+ wait_for_requests
end
it 'does not show the linked issues and notes/comment components' do
page.within('.issuable-details') do
- hidden_items = find_all('.js-issue-widgets')
+ hidden_items = find_all('.js-issue-widgets', wait: false)
# Linked Issues/MRs and comment box are hidden on page
expect(hidden_items.count).to eq(0)
diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js
index 2c3ec69f9ae..ab80f306ec5 100644
--- a/spec/frontend/boards/board_card_inner_spec.js
+++ b/spec/frontend/boards/board_card_inner_spec.js
@@ -5,7 +5,7 @@ import { nextTick } from 'vue';
import setWindowLocation from 'helpers/set_window_location_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { mountExtended } from 'helpers/vue_test_utils_helper';
-import BoardBlockedIcon from '~/boards/components/board_blocked_icon.vue';
+import IssuableBlockedIcon from '~/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue';
import BoardCardInner from '~/boards/components/board_card_inner.vue';
import BoardCardMoveToPosition from '~/boards/components/board_card_move_to_position.vue';
import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
@@ -39,7 +39,7 @@ describe('Board card component', () => {
let list;
let store;
- const findBoardBlockedIcon = () => wrapper.findComponent(BoardBlockedIcon);
+ const findIssuableBlockedIcon = () => wrapper.findComponent(IssuableBlockedIcon);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findEpicCountablesTotalTooltip = () => wrapper.findComponent(GlTooltip);
const findEpicCountables = () => wrapper.findByTestId('epic-countables');
@@ -189,7 +189,7 @@ describe('Board card component', () => {
},
});
- expect(findBoardBlockedIcon().exists()).toBe(true);
+ expect(findIssuableBlockedIcon().exists()).toBe(true);
});
it('does not show blocked icon if issue is not blocked', () => {
@@ -200,7 +200,7 @@ describe('Board card component', () => {
},
});
- expect(findBoardBlockedIcon().exists()).toBe(false);
+ expect(findIssuableBlockedIcon().exists()).toBe(false);
});
});
diff --git a/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap b/spec/frontend/vue_shared/issuable/__snapshots__/issuable_blocked_icon_spec.js.snap
index 34e4f996ff0..dd011b9d84e 100644
--- a/spec/frontend/boards/components/__snapshots__/board_blocked_icon_spec.js.snap
+++ b/spec/frontend/vue_shared/issuable/__snapshots__/issuable_blocked_icon_spec.js.snap
@@ -1,23 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`BoardBlockedIcon on mouseenter on blocked icon with more than three blocking issues matches the snapshot 1`] = `
-"<div class=\\"gl-display-inline\\"><svg data-testid=\\"issue-blocked-icon\\" role=\\"img\\" aria-hidden=\\"true\\" class=\\"issue-blocked-icon gl-mr-2 gl-cursor-pointer gl-text-red-500 gl-icon s16\\" id=\\"blocked-icon-uniqueId\\">
+exports[`IssuableBlockedIcon on mouseenter on blocked icon with more than three blocking issues matches the snapshot 1`] = `
+"<div class=\\"gl-display-inline\\"><svg data-testid=\\"issuable-blocked-icon\\" role=\\"img\\" aria-hidden=\\"true\\" class=\\"issuable-blocked-icon gl-mr-2 gl-cursor-pointer gl-text-red-500 gl-icon s16\\" id=\\"blocked-icon-uniqueId\\">
<use href=\\"#issue-block\\"></use>
</svg>
<div class=\\"gl-popover\\">
- <ul class=\\"gl-list-style-none gl-p-0\\">
+ <ul class=\\"gl-list-style-none gl-p-0 gl-mb-0\\">
<li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/6\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#6</a>
- <p data-testid=\\"issuable-title\\" class=\\"gl-mb-3 gl-display-block!\\">
+ <p data-testid=\\"issuable-title\\" class=\\"gl-display-block! gl-mb-3\\">
blocking issue title 1
</p>
</li>
<li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/5\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#5</a>
- <p data-testid=\\"issuable-title\\" class=\\"gl-mb-3 gl-display-block!\\">
+ <p data-testid=\\"issuable-title\\" class=\\"gl-display-block! gl-mb-3\\">
blocking issue title 2 + blocking issue title 2 + blocking issue title 2 + bloc…
</p>
</li>
<li><a href=\\"http://gdk.test:3000/gitlab-org/my-project-1/-/issues/4\\" class=\\"gl-link gl-text-blue-500! gl-font-sm\\">my-project-1#4</a>
- <p data-testid=\\"issuable-title\\" class=\\"gl-mb-3 gl-display-block!\\">
+ <p data-testid=\\"issuable-title\\" class=\\"gl-display-block! gl-mb-0\\">
blocking issue title 3
</p>
</li>
diff --git a/spec/frontend/boards/components/board_blocked_icon_spec.js b/spec/frontend/vue_shared/issuable/issuable_blocked_icon_spec.js
index ffdc0a7cecc..d59cbce6633 100644
--- a/spec/frontend/boards/components/board_blocked_icon_spec.js
+++ b/spec/frontend/vue_shared/issuable/issuable_blocked_icon_spec.js
@@ -5,8 +5,9 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import BoardBlockedIcon from '~/boards/components/board_blocked_icon.vue';
-import { blockingIssuablesQueries, issuableTypes } from '~/boards/constants';
+import IssuableBlockedIcon from '~/vue_shared/components/issuable_blocked_icon/issuable_blocked_icon.vue';
+import { blockingIssuablesQueries } from '~/vue_shared/components/issuable_blocked_icon/constants';
+import { issuableTypes } from '~/boards/constants';
import { truncate } from '~/lib/utils/text_utility';
import {
mockIssue,
@@ -21,9 +22,9 @@ import {
mockBlockedIssue2,
mockBlockedEpic1,
mockBlockingEpicIssuablesResponse1,
-} from '../mock_data';
+} from '../../boards/mock_data';
-describe('BoardBlockedIcon', () => {
+describe('IssuableBlockedIcon', () => {
let wrapper;
let mockApollo;
@@ -64,7 +65,7 @@ describe('BoardBlockedIcon', () => {
Vue.use(VueApollo);
wrapper = extendedWrapper(
- mount(BoardBlockedIcon, {
+ mount(IssuableBlockedIcon, {
apolloProvider: mockApollo,
propsData: {
item: {
@@ -88,7 +89,7 @@ describe('BoardBlockedIcon', () => {
issuableType = issuableTypes.issue,
} = {}) => {
wrapper = extendedWrapper(
- shallowMount(BoardBlockedIcon, {
+ shallowMount(IssuableBlockedIcon, {
propsData: {
item: {
...mockIssuable,
diff --git a/workhorse/internal/queueing/queue.go b/workhorse/internal/queueing/queue.go
index db082cf19c6..c8d32280355 100644
--- a/workhorse/internal/queueing/queue.go
+++ b/workhorse/internal/queueing/queue.go
@@ -26,11 +26,10 @@ type queueMetrics struct {
// newQueueMetrics prepares Prometheus metrics for queueing mechanism
// name specifies name of the queue, used to label metrics with ConstLabel `queue_name`
-// Don't call newQueueMetrics twice with the same name argument!
// timeout specifies the timeout of storing a request in queue - queueMetrics
// uses it to calculate histogram buckets for gitlab_workhorse_queueing_waiting_time
// metric
-func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
+func newQueueMetrics(name string, timeout time.Duration, reg prometheus.Registerer) *queueMetrics {
waitingTimeBuckets := []float64{
timeout.Seconds() * 0.01,
timeout.Seconds() * 0.05,
@@ -44,8 +43,9 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
timeout.Seconds(),
}
+ promFactory := promauto.With(reg)
metrics := &queueMetrics{
- queueingLimit: promauto.NewGauge(prometheus.GaugeOpts{
+ queueingLimit: promFactory.NewGauge(prometheus.GaugeOpts{
Name: "gitlab_workhorse_queueing_limit",
Help: "Current limit set for the queueing mechanism",
ConstLabels: prometheus.Labels{
@@ -53,7 +53,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
},
}),
- queueingQueueLimit: promauto.NewGauge(prometheus.GaugeOpts{
+ queueingQueueLimit: promFactory.NewGauge(prometheus.GaugeOpts{
Name: "gitlab_workhorse_queueing_queue_limit",
Help: "Current queueLimit set for the queueing mechanism",
ConstLabels: prometheus.Labels{
@@ -61,7 +61,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
},
}),
- queueingQueueTimeout: promauto.NewGauge(prometheus.GaugeOpts{
+ queueingQueueTimeout: promFactory.NewGauge(prometheus.GaugeOpts{
Name: "gitlab_workhorse_queueing_queue_timeout",
Help: "Current queueTimeout set for the queueing mechanism",
ConstLabels: prometheus.Labels{
@@ -69,7 +69,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
},
}),
- queueingBusy: promauto.NewGauge(prometheus.GaugeOpts{
+ queueingBusy: promFactory.NewGauge(prometheus.GaugeOpts{
Name: "gitlab_workhorse_queueing_busy",
Help: "How many queued requests are now processed",
ConstLabels: prometheus.Labels{
@@ -77,7 +77,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
},
}),
- queueingWaiting: promauto.NewGauge(prometheus.GaugeOpts{
+ queueingWaiting: promFactory.NewGauge(prometheus.GaugeOpts{
Name: "gitlab_workhorse_queueing_waiting",
Help: "How many requests are now queued",
ConstLabels: prometheus.Labels{
@@ -85,7 +85,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
},
}),
- queueingWaitingTime: promauto.NewHistogram(prometheus.HistogramOpts{
+ queueingWaitingTime: promFactory.NewHistogram(prometheus.HistogramOpts{
Name: "gitlab_workhorse_queueing_waiting_time",
Help: "How many time a request spent in queue",
ConstLabels: prometheus.Labels{
@@ -94,7 +94,7 @@ func newQueueMetrics(name string, timeout time.Duration) *queueMetrics {
Buckets: waitingTimeBuckets,
}),
- queueingErrors: promauto.NewCounterVec(
+ queueingErrors: promFactory.NewCounterVec(
prometheus.CounterOpts{
Name: "gitlab_workhorse_queueing_errors",
Help: "How many times the TooManyRequests or QueueintTimedout errors were returned while queueing, partitioned by error type",
@@ -120,12 +120,11 @@ type Queue struct {
// newQueue creates a new queue
// name specifies name used to label queue metrics.
-// Don't call newQueue twice with the same name argument!
// limit specifies number of requests run concurrently
// queueLimit specifies maximum number of requests that can be queued
// timeout specifies the time limit of storing the request in the queue
// if the number of requests is above the limit
-func newQueue(name string, limit, queueLimit uint, timeout time.Duration) *Queue {
+func newQueue(name string, limit, queueLimit uint, timeout time.Duration, reg prometheus.Registerer) *Queue {
queue := &Queue{
name: name,
busyCh: make(chan struct{}, limit),
@@ -133,7 +132,7 @@ func newQueue(name string, limit, queueLimit uint, timeout time.Duration) *Queue
timeout: timeout,
}
- queue.queueMetrics = newQueueMetrics(name, timeout)
+ queue.queueMetrics = newQueueMetrics(name, timeout, reg)
queue.queueingLimit.Set(float64(limit))
queue.queueingQueueLimit.Set(float64(queueLimit))
queue.queueingQueueTimeout.Set(timeout.Seconds())
diff --git a/workhorse/internal/queueing/queue_test.go b/workhorse/internal/queueing/queue_test.go
index 7f5ed9154f4..dee0df76c67 100644
--- a/workhorse/internal/queueing/queue_test.go
+++ b/workhorse/internal/queueing/queue_test.go
@@ -3,10 +3,12 @@ package queueing
import (
"testing"
"time"
+
+ "github.com/prometheus/client_golang/prometheus"
)
func TestNormalQueueing(t *testing.T) {
- q := newQueue("queue 1", 2, 1, time.Microsecond)
+ q := newQueue("queue name", 2, 1, time.Microsecond, prometheus.NewRegistry())
err1 := q.Acquire()
if err1 != nil {
t.Fatal("we should acquire a new slot")
@@ -31,7 +33,7 @@ func TestNormalQueueing(t *testing.T) {
}
func TestQueueLimit(t *testing.T) {
- q := newQueue("queue 2", 1, 0, time.Microsecond)
+ q := newQueue("queue name", 1, 0, time.Microsecond, prometheus.NewRegistry())
err1 := q.Acquire()
if err1 != nil {
t.Fatal("we should acquire a new slot")
@@ -44,7 +46,7 @@ func TestQueueLimit(t *testing.T) {
}
func TestQueueProcessing(t *testing.T) {
- q := newQueue("queue 3", 1, 1, time.Second)
+ q := newQueue("queue name", 1, 1, time.Second, prometheus.NewRegistry())
err1 := q.Acquire()
if err1 != nil {
t.Fatal("we should acquire a new slot")
diff --git a/workhorse/internal/queueing/requests.go b/workhorse/internal/queueing/requests.go
index 3a22cb367ce..34d4c985f53 100644
--- a/workhorse/internal/queueing/requests.go
+++ b/workhorse/internal/queueing/requests.go
@@ -4,6 +4,8 @@ import (
"net/http"
"time"
+ "github.com/prometheus/client_golang/prometheus"
+
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
)
@@ -19,7 +21,7 @@ const (
// limit specifies number of requests run concurrently
// queueLimit specifies maximum number of requests that can be queued
// queueTimeout specifies the time limit of storing the request in the queue
-func QueueRequests(name string, h http.Handler, limit, queueLimit uint, queueTimeout time.Duration) http.Handler {
+func QueueRequests(name string, h http.Handler, limit, queueLimit uint, queueTimeout time.Duration, reg prometheus.Registerer) http.Handler {
if limit == 0 {
return h
}
@@ -27,7 +29,7 @@ func QueueRequests(name string, h http.Handler, limit, queueLimit uint, queueTim
queueTimeout = DefaultTimeout
}
- queue := newQueue(name, limit, queueLimit, queueTimeout)
+ queue := newQueue(name, limit, queueLimit, queueTimeout, reg)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
err := queue.Acquire()
diff --git a/workhorse/internal/queueing/requests_test.go b/workhorse/internal/queueing/requests_test.go
index f1c52e5c6f5..eb098a6242e 100644
--- a/workhorse/internal/queueing/requests_test.go
+++ b/workhorse/internal/queueing/requests_test.go
@@ -6,6 +6,8 @@ import (
"net/http/httptest"
"testing"
"time"
+
+ "github.com/prometheus/client_golang/prometheus"
)
var httpHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -21,7 +23,7 @@ func pausedHttpHandler(pauseCh chan struct{}) http.Handler {
func TestNormalRequestProcessing(t *testing.T) {
w := httptest.NewRecorder()
- h := QueueRequests("Normal request processing", httpHandler, 1, 1, time.Second)
+ h := QueueRequests("Normal request processing", httpHandler, 1, 1, time.Second, prometheus.NewRegistry())
h.ServeHTTP(w, nil)
if w.Code != 200 {
t.Fatal("QueueRequests should process request")
@@ -36,7 +38,7 @@ func testSlowRequestProcessing(name string, count int, limit, queueLimit uint, q
pauseCh := make(chan struct{})
defer close(pauseCh)
- handler := QueueRequests("Slow request processing: "+name, pausedHttpHandler(pauseCh), limit, queueLimit, queueTimeout)
+ handler := QueueRequests("Slow request processing: "+name, pausedHttpHandler(pauseCh), limit, queueLimit, queueTimeout, prometheus.NewRegistry())
respCh := make(chan *httptest.ResponseRecorder, count)
diff --git a/workhorse/internal/upload/destination/objectstore/s3_session.go b/workhorse/internal/upload/destination/objectstore/s3_session.go
index d71b38eb22e..e1fe6fbbdc9 100644
--- a/workhorse/internal/upload/destination/objectstore/s3_session.go
+++ b/workhorse/internal/upload/destination/objectstore/s3_session.go
@@ -37,17 +37,13 @@ func (s *s3Session) isExpired() bool {
return time.Now().After(s.expiry)
}
-func newS3SessionCache() *s3SessionCache {
- return &s3SessionCache{sessions: make(map[config.S3Config]*s3Session)}
-}
-
var (
// By default, it looks like IAM instance profiles may last 6 hours
// (via curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<role_name>),
// but this may be configurable from anywhere for 15 minutes to 12
// hours. To be safe, refresh AWS sessions every 10 minutes.
sessionExpiration = time.Duration(10 * time.Minute)
- sessionCache = newS3SessionCache()
+ sessionCache = &s3SessionCache{sessions: make(map[config.S3Config]*s3Session)}
)
// SetupS3Session initializes a new AWS S3 session and refreshes one if
@@ -105,10 +101,3 @@ func setupS3Session(s3Credentials config.S3Credentials, s3Config config.S3Config
return sess, nil
}
-
-func ResetS3Session(s3Config config.S3Config) {
- sessionCache.Lock()
- defer sessionCache.Unlock()
-
- delete(sessionCache.sessions, s3Config)
-}
diff --git a/workhorse/internal/upload/destination/objectstore/s3_session_test.go b/workhorse/internal/upload/destination/objectstore/s3_session_test.go
index 4bbe38f90ec..b7bbee0ef69 100644
--- a/workhorse/internal/upload/destination/objectstore/s3_session_test.go
+++ b/workhorse/internal/upload/destination/objectstore/s3_session_test.go
@@ -12,6 +12,8 @@ import (
)
func TestS3SessionSetup(t *testing.T) {
+ resetS3Sessions()
+
credentials := config.S3Credentials{}
cfg := config.S3Config{Region: "us-west-1", PathStyle: true}
@@ -28,11 +30,11 @@ func TestS3SessionSetup(t *testing.T) {
_, err = setupS3Session(credentials, anotherConfig)
require.NoError(t, err)
require.Equal(t, len(sessionCache.sessions), 1)
-
- ResetS3Session(cfg)
}
func TestS3SessionEndpointSetup(t *testing.T) {
+ resetS3Sessions()
+
credentials := config.S3Credentials{}
const customS3Endpoint = "https://example.com"
const region = "us-west-2"
@@ -48,11 +50,11 @@ func TestS3SessionEndpointSetup(t *testing.T) {
stsConfig := sess.ClientConfig(endpoints.StsServiceID)
require.Equal(t, "https://sts.amazonaws.com", stsConfig.Endpoint, "STS should use default endpoint")
-
- ResetS3Session(cfg)
}
func TestS3SessionExpiry(t *testing.T) {
+ resetS3Sessions()
+
credentials := config.S3Credentials{}
cfg := config.S3Config{Region: "us-west-1", PathStyle: true}
@@ -75,6 +77,10 @@ func TestS3SessionExpiry(t *testing.T) {
nextSession, ok := sessionCache.sessions[cfg]
require.True(t, ok)
require.False(t, nextSession.isExpired())
+}
- ResetS3Session(cfg)
+func resetS3Sessions() {
+ sessionCache.Lock()
+ defer sessionCache.Unlock()
+ sessionCache.sessions = make(map[config.S3Config]*s3Session)
}
diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go
index 40cd012a890..08e3ef8c9f1 100644
--- a/workhorse/internal/upstream/routes.go
+++ b/workhorse/internal/upstream/routes.go
@@ -6,6 +6,7 @@ import (
"regexp"
"github.com/gorilla/websocket"
+ "github.com/prometheus/client_golang/prometheus"
"gitlab.com/gitlab-org/labkit/log"
"gitlab.com/gitlab-org/labkit/tracing"
@@ -221,7 +222,7 @@ func configureRoutes(u *upstream) {
mimeMultipartUploader := upload.Multipart(api, signingProxy, preparer)
tempfileMultipartProxy := upload.FixedPreAuthMultipart(api, proxy, preparer)
- ciAPIProxyQueue := queueing.QueueRequests("ci_api_job_requests", tempfileMultipartProxy, u.APILimit, u.APIQueueLimit, u.APIQueueTimeout)
+ ciAPIProxyQueue := queueing.QueueRequests("ci_api_job_requests", tempfileMultipartProxy, u.APILimit, u.APIQueueLimit, u.APIQueueTimeout, prometheus.DefaultRegisterer)
ciAPILongPolling := builds.RegisterHandler(ciAPIProxyQueue, u.watchKeyHandler, u.APICILongPollingDuration)
dependencyProxyInjector.SetUploadHandler(requestBodyUploader)