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--Gemfile4
-rw-r--r--Gemfile.lock29
-rw-r--r--app/assets/javascripts/diffs/utils/uuids.js79
-rw-r--r--app/assets/javascripts/monitoring/components/links_section.vue16
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js3
-rw-r--r--app/assets/javascripts/monitoring/stores/mutations.js10
-rw-r--r--app/assets/javascripts/monitoring/stores/utils.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue43
-rw-r--r--app/assets/stylesheets/pages/prometheus.scss8
-rw-r--r--app/controllers/concerns/service_params.rb2
-rw-r--r--app/graphql/mutations/metrics/dashboard/annotations/base.rb18
-rw-r--r--app/graphql/mutations/metrics/dashboard/annotations/delete.rb32
-rw-r--r--app/graphql/types/mutation_type.rb1
-rw-r--r--app/models/design_management/design.rb7
-rw-r--r--app/models/project_services/prometheus_service.rb42
-rw-r--r--app/presenters/projects/prometheus/alert_presenter.rb8
-rw-r--r--app/services/design_management/delete_designs_service.rb5
-rw-r--r--app/services/design_management/save_designs_service.rb17
-rw-r--r--app/services/event_create_service.rb64
-rw-r--r--changelogs/unreleased/11805-support-first-name-and-last-name-attributes-in-ldap-user-sync.yml5
-rw-r--r--changelogs/unreleased/211461-destroy-annotations-graphql-endpoint.yml5
-rw-r--r--changelogs/unreleased/214109-date-time-format-should-be-consistent-in-the-incident.yml5
-rw-r--r--changelogs/unreleased/216385-add-related-dashboard-links-in-metrics-dashboard-mvc1.yml5
-rw-r--r--changelogs/unreleased/217748-pipeline-index-endpoint-performance.yml5
-rw-r--r--changelogs/unreleased/217985-use-glinfinitescroll-s-default-slot-in-the-project-selector-vue-co.yml5
-rw-r--r--changelogs/unreleased/ak-update-google-auth.yml5
-rw-r--r--changelogs/unreleased/dennis-project-templates-add-gitbook-logo.yml5
-rw-r--r--changelogs/unreleased/dennis-project-templates-add-hugo-logo.yml5
-rw-r--r--config/dependency_decisions.yml6
-rw-r--r--config/initializers/google_api_client.rb19
-rw-r--r--db/migrate/20200528125905_add_project_id_user_id_status_ref_index_to_ci_pipelines.rb27
-rw-r--r--db/structure.sql3
-rw-r--r--doc/.vale/gitlab/Acronyms.yml3
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt1
-rw-r--r--doc/administration/high_availability/nfs.md2
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md2
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md78
-rw-r--r--doc/administration/monitoring/prometheus/node_exporter.md25
-rw-r--r--doc/administration/monitoring/prometheus/pgbouncer_exporter.md29
-rw-r--r--doc/administration/monitoring/prometheus/postgres_exporter.md72
-rw-r--r--doc/administration/monitoring/prometheus/redis_exporter.md23
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql31
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json115
-rw-r--r--doc/api/graphql/reference/index.md9
-rw-r--r--doc/api/services.md2
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md2
-rw-r--r--doc/ci/jenkins/index.md2
-rw-r--r--doc/ci/yaml/README.md2
-rw-r--r--doc/development/application_limits.md2
-rw-r--r--doc/development/architecture.md2
-rw-r--r--doc/development/code_review.md2
-rw-r--r--doc/development/documentation/styleguide.md2
-rw-r--r--doc/development/documentation/workflow.md2
-rw-r--r--doc/development/fe_guide/dependencies.md2
-rw-r--r--doc/development/fe_guide/graphql.md6
-rw-r--r--doc/development/i18n/externalization.md2
-rw-r--r--doc/development/integrations/jenkins.md2
-rw-r--r--doc/development/multi_version_compatibility.md2
-rw-r--r--doc/development/new_fe_guide/development/performance.md2
-rw-r--r--doc/development/secure_coding_guidelines.md2
-rw-r--r--doc/development/testing_guide/index.md2
-rw-r--r--doc/development/testing_guide/review_apps.md2
-rw-r--r--doc/gitlab-basics/start-using-git.md2
-rw-r--r--doc/install/azure/index.md2
-rw-r--r--doc/install/requirements.md4
-rw-r--r--doc/integration/vault.md2
-rw-r--r--doc/ssh/README.md4
-rw-r--r--doc/topics/authentication/index.md2
-rw-r--r--doc/topics/autodevops/stages.md2
-rw-r--r--doc/topics/web_application_firewall/index.md4
-rw-r--r--doc/topics/web_application_firewall/quick_start_guide.md2
-rw-r--r--doc/university/README.md3
-rw-r--r--doc/university/support/README.md2
-rw-r--r--doc/user/clusters/applications.md10
-rw-r--r--doc/user/compliance/license_compliance/index.md4
-rw-r--r--doc/user/group/saml_sso/index.md2
-rw-r--r--doc/user/group/saml_sso/scim_setup.md2
-rw-r--r--doc/user/markdown.md2
-rw-r--r--doc/user/project/clusters/serverless/aws.md4
-rw-r--r--doc/user/project/import/tfvc.md2
-rw-r--r--doc/user/project/integrations/gitlab_slack_application.md2
-rw-r--r--doc/user/project/integrations/jira_cloud_configuration.md2
-rw-r--r--doc/user/project/integrations/prometheus.md2
-rw-r--r--doc/user/project/issues/design_management.md4
-rw-r--r--lib/api/helpers/services_helpers.rb12
-rw-r--r--lib/gitlab/alerting/alert.rb5
-rw-r--r--lib/gitlab/auth/ldap/person.rb2
-rw-r--r--lib/gitlab/project_template.rb4
-rw-r--r--locale/gitlab.pot14
-rw-r--r--package.json3
-rw-r--r--spec/frontend/diffs/utils/uuids_spec.js92
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js17
-rw-r--r--spec/frontend/monitoring/store/utils_spec.js6
-rw-r--r--spec/frontend/monitoring/store_utils.js12
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_selector_spec.js22
-rw-r--r--spec/initializers/google_api_client_spec.rb17
-rw-r--r--spec/lib/gitlab/auth/ldap/person_spec.rb7
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/models/project_services/prometheus_service_spec.rb44
-rw-r--r--spec/presenters/projects/prometheus/alert_presenter_spec.rb35
-rw-r--r--spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb80
-rw-r--r--spec/services/design_management/delete_designs_service_spec.rb26
-rw-r--r--spec/services/design_management/save_designs_service_spec.rb25
-rw-r--r--spec/services/event_create_service_spec.rb91
-rw-r--r--yarn.lock15
105 files changed, 1227 insertions, 296 deletions
diff --git a/Gemfile b/Gemfile
index 7d63a5f50c0..8137b66c283 100644
--- a/Gemfile
+++ b/Gemfile
@@ -112,14 +112,14 @@ gem 'fog-aws', '~> 3.5'
# Locked until fog-google resolves https://github.com/fog/fog-google/issues/421.
# Also see config/initializers/fog_core_patch.rb.
gem 'fog-core', '= 2.1.0'
-gem 'fog-google', '~> 1.9'
+gem 'fog-google', '~> 1.10'
gem 'fog-local', '~> 0.6'
gem 'fog-openstack', '~> 1.0'
gem 'fog-rackspace', '~> 0.1.1'
gem 'fog-aliyun', '~> 0.3'
# for Google storage
-gem 'google-api-client', '~> 0.23'
+gem 'google-api-client', '~> 0.33'
# for aws storage
gem 'unf', '~> 0.1.4'
diff --git a/Gemfile.lock b/Gemfile.lock
index 31ff0fb304c..49a0113f510 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -286,7 +286,7 @@ GEM
factory_bot_rails (5.1.0)
factory_bot (~> 5.1.0)
railties (>= 4.2.0)
- faraday (0.15.4)
+ faraday (0.17.3)
multipart-post (>= 1.2, < 3)
faraday-http-cache (2.0.0)
faraday (~> 0.8)
@@ -330,11 +330,11 @@ GEM
excon (~> 0.58)
formatador (~> 0.2)
mime-types
- fog-google (1.9.1)
+ fog-google (1.10.0)
fog-core (<= 2.1.0)
fog-json (~> 1.2)
fog-xml (~> 0.1.0)
- google-api-client (~> 0.23.0)
+ google-api-client (>= 0.32, < 0.34)
fog-json (1.2.0)
fog-core
multi_json (~> 1.10)
@@ -419,23 +419,24 @@ GEM
actionpack (>= 3.0)
multi_json
request_store (>= 1.0)
- google-api-client (0.23.4)
+ google-api-client (0.33.2)
addressable (~> 2.5, >= 2.5.1)
- googleauth (>= 0.5, < 0.7.0)
+ googleauth (~> 0.9)
httpclient (>= 2.8.1, < 3.0)
- mime-types (~> 3.0)
+ mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
+ signet (~> 0.12)
google-protobuf (3.8.0)
googleapis-common-protos-types (1.0.4)
google-protobuf (~> 3.0)
- googleauth (0.6.6)
- faraday (~> 0.12)
+ googleauth (0.12.0)
+ faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
- memoist (~> 0.12)
+ memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
- signet (~> 0.7)
+ signet (~> 0.14)
gpgme (2.0.20)
mini_portile2 (~> 2.3)
grape (1.1.0)
@@ -1010,9 +1011,9 @@ GEM
sidekiq-cron (1.0.4)
fugit (~> 1.1)
sidekiq (>= 4.2.1)
- signet (0.11.0)
+ signet (0.14.0)
addressable (~> 2.3)
- faraday (~> 0.9)
+ faraday (>= 0.17.3, < 2.0)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simple_po_parser (1.1.2)
@@ -1224,7 +1225,7 @@ DEPENDENCIES
fog-aliyun (~> 0.3)
fog-aws (~> 3.5)
fog-core (= 2.1.0)
- fog-google (~> 1.9)
+ fog-google (~> 1.10)
fog-local (~> 0.6)
fog-openstack (~> 1.0)
fog-rackspace (~> 0.1.1)
@@ -1250,7 +1251,7 @@ DEPENDENCIES
gitlab_chronic_duration (~> 0.10.6.2)
gitlab_omniauth-ldap (~> 2.1.1)
gon (~> 6.2)
- google-api-client (~> 0.23)
+ google-api-client (~> 0.33)
google-protobuf (~> 3.8.0)
gpgme (~> 2.0.19)
grape (~> 1.1.0)
diff --git a/app/assets/javascripts/diffs/utils/uuids.js b/app/assets/javascripts/diffs/utils/uuids.js
new file mode 100644
index 00000000000..1a529c07ccc
--- /dev/null
+++ b/app/assets/javascripts/diffs/utils/uuids.js
@@ -0,0 +1,79 @@
+/**
+ * @module uuids
+ */
+
+/**
+ * A string or number representing a start state for a random generator
+ * @typedef {(Number|String)} Seed
+ */
+/**
+ * A UUIDv4 string in the format <code>Hex{8}-Hex{4}-4Hex{3}-[89ab]Hex{3}-Hex{12}</code>
+ * @typedef {String} UUIDv4
+ */
+
+// https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20
+/* eslint-disable import/prefer-default-export */
+
+import MersenneTwister from 'mersenne-twister';
+import stringHash from 'string-hash';
+import { isString } from 'lodash';
+import { v4 } from 'uuid';
+
+function getSeed(seeds) {
+ return seeds.reduce((seedling, seed, i) => {
+ let thisSeed = 0;
+
+ if (Number.isInteger(seed)) {
+ thisSeed = seed;
+ } else if (isString(seed)) {
+ thisSeed = stringHash(seed);
+ }
+
+ return seedling + (seeds.length - i) * thisSeed;
+ }, 0);
+}
+
+function getPseudoRandomNumberGenerator(...seeds) {
+ let seedNumber;
+
+ if (seeds.length) {
+ seedNumber = getSeed(seeds);
+ } else {
+ seedNumber = Math.floor(Math.random() * 10 ** 15);
+ }
+
+ return new MersenneTwister(seedNumber);
+}
+
+function randomValuesForUuid(prng) {
+ const randomValues = [];
+
+ for (let i = 0; i <= 3; i += 1) {
+ const buffer = new ArrayBuffer(4);
+ const view = new DataView(buffer);
+
+ view.setUint32(0, prng.random_int());
+
+ randomValues.push(view.getUint8(0), view.getUint8(1), view.getUint8(2), view.getUint8(3));
+ }
+
+ return randomValues;
+}
+
+/**
+ * Get an array of UUIDv4s
+ * @param {Object} [options={}]
+ * @param {Seed[]} [options.seeds=[]] - A list of mixed strings or numbers to seed the UUIDv4 generator
+ * @param {Number} [options.count=1] - A total number of UUIDv4s to generate
+ * @returns {UUIDv4[]} An array of UUIDv4s
+ */
+export function uuids({ seeds = [], count = 1 } = {}) {
+ const rng = getPseudoRandomNumberGenerator(...seeds);
+ return (
+ // Create an array the same size as the number of UUIDs requested
+ Array(count)
+ .fill(0)
+ // Replace each slot in the array with a UUID which needs 16 (pseudo)random values to generate
+ .map(() => v4({ random: randomValuesForUuid(rng) }))
+ );
+}
diff --git a/app/assets/javascripts/monitoring/components/links_section.vue b/app/assets/javascripts/monitoring/components/links_section.vue
index 6ea650071a0..2de3a40e157 100644
--- a/app/assets/javascripts/monitoring/components/links_section.vue
+++ b/app/assets/javascripts/monitoring/components/links_section.vue
@@ -1,10 +1,4 @@
<script>
-/**
- * This component generates user-defined links in the
- * dashboard yml file. However, this component will be
- * used in the metrics dashboard after
- * https://gitlab.com/gitlab-org/gitlab/-/merge_requests/32895
- */
import { mapState } from 'vuex';
import { GlIcon, GlLink } from '@gitlab/ui';
@@ -21,15 +15,17 @@ export default {
<template>
<div
ref="linksSection"
- class="d-sm-flex flex-sm-wrap gl-mt-3 gl-p-2 bg-gray-light border border-radius-default"
+ class="gl-display-sm-flex gl-flex-sm-wrap gl-mt-5 gl-p-3 gl-bg-gray-10 border gl-rounded-base links-section"
>
<div
v-for="(link, key) in links"
:key="key"
- class="gl-mb-1 gl-pr-3 d-flex d-sm-block text-break-word"
+ class="gl-mb-1 gl-mr-5 gl-display-flex gl-display-sm-block gl-hover-text-blue-600-children gl-word-break-all"
>
- <gl-link :href="link.url" class="text-plain text-decoration-none"
- ><gl-icon name="link" class="align-text-bottom mr-1" />{{ link.title }}
+ <gl-link :href="link.url" class="gl-text-gray-900 gl-text-decoration-none!"
+ ><gl-icon name="link" class="gl-text-gray-700 gl-vertical-align-text-bottom gl-mr-2" />{{
+ link.title
+ }}
</gl-link>
</div>
</div>
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index a9b8b1db922..f740bc515a7 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -3,8 +3,6 @@ import * as types from './mutation_types';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
-import { parseTemplatingVariables } from './variable_mapping';
-import { mergeURLVariables } from '../utils';
import {
gqClient,
parseEnvironmentsResponse,
@@ -161,7 +159,6 @@ export const receiveMetricsDashboardSuccess = ({ commit, dispatch }, { response
commit(types.SET_ALL_DASHBOARDS, all_dashboards);
commit(types.RECEIVE_METRICS_DASHBOARD_SUCCESS, dashboard);
- commit(types.SET_VARIABLES, mergeURLVariables(parseTemplatingVariables(dashboard.templating)));
commit(types.SET_ENDPOINTS, convertObjectPropsToCamelCase(metrics_data));
return dispatch('fetchDashboardData');
diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js
index 92151a8c40e..688880e04c3 100644
--- a/app/assets/javascripts/monitoring/stores/mutations.js
+++ b/app/assets/javascripts/monitoring/stores/mutations.js
@@ -61,8 +61,14 @@ export default {
state.emptyState = 'loading';
state.showEmptyState = true;
},
- [types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, dashboard) {
- state.dashboard = mapToDashboardViewModel(dashboard);
+ [types.RECEIVE_METRICS_DASHBOARD_SUCCESS](state, dashboardYML) {
+ const { dashboard, panelGroups, variables, links } = mapToDashboardViewModel(dashboardYML);
+ state.dashboard = {
+ dashboard,
+ panelGroups,
+ };
+ state.variables = variables;
+ state.links = links;
if (!state.dashboard.panelGroups.length) {
state.emptyState = 'noData';
diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js
index 060b2e7013e..64cedf8e8f5 100644
--- a/app/assets/javascripts/monitoring/stores/utils.js
+++ b/app/assets/javascripts/monitoring/stores/utils.js
@@ -2,6 +2,7 @@ import { slugify } from '~/lib/utils/text_utility';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
import { SUPPORTED_FORMATS } from '~/lib/utils/unit_format';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { parseTemplatingVariables } from './variable_mapping';
import { NOT_IN_DB_PREFIX } from '../constants';
import { isSafeURL } from '~/lib/utils/url_utility';
@@ -217,9 +218,16 @@ const mapToPanelGroupViewModel = ({ group = '', panels = [] }, i) => {
* @param {Array} dashboard.panel_groups - Panel groups array
* @returns {Object}
*/
-export const mapToDashboardViewModel = ({ dashboard = '', panel_groups = [] }) => {
+export const mapToDashboardViewModel = ({
+ dashboard = '',
+ templating = {},
+ links = [],
+ panel_groups = [],
+}) => {
return {
dashboard,
+ variables: parseTemplatingVariables(templating),
+ links: links.map(mapLinksToViewModel),
panelGroups: panel_groups.map(mapToPanelGroupViewModel),
};
};
diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
index 6f3f2aa0e8e..15a5ce85046 100644
--- a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
+++ b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
@@ -1,6 +1,7 @@
<script>
import { debounce } from 'lodash';
import { GlLoadingIcon, GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui';
+import { __, n__, sprintf } from '~/locale';
import ProjectListItem from './project_list_item.vue';
const SEARCH_INPUT_TIMEOUT_MS = 500;
@@ -48,6 +49,20 @@ export default {
searchQuery: '',
};
},
+ computed: {
+ legendText() {
+ const count = this.projectSearchResults.length;
+ const total = this.totalResults;
+
+ if (total > 0) {
+ return sprintf(__('Showing %{count} of %{total} projects'), { count, total });
+ }
+
+ return sprintf(n__('Showing %{count} project', 'Showing %{count} projects', count), {
+ count,
+ });
+ },
+ },
methods: {
projectClicked(project) {
this.$emit('projectClicked', project);
@@ -82,17 +97,23 @@ export default {
:total-items="totalResults"
@bottomReached="bottomReached"
>
- <div v-if="!showLoadingIndicator" slot="items" class="d-flex flex-column">
- <project-list-item
- v-for="project in projectSearchResults"
- :key="project.id"
- :selected="isSelected(project)"
- :project="project"
- :matcher="searchQuery"
- class="js-project-list-item"
- @click="projectClicked(project)"
- />
- </div>
+ <template v-if="!showLoadingIndicator" #items>
+ <div class="d-flex flex-column">
+ <project-list-item
+ v-for="project in projectSearchResults"
+ :key="project.id"
+ :selected="isSelected(project)"
+ :project="project"
+ :matcher="searchQuery"
+ class="js-project-list-item"
+ @click="projectClicked(project)"
+ />
+ </div>
+ </template>
+
+ <template #default>
+ {{ legendText }}
+ </template>
</gl-infinite-scroll>
<div v-if="showNoResultsMessage" class="text-muted ml-2 js-no-results-message">
{{ __('Sorry, no projects matched your search') }}
diff --git a/app/assets/stylesheets/pages/prometheus.scss b/app/assets/stylesheets/pages/prometheus.scss
index 0f56b98a78d..26db1fb9f58 100644
--- a/app/assets/stylesheets/pages/prometheus.scss
+++ b/app/assets/stylesheets/pages/prometheus.scss
@@ -21,6 +21,14 @@
}
}
}
+
+ .links-section {
+ .gl-hover-text-blue-600-children:hover {
+ * {
+ @include gl-text-blue-600;
+ }
+ }
+ }
}
.draggable {
diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb
index e2c83f9a069..66e01ac5250 100644
--- a/app/controllers/concerns/service_params.rb
+++ b/app/controllers/concerns/service_params.rb
@@ -28,6 +28,8 @@ module ServiceParams
:drone_url,
:enable_ssl_verification,
:external_wiki_url,
+ :google_iap_service_account_json,
+ :google_iap_audience_client_id,
# We're using `issues_events` and `merge_requests_events`
# in the view so we still need to explicitly state them
# here. `Service#event_names` would only give
diff --git a/app/graphql/mutations/metrics/dashboard/annotations/base.rb b/app/graphql/mutations/metrics/dashboard/annotations/base.rb
new file mode 100644
index 00000000000..3126267da64
--- /dev/null
+++ b/app/graphql/mutations/metrics/dashboard/annotations/base.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Metrics
+ module Dashboard
+ module Annotations
+ class Base < BaseMutation
+ private
+
+ # This method is defined here in order to be used by `authorized_find!` in the subclasses.
+ def find_object(id:)
+ GitlabSchema.object_from_id(id)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/mutations/metrics/dashboard/annotations/delete.rb b/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
new file mode 100644
index 00000000000..fb828ba0e2f
--- /dev/null
+++ b/app/graphql/mutations/metrics/dashboard/annotations/delete.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Mutations
+ module Metrics
+ module Dashboard
+ module Annotations
+ class Delete < Base
+ graphql_name 'DeleteAnnotation'
+
+ authorize :delete_metrics_dashboard_annotation
+
+ argument :id,
+ GraphQL::ID_TYPE,
+ required: true,
+ description: 'The global id of the annotation to delete'
+
+ def resolve(id:)
+ annotation = authorized_find!(id: id)
+
+ result = ::Metrics::Dashboard::Annotations::DeleteService.new(context[:current_user], annotation).execute
+
+ errors = Array.wrap(result[:message])
+
+ {
+ errors: errors
+ }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index a983231c78a..a1dee351475 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -26,6 +26,7 @@ module Types
mount_mutation Mutations::MergeRequests::SetWip, calls_gitaly: true
mount_mutation Mutations::MergeRequests::SetAssignees
mount_mutation Mutations::Metrics::Dashboard::Annotations::Create
+ mount_mutation Mutations::Metrics::Dashboard::Annotations::Delete
mount_mutation Mutations::Notes::Create::Note, calls_gitaly: true
mount_mutation Mutations::Notes::Create::DiffNote, calls_gitaly: true
mount_mutation Mutations::Notes::Create::ImageDiffNote, calls_gitaly: true
diff --git a/app/models/design_management/design.rb b/app/models/design_management/design.rb
index 057bbab1c83..0dca6333fa1 100644
--- a/app/models/design_management/design.rb
+++ b/app/models/design_management/design.rb
@@ -20,6 +20,8 @@ module DesignManagement
has_many :notes, as: :noteable, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_many :user_mentions, class_name: 'DesignUserMention', dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
+ has_many :events, as: :target, dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
+
validates :project, :filename, presence: true
validates :issue, presence: true, unless: :importing?
validates :filename, uniqueness: { scope: :issue_id }, length: { maximum: 255 }
@@ -189,6 +191,11 @@ module DesignManagement
alias_method :after_note_created, :after_note_changed
alias_method :after_note_destroyed, :after_note_changed
+ # Part of the interface of objects we can create events about
+ def resource_parent
+ project
+ end
+
private
def head_version
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
index 4a28d1ff2b0..b3a4c8db02d 100644
--- a/app/models/project_services/prometheus_service.rb
+++ b/app/models/project_services/prometheus_service.rb
@@ -5,6 +5,8 @@ class PrometheusService < MonitoringService
# Access to prometheus is directly through the API
prop_accessor :api_url
+ prop_accessor :google_iap_service_account_json
+ prop_accessor :google_iap_audience_client_id
boolean_accessor :manual_configuration
# We need to allow the self-monitoring project to connect to the internal
@@ -49,7 +51,7 @@ class PrometheusService < MonitoringService
end
def fields
- [
+ result = [
{
type: 'checkbox',
name: 'manual_configuration',
@@ -64,6 +66,27 @@ class PrometheusService < MonitoringService
required: true
}
]
+
+ if Feature.enabled?(:prometheus_service_iap_auth)
+ result += [
+ {
+ type: 'text',
+ name: 'google_iap_audience_client_id',
+ title: 'Google IAP Audience Client ID',
+ placeholder: s_('PrometheusService|Client ID of the IAP secured resource (looks like IAP_CLIENT_ID.apps.googleusercontent.com)'),
+ required: false
+ },
+ {
+ type: 'textarea',
+ name: 'google_iap_service_account_json',
+ title: 'Google IAP Service Account JSON',
+ placeholder: s_('PrometheusService|Contents of the credentials.json file of your service account, like: { "type": "service_account", "project_id": ... }'),
+ required: false
+ }
+ ]
+ end
+
+ result
end
# Check we can connect to the Prometheus API
@@ -77,7 +100,14 @@ class PrometheusService < MonitoringService
def prometheus_client
return unless should_return_client?
- Gitlab::PrometheusClient.new(api_url, allow_local_requests: allow_local_api_url?)
+ options = { allow_local_requests: allow_local_api_url? }
+
+ if Feature.enabled?(:prometheus_service_iap_auth) && behind_iap?
+ # Adds the Authorization header
+ options[:headers] = iap_client.apply({})
+ end
+
+ Gitlab::PrometheusClient.new(api_url, options)
end
def prometheus_available?
@@ -149,4 +179,12 @@ class PrometheusService < MonitoringService
Prometheus::CreateDefaultAlertsWorker.perform_async(project_id)
end
+
+ def behind_iap?
+ manual_configuration? && google_iap_audience_client_id.present? && google_iap_service_account_json.present?
+ end
+
+ def iap_client
+ @iap_client ||= Google::Auth::Credentials.new(Gitlab::Json.parse(google_iap_service_account_json), target_audience: google_iap_audience_client_id).client
+ end
end
diff --git a/app/presenters/projects/prometheus/alert_presenter.rb b/app/presenters/projects/prometheus/alert_presenter.rb
index 2114e06a8c5..6009ee4c7be 100644
--- a/app/presenters/projects/prometheus/alert_presenter.rb
+++ b/app/presenters/projects/prometheus/alert_presenter.rb
@@ -45,8 +45,8 @@ module Projects
project_issues_url(project, label_name: INCIDENT_LABEL_NAME)
end
- def starts_at
- super&.rfc3339
+ def start_time
+ starts_at&.strftime('%d %B %Y, %-l:%M%p (%Z)')
end
def issue_summary_markdown
@@ -73,7 +73,7 @@ module Projects
def metadata_list
metadata = []
- metadata << list_item('Start time', starts_at) if starts_at
+ metadata << list_item('Start time', start_time) if start_time
metadata << list_item('full_query', backtick(full_query)) if full_query
metadata << list_item(service.label.humanize, service.value) if service
metadata << list_item(monitoring_tool.label.humanize, monitoring_tool.value) if monitoring_tool
@@ -149,7 +149,7 @@ module Projects
end
def embed_time
- starts_at ? Time.rfc3339(starts_at) : Time.current
+ starts_at || Time.current
end
def alert_embed_window_params(time)
diff --git a/app/services/design_management/delete_designs_service.rb b/app/services/design_management/delete_designs_service.rb
index e69f07db5bf..5d875c630a0 100644
--- a/app/services/design_management/delete_designs_service.rb
+++ b/app/services/design_management/delete_designs_service.rb
@@ -15,6 +15,7 @@ module DesignManagement
return error('Forbidden!') unless can_delete_designs?
version = delete_designs!
+ EventCreateService.new.destroy_designs(designs, current_user)
success(version: version)
end
@@ -48,7 +49,9 @@ module DesignManagement
end
def design_action(design)
- on_success { counter.count(:delete) }
+ on_success do
+ counter.count(:delete)
+ end
DesignManagement::DesignAction.new(design, :delete)
end
diff --git a/app/services/design_management/save_designs_service.rb b/app/services/design_management/save_designs_service.rb
index a09c19bc885..0446d2f1ee8 100644
--- a/app/services/design_management/save_designs_service.rb
+++ b/app/services/design_management/save_designs_service.rb
@@ -20,6 +20,7 @@ module DesignManagement
uploaded_designs, version = upload_designs!
skipped_designs = designs - uploaded_designs
+ create_events
success({ designs: uploaded_designs, version: version, skipped_designs: skipped_designs })
rescue ::ActiveRecord::RecordInvalid => e
error(e.message)
@@ -47,7 +48,7 @@ module DesignManagement
end
def build_actions
- files.zip(designs).flat_map do |(file, design)|
+ @actions ||= files.zip(designs).flat_map do |(file, design)|
Array.wrap(build_design_action(file, design))
end
end
@@ -57,7 +58,9 @@ module DesignManagement
return if design_unchanged?(design, content)
action = new_file?(design) ? :create : :update
- on_success { ::Gitlab::UsageDataCounters::DesignsCounter.count(action) }
+ on_success do
+ ::Gitlab::UsageDataCounters::DesignsCounter.count(action)
+ end
DesignManagement::DesignAction.new(design, action, content)
end
@@ -67,6 +70,16 @@ module DesignManagement
content == existing_blobs[design]&.data
end
+ def create_events
+ by_action = @actions.group_by(&:action).transform_values { |grp| grp.map(&:design) }
+
+ event_create_service.save_designs(current_user, **by_action)
+ end
+
+ def event_create_service
+ @event_create_service ||= EventCreateService.new
+ end
+
def commit_message
<<~MSG
Updated #{files.size} #{'designs'.pluralize(files.size)}
diff --git a/app/services/event_create_service.rb b/app/services/event_create_service.rb
index 1fb87ca2a98..89c3225dbcd 100644
--- a/app/services/event_create_service.rb
+++ b/app/services/event_create_service.rb
@@ -96,6 +96,29 @@ class EventCreateService
create_push_event(BulkPushEventPayloadService, project, current_user, push_data)
end
+ def save_designs(current_user, create: [], update: [])
+ created = create.group_by(&:project).flat_map do |project, designs|
+ Feature.enabled?(:design_activity_events, project) ? designs : []
+ end.to_set
+ updated = update.group_by(&:project).flat_map do |project, designs|
+ Feature.enabled?(:design_activity_events, project) ? designs : []
+ end.to_set
+ return [] if created.empty? && updated.empty?
+
+ records = created.zip([:created].cycle) + updated.zip([:updated].cycle)
+
+ create_record_events(records, current_user)
+ end
+
+ def destroy_designs(designs, current_user)
+ designs = designs.select do |design|
+ Feature.enabled?(:design_activity_events, design.project)
+ end
+ return [] unless designs.present?
+
+ create_record_events(designs.zip([:destroyed].cycle), current_user)
+ end
+
# Create a new wiki page event
#
# @param [WikiPage::Meta] wiki_page_meta The event target
@@ -134,7 +157,32 @@ class EventCreateService
end
def create_record_event(record, current_user, status)
- create_event(record.resource_parent, current_user, status, target_id: record.id, target_type: record.class.name)
+ create_event(record.resource_parent, current_user, status,
+ target_id: record.id, target_type: record.class.name)
+ end
+
+ # If creating several events, this method will insert them all in a single
+ # statement
+ #
+ # @param [[Eventable, Symbol]] a list of pairs of records and a valid status
+ # @param [User] the author of the event
+ def create_record_events(pairs, current_user)
+ base_attrs = {
+ created_at: Time.now.utc,
+ updated_at: Time.now.utc,
+ author_id: current_user.id
+ }
+
+ attribute_sets = pairs.map do |record, status|
+ action = Event.actions[status]
+ raise IllegalActionError, "#{status} is not a valid status" if action.nil?
+
+ parent_attrs(record.resource_parent)
+ .merge(base_attrs)
+ .merge(action: action, target_id: record.id, target_type: record.class.name)
+ end
+
+ Event.insert_all(attribute_sets, returning: %w[id])
end
def create_push_event(service_class, project, current_user, push_data)
@@ -160,16 +208,22 @@ class EventCreateService
action: status,
author_id: current_user.id
)
+ attributes.merge!(parent_attrs(resource_parent))
+ Event.create!(attributes)
+ end
+
+ def parent_attrs(resource_parent)
resource_parent_attr = case resource_parent
when Project
- :project
+ :project_id
when Group
- :group
+ :group_id
end
- attributes[resource_parent_attr] = resource_parent if resource_parent_attr
- Event.create!(attributes)
+ return {} unless resource_parent_attr
+
+ { resource_parent_attr => resource_parent.id }
end
def create_resource_event(issuable, current_user, status)
diff --git a/changelogs/unreleased/11805-support-first-name-and-last-name-attributes-in-ldap-user-sync.yml b/changelogs/unreleased/11805-support-first-name-and-last-name-attributes-in-ldap-user-sync.yml
new file mode 100644
index 00000000000..4878eeb26e7
--- /dev/null
+++ b/changelogs/unreleased/11805-support-first-name-and-last-name-attributes-in-ldap-user-sync.yml
@@ -0,0 +1,5 @@
+---
+title: Support first_name and last_name attributes in LDAP user sync
+merge_request: 29542
+author:
+type: added
diff --git a/changelogs/unreleased/211461-destroy-annotations-graphql-endpoint.yml b/changelogs/unreleased/211461-destroy-annotations-graphql-endpoint.yml
new file mode 100644
index 00000000000..7e9edaad64b
--- /dev/null
+++ b/changelogs/unreleased/211461-destroy-annotations-graphql-endpoint.yml
@@ -0,0 +1,5 @@
+---
+title: Added delete action for Dashboard Annotations in GraphQL
+merge_request: 33468
+author:
+type: added
diff --git a/changelogs/unreleased/214109-date-time-format-should-be-consistent-in-the-incident.yml b/changelogs/unreleased/214109-date-time-format-should-be-consistent-in-the-incident.yml
new file mode 100644
index 00000000000..762c8dc1992
--- /dev/null
+++ b/changelogs/unreleased/214109-date-time-format-should-be-consistent-in-the-incident.yml
@@ -0,0 +1,5 @@
+---
+title: Add timezone display to alert based issue start time
+merge_request: 32702
+author:
+type: added
diff --git a/changelogs/unreleased/216385-add-related-dashboard-links-in-metrics-dashboard-mvc1.yml b/changelogs/unreleased/216385-add-related-dashboard-links-in-metrics-dashboard-mvc1.yml
new file mode 100644
index 00000000000..1d211732e04
--- /dev/null
+++ b/changelogs/unreleased/216385-add-related-dashboard-links-in-metrics-dashboard-mvc1.yml
@@ -0,0 +1,5 @@
+---
+title: Render user-defined links in dashboard yml file on metrics dashboard
+merge_request: 32895
+author:
+type: added
diff --git a/changelogs/unreleased/217748-pipeline-index-endpoint-performance.yml b/changelogs/unreleased/217748-pipeline-index-endpoint-performance.yml
new file mode 100644
index 00000000000..d9a68248010
--- /dev/null
+++ b/changelogs/unreleased/217748-pipeline-index-endpoint-performance.yml
@@ -0,0 +1,5 @@
+---
+title: Add project_id, user_id, status, ref index to ci_pipelines
+merge_request: 33290
+author:
+type: performance
diff --git a/changelogs/unreleased/217985-use-glinfinitescroll-s-default-slot-in-the-project-selector-vue-co.yml b/changelogs/unreleased/217985-use-glinfinitescroll-s-default-slot-in-the-project-selector-vue-co.yml
new file mode 100644
index 00000000000..2d06af04985
--- /dev/null
+++ b/changelogs/unreleased/217985-use-glinfinitescroll-s-default-slot-in-the-project-selector-vue-co.yml
@@ -0,0 +1,5 @@
+---
+title: Make project selector in various dashboard more translatable
+merge_request: 33771
+author:
+type: other
diff --git a/changelogs/unreleased/ak-update-google-auth.yml b/changelogs/unreleased/ak-update-google-auth.yml
new file mode 100644
index 00000000000..cb91b9ebe93
--- /dev/null
+++ b/changelogs/unreleased/ak-update-google-auth.yml
@@ -0,0 +1,5 @@
+---
+title: Support IAP protected prometheus installations
+merge_request: 33508
+author:
+type: added
diff --git a/changelogs/unreleased/dennis-project-templates-add-gitbook-logo.yml b/changelogs/unreleased/dennis-project-templates-add-gitbook-logo.yml
new file mode 100644
index 00000000000..ebe823442f0
--- /dev/null
+++ b/changelogs/unreleased/dennis-project-templates-add-gitbook-logo.yml
@@ -0,0 +1,5 @@
+---
+title: Add GitBook logo to project templates
+merge_request: 33403
+author:
+type: changed
diff --git a/changelogs/unreleased/dennis-project-templates-add-hugo-logo.yml b/changelogs/unreleased/dennis-project-templates-add-hugo-logo.yml
new file mode 100644
index 00000000000..df2305c1406
--- /dev/null
+++ b/changelogs/unreleased/dennis-project-templates-add-hugo-logo.yml
@@ -0,0 +1,5 @@
+---
+title: Add Hugo logo to project templates
+merge_request: 33402
+author:
+type: changed
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 84db15d6535..ff5ccbb3c1b 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -626,3 +626,9 @@
:why:
:versions: []
:when: 2019-11-08 10:03:31.787226000 Z
+- - :whitelist
+ - CC0-1.0
+ - :who: Thomas Randolph
+ :why: This license is public domain
+ :versions: []
+ :when: 2020-06-03 05:04:44.632875345 Z
diff --git a/config/initializers/google_api_client.rb b/config/initializers/google_api_client.rb
index 443bb29fb52..49a35e5bd7c 100644
--- a/config/initializers/google_api_client.rb
+++ b/config/initializers/google_api_client.rb
@@ -1,23 +1,12 @@
# frozen_string_literal: true
-#
-# google-api-client >= 0.26.0 supports enabling CloudRun and Istio during
-# cluster creation, but fog-google currently hard deps on '~> 0.23.0', which
-# prevents us from upgrading. We are injecting these options as hashes below
-# as a workaround until this is resolved.
-#
-# This can be removed once fog-google and google-api-client can be upgraded.
-# See https://gitlab.com/gitlab-org/gitlab/issues/31280 for more details.
-#
-require 'google/apis/container_v1beta1'
require 'google/apis/options'
+# these require solve load order issues (undefined constant Google::Apis::ServerError and Signet::RemoteServerError, rescued in multiple places)
+require 'google/apis/errors'
+require 'signet/errors'
+
# As stated in https://github.com/googleapis/google-api-ruby-client#errors--retries,
# enabling retries is strongly encouraged but disabled by default. Large uploads
# that may hit timeouts will mainly benefit from this.
Google::Apis::RequestOptions.default.retries = 3 if Gitlab::Utils.to_boolean(ENV.fetch('ENABLE_GOOGLE_API_RETRIES', true))
-
-Google::Apis::ContainerV1beta1::AddonsConfig::Representation.tap do |representation|
- representation.hash :cloud_run_config, as: 'cloudRunConfig'
- representation.hash :istio_config, as: 'istioConfig'
-end
diff --git a/db/migrate/20200528125905_add_project_id_user_id_status_ref_index_to_ci_pipelines.rb b/db/migrate/20200528125905_add_project_id_user_id_status_ref_index_to_ci_pipelines.rb
new file mode 100644
index 00000000000..7211490e337
--- /dev/null
+++ b/db/migrate/20200528125905_add_project_id_user_id_status_ref_index_to_ci_pipelines.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class AddProjectIdUserIdStatusRefIndexToCiPipelines < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ SOURCE_PARENT_PIPELINE = 12
+
+ def up
+ add_concurrent_index(
+ :ci_pipelines,
+ [:project_id, :user_id, :status, :ref],
+ where: "source != #{SOURCE_PARENT_PIPELINE}"
+ )
+ end
+
+ def down
+ remove_concurrent_index(
+ :ci_pipelines,
+ [:project_id, :user_id, :status, :ref],
+ where: "source != #{SOURCE_PARENT_PIPELINE}"
+ )
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index f2196ef4847..b72a27d88ff 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -9416,6 +9416,8 @@ CREATE INDEX index_ci_pipelines_on_project_id_and_status_and_config_source ON pu
CREATE INDEX index_ci_pipelines_on_project_id_and_status_and_updated_at ON public.ci_pipelines USING btree (project_id, status, updated_at);
+CREATE INDEX index_ci_pipelines_on_project_id_and_user_id_and_status_and_ref ON public.ci_pipelines USING btree (project_id, user_id, status, ref) WHERE (source <> 12);
+
CREATE INDEX index_ci_pipelines_on_project_idandrefandiddesc ON public.ci_pipelines USING btree (project_id, ref, id DESC);
CREATE INDEX index_ci_pipelines_on_status ON public.ci_pipelines USING btree (status);
@@ -13791,6 +13793,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200527152657
20200528054112
20200528123703
+20200528125905
20200603073101
\.
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml
index d85c930ad82..21c0c29e4fe 100644
--- a/doc/.vale/gitlab/Acronyms.yml
+++ b/doc/.vale/gitlab/Acronyms.yml
@@ -15,6 +15,7 @@ exceptions:
- ASCII
- AWS
- CNAME
+ - CPU
- CSS
- CSV
- DNS
@@ -39,6 +40,7 @@ exceptions:
- POST
- PUT
- RSA
+ - RSS
- SAML
- SCP
- SCSS
@@ -50,6 +52,7 @@ exceptions:
- TIP
- TLS
- TODO
+ - UNIX
- URI
- URL
- VPC
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index 91dd058a587..98cb91757a9 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -113,6 +113,7 @@ Dreamweaver
Elasticsearch
enablement
enqueued
+ETag
Excon
expirable
Facebook
diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md
index 437f75f341b..ca0a14b8c5c 100644
--- a/doc/administration/high_availability/nfs.md
+++ b/doc/administration/high_availability/nfs.md
@@ -194,7 +194,7 @@ use the `hard` option, because (from the man page):
Other vendors make similar recommendations, including
[SAP](http://wiki.scn.sap.com/wiki/x/PARnFQ) and NetApp's
-[knowledge base](https://kb.netapp.com/app/answers/answer_view/a_id/1004893/~/hard-mount-vs-soft-mount-),
+[knowledge base](https://kb.netapp.com/Advice_and_Troubleshooting/Data_Storage_Software/ONTAP_OS/What_are_the_differences_between_hard_mount_and_soft_mount),
they highlight that if the NFS client driver caches data, `soft` means there is no certainty if
writes by GitLab are actually on disk.
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index 5c6c85c7356..c681dedbca8 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -24,7 +24,7 @@ It allows you to see (from left to right):
![Redis profiling using the Performance Bar](img/performance_bar_redis_calls.png)
- total load timings of the page; click through for details of these calls. Values in the following order:
- Backend - Time that the actual base page took to load
- - [First Contentful Paint](https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint) - Time until something was visible to the user
+ - [First Contentful Paint](hhttps://web.dev/first-contentful-paint/) - Time until something was visible to the user
- [DomContentLoaded](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/measure-crp) Event
- Number of Requests that the page loaded
![Frontend requests using the Performance Bar](img/performance_bar_frontend.png)
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index 9d26c1bcad1..7833f908eb7 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -6,30 +6,29 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Prometheus metrics
->**Note:**
-Available since [Omnibus GitLab 9.3](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/29118). For
-installations from source you'll have to configure it yourself.
-
To enable the GitLab Prometheus metrics:
-1. Log into GitLab as an administrator.
-1. Navigate to **Admin Area > Settings > Metrics and profiling**.
+1. Log into GitLab as a user with [administrator permissions](../../../user/permissions.md).
+1. Navigate to **{admin}** **Admin Area > Settings > Metrics and profiling**.
1. Find the **Metrics - Prometheus** section, and click **Enable Prometheus Metrics**.
1. [Restart GitLab](../../restart_gitlab.md#omnibus-gitlab-restart) for the changes to take effect.
+NOTE: **Note:**
+For installations from source you'll have to configure it yourself.
+
## Collecting the metrics
GitLab monitors its own internal service metrics, and makes them available at the
-`/-/metrics` endpoint. Unlike other [Prometheus](https://prometheus.io) exporters, in order to access
-it, the client IP needs to be [included in a whitelist](../ip_whitelist.md).
+`/-/metrics` endpoint. Unlike other [Prometheus](https://prometheus.io) exporters, to access
+it, the client IP address needs to be [explicitly allowed](../ip_whitelist.md).
-For Omnibus and Chart installations, these metrics are automatically enabled
-and collected as of [GitLab
-9.4](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/1702). For
-source installations or earlier versions, these metrics will need to be enabled
+For [Omnibus GitLab](https://docs.gitlab.com/omnibus/) and Chart installations,
+these metrics are enabled and collected as of
+[GitLab 9.4](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/1702).
+For source installations or earlier versions, these metrics must be enabled
manually and collected by a Prometheus server.
-See also [Sidekiq metrics](#sidekiq-metrics) for how to enable and view metrics from Sidekiq nodes.
+For enabling and viewing metrics from Sidekiq nodes, see [Sidekiq metrics](#sidekiq-metrics).
## Metrics available
@@ -50,7 +49,7 @@ The following metrics are available:
| `gitlab_method_call_duration_seconds` | Histogram | 10.2 | Method calls real duration | `controller`, `action`, `module`, `method` |
| `gitlab_page_out_of_bounds` | Counter | 12.8 | Counter for the PageLimiter pagination limit being hit | `controller`, `action`, `bot` |
| `gitlab_rails_queue_duration_seconds` | Histogram | 9.4 | Measures latency between GitLab Workhorse forwarding a request to Rails | |
-| `gitlab_sql_duration_seconds` | Histogram | 10.2 | SQL execution time, excluding SCHEMA operations and BEGIN / COMMIT | |
+| `gitlab_sql_duration_seconds` | Histogram | 10.2 | SQL execution time, excluding `SCHEMA` operations and `BEGIN` / `COMMIT` | |
| `gitlab_transaction_allocated_memory_bytes` | Histogram | 10.2 | Allocated memory for all transactions (`gitlab_transaction_*` metrics) | |
| `gitlab_transaction_cache_<key>_count_total` | Counter | 10.2 | Counter for total Rails cache calls (per key) | |
| `gitlab_transaction_cache_<key>_duration_total` | Counter | 10.2 | Counter for total time (seconds) spent in Rails cache calls (per key) | |
@@ -65,11 +64,11 @@ The following metrics are available:
| `gitlab_transaction_event_build_not_found_total` | Counter | 9.4 | Counter for build not found for API /jobs/request | |
| `gitlab_transaction_event_change_default_branch_total` | Counter | 9.4 | Counter when default branch is changed for any repository | |
| `gitlab_transaction_event_create_repository_total` | Counter | 9.4 | Counter when any repository is created | |
-| `gitlab_transaction_event_etag_caching_cache_hit_total` | Counter | 9.4 | Counter for etag cache hit. | `endpoint` |
-| `gitlab_transaction_event_etag_caching_header_missing_total` | Counter | 9.4 | Counter for etag cache miss - header missing | `endpoint` |
-| `gitlab_transaction_event_etag_caching_key_not_found_total` | Counter | 9.4 | Counter for etag cache miss - key not found | `endpoint` |
-| `gitlab_transaction_event_etag_caching_middleware_used_total` | Counter | 9.4 | Counter for etag middleware accessed | `endpoint` |
-| `gitlab_transaction_event_etag_caching_resource_changed_total` | Counter | 9.4 | Counter for etag cache miss - resource changed | `endpoint` |
+| `gitlab_transaction_event_etag_caching_cache_hit_total` | Counter | 9.4 | Counter for ETag cache hit. | `endpoint` |
+| `gitlab_transaction_event_etag_caching_header_missing_total` | Counter | 9.4 | Counter for ETag cache miss - header missing | `endpoint` |
+| `gitlab_transaction_event_etag_caching_key_not_found_total` | Counter | 9.4 | Counter for ETag cache miss - key not found | `endpoint` |
+| `gitlab_transaction_event_etag_caching_middleware_used_total` | Counter | 9.4 | Counter for ETag middleware accessed | `endpoint` |
+| `gitlab_transaction_event_etag_caching_resource_changed_total` | Counter | 9.4 | Counter for ETag cache miss - resource changed | `endpoint` |
| `gitlab_transaction_event_fork_repository_total` | Counter | 9.4 | Counter for repository forks (RepositoryForkWorker). Only incremented when source repository exists | |
| `gitlab_transaction_event_import_repository_total` | Counter | 9.4 | Counter for repository imports (RepositoryImportWorker) | |
| `gitlab_transaction_event_push_branch_total` | Counter | 9.4 | Counter for all branch pushes | |
@@ -193,8 +192,6 @@ They all have these labels:
1. `ActiveRecord::Base` is the main database connection.
1. `Geo::TrackingBase` is the connection to the Geo tracking database, if
enabled.
- 1. `Gitlab::Database::LoadBalancing::Host` is a connection used by [database
- load balancing](../../database_load_balancing.md), if enabled.
1. `host` - the host name used to connect to the database.
1. `port` - the port used to connect to the database.
@@ -238,31 +235,28 @@ Unicorn specific metrics, when Unicorn is used.
When Puma is used instead of Unicorn, the following metrics are available:
-| Metric | Type | Since | Description |
-|:---------------------------------------------- |:------- |:----- |:----------- |
-| `puma_workers` | Gauge | 12.0 | Total number of workers |
-| `puma_running_workers` | Gauge | 12.0 | Number of booted workers |
-| `puma_stale_workers` | Gauge | 12.0 | Number of old workers |
-| `puma_running` | Gauge | 12.0 | Number of running threads |
-| `puma_queued_connections` | Gauge | 12.0 | Number of connections in that worker's "to do" set waiting for a worker thread |
-| `puma_active_connections` | Gauge | 12.0 | Number of threads processing a request |
-| `puma_pool_capacity` | Gauge | 12.0 | Number of requests the worker is capable of taking right now |
-| `puma_max_threads` | Gauge | 12.0 | Maximum number of worker threads |
-| `puma_idle_threads` | Gauge | 12.0 | Number of spawned threads which are not processing a request |
-| `puma_killer_terminations_total` | Gauge | 12.0 | Number of workers terminated by PumaWorkerKiller |
+| Metric | Type | Since | Description |
+|:--------------------------------- |:------- |:----- |:----------- |
+| `puma_workers` | Gauge | 12.0 | Total number of workers |
+| `puma_running_workers` | Gauge | 12.0 | Number of booted workers |
+| `puma_stale_workers` | Gauge | 12.0 | Number of old workers |
+| `puma_running` | Gauge | 12.0 | Number of running threads |
+| `puma_queued_connections` | Gauge | 12.0 | Number of connections in that worker's "to do" set waiting for a worker thread |
+| `puma_active_connections` | Gauge | 12.0 | Number of threads processing a request |
+| `puma_pool_capacity` | Gauge | 12.0 | Number of requests the worker is capable of taking right now |
+| `puma_max_threads` | Gauge | 12.0 | Maximum number of worker threads |
+| `puma_idle_threads` | Gauge | 12.0 | Number of spawned threads which are not processing a request |
+| `puma_killer_terminations_total` | Gauge | 12.0 | Number of workers terminated by PumaWorkerKiller |
## Metrics shared directory
GitLab's Prometheus client requires a directory to store metrics data shared between multi-process services.
Those files are shared among all instances running under Unicorn server.
-The directory needs to be accessible to all running Unicorn's processes otherwise
-metrics will not function correctly.
-
-For best performance its advisable that this directory will be located in `tmpfs`.
-
-Its location is configured using environment variable `prometheus_multiproc_dir`.
+The directory must be accessible to all running Unicorn's processes, or
+metrics won't function correctly.
-If GitLab is installed using Omnibus and `tmpfs` is available then metrics
-directory will be automatically configured.
+This directory's location is configured using environment variable `prometheus_multiproc_dir`.
+For best performance, create this directory in `tmpfs`.
-[← Back to the main Prometheus page](index.md)
+If GitLab is installed using [Omnibus GitLab](https://docs.gitlab.com/omnibus/)
+and `tmpfs` is available, then the metrics directory will be configured for you.
diff --git a/doc/administration/monitoring/prometheus/node_exporter.md b/doc/administration/monitoring/prometheus/node_exporter.md
index 357303ee4e1..07f6b8b8e1e 100644
--- a/doc/administration/monitoring/prometheus/node_exporter.md
+++ b/doc/administration/monitoring/prometheus/node_exporter.md
@@ -6,27 +6,24 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Node exporter
->**Note:**
-Available since Omnibus GitLab 8.16. For installations from source you'll
-have to install and configure it yourself.
-
-The [node exporter](https://github.com/prometheus/node_exporter) allows you to measure
+The [node exporter](https://github.com/prometheus/node_exporter) enables you to measure
various machine resources such as memory, disk and CPU utilization.
+NOTE: **Note:**
+For installations from source you'll have to install and configure it yourself.
+
To enable the node exporter:
-1. [Enable Prometheus](index.md#configuring-prometheus)
-1. Edit `/etc/gitlab/gitlab.rb`
-1. Add or find and uncomment the following line, making sure it's set to `true`:
+1. [Enable Prometheus](index.md#configuring-prometheus).
+1. Edit `/etc/gitlab/gitlab.rb`.
+1. Add (or find and uncomment) the following line, making sure it's set to `true`:
```ruby
node_exporter['enable'] = true
```
-1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
- for the changes to take effect
-
-Prometheus will now automatically begin collecting performance data from
-the node exporter exposed under `localhost:9100`.
+1. Save the file, and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
+ for the changes to take effect.
-[← Back to the main Prometheus page](index.md)
+Prometheus will now begin collecting performance data from the node exporter
+exposed at `localhost:9100`.
diff --git a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
index 2183ace42a1..62d0bf684b6 100644
--- a/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
+++ b/doc/administration/monitoring/prometheus/pgbouncer_exporter.md
@@ -6,29 +6,30 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# PgBouncer exporter
->**Note:**
-Available since [Omnibus GitLab 11.0](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2493).
-For installations from source you'll have to install and configure it yourself.
+> Introduced in [Omnibus GitLab 11.0](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2493).
+
+The [PgBouncer exporter](https://github.com/prometheus-community/pgbouncer_exporter) enables
+you to measure various [PgBouncer](https://www.pgbouncer.org/) metrics.
-The [PgBouncer exporter](https://github.com/prometheus-community/pgbouncer_exporter) allows you to measure various PgBouncer metrics.
+NOTE: **Note:**
+For installations from source you'll have to install and configure it yourself.
To enable the PgBouncer exporter:
-1. [Enable Prometheus](index.md#configuring-prometheus)
-1. Edit `/etc/gitlab/gitlab.rb`
-1. Add or find and uncomment the following line, making sure it's set to `true`:
+1. [Enable Prometheus](index.md#configuring-prometheus).
+1. Edit `/etc/gitlab/gitlab.rb`.
+1. Add (or find and uncomment) the following line, making sure it's set to `true`:
```ruby
pgbouncer_exporter['enable'] = true
```
-1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to
- take effect.
+1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
+ for the changes to take effect.
-Prometheus will now automatically begin collecting performance data from
-the PgBouncer exporter exposed under `localhost:9188`.
+Prometheus will now begin collecting performance data from the PgBouncer exporter
+exposed at `localhost:9188`.
-The PgBouncer exporter will also be enabled by default if the [`pgbouncer_role`](https://docs.gitlab.com/omnibus/roles/#postgres-roles)
+The PgBouncer exporter will also be enabled by default if the
+[`pgbouncer_role`](https://docs.gitlab.com/omnibus/roles/#postgresql-roles)
role is enabled.
-
-[← Back to the main Prometheus page](index.md)
diff --git a/doc/administration/monitoring/prometheus/postgres_exporter.md b/doc/administration/monitoring/prometheus/postgres_exporter.md
index 77ca502b21d..0dd69bd81d6 100644
--- a/doc/administration/monitoring/prometheus/postgres_exporter.md
+++ b/doc/administration/monitoring/prometheus/postgres_exporter.md
@@ -6,12 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# PostgreSQL Server Exporter
->**Note:**
-Available since [Omnibus GitLab 8.17](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/1131).
-For installations from source you will have to install and configure it yourself.
-
The [PostgreSQL Server Exporter](https://github.com/wrouesnel/postgres_exporter) allows you to export various PostgreSQL metrics.
+NOTE: **Note:**
+For installations from source you will have to install and configure it yourself.
+
To enable the PostgreSQL Server Exporter:
1. [Enable Prometheus](index.md#configuring-prometheus).
@@ -21,10 +20,10 @@ To enable the PostgreSQL Server Exporter:
postgres_exporter['enable'] = true
```
-NOTE: **Note:**
-If PostgreSQL Server Exporter is configured on a separate node, make sure that the local
-address is [listed in `trust_auth_cidr_addresses`](../../high_availability/database.md#network-information) or the
-exporter will not be able to connect to the database.
+ NOTE: **Note:**
+ If PostgreSQL Server Exporter is configured on a separate node, make sure the local
+ address is [listed in `trust_auth_cidr_addresses`](../../high_availability/database.md#network-information), or the
+ exporter can't connect to the database.
1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to
take effect.
@@ -34,31 +33,44 @@ the PostgreSQL Server Exporter exposed under `localhost:9187`.
## Advanced configuration
-In most cases, PostgreSQL Server Exporter will work with the defaults and you should not
-need to change anything.
-
-To further customize the PostgreSQL Server Exporter, use the following configuration options:
+In most cases, PostgreSQL Server Exporter works with the defaults and you should not
+need to change anything. To further customize the PostgreSQL Server Exporter,
+use the following configuration options:
1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
- postgres_exporter['dbname'] = 'pgbouncer' # The name of the database to connect to.
- postgres_exporter['user'] = 'gitlab-psql' # The user to sign in as.
- postgres_exporter['password'] = '' # The user's password.
- postgres_exporter['host'] = 'localhost' # The host to connect to. Values that start with '/' are for unix domain sockets (default is 'localhost').
- postgres_exporter['port'] = 5432 # The port to bind to (default is '5432').
- postgres_exporter['sslmode'] = 'require' # Whether or not to use SSL. Valid options are:
- # 'disable' (no SSL),
- # 'require' (always use SSL and skip verification, this is the default value),
- # 'verify-ca' (always use SSL and verify that the certificate presented by the server was signed by a trusted CA),
- # 'verify-full' (always use SSL and verify that the certification presented by the server was signed by a trusted CA and the server host name matches the one in the certificate).
- postgres_exporter['fallback_application_name'] = '' # An application_name to fall back to if one isn't provided.
- postgres_exporter['connect_timeout'] = '' # Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely.
- postgres_exporter['sslcert'] = 'ssl.crt' # Cert file location. The file must contain PEM encoded data.
- postgres_exporter['sslkey'] = 'ssl.key' # Key file location. The file must contain PEM encoded data.
- postgres_exporter['sslrootcert'] = 'ssl-root.crt' # The location of the root certificate file. The file must contain PEM encoded data.
+ # The name of the database to connect to.
+ postgres_exporter['dbname'] = 'pgbouncer'
+ # The user to sign in as.
+ postgres_exporter['user'] = 'gitlab-psql'
+ # The user's password.
+ postgres_exporter['password'] = ''
+ # The host to connect to. Values that start with '/' are for unix domain sockets
+ # (default is 'localhost').
+ postgres_exporter['host'] = 'localhost'
+ # The port to bind to (default is '5432').
+ postgres_exporter['port'] = 5432
+ # Whether or not to use SSL. Valid options are:
+ # 'disable' (no SSL),
+ # 'require' (always use SSL and skip verification, this is the default value),
+ # 'verify-ca' (always use SSL and verify that the certificate presented by
+ # the server was signed by a trusted CA),
+ # 'verify-full' (always use SSL and verify that the certification presented
+ # by the server was signed by a trusted CA and the server host name matches
+ # the one in the certificate).
+ postgres_exporter['sslmode'] = 'require'
+ # An application_name to fall back to if one isn't provided.
+ postgres_exporter['fallback_application_name'] = ''
+ # Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely.
+ postgres_exporter['connect_timeout'] = ''
+ # Cert file location. The file must contain PEM encoded data.
+ postgres_exporter['sslcert'] = 'ssl.crt'
+ # Key file location. The file must contain PEM encoded data.
+ postgres_exporter['sslkey'] = 'ssl.key'
+ # The location of the root certificate file. The file must contain PEM encoded data.
+ postgres_exporter['sslrootcert'] = 'ssl-root.crt'
```
-1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-[← Back to the main Prometheus page](index.md)
+1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
+ for the changes to take effect.
diff --git a/doc/administration/monitoring/prometheus/redis_exporter.md b/doc/administration/monitoring/prometheus/redis_exporter.md
index bef87400f5a..b7c66959349 100644
--- a/doc/administration/monitoring/prometheus/redis_exporter.md
+++ b/doc/administration/monitoring/prometheus/redis_exporter.md
@@ -6,19 +6,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Redis exporter
->**Note:**
-Available since [Omnibus GitLab 8.17](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/1118).
-For installations from source you'll have to install and configure it yourself.
-
-The [Redis exporter](https://github.com/oliver006/redis_exporter) allows you to measure
-various [Redis](https://redis.io) metrics. For more information on what's exported,
+The [Redis exporter](https://github.com/oliver006/redis_exporter) enables you to measure
+various [Redis](https://redis.io) metrics. For more information on what is exported,
[read the upstream documentation](https://github.com/oliver006/redis_exporter/blob/master/README.md#whats-exported).
+NOTE: **Note:**
+For installations from source you'll have to install and configure it yourself.
+
To enable the Redis exporter:
-1. [Enable Prometheus](index.md#configuring-prometheus)
-1. Edit `/etc/gitlab/gitlab.rb`
-1. Add or find and uncomment the following line, making sure it's set to `true`:
+1. [Enable Prometheus](index.md#configuring-prometheus).
+1. Edit `/etc/gitlab/gitlab.rb`.
+1. Add (or find and uncomment) the following line, making sure it's set to `true`:
```ruby
redis_exporter['enable'] = true
@@ -27,7 +26,5 @@ To enable the Redis exporter:
1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure)
for the changes to take effect.
-Prometheus will now automatically begin collecting performance data from
-the Redis exporter exposed under `localhost:9121`.
-
-[← Back to the main Prometheus page](index.md)
+Prometheus will now begin collecting performance data from
+the Redis exporter exposed at `localhost:9121`.
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index dc9ab8674d2..12ca8a41f20 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -1726,6 +1726,36 @@ type CreateSnippetPayload {
}
"""
+Autogenerated input type of DeleteAnnotation
+"""
+input DeleteAnnotationInput {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ The global id of the annotation to delete
+ """
+ id: ID!
+}
+
+"""
+Autogenerated return type of DeleteAnnotation
+"""
+type DeleteAnnotationPayload {
+ """
+ A unique identifier for the client performing the mutation.
+ """
+ clientMutationId: String
+
+ """
+ Errors encountered during execution of the mutation.
+ """
+ errors: [String!]!
+}
+
+"""
The response from the AdminSidekiqQueuesDeleteJobs mutation.
"""
type DeleteJobsResponse {
@@ -7210,6 +7240,7 @@ type Mutation {
createNote(input: CreateNoteInput!): CreateNotePayload
createRequirement(input: CreateRequirementInput!): CreateRequirementPayload
createSnippet(input: CreateSnippetInput!): CreateSnippetPayload
+ deleteAnnotation(input: DeleteAnnotationInput!): DeleteAnnotationPayload
designManagementDelete(input: DesignManagementDeleteInput!): DesignManagementDeletePayload
designManagementUpload(input: DesignManagementUploadInput!): DesignManagementUploadPayload
destroyNote(input: DestroyNoteInput!): DestroyNotePayload
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 73be5c414c6..393585260b5 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -4571,6 +4571,94 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "DeleteAnnotationInput",
+ "description": "Autogenerated input type of DeleteAnnotation",
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "id",
+ "description": "The global id of the annotation to delete",
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ID",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "DeleteAnnotationPayload",
+ "description": "Autogenerated return type of DeleteAnnotation",
+ "fields": [
+ {
+ "name": "clientMutationId",
+ "description": "A unique identifier for the client performing the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "errors",
+ "description": "Errors encountered during execution of the mutation.",
+ "args": [
+
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [
+
+ ],
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "DeleteJobsResponse",
"description": "The response from the AdminSidekiqQueuesDeleteJobs mutation.",
@@ -20522,6 +20610,33 @@
"deprecationReason": null
},
{
+ "name": "deleteAnnotation",
+ "description": null,
+ "args": [
+ {
+ "name": "input",
+ "description": null,
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "INPUT_OBJECT",
+ "name": "DeleteAnnotationInput",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "DeleteAnnotationPayload",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "designManagementDelete",
"description": null,
"args": [
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index fca1038ca7d..0cfa7d4b3a6 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -305,6 +305,15 @@ Autogenerated return type of CreateSnippet
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `snippet` | Snippet | The snippet after mutation |
+## DeleteAnnotationPayload
+
+Autogenerated return type of DeleteAnnotation
+
+| Name | Type | Description |
+| --- | ---- | ---------- |
+| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
+| `errors` | String! => Array | Errors encountered during execution of the mutation. |
+
## DeleteJobsResponse
The response from the AdminSidekiqQueuesDeleteJobs mutation.
diff --git a/doc/api/services.md b/doc/api/services.md
index b1549dacd2b..02048a27c1b 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -1007,6 +1007,8 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `api_url` | string | true | Prometheus API Base URL. For example, `http://prometheus.example.com/`. |
+| `google_iap_audience_client_id` | string | false | Client ID of the IAP secured resource (looks like IAP_CLIENT_ID.apps.googleusercontent.com) |
+| `google_iap_service_account_json` | string | false | credentials.json file for your service account, like { "type": "service_account", "project_id": ... } |
### Delete Prometheus service
diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
index e9875bc8c2b..5f8db5f7ee8 100644
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
+++ b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
@@ -48,7 +48,7 @@ Phoenix can run in any OS where Erlang is supported:
- Fedora
- Raspbian
-Check the [Phoenix learning guide](https://hexdocs.pm/phoenix/learning.html) for more information.
+Check the [Phoenix learning guide](https://hexdocs.pm/phoenix/overview.html) for more information.
### What is Elixir?
diff --git a/doc/ci/jenkins/index.md b/doc/ci/jenkins/index.md
index daa6739f503..8eeab6f6c2e 100644
--- a/doc/ci/jenkins/index.md
+++ b/doc/ci/jenkins/index.md
@@ -210,7 +210,7 @@ which can be used by projects in that instance.
Declarative Jenkinsfiles contain "Sections" and "Directives" which are used to control the behavior of your
pipelines. There are equivalents for all of these in GitLab, which we've documented below.
-This section is based on the [Jenkinsfile syntax documentation](https://jenkins.io/doc/book/pipeline/syntax/)
+This section is based on the [Jenkinsfile syntax documentation](http://www.jenkins.io/doc/book/pipeline/syntax/)
and is meant to be a mapping of concepts there to concepts in GitLab.
### Sections
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 413e701013b..8f44c3067bf 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -2561,7 +2561,7 @@ job:
#### `artifacts:exclude`
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/15122) in GitLab 13.1
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15122) in GitLab 13.1
> - Requires GitLab Runner 13.1
`exclude` makes it possible to prevent files from being added to an artifacts
diff --git a/doc/development/application_limits.md b/doc/development/application_limits.md
index 60138f23cc2..36dc09b62b6 100644
--- a/doc/development/application_limits.md
+++ b/doc/development/application_limits.md
@@ -11,7 +11,7 @@ coordinate with others to [document](../administration/instance_limits.md)
and communicate those limits.
There is a guide about [introducing application
-limits](https://about.gitlab.com/handbook/product/product-management/process/index.html#introducing-application-limits).
+limits](https://about.gitlab.com/handbook/product/product-management/process/#introducing-application-limits).
## Development
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index a20309ad408..1001a49be6a 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -444,7 +444,7 @@ Lightweight connection pooler for PostgreSQL.
#### PgBouncer Exporter
-- [Project page](https://github.com/stanhu/pgbouncer_exporter/blob/master/README.md)
+- [Project page](https://github.com/prometheus-community/pgbouncer_exporter/blob/master/README.md)
- Configuration:
- [Omnibus](../administration/monitoring/prometheus/pgbouncer_exporter.md)
- [Charts](https://docs.gitlab.com/charts/installation/deployment.html#postgresql)
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 48644eeaf92..5e7f4ba9f37 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -502,7 +502,7 @@ Properties of customer critical merge requests:
- The DRI will assign the `customer-critical-merge-request` label to the merge request.
- It is required that the reviewer(s) and maintainer(s) involved with a customer critical merge request are engaged as soon as this decision is made.
- It is required to prioritize work for those involved on a customer critical merge request so that they have the time available necessary to focus on it.
-- It is required to adhere to GitLab [values](https://about.gitlab.com/handbook/values.md) and processes when working on customer critical merge requests, taking particular note of family and friends first/work second, definition of done, iteration, and release when it's ready.
+- It is required to adhere to GitLab [values](https://about.gitlab.com/handbook/values/) and processes when working on customer critical merge requests, taking particular note of family and friends first/work second, definition of done, iteration, and release when it's ready.
- Customer critical merge requests are required to not reduce security, introduce data-loss risk, reduce availability, nor break existing functionality per the process for [prioritizing technical decisions](https://about.gitlab.com/handbook/engineering/#prioritizing-technical-decisions.md).
- On customer critical requests, it is _recommended_ that those involved _consider_ coordinating synchronously (Zoom, Slack) in addition to asynchronously (merge requests comments) if they believe this will reduce elapsed time to merge even though this _may_ sacrifice [efficiency](https://about.gitlab.com/company/culture/all-remote/asynchronous/#evaluating-efficiency.md).
- After a customer critical merge request is merged, a retrospective must be completed with the intention of reducing the frequency of future customer critical merge requests.
diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md
index ebdd35ee34d..ddd7ee39155 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -96,7 +96,7 @@ Having a knowledge base in any form that is separate from the documentation woul
All GitLab documentation is written using [Markdown](https://en.wikipedia.org/wiki/Markdown).
-The [documentation website](https://docs.gitlab.com) uses GitLab Kramdown as its Markdown rendering engine. For a complete Kramdown reference, see the [GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/engineering/ux/technical-writing/markdown-guide/).
+The [documentation website](https://docs.gitlab.com) uses GitLab Kramdown as its Markdown rendering engine. For a complete Kramdown reference, see the [GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/markdown-guide/).
The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown)
Ruby gem will support all [GFM markup](../../user/markdown.md) in the future. That is,
diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md
index 35cbbad6c55..c3e15cb1b2b 100644
--- a/doc/development/documentation/workflow.md
+++ b/doc/development/documentation/workflow.md
@@ -54,7 +54,7 @@ To update GitLab documentation:
1. Follow the described standards and processes listed on the page, including:
- The [Structure and template](structure.md) page.
- The [Style Guide](styleguide.md).
- - The [Markdown Guide](https://about.gitlab.com/handbook/engineering/ux/technical-writing/markdown-guide/).
+ - The [Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/).
1. Follow GitLab's [Merge Request Guidelines](../contributing/merge_request_workflow.md#merge-request-guidelines).
TIP: **Tip:**
diff --git a/doc/development/fe_guide/dependencies.md b/doc/development/fe_guide/dependencies.md
index 0f5825992e9..7f078df887d 100644
--- a/doc/development/fe_guide/dependencies.md
+++ b/doc/development/fe_guide/dependencies.md
@@ -32,7 +32,7 @@ because they can create conflicts in the dependency tree. Blocked dependencies a
### BootstrapVue
-[BootstrapVue](https://bootstrap-vue.js.org/) is a component library built with Vue.js and Bootstrap.
+[BootstrapVue](https://bootstrap-vue.org/) is a component library built with Vue.js and Bootstrap.
We wrap BootstrapVue components in [GitLab UI](https://gitlab.com/gitlab-org/gitlab-ui/) with the
purpose of applying visual styles and usage guidelines specified in the
[Pajamas Design System](https://design.gitlab.com/). For this reason, we recommend not installing
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 44f8ebbdd00..4be7623db8d 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -24,7 +24,7 @@
### Libraries
-We use [Apollo](https://www.apollographql.com/) (specifically [Apollo Client](https://www.apollographql.com/docs/react/)) and [Vue Apollo](https://github.com/Akryum/vue-apollo/)
+We use [Apollo](https://www.apollographql.com/) (specifically [Apollo Client](https://www.apollographql.com/docs/react/)) and [Vue Apollo](https://github.com/vuejs/vue-apollo)
when using GraphQL for frontend development.
If you are using GraphQL within a Vue application, the [Usage in Vue](#usage-in-vue) section
@@ -153,7 +153,7 @@ new Vue({
});
```
-Read more about [Vue Apollo](https://github.com/vuejs/vue-apollo) in the [Vue Apollo documentation](https://vue-apollo.netlify.com/guide/).
+Read more about [Vue Apollo](https://github.com/vuejs/vue-apollo) in the [Vue Apollo documentation](https://vue-apollo.netlify.app/guide/).
### Local state with Apollo
@@ -265,7 +265,7 @@ const defaultClient = createDefaultClient(
Now every single time on attempt to fetch a version, our client will fetch `id` and `sha` from the remote API endpoint and will assign our hardcoded values to `author` and `createdAt` version properties. With this data, frontend developers are able to work on UI part without being blocked by backend. When actual response is added to the API, a custom local resolver can be removed fast and the only change to query/fragment is `@client` directive removal.
-Read more about local state management with Apollo in the [Vue Apollo documentation](https://vue-apollo.netlify.com/guide/local-state.html#local-state).
+Read more about local state management with Apollo in the [Vue Apollo documentation](https://vue-apollo.netlify.app/guide/local-state.html#local-state).
### Using with Vuex
diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md
index 7848c8b11d9..e963bdd6848 100644
--- a/doc/development/i18n/externalization.md
+++ b/doc/development/i18n/externalization.md
@@ -306,7 +306,7 @@ const dateFormat = createDateTimeFormat({ year: 'numeric', month: 'long', day: '
console.log(dateFormat.format(new Date('2063-04-05'))) // April 5, 2063
```
-This makes use of [`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat).
+This makes use of [`Intl.DateTimeFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat).
- In Ruby/HAML, we have two ways of adding format to dates and times:
diff --git a/doc/development/integrations/jenkins.md b/doc/development/integrations/jenkins.md
index 001d1c21fd3..3d6f314c02b 100644
--- a/doc/development/integrations/jenkins.md
+++ b/doc/development/integrations/jenkins.md
@@ -1,6 +1,6 @@
# How to run Jenkins in development environment (on macOS) **(STARTER)**
-This is a step by step guide on how to set up [Jenkins](https://jenkins.io/) on your local machine and connect to it from your GitLab instance. GitLab triggers webhooks on Jenkins, and Jenkins connects to GitLab using the API. By running both applications on the same machine, we can make sure they are able to access each other.
+This is a step by step guide on how to set up [Jenkins](http://www.jenkins.io/) on your local machine and connect to it from your GitLab instance. GitLab triggers webhooks on Jenkins, and Jenkins connects to GitLab using the API. By running both applications on the same machine, we can make sure they are able to access each other.
## Install Jenkins
diff --git a/doc/development/multi_version_compatibility.md b/doc/development/multi_version_compatibility.md
index aedd5c1ffb7..001517d44ea 100644
--- a/doc/development/multi_version_compatibility.md
+++ b/doc/development/multi_version_compatibility.md
@@ -45,7 +45,7 @@ and set this column to `false`. The old servers were still updating the old colu
that updated the new column from the old one. For the new servers though, they were only updating the new column and that same trigger
was now working against us and setting it back to the wrong value.
-For more information, see [the relevant issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/9176).
+For more information, see this [confidential issue](../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/9176`.
### Sidebar wasn't loading for some users
diff --git a/doc/development/new_fe_guide/development/performance.md b/doc/development/new_fe_guide/development/performance.md
index edb2eed982d..7b58a80576a 100644
--- a/doc/development/new_fe_guide/development/performance.md
+++ b/doc/development/new_fe_guide/development/performance.md
@@ -9,7 +9,7 @@ Any frontend engineer can contribute to this dashboard. They can contribute by a
There are 3 recommended high impact metrics to review on each page:
-- [First visual change](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint)
+- [First visual change](https://web.dev/first-meaningful-paint/)
- [Speed Index](https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index)
- [Visual Complete 95%](https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index)
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index d7cd3d3cd2a..912b8fbf043 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -48,7 +48,7 @@ Be careful to **also test [visibility levels](https://gitlab.com/gitlab-org/gitl
Some example of well implemented access controls and tests:
-1. [example1](https://dev.gitlab.org/gitlab/gitlab-ee/merge_requests/710/diffs?diff_id=13750#af40ef0eaae3c1e018809e1d88086e32bccaca40_43_43)
+1. [example1](https://dev.gitlab.org/gitlab/gitlab-ee/-/merge_requests/710/diffs?diff_id=13750#af40ef0eaae3c1e018809e1d88086e32bccaca40_43_43)
1. [example2](https://dev.gitlab.org/gitlab/gitlabhq/-/merge_requests/2511/diffs#ed3aaab1510f43b032ce345909a887e5b167e196_142_155)
1. [example3](https://dev.gitlab.org/gitlab/gitlabhq/-/merge_requests/3170/diffs?diff_id=17494)
diff --git a/doc/development/testing_guide/index.md b/doc/development/testing_guide/index.md
index 62e6fcb2aa1..0d470e0e737 100644
--- a/doc/development/testing_guide/index.md
+++ b/doc/development/testing_guide/index.md
@@ -20,7 +20,7 @@ Following are two great articles that everyone should read to understand what
automated testing means, and what are its principles:
- [Five Factor Testing](https://madeintandem.com/blog/five-factor-testing/): Why do we need tests?
-- [Principles of Automated Testing](http://www.lihaoyi.com/post/PrinciplesofAutomatedTesting.html): Levels of testing. Prioritize tests. Cost of tests.
+- [Principles of Automated Testing](https://www.lihaoyi.com/post/PrinciplesofAutomatedTesting.html): Levels of testing. Prioritize tests. Cost of tests.
## [Testing levels](testing_levels.md)
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 342d470c392..2a252d0ca6d 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -212,7 +212,7 @@ If [Review App Stability](https://app.periscopedata.com/app/gitlab/496118/Engine
dips this may be a signal that the `review-apps-ce/ee` cluster is unhealthy.
Leading indicators may be health check failures leading to restarts or majority failure for Review App deployments.
-The [Review Apps Overview dashboard](https://app.google.stackdriver.com/dashboards/6798952013815386466?project=gitlab-review-apps&timeDomain=1d)
+The [Review Apps Overview dashboard](https://console.cloud.google.com/monitoring/classic/dashboards/6798952013815386466?project=gitlab-review-apps&timeDomain=1d)
aids in identifying load spikes on the cluster, and if nodes are problematic or the entire cluster is trending towards unhealthy.
### Release failed with `ImagePullBackOff`
diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md
index 8dc019d3fe1..21f43e359e0 100644
--- a/doc/gitlab-basics/start-using-git.md
+++ b/doc/gitlab-basics/start-using-git.md
@@ -50,7 +50,7 @@ prompt, terminal, and command line) of your preference. Here are some suggestion
- [iTerm2](https://www.iterm2.com/), which you can integrate with [zsh](https://git-scm.com/book/id/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh) and [oh my zsh](https://ohmyz.sh/) for color highlighting, among other handy features for Git users.
- For Windows users:
- Built-in: **cmd**. Click the search icon on the bottom navbar on Windows and type "cmd" to find it.
- - [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-windows-powershell?view=powershell-7): a Windows "powered up" shell, from which you can execute a greater number of commands.
+ - [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/install/installing-windows-powershell): a Windows "powered up" shell, from which you can execute a greater number of commands.
- Git Bash: it comes built into [Git for Windows](https://gitforwindows.org/).
- For Linux users:
- Built-in: [Linux Terminal](https://www.howtogeek.com/140679/beginner-geek-how-to-start-using-the-linux-terminal/).
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index fbc81da20d4..3cf963bdf57 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -177,7 +177,7 @@ Click **"Save"** for the changes to take effect.
domain registrar which points to the public IP address of your Azure VM. If you do this, you'll need
to make sure your VM is configured to use a _static_ public IP address (i.e. not a _dynamic_ one)
or you will have to reconfigure the DNS `A` record each time Azure reassigns your VM a new public IP
-address. Read [IP address types and allocation methods in Azure](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-ip-addresses-overview-arm) to learn more.
+address. Read [Public IP addresses](https://docs.microsoft.com/en-us/azure/virtual-network/public-ip-addresses) to learn more.
## Let's open some ports
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 45b9ed5f6af..23c61f54375 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -275,11 +275,11 @@ You can provide feedback [on this issue](https://gitlab.com/gitlab-org/gitlab/-/
GitLab supports the following web browsers:
-- [Mozilla Firefox](https://www.mozilla.org/firefox/new/)
+- [Mozilla Firefox](https://www.mozilla.org/en-US/firefox/new/)
- [Google Chrome](https://www.google.com/chrome/)
- [Chromium](https://www.chromium.org/getting-involved/dev-channel)
- [Apple Safari](https://www.apple.com/safari/)
-- [Microsoft Edge](https://www.microsoft.com/edge)
+- [Microsoft Edge](https://www.microsoft.com/en-us/edge)
For the listed web browsers, GitLab supports:
diff --git a/doc/integration/vault.md b/doc/integration/vault.md
index 46e33d05b6d..f26c3df93f8 100644
--- a/doc/integration/vault.md
+++ b/doc/integration/vault.md
@@ -21,7 +21,7 @@ The following assumes you already have Vault installed and running.
First you'll need to create a GitLab application to obtain an application ID and secret for authenticating into Vault. To do this, sign in to GitLab and follow these steps:
1. On GitLab, click your avatar on the top-right corner, and select your user **Settings > Applications**.
- 1. Fill out the application **Name** and [**Redirect URI**](https://www.vaultproject.io/docs/auth/jwt/#redirect-uris),
+ 1. Fill out the application **Name** and [**Redirect URI**](https://www.vaultproject.io/docs/auth/jwt#redirect-uris),
making sure to select the **OpenID** scope.
1. Save application.
1. Copy client ID and secret, or keep the page open for reference.
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index ba4ea49adc8..595c426d1db 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -141,7 +141,7 @@ You can assign the directory and file name of your choice.
You can also dedicate that SSH key pair to a [specific host](#working-with-non-default-ssh-key-pair-paths).
After assigning a file to save your SSH key, you'll get a chance to set up
-a [passphrase](https://www.ssh.com/ssh/passphrase) for your SSH key:
+a [passphrase](https://www.ssh.com/ssh/passphrase/) for your SSH key:
```plaintext
Enter passphrase (empty for no passphrase):
@@ -412,7 +412,7 @@ are *explicitly not supported* and may stop working at any time.
### Options for Microsoft Windows
-If you're running Windows 10, the [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10), and its latest [WSL 2](https://docs.microsoft.com/en-us/windows/wsl/wsl2-install) version,
+If you're running Windows 10, the [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10), and its latest [WSL 2](https://docs.microsoft.com/install-win10) version,
support the installation of different Linux distributions, which include the Git and SSH clients.
For current versions of Windows, you can also install the Git and SSH clients with
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 2ba5c6017e9..eca37b5f73a 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -44,5 +44,5 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [Kanboard Plugin GitLab Authentication](https://github.com/kanboard/plugin-gitlab-auth)
- [Jenkins GitLab OAuth Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+OAuth+Plugin)
-- [How to customize GitLab to support OpenID authentication](http://eric.van-der-vlist.com/blog/2013/11/23/how-to-customize-gitlab-to-support-openid-authentication/)
+- [How to customize GitLab to support OpenID authentication](https://eric.van-der-vlist.com/blog/2013/11/23/how-to-customize-gitlab-to-support-openid-authentication//)
- [OKD - Configuring Authentication and User Agent](https://docs.okd.io/3.11/install_config/configuring_authentication.html#GitLab)
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index d2f2b8e5183..61023449e3b 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -497,7 +497,7 @@ traffic within a local namespace, and from the `gitlab-managed-apps`
namespace. All other inbound connections are blocked. Outbound
traffic (for example, to the Internet) is not affected by the default policy.
-You can also provide a custom [policy specification](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#networkpolicyspec-v1-networking-k8s-io)
+You can also provide a custom [policy specification](https://kubernetes.io/docs/concepts/services-networking/network-policies/)
in the `.gitlab/auto-deploy-values.yaml` file, for example:
```yaml
diff --git a/doc/topics/web_application_firewall/index.md b/doc/topics/web_application_firewall/index.md
index 9f3289cd797..57043bf73b3 100644
--- a/doc/topics/web_application_firewall/index.md
+++ b/doc/topics/web_application_firewall/index.md
@@ -70,7 +70,7 @@ more advanced rules around threat detection.
## Features
-ModSecurity is enabled with the [OWASP Core Rule Set (CRS)](https://modsecurity.org/crs/) by
+ModSecurity is enabled with the [OWASP Core Rule Set (CRS)](https://github.com/coreruleset/coreruleset/) by
default. The OWASP CRS logs attempts to the following attacks:
- [SQL Injection](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_SQL_Injection)
@@ -87,7 +87,7 @@ It is good to have a basic knowledge of the following:
- [Kubernetes](https://kubernetes.io/docs/home/)
- [Ingress](https://kubernetes.github.io/ingress-nginx/)
- [ModSecurity](https://www.modsecurity.org/)
-- [OWASP Core Rule Set](https://modsecurity.org/crs/)
+- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/)
## Roadmap
diff --git a/doc/topics/web_application_firewall/quick_start_guide.md b/doc/topics/web_application_firewall/quick_start_guide.md
index 79435d6a11d..ec6702bb457 100644
--- a/doc/topics/web_application_firewall/quick_start_guide.md
+++ b/doc/topics/web_application_firewall/quick_start_guide.md
@@ -254,5 +254,5 @@ You can explore them in more detail:
- [GitLab Defend Vision](https://about.gitlab.com/direction/defend/#waf)
- [ModSecurity](https://www.modsecurity.org/)
-- [OWASP Core Rule Set](https://modsecurity.org/crs/)
+- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/)
- [AutoDevOps](../autodevops/index.md)
diff --git a/doc/university/README.md b/doc/university/README.md
index 1296e178ef0..1b13f9af584 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -76,7 +76,6 @@ The GitLab University curriculum is composed of GitLab videos, screencasts, pres
- Getting Technical Support
- Being part of our Great Community and Contributing to GitLab
1. [Getting Started with the GitLab Development Kit (GDK)](https://about.gitlab.com/blog/2016/06/08/getting-started-with-gitlab-development-kit/)
-1. [Contributing Technical Articles to the GitLab Blog](https://about.gitlab.com/blog/2016/01/26/call-for-writers/)
1. [GitLab Training Workshops](training/end-user/README.md)
1. [GitLab Professional Services](https://about.gitlab.com/services/)
@@ -176,7 +175,7 @@ The GitLab University curriculum is composed of GitLab videos, screencasts, pres
1. [Scalability and High Availability - Video](https://www.youtube.com/watch?v=cXRMJJb6sp4&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e&index=2)
1. [High Availability - Video](https://www.youtube.com/watch?v=36KS808u6bE&index=15&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
-1. [High Availability Documentation](https://about.gitlab.com/solutions/high-availability/)
+1. [High Availability Documentation](https://about.gitlab.com/solutions/reference-architectures/)
### 3.8 Cycle Analytics
diff --git a/doc/university/support/README.md b/doc/university/support/README.md
index c192aa18d24..6dbbf075e9c 100644
--- a/doc/university/support/README.md
+++ b/doc/university/support/README.md
@@ -145,7 +145,7 @@ Zendesk is our Support Center and our main communication line with our Customers
Some tickets need specific knowledge or a deep understanding of a particular component and will need to be escalated to a Senior Service Engineer or Developer
-- Read about [Escalation](https://about.gitlab.com/handbook/support/workflows/issue_escalations.html)
+- Read about [Escalation](https://about.gitlab.com/handbook/support/workflows/working-with-issues.html#functional-escalation-points)
- Find the macros in Zendesk for ticket escalations
- Take a look at the [GitLab.com Team page](https://about.gitlab.com/company/team/) to find the resident experts in their fields
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index 750bae6f5b5..dfe70613815 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -990,17 +990,17 @@ when upgrading the Vault application.
To optimally use Vault in a production environment, it's ideal to have a good understanding
of the internals of Vault and how to configure it. This can be done by reading the
-[the Vault documentation](https://www.vaultproject.io/docs/internals/) as well as
+[the Vault documentation](https://www.vaultproject.io/docs/internals) as well as
the Vault Helm chart [`values.yaml` file](https://github.com/hashicorp/vault-helm/blob/v0.3.3/values.yaml).
At a minimum you will likely set up:
-- A [seal](https://www.vaultproject.io/docs/configuration/seal/) for extra encryption
+- A [seal](https://www.vaultproject.io/docs/configuration/seal) for extra encryption
of the master key.
-- A [storage backend](https://www.vaultproject.io/docs/configuration/storage/) that is
+- A [storage backend](https://www.vaultproject.io/docs/configuration/storage) that is
suitable for environment and storage security requirements.
-- [HA Mode](https://www.vaultproject.io/docs/concepts/ha/).
-- [The Vault UI](https://www.vaultproject.io/docs/configuration/ui/).
+- [HA Mode](https://www.vaultproject.io/docs/concepts/ha).
+- [The Vault UI](https://www.vaultproject.io/docs/configuration/ui).
The following is an example values file (`.gitlab/managed-apps/vault/values.yaml`)
that configures Google Key Management Service for auto-unseal, using a Google Cloud Storage backend, enabling
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index 8ac3d266b95..37ceaa24349 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -64,7 +64,7 @@ The following languages and package managers are supported.
| Go | [Godep](https://github.com/tools/godep), [go mod](https://github.com/golang/go/wiki/Modules) |[License Finder](https://github.com/pivotal/LicenseFinder)|
| Java | [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) |[License Finder](https://github.com/pivotal/LicenseFinder)|
| .NET | [Nuget](https://www.nuget.org/) (.NET Framework is supported via the [mono project](https://www.mono-project.com/). Windows specific dependencies are not supported at this time.) |[License Finder](https://github.com/pivotal/LicenseFinder)|
-| Python | [pip](https://pip.pypa.io/en/stable/) (Python is supported through [requirements.txt](https://pip.readthedocs.io/en/1.1/requirements.html) and [Pipfile.lock](https://github.com/pypa/pipfile#pipfilelock).) |[License Finder](https://github.com/pivotal/LicenseFinder)|
+| Python | [pip](https://pip.pypa.io/en/stable/) (Python is supported through [requirements.txt](https://pip.pypa.io/en/1.1/requirements/) and [Pipfile.lock](https://github.com/pypa/pipfile#pipfilelock).) |[License Finder](https://github.com/pivotal/LicenseFinder)|
| Ruby | [gem](https://rubygems.org/) |[License Finder](https://github.com/pivotal/LicenseFinder)|
| Objective-C, Swift | [Carthage](https://github.com/Carthage/Carthage) |[License Finder](https://github.com/pivotal/LicenseFinder)|
@@ -339,7 +339,7 @@ strict-ssl = false
### Configuring Yarn projects
-You can configure Yarn projects by using a [`.yarnrc.yml`](https://yarnpkg.com/configuration/yarnrc)
+You can configure Yarn projects by using a [`.yarnrc.yml`](https://yarnpkg.com/configuration/yarnrc/)
file.
#### Using private Yarn registries
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 0bf14eb8b5a..95488541415 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -231,7 +231,7 @@ NOTE: **Note:** GitLab is unable to provide support for IdPs that are not listed
|----------|---------------|
| ADFS (Active Directory Federation Services) | [Create a Relying Party Trust](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust) |
| Azure | [Configuring single sign-on to applications](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/configure-single-sign-on-non-gallery-applications) |
-| Okta | [Setting up a SAML application in Okta](https://developer.okta.com/docs/guides/saml-application-setup/overview/) |
+| Okta | [Setting up a SAML application in Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) |
| OneLogin | [Use the OneLogin SAML Test Connector](https://onelogin.service-now.com/support?id=kb_article&sys_id=93f95543db109700d5505eea4b96198f) |
When [configuring your identify provider](#configuring-your-identity-provider), please consider the notes below for specific providers to help avoid common issues and as a guide for terminology used.
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index f66c8a788b6..93e2a07a4ca 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -117,7 +117,7 @@ Once synchronized, changing the field mapped to `id` and `externalId` will likel
### Okta configuration steps
-The SAML application that was created during [Single sign-on](index.md#okta-setup-notes) setup for [Okta](https://developer.okta.com/docs/guides/saml-application-setup/overview/) now needs to be set up for SCIM.
+The SAML application that was created during [Single sign-on](index.md#okta-setup-notes) setup for [Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) now needs to be set up for SCIM.
Before proceeding, be sure to complete the [GitLab configuration](#gitlab-configuration) process.
1. Sign in to Okta.
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index f2e9bc4954a..3bf7bd6c52c 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -11,7 +11,7 @@ It is **not** valid for the [GitLab documentation website](https://docs.gitlab.c
or [GitLab's main website](https://about.gitlab.com), as they both use
[Kramdown](https://kramdown.gettalong.org) as their Markdown engine. The documentation
website uses an extended Kramdown gem, [GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown).
-Consult the [GitLab Kramdown Guide](https://about.gitlab.com/handbook/engineering/ux/technical-writing/markdown-guide/)
+Consult the [GitLab Kramdown Guide](https://about.gitlab.com/handbook/markdown-guide/)
for a complete Kramdown reference.
NOTE: **Note:** We encourage you to view this document as [rendered by GitLab itself](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md).
diff --git a/doc/user/project/clusters/serverless/aws.md b/doc/user/project/clusters/serverless/aws.md
index f4e8ea919b9..c26f622836c 100644
--- a/doc/user/project/clusters/serverless/aws.md
+++ b/doc/user/project/clusters/serverless/aws.md
@@ -101,7 +101,7 @@ The handler definition will provision the Lambda function using the source code
The `events` declaration will create a AWS API Gateway `GET` endpoint to receive external requests and hand them over to the Lambda function via a service integration.
-You can read more about the available properties and additional configuration possibilities of the Serverless Framework here: <https://serverless.com/framework/docs/providers/aws/guide/serverless.yml/>
+You can read more about the [available properties and additional configuration possibilities](https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/) of the Serverless Framework.
#### Crafting the `.gitlab-ci.yml` file
@@ -275,7 +275,7 @@ module.exports.hello = async event => {
};
```
-For more information, see the [Your CORS and API Gateway survival guide](https://serverless.com/blog/cors-api-gateway-survival-guide/)
+For more information, see the [Your CORS and API Gateway survival guide](https://www.serverless.com/blog/cors-api-gateway-survival-guide/)
blog post written by the Serverless Framework team.
#### Writing automated tests
diff --git a/doc/user/project/import/tfvc.md b/doc/user/project/import/tfvc.md
index 9b148224e10..1c9ee7476bd 100644
--- a/doc/user/project/import/tfvc.md
+++ b/doc/user/project/import/tfvc.md
@@ -6,7 +6,7 @@ type: concepts
Team Foundation Server (TFS), renamed [Azure DevOps Server](https://azure.microsoft.com/en-us/services/devops/server/)
in 2019, is a set of tools developed by Microsoft which also includes
-[Team Foundation Version Control](https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/overview?view=azure-devops)
+[Team Foundation Version Control](https://docs.microsoft.com/en-us/azure/devops/repos/tfvc/what-is-tfvc?view=azure-devops)
(TFVC), a centralized version control system similar to Git.
In this document, we focus on the TFVC to Git migration.
diff --git a/doc/user/project/integrations/gitlab_slack_application.md b/doc/user/project/integrations/gitlab_slack_application.md
index eaeeab72dfb..7a827364d41 100644
--- a/doc/user/project/integrations/gitlab_slack_application.md
+++ b/doc/user/project/integrations/gitlab_slack_application.md
@@ -32,7 +32,7 @@ integration settings.
Keep in mind that you need to have the appropriate permissions for your Slack
team in order to be able to install a new application, read more in Slack's
-docs on [Adding an app to your team](https://slack.com/help/articles/202035138).
+docs on [Adding an app to your workspace](https://slack.com/help/articles/202035138-Add-an-app-to-your-workspace).
To enable GitLab's service for your Slack team:
diff --git a/doc/user/project/integrations/jira_cloud_configuration.md b/doc/user/project/integrations/jira_cloud_configuration.md
index 9fa92f19e4f..619c94b282b 100644
--- a/doc/user/project/integrations/jira_cloud_configuration.md
+++ b/doc/user/project/integrations/jira_cloud_configuration.md
@@ -3,7 +3,7 @@
An API token is needed when integrating with Jira Cloud, follow the steps
below to create one:
-1. Log in to <https://id.atlassian.com/manage/api-tokens> with your email address.
+1. Log in to [`id.atlassian.com`](https://id.atlassian.com/manage-profile/security/api-tokens) with your email address.
NOTE: **Note**
It is important that the user associated with this email address has *write* access
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index 58bed6613a4..0eb8cc61505 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -865,7 +865,7 @@ You can create annotations by making requests to the
#### Retention policy
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/211433) in GitLab 13.01.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211433) in GitLab 13.01.
To avoid excessive storage space consumption by stale annotations, records attached
to time periods older than two weeks are removed daily. This recurring background
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index 58efb1acc27..fa7b221ea16 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -208,12 +208,12 @@ At present, full URL references are supported. For example, if we refer to a des
somewhere with:
```markdown
-See http://gitlab.com/your-group/your-project/-/issues/123/designs/homescreen.png
+See https://gitlab.com/your-group/your-project/-/issues/123/designs/homescreen.png
```
This will be rendered as:
-> See [#123[homescreen.png]](http://gitlab.com/your-group/your-project/-/issues/123/designs/homescreen.png)
+> See [#123[homescreen.png]](https://gitlab.com/your-group/your-project/-/issues/123/designs/homescreen.png)
### Enable or disable design references **(CORE ONLY)**
diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/services_helpers.rb
index 02e60ff5db5..3d6039cacaa 100644
--- a/lib/api/helpers/services_helpers.rb
+++ b/lib/api/helpers/services_helpers.rb
@@ -583,6 +583,18 @@ module API
name: :api_url,
type: String,
desc: 'Prometheus API Base URL, like http://prometheus.example.com/'
+ },
+ {
+ required: true,
+ name: :google_iap_audience_client_id,
+ type: String,
+ desc: 'Client ID of the IAP secured resource (looks like IAP_CLIENT_ID.apps.googleusercontent.com)'
+ },
+ {
+ required: true,
+ name: :google_iap_service_account_json,
+ type: String,
+ desc: 'Contents of the credentials.json file of your service account, like: { "type": "service_account", "project_id": ... }'
}
],
'pushover' => [
diff --git a/lib/gitlab/alerting/alert.rb b/lib/gitlab/alerting/alert.rb
index 802423a93f4..dad3dabb4fc 100644
--- a/lib/gitlab/alerting/alert.rb
+++ b/lib/gitlab/alerting/alert.rb
@@ -173,7 +173,10 @@ module Gitlab
value = payload&.dig(field)
return unless value
- Time.rfc3339(value)
+ # value is a rfc3339 timestamp
+ # Timestamps from Prometheus and Alertmanager are UTC RFC3339 timestamps like: '2018-03-12T09:06:00Z' (Z represents 0 offset or UTC)
+ # .utc sets the datetime zone to `UTC`
+ Time.rfc3339(value).utc
rescue ArgumentError
end
diff --git a/lib/gitlab/auth/ldap/person.rb b/lib/gitlab/auth/ldap/person.rb
index e4a4900c37a..b3321c0b1fb 100644
--- a/lib/gitlab/auth/ldap/person.rb
+++ b/lib/gitlab/auth/ldap/person.rb
@@ -39,7 +39,7 @@ module Gitlab
*config.attributes['name'],
*config.attributes['email'],
*config.attributes['username']
- ].compact.uniq
+ ].compact.uniq.reject(&:blank?)
end
def self.normalize_dn(dn)
diff --git a/lib/gitlab/project_template.rb b/lib/gitlab/project_template.rb
index 69b311f896c..fdb3fbc03bc 100644
--- a/lib/gitlab/project_template.rb
+++ b/lib/gitlab/project_template.rb
@@ -46,10 +46,10 @@ module Gitlab
ProjectTemplate.new('android', 'Android', _('A ready-to-go template for use with Android apps.'), 'https://gitlab.com/gitlab-org/project-templates/android', 'illustrations/logos/android.svg'),
ProjectTemplate.new('gomicro', 'Go Micro', _('Go Micro is a framework for micro service development.'), 'https://gitlab.com/gitlab-org/project-templates/go-micro', 'illustrations/logos/gomicro.svg'),
ProjectTemplate.new('gatsby', 'Pages/Gatsby', _('Everything you need to create a GitLab Pages site using Gatsby.'), 'https://gitlab.com/pages/gatsby'),
- ProjectTemplate.new('hugo', 'Pages/Hugo', _('Everything you need to create a GitLab Pages site using Hugo.'), 'https://gitlab.com/pages/hugo'),
+ ProjectTemplate.new('hugo', 'Pages/Hugo', _('Everything you need to create a GitLab Pages site using Hugo.'), 'https://gitlab.com/pages/hugo', 'illustrations/logos/hugo.svg'),
ProjectTemplate.new('jekyll', 'Pages/Jekyll', _('Everything you need to create a GitLab Pages site using Jekyll.'), 'https://gitlab.com/pages/jekyll', 'illustrations/logos/jekyll.svg'),
ProjectTemplate.new('plainhtml', 'Pages/Plain HTML', _('Everything you need to create a GitLab Pages site using plain HTML.'), 'https://gitlab.com/pages/plain-html'),
- ProjectTemplate.new('gitbook', 'Pages/GitBook', _('Everything you need to create a GitLab Pages site using GitBook.'), 'https://gitlab.com/pages/gitbook'),
+ ProjectTemplate.new('gitbook', 'Pages/GitBook', _('Everything you need to create a GitLab Pages site using GitBook.'), 'https://gitlab.com/pages/gitbook', 'illustrations/logos/gitbook.svg'),
ProjectTemplate.new('hexo', 'Pages/Hexo', _('Everything you need to create a GitLab Pages site using Hexo.'), 'https://gitlab.com/pages/hexo', 'illustrations/logos/hexo.svg'),
ProjectTemplate.new('sse_middleman', 'Static Site Editor/Middleman', _('Middleman project with Static Site Editor support'), 'https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman'),
ProjectTemplate.new('nfhugo', 'Netlify/Hugo', _('A Hugo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features.'), 'https://gitlab.com/pages/nfhugo', 'illustrations/logos/netlify.svg'),
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 8b15fead5bb..4baf53d88d9 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -17475,12 +17475,18 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
+msgid "PrometheusService|Client ID of the IAP secured resource (looks like IAP_CLIENT_ID.apps.googleusercontent.com)"
+msgstr ""
+
msgid "PrometheusService|Common metrics"
msgstr ""
msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
msgstr ""
+msgid "PrometheusService|Contents of the credentials.json file of your service account, like: { \"type\": \"service_account\", \"project_id\": ... }"
+msgstr ""
+
msgid "PrometheusService|Custom metrics"
msgstr ""
@@ -20161,6 +20167,14 @@ msgid_plural "Showing %d events"
msgstr[0] ""
msgstr[1] ""
+msgid "Showing %{count} of %{total} projects"
+msgstr ""
+
+msgid "Showing %{count} project"
+msgid_plural "Showing %{count} projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Showing %{limit} of %{total_count} issues. "
msgstr ""
diff --git a/package.json b/package.json
index 3c1abb083dd..c1f20c3fc8d 100644
--- a/package.json
+++ b/package.json
@@ -102,6 +102,7 @@
"lodash": "^4.17.15",
"marked": "^0.3.12",
"mermaid": "^8.5.1",
+ "mersenne-twister": "1.1.0",
"mitt": "^1.2.0",
"monaco-editor": "^0.18.1",
"monaco-editor-webpack-plugin": "^1.7.0",
@@ -120,6 +121,7 @@
"sortablejs": "^1.10.2",
"sql.js": "^0.4.0",
"stickyfilljs": "^2.1.0",
+ "string-hash": "1.1.3",
"style-loader": "^1.1.3",
"svg4everybody": "2.1.9",
"swagger-ui-dist": "^3.24.3",
@@ -133,6 +135,7 @@
"tributejs": "4.1.3",
"unfetch": "^4.1.0",
"url-loader": "^3.0.0",
+ "uuid": "8.1.0",
"visibilityjs": "^1.2.4",
"vue": "^2.6.10",
"vue-apollo": "^3.0.3",
diff --git a/spec/frontend/diffs/utils/uuids_spec.js b/spec/frontend/diffs/utils/uuids_spec.js
new file mode 100644
index 00000000000..79d3ebadd4f
--- /dev/null
+++ b/spec/frontend/diffs/utils/uuids_spec.js
@@ -0,0 +1,92 @@
+import { uuids } from '~/diffs/utils/uuids';
+
+const HEX = /[a-f0-9]/i;
+const HEX_RE = HEX.source;
+const UUIDV4 = new RegExp(
+ `${HEX_RE}{8}-${HEX_RE}{4}-4${HEX_RE}{3}-[89ab]${HEX_RE}{3}-${HEX_RE}{12}`,
+ 'i',
+);
+
+describe('UUIDs Util', () => {
+ describe('uuids', () => {
+ const SEQUENCE_FOR_GITLAB_SEED = [
+ 'a1826a44-316c-480e-a93d-8cdfeb36617c',
+ 'e049db1f-a4cf-4cba-aa60-6d95e3b547dc',
+ '6e3c737c-13a7-4380-b17d-601f187d7e69',
+ 'bee5cc7f-c486-45c0-8ad3-d1ac5402632d',
+ 'af248c9f-a3a6-4d4f-a311-fe151ffab25a',
+ ];
+ const SEQUENCE_FOR_12345_SEED = [
+ 'edfb51e2-e3e1-4de5-90fd-fd1d21760881',
+ '2f154da4-0a2d-4da9-b45e-0ffed391517e',
+ '91566d65-8836-4222-9875-9e1df4d0bb01',
+ 'f6ea6c76-7640-4d71-a736-9d3bec7a1a8e',
+ 'bfb85869-5fb9-4c5b-a750-5af727ac5576',
+ ];
+
+ it('returns version 4 UUIDs', () => {
+ expect(uuids()[0]).toMatch(UUIDV4);
+ });
+
+ it('outputs an array of UUIDs', () => {
+ const ids = uuids({ count: 11 });
+
+ expect(ids.length).toEqual(11);
+ expect(ids.every(id => UUIDV4.test(id))).toEqual(true);
+ });
+
+ it.each`
+ seeds | uuid
+ ${['some', 'special', 'seed']} | ${'6fa53e51-0f70-4072-9c84-1c1eee1b9934'}
+ ${['magic']} | ${'fafae8cd-7083-44f3-b82d-43b30bd27486'}
+ ${['seeded']} | ${'e06ed291-46c5-4e42-836b-e7c772d48b49'}
+ ${['GitLab']} | ${'a1826a44-316c-480e-a93d-8cdfeb36617c'}
+ ${['JavaScript']} | ${'12dfb297-1560-4c38-9775-7178ef8472fb'}
+ ${[99, 169834, 2619]} | ${'3ecc8ad6-5b7c-4c9b-94a8-c7271c2fa083'}
+ ${[12]} | ${'2777374b-723b-469b-bd73-e586df964cfd'}
+ ${[9876, 'mixed!', 7654]} | ${'865212e0-4a16-4934-96f9-103cf36a6931'}
+ ${[123, 1234, 12345, 6]} | ${'40aa2ee6-0a11-4e67-8f09-72f5eba04244'}
+ ${[0]} | ${'8c7f0aac-97c4-4a2f-b716-a675d821ccc0'}
+ `(
+ 'should always output the UUID $uuid when the options.seeds argument is $seeds',
+ ({ uuid, seeds }) => {
+ expect(uuids({ seeds })[0]).toEqual(uuid);
+ },
+ );
+
+ describe('unseeded UUID randomness', () => {
+ const nonRandom = Array(6)
+ .fill(0)
+ .map((_, i) => uuids({ seeds: [i] })[0]);
+ const random = uuids({ count: 6 });
+ const moreRandom = uuids({ count: 6 });
+
+ it('is different from a seeded result', () => {
+ random.forEach((id, i) => {
+ expect(id).not.toEqual(nonRandom[i]);
+ });
+ });
+
+ it('is different from other random results', () => {
+ random.forEach((id, i) => {
+ expect(id).not.toEqual(moreRandom[i]);
+ });
+ });
+
+ it('never produces any duplicates', () => {
+ expect(new Set(random).size).toEqual(random.length);
+ });
+ });
+
+ it.each`
+ seed | sequence
+ ${'GitLab'} | ${SEQUENCE_FOR_GITLAB_SEED}
+ ${12345} | ${SEQUENCE_FOR_12345_SEED}
+ `(
+ 'should output the same sequence of UUIDs for the given seed "$seed"',
+ ({ seed, sequence }) => {
+ expect(uuids({ seeds: [seed], count: 5 })).toEqual(sequence);
+ },
+ );
+ });
+});
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index 5e2d2847cad..7bb4c68b4cd 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -16,6 +16,7 @@ import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue'
import EmptyState from '~/monitoring/components/empty_state.vue';
import GroupEmptyState from '~/monitoring/components/group_empty_state.vue';
import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
+import LinksSection from '~/monitoring/components/links_section.vue';
import { createStore } from '~/monitoring/stores';
import * as types from '~/monitoring/stores/mutation_types';
import {
@@ -24,6 +25,7 @@ import {
setMetricResult,
setupStoreWithData,
setupStoreWithVariable,
+ setupStoreWithLinks,
} from '../store_utils';
import { environmentData, dashboardGitResponse, propsData } from '../mock_data';
import { metricsDashboardViewModel, metricsDashboardPanelCount } from '../fixture_data';
@@ -483,6 +485,21 @@ describe('Dashboard', () => {
});
});
+ describe('links section', () => {
+ beforeEach(() => {
+ createShallowWrapper({ hasMetrics: true });
+ setupStoreWithData(store);
+ setupStoreWithLinks(store);
+
+ return wrapper.vm.$nextTick();
+ });
+
+ it('shows the links section', () => {
+ expect(wrapper.vm.shouldShowLinksSection).toBe(true);
+ expect(wrapper.find(LinksSection)).toExist();
+ });
+ });
+
describe('single panel expands to "full screen" mode', () => {
const findExpandedPanel = () => wrapper.find({ ref: 'expandedPanel' });
diff --git a/spec/frontend/monitoring/store/utils_spec.js b/spec/frontend/monitoring/store/utils_spec.js
index f6c2b5b9682..02cdd3d7f41 100644
--- a/spec/frontend/monitoring/store/utils_spec.js
+++ b/spec/frontend/monitoring/store/utils_spec.js
@@ -16,6 +16,8 @@ describe('mapToDashboardViewModel', () => {
expect(mapToDashboardViewModel({})).toEqual({
dashboard: '',
panelGroups: [],
+ links: [],
+ variables: {},
});
});
@@ -44,6 +46,8 @@ describe('mapToDashboardViewModel', () => {
expect(mapToDashboardViewModel(response)).toEqual({
dashboard: 'Dashboard Name',
+ links: [],
+ variables: {},
panelGroups: [
{
group: 'Group 1',
@@ -76,6 +80,8 @@ describe('mapToDashboardViewModel', () => {
it('key', () => {
const response = {
dashboard: 'Dashboard Name',
+ links: [],
+ variables: {},
panel_groups: [
{
group: 'Group A',
diff --git a/spec/frontend/monitoring/store_utils.js b/spec/frontend/monitoring/store_utils.js
index 8ac8b4367c6..eb2578aa9db 100644
--- a/spec/frontend/monitoring/store_utils.js
+++ b/spec/frontend/monitoring/store_utils.js
@@ -38,6 +38,18 @@ export const setupStoreWithVariable = store => {
});
};
+export const setupStoreWithLinks = store => {
+ store.commit(`monitoringDashboard/${types.RECEIVE_METRICS_DASHBOARD_SUCCESS}`, {
+ ...metricsDashboardPayload,
+ links: [
+ {
+ title: 'GitLab Website',
+ url: `https://gitlab.com/website`,
+ },
+ ],
+ });
+};
+
export const setupStoreWithData = store => {
setupAllDashboards(store);
setupStoreWithDashboard(store);
diff --git a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
index 691e98236e4..6d1ebe85aa0 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
@@ -110,4 +110,26 @@ describe('ProjectSelector component', () => {
);
});
});
+
+ describe('the search results legend', () => {
+ it.each`
+ count | total | expected
+ ${0} | ${0} | ${'Showing 0 projects'}
+ ${1} | ${0} | ${'Showing 1 project'}
+ ${2} | ${0} | ${'Showing 2 projects'}
+ ${2} | ${3} | ${'Showing 2 of 3 projects'}
+ `(
+ 'is "$expected" given $count results are showing out of $total',
+ ({ count, total, expected }) => {
+ wrapper.setProps({
+ projectSearchResults: searchResults.slice(0, count),
+ totalResults: total,
+ });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.text()).toContain(expected);
+ });
+ },
+ );
+ });
});
diff --git a/spec/initializers/google_api_client_spec.rb b/spec/initializers/google_api_client_spec.rb
deleted file mode 100644
index 44a1bc0836c..00000000000
--- a/spec/initializers/google_api_client_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe './config/initializers/google_api_client.rb' do
- subject { Google::Apis::ContainerV1beta1 }
-
- it 'is needed' do |example|
- is_expected.not_to be_const_defined(:CloudRunConfig),
- <<-MSG.strip_heredoc
- The google-api-client gem has been upgraded!
- Remove:
- #{example.example_group.description}
- #{example.file_path}
- MSG
- end
-end
diff --git a/spec/lib/gitlab/auth/ldap/person_spec.rb b/spec/lib/gitlab/auth/ldap/person_spec.rb
index e90917cfce1..403a48d40ef 100644
--- a/spec/lib/gitlab/auth/ldap/person_spec.rb
+++ b/spec/lib/gitlab/auth/ldap/person_spec.rb
@@ -57,14 +57,17 @@ describe Gitlab::Auth::Ldap::Person do
'attributes' => {
'name' => 'cn',
'email' => 'mail',
- 'username' => %w(uid mail memberof)
+ 'username' => %w(uid mail),
+ 'first_name' => ''
}
}
)
config = Gitlab::Auth::Ldap::Config.new('ldapmain')
ldap_attributes = described_class.ldap_attributes(config)
- expect(ldap_attributes).to match_array(%w(dn uid cn mail memberof))
+ expect(ldap_attributes).to include('dn', 'uid', 'cn', 'mail')
+ expect(ldap_attributes).to be_present
+ expect(ldap_attributes.uniq!).to eq(nil)
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 6d903ce5fc9..432190b4318 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -599,6 +599,7 @@ design: &design
- versions
- notes
- user_mentions
+- events
designs: *design
actions:
- design
diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb
index a85dbe3a7df..ec5bef92cde 100644
--- a/spec/models/project_services/prometheus_service_spec.rb
+++ b/spec/models/project_services/prometheus_service_spec.rb
@@ -252,6 +252,26 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
end
end
end
+
+ context 'behind IAP' do
+ let(:manual_configuration) { true }
+
+ before do
+ # dummy private key generated only for this test to pass openssl validation
+ service.google_iap_service_account_json = '{"type":"service_account","private_key":"-----BEGIN RSA PRIVATE KEY-----\nMIIBOAIBAAJAU85LgUY5o6j6j/07GMLCNUcWJOBA1buZnNgKELayA6mSsHrIv31J\nY8kS+9WzGPQninea7DcM4hHA7smMgQD1BwIDAQABAkAqKxMy6PL3tn7dFL43p0ex\nJyOtSmlVIiAZG1t1LXhE/uoLpYi5DnbYqGgu0oih+7nzLY/dXpNpXUmiRMOUEKmB\nAiEAoTi2rBXbrLSi2C+H7M/nTOjMQQDuZ8Wr4uWpKcjYJTMCIQCFEskL565oFl/7\nRRQVH+cARrAsAAoJSbrOBAvYZ0PI3QIgIEFwis10vgEF86rOzxppdIG/G+JL0IdD\n9IluZuXAGPECIGUo7qSaLr75o2VEEgwtAFH5aptIPFjrL5LFCKwtdB4RAiAYZgFV\nHCMmaooAw/eELuMoMWNYmujZ7VaAnOewGDW0uw==\n-----END RSA PRIVATE KEY-----\n"}'
+ service.google_iap_audience_client_id = "IAP_CLIENT_ID.apps.googleusercontent.com"
+
+ stub_request(:post, "https://oauth2.googleapis.com/token").to_return(status: 200, body: '{"id_token": "FOO"}', headers: { 'Content-Type': 'application/json; charset=UTF-8' })
+
+ stub_feature_flags(prometheus_service_iap_auth: true)
+ end
+
+ it 'includes the authorization header' do
+ expect(service.prometheus_client).not_to be_nil
+ expect(service.prometheus_client.send(:options)).to have_key(:headers)
+ expect(service.prometheus_client.send(:options)[:headers]).to eq(authorization: "Bearer FOO")
+ end
+ end
end
describe '#prometheus_available?' do
@@ -457,9 +477,33 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
}
]
end
+ let(:feature_flagged_fields) do
+ [
+ {
+ type: 'text',
+ name: 'google_iap_audience_client_id',
+ title: 'Google IAP Audience Client ID',
+ placeholder: s_('PrometheusService|Client ID of the IAP secured resource (looks like IAP_CLIENT_ID.apps.googleusercontent.com)'),
+ required: false
+ },
+ {
+ type: 'textarea',
+ name: 'google_iap_service_account_json',
+ title: 'Google IAP Service Account JSON',
+ placeholder: s_('PrometheusService|Contents of the credentials.json file of your service account, like: { "type": "service_account", "project_id": ... }'),
+ required: false
+ }
+ ]
+ end
it 'returns fields' do
+ stub_feature_flags(prometheus_service_iap_auth: false)
expect(service.fields).to eq(expected_fields)
end
+
+ it 'returns fields with feature flag on' do
+ stub_feature_flags(prometheus_service_iap_auth: true)
+ expect(service.fields).to eq(expected_fields + feature_flagged_fields)
+ end
end
end
diff --git a/spec/presenters/projects/prometheus/alert_presenter_spec.rb b/spec/presenters/projects/prometheus/alert_presenter_spec.rb
index 967a0fb2c09..8ee5a4d7b3f 100644
--- a/spec/presenters/projects/prometheus/alert_presenter_spec.rb
+++ b/spec/presenters/projects/prometheus/alert_presenter_spec.rb
@@ -24,18 +24,25 @@ describe Projects::Prometheus::AlertPresenter do
it { is_expected.to eq(project.full_path) }
end
- describe '#starts_at' do
- subject { presenter.starts_at }
+ describe '#start_time' do
+ subject { presenter.start_time }
+
+ let(:starts_at) { '2020-10-31T14:02:04Z' }
before do
payload['startsAt'] = starts_at
end
- context 'with valid datetime' do
- let(:datetime) { Time.now }
- let(:starts_at) { datetime.rfc3339 }
+ context 'with valid utc datetime' do
+ it { is_expected.to eq('31 October 2020, 2:02PM (UTC)') }
- it { is_expected.to eq(datetime.rfc3339) }
+ context 'with admin time zone not UTC' do
+ before do
+ allow(Time).to receive(:zone).and_return(ActiveSupport::TimeZone.new('Perth'))
+ end
+
+ it { is_expected.to eq('31 October 2020, 2:02PM (UTC)') }
+ end
end
context 'with invalid datetime' do
@@ -56,7 +63,7 @@ describe Projects::Prometheus::AlertPresenter do
<<~MARKDOWN.chomp
#### Summary
- **Start time:** #{presenter.starts_at}
+ **Start time:** #{presenter.start_time}
MARKDOWN
)
@@ -73,7 +80,7 @@ describe Projects::Prometheus::AlertPresenter do
<<~MARKDOWN.chomp
#### Summary
- **Start time:** #{presenter.starts_at}
+ **Start time:** #{presenter.start_time}
#### Alert Details
@@ -94,7 +101,7 @@ describe Projects::Prometheus::AlertPresenter do
<<~MARKDOWN.chomp
#### Summary
- **Start time:** #{presenter.starts_at}#{markdown_line_break}
+ **Start time:** #{presenter.start_time}#{markdown_line_break}
**full_query:** `query`
MARKDOWN
@@ -122,7 +129,7 @@ describe Projects::Prometheus::AlertPresenter do
<<~MARKDOWN.chomp
#### Summary
- **Start time:** #{presenter.starts_at}#{markdown_line_break}
+ **Start time:** #{presenter.start_time}#{markdown_line_break}
**Service:** service_name#{markdown_line_break}
**Monitoring tool:** monitoring_tool_name#{markdown_line_break}
**Hosts:** http://localhost:3000 http://localhost:3001
@@ -144,7 +151,7 @@ describe Projects::Prometheus::AlertPresenter do
<<~MARKDOWN.chomp
#### Summary
- **Start time:** #{presenter.starts_at}#{markdown_line_break}
+ **Start time:** #{presenter.start_time}#{markdown_line_break}
**Hosts:** http://localhost:3000
MARKDOWN
@@ -161,7 +168,7 @@ describe Projects::Prometheus::AlertPresenter do
<<~MARKDOWN.chomp
#### Summary
- **Start time:** #{presenter.starts_at}#{markdown_line_break}
+ **Start time:** #{presenter.start_time}#{markdown_line_break}
**full_query:** `avg(metric) > 1.0`
[](#{url})
@@ -253,7 +260,7 @@ describe Projects::Prometheus::AlertPresenter do
<<~MARKDOWN.chomp
#### Summary
- **Start time:** #{presenter.starts_at}#{markdown_line_break}
+ **Start time:** #{presenter.start_time}#{markdown_line_break}
**full_query:** `avg(metric) > 1.0`
MARKDOWN
@@ -280,7 +287,7 @@ describe Projects::Prometheus::AlertPresenter do
<<~MARKDOWN.chomp
#### Summary
- **Start time:** #{presenter.starts_at}
+ **Start time:** #{presenter.start_time}
MARKDOWN
end
diff --git a/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb
new file mode 100644
index 00000000000..217f538c53e
--- /dev/null
+++ b/spec/requests/api/graphql/mutations/metrics/dashboard/annotations/delete_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Mutations::Metrics::Dashboard::Annotations::Delete do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:project) { create(:project, :private, :repository) }
+ let_it_be(:environment) { create(:environment, project: project) }
+ let_it_be(:annotation) { create(:metrics_dashboard_annotation, environment: environment) }
+ let(:mutation) do
+ variables = {
+ id: GitlabSchema.id_from_object(annotation).to_s
+ }
+
+ graphql_mutation(:delete_annotation, variables)
+ end
+
+ def mutation_response
+ graphql_mutation_response(:delete_annotation)
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:delete_metrics_dashboard_annotation) }
+
+ context 'when the user has permission to delete the annotation' do
+ before do
+ project.add_developer(current_user)
+ end
+
+ context 'with valid params' do
+ it 'deletes the annotation' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.to change { Metrics::Dashboard::Annotation.count }.by(-1)
+ end
+ end
+
+ context 'with invalid params' do
+ let(:mutation) do
+ variables = {
+ id: 'invalid_id'
+ }
+
+ graphql_mutation(:delete_annotation, variables)
+ end
+
+ it_behaves_like 'a mutation that returns top-level errors', errors: ['invalid_id is not a valid GitLab id.']
+ end
+
+ context 'when the delete fails' do
+ let(:service_response) { { message: 'Annotation has not been deleted', status: :error, last_step: :delete } }
+
+ before do
+ allow_next_instance_of(Metrics::Dashboard::Annotations::DeleteService) do |delete_service|
+ allow(delete_service).to receive(:execute).and_return(service_response)
+ end
+ end
+ it 'returns the error' do
+ post_graphql_mutation(mutation, current_user: current_user)
+
+ expect(mutation_response['errors']).to eq([service_response[:message]])
+ end
+ end
+ end
+
+ context 'when the user does not have permission to delete the annotation' do
+ before do
+ project.add_reporter(current_user)
+ end
+
+ it_behaves_like 'a mutation that returns top-level errors', errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR]
+
+ it 'does not delete the annotation' do
+ expect do
+ post_graphql_mutation(mutation, current_user: current_user)
+ end.not_to change { Metrics::Dashboard::Annotation.count }
+ end
+ end
+end
diff --git a/spec/services/design_management/delete_designs_service_spec.rb b/spec/services/design_management/delete_designs_service_spec.rb
index 2c0c1570cb4..bf5d6b443e6 100644
--- a/spec/services/design_management/delete_designs_service_spec.rb
+++ b/spec/services/design_management/delete_designs_service_spec.rb
@@ -56,6 +56,10 @@ describe DesignManagement::DeleteDesignsService do
let(:enabled) { false }
it_behaves_like "a service error"
+
+ it 'does not create any events in the activity stream' do
+ expect { run_service rescue nil }.not_to change { Event.count }
+ end
end
context "when the feature is available" do
@@ -72,7 +76,9 @@ describe DesignManagement::DeleteDesignsService do
it 'does not log any events' do
counter = ::Gitlab::UsageDataCounters::DesignsCounter
- expect { run_service rescue nil }.not_to change { counter.totals }
+
+ expect { run_service rescue nil }
+ .not_to change { [counter.totals, Event.count] }
end
end
@@ -92,6 +98,12 @@ describe DesignManagement::DeleteDesignsService do
expect { run_service }.to change { counter.read(:delete) }.by(1)
end
+ it 'creates an event in the activity stream' do
+ expect { run_service }
+ .to change { Event.count }.by(1)
+ .and change { Event.destroyed_action.for_design.count }.by(1)
+ end
+
it 'informs the new-version-worker' do
expect(::DesignManagement::NewVersionWorker).to receive(:perform_async).with(Integer)
@@ -129,14 +141,14 @@ describe DesignManagement::DeleteDesignsService do
let!(:designs) { create_designs(2) }
- it 'removes those designs' do
+ it 'makes the correct changes' do
+ counter = ::Gitlab::UsageDataCounters::DesignsCounter
+
expect { run_service }
.to change { issue.designs.current.count }.from(3).to(1)
- end
-
- it 'logs the correct number of deletion events' do
- counter = ::Gitlab::UsageDataCounters::DesignsCounter
- expect { run_service }.to change { counter.read(:delete) }.by(2)
+ .and change { counter.read(:delete) }.by(2)
+ .and change { Event.count }.by(2)
+ .and change { Event.destroyed_action.for_design.count }.by(2)
end
it_behaves_like "a success"
diff --git a/spec/services/design_management/save_designs_service_spec.rb b/spec/services/design_management/save_designs_service_spec.rb
index 013d5473860..3be3ac9daca 100644
--- a/spec/services/design_management/save_designs_service_spec.rb
+++ b/spec/services/design_management/save_designs_service_spec.rb
@@ -65,6 +65,10 @@ describe DesignManagement::SaveDesignsService do
end
it_behaves_like 'a service error'
+
+ it 'does not create an event in the activity stream' do
+ expect { run_service }.not_to change { Event.count }
+ end
end
context 'when the feature is available' do
@@ -89,6 +93,12 @@ describe DesignManagement::SaveDesignsService do
expect { run_service }.to change { counter.read(:create) }.by(1)
end
+ it 'creates an event in the activity stream' do
+ expect { run_service }
+ .to change { Event.count }.by(1)
+ .and change { Event.for_design.created_action.count }.by(1)
+ end
+
it 'creates a commit in the repository' do
run_service
@@ -166,9 +176,12 @@ describe DesignManagement::SaveDesignsService do
expect(updated_designs.first.versions.size).to eq(2)
end
- it 'increments the update counter' do
+ it 'records the correct events' do
counter = Gitlab::UsageDataCounters::DesignsCounter
- expect { run_service }.to change { counter.read(:update) }.by 1
+ expect { run_service }
+ .to change { counter.read(:update) }.by(1)
+ .and change { Event.count }.by(1)
+ .and change { Event.for_design.updated_action.count }.by(1)
end
context 'when uploading a new design' do
@@ -217,6 +230,14 @@ describe DesignManagement::SaveDesignsService do
.and change { counter.read(:update) }.by(1)
end
+ it 'creates the correct activity stream events' do
+ expect { run_service }
+ .to change { Event.count }.by(2)
+ .and change { Event.for_design.count }.by(2)
+ .and change { Event.created_action.count }.by(1)
+ .and change { Event.updated_action.count }.by(1)
+ end
+
it 'creates a single commit' do
commit_count = -> do
design_repository.expire_all_method_caches
diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb
index a43678626f7..73c089334ed 100644
--- a/spec/services/event_create_service_spec.rb
+++ b/spec/services/event_create_service_spec.rb
@@ -5,6 +5,9 @@ require 'spec_helper'
describe EventCreateService do
let(:service) { described_class.new }
+ let_it_be(:user, reload: true) { create :user }
+ let_it_be(:project) { create(:project) }
+
describe 'Issues' do
describe '#open_issue' do
let(:issue) { create(:issue) }
@@ -87,8 +90,6 @@ describe EventCreateService do
end
describe 'Milestone' do
- let(:user) { create :user }
-
describe '#open_milestone' do
let(:milestone) { create(:milestone) }
@@ -210,9 +211,6 @@ describe EventCreateService do
end
describe '#push', :clean_gitlab_redis_shared_state do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
-
let(:push_data) do
{
commits: [
@@ -234,9 +232,6 @@ describe EventCreateService do
end
describe '#bulk_push', :clean_gitlab_redis_shared_state do
- let(:project) { create(:project) }
- let(:user) { create(:user) }
-
let(:push_data) do
{
action: :created,
@@ -251,9 +246,6 @@ describe EventCreateService do
end
describe 'Project' do
- let(:user) { create :user }
- let(:project) { create(:project) }
-
describe '#join_project' do
subject { service.join_project(project, user) }
@@ -268,4 +260,81 @@ describe EventCreateService do
it { expect { subject }.to change { Event.count }.from(0).to(1) }
end
end
+
+ describe 'design events' do
+ let_it_be(:design) { create(:design, project: project) }
+ let_it_be(:author) { user }
+
+ shared_examples 'feature flag gated multiple event creation' do
+ context 'the feature flag is off' do
+ before do
+ stub_feature_flags(design_activity_events: false)
+ end
+
+ specify { expect(result).to be_empty }
+ specify { expect { result }.not_to change { Event.count } }
+ specify { expect { result }.not_to exceed_query_limit(0) }
+ end
+
+ context 'the feature flag is enabled for a single project' do
+ before do
+ stub_feature_flags(design_activity_events: project)
+ end
+
+ specify { expect(result).not_to be_empty }
+ specify { expect { result }.to change { Event.count }.by(1) }
+ end
+ end
+
+ describe '#save_designs' do
+ let_it_be(:updated) { create_list(:design, 5) }
+ let_it_be(:created) { create_list(:design, 3) }
+
+ let(:result) { service.save_designs(author, create: created, update: updated) }
+
+ specify { expect { result }.to change { Event.count }.by(8) }
+
+ specify { expect { result }.not_to exceed_query_limit(1) }
+
+ it 'creates 3 created design events' do
+ ids = result.pluck('id')
+ events = Event.created_action.where(id: ids)
+
+ expect(events.map(&:design)).to match_array(created)
+ end
+
+ it 'creates 5 created design events' do
+ ids = result.pluck('id')
+ events = Event.updated_action.where(id: ids)
+
+ expect(events.map(&:design)).to match_array(updated)
+ end
+
+ it_behaves_like 'feature flag gated multiple event creation' do
+ let(:project) { created.first.project }
+ end
+ end
+
+ describe '#destroy_designs' do
+ let_it_be(:designs) { create_list(:design, 5) }
+ let_it_be(:author) { create(:user) }
+
+ let(:result) { service.destroy_designs(designs, author) }
+
+ specify { expect { result }.to change { Event.count }.by(5) }
+
+ specify { expect { result }.not_to exceed_query_limit(1) }
+
+ it 'creates 5 destroyed design events' do
+ ids = result.pluck('id')
+ events = Event.destroyed_action.where(id: ids)
+
+ expect(events.map(&:design)).to match_array(designs)
+ end
+
+ it_behaves_like 'feature flag gated multiple event creation' do
+ let(:project) { designs.first.project }
+ end
+ end
+ end
end
diff --git a/yarn.lock b/yarn.lock
index 542bd369c14..ef03db616ce 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7774,6 +7774,11 @@ mermaid@^8.5.1:
moment-mini "^2.22.1"
scope-css "^1.2.1"
+mersenne-twister@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/mersenne-twister/-/mersenne-twister-1.1.0.tgz#f916618ee43d7179efcf641bec4531eb9670978a"
+ integrity sha1-+RZhjuQ9cXnvz2Qb7EUx65Zwl4o=
+
methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
@@ -10629,6 +10634,11 @@ streamroller@^1.0.6:
fs-extra "^7.0.1"
lodash "^4.17.14"
+string-hash@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b"
+ integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=
+
string-length@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
@@ -11687,6 +11697,11 @@ uuid@3.3.2, uuid@^3.0.1, uuid@^3.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
+uuid@8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d"
+ integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg==
+
v8-compile-cache@2.0.3, v8-compile-cache@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe"