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:
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/clusters_list/components/ancestor_notice.vue34
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters.vue4
-rw-r--r--app/assets/javascripts/clusters_list/store/state.js1
-rw-r--r--app/graphql/types/jira_user_type.rb6
-rw-r--r--app/helpers/clusters_helper.rb1
-rw-r--r--app/services/ci/register_job_service.rb19
-rw-r--r--app/services/jira_import/users_mapper.rb7
-rw-r--r--app/views/clusters/clusters/index.html.haml11
-rw-r--r--app/workers/concerns/reenqueuer.rb2
-rw-r--r--changelogs/unreleased/225212-add-fields-to-jira-mutation.yml5
-rw-r--r--changelogs/unreleased/rc-remove_metric_identifier_index.yml5
-rw-r--r--changelogs/unreleased/sh-requeue-failed-job-register.yml5
-rw-r--r--db/migrate/20200702201039_change_prometheus_metrics_identifier_index.rb22
-rw-r--r--db/structure.sql3
-rw-r--r--doc/administration/gitaly/praefect.md7
-rw-r--r--doc/administration/server_hooks.md43
-rw-r--r--doc/api/README.md2
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql12
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json30
-rw-r--r--doc/api/graphql/reference/index.md4
-rw-r--r--doc/api/settings.md5
-rw-r--r--doc/development/elasticsearch.md3
-rw-r--r--doc/development/fe_guide/vue.md14
-rw-r--r--lib/api/ci/runner.rb19
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/frontend/clusters_list/components/ancestor_notice_spec.js51
-rw-r--r--spec/graphql/types/jira_user_type_spec.rb13
-rw-r--r--spec/helpers/clusters_helper_spec.rb24
-rw-r--r--spec/requests/api/ci/runner_spec.rb21
-rw-r--r--spec/services/ci/register_job_service_spec.rb4
-rw-r--r--spec/services/jira_import/users_mapper_spec.rb6
32 files changed, 336 insertions, 52 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index debfaddcc6d..a9899263941 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-a75309cec88ed34f594a4f6514bb0bb2aef7fcd5
+fdd1fe70085c1a20b10553680d88a967a4cfbfae
diff --git a/app/assets/javascripts/clusters_list/components/ancestor_notice.vue b/app/assets/javascripts/clusters_list/components/ancestor_notice.vue
new file mode 100644
index 00000000000..7954fc61785
--- /dev/null
+++ b/app/assets/javascripts/clusters_list/components/ancestor_notice.vue
@@ -0,0 +1,34 @@
+<script>
+import { GlLink, GlSprintf } from '@gitlab/ui';
+import { mapState } from 'vuex';
+
+export default {
+ components: {
+ GlLink,
+ GlSprintf,
+ },
+ computed: {
+ ...mapState(['ancestorHelperPath', 'hasAncestorClusters']),
+ },
+};
+</script>
+
+<template>
+ <div v-if="hasAncestorClusters" class="bs-callout bs-callout-info">
+ <p>
+ <gl-sprintf
+ :message="
+ s__(
+ 'ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}',
+ )
+ "
+ >
+ <template #link="{ content }">
+ <gl-link :href="ancestorHelperPath">
+ <strong>{{ content }}</strong>
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </div>
+</template>
diff --git a/app/assets/javascripts/clusters_list/components/clusters.vue b/app/assets/javascripts/clusters_list/components/clusters.vue
index a51760599ea..7e9b720d269 100644
--- a/app/assets/javascripts/clusters_list/components/clusters.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters.vue
@@ -9,6 +9,7 @@ import {
GlSprintf,
GlTable,
} from '@gitlab/ui';
+import AncestorNotice from './ancestor_notice.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import { CLUSTER_TYPES, STATUSES } from '../constants';
import { __, sprintf } from '~/locale';
@@ -17,6 +18,7 @@ export default {
nodeMemoryText: __('%{totalMemory} (%{freeSpacePercentage}%{percentSymbol} free)'),
nodeCpuText: __('%{totalCpu} (%{freeSpacePercentage}%{percentSymbol} free)'),
components: {
+ AncestorNotice,
GlBadge,
GlLink,
GlLoadingIcon,
@@ -195,6 +197,8 @@ export default {
<gl-loading-icon v-if="loadingClusters" size="md" class="gl-mt-3" />
<section v-else>
+ <ancestor-notice />
+
<gl-table :items="clusters" :fields="fields" stacked="md" class="qa-clusters-table">
<template #cell(name)="{ item }">
<div :class="[contentAlignClasses, 'js-status']">
diff --git a/app/assets/javascripts/clusters_list/store/state.js b/app/assets/javascripts/clusters_list/store/state.js
index 8f42cba6a6e..51fafd49479 100644
--- a/app/assets/javascripts/clusters_list/store/state.js
+++ b/app/assets/javascripts/clusters_list/store/state.js
@@ -1,4 +1,5 @@
export default (initialState = {}) => ({
+ ancestorHelperPath: initialState.ancestorHelpPath,
endpoint: initialState.endpoint,
hasAncestorClusters: false,
clusters: [],
diff --git a/app/graphql/types/jira_user_type.rb b/app/graphql/types/jira_user_type.rb
index 8aa21ce669b..999526a920e 100644
--- a/app/graphql/types/jira_user_type.rb
+++ b/app/graphql/types/jira_user_type.rb
@@ -13,7 +13,11 @@ module Types
field :jira_email, GraphQL::STRING_TYPE, null: true,
description: 'Email of the Jira user, returned only for users with public emails'
field :gitlab_id, GraphQL::INT_TYPE, null: true,
- description: 'Id of the matched GitLab user'
+ description: 'ID of the matched GitLab user'
+ field :gitlab_username, GraphQL::STRING_TYPE, null: true,
+ description: 'Username of the matched GitLab user'
+ field :gitlab_name, GraphQL::STRING_TYPE, null: true,
+ description: 'Name of the matched GitLab user'
end
# rubocop: enable Graphql/AuthorizeTypes
end
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index 005070cca5c..b87d1c4e1ce 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -18,6 +18,7 @@ module ClustersHelper
def js_clusters_list_data(path = nil)
{
+ ancestor_help_path: help_page_path('user/group/clusters/index', anchor: 'cluster-precedence'),
endpoint: path,
img_tags: {
aws: { path: image_path('illustrations/logos/amazon_eks.svg'), text: s_('ClusterIntegration|Amazon EKS') },
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index 17b9e56636b..3797ea1d96c 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -11,7 +11,7 @@ module Ci
METRICS_SHARD_TAG_PREFIX = 'metrics_shard::'.freeze
DEFAULT_METRICS_SHARD = 'default'.freeze
- Result = Struct.new(:build, :valid?)
+ Result = Struct.new(:build, :build_json, :valid?)
def initialize(runner)
@runner = runner
@@ -59,7 +59,7 @@ module Ci
end
register_failure
- Result.new(nil, valid)
+ Result.new(nil, nil, valid)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -71,7 +71,7 @@ module Ci
# In case when 2 runners try to assign the same build, second runner will be declined
# with StateMachines::InvalidTransition or StaleObjectError when doing run! or save method.
if assign_runner!(build, params)
- Result.new(build, true)
+ present_build!(build)
end
rescue StateMachines::InvalidTransition, ActiveRecord::StaleObjectError
# We are looping to find another build that is not conflicting
@@ -83,8 +83,10 @@ module Ci
# In case we hit the concurrency-access lock,
# we still have to return 409 in the end,
# to make sure that this is properly handled by runner.
- Result.new(nil, false)
+ Result.new(nil, nil, false)
rescue => ex
+ # If an error (e.g. GRPC::DeadlineExceeded) occurred constructing
+ # the result, consider this as a failure to be retried.
scheduler_failure!(build)
track_exception_for_build(ex, build)
@@ -92,6 +94,15 @@ module Ci
nil
end
+ # Force variables evaluation to occur now
+ def present_build!(build)
+ # We need to use the presenter here because Gitaly calls in the presenter
+ # may fail, and we need to ensure the response has been generated.
+ presented_build = ::Ci::BuildRunnerPresenter.new(build) # rubocop:disable CodeReuse/Presenter
+ build_json = ::API::Entities::JobRequest::Response.new(presented_build).to_json
+ Result.new(build, build_json, true)
+ end
+
def assign_runner!(build, params)
build.runner_id = runner.id
build.runner_session_attributes = params[:session] if params[:session].present?
diff --git a/app/services/jira_import/users_mapper.rb b/app/services/jira_import/users_mapper.rb
index 31a3f721556..c3cbeb157bd 100644
--- a/app/services/jira_import/users_mapper.rb
+++ b/app/services/jira_import/users_mapper.rb
@@ -14,9 +14,8 @@ module JiraImport
{
jira_account_id: jira_user['accountId'],
jira_display_name: jira_user['displayName'],
- jira_email: jira_user['emailAddress'],
- gitlab_id: match_user(jira_user)
- }
+ jira_email: jira_user['emailAddress']
+ }.merge(match_user(jira_user))
end
end
@@ -25,7 +24,7 @@ module JiraImport
# TODO: Matching user by email and displayName will be done as the part
# of follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/219023
def match_user(jira_user)
- nil
+ { gitlab_id: nil, gitlab_username: nil, gitlab_name: nil }
end
end
end
diff --git a/app/views/clusters/clusters/index.html.haml b/app/views/clusters/clusters/index.html.haml
index a654a8741a4..557ad1bf280 100644
--- a/app/views/clusters/clusters/index.html.haml
+++ b/app/views/clusters/clusters/index.html.haml
@@ -12,15 +12,14 @@
= s_('ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project')
= render 'clusters/clusters/buttons'
- - if @has_ancestor_clusters
- .bs-callout.bs-callout-info
- = s_('ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters.')
- %strong
- = link_to _('More information'), help_page_path('user/group/clusters/index', anchor: 'cluster-precedence')
-
- if Feature.enabled?(:clusters_list_redesign)
#js-clusters-list-app{ data: js_clusters_list_data(clusterable.index_path(format: :json)) }
- else
+ - if @has_ancestor_clusters
+ .bs-callout.bs-callout-info
+ = s_('ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters.')
+ %strong
+ = link_to _('More information'), help_page_path('user/group/clusters/index', anchor: 'cluster-precedence')
.clusters-table.js-clusters-list
.gl-responsive-table-row.table-row-header{ role: "row" }
.table-section.section-60{ role: "rowheader" }
diff --git a/app/workers/concerns/reenqueuer.rb b/app/workers/concerns/reenqueuer.rb
index 79a1d2d0070..bf6f6546c03 100644
--- a/app/workers/concerns/reenqueuer.rb
+++ b/app/workers/concerns/reenqueuer.rb
@@ -60,8 +60,6 @@ module Reenqueuer
5.seconds
end
- # We intend to get rid of sleep:
- # https://gitlab.com/gitlab-org/gitlab/issues/121697
module ReenqueuerSleeper
# The block will run, and then sleep until the minimum duration. Returns the
# block's return value.
diff --git a/changelogs/unreleased/225212-add-fields-to-jira-mutation.yml b/changelogs/unreleased/225212-add-fields-to-jira-mutation.yml
new file mode 100644
index 00000000000..0873b43de80
--- /dev/null
+++ b/changelogs/unreleased/225212-add-fields-to-jira-mutation.yml
@@ -0,0 +1,5 @@
+---
+title: Add GitLab username and name to the import users from Jira mutation response
+merge_request: 35542
+author:
+type: changed
diff --git a/changelogs/unreleased/rc-remove_metric_identifier_index.yml b/changelogs/unreleased/rc-remove_metric_identifier_index.yml
new file mode 100644
index 00000000000..3196313e731
--- /dev/null
+++ b/changelogs/unreleased/rc-remove_metric_identifier_index.yml
@@ -0,0 +1,5 @@
+---
+title: Change PrometheusMetrics identifier index
+merge_request: 35912
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-requeue-failed-job-register.yml b/changelogs/unreleased/sh-requeue-failed-job-register.yml
new file mode 100644
index 00000000000..1a80095aeee
--- /dev/null
+++ b/changelogs/unreleased/sh-requeue-failed-job-register.yml
@@ -0,0 +1,5 @@
+---
+title: Fail jobs that fail to render registration response
+merge_request: 36274
+author:
+type: fixed
diff --git a/db/migrate/20200702201039_change_prometheus_metrics_identifier_index.rb b/db/migrate/20200702201039_change_prometheus_metrics_identifier_index.rb
new file mode 100644
index 00000000000..248195c8c75
--- /dev/null
+++ b/db/migrate/20200702201039_change_prometheus_metrics_identifier_index.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class ChangePrometheusMetricsIdentifierIndex < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ NEW_INDEX = :index_prometheus_metrics_on_identifier_and_null_project
+ OLD_INDEX = :index_prometheus_metrics_on_identifier
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :prometheus_metrics, :identifier, name: NEW_INDEX, unique: true, where: 'project_id IS NULL'
+ remove_concurrent_index_by_name :prometheus_metrics, OLD_INDEX
+ end
+
+ def down
+ add_concurrent_index :prometheus_metrics, :identifier, name: OLD_INDEX, unique: true
+ remove_concurrent_index_by_name :prometheus_metrics, NEW_INDEX
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index 49c023d6ed4..752fc2b1502 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -20025,7 +20025,7 @@ CREATE INDEX index_prometheus_metrics_on_common ON public.prometheus_metrics USI
CREATE INDEX index_prometheus_metrics_on_group ON public.prometheus_metrics USING btree ("group");
-CREATE UNIQUE INDEX index_prometheus_metrics_on_identifier ON public.prometheus_metrics USING btree (identifier);
+CREATE UNIQUE INDEX index_prometheus_metrics_on_identifier_and_null_project ON public.prometheus_metrics USING btree (identifier) WHERE (project_id IS NULL);
CREATE UNIQUE INDEX index_prometheus_metrics_on_identifier_and_project_id ON public.prometheus_metrics USING btree (identifier, project_id);
@@ -23718,6 +23718,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200701093859
20200701205710
20200702123805
+20200702201039
20200703064117
20200703121557
20200703154822
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index 88e59ba7ffc..a718de85b54 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -35,7 +35,8 @@ The availability objectives for Gitaly clusters are:
Writes are replicated asynchronously. Any writes that have not been replicated
to the newly promoted primary are lost.
- [Strong consistency](#strong-consistency) can be used to improve this to "no loss".
+ [Strong consistency](#strong-consistency) can be used to avoid loss in some
+ circumstances.
- **Recovery Time Objective (RTO):** Less than 10 seconds.
@@ -886,8 +887,8 @@ after the write to the primary Gitaly node has happened.
Praefect can instead provide strong consistency by creating a transaction and writing
changes to all Gitaly nodes at once. Strong consistency is currently in
[alpha](https://about.gitlab.com/handbook/product/#alpha-beta-ga) and not enabled by
-default. For more information, see the
-[strong consistency epic](https://gitlab.com/groups/gitlab-org/-/epics/1189).
+default. If enabled, transactions are only available for a subset of RPCs. For more
+information, see the [strong consistency epic](https://gitlab.com/groups/gitlab-org/-/epics/1189).
To enable strong consistency:
diff --git a/doc/administration/server_hooks.md b/doc/administration/server_hooks.md
index 6df0f187a42..eebf9113643 100644
--- a/doc/administration/server_hooks.md
+++ b/doc/administration/server_hooks.md
@@ -119,6 +119,49 @@ For `<project>.git` you'll need to
[translate your project name into the hashed storage format](repository_storage_types.md#translating-hashed-storage-paths)
that GitLab uses.
+## Environment Variables
+
+The following set of environment variables are available to server hooks.
+
+### GitLab Environment Variables
+
+| Envirnment Variable | purpose |
+|---------------------|---------------------------------------------------------|
+| GL_ID | GitLab identifier eg: user-2234 that initiated the push |
+| GL_PROJECT_PATH (available starting 13.2) | GitLab project path |
+| GL_PROTOCOL (available starting 13.2) | Protocol used with push |
+| GL_REPOSITORY | project-<id> where id of the project |
+| GL_USERNAME | GitLab username that initiated the push |
+
+Pre-receive and post-receive server hooks can also access the following Git environment variables.
+
+| Environment variable | Description |
+|:-----------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `GIT_ALTERNATE_OBJECT_DIRECTORIES` | Alternate object directories in the quarantine environment. See [Git `receive-pack` documentation](https://git-scm.com/docs/git-receive-pack#_quarantine_environment). |
+| `GIT_OBJECT_DIRECTORY` | GitLab project path in the quarantine environment. See [Git `receive-pack` documentation](https://git-scm.com/docs/git-receive-pack#_quarantine_environment). |
+| `GIT_PUSH_OPTION_COUNT` | Number of push options. See [Git `pre-receive` documentation](https://git-scm.com/docs/githooks#pre-receive). |
+| `GIT_PUSH_OPTION_<i>` | Value of push options where `i` is from `0` to `GIT_PUSH_OPTION_COUNT - 1`. See [Git `pre-receive` documentation](https://git-scm.com/docs/githooks#pre-receive). |
+
+NOTE: **Note:**
+While other environment variables can be passed to server hooks, your application
+should not rely on them as they can change.
+
+## Transition to Go
+
+> Introduced in GitLab 13.2 using feature flags.
+
+The following server hooks have been reimplemented in Go:
+
+- `pre-receive`, with the Go implementation used by default. To use the Ruby
+ implementation instead, [disable](../operations/feature_flags.md#enable-or-disable-feature-flag-strategies)
+ the `:gitaly_go_preceive_hook` feature flag.
+- `update`, with the Go implementation used by default. To use the Ruby implementation
+ instead, [disable](../operations/feature_flags.md#enable-or-disable-feature-flag-strategies)
+ the `:gitaly_go_update_hook` feature flag.
+- `post-receive`, however the Ruby implementation is used by default. To use the Go
+ implementation instead, [enabled](../operations/feature_flags.md#enable-or-disable-feature-flag-strategies)
+ the `:gitaly_go_postreceive_hook` feature flag.
+
## Custom error messages
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5073) in GitLab 8.10.
diff --git a/doc/api/README.md b/doc/api/README.md
index 16413632d78..b07f14b5a7a 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -423,7 +423,7 @@ Status: 200 OK
```
CAUTION: **Deprecation:**
-The `Links` Header will be removed in GitLab 14.0 to be aligned with the [W3C specification](https://www.w3.org/wiki/LinkHeader)
+The `Links` Header will be removed in GitLab 14.0 to be aligned with the [W3C `Link` specification](https://www.w3.org/wiki/LinkHeader)
The link to the next page contains an additional filter `id_after=42` which excludes records we have retrieved already.
Note the type of filter depends on the `order_by` option used and we may have more than one additional filter.
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index b25a3179ca6..f3659f9269f 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -6656,11 +6656,21 @@ type JiraService implements Service {
type JiraUser {
"""
- Id of the matched GitLab user
+ ID of the matched GitLab user
"""
gitlabId: Int
"""
+ Name of the matched GitLab user
+ """
+ gitlabName: String
+
+ """
+ Username of the matched GitLab user
+ """
+ gitlabUsername: String
+
+ """
Account id of the Jira user
"""
jiraAccountId: String!
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 432342ad8b1..96097e3f5ac 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -18439,7 +18439,7 @@
"fields": [
{
"name": "gitlabId",
- "description": "Id of the matched GitLab user",
+ "description": "ID of the matched GitLab user",
"args": [
],
@@ -18452,6 +18452,34 @@
"deprecationReason": null
},
{
+ "name": "gitlabName",
+ "description": "Name of the matched GitLab user",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "gitlabUsername",
+ "description": "Username of the matched GitLab user",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "jiraAccountId",
"description": "Account id of the Jira user",
"args": [
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 431e068a497..c80337175c9 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -1007,7 +1007,9 @@ Autogenerated return type of JiraImportUsers
| Name | Type | Description |
| --- | ---- | ---------- |
-| `gitlabId` | Int | Id of the matched GitLab user |
+| `gitlabId` | Int | ID of the matched GitLab user |
+| `gitlabName` | String | Name of the matched GitLab user |
+| `gitlabUsername` | String | Username of the matched GitLab user |
| `jiraAccountId` | String! | Account id of the Jira user |
| `jiraDisplayName` | String! | Display name of the Jira user |
| `jiraEmail` | String | Email of the Jira user, returned only for users with public emails |
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 78d992cff58..e5f3da7fbf6 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -48,7 +48,7 @@ Example response:
"sign_in_text" : null,
"container_expiration_policies_enable_historic_entries": true,
"container_registry_token_expire_delay": 5,
- "repository_storages": ["default"],
+ "repository_storages_weighted": {"default": 100},
"plantuml_enabled": false,
"plantuml_url": null,
"terminal_max_session_time": 0,
@@ -314,7 +314,8 @@ are listed in the descriptions of the relevant settings.
| `receive_max_input_size` | integer | no | Maximum push size (MB). |
| `repository_checks_enabled` | boolean | no | GitLab will periodically run `git fsck` in all project and wiki repositories to look for silent disk corruption issues. |
| `repository_size_limit` | integer | no | **(PREMIUM)** Size limit per repository (MB) |
-| `repository_storages` | array of strings | no | A list of names of enabled storage paths, taken from `gitlab.yml`. New projects will be created in one of these stores, chosen at random. |
+| `repository_storages` | array of strings | no | (GitLab 13.0 and earlier) List of names of enabled storage paths, taken from `gitlab.yml`. New projects are created in one of these stores, chosen at random. |
+| `repository_storages_weighted` | hash of strings to integers | no | (GitLab 13.1 and later) Hash of names of taken from `gitlab.yml` to weights. New projects are created in one of these stores, chosen by a weighted random selection. |
| `require_two_factor_authentication` | boolean | no | (**If enabled, requires:** `two_factor_grace_period`) Require all users to set up Two-factor authentication. |
| `restricted_visibility_levels` | array of strings | no | Selected levels cannot be used by non-admin users for groups, projects or snippets. Can take `private`, `internal` and `public` as a parameter. Default is `null` which means there is no restriction. |
| `rsa_key_restriction` | integer | no | The minimum allowed bit length of an uploaded RSA key. Default is `0` (no restriction). `-1` disables RSA keys. |
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index c63e0164e43..425b6b01b76 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -111,7 +111,8 @@ Patterns:
- `'"((?:\\"|[^"]|\\")*)"'`: captures terms inside quotes, removing the quotes
- `"'((?:\\'|[^']|\\')*)'"`: same as above, for single-quotes
- `'\.([^.]+)(?=\.|\s|\Z)'`: separate terms with periods in-between
-- `'([\p{L}_.-]+)'` : some common chars in file names to keep the whole filename intact (eg. `my_file-ñame.txt`)
+- `'([\p{L}_.-]+)'`: some common chars in file names to keep the whole filename intact (eg. `my_file-ñame.txt`)
+- `'([\p{L}\d_]+)'`: letters, numbers and underscores are the most common tokens in programming. Always capture them greedily regardless of context.
## Gotchas
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 0d77e4d129b..2a0556c6cda 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -53,14 +53,14 @@ Be sure to read about [page-specific JavaScript](./performance.md#page-specific-
#### Providing data from HAML to JavaScript
-While mounting a Vue application may be a need to provide data from Rails to JavaScript.
-To do that, provide the data through `data` attributes in the HTML element and query them while mounting the application.
+While mounting a Vue application, you might need to provide data from Rails to JavaScript.
+To do that, you can use the `data` attributes in the HTML element and query them while mounting the application.
_Note:_ You should only do this while initializing the application, because the mounted element will be replaced with Vue-generated DOM.
The advantage of providing data from the DOM to the Vue instance through `props` in the `render` function
-instead of querying the DOM inside the main Vue component is that makes tests easier by avoiding the need to
-create a fixture or an HTML element in the unit test. See the following example:
+instead of querying the DOM inside the main Vue component is avoiding the need to create a fixture or an HTML element in the unit test,
+which will make the tests easier. See the following example:
```javascript
// haml
@@ -134,7 +134,7 @@ This approach has a few benefits:
intermediate components being aware of it (c.f. passing the flag down via
props).
- Good testability, since the flag can be provided to `mount`/`shallowMount`
- from `vue-test-utils` as easily as a prop.
+ from `vue-test-utils` simply as a prop.
```javascript
import { shallowMount } from '@vue/test-utils';
@@ -155,7 +155,7 @@ This folder holds all components that are specific of this new feature.
If you need to use or create a component that will probably be used somewhere
else, please refer to `vue_shared/components`.
-A good thumb rule to know when you should create a component is to think if
+A good rule of thumb to know when you should create a component is to think if
it will be reusable elsewhere.
For example, tables are used in a quite amount of places across GitLab, a table
@@ -321,7 +321,7 @@ We should verify an event has been fired by asserting against the result of the
## Vue.js Expert Role
-One should apply to be a Vue.js expert by opening an MR when the Merge Request's they create and review show:
+You should only apply to be a Vue.js expert when your own merge requests and your reviews show:
- Deep understanding of Vue and Vuex reactivity
- Vue and Vuex code are structured according to both official and our guidelines
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index 4c96acd3ea7..31be1bb7e3e 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -108,6 +108,20 @@ module API
end
optional :job_age, type: Integer, desc: %q(Job should be older than passed age in seconds to be ran on runner)
end
+
+ # Since we serialize the build output ourselves to ensure Gitaly
+ # gRPC calls succeed, we need a custom Grape format to handle
+ # this:
+ # 1. Grape will ordinarily call `JSON.dump` when Content-Type is set
+ # to application/json. To avoid this, we need to define a custom type in
+ # `content_type` and a custom formatter to go with it.
+ # 2. Grape will parse the request input with the parser defined for
+ # `content_type`. If no such parser exists, it will be treated as text. We
+ # reuse the existing JSON parser to preserve the previous behavior.
+ content_type :build_json, 'application/json'
+ formatter :build_json, ->(object, _) { object }
+ parser :build_json, ::Grape::Parser::Json
+
post '/request' do
authenticate_runner!
@@ -128,9 +142,10 @@ module API
result = ::Ci::RegisterJobService.new(current_runner).execute(runner_params)
if result.valid?
- if result.build
+ if result.build_json
Gitlab::Metrics.add_event(:build_found)
- present ::Ci::BuildRunnerPresenter.new(result.build), with: Entities::JobRequest::Response
+ env['api.format'] = :build_json
+ body result.build_json
else
Gitlab::Metrics.add_event(:build_not_found)
header 'X-GitLab-Last-Update', new_update
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index f19ad07a192..cfb37fb12a4 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5054,6 +5054,9 @@ msgstr ""
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters."
msgstr ""
+msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
+msgstr ""
+
msgid "ClusterIntegration|Copy API URL"
msgstr ""
diff --git a/spec/frontend/clusters_list/components/ancestor_notice_spec.js b/spec/frontend/clusters_list/components/ancestor_notice_spec.js
new file mode 100644
index 00000000000..c931912eaf9
--- /dev/null
+++ b/spec/frontend/clusters_list/components/ancestor_notice_spec.js
@@ -0,0 +1,51 @@
+import AncestorNotice from '~/clusters_list/components/ancestor_notice.vue';
+import ClusterStore from '~/clusters_list/store';
+import { shallowMount } from '@vue/test-utils';
+import { GlLink, GlSprintf } from '@gitlab/ui';
+
+describe('ClustersAncestorNotice', () => {
+ let store;
+ let wrapper;
+
+ const createWrapper = () => {
+ store = ClusterStore({ ancestorHelperPath: '/some/ancestor/path' });
+ wrapper = shallowMount(AncestorNotice, { store, stubs: { GlSprintf } });
+ return wrapper.vm.$nextTick();
+ };
+
+ beforeEach(() => {
+ return createWrapper();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('when cluster does not have ancestors', () => {
+ beforeEach(() => {
+ store.state.hasAncestorClusters = false;
+ return wrapper.vm.$nextTick();
+ });
+
+ it('displays no notice', () => {
+ expect(wrapper.isEmpty()).toBe(true);
+ });
+ });
+
+ describe('when cluster has ancestors', () => {
+ beforeEach(() => {
+ store.state.hasAncestorClusters = true;
+ return wrapper.vm.$nextTick();
+ });
+
+ it('displays notice text', () => {
+ expect(wrapper.text()).toContain(
+ 'Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters.',
+ );
+ });
+
+ it('displays link', () => {
+ expect(wrapper.contains(GlLink)).toBe(true);
+ });
+ });
+});
diff --git a/spec/graphql/types/jira_user_type_spec.rb b/spec/graphql/types/jira_user_type_spec.rb
new file mode 100644
index 00000000000..6e55efb42f4
--- /dev/null
+++ b/spec/graphql/types/jira_user_type_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['JiraUser'] do
+ specify { expect(described_class.graphql_name).to eq('JiraUser') }
+
+ it 'has the expected fields' do
+ expect(described_class).to have_graphql_fields(
+ :jira_account_id, :jira_display_name, :jira_email, :gitlab_id, :gitlab_username, :gitlab_name
+ )
+ end
+end
diff --git a/spec/helpers/clusters_helper_spec.rb b/spec/helpers/clusters_helper_spec.rb
index cebf6235f44..8ad955b61f1 100644
--- a/spec/helpers/clusters_helper_spec.rb
+++ b/spec/helpers/clusters_helper_spec.rb
@@ -60,18 +60,24 @@ RSpec.describe ClustersHelper do
end
describe '#js_clusters_list_data' do
- it 'displays endpoint path and images' do
- js_data = helper.js_clusters_list_data('/path')
+ subject { helper.js_clusters_list_data('/path') }
- expect(js_data[:endpoint]).to eq('/path')
+ it 'displays endpoint path' do
+ expect(subject[:endpoint]).to eq('/path')
+ end
+
+ it 'generates svg image data', :aggregate_failures do
+ expect(subject.dig(:img_tags, :aws, :path)).to match(%r(/illustrations/logos/amazon_eks|svg))
+ expect(subject.dig(:img_tags, :default, :path)).to match(%r(/illustrations/logos/kubernetes|svg))
+ expect(subject.dig(:img_tags, :gcp, :path)).to match(%r(/illustrations/logos/google_gke|svg))
- expect(js_data.dig(:img_tags, :aws, :path)).to match(%r(/illustrations/logos/amazon_eks|svg))
- expect(js_data.dig(:img_tags, :default, :path)).to match(%r(/illustrations/logos/kubernetes|svg))
- expect(js_data.dig(:img_tags, :gcp, :path)).to match(%r(/illustrations/logos/google_gke|svg))
+ expect(subject.dig(:img_tags, :aws, :text)).to eq('Amazon EKS')
+ expect(subject.dig(:img_tags, :default, :text)).to eq('Kubernetes Cluster')
+ expect(subject.dig(:img_tags, :gcp, :text)).to eq('Google GKE')
+ end
- expect(js_data.dig(:img_tags, :aws, :text)).to eq('Amazon EKS')
- expect(js_data.dig(:img_tags, :default, :text)).to eq('Kubernetes Cluster')
- expect(js_data.dig(:img_tags, :gcp, :text)).to eq('Google GKE')
+ it 'displays and ancestor_help_path' do
+ expect(subject[:ancestor_help_path]).to eq('/help/user/group/clusters/index#cluster-precedence')
end
end
diff --git a/spec/requests/api/ci/runner_spec.rb b/spec/requests/api/ci/runner_spec.rb
index 20bd59c5c72..8106b7195c8 100644
--- a/spec/requests/api/ci/runner_spec.rb
+++ b/spec/requests/api/ci/runner_spec.rb
@@ -518,6 +518,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
request_job info: { platform: :darwin }
expect(response).to have_gitlab_http_status(:created)
+ expect(response.headers['Content-Type']).to eq('application/json')
expect(response.headers).not_to have_key('X-GitLab-Last-Update')
expect(runner.reload.platform).to eq('darwin')
expect(json_response['id']).to eq(job.id)
@@ -569,6 +570,24 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
end
+ context 'when a Gitaly exception is thrown during response' do
+ before do
+ allow_next_instance_of(Ci::BuildRunnerPresenter) do |instance|
+ allow(instance).to receive(:artifacts).and_raise(GRPC::DeadlineExceeded)
+ end
+ end
+
+ it 'fails the job as a scheduler failure' do
+ request_job
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ expect(job.reload.failed?).to be_truthy
+ expect(job.failure_reason).to eq('scheduler_failure')
+ expect(job.runner_id).to eq(runner.id)
+ expect(job.runner_session).to be_nil
+ end
+ end
+
context 'when GIT_DEPTH is not specified and there is no default git depth for the project' do
before do
project.update!(ci_default_git_depth: nil)
@@ -1090,7 +1109,7 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
def request_job(token = runner.token, **params)
new_params = params.merge(token: token, last_update: last_update)
- post api('/jobs/request'), params: new_params, headers: { 'User-Agent' => user_agent }
+ post api('/jobs/request'), params: new_params.to_json, headers: { 'User-Agent' => user_agent, 'Content-Type': 'application/json' }
end
end
diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb
index de4db4f144c..921f5ba4c7e 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -109,12 +109,14 @@ module Ci
end
context 'shared runner' do
- let(:build) { execute(shared_runner) }
+ let(:response) { described_class.new(shared_runner).execute }
+ let(:build) { response.build }
it { expect(build).to be_kind_of(Build) }
it { expect(build).to be_valid }
it { expect(build).to be_running }
it { expect(build.runner).to eq(shared_runner) }
+ it { expect(Gitlab::Json.parse(response.build_json)['id']).to eq(build.id) }
end
context 'specific runner' do
diff --git a/spec/services/jira_import/users_mapper_spec.rb b/spec/services/jira_import/users_mapper_spec.rb
index 0fa98736b51..e5e8279a6fb 100644
--- a/spec/services/jira_import/users_mapper_spec.rb
+++ b/spec/services/jira_import/users_mapper_spec.rb
@@ -29,9 +29,9 @@ RSpec.describe JiraImport::UsersMapper do
# mapping is tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/219023
let(:mapped_users) do
[
- { jira_account_id: 'abcd', jira_display_name: 'user1', jira_email: nil, gitlab_id: nil },
- { jira_account_id: 'efg', jira_display_name: nil, jira_email: nil, gitlab_id: nil },
- { jira_account_id: 'hij', jira_display_name: 'user3', jira_email: 'user3@example.com', gitlab_id: nil }
+ { jira_account_id: 'abcd', jira_display_name: 'user1', jira_email: nil, gitlab_id: nil, gitlab_username: nil, gitlab_name: nil },
+ { jira_account_id: 'efg', jira_display_name: nil, jira_email: nil, gitlab_id: nil, gitlab_username: nil, gitlab_name: nil },
+ { jira_account_id: 'hij', jira_display_name: 'user3', jira_email: 'user3@example.com', gitlab_id: nil, gitlab_username: nil, gitlab_name: nil }
]
end