diff --git a/.rubocop.yml b/.rubocop.yml index 60012c1b96d..9b5ed0a38c3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -162,13 +162,16 @@ Naming/FileName: - SSE - JWT - HLL - - VSCode - GPG - OTP - GID - AR - RSpec - - Javascript + - ECDSA + - ED25519 + - GitLab + - JavaScript + - VSCode # default ones: - CLI - DSL diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml index f66b42e6544..c460dbe7fe1 100644 --- a/.rubocop_manual_todo.yml +++ b/.rubocop_manual_todo.yml @@ -2597,76 +2597,6 @@ Rails/IncludeUrlHelper: - 'spec/lib/banzai/filter/reference_redactor_filter_spec.rb' - 'spec/lib/banzai/reference_redactor_spec.rb' -# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/343244 -Naming/FileName: - Exclude: - - 'app/controllers/concerns/clientside_preview_csp.rb' - - 'app/controllers/concerns/one_trust_csp.rb' - - 'app/controllers/concerns/static_object_external_storage_csp.rb' - - 'app/models/blob_viewer/csv.rb' - - 'app/views/issues/_issues_calendar.ics.ruby' - - 'ee/app/models/dast/branch.rb' - - 'ee/app/models/sca.rb' - - 'ee/lib/ee/gitlab/usage_data_counters/hll_redis_counter.rb' - - 'ee/lib/elastic/v12p1/application_class_proxy.rb' - - 'ee/lib/elastic/v12p1/application_instance_proxy.rb' - - 'ee/lib/elastic/v12p1/config.rb' - - 'ee/lib/elastic/v12p1/issue_class_proxy.rb' - - 'ee/lib/elastic/v12p1/issue_instance_proxy.rb' - - 'ee/lib/elastic/v12p1/merge_request_class_proxy.rb' - - 'ee/lib/elastic/v12p1/merge_request_instance_proxy.rb' - - 'ee/lib/elastic/v12p1/milestone_class_proxy.rb' - - 'ee/lib/elastic/v12p1/milestone_instance_proxy.rb' - - 'ee/lib/elastic/v12p1/note_class_proxy.rb' - - 'ee/lib/elastic/v12p1/note_instance_proxy.rb' - - 'ee/lib/elastic/v12p1/project_class_proxy.rb' - - 'ee/lib/elastic/v12p1/project_instance_proxy.rb' - - 'ee/lib/elastic/v12p1/project_wiki_class_proxy.rb' - - 'ee/lib/elastic/v12p1/project_wiki_instance_proxy.rb' - - 'ee/lib/elastic/v12p1/repository_class_proxy.rb' - - 'ee/lib/elastic/v12p1/repository_instance_proxy.rb' - - 'ee/lib/elastic/v12p1/routing.rb' - - 'ee/lib/elastic/v12p1/snippet_class_proxy.rb' - - 'ee/lib/elastic/v12p1/snippet_instance_proxy.rb' - - 'ee/lib/gitlab/auth/smartcard/san_extension.rb' - - 'ee/lib/gitlab/cidr.rb' - - 'ee/lib/gitlab/elastic/bool_expr.rb' - - 'ee/lib/gitlab/spdx/catalogue.rb' - - 'ee/lib/gitlab/spdx/catalogue_gateway.rb' - - 'ee/lib/gitlab/spdx/license.rb' - - 'ee/lib/gitlab/status_page/storage/object.rb' - - 'haml_lint/inline_javascript.rb' - - 'lib/api/entities/mr_note.rb' - - 'lib/api/helpers/sse_helpers.rb' - - 'lib/gitlab/ci/pipeline/chain/command.rb' - - 'lib/gitlab/database/migrations/observation.rb' - - 'lib/gitlab/health_checks/metric.rb' - - 'lib/gitlab/health_checks/probes/status.rb' - - 'lib/gitlab/health_checks/result.rb' - - 'lib/gitlab/jwt_token.rb' - - 'lib/gitlab/middleware/release_env.rb' - - 'lib/gitlab/redis/hll.rb' - - 'lib/gitlab/slash_commands/result.rb' - - 'lib/gitlab/template_parser/ast.rb' - - 'lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb' - - 'lib/gitlab/usage_data_counters/hll_redis_counter.rb' - - 'lib/gitlab/usage_data_counters/vs_code_extension_activity_unique_counter.rb' - - 'qa/qa/fixtures/auto_devops_rack/config.ru' - - 'qa/qa/resource/user_gpg.rb' - - 'qa/qa/runtime/gpg.rb' - - 'qa/qa/runtime/key/ecdsa.rb' - - 'qa/qa/runtime/key/ed25519.rb' - - 'qa/qa/support/otp.rb' - - 'qa/qa/tools/initialize_gitlab_auth.rb' - - 'rubocop/cop/gitlab/change_timzone.rb' - - 'rubocop/cop/gitlab/keys-first-and-values-first.rb' - - 'rubocop/cop/graphql/gid_expected_type.rb' - - 'rubocop/cop/performance/ar_count_each.rb' - - 'rubocop/cop/performance/ar_exists_and_present_blank.rb' - - 'rubocop/rubocop.rb' - - 'tooling/lib/tooling/images.rb' - - 'tooling/lib/tooling/parallel_rspec_runner.rb' - # TODO issue: https://gitlab.com/gitlab-org/gitlab/-/issues/344279 Style/OpenStructUse: Exclude: diff --git a/app/assets/javascripts/access_tokens/index.js b/app/assets/javascripts/access_tokens/index.js index 2cd3a8f12ee..7f5f0403de6 100644 --- a/app/assets/javascripts/access_tokens/index.js +++ b/app/assets/javascripts/access_tokens/index.js @@ -49,7 +49,7 @@ export const initProjectsField = () => { { default: createDefaultClient }, ]) => { const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); Vue.use(VueApollo); diff --git a/app/assets/javascripts/admin/users/index.js b/app/assets/javascripts/admin/users/index.js index 852b253d25a..0c485d2a239 100644 --- a/app/assets/javascripts/admin/users/index.js +++ b/app/assets/javascripts/admin/users/index.js @@ -15,7 +15,7 @@ import { Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); const initApp = (el, component, userPropKey, props = {}) => { diff --git a/app/assets/javascripts/alert_management/list.js b/app/assets/javascripts/alert_management/list.js index 4cb56a2614c..b23f8a8eba4 100644 --- a/app/assets/javascripts/alert_management/list.js +++ b/app/assets/javascripts/alert_management/list.js @@ -38,7 +38,6 @@ export default () => { return defaultDataIdFromObject(object); }, }, - assumeImmutableResults: true, }, ), }); diff --git a/app/assets/javascripts/alerts_settings/graphql.js b/app/assets/javascripts/alerts_settings/graphql.js index 15862f4034a..b64e2e3eefa 100644 --- a/app/assets/javascripts/alerts_settings/graphql.js +++ b/app/assets/javascripts/alerts_settings/graphql.js @@ -59,6 +59,5 @@ export default new VueApollo({ cacheConfig: { fragmentMatcher, }, - assumeImmutableResults: true, }), }); diff --git a/app/assets/javascripts/analytics/usage_trends/index.js b/app/assets/javascripts/analytics/usage_trends/index.js index 3e85832edcf..d1880b09f15 100644 --- a/app/assets/javascripts/analytics/usage_trends/index.js +++ b/app/assets/javascripts/analytics/usage_trends/index.js @@ -6,7 +6,7 @@ import UsageTrendsApp from './components/app.vue'; Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); export default () => { diff --git a/app/assets/javascripts/artifacts_settings/index.js b/app/assets/javascripts/artifacts_settings/index.js index 5c9f1c3129c..531b42bc185 100644 --- a/app/assets/javascripts/artifacts_settings/index.js +++ b/app/assets/javascripts/artifacts_settings/index.js @@ -6,7 +6,7 @@ import createDefaultClient from '~/lib/graphql'; Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); export default (containerId = 'js-artifacts-settings-app') => { diff --git a/app/assets/javascripts/boards/graphql.js b/app/assets/javascripts/boards/graphql.js index d8d16184936..64938cb42ed 100644 --- a/app/assets/javascripts/boards/graphql.js +++ b/app/assets/javascripts/boards/graphql.js @@ -17,6 +17,5 @@ export const gqlClient = createDefaultClient( fragmentMatcher, }, - assumeImmutableResults: true, }, ); diff --git a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js index a3a8ad06c43..d74a772170b 100644 --- a/app/assets/javascripts/boards/mount_multiple_boards_switcher.js +++ b/app/assets/javascripts/boards/mount_multiple_boards_switcher.js @@ -8,12 +8,7 @@ import { parseBoolean } from '~/lib/utils/common_utils'; Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); export default (params = {}) => { diff --git a/app/assets/javascripts/ci_lint/index.js b/app/assets/javascripts/ci_lint/index.js index f97590ec5db..274aab45deb 100644 --- a/app/assets/javascripts/ci_lint/index.js +++ b/app/assets/javascripts/ci_lint/index.js @@ -8,9 +8,7 @@ import CiLint from './components/ci_lint.vue'; Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient(resolvers, { - assumeImmutableResults: true, - }), + defaultClient: createDefaultClient(resolvers), }); export default (containerId = '#js-ci-lint') => { diff --git a/app/assets/javascripts/clusters/agents/index.js b/app/assets/javascripts/clusters/agents/index.js index ec6b6c6fc35..bcb5b271203 100644 --- a/app/assets/javascripts/clusters/agents/index.js +++ b/app/assets/javascripts/clusters/agents/index.js @@ -12,12 +12,7 @@ export default () => { return null; } - const defaultClient = createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ); + const defaultClient = createDefaultClient(); const { agentName, projectPath } = el.dataset; return new Vue({ diff --git a/app/assets/javascripts/clusters_list/load_agents.js b/app/assets/javascripts/clusters_list/load_agents.js index b77d386df20..3f00cabccdb 100644 --- a/app/assets/javascripts/clusters_list/load_agents.js +++ b/app/assets/javascripts/clusters_list/load_agents.js @@ -8,7 +8,7 @@ export default (Vue, VueApollo) => { return null; } - const defaultClient = createDefaultClient({}, { assumeImmutableResults: true }); + const defaultClient = createDefaultClient(); const { emptyStateImage, diff --git a/app/assets/javascripts/design_management/graphql.js b/app/assets/javascripts/design_management/graphql.js index fa57537f74e..5cf32cb7fe3 100644 --- a/app/assets/javascripts/design_management/graphql.js +++ b/app/assets/javascripts/design_management/graphql.js @@ -88,7 +88,6 @@ const defaultClient = createDefaultClient( fragmentMatcher, }, typeDefs, - assumeImmutableResults: true, }, ); diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js b/app/assets/javascripts/environments/folder/environments_folder_bundle.js index f248e9ec079..206381e0b7e 100644 --- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js +++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js @@ -8,7 +8,7 @@ Vue.use(Translate); Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); export default () => { diff --git a/app/assets/javascripts/environments/graphql/client.js b/app/assets/javascripts/environments/graphql/client.js index 498163c7abc..c734c2fba0c 100644 --- a/app/assets/javascripts/environments/graphql/client.js +++ b/app/assets/javascripts/environments/graphql/client.js @@ -2,16 +2,12 @@ import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; import environmentApp from './queries/environmentApp.query.graphql'; import { resolvers } from './resolvers'; -import typedefs from './typedefs.graphql'; +import typeDefs from './typedefs.graphql'; export const apolloProvider = (endpoint) => { - const defaultClient = createDefaultClient( - resolvers(endpoint), - { - assumeImmutableResults: true, - }, - typedefs, - ); + const defaultClient = createDefaultClient(resolvers(endpoint), { + typeDefs, + }); const { cache } = defaultClient; cache.writeQuery({ diff --git a/app/assets/javascripts/environments/index.js b/app/assets/javascripts/environments/index.js index 99a1d12adf7..3b1d35c1f22 100644 --- a/app/assets/javascripts/environments/index.js +++ b/app/assets/javascripts/environments/index.js @@ -9,7 +9,7 @@ Vue.use(Translate); Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); export default (el) => { diff --git a/app/assets/javascripts/error_tracking/details.js b/app/assets/javascripts/error_tracking/details.js index 38245210b70..37b8007d556 100644 --- a/app/assets/javascripts/error_tracking/details.js +++ b/app/assets/javascripts/error_tracking/details.js @@ -20,12 +20,7 @@ export default () => { } = domEl.dataset; const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); // eslint-disable-next-line no-new diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js index c08cf909a00..6eca530b49c 100644 --- a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js +++ b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js @@ -376,8 +376,4 @@ export function createResolvers({ endpoints, sourceUrl, GroupsManager = SourceGr } export const createApolloClient = ({ sourceUrl, endpoints }) => - createDefaultClient( - createResolvers({ sourceUrl, endpoints }), - { assumeImmutableResults: true }, - typeDefs, - ); + createDefaultClient(createResolvers({ sourceUrl, endpoints }), { typeDefs }); diff --git a/app/assets/javascripts/incidents/list.js b/app/assets/javascripts/incidents/list.js index 6e6461cd7a9..8644ff3a249 100644 --- a/app/assets/javascripts/incidents/list.js +++ b/app/assets/javascripts/incidents/list.js @@ -24,7 +24,7 @@ export default () => { } = domEl.dataset; const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); return new Vue({ diff --git a/app/assets/javascripts/issuable_suggestions/index.js b/app/assets/javascripts/issuable_suggestions/index.js index 22a99a17741..8f7f317d6b4 100644 --- a/app/assets/javascripts/issuable_suggestions/index.js +++ b/app/assets/javascripts/issuable_suggestions/index.js @@ -10,12 +10,7 @@ export default function initIssuableSuggestions() { const issueTitle = document.getElementById('issue_title'); const { projectPath } = el.dataset; const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); return new Vue({ diff --git a/app/assets/javascripts/issues_list/index.js b/app/assets/javascripts/issues_list/index.js index 421d6b35919..59034964afb 100644 --- a/app/assets/javascripts/issues_list/index.js +++ b/app/assets/javascripts/issues_list/index.js @@ -24,7 +24,7 @@ export function mountJiraIssuesListApp() { } Vue.use(VueApollo); - const defaultClient = createDefaultClient({}, { assumeImmutableResults: true }); + const defaultClient = createDefaultClient(); const apolloProvider = new VueApollo({ defaultClient, }); @@ -103,7 +103,7 @@ export function mountIssuesListApp() { }, }; - const defaultClient = createDefaultClient(resolvers, { assumeImmutableResults: true }); + const defaultClient = createDefaultClient(resolvers); const apolloProvider = new VueApollo({ defaultClient, }); diff --git a/app/assets/javascripts/jira_connect/branches/index.js b/app/assets/javascripts/jira_connect/branches/index.js index 95bd4f5c675..04510fcff4b 100644 --- a/app/assets/javascripts/jira_connect/branches/index.js +++ b/app/assets/javascripts/jira_connect/branches/index.js @@ -14,12 +14,7 @@ export default async function initJiraConnectBranches() { const { initialBranchName, successStateSvgPath } = el.dataset; const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); return new Vue({ diff --git a/app/assets/javascripts/jira_import/index.js b/app/assets/javascripts/jira_import/index.js index 003f3c7107e..695a237bf50 100644 --- a/app/assets/javascripts/jira_import/index.js +++ b/app/assets/javascripts/jira_import/index.js @@ -6,7 +6,7 @@ import App from './components/jira_import_app.vue'; Vue.use(VueApollo); -const defaultClient = createDefaultClient({}, { assumeImmutableResults: true }); +const defaultClient = createDefaultClient(); const apolloProvider = new VueApollo({ defaultClient, diff --git a/app/assets/javascripts/jobs/components/table/index.js b/app/assets/javascripts/jobs/components/table/index.js index cec871ddbb4..f24daf90815 100644 --- a/app/assets/javascripts/jobs/components/table/index.js +++ b/app/assets/javascripts/jobs/components/table/index.js @@ -9,12 +9,7 @@ Vue.use(VueApollo); Vue.use(GlToast); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); export default (containerId = 'js-jobs-table') => { diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js index 39bf804b54e..df2e85afe24 100644 --- a/app/assets/javascripts/lib/graphql.js +++ b/app/assets/javascripts/lib/graphql.js @@ -48,7 +48,6 @@ export const stripWhitespaceFromQuery = (url, path) => { export default (resolvers = {}, config = {}) => { const { - assumeImmutableResults, baseUrl, batchMax = 10, cacheConfig, @@ -161,10 +160,10 @@ export default (resolvers = {}, config = {}) => { link: appLink, cache: new InMemoryCache({ ...cacheConfig, - freezeResults: assumeImmutableResults, + freezeResults: true, }), resolvers, - assumeImmutableResults, + assumeImmutableResults: true, defaultOptions: { query: { fetchPolicy, diff --git a/app/assets/javascripts/mr_popover/index.js b/app/assets/javascripts/mr_popover/index.js index 6e46c5d3c1f..714cf67e0bd 100644 --- a/app/assets/javascripts/mr_popover/index.js +++ b/app/assets/javascripts/mr_popover/index.js @@ -48,12 +48,7 @@ export default (elements) => { Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); const listenerAddedAttr = 'data-mr-listener-added'; diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/index.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/index.js index 16152eb81f6..56f95fa2c1f 100644 --- a/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/index.js +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/index.js @@ -5,10 +5,5 @@ import createDefaultClient from '~/lib/graphql'; Vue.use(VueApollo); export const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js b/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js index f8cb5c516e2..21d6fbc9e1f 100644 --- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js +++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/index.js @@ -17,7 +17,6 @@ export const apolloProvider = new VueApollo({ cacheConfig: { fragmentMatcher, }, - assumeImmutableResults: true, }, ), }); diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js b/app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js index 16152eb81f6..56f95fa2c1f 100644 --- a/app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js +++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/index.js @@ -5,10 +5,5 @@ import createDefaultClient from '~/lib/graphql'; Vue.use(VueApollo); export const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); diff --git a/app/assets/javascripts/packages_and_registries/settings/project/graphql/index.js b/app/assets/javascripts/packages_and_registries/settings/project/graphql/index.js index 16152eb81f6..56f95fa2c1f 100644 --- a/app/assets/javascripts/packages_and_registries/settings/project/graphql/index.js +++ b/app/assets/javascripts/packages_and_registries/settings/project/graphql/index.js @@ -5,10 +5,5 @@ import createDefaultClient from '~/lib/graphql'; Vue.use(VueApollo); export const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js index 80bcbefab46..b365e039191 100644 --- a/app/assets/javascripts/pages/projects/blob/show/index.js +++ b/app/assets/javascripts/pages/projects/blob/show/index.js @@ -14,7 +14,7 @@ import '~/sourcegraph/load'; Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); const viewBlobEl = document.querySelector('#js-view-blob-app'); diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js index 194e273e261..99094617b0a 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js +++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js @@ -28,7 +28,7 @@ export default function initMergeRequestShow() { const el = document.querySelector('.js-mr-status-box'); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); // eslint-disable-next-line no-new new Vue({ diff --git a/app/assets/javascripts/pages/shared/mount_runner_instructions.js b/app/assets/javascripts/pages/shared/mount_runner_instructions.js index 1cb7259be64..e83c73edfde 100644 --- a/app/assets/javascripts/pages/shared/mount_runner_instructions.js +++ b/app/assets/javascripts/pages/shared/mount_runner_instructions.js @@ -9,12 +9,7 @@ export function initInstallRunner(componentId = 'js-install-runner') { const installRunnerEl = document.getElementById(componentId); if (installRunnerEl) { - const defaultClient = createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ); + const defaultClient = createDefaultClient(); const apolloProvider = new VueApollo({ defaultClient, diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js index 58dc71d981f..4f7f2743aca 100644 --- a/app/assets/javascripts/pipeline_editor/index.js +++ b/app/assets/javascripts/pipeline_editor/index.js @@ -61,7 +61,6 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => { defaultClient: createDefaultClient(resolvers, { typeDefs, useGet: true, - assumeImmutableResults: true, }), }); const { cache } = apolloProvider.clients.defaultClient; diff --git a/app/assets/javascripts/pipelines/pipeline_shared_client.js b/app/assets/javascripts/pipelines/pipeline_shared_client.js index 7a922acd0b3..c3be487caae 100644 --- a/app/assets/javascripts/pipelines/pipeline_shared_client.js +++ b/app/assets/javascripts/pipelines/pipeline_shared_client.js @@ -5,7 +5,6 @@ export const apolloProvider = new VueApollo({ defaultClient: createDefaultClient( {}, { - assumeImmutableResults: true, useGet: true, }, ), diff --git a/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js b/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js index 2505c47147f..1d4ec4c110b 100644 --- a/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js +++ b/app/assets/javascripts/projects/commit_box/info/init_commit_pipeline_mini_graph.js @@ -5,12 +5,7 @@ import createDefaultClient from '~/lib/graphql'; Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); export const initCommitPipelineMiniGraph = async (selector = '.js-commit-pipeline-mini-graph') => { diff --git a/app/assets/javascripts/projects/new/index.js b/app/assets/javascripts/projects/new/index.js index 572d3276e4f..010c6a29ae3 100644 --- a/app/assets/javascripts/projects/new/index.js +++ b/app/assets/javascripts/projects/new/index.js @@ -50,7 +50,7 @@ export function initNewProjectUrlSelect() { new Vue({ el, apolloProvider: new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }), provide: { namespaceFullPath: el.dataset.namespaceFullPath, diff --git a/app/assets/javascripts/projects/pipelines/charts/index.js b/app/assets/javascripts/projects/pipelines/charts/index.js index f7ea89068a0..5f5ee44c204 100644 --- a/app/assets/javascripts/projects/pipelines/charts/index.js +++ b/app/assets/javascripts/projects/pipelines/charts/index.js @@ -7,7 +7,7 @@ import ProjectPipelinesCharts from './components/app.vue'; Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); const mountPipelineChartsApp = (el) => { diff --git a/app/assets/javascripts/projects/storage_counter/index.js b/app/assets/javascripts/projects/storage_counter/index.js index 10668f08402..15796bc1870 100644 --- a/app/assets/javascripts/projects/storage_counter/index.js +++ b/app/assets/javascripts/projects/storage_counter/index.js @@ -25,7 +25,7 @@ export default (containerId = 'js-project-storage-count-app') => { } = el.dataset; const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); return new Vue({ diff --git a/app/assets/javascripts/projects/terraform_notification/index.js b/app/assets/javascripts/projects/terraform_notification/index.js index 21c8d09b7fc..362e71ed902 100644 --- a/app/assets/javascripts/projects/terraform_notification/index.js +++ b/app/assets/javascripts/projects/terraform_notification/index.js @@ -6,7 +6,7 @@ import TerraformNotification from './components/terraform_notification.vue'; Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmtableResults: true }), + defaultClient: createDefaultClient(), }); export default () => { diff --git a/app/assets/javascripts/registry/explorer/graphql/index.js b/app/assets/javascripts/registry/explorer/graphql/index.js index d934bcc7419..9694bfd4e77 100644 --- a/app/assets/javascripts/registry/explorer/graphql/index.js +++ b/app/assets/javascripts/registry/explorer/graphql/index.js @@ -9,7 +9,6 @@ export const apolloProvider = new VueApollo({ {}, { batchMax: 1, - assumeImmutableResults: true, }, ), }); diff --git a/app/assets/javascripts/releases/mount_index.js b/app/assets/javascripts/releases/mount_index.js index 59f6ebfc928..86fa72d1496 100644 --- a/app/assets/javascripts/releases/mount_index.js +++ b/app/assets/javascripts/releases/mount_index.js @@ -24,7 +24,6 @@ export default () => { // the purpose of making separate requests. So we explicitly // disable batching on this page. batchMax: 1, - assumeImmutableResults: true, }, ), }); diff --git a/app/assets/javascripts/releases/mount_show.js b/app/assets/javascripts/releases/mount_show.js index 686f9e294b7..7272880197a 100644 --- a/app/assets/javascripts/releases/mount_show.js +++ b/app/assets/javascripts/releases/mount_show.js @@ -6,12 +6,7 @@ import ReleaseShowApp from './components/app_show.vue'; Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); export default () => { diff --git a/app/assets/javascripts/repository/graphql.js b/app/assets/javascripts/repository/graphql.js index 4892e54ebef..96d712ce9b4 100644 --- a/app/assets/javascripts/repository/graphql.js +++ b/app/assets/javascripts/repository/graphql.js @@ -64,7 +64,6 @@ const defaultClient = createDefaultClient( /* eslint-enable @gitlab/require-i18n-strings */ }, }, - assumeImmutableResults: true, }, ); diff --git a/app/assets/javascripts/runner/admin_runners/index.js b/app/assets/javascripts/runner/admin_runners/index.js index 84527032694..9d80eec6f54 100644 --- a/app/assets/javascripts/runner/admin_runners/index.js +++ b/app/assets/javascripts/runner/admin_runners/index.js @@ -19,12 +19,7 @@ export const initAdminRunners = (selector = '#js-admin-runners') => { const { activeRunnersCount, registrationToken, runnerInstallHelpPage } = el.dataset; const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); return new Vue({ diff --git a/app/assets/javascripts/runner/group_runners/index.js b/app/assets/javascripts/runner/group_runners/index.js index 959e8a4fedd..60b7a7ab541 100644 --- a/app/assets/javascripts/runner/group_runners/index.js +++ b/app/assets/javascripts/runner/group_runners/index.js @@ -23,12 +23,7 @@ export const initGroupRunners = (selector = '#js-group-runners') => { } = el.dataset; const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); return new Vue({ diff --git a/app/assets/javascripts/runner/runner_details/index.js b/app/assets/javascripts/runner/runner_details/index.js index 05e6f86869d..db8f239a3c3 100644 --- a/app/assets/javascripts/runner/runner_details/index.js +++ b/app/assets/javascripts/runner/runner_details/index.js @@ -15,12 +15,7 @@ export const initRunnerDetail = (selector = '#js-runner-details') => { const { runnerId } = el.dataset; const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); return new Vue({ diff --git a/app/assets/javascripts/security_configuration/index.js b/app/assets/javascripts/security_configuration/index.js index 60d2c0d4e5a..a8623b468f2 100644 --- a/app/assets/javascripts/security_configuration/index.js +++ b/app/assets/javascripts/security_configuration/index.js @@ -14,7 +14,7 @@ export const initSecurityConfiguration = (el) => { Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); const { diff --git a/app/assets/javascripts/sidebar/graphql.js b/app/assets/javascripts/sidebar/graphql.js index 1a806a051b7..6a670db2d38 100644 --- a/app/assets/javascripts/sidebar/graphql.js +++ b/app/assets/javascripts/sidebar/graphql.js @@ -25,7 +25,6 @@ export const defaultClient = createDefaultClient(resolvers, { cacheConfig: { fragmentMatcher, }, - assumeImmutableResults: true, }); export const apolloProvider = new VueApollo({ diff --git a/app/assets/javascripts/snippets/index.js b/app/assets/javascripts/snippets/index.js index 8e7368ef804..21f38c4d8c9 100644 --- a/app/assets/javascripts/snippets/index.js +++ b/app/assets/javascripts/snippets/index.js @@ -18,7 +18,6 @@ export default function appFactory(el, Component) { {}, { batchMax: 1, - assumeImmutableResults: true, }, ), }); diff --git a/app/assets/javascripts/static_site_editor/graphql/index.js b/app/assets/javascripts/static_site_editor/graphql/index.js index 2ae2baddbcc..53572e680e5 100644 --- a/app/assets/javascripts/static_site_editor/graphql/index.js +++ b/app/assets/javascripts/static_site_editor/graphql/index.js @@ -22,7 +22,6 @@ const createApolloProvider = (appData) => { }, { typeDefs, - assumeImmutableResults: true, }, ); diff --git a/app/assets/javascripts/terraform/index.js b/app/assets/javascripts/terraform/index.js index 013b95c5633..1b8cab0d51e 100644 --- a/app/assets/javascripts/terraform/index.js +++ b/app/assets/javascripts/terraform/index.js @@ -22,7 +22,6 @@ export default () => { return object.id || defaultDataIdFromObject(object); }, }, - assumeImmutableResults: true, }); const { emptyStateImage, projectPath, accessTokensPath, terraformApiUrl, username } = el.dataset; diff --git a/app/assets/javascripts/token_access/index.js b/app/assets/javascripts/token_access/index.js index 8d29a65d705..6a29883290a 100644 --- a/app/assets/javascripts/token_access/index.js +++ b/app/assets/javascripts/token_access/index.js @@ -6,7 +6,7 @@ import TokenAccess from './components/token_access.vue'; Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); export const initTokenAccess = (containerId = 'js-ci-token-access-app') => { diff --git a/app/assets/javascripts/vue_merge_request_widget/index.js b/app/assets/javascripts/vue_merge_request_widget/index.js index f5dbcec7dbe..8d596465970 100644 --- a/app/assets/javascripts/vue_merge_request_widget/index.js +++ b/app/assets/javascripts/vue_merge_request_widget/index.js @@ -13,12 +13,7 @@ Vue.use(Translate); Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient( - {}, - { - assumeImmutableResults: true, - }, - ), + defaultClient: createDefaultClient(), }); export default () => { diff --git a/app/assets/javascripts/vue_shared/alert_details/index.js b/app/assets/javascripts/vue_shared/alert_details/index.js index fda405c0fa5..9f1da9ae173 100644 --- a/app/assets/javascripts/vue_shared/alert_details/index.js +++ b/app/assets/javascripts/vue_shared/alert_details/index.js @@ -38,7 +38,6 @@ export default (selector) => { return defaultDataIdFromObject(object); }, }, - assumeImmutableResults: true, }), }); diff --git a/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue b/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue index c1e8376d656..114f60c96ee 100644 --- a/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue +++ b/app/assets/javascripts/vue_shared/new_namespace/new_namespace_page.vue @@ -82,7 +82,7 @@ export default { }); this.$root.$on('clicked::link', (e) => { - window.location = e.target.href; + window.location = e.currentTarget.href; }); }, diff --git a/app/assets/javascripts/vue_shared/security_configuration/provider.js b/app/assets/javascripts/vue_shared/security_configuration/provider.js index fa23669b615..ef96b443da8 100644 --- a/app/assets/javascripts/vue_shared/security_configuration/provider.js +++ b/app/assets/javascripts/vue_shared/security_configuration/provider.js @@ -5,5 +5,5 @@ import createDefaultClient from '~/lib/graphql'; Vue.use(VueApollo); export default new VueApollo({ - defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), + defaultClient: createDefaultClient(), }); diff --git a/app/assets/javascripts/work_items/graphql/provider.js b/app/assets/javascripts/work_items/graphql/provider.js index 2547b81bbd2..083735336ce 100644 --- a/app/assets/javascripts/work_items/graphql/provider.js +++ b/app/assets/javascripts/work_items/graphql/provider.js @@ -4,6 +4,7 @@ import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; import createDefaultClient from '~/lib/graphql'; import workItemQuery from './work_item.query.graphql'; import introspectionQueryResultData from './fragmentTypes.json'; +import typeDefs from './typedefs.graphql'; const fragmentMatcher = new IntrospectionFragmentMatcher({ introspectionQueryResultData, @@ -18,7 +19,7 @@ export function createApolloProvider() { cacheConfig: { fragmentMatcher, }, - assumeImmutableResults: true, + typeDefs, }, ); diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss index 0c1fe00b4b4..efa4b04ee62 100644 --- a/app/assets/stylesheets/startup/startup-dark.scss +++ b/app/assets/stylesheets/startup/startup-dark.scss @@ -1943,7 +1943,7 @@ body.gl-dark { .gl-display-none { display: none; } -@media (min-width: 36rem) { +@media (min-width: 576px) { .gl-sm-display-block { display: block; } diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss index 40026c95a15..977f994dc78 100644 --- a/app/assets/stylesheets/startup/startup-general.scss +++ b/app/assets/stylesheets/startup/startup-general.scss @@ -1621,7 +1621,7 @@ svg.s16 { .gl-display-none { display: none; } -@media (min-width: 36rem) { +@media (min-width: 576px) { .gl-sm-display-block { display: block; } diff --git a/app/assets/stylesheets/startup/startup-signin.scss b/app/assets/stylesheets/startup/startup-signin.scss index 8d7531d6c9c..3daeeb30082 100644 --- a/app/assets/stylesheets/startup/startup-signin.scss +++ b/app/assets/stylesheets/startup/startup-signin.scss @@ -776,7 +776,7 @@ svg { .gl-mb-5 { margin-bottom: 1rem; } -@media (min-width: 36rem) { +@media (min-width: 576px) { .gl-sm-mt-0 { margin-top: 0; } diff --git a/app/views/projects/blob/viewers/_changelog.html.haml b/app/views/projects/blob/viewers/_changelog.html.haml index cac858c1444..5f3b9285ea9 100644 --- a/app/views/projects/blob/viewers/_changelog.html.haml +++ b/app/views/projects/blob/viewers/_changelog.html.haml @@ -1,3 +1,3 @@ = sprite_icon('history', css_class: 'gl-mr-1 gl-vertical-align-text-bottom') = succeed '.' do - = _("To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}.").html_safe % { link_start: "".html_safe, link_end: "".html_safe } + = _("To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}").html_safe % { link_start: "".html_safe, link_end: "".html_safe } diff --git a/app/views/projects/blob/viewers/_readme.html.haml b/app/views/projects/blob/viewers/_readme.html.haml index e06ff4edf71..c07428f0337 100644 --- a/app/views/projects/blob/viewers/_readme.html.haml +++ b/app/views/projects/blob/viewers/_readme.html.haml @@ -1,4 +1,4 @@ = sprite_icon('information-o', css_class: 'gl-vertical-align-middle! gl-mr-2') = succeed '.' do - link_to_wiki = link_to(_("the wiki"), wiki_path(viewer.project.wiki)) - = _("To learn more about this project, read %{link_to_wiki}.").html_safe % { link_to_wiki: link_to_wiki } + = _("To learn more about this project, read %{link_to_wiki}").html_safe % { link_to_wiki: link_to_wiki } diff --git a/config/initializers_before_autoloader/000_inflections.rb b/config/initializers_before_autoloader/000_inflections.rb index b7e4e143765..876ae5da230 100644 --- a/config/initializers_before_autoloader/000_inflections.rb +++ b/config/initializers_before_autoloader/000_inflections.rb @@ -39,4 +39,5 @@ ActiveSupport::Inflector.inflections do |inflect| inflect.acronym 'EE' inflect.acronym 'JH' inflect.acronym 'CSP' + inflect.acronym 'VSCode' end diff --git a/db/post_migrate/20210930211936_backfill_user_namespace.rb b/db/post_migrate/20210930211936_backfill_user_namespace.rb new file mode 100644 index 00000000000..c5dd170f18e --- /dev/null +++ b/db/post_migrate/20210930211936_backfill_user_namespace.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +class BackfillUserNamespace < Gitlab::Database::Migration[1.0] + MIGRATION = 'BackfillUserNamespace' + INTERVAL = 2.minutes + BATCH_SIZE = 1_000 + SUB_BATCH_SIZE = 200 + DOWNTIME = false + + def up + queue_batched_background_migration( + MIGRATION, + :namespaces, + :id, + job_interval: INTERVAL, + batch_size: BATCH_SIZE, + sub_batch_size: SUB_BATCH_SIZE + ) + end + + def down + Gitlab::Database::BackgroundMigration::BatchedMigration + .for_configuration(MIGRATION, :namespaces, :id, []) + .delete_all + end +end diff --git a/db/schema_migrations/20210930211936 b/db/schema_migrations/20210930211936 new file mode 100644 index 00000000000..4538ddf180d --- /dev/null +++ b/db/schema_migrations/20210930211936 @@ -0,0 +1 @@ +3aaf2a4fa834331768e2acc10f67b8d456e70aca9784787e40b55dade7b6f64c \ No newline at end of file diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md index 0229aa0123a..683b3bc61cd 100644 --- a/doc/development/fe_guide/graphql.md +++ b/doc/development/fe_guide/graphql.md @@ -103,7 +103,6 @@ Default client accepts two parameters: `resolvers` and `config`. - `config` parameter takes an object of configuration settings: - `cacheConfig` field accepts an optional object of settings to [customize Apollo cache](https://www.apollographql.com/docs/react/caching/cache-configuration/#configuring-the-cache) - `baseUrl` allows us to pass a URL for GraphQL endpoint different from our main endpoint (for example, `${gon.relative_url_root}/api/graphql`) - - `assumeImmutableResults` (set to `false` by default) - this setting, when set to `true`, assumes that every single operation on updating Apollo Cache is immutable. It also sets `freezeResults` to `true`, so any attempt on mutating Apollo Cache throws a console warning in development environment. Please ensure you're following the immutability pattern on cache update operations before setting this option to `true`. - `fetchPolicy` determines how you want your component to interact with the Apollo cache. Defaults to "cache-first". ### Multiple client queries for the same object @@ -179,7 +178,7 @@ with a **new and updated** object. To facilitate the process of updating the cache and returning the new object we use the library [Immer](https://immerjs.github.io/immer/). -When possible, follow these conventions: +Please, follow these conventions: - The updated cache is named `data`. - The original cache data is named `sourceData`. @@ -204,11 +203,6 @@ client.writeQuery({ As shown in the code example by using `produce`, we can perform any kind of direct manipulation of the `draftState`. Besides, `immer` guarantees that a new state which includes the changes to `draftState` is generated. -Finally, to verify whether the immutable cache update is working properly, we need to change -`assumeImmutableResults` to `true` in the default client configuration. See [Apollo Client](#apollo-client) for more information. - -If everything is working properly `assumeImmutableResults` should remain set to `true`. - ## Usage in Vue To use Vue Apollo, import the [Vue Apollo](https://github.com/vuejs/vue-apollo) plugin as well diff --git a/lib/api/integrations.rb b/lib/api/integrations.rb index 926cde340a0..bab8e556a73 100644 --- a/lib/api/integrations.rb +++ b/lib/api/integrations.rb @@ -153,7 +153,7 @@ module API requires setting[:name], type: setting[:type], desc: setting[:desc] end end - post "#{path}/#{integration_slug.underscore}/trigger" do + post "#{path}/#{integration_slug.underscore}/trigger", urgency: :low do project = find_project(params[:id]) # This is not accurate, but done to prevent leakage of the project names diff --git a/lib/error_tracking/collector/sentry_request_parser.rb b/lib/error_tracking/collector/sentry_request_parser.rb index 29e4cc8976f..ae632ebd518 100644 --- a/lib/error_tracking/collector/sentry_request_parser.rb +++ b/lib/error_tracking/collector/sentry_request_parser.rb @@ -4,15 +4,7 @@ module ErrorTracking module Collector class SentryRequestParser def self.parse(request) - # Request body can be "" or "gzip". - # If later then body was compressed with Zlib.gzip - encoding = request.headers['Content-Encoding'] - - body = if encoding == 'gzip' - Zlib.gunzip(request.body.read) - else - request.body.read - end + body = request.body.read # Request body contains 3 json objects merged together in one StringIO. # We need to separate and parse them into array of hash objects. diff --git a/lib/gitlab/background_migration/backfill_user_namespace.rb b/lib/gitlab/background_migration/backfill_user_namespace.rb new file mode 100644 index 00000000000..f55eaa3b14e --- /dev/null +++ b/lib/gitlab/background_migration/backfill_user_namespace.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # Backfills the `namespaces.type` column, replacing any + # instances of `NULL` with `User` + class BackfillUserNamespace + include Gitlab::Database::DynamicModelHelpers + + def perform(start_id, end_id, batch_table, batch_column, sub_batch_size, pause_ms) + parent_batch_relation = relation_scoped_to_range(batch_table, batch_column, start_id, end_id) + parent_batch_relation.each_batch(column: batch_column, of: sub_batch_size, order_hint: :type) do |sub_batch| + batch_metrics.time_operation(:update_all) do + sub_batch.update_all(type: 'User') + end + pause_ms = 0 if pause_ms < 0 + sleep(pause_ms * 0.001) + end + end + + def batch_metrics + @batch_metrics ||= Gitlab::Database::BackgroundMigration::BatchMetrics.new + end + + private + + def connection + ActiveRecord::Base.connection + end + + def relation_scoped_to_range(source_table, source_key_column, start_id, stop_id) + define_batchable_model(source_table) + .where(source_key_column => start_id..stop_id) + .where(type: nil) + end + end + end +end diff --git a/lib/gitlab/ci/build/auto_retry.rb b/lib/gitlab/ci/build/auto_retry.rb index 6d139519085..4950a7616c8 100644 --- a/lib/gitlab/ci/build/auto_retry.rb +++ b/lib/gitlab/ci/build/auto_retry.rb @@ -11,7 +11,8 @@ class Gitlab::Ci::Build::AutoRetry ci_quota_exceeded: 0, no_matching_runner: 0, missing_dependency_failure: 0, - forward_deployment_failure: 0 + forward_deployment_failure: 0, + environment_creation_failure: 0 }.freeze def initialize(build) diff --git a/lib/gitlab/middleware/compressed_json.rb b/lib/gitlab/middleware/compressed_json.rb index e2dabca69a8..ef6e0db5673 100644 --- a/lib/gitlab/middleware/compressed_json.rb +++ b/lib/gitlab/middleware/compressed_json.rb @@ -27,10 +27,10 @@ module Gitlab end def compressed_et_request?(env) - env['REQUEST_METHOD'] == 'POST' && - env['HTTP_CONTENT_ENCODING'] == 'gzip' && - env['CONTENT_TYPE'] == 'application/json' && - env['PATH_INFO'].start_with?((File.join(relative_url, COLLECTOR_PATH))) + post_request?(env) && + gzip_encoding?(env) && + match_content_type?(env) && + match_path?(env) end def too_large @@ -44,6 +44,23 @@ module Gitlab def extract(input) Zlib::GzipReader.new(input).read(MAXIMUM_BODY_SIZE + 1) end + + def post_request?(env) + env['REQUEST_METHOD'] == 'POST' + end + + def gzip_encoding?(env) + env['HTTP_CONTENT_ENCODING'] == 'gzip' + end + + def match_content_type?(env) + env['CONTENT_TYPE'] == 'application/json' || + env['CONTENT_TYPE'] == 'application/x-sentry-envelope' + end + + def match_path?(env) + env['PATH_INFO'].start_with?((File.join(relative_url, COLLECTOR_PATH))) + end end end end diff --git a/lib/gitlab/usage_data_counters/vs_code_extension_activity_unique_counter.rb b/lib/gitlab/usage_data_counters/vscode_extension_activity_unique_counter.rb similarity index 100% rename from lib/gitlab/usage_data_counters/vs_code_extension_activity_unique_counter.rb rename to lib/gitlab/usage_data_counters/vscode_extension_activity_unique_counter.rb diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 44fb580caa0..62746d28d5b 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -35813,7 +35813,7 @@ msgstr "" msgid "To ensure no loss of personal content, this account should only be used for matters related to %{group_name}." msgstr "" -msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}." +msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}" msgstr "" msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method." @@ -35849,7 +35849,7 @@ msgstr "" msgid "To keep this project going, create a new merge request" msgstr "" -msgid "To learn more about this project, read %{link_to_wiki}." +msgid "To learn more about this project, read %{link_to_wiki}" msgstr "" msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here." diff --git a/package.json b/package.json index faa859a7cb9..778da296e37 100644 --- a/package.json +++ b/package.json @@ -55,9 +55,9 @@ "@babel/preset-env": "^7.10.1", "@gitlab/at.js": "1.5.7", "@gitlab/favicon-overlay": "2.0.0", - "@gitlab/svgs": "1.218.0", + "@gitlab/svgs": "1.219.0", "@gitlab/tributejs": "1.0.0", - "@gitlab/ui": "32.21.0", + "@gitlab/ui": "32.28.0", "@gitlab/visual-review-tools": "1.6.1", "@rails/actioncable": "6.1.4-1", "@rails/ujs": "6.1.4-1", diff --git a/qa/qa/scenario/test/integration/ldap_no_tls.rb b/qa/qa/scenario/test/integration/ldap_no_tls.rb index 339fc8924c1..19f62b6ed80 100644 --- a/qa/qa/scenario/test/integration/ldap_no_tls.rb +++ b/qa/qa/scenario/test/integration/ldap_no_tls.rb @@ -1,4 +1,4 @@ -# rubocop:disable Naming/FileName +# rubocop:todo Naming/FileName # frozen_string_literal: true module QA diff --git a/qa/qa/scenario/test/integration/ldap_tls.rb b/qa/qa/scenario/test/integration/ldap_tls.rb index 0214baddd2d..109fbe6fd74 100644 --- a/qa/qa/scenario/test/integration/ldap_tls.rb +++ b/qa/qa/scenario/test/integration/ldap_tls.rb @@ -1,4 +1,4 @@ -# rubocop:disable Naming/FileName +# rubocop:todo Naming/FileName # frozen_string_literal: true module QA diff --git a/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap b/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap index f80e2ce6ecc..7044c1285d8 100644 --- a/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap +++ b/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap @@ -4,10 +4,10 @@ exports[`Registry Breadcrumb when is not rootRoute renders 1`] = `
+
`; @@ -52,10 +60,10 @@ exports[`Registry Breadcrumb when is rootRoute renders 1`] = `
+
`; diff --git a/spec/lib/error_tracking/collector/sentry_request_parser_spec.rb b/spec/lib/error_tracking/collector/sentry_request_parser_spec.rb index 6f12c6d25e0..06f4b64ce93 100644 --- a/spec/lib/error_tracking/collector/sentry_request_parser_spec.rb +++ b/spec/lib/error_tracking/collector/sentry_request_parser_spec.rb @@ -33,12 +33,5 @@ RSpec.describe ErrorTracking::Collector::SentryRequestParser do context 'plain text sentry request' do it_behaves_like 'valid parser' end - - context 'gzip encoded sentry request' do - let(:headers) { { 'Content-Encoding' => 'gzip' } } - let(:body) { Zlib.gzip(raw_event) } - - it_behaves_like 'valid parser' - end end end diff --git a/spec/lib/gitlab/background_migration/backfill_user_namespace_spec.rb b/spec/lib/gitlab/background_migration/backfill_user_namespace_spec.rb new file mode 100644 index 00000000000..395248b786d --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_user_namespace_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillUserNamespace, :migration, schema: 20210930211936 do + let(:migration) { described_class.new } + let(:namespaces_table) { table(:namespaces) } + + let(:table_name) { 'namespaces' } + let(:batch_column) { :id } + let(:sub_batch_size) { 100 } + let(:pause_ms) { 0 } + + subject(:perform_migration) { migration.perform(1, 10, table_name, batch_column, sub_batch_size, pause_ms) } + + before do + namespaces_table.create!(id: 1, name: 'test1', path: 'test1', type: nil) + namespaces_table.create!(id: 2, name: 'test2', path: 'test2', type: 'User') + namespaces_table.create!(id: 3, name: 'test3', path: 'test3', type: 'Group') + namespaces_table.create!(id: 4, name: 'test4', path: 'test4', type: nil) + namespaces_table.create!(id: 11, name: 'test11', path: 'test11', type: nil) + end + + it 'backfills `type` for the selected records', :aggregate_failures do + queries = ActiveRecord::QueryRecorder.new do + perform_migration + end + + expect(queries.count).to eq(3) + expect(namespaces_table.where(type: 'User').count).to eq 3 + expect(namespaces_table.where(type: 'User').pluck(:id)).to match_array([1, 2, 4]) + end + + it 'tracks timings of queries' do + expect(migration.batch_metrics.timings).to be_empty + + expect { perform_migration }.to change { migration.batch_metrics.timings } + end +end diff --git a/spec/lib/gitlab/ci/build/auto_retry_spec.rb b/spec/lib/gitlab/ci/build/auto_retry_spec.rb index b6eb078dbea..9ff9200322e 100644 --- a/spec/lib/gitlab/ci/build/auto_retry_spec.rb +++ b/spec/lib/gitlab/ci/build/auto_retry_spec.rb @@ -26,6 +26,7 @@ RSpec.describe Gitlab::Ci::Build::AutoRetry do "no matching runner" | 0 | { max: 2 } | :no_matching_runner | false "missing dependencies" | 0 | { max: 2 } | :missing_dependency_failure | false "forward deployment failure" | 0 | { max: 2 } | :forward_deployment_failure | false + "environment creation failure" | 0 | { max: 2 } | :environment_creation_failure | false end with_them do diff --git a/spec/lib/gitlab/usage_data_counters/vs_code_extenion_activity_unique_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/vscode_extenion_activity_unique_counter_spec.rb similarity index 100% rename from spec/lib/gitlab/usage_data_counters/vs_code_extenion_activity_unique_counter_spec.rb rename to spec/lib/gitlab/usage_data_counters/vscode_extenion_activity_unique_counter_spec.rb diff --git a/spec/migrations/backfill_user_namespace_spec.rb b/spec/migrations/backfill_user_namespace_spec.rb new file mode 100644 index 00000000000..094aec82e9c --- /dev/null +++ b/spec/migrations/backfill_user_namespace_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe BackfillUserNamespace do + let_it_be(:migration) { described_class::MIGRATION } + + describe '#up' do + it 'schedules background jobs for each batch of namespaces' do + migrate! + + expect(migration).to have_scheduled_batched_migration( + table_name: :namespaces, + column_name: :id, + interval: described_class::INTERVAL + ) + end + end + + describe '#down' do + it 'deletes all batched migration records' do + migrate! + schema_migrate_down! + + expect(migration).not_to have_scheduled_batched_migration + end + end +end diff --git a/spec/requests/api/error_tracking/collector_spec.rb b/spec/requests/api/error_tracking/collector_spec.rb index 3f17835e789..57c87811c9e 100644 --- a/spec/requests/api/error_tracking/collector_spec.rb +++ b/spec/requests/api/error_tracking/collector_spec.rb @@ -96,6 +96,20 @@ RSpec.describe API::ErrorTracking::Collector do end end + context 'gzip body' do + let(:headers) do + { + 'X-Sentry-Auth' => "Sentry sentry_key=#{client_key.public_key}", + 'HTTP_CONTENT_ENCODING' => 'gzip', + 'CONTENT_TYPE' => 'application/x-sentry-envelope' + } + end + + let(:params) { ActiveSupport::Gzip.compress(raw_event) } + + it_behaves_like 'successful request' + end + it_behaves_like 'successful request' end @@ -131,7 +145,7 @@ RSpec.describe API::ErrorTracking::Collector do } end - let(:raw_event) { ActiveSupport::Gzip.compress(fixture_file('error_tracking/parsed_event.json')) } + let(:params) { ActiveSupport::Gzip.compress(raw_event) } it_behaves_like 'successful request' end diff --git a/spec/support/helpers/project_forks_helper.rb b/spec/support/helpers/project_forks_helper.rb index 4b4285f251e..84b5dbc1d23 100644 --- a/spec/support/helpers/project_forks_helper.rb +++ b/spec/support/helpers/project_forks_helper.rb @@ -28,11 +28,15 @@ module ProjectForksHelper unless params[:target_project] || params[:using_service] target_level = [project.visibility_level, namespace.visibility_level].min visibility_level = Gitlab::VisibilityLevel.closest_allowed_level(target_level) + # Builds and MRs can't have higher visibility level than repository access level. + builds_access_level = [project.builds_access_level, project.repository_access_level].min params[:target_project] = create(:project, (:repository if create_repository), - visibility_level: visibility_level, creator: user, namespace: namespace) + visibility_level: visibility_level, + builds_access_level: builds_access_level, + creator: user, namespace: namespace) end service = Projects::ForkService.new(project, user, params) diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go index d39ba845dc5..b4a3f85e4c4 100644 --- a/workhorse/internal/upstream/routes.go +++ b/workhorse/internal/upstream/routes.go @@ -374,6 +374,10 @@ func configureRoutes(u *upstream) { // Geo API routes u.route("", "^/api/v4/geo_nodes", defaultUpstream), u.route("", "^/api/v4/geo_replication", defaultUpstream), + u.route("", "^/api/v4/geo/proxy_git_ssh", defaultUpstream), + + // Internal API routes + u.route("", "^/api/v4/internal", defaultUpstream), // Don't define a catch-all route. If a route does not match, then we know // the request should be proxied. diff --git a/workhorse/internal/upstream/routes_test.go b/workhorse/internal/upstream/routes_test.go new file mode 100644 index 00000000000..f196433f5b4 --- /dev/null +++ b/workhorse/internal/upstream/routes_test.go @@ -0,0 +1,47 @@ +package upstream + +import ( + "testing" +) + +func TestProjectNotExistingGitHttpPullWithGeoProxy(t *testing.T) { + testCases := []testCase{ + {"secondary info/refs", "/group/project.git/info/refs", "Local Rails server received request to path /group/project.git/info/refs"}, + {"primary info/refs", "/-/push_from_secondary/2/group/project.git/info/refs", "Geo primary received request to path /-/push_from_secondary/2/group/project.git/info/refs"}, + {"primary upload-pack", "/-/push_from_secondary/2/group/project.git/git-upload-pack", "Geo primary received request to path /-/push_from_secondary/2/group/project.git/git-upload-pack"}, + } + + runTestCasesWithGeoProxyEnabled(t, testCases) +} + +func TestProjectNotExistingGitHttpPushWithGeoProxy(t *testing.T) { + testCases := []testCase{ + {"secondary info/refs", "/group/project.git/info/refs", "Local Rails server received request to path /group/project.git/info/refs"}, + {"primary info/refs", "/-/push_from_secondary/2/group/project.git/info/refs", "Geo primary received request to path /-/push_from_secondary/2/group/project.git/info/refs"}, + {"primary receive-pack", "/-/push_from_secondary/2/group/project.git/git-receive-pack", "Geo primary received request to path /-/push_from_secondary/2/group/project.git/git-receive-pack"}, + } + + runTestCasesWithGeoProxyEnabled(t, testCases) +} + +func TestProjectNotExistingGitSSHPullWithGeoProxy(t *testing.T) { + testCases := []testCase{ + {"GitLab Shell call to authorized-keys", "/api/v4/internal/authorized_keys", "Local Rails server received request to path /api/v4/internal/authorized_keys"}, + {"GitLab Shell call to allowed", "/api/v4/internal/allowed", "Local Rails server received request to path /api/v4/internal/allowed"}, + {"GitLab Shell call to info/refs", "/api/v4/geo/proxy_git_ssh/info_refs_receive_pack", "Local Rails server received request to path /api/v4/geo/proxy_git_ssh/info_refs_receive_pack"}, + {"GitLab Shell call to receive_pack", "/api/v4/geo/proxy_git_ssh/receive_pack", "Local Rails server received request to path /api/v4/geo/proxy_git_ssh/receive_pack"}, + } + + runTestCasesWithGeoProxyEnabled(t, testCases) +} + +func TestProjectNotExistingGitSSHPushWithGeoProxy(t *testing.T) { + testCases := []testCase{ + {"GitLab Shell call to authorized-keys", "/api/v4/internal/authorized_keys", "Local Rails server received request to path /api/v4/internal/authorized_keys"}, + {"GitLab Shell call to allowed", "/api/v4/internal/allowed", "Local Rails server received request to path /api/v4/internal/allowed"}, + {"GitLab Shell call to info/refs", "/api/v4/geo/proxy_git_ssh/info_refs_upload_pack", "Local Rails server received request to path /api/v4/geo/proxy_git_ssh/info_refs_upload_pack"}, + {"GitLab Shell call to receive_pack", "/api/v4/geo/proxy_git_ssh/upload_pack", "Local Rails server received request to path /api/v4/geo/proxy_git_ssh/upload_pack"}, + } + + runTestCasesWithGeoProxyEnabled(t, testCases) +} diff --git a/workhorse/internal/upstream/upstream_test.go b/workhorse/internal/upstream/upstream_test.go index 3c942767384..53c15bb7e91 100644 --- a/workhorse/internal/upstream/upstream_test.go +++ b/workhorse/internal/upstream/upstream_test.go @@ -88,16 +88,6 @@ func TestGeoProxyFeatureDisabledOnGeoSecondarySite(t *testing.T) { } func TestGeoProxyFeatureEnabledOnGeoSecondarySite(t *testing.T) { - remoteServer, rsDeferredClose := startRemoteServer("Geo primary") - defer rsDeferredClose() - - geoProxyEndpointResponseBody := fmt.Sprintf(`{"geo_proxy_url":"%v"}`, remoteServer.URL) - railsServer, deferredClose := startRailsServer("Local Rails server", &geoProxyEndpointResponseBody) - defer deferredClose() - - ws, wsDeferredClose, _ := startWorkhorseServer(railsServer.URL, true) - defer wsDeferredClose() - testCases := []testCase{ {"push from secondary is forwarded", "/-/push_from_secondary/foo/bar.git/info/refs", "Geo primary received request to path /-/push_from_secondary/foo/bar.git/info/refs"}, {"LFS files are served locally", "/group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6", "Local Rails server received request to path /group/project.git/gitlab-lfs/objects/37446575700829a11278ad3a550f244f45d5ae4fe1552778fa4f041f9eaeecf6"}, @@ -106,7 +96,7 @@ func TestGeoProxyFeatureEnabledOnGeoSecondarySite(t *testing.T) { {"unknown route is forwarded", "/anything", "Geo primary received request to path /anything"}, } - runTestCases(t, ws, testCases) + runTestCasesWithGeoProxyEnabled(t, testCases) } // This test can be removed when the environment variable `GEO_SECONDARY_PROXY` is removed @@ -227,6 +217,20 @@ func runTestCases(t *testing.T, ws *httptest.Server, testCases []testCase) { } } +func runTestCasesWithGeoProxyEnabled(t *testing.T, testCases []testCase) { + remoteServer, rsDeferredClose := startRemoteServer("Geo primary") + defer rsDeferredClose() + + geoProxyEndpointResponseBody := fmt.Sprintf(`{"geo_proxy_url":"%v"}`, remoteServer.URL) + railsServer, deferredClose := startRailsServer("Local Rails server", &geoProxyEndpointResponseBody) + defer deferredClose() + + ws, wsDeferredClose, _ := startWorkhorseServer(railsServer.URL, true) + defer wsDeferredClose() + + runTestCases(t, ws, testCases) +} + func newUpstreamConfig(authBackend string) *config.Config { return &config.Config{ Version: "123", @@ -284,9 +288,13 @@ func startWorkhorseServer(railsServerURL string, enableGeoProxyFeature bool) (*h } cfg := newUpstreamConfig(railsServerURL) upstreamHandler := newUpstream(*cfg, logrus.StandardLogger(), myConfigureRoutes) - ws := httptest.NewServer(upstreamHandler) + + // Secret should be configured before the first Geo API poll happens on server start + // to prevent race conditions where the first API call happens without a secret path testhelper.ConfigureSecret() + ws := httptest.NewServer(upstreamHandler) + waitForNextApiPoll := func() {} if enableGeoProxyFeature { diff --git a/yarn.lock b/yarn.lock index a42f69f54f9..12752d5937f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -904,20 +904,20 @@ stylelint-declaration-strict-value "1.7.7" stylelint-scss "3.18.0" -"@gitlab/svgs@1.218.0": - version "1.218.0" - resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.218.0.tgz#0715e2ef50b5cb83813e1a5e29d5919a96685734" - integrity sha512-eckixyumeWogykEUZfP4pGjoRdhdWQIFwSTM0ks5tQqza+BikcL2xvxzicJs69T1IiCKwYtEpR1c3T/hSx39Mg== +"@gitlab/svgs@1.219.0": + version "1.219.0" + resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.219.0.tgz#82735876b98bd3a46f42b4a424b45086ed48e7ac" + integrity sha512-UOy0+6A6PTbjNHLFBc70ATYztsiQfWHPORgPGnzugYJz2F7ewMr4p6R8d9avFqMNtVB5mIHSnbrsr0pp0XVMGA== "@gitlab/tributejs@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8" integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw== -"@gitlab/ui@32.21.0": - version "32.21.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.21.0.tgz#d4a5e9b369aa91a9512fb742d1cd5f23f1653a7c" - integrity sha512-ssobbMDscsJa/mWqAne6xOAsNy3pQNOahzn4oLyVmmNPiMRZNcS4mEda28MwexntlkzEkOxWHjmkoa4YI0JQqQ== +"@gitlab/ui@32.28.0": + version "32.28.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.28.0.tgz#afa0e1dee66ec438126b2706e0860e2c622fc867" + integrity sha512-DudY+jPIxjGymyB2KgdexmxV+sbjCy3or7LzviiI0jb5jCIiqNoZ4F4G+P0T+Z1FbLBgEXjgUaEZw09edka/lg== dependencies: "@babel/standalone" "^7.0.0" bootstrap-vue "2.20.1"