diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-26 18:07:59 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-06-26 18:07:59 +0300 |
commit | c46e0d0c271a21b67a3412faf750d27dd63432bb (patch) | |
tree | 58d5ac8c94228c1c282f3ca3929eeb61b65c6c36 | |
parent | a46fed716c91d449fde2f08d25e0f4530170bc15 (diff) |
Add latest changes from gitlab-org/gitlab@master
107 files changed, 966 insertions, 361 deletions
diff --git a/.dockerignore b/.dockerignore index 0782627230a..a2d54fa65dd 100644 --- a/.dockerignore +++ b/.dockerignore @@ -80,4 +80,3 @@ /spec/ /symbol/ /tmp/ -/vendor/ diff --git a/.gitlab/ci/gitlab-gems.gitlab-ci.yml b/.gitlab/ci/gitlab-gems.gitlab-ci.yml index adab179d2a2..aff272935c5 100644 --- a/.gitlab/ci/gitlab-gems.gitlab-ci.yml +++ b/.gitlab/ci/gitlab-gems.gitlab-ci.yml @@ -5,3 +5,11 @@ gems gitlab-rspec: trigger: include: gems/gitlab-rspec/.gitlab-ci.yml strategy: depend + +gems gitlab-utils: + extends: + - .gems:rules:gitlab-utils + needs: [] + trigger: + include: gems/gitlab-utils/.gitlab-ci.yml + strategy: depend diff --git a/.gitlab/ci/package-and-test-nightly/main.gitlab-ci.yml b/.gitlab/ci/package-and-test-nightly/main.gitlab-ci.yml index 34b4e853415..d1062250040 100644 --- a/.gitlab/ci/package-and-test-nightly/main.gitlab-ci.yml +++ b/.gitlab/ci/package-and-test-nightly/main.gitlab-ci.yml @@ -97,6 +97,17 @@ integration-opensearch-compatibility-version-2: OPENSEARCH_VERSION: "2.0.1" QA_SCENARIO: "Test::Integration::Opensearch" +# ------------------------------------------ +# Relative url +# ------------------------------------------ +relative-url: + extends: + - .qa + - .ee + - .parallel + variables: + QA_SCENARIO: Test::Instance::RelativeUrl + # ========================================== # Post test stage # ========================================== diff --git a/.gitlab/ci/package-and-test/main.gitlab-ci.yml b/.gitlab/ci/package-and-test/main.gitlab-ci.yml index fcea49e3103..8ed1bb5d067 100644 --- a/.gitlab/ci/package-and-test/main.gitlab-ci.yml +++ b/.gitlab/ci/package-and-test/main.gitlab-ci.yml @@ -81,6 +81,7 @@ instance-ff-inverse: # ------------------------------------------ # ========== instance =========== + instance: extends: - .parallel @@ -151,38 +152,6 @@ praefect-selective-parallel: variables: QA_TESTS: "" -# ========== relative-url =========== - -relative-url: - extends: - - .qa - - .parallel - variables: - QA_SCENARIO: Test::Instance::RelativeUrl - rules: - - !reference [.rules:test:qa-parallel, rules] - - if: $QA_SUITES =~ /Test::Instance::All/ - -relative-url-selective: - extends: .qa - variables: - QA_SCENARIO: Test::Instance::RelativeUrl - rules: - - !reference [.rules:test:qa-selective, rules] - - if: $QA_SUITES =~ /Test::Instance::All/ - -relative-url-selective-parallel: - extends: - - .qa - - .parallel - variables: - QA_SCENARIO: Test::Instance::RelativeUrl - rules: - - !reference [.rules:test:qa-selective-parallel, rules] - - if: $QA_SUITES =~ /Test::Instance::All/ - variables: - QA_TESTS: "" - # ========== decomposition-single-db =========== decomposition-single-db: diff --git a/.gitlab/ci/preflight.gitlab-ci.yml b/.gitlab/ci/preflight.gitlab-ci.yml index 968402b2ea5..6a2ea85f393 100644 --- a/.gitlab/ci/preflight.gitlab-ci.yml +++ b/.gitlab/ci/preflight.gitlab-ci.yml @@ -24,9 +24,6 @@ - .ruby-cache - .preflight:rules:rails-production-server-boot - .use-pg13 - variables: - BUNDLE_WITHOUT: "development:test" - BUNDLE_WITH: "production" # Test the puma configuration present in `config/puma.rb.example` rails-production-server-boot-puma-example: diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 6acc2dea2e2..007e5cefb89 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -2135,6 +2135,11 @@ - <<: *if-merge-request changes: ["gems/gitlab-rspec/**/*"] +.gems:rules:gitlab-utils: + rules: + - <<: *if-merge-request + changes: ["gems/gitlab-utils/**/*"] + ####################### # Vendored gems rules # ####################### diff --git a/.rubocop_todo/gitlab/doc_url.yml b/.rubocop_todo/gitlab/doc_url.yml index 119de2296ce..13537a142a1 100644 --- a/.rubocop_todo/gitlab/doc_url.yml +++ b/.rubocop_todo/gitlab/doc_url.yml @@ -43,7 +43,6 @@ Gitlab/DocUrl: - 'lib/gitlab/pagination/keyset/unsupported_scope_order.rb' - 'lib/gitlab/redis/hll.rb' - 'lib/gitlab/slash_commands/presenters/help.rb' - - 'lib/gitlab/utils/strong_memoize.rb' - 'lib/initializer_connections.rb' - 'lib/security/ci_configuration/base_build_action.rb' - 'lib/tasks/db_obsolete_ignored_columns.rake' diff --git a/.rubocop_todo/gitlab/namespaced_class.yml b/.rubocop_todo/gitlab/namespaced_class.yml index 8a0dd63ae7c..4ab42f01790 100644 --- a/.rubocop_todo/gitlab/namespaced_class.yml +++ b/.rubocop_todo/gitlab/namespaced_class.yml @@ -1248,7 +1248,6 @@ Gitlab/NamespacedClass: - 'lib/gitlab/user_access.rb' - 'lib/gitlab/user_access_snippet.rb' - 'lib/gitlab/uuid.rb' - - 'lib/gitlab/version_info.rb' - 'lib/gitlab/visibility_level_checker.rb' - 'lib/gitlab/wiki_file_finder.rb' - 'lib/gitlab/workhorse.rb' diff --git a/.rubocop_todo/layout/argument_alignment.yml b/.rubocop_todo/layout/argument_alignment.yml index 826e20fb40f..e774c081ef4 100644 --- a/.rubocop_todo/layout/argument_alignment.yml +++ b/.rubocop_todo/layout/argument_alignment.yml @@ -1820,7 +1820,6 @@ Layout/ArgumentAlignment: - 'spec/lib/gitlab/usage_data_queries_spec.rb' - 'spec/lib/gitlab/usage_data_spec.rb' - 'spec/lib/gitlab/utils/lazy_attributes_spec.rb' - - 'spec/lib/gitlab/utils_spec.rb' - 'spec/lib/gitlab/workhorse_spec.rb' - 'spec/lib/google_api/cloud_platform/client_spec.rb' - 'spec/lib/peek/views/detailed_view_spec.rb' diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml index 1deedbfc96e..a5fafa59388 100644 --- a/.rubocop_todo/layout/line_length.yml +++ b/.rubocop_todo/layout/line_length.yml @@ -4230,7 +4230,6 @@ Layout/LineLength: - 'spec/lib/gitlab/utils/measuring_spec.rb' - 'spec/lib/gitlab/utils/nokogiri_spec.rb' - 'spec/lib/gitlab/utils/usage_data_spec.rb' - - 'spec/lib/gitlab/utils_spec.rb' - 'spec/lib/gitlab/web_ide/config/entry/global_spec.rb' - 'spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb' - 'spec/lib/gitlab/webpack/file_loader_spec.rb' diff --git a/.rubocop_todo/lint/ambiguous_regexp_literal.yml b/.rubocop_todo/lint/ambiguous_regexp_literal.yml index c3b06ede5be..4754e381780 100644 --- a/.rubocop_todo/lint/ambiguous_regexp_literal.yml +++ b/.rubocop_todo/lint/ambiguous_regexp_literal.yml @@ -66,7 +66,6 @@ Lint/AmbiguousRegexpLiteral: - 'spec/lib/gitlab/pagination/keyset/iterator_spec.rb' - 'spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb' - 'spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb' - - 'spec/lib/gitlab/utils/strong_memoize_spec.rb' - 'spec/lib/gitlab/web_ide/config/entry/global_spec.rb' - 'spec/lib/gitlab/web_ide/config/entry/terminal_spec.rb' - 'spec/lib/object_storage/direct_upload_spec.rb' diff --git a/.rubocop_todo/lint/symbol_conversion.yml b/.rubocop_todo/lint/symbol_conversion.yml index 147cd66f993..8799414c911 100644 --- a/.rubocop_todo/lint/symbol_conversion.yml +++ b/.rubocop_todo/lint/symbol_conversion.yml @@ -117,7 +117,6 @@ Lint/SymbolConversion: - 'spec/lib/gitlab/search/abuse_validators/no_abusive_coercion_from_string_validator_spec.rb' - 'spec/lib/gitlab/slug/path_spec.rb' - 'spec/lib/gitlab/tracking_spec.rb' - - 'spec/lib/gitlab/utils_spec.rb' - 'spec/lib/google_api/cloud_platform/client_spec.rb' - 'spec/lib/service_ping/devops_report_spec.rb' - 'spec/models/integrations/prometheus_spec.rb' diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml index af708ad54e5..1ce003ecd2f 100644 --- a/.rubocop_todo/rspec/context_wording.yml +++ b/.rubocop_todo/rspec/context_wording.yml @@ -2062,9 +2062,7 @@ RSpec/ContextWording: - 'spec/lib/gitlab/usage_data_spec.rb' - 'spec/lib/gitlab/utils/lazy_attributes_spec.rb' - 'spec/lib/gitlab/utils/mime_type_spec.rb' - - 'spec/lib/gitlab/utils/strong_memoize_spec.rb' - 'spec/lib/gitlab/utils/usage_data_spec.rb' - - 'spec/lib/gitlab/utils_spec.rb' - 'spec/lib/gitlab/view/presenter/base_spec.rb' - 'spec/lib/gitlab/visibility_level_checker_spec.rb' - 'spec/lib/gitlab/visibility_level_spec.rb' diff --git a/.rubocop_todo/rspec/missing_feature_category.yml b/.rubocop_todo/rspec/missing_feature_category.yml index e3829a97b02..3cf0ed5c38c 100644 --- a/.rubocop_todo/rspec/missing_feature_category.yml +++ b/.rubocop_todo/rspec/missing_feature_category.yml @@ -4413,7 +4413,6 @@ RSpec/MissingFeatureCategory: - 'spec/lib/gitlab/utils/safe_inline_hash_spec.rb' - 'spec/lib/gitlab/utils/sanitize_node_link_spec.rb' - 'spec/lib/gitlab/utils/usage_data_spec.rb' - - 'spec/lib/gitlab/utils_spec.rb' - 'spec/lib/gitlab/uuid_spec.rb' - 'spec/lib/gitlab/verify/job_artifacts_spec.rb' - 'spec/lib/gitlab/verify/lfs_objects_spec.rb' diff --git a/.rubocop_todo/style/percent_literal_delimiters.yml b/.rubocop_todo/style/percent_literal_delimiters.yml index 2e03bbf4557..bb29652fe96 100644 --- a/.rubocop_todo/style/percent_literal_delimiters.yml +++ b/.rubocop_todo/style/percent_literal_delimiters.yml @@ -843,7 +843,6 @@ Style/PercentLiteralDelimiters: - 'spec/lib/gitlab/usage_data_counters/hll_redis_counter_spec.rb' - 'spec/lib/gitlab/usage_data_spec.rb' - 'spec/lib/gitlab/utils/log_limited_array_spec.rb' - - 'spec/lib/gitlab/utils_spec.rb' - 'spec/lib/gitlab/webpack/graphql_known_operations_spec.rb' - 'spec/lib/gitlab/wiki_pages/front_matter_parser_spec.rb' - 'spec/lib/object_storage/config_spec.rb' diff --git a/.rubocop_todo/style/string_concatenation.yml b/.rubocop_todo/style/string_concatenation.yml index 4e3b17fe4c0..34e4549a987 100644 --- a/.rubocop_todo/style/string_concatenation.yml +++ b/.rubocop_todo/style/string_concatenation.yml @@ -212,7 +212,6 @@ Style/StringConcatenation: - 'spec/lib/gitlab/themes_spec.rb' - 'spec/lib/gitlab/throttle_spec.rb' - 'spec/lib/gitlab/tree_summary_spec.rb' - - 'spec/lib/gitlab/utils_spec.rb' - 'spec/lib/gitlab/visibility_level_spec.rb' - 'spec/lib/gitlab/wiki_pages/front_matter_parser_spec.rb' - 'spec/lib/gitlab/workhorse_spec.rb' @@ -20,6 +20,11 @@ gem 'bootsnap', '~> 1.16.0', require: false gem 'openssl', '~> 3.0' gem 'ipaddr', '~> 1.2.5' +# GitLab Monorepo Gems +group :monorepo do + gem 'gitlab-utils', path: 'gems/gitlab-utils' +end + # Responders respond_to and respond_with gem 'responders', '~> 3.0' diff --git a/Gemfile.lock b/Gemfile.lock index 8844732d35e..395293f17a2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,6 +5,16 @@ PATH rspec (~> 3.0) PATH + remote: gems/gitlab-utils + specs: + gitlab-utils (0.1.0) + actionview (>= 6.1.7.2) + activesupport (>= 6.1.7.2) + addressable (~> 2.8) + nokogiri (~> 1.15.2) + rake (~> 13.0) + +PATH remote: vendor/gems/attr_encrypted specs: attr_encrypted (3.2.4) @@ -1778,6 +1788,7 @@ DEPENDENCIES gitlab-rspec! gitlab-sidekiq-fetcher! gitlab-styles (~> 10.0.0) + gitlab-utils! gitlab_chronic_duration (~> 0.10.6.2) gitlab_omniauth-ldap (~> 2.2.0) gitlab_quality-test_tooling (~> 0.8.1) diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js index 39a7a76e91f..3b55611a8fa 100644 --- a/app/assets/javascripts/behaviors/markdown/render_gfm.js +++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js @@ -9,7 +9,7 @@ import { renderJSONTable } from './render_json_table'; function initPopovers(elements) { if (!elements.length) return; - import(/* webpackChunkName: 'IssuablePopoverBundle' */ '~/issuable/popover') + import(/* webpackChunkName: 'IssuablePopoverBundle' */ 'ee_else_ce/issuable/popover') .then(({ default: initIssuablePopovers }) => { initIssuablePopovers(elements); }) @@ -39,7 +39,7 @@ export function renderGFM(element) { '.js-render-mermaid', '[lang="json"][data-lang-params="table"]', '.gfm-project_member', - '.gfm-issue, .gfm-work_item, .gfm-merge_request', + '.gfm-issue, .gfm-work_item, .gfm-merge_request, .gfm-epic', '.js-render-metrics', '.js-render-observability', ].map((selector) => Array.from(element.querySelectorAll(selector))); diff --git a/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js index bd9e41ac0ba..22e9b2b9709 100644 --- a/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js +++ b/app/assets/javascripts/behaviors/markdown/render_sandboxed_mermaid.js @@ -72,11 +72,14 @@ function fixElementSource(el) { export function getSandboxFrameSrc() { const path = joinPaths(gon.relative_url_root || '', SANDBOX_FRAME_PATH); - if (!darkModeEnabled()) { - return path; + let absoluteUrl = relativePathToAbsolute(path, getBaseURL()); + if (darkModeEnabled()) { + absoluteUrl = setUrlParams({ darkMode: darkModeEnabled() }, absoluteUrl); } - const absoluteUrl = relativePathToAbsolute(path, getBaseURL()); - return setUrlParams({ darkMode: darkModeEnabled() }, absoluteUrl); + if (window.gon?.relative_url_root) { + absoluteUrl = setUrlParams({ relativeRootPath: window.gon.relative_url_root }, absoluteUrl); + } + return absoluteUrl; } function renderMermaidEl(el, source) { diff --git a/app/assets/javascripts/issuable/components/status_box.vue b/app/assets/javascripts/issuable/components/status_box.vue index 799c0a18444..a83884dd261 100644 --- a/app/assets/javascripts/issuable/components/status_box.vue +++ b/app/assets/javascripts/issuable/components/status_box.vue @@ -4,7 +4,13 @@ import Vue from 'vue'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { fetchPolicies } from '~/lib/graphql'; import { __ } from '~/locale'; -import { STATUS_CLOSED, STATUS_OPEN, TYPE_ISSUE, TYPE_MERGE_REQUEST } from '~/issues/constants'; +import { + STATUS_CLOSED, + STATUS_OPEN, + TYPE_ISSUE, + TYPE_MERGE_REQUEST, + TYPE_EPIC, +} from '~/issues/constants'; export const badgeState = Vue.observable({ state: '', @@ -18,17 +24,22 @@ const CLASSES = { merged: 'issuable-status-badge-merged', }; -const ISSUE_ICONS = { - opened: 'issues', - locked: 'issues', - closed: 'issue-closed', -}; - -const MERGE_REQUEST_ICONS = { - opened: 'merge-request-open', - locked: 'merge-request-open', - closed: 'merge-request-close', - merged: 'merge', +const ICONS = { + [TYPE_EPIC]: { + opened: 'epic', + closed: 'epic-closed', + }, + [TYPE_ISSUE]: { + opened: 'issues', + locked: 'issues', + closed: 'issue-closed', + }, + [TYPE_MERGE_REQUEST]: { + opened: 'merge-request-open', + locked: 'merge-request-open', + closed: 'merge-request-close', + merged: 'merge', + }, }; const STATUS = { @@ -91,10 +102,8 @@ export default { return STATUS[this.state]; }, badgeIcon() { - if (this.issuableType === TYPE_ISSUE) { - return ISSUE_ICONS[this.state]; - } - return MERGE_REQUEST_ICONS[this.state]; + const type = this.issuableType || TYPE_MERGE_REQUEST; + return ICONS[type][this.state]; }, }, created() { diff --git a/app/assets/javascripts/issuable/popover/components/issue_popover.vue b/app/assets/javascripts/issuable/popover/components/issue_popover.vue index 55fb3958e82..044a1bba7ad 100644 --- a/app/assets/javascripts/issuable/popover/components/issue_popover.vue +++ b/app/assets/javascripts/issuable/popover/components/issue_popover.vue @@ -28,7 +28,7 @@ export default { type: HTMLAnchorElement, required: true, }, - projectPath: { + namespacePath: { type: String, required: true, }, @@ -65,10 +65,10 @@ export default { query, update: (data) => data.project.issue, variables() { - const { projectPath, iid } = this; + const { namespacePath, iid } = this; return { - projectPath, + projectPath: namespacePath, iid, }; }, @@ -100,7 +100,7 @@ export default { <!-- eslint-disable @gitlab/vue-require-i18n-strings --> <div> <work-item-type-icon v-if="!$apollo.queries.issue.loading" :work-item-type="issue.type" /> - <span class="gl-text-secondary">{{ `${projectPath}#${iid}` }}</span> + <span class="gl-text-secondary">{{ `${namespacePath}#${iid}` }}</span> </div> <!-- eslint-enable @gitlab/vue-require-i18n-strings --> diff --git a/app/assets/javascripts/issuable/popover/components/mr_popover.vue b/app/assets/javascripts/issuable/popover/components/mr_popover.vue index af93430963e..e2c2181684f 100644 --- a/app/assets/javascripts/issuable/popover/components/mr_popover.vue +++ b/app/assets/javascripts/issuable/popover/components/mr_popover.vue @@ -19,7 +19,7 @@ export default { type: HTMLAnchorElement, required: true, }, - projectPath: { + namespacePath: { type: String, required: true, }, @@ -76,10 +76,10 @@ export default { query, update: (data) => data.project.mergeRequest, variables() { - const { projectPath, iid } = this; + const { namespacePath, iid } = this; return { - projectPath, + projectPath: namespacePath, iid, }; }, @@ -108,7 +108,7 @@ export default { <h5 v-if="!$apollo.queries.mergeRequest.loading" class="my-2">{{ title }}</h5> <!-- eslint-disable @gitlab/vue-require-i18n-strings --> <div class="gl-text-secondary"> - {{ `${projectPath}!${iid}` }} + {{ `${namespacePath}!${iid}` }} </div> <!-- eslint-enable @gitlab/vue-require-i18n-strings --> </div> diff --git a/app/assets/javascripts/issuable/popover/index.js b/app/assets/javascripts/issuable/popover/index.js index 9430419685b..58f015fe40e 100644 --- a/app/assets/javascripts/issuable/popover/index.js +++ b/app/assets/javascripts/issuable/popover/index.js @@ -4,7 +4,7 @@ import createDefaultClient from '~/lib/graphql'; import IssuePopover from './components/issue_popover.vue'; import MRPopover from './components/mr_popover.vue'; -const componentsByReferenceType = { +export const componentsByReferenceTypeMap = { issue: IssuePopover, work_item: IssuePopover, merge_request: MRPopover, @@ -26,9 +26,10 @@ const popoverMountedAttr = 'data-popover-mounted'; * Adds a MergeRequestPopover component to the body, hands over as much data as the target element has in data attributes. * loads based on data-project-path and data-iid more data about an MR from the API and sets it on the popover */ -const handleIssuablePopoverMount = ({ +export const handleIssuablePopoverMount = ({ + componentsByReferenceType = componentsByReferenceTypeMap, apolloProvider, - projectPath, + namespacePath, title, iid, referenceType, @@ -42,7 +43,7 @@ const handleIssuablePopoverMount = ({ new PopoverComponent({ propsData: { target, - projectPath, + namespacePath, iid, cachedTitle: title, }, @@ -53,7 +54,7 @@ const handleIssuablePopoverMount = ({ }, 200); // 200ms delay so not every mouseover triggers Popover + API Call }; -export default (elements) => { +export default (elements, issuablePopoverMount = handleIssuablePopoverMount) => { if (elements.length > 0) { Vue.use(VueApollo); @@ -63,15 +64,16 @@ export default (elements) => { const listenerAddedAttr = 'data-popover-listener-added'; elements.forEach((el) => { - const { projectPath, iid, referenceType } = el.dataset; + const { projectPath, groupPath, iid, referenceType } = el.dataset; const title = el.dataset.mrTitle || el.title; + const namespacePath = groupPath || projectPath; - if (!el.getAttribute(listenerAddedAttr) && projectPath && title && iid && referenceType) { + if (!el.getAttribute(listenerAddedAttr) && namespacePath && title && iid && referenceType) { el.addEventListener('mouseenter', ({ target }) => { if (!el.getAttribute(popoverMountedAttr)) { - handleIssuablePopoverMount({ + issuablePopoverMount({ apolloProvider, - projectPath, + namespacePath, title, iid, referenceType, diff --git a/app/assets/javascripts/lib/mermaid.js b/app/assets/javascripts/lib/mermaid.js index bbc1d8ae1e1..5e62a023777 100644 --- a/app/assets/javascripts/lib/mermaid.js +++ b/app/assets/javascripts/lib/mermaid.js @@ -1,6 +1,13 @@ import mermaid from 'mermaid'; import { getParameterByName } from '~/lib/utils/url_utility'; +import { resetServiceWorkersPublicPath } from '~/lib/utils/webpack'; +const resetWebpackPublicPath = () => { + window.gon = { relative_url_root: getParameterByName('relativeRootPath') }; + resetServiceWorkersPublicPath(); +}; + +resetWebpackPublicPath(); const setIframeRenderedSize = (h, w) => { const { origin } = window.location; window.parent.postMessage({ h, w }, origin); diff --git a/app/assets/javascripts/lib/utils/datetime/date_format_utility.js b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js index e1a57bf4589..b0264796d90 100644 --- a/app/assets/javascripts/lib/utils/datetime/date_format_utility.js +++ b/app/assets/javascripts/lib/utils/datetime/date_format_utility.js @@ -3,6 +3,7 @@ import dateFormat from '~/lib/dateformat'; import { roundToNearestHalf } from '~/lib/utils/common_utils'; import { sanitize } from '~/lib/dompurify'; import { s__, n__, __, sprintf } from '~/locale'; +import { parsePikadayDate } from './pikaday_utility'; /** * Returns i18n month names array. @@ -420,3 +421,34 @@ export const formatUtcOffset = (offset) => { * @returns {String} the UTC timezone with the offset, e.g. `[UTC+2] Berlin, [UTC 0] London` */ export const formatTimezone = ({ offset, name }) => `[UTC${formatUtcOffset(offset)}] ${name}`; + +/** + * Returns humanized string showing date range from provided start and due dates. + * + * @param {Date} startDate + * @param {Date} dueDate + * @returns + */ +export const humanTimeframe = (startDate, dueDate) => { + const start = startDate ? parsePikadayDate(startDate) : null; + const due = dueDate ? parsePikadayDate(dueDate) : null; + + if (startDate && dueDate) { + const startDateInWords = dateInWords(start, true, start.getFullYear() === due.getFullYear()); + const dueDateInWords = dateInWords(due, true); + + return sprintf(__('%{startDate} – %{dueDate}'), { + startDate: startDateInWords, + dueDate: dueDateInWords, + }); + } else if (startDate && !dueDate) { + return sprintf(__('%{startDate} – No due date'), { + startDate: dateInWords(start, true, false), + }); + } else if (!startDate && dueDate) { + return sprintf(__('No start date – %{dueDate}'), { + dueDate: dateInWords(due, true, false), + }); + } + return ''; +}; diff --git a/app/assets/javascripts/tracking/constants.js b/app/assets/javascripts/tracking/constants.js index 968e866eedd..0e440750fdb 100644 --- a/app/assets/javascripts/tracking/constants.js +++ b/app/assets/javascripts/tracking/constants.js @@ -25,3 +25,7 @@ export const URLS_CACHE_STORAGE_KEY = 'gl-snowplow-pseudonymized-urls'; export const REFERRER_TTL = 24 * 60 * 60 * 1000; export const GOOGLE_ANALYTICS_ID_COOKIE_NAME = '_ga'; + +export const GITLAB_INTERNAL_EVENT_CATEGORY = 'InternalEventTracking'; + +export const SERVICE_PING_SCHEMA = 'iglu:com.gitlab/gitlab_service_ping/jsonschema/1-0-0'; diff --git a/app/assets/javascripts/tracking/index.js b/app/assets/javascripts/tracking/index.js index 472ce3c5bbf..6494838abac 100644 --- a/app/assets/javascripts/tracking/index.js +++ b/app/assets/javascripts/tracking/index.js @@ -2,8 +2,10 @@ import { getAllExperimentContexts } from '~/experimentation/utils'; import { DEFAULT_SNOWPLOW_OPTIONS } from './constants'; import getStandardContext from './get_standard_context'; import Tracking from './tracking'; +import InternalEvents from './internal_events'; export { Tracking as default }; +export { InternalEvents }; /** * Tracker initialization as defined in: diff --git a/app/assets/javascripts/tracking/internal_events.js b/app/assets/javascripts/tracking/internal_events.js new file mode 100644 index 00000000000..a69f192f520 --- /dev/null +++ b/app/assets/javascripts/tracking/internal_events.js @@ -0,0 +1,36 @@ +import API from '~/api'; + +import Tracking from './tracking'; +import { GITLAB_INTERNAL_EVENT_CATEGORY, SERVICE_PING_SCHEMA } from './constants'; + +const InternalEvents = { + /** + * Returns an implementation of this class in the form of + * a Vue mixin. + * + * @param {Object} opts - default options for all events + * @returns {Object} + */ + mixin(opts = {}) { + return { + mixins: [Tracking.mixin(opts)], + methods: { + track_event(event) { + API.trackRedisHllUserEvent(event); + this.track(event, { + context: { + schema: SERVICE_PING_SCHEMA, + data: { + event_name: event, + data_source: 'redis_hll', + }, + }, + category: GITLAB_INTERNAL_EVENT_CATEGORY, + }); + }, + }, + }; + }, +}; + +export default InternalEvents; diff --git a/app/controllers/concerns/uploads_actions.rb b/app/controllers/concerns/uploads_actions.rb index 222fcc17222..29b61264322 100644 --- a/app/controllers/concerns/uploads_actions.rb +++ b/app/controllers/concerns/uploads_actions.rb @@ -110,7 +110,7 @@ module UploadsActions if uploader_mounted? model.public_send(upload_mount) # rubocop:disable GitlabSecurity/PublicSend else - build_uploader_from_upload || build_uploader_from_params + build_uploader_from_upload end end strong_memoize_attr :uploader @@ -125,21 +125,6 @@ module UploadsActions end # rubocop: enable CodeReuse/ActiveRecord - def build_uploader_from_params - return unless uploader = build_uploader - - uploader.retrieve_from_store!(params[:filename]) - - Gitlab::AppJsonLogger.info( - message: 'Deprecated usage of build_uploader_from_params', - uploader_class: uploader.class.name, - path: params[:filename], - exists: uploader.exists? - ) - - uploader - end - def build_uploader return unless params[:secret] && params[:filename] diff --git a/app/models/concerns/project_features_compatibility.rb b/app/models/concerns/project_features_compatibility.rb index 76c733b1c0b..c70100c03c8 100644 --- a/app/models/concerns/project_features_compatibility.rb +++ b/app/models/concerns/project_features_compatibility.rb @@ -4,7 +4,7 @@ # # After migrating issues_enabled merge_requests_enabled builds_enabled snippets_enabled and wiki_enabled # fields to a new table "project_features", support for the old fields is still needed in the API. -require 'gitlab/utils' +require 'gitlab/utils/all' module ProjectFeaturesCompatibility extend ActiveSupport::Concern diff --git a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json index fb6b80e0725..9cfb62d4439 100644 --- a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json +++ b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json @@ -32,12 +32,12 @@ }, { "field": "SEARCH_MAX_DEPTH", - "label": "Search maximum depth", + "label": "Search Maximum Depth", "type": "string", "default_value": "", "value": "", "size": "SMALL", - "description": "Maximum depth of language and framework detection" + "description": "Specifies the number of directory levels to be included in the repository search phase during SAST analysis. SAST scanner searches through the repository to detect the programming languages used and selects the corresponding analyzers. After that, the entire repository is analyzed." } ], "analyzers": [ @@ -80,56 +80,72 @@ "label": "Kubesec", "enabled": true, "description": "Kubernetes manifests, Helm Charts", - "variables": [] + "variables": [ + + ] }, { "name": "nodejs-scan", "label": "Node.js Scan", "enabled": true, "description": "Node.js", - "variables": [] + "variables": [ + + ] }, { "name": "phpcs-security-audit", "label": "PHP Security Audit", "enabled": true, "description": "PHP", - "variables": [] + "variables": [ + + ] }, { "name": "pmd-apex", "label": "PMD APEX", "enabled": true, "description": "Apex (Salesforce)", - "variables": [] + "variables": [ + + ] }, { "name": "security-code-scan", "label": "Security Code Scan", "enabled": true, "description": ".NET Core, .NET Framework", - "variables": [] + "variables": [ + + ] }, { "name": "semgrep", "label": "Semgrep", "enabled": true, "description": "Multi-language scanning", - "variables": [] + "variables": [ + + ] }, { "name": "sobelow", "label": "Sobelow", "enabled": true, "description": "Elixir (Phoenix)", - "variables": [] + "variables": [ + + ] }, { "name": "spotbugs", "label": "Spotbugs", "enabled": true, "description": "Groovy, Java, Scala", - "variables": [] + "variables": [ + + ] } ] -}
\ No newline at end of file +} diff --git a/bin/audit-event-type b/bin/audit-event-type index fec34724c7c..e9d72aaba46 100755 --- a/bin/audit-event-type +++ b/bin/audit-event-type @@ -11,9 +11,10 @@ require 'yaml' require 'fileutils' require 'uri' require 'readline' +require_relative '../config/bundler_setup' +require 'gitlab/utils/all' require_relative '../lib/gitlab/audit/type/shared' unless defined?(::Gitlab::Audit::Type::Shared) -require_relative '../lib/gitlab/utils' unless defined?(::Gitlab::Utils) module AuditEventTypeHelpers Abort = Class.new(StandardError) diff --git a/config/application.rb b/config/application.rb index 06153b377f3..c8bb56ce956 100644 --- a/config/application.rb +++ b/config/application.rb @@ -12,6 +12,8 @@ require 'action_mailer/railtie' require 'action_cable/engine' require 'rails/test_unit/railtie' +require 'gitlab/utils/all' + Bundler.require(*Rails.groups) module Gitlab @@ -49,7 +51,6 @@ module Gitlab ActiveSupport.to_time_preserves_timezone = false require_dependency Rails.root.join('lib/gitlab') - require_dependency Rails.root.join('lib/gitlab/utils') require_dependency Rails.root.join('lib/gitlab/action_cable/config') require_dependency Rails.root.join('lib/gitlab/redis/wrapper') require_dependency Rails.root.join('lib/gitlab/redis/cache') diff --git a/config/environments/test.rb b/config/environments/test.rb index da91752549e..b919df45214 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -4,7 +4,7 @@ require 'gitlab/testing/request_blocker_middleware' require 'gitlab/testing/robots_blocker_middleware' require 'gitlab/testing/request_inspector_middleware' require 'gitlab/testing/clear_process_memory_cache_middleware' -require 'gitlab/utils' +require 'gitlab/utils/all' Rails.application.configure do # Make sure the middleware is inserted first in middleware chain diff --git a/db/docs/subscription_user_add_on_assignments.yml b/db/docs/subscription_user_add_on_assignments.yml new file mode 100644 index 00000000000..acd9b821115 --- /dev/null +++ b/db/docs/subscription_user_add_on_assignments.yml @@ -0,0 +1,10 @@ +--- +table_name: subscription_user_add_on_assignments +description: Tracks the assignment of an add-on to a user within a namespace +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123967 +milestone: '16.2' +feature_categories: +- seat_cost_management +classes: +- GitlabSubscriptions::UserAddOnAssignment +gitlab_schema: gitlab_main diff --git a/db/migrate/20230616164309_create_subscription_user_add_on_assignments.rb b/db/migrate/20230616164309_create_subscription_user_add_on_assignments.rb new file mode 100644 index 00000000000..cb184cd1987 --- /dev/null +++ b/db/migrate/20230616164309_create_subscription_user_add_on_assignments.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class CreateSubscriptionUserAddOnAssignments < Gitlab::Database::Migration[2.1] + UNIQUE_INDEX_NAME = 'uniq_idx_user_add_on_assignments_on_add_on_purchase_and_user' + + def change + create_table :subscription_user_add_on_assignments do |t| + t.bigint :add_on_purchase_id, null: false + t.bigint :user_id, null: false + + t.timestamps_with_timezone null: false + + t.index [:add_on_purchase_id, :user_id], unique: true, name: UNIQUE_INDEX_NAME + t.index :user_id + end + end +end diff --git a/db/migrate/20230616164705_add_foreign_key_add_on_purchase_id_on_subscription_user_add_on_assignments.rb b/db/migrate/20230616164705_add_foreign_key_add_on_purchase_id_on_subscription_user_add_on_assignments.rb new file mode 100644 index 00000000000..d0d89bd5027 --- /dev/null +++ b/db/migrate/20230616164705_add_foreign_key_add_on_purchase_id_on_subscription_user_add_on_assignments.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class AddForeignKeyAddOnPurchaseIdOnSubscriptionUserAddOnAssignments < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + def up + add_concurrent_foreign_key :subscription_user_add_on_assignments, :subscription_add_on_purchases, + column: :add_on_purchase_id, on_delete: :cascade + end + + def down + with_lock_retries do + remove_foreign_key :subscription_user_add_on_assignments, column: :add_on_purchase_id + end + end +end diff --git a/db/migrate/20230616164731_add_foreign_key_user_id_on_subscription_user_add_on_assignments.rb b/db/migrate/20230616164731_add_foreign_key_user_id_on_subscription_user_add_on_assignments.rb new file mode 100644 index 00000000000..a28c798deec --- /dev/null +++ b/db/migrate/20230616164731_add_foreign_key_user_id_on_subscription_user_add_on_assignments.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class AddForeignKeyUserIdOnSubscriptionUserAddOnAssignments < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + + def up + add_concurrent_foreign_key :subscription_user_add_on_assignments, :users, column: :user_id, on_delete: :cascade + end + + def down + with_lock_retries do + remove_foreign_key :subscription_user_add_on_assignments, column: :user_id + end + end +end diff --git a/db/schema_migrations/20230616164309 b/db/schema_migrations/20230616164309 new file mode 100644 index 00000000000..b9fbdc7d33e --- /dev/null +++ b/db/schema_migrations/20230616164309 @@ -0,0 +1 @@ +f3b14748f1702972e7f5069edd9ed25d9896dfb11f4fc4a4386ca9c94533e10a
\ No newline at end of file diff --git a/db/schema_migrations/20230616164705 b/db/schema_migrations/20230616164705 new file mode 100644 index 00000000000..1bcb723524b --- /dev/null +++ b/db/schema_migrations/20230616164705 @@ -0,0 +1 @@ +75310614bb98a598b8425aa87a0a4a6561fa1b166461d55329c21aff849d71fc
\ No newline at end of file diff --git a/db/schema_migrations/20230616164731 b/db/schema_migrations/20230616164731 new file mode 100644 index 00000000000..2588271d9ac --- /dev/null +++ b/db/schema_migrations/20230616164731 @@ -0,0 +1 @@ +e6308ee437b6e57da16e1b8aff1d6a571ef849c4c7cccafe940710c799fa6eea
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 35c119628ce..5cff7ab4337 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -23057,6 +23057,23 @@ CREATE SEQUENCE subscription_add_ons_id_seq ALTER SEQUENCE subscription_add_ons_id_seq OWNED BY subscription_add_ons.id; +CREATE TABLE subscription_user_add_on_assignments ( + id bigint NOT NULL, + add_on_purchase_id bigint NOT NULL, + user_id bigint NOT NULL, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL +); + +CREATE SEQUENCE subscription_user_add_on_assignments_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +ALTER SEQUENCE subscription_user_add_on_assignments_id_seq OWNED BY subscription_user_add_on_assignments.id; + CREATE TABLE subscriptions ( id integer NOT NULL, user_id integer, @@ -25862,6 +25879,8 @@ ALTER TABLE ONLY subscription_add_on_purchases ALTER COLUMN id SET DEFAULT nextv ALTER TABLE ONLY subscription_add_ons ALTER COLUMN id SET DEFAULT nextval('subscription_add_ons_id_seq'::regclass); +ALTER TABLE ONLY subscription_user_add_on_assignments ALTER COLUMN id SET DEFAULT nextval('subscription_user_add_on_assignments_id_seq'::regclass); + ALTER TABLE ONLY subscriptions ALTER COLUMN id SET DEFAULT nextval('subscriptions_id_seq'::regclass); ALTER TABLE ONLY suggestions ALTER COLUMN id SET DEFAULT nextval('suggestions_id_seq'::regclass); @@ -28351,6 +28370,9 @@ ALTER TABLE ONLY subscription_add_on_purchases ALTER TABLE ONLY subscription_add_ons ADD CONSTRAINT subscription_add_ons_pkey PRIMARY KEY (id); +ALTER TABLE ONLY subscription_user_add_on_assignments + ADD CONSTRAINT subscription_user_add_on_assignments_pkey PRIMARY KEY (id); + ALTER TABLE ONLY subscriptions ADD CONSTRAINT subscriptions_pkey PRIMARY KEY (id); @@ -32910,6 +32932,8 @@ CREATE INDEX index_subscription_add_on_purchases_on_subscription_add_on_id ON su CREATE UNIQUE INDEX index_subscription_add_ons_on_name ON subscription_add_ons USING btree (name); +CREATE INDEX index_subscription_user_add_on_assignments_on_user_id ON subscription_user_add_on_assignments USING btree (user_id); + CREATE INDEX index_subscriptions_on_project_id ON subscriptions USING btree (project_id); CREATE UNIQUE INDEX index_subscriptions_on_subscribable_and_user_id_and_project_id ON subscriptions USING btree (subscribable_id, subscribable_type, user_id, project_id); @@ -33556,6 +33580,8 @@ CREATE UNIQUE INDEX u_project_compliance_standards_adherence_for_reporting ON pr CREATE UNIQUE INDEX uniq_idx_packages_packages_on_project_id_name_version_ml_model ON packages_packages USING btree (project_id, name, version) WHERE (package_type = 14); +CREATE UNIQUE INDEX uniq_idx_user_add_on_assignments_on_add_on_purchase_and_user ON subscription_user_add_on_assignments USING btree (add_on_purchase_id, user_id); + CREATE UNIQUE INDEX uniq_pkgs_deb_grp_architectures_on_distribution_id_and_name ON packages_debian_group_architectures USING btree (distribution_id, name); CREATE UNIQUE INDEX uniq_pkgs_deb_grp_components_on_distribution_id_and_name ON packages_debian_group_components USING btree (distribution_id, name); @@ -35227,6 +35253,9 @@ ALTER TABLE ONLY notification_settings ALTER TABLE ONLY lists ADD CONSTRAINT fk_0d3f677137 FOREIGN KEY (board_id) REFERENCES boards(id) ON DELETE CASCADE; +ALTER TABLE ONLY subscription_user_add_on_assignments + ADD CONSTRAINT fk_0d89020c49 FOREIGN KEY (add_on_purchase_id) REFERENCES subscription_add_on_purchases(id) ON DELETE CASCADE; + ALTER TABLE ONLY deployment_approvals ADD CONSTRAINT fk_0f58311058 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; @@ -35596,6 +35625,9 @@ ALTER TABLE ONLY integrations ALTER TABLE ONLY user_interacted_projects ADD CONSTRAINT fk_722ceba4f7 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; +ALTER TABLE ONLY subscription_user_add_on_assignments + ADD CONSTRAINT fk_724c2df9a8 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; + ALTER TABLE ONLY vulnerabilities ADD CONSTRAINT fk_725465b774 FOREIGN KEY (dismissed_by_id) REFERENCES users(id) ON DELETE SET NULL; diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md index df364a3f737..7a24db4347b 100644 --- a/doc/administration/instance_limits.md +++ b/doc/administration/instance_limits.md @@ -19,8 +19,6 @@ Read more about [configuring rate limits](../security/rate_limits.md). ### Issue creation -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28129) in GitLab 12.10. - This setting limits the request rate to the issue creation endpoint. Read more about [issue creation rate limits](../user/admin_area/settings/rate_limit_on_issues_creation.md). @@ -37,8 +35,6 @@ Read more about [User and IP rate limits](../user/admin_area/settings/user_and_i ### By raw endpoint -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30829) in GitLab 12.2. - This setting limits the request rate per endpoint. Read more about [raw endpoint rate limits](../user/admin_area/settings/rate_limits_on_raw_endpoints.md). @@ -69,8 +65,6 @@ Read more about [protected path rate limits](../user/admin_area/settings/protect ### Package Registry -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57029) in GitLab 13.12. - This setting limits the request rate on the Packages API per user or IP. For more information, see [Package Registry Rate Limits](../user/admin_area/settings/package_registry_rate_limits.md). @@ -107,18 +101,16 @@ This setting limits the request rate on deprecated API endpoints per user or IP ### Import/Export -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35728) in GitLab 13.2. - This setting limits the import/export actions for groups and projects. | Limit | Default (per minute per user) | |-------------------------|-------------------------------| -| Project Import | 6 | -| Project Export | 6 | -| Project Export Download | 1 | -| Group Import | 6 | -| Group Export | 6 | -| Group Export Download | 1 | +| Project Import | 6 | +| Project Export | 6 | +| Project Export Download | 1 | +| Group Import | 6 | +| Group Export | 6 | +| Group Export Download | 1 | Read more about [import/export rate limits](../user/admin_area/settings/import_export_rate_limits.md). @@ -162,10 +154,10 @@ Set the limit to `0` to disable it. This setting limits search requests as follows: -| Limit | Default (requests per minute) | -|-------------------------|-------------------------------| -| Authenticated user | 300 | -| Unauthenticated user | 100 | +| Limit | Default (requests per minute) | +|----------------------|-------------------------------| +| Authenticated user | 300 | +| Unauthenticated user | 100 | Search requests that exceed the search rate limit per minute return the following error: @@ -191,8 +183,6 @@ Read more about [Gitaly concurrency limits](gitaly/configure_gitaly.md#limit-rpc ## Number of comments per issue, merge request, or commit -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22388) in GitLab 12.4. - There's a limit to the number of comments that can be submitted on an issue, merge request, or commit. When the limit is reached, system notes can still be added so that the history of events is not lost, but the user-submitted @@ -202,8 +192,6 @@ comment fails. ## Size of comments and descriptions of issues, merge requests, and epics -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/61974) in GitLab 12.2. - There is a limit to the size of comments and descriptions of issues, merge requests, and epics. Attempting to add a body of text larger than the limit, results in an error, and the item is also not created. @@ -214,8 +202,6 @@ It's possible that this limit changes to a lower number in the future. ## Size of commit titles and descriptions -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292039) in GitLab 13.9. - Commits with arbitrarily large messages may be pushed to GitLab, but the following display limits apply: @@ -231,9 +217,6 @@ are processed. ## Number of issues in the milestone overview -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39453) in GitLab 12.10. -> - [Set](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58168) to 500 in GitLab 13.11. - The maximum number of issues loaded on the milestone overview page is 500. When the number exceeds the limit the page displays an alert and links to a paginated [issue list](../user/project/issues/managing_issues.md) of all issues in the milestone. @@ -242,8 +225,6 @@ When the number exceeds the limit the page displays an alert and links to a pagi ## Number of pipelines per Git push -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/51401) in GitLab 11.10. - When pushing multiple changes with a single Git push, like multiple tags or branches, only four tag or branch pipelines can be triggered. This limit prevents the accidental creation of a large number of pipelines when using `git push --all` or `git push --mirror`. @@ -259,12 +240,10 @@ instance if too many changes are pushed at once and a flood of pipelines are cre ## Retention of activity history -Activity history for projects and individuals' profiles was limited to one year until [GitLab 11.4](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/52246) when it was extended to two years, and in [GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/issues/33840) to three years. +Activity history for projects and individuals' profiles is limited to three years. ## Number of embedded metrics -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14939) in GitLab 12.7. - There is a limit when embedding metrics in GitLab Flavored Markdown (GLFM) for performance reasons. - **Max limit**: 100 embeds. @@ -343,8 +322,6 @@ Blocked recursive webhook calls are logged in `auth.log` with the message `"Recu ## Pull Mirroring Interval -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/237891) in GitLab 13.7. - The [minimum wait time between pull refreshes](../user/project/repository/mirror/index.md) defaults to 300 seconds (5 minutes). For example, a pull refresh only runs once in a given 300 second period, regardless of how many times you trigger it. @@ -362,8 +339,6 @@ Plan.default.actual_limits.update!(pull_mirror_interval_seconds: 200) ## Incoming emails from auto-responders -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30327) in GitLab 12.4. - GitLab ignores all incoming emails sent from auto-responders by looking for the `X-Autoreply` header. Such emails don't create comments on issues or merge requests. @@ -376,8 +351,6 @@ and to limit memory consumption. ## Max offset allowed by the REST API for offset-based pagination -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34565) in GitLab 13.0. - When using offset-based pagination in the REST API, there is a limit to the maximum requested offset into the set of results. This limit is only applied to endpoints that also support keyset-based pagination. More information about pagination options can be @@ -401,8 +374,6 @@ Set the limit to `0` to disable it. ### Number of jobs in active pipelines -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32823) in GitLab 12.6. - The total number of jobs in active pipelines can be limited per project. This limit is checked each time a new pipeline is created. An active pipeline is any pipeline in one of the following states: @@ -433,8 +404,6 @@ Set the limit to `0` to disable it. ### Maximum time jobs can run -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16777) in GitLab 12.3. - The default maximum time that jobs can run for is 60 minutes. Jobs that run for more than 60 minutes time out. @@ -447,8 +416,6 @@ You can change the maximum time a job can run before it times out: ### Maximum number of deployment jobs in a pipeline -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46931) in GitLab 13.7. - You can limit the maximum number of deployment jobs in a pipeline. A deployment is any job with an [`environment`](../ci/environments/index.md) specified. The number of deployments in a pipeline is checked at pipeline creation. Pipelines that have @@ -470,8 +437,6 @@ Set the limit to `0` to disable it. ### Number of CI/CD subscriptions to a project -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9045) in GitLab 12.9. - The total number of subscriptions can be limited per project. This limit is checked each time a new subscription is created. @@ -516,8 +481,6 @@ This limit is [enabled on GitLab.com](../user/gitlab_com/index.md#gitlab-cicd). ### Number of pipeline schedules -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29566) in GitLab 12.10. - The total number of pipeline schedules can be limited per project. This limit is checked each time a new pipeline schedule is created. If a new pipeline schedule would cause the total number of pipeline schedules to exceed the limit, the @@ -585,8 +548,6 @@ This limit is [enabled on GitLab.com](../user/gitlab_com/index.md#gitlab-cicd). ### Number of instance level variables -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216097) in GitLab 13.1. - The total number of instance level CI/CD variables is limited at the instance level. This limit is checked each time a new instance level variable is created. If a new variable would cause the total number of variables to exceed the limit, the new variable is not created. @@ -639,8 +600,6 @@ Plan.default.actual_limits.update!(project_ci_variables: 10000) ### Maximum file size per type of artifact -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37226) in GitLab 13.3. - Job artifacts defined with [`artifacts:reports`](../ci/yaml/index.md#artifactsreports) that are uploaded by the runner are rejected if the file size exceeds the maximum file size limit. The limit is determined by comparing the project's @@ -655,35 +614,35 @@ setting is used: | Artifact limit name | Default value | |---------------------------------------------|---------------| -| `ci_max_artifact_size_accessibility` | 0 | -| `ci_max_artifact_size_api_fuzzing` | 0 | -| `ci_max_artifact_size_archive` | 0 | -| `ci_max_artifact_size_browser_performance` | 0 | -| `ci_max_artifact_size_cluster_applications` | 0 | -| `ci_max_artifact_size_cobertura` | 0 | -| `ci_max_artifact_size_codequality` | 0 | -| `ci_max_artifact_size_container_scanning` | 0 | -| `ci_max_artifact_size_coverage_fuzzing` | 0 | -| `ci_max_artifact_size_dast` | 0 | -| `ci_max_artifact_size_dependency_scanning` | 0 | -| `ci_max_artifact_size_dotenv` | 0 | -| `ci_max_artifact_size_junit` | 0 | -| `ci_max_artifact_size_license_management` | 0 | -| `ci_max_artifact_size_license_scanning` | 0 | -| `ci_max_artifact_size_load_performance` | 0 | -| `ci_max_artifact_size_lsif` | 100 MB ([Introduced at 20 MB](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37226) in GitLab 13.3 and [raised to 100 MB](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46980) in GitLab 13.6.) | -| `ci_max_artifact_size_metadata` | 0 | -| `ci_max_artifact_size_metrics_referee` | 0 | -| `ci_max_artifact_size_metrics` | 0 | -| `ci_max_artifact_size_network_referee` | 0 | -| `ci_max_artifact_size_performance` | 0 | -| `ci_max_artifact_size_requirements` | 0 | -| `ci_max_artifact_size_requirements_v2` | 0 | -| `ci_max_artifact_size_sast` | 0 | -| `ci_max_artifact_size_secret_detection` | 0 | -| `ci_max_artifact_size_terraform` | 5 MB ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37018) in GitLab 13.3) | -| `ci_max_artifact_size_trace` | 0 | -| `ci_max_artifact_size_cyclonedx` | 1 MB | +| `ci_max_artifact_size_accessibility` | 0 | +| `ci_max_artifact_size_api_fuzzing` | 0 | +| `ci_max_artifact_size_archive` | 0 | +| `ci_max_artifact_size_browser_performance` | 0 | +| `ci_max_artifact_size_cluster_applications` | 0 | +| `ci_max_artifact_size_cobertura` | 0 | +| `ci_max_artifact_size_codequality` | 0 | +| `ci_max_artifact_size_container_scanning` | 0 | +| `ci_max_artifact_size_coverage_fuzzing` | 0 | +| `ci_max_artifact_size_dast` | 0 | +| `ci_max_artifact_size_dependency_scanning` | 0 | +| `ci_max_artifact_size_dotenv` | 0 | +| `ci_max_artifact_size_junit` | 0 | +| `ci_max_artifact_size_license_management` | 0 | +| `ci_max_artifact_size_license_scanning` | 0 | +| `ci_max_artifact_size_load_performance` | 0 | +| `ci_max_artifact_size_lsif` | 100 MB | +| `ci_max_artifact_size_metadata` | 0 | +| `ci_max_artifact_size_metrics_referee` | 0 | +| `ci_max_artifact_size_metrics` | 0 | +| `ci_max_artifact_size_network_referee` | 0 | +| `ci_max_artifact_size_performance` | 0 | +| `ci_max_artifact_size_requirements` | 0 | +| `ci_max_artifact_size_requirements_v2` | 0 | +| `ci_max_artifact_size_sast` | 0 | +| `ci_max_artifact_size_secret_detection` | 0 | +| `ci_max_artifact_size_terraform` | 5 MB | +| `ci_max_artifact_size_trace` | 0 | +| `ci_max_artifact_size_cyclonedx` | 1 MB | For example, to set the `ci_max_artifact_size_junit` limit to 10 MB on a self-managed installation, run the following in the [GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session): @@ -732,10 +691,10 @@ GitLab SaaS subscribers have different limits defined per plan, affecting all pr Self-managed GitLab Premium and Ultimate limits are defined by a default plan that affects all projects: -| Runner scope | Default value | -|---------------------------------------------|---------------| -| `ci_registered_group_runners` | 1000 | -| `ci_registered_project_runners` | 1000 | +| Runner scope | Default value | +|---------------------------------|---------------| +| `ci_registered_group_runners` | 1000 | +| `ci_registered_project_runners` | 1000 | To update these limits, run the following in the [GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session): @@ -839,28 +798,20 @@ Plan.default.actual_limits.update!(dotenv_size: 5.kilobytes) ### Limit inbound incident management alerts -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17859) in GitLab 12.5. - This setting limits the number of inbound alert payloads over a period of time. Read more about [incident management rate limits](../user/admin_area/settings/rate_limit_on_pipelines_creation.md). ### Prometheus Alert JSON payloads -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19940) in GitLab 12.6. - Prometheus alert payloads sent to the `notify.json` endpoint are limited to 1 MB in size. ### Generic Alert JSON payloads -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/16441) in GitLab 12.4. - Alert payloads sent to the `notify.json` endpoint are limited to 1 MB in size. ### Metrics dashboard YAML files -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34834) in GitLab 13.2. - The memory occupied by a parsed metrics dashboard YAML file cannot exceed 1 MB. The maximum depth of each YAML file is limited to 100. The maximum depth of a YAML @@ -891,8 +842,6 @@ panel_groups: ## Environment Dashboard limits **(PREMIUM)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33895) in GitLab 13.4. - See [Environment Dashboard](../ci/environments/environments_dashboard.md#adding-a-project-to-the-dashboard) for the maximum number of displayed projects. ## Environment data on deploy boards @@ -932,8 +881,6 @@ Reports that go over the 20 MB limit aren't loaded. Affected reports: ### Maximum file size indexed -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8638) in GitLab 13.3. - You can set a limit on the content of repository files that are indexed in Elasticsearch. Any files larger than this limit only index the filename. The file content is neither indexed nor searchable. @@ -949,8 +896,6 @@ is pre-allocated during indexing. ### Maximum field length -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/201826) in GitLab 12.8. - You can set a limit on the content of text fields indexed for advanced search. Setting a maximum helps to reduce the load of the indexing processes. If any text field exceeds this limit, then the text is truncated to this number of @@ -987,8 +932,6 @@ The maximum allowed [push size](../user/admin_area/settings/account_and_limit_se ### Webhooks and Project Services -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31009) in GitLab 12.4. - Total number of changes (branches or tags) in a single push. If changes are more than the specified limit, hooks are not executed. @@ -999,8 +942,6 @@ More information can be found in these documentations: ### Activities -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31007) in GitLab 12.4. - Total number of changes (branches or tags) in a single push to determine whether individual push events or a bulk push event are created. @@ -1010,8 +951,6 @@ More information can be found in the [Push event activities limit and bulk push ### File Size Limits -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218017) in GitLab 13.4. - The default maximum file size for a package that's uploaded to the [GitLab Package Registry](../user/packages/package_registry/index.md) varies by format: - Conan: 3 GB @@ -1074,14 +1013,6 @@ varies by file type: - Image blob: 5 GB - Image manifest: 10 MB -## Branch retargeting on merge - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/320902) in GitLab 13.9. - -If a branch is merged while open merge requests still point to it, GitLab can -retarget merge requests pointing to the now-merged branch. For more information, see -[Update merge requests when target branch merges](../user/project/merge_requests/index.md#update-merge-requests-when-target-branch-merges). - ## Maximum number of assignees and reviewers > - Maximum assignees [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/368936) in GitLab 15.6. diff --git a/doc/ci/runners/saas/macos_saas_runner.md b/doc/ci/runners/saas/macos_saas_runner.md index 836a14d7521..a559fc7d53e 100644 --- a/doc/ci/runners/saas/macos_saas_runner.md +++ b/doc/ci/runners/saas/macos_saas_runner.md @@ -45,7 +45,7 @@ Each image runs a specific version of macOS and Xcode. | (none, awaiting macOS 13) | `beta` | NOTE: -Each time you run a job that requires tooling or dependencies not available in the base image, those items must be added to the newly provisioned build VM increasing the total job duration. +If your job requires tooling or dependencies not available in our available images, those can only be installed in the job execution. ## Image update policy @@ -88,9 +88,6 @@ test: - echo "running scripts in the test job" ``` -NOTE: -You can specify a different Xcode image to run a job. To do so, replace the value for the `image` keyword with the value of the [virtual machine image name](#supported-macos-images) from the list of available images. The default value is our latest image. - ## Code signing iOS Projects with fastlane Before you can integrate GitLab with Apple services, install to a device, or deploy to the Apple App Store, you must [code sign](https://developer.apple.com/support/code-signing/) your application. @@ -106,22 +103,22 @@ Related topics: - [Code Signing Best Practice Guide](https://codesigning.guide/) - [fastlane authentication with Apple Services guide](https://docs.fastlane.tools/getting-started/ios/authentication/) -## Known Limitations and Usage Constraints - -- If the VM image does not include the specific software version you need for your job, then the job execution time will increase as the required software needs to be fetched and installed. -- At this time, it is not possible to bring your own OS image. -- The keychain for user `gitlab` is not publicly available. You must create a keychain instead. - ## Optimizing Homebrew By default, Homebrew checks for updates at the start of any operation. Homebrew has a -release cycle that may be more frequent than the GitLab MacOS image release cycle. This +release cycle that may be more frequent than the GitLab macOS image release cycle. This difference in release cycles may cause steps that call `brew` to take extra time to complete while Homebrew makes updates. -To reduce build time due to unintended Homebrew updates, set the `HOMEBREW_NO_AUTO_UPDATE` variable in `.gitlab-ci.yml` : +To reduce build time due to unintended Homebrew updates, set the `HOMEBREW_NO_AUTO_UPDATE` variable in `.gitlab-ci.yml`: ```yaml variables: HOMEBREW_NO_AUTO_UPDATE: 1 ``` + +## Known issues and usage constraints + +- If the VM image does not include the specific software version you need for your job, the required software must be fetched and installed. This causes an increase in job execution time. +- It is not possible to bring your own OS image. +- The keychain for user `gitlab` is not publicly available. You must create a keychain instead. diff --git a/doc/development/gems.md b/doc/development/gems.md index 4d364242efd..55963438347 100644 --- a/doc/development/gems.md +++ b/doc/development/gems.md @@ -107,7 +107,7 @@ You can see example adding new Gem: [!121676](https://gitlab.com/gitlab-org/gitl rspec: image: "ruby:${RUBY_VERSION}" cache: - key: gitlab-<name-of-gem> + key: gitlab-<name-of-gem>-${RUBY_VERSION} paths: - gitlab-<name-of-gem>/vendor/ruby before_script: diff --git a/doc/development/pipelines/index.md b/doc/development/pipelines/index.md index cadba17f03e..9e6abaa8eb3 100644 --- a/doc/development/pipelines/index.md +++ b/doc/development/pipelines/index.md @@ -755,10 +755,14 @@ graph RL; click 2_5-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations" 2_5-1 --> 1-3 & 1-6 & 1-14 & 1-15; - 3_2-1["rspec:coverage (5 minutes)"]; + ac-1["rspec:artifact-collector (2 minutes)<br/>(workaround for 'needs' limitation)"]; + class ac-1 criticalPath; + ac-1 --> 2_5-1; + + 3_2-1["rspec:coverage (3 minutes)"]; class 3_2-1 criticalPath; click 3_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7248745&udv=0" - 3_2-1 -.->|"(don't use needs<br/>because of limitations)"| 2_5-1; + 3_2-1 --> ac-1; 4_3-1["rspec:undercoverage (1.3 minutes)"]; class 4_3-1 criticalPath; diff --git a/doc/integration/advanced_search/elasticsearch_troubleshooting.md b/doc/integration/advanced_search/elasticsearch_troubleshooting.md index e8eace7bd16..d3a065f1f99 100644 --- a/doc/integration/advanced_search/elasticsearch_troubleshooting.md +++ b/doc/integration/advanced_search/elasticsearch_troubleshooting.md @@ -256,6 +256,24 @@ Bulk requests getting rejected by the Elasticsearch nodes are likely due to load Ensure that your Elasticsearch cluster meets the [system requirements](elasticsearch.md#system-requirements) and has enough resources to perform bulk operations. See also the error ["429 (Too Many Requests)"](#indexing-fails-with-error-elastic-error-429-too-many-requests). +### Indexing fails with `strict_dynamic_mapping_exception` + +Indexing might fail if all [advanced search migrations were not finished before doing a major upgrade](elasticsearch.md#all-migrations-must-be-finished-before-doing-a-major-upgrade). +A large Sidekiq backlog might accompany this error. To fix the indexing failures, you must re-index the database, repositories, and wikis. + +1. Pause indexing so Sidekiq can catch up: + + ```shell + sudo gitlab-rake gitlab:elastic:pause_indexing + ``` + +1. [Recreate the index from scratch](#last-resort-to-recreate-an-index). +1. Resume indexing: + + ```shell + sudo gitlab-rake gitlab:elastic:resume_indexing + ``` + ### Last resort to recreate an index There may be cases where somehow data never got indexed and it's not in the diff --git a/doc/user/permissions.md b/doc/user/permissions.md index 0b02de59ab4..c3a3c4f6d3c 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -58,11 +58,11 @@ The following table lists project permissions available for each role: | Action | Guest | Reporter | Developer | Maintainer | Owner | |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|----------|-----------|------------|----------| | [Analytics](analytics/index.md):<br>View [issue analytics](analytics/issue_analytics.md) | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Analytics](analytics/index.md):<br>View [merge request analytics](analytics/merge_request_analytics.md) | ✓ | ✓ | ✓ | ✓ | ✓ | | [Analytics](analytics/index.md):<br>View [value stream analytics](group/value_stream_analytics/index.md) | ✓ | ✓ | ✓ | ✓ | ✓ | | [Analytics](analytics/index.md):<br>View [DORA metrics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ | | [Analytics](analytics/index.md):<br>View [CI/CD analytics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ | | [Analytics](analytics/index.md):<br>View [code review analytics](analytics/code_review_analytics.md) | | ✓ | ✓ | ✓ | ✓ | +| [Analytics](analytics/index.md):<br>View [merge request analytics](analytics/merge_request_analytics.md) | | ✓ | ✓ | ✓ | ✓ | | [Analytics](analytics/index.md):<br>View [repository analytics](analytics/repository_analytics.md) | | ✓ | ✓ | ✓ | ✓ | | [Application security](application_security/index.md):<br>View licenses in [dependency list](application_security/dependency_list/index.md) | | | ✓ | ✓ | ✓ | | [Application security](application_security/index.md):<br>Create and run [on-demand DAST scans](application_security/dast/proxy-based.md#on-demand-scans) | | | ✓ | ✓ | ✓ | diff --git a/gems/gitlab-rspec/.gitlab-ci.yml b/gems/gitlab-rspec/.gitlab-ci.yml index 0932753d1e7..95bdc51cb7d 100644 --- a/gems/gitlab-rspec/.gitlab-ci.yml +++ b/gems/gitlab-rspec/.gitlab-ci.yml @@ -12,7 +12,7 @@ workflow: rspec: image: "ruby:${RUBY_VERSION}" cache: - key: gitlab-rspec + key: gitlab-rspec-${RUBY_VERSION} paths: - gitlab-rspec/vendor/ruby before_script: diff --git a/gems/gitlab-rspec/gitlab-rspec.gemspec b/gems/gitlab-rspec/gitlab-rspec.gemspec index 061647190ec..f9cc83bb497 100644 --- a/gems/gitlab-rspec/gitlab-rspec.gemspec +++ b/gems/gitlab-rspec/gitlab-rspec.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |spec| spec.description = "A set of useful helpers to configure RSpec with various stubs and CI configs." spec.homepage = "https://gitlab.com/gitlab-org/gitlab/-/tree/master/gems/gitlab-rspec" spec.license = "MIT" - spec.required_ruby_version = ">= 3.0" + spec.required_ruby_version = ">= 2.7" spec.files = Dir['lib/**/*.rb'] spec.test_files = Dir['spec/**/*'] diff --git a/gems/gitlab-utils/.gitignore b/gems/gitlab-utils/.gitignore new file mode 100644 index 00000000000..b04a8c840df --- /dev/null +++ b/gems/gitlab-utils/.gitignore @@ -0,0 +1,11 @@ +/.bundle/ +/.yardoc +/_yardoc/ +/coverage/ +/doc/ +/pkg/ +/spec/reports/ +/tmp/ + +# rspec failure tracking +.rspec_status diff --git a/gems/gitlab-utils/.gitlab-ci.yml b/gems/gitlab-utils/.gitlab-ci.yml new file mode 100644 index 00000000000..ab92953b57d --- /dev/null +++ b/gems/gitlab-utils/.gitlab-ci.yml @@ -0,0 +1,30 @@ +# You can override the included template(s) by including variable overrides +# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings +# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings +# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings +# Note that environment variables can be set in several places +# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence +workflow: + rules: + - if: $CI_MERGE_REQUEST_ID + +rspec: + image: "ruby:${RUBY_VERSION}" + cache: + key: gitlab-utils-${RUBY_VERSION} + paths: + - gitlab-utils/vendor/ruby + before_script: + - cd gems/gitlab-utils + - ruby -v # Print out ruby version for debugging + - gem install bundler --no-document # Bundler is not installed with the image + - bundle config set --local path 'vendor' # Install dependencies into ./vendor/ruby + - bundle config set with 'development' + - bundle config set --local frozen 'true' # Disallow Gemfile.lock changes on CI + - bundle config # Show bundler configuration + - bundle install -j $(nproc) + script: + - bundle exec rspec + parallel: + matrix: + - RUBY_VERSION: ["2.7", "3.0", "3.1", "3.2"] diff --git a/gems/gitlab-utils/.rspec b/gems/gitlab-utils/.rspec new file mode 100644 index 00000000000..34c5164d9b5 --- /dev/null +++ b/gems/gitlab-utils/.rspec @@ -0,0 +1,3 @@ +--format documentation +--color +--require spec_helper diff --git a/gems/gitlab-utils/.rubocop.yml b/gems/gitlab-utils/.rubocop.yml new file mode 100644 index 00000000000..7f0d48d1b2b --- /dev/null +++ b/gems/gitlab-utils/.rubocop.yml @@ -0,0 +1,31 @@ +inherit_from: + - ../../.rubocop.yml + +CodeReuse/ActiveRecord: + Enabled: false + +Gitlab/DocUrl: + Enabled: false + +Gitlab/NamespacedClass: + Enabled: false + +AllCops: + TargetRubyVersion: 3.0 + +Naming/FileName: + Exclude: + - spec/**/*.rb + - lib/gitlab/utils/all.rb + +Lint/AmbiguousRegexpLiteral: + Exclude: + - spec/**/*.rb + +RSpec/InstanceVariable: + Exclude: + - spec/**/*.rb + +Lint/BinaryOperatorWithIdenticalOperands: + Exclude: + - spec/**/*.rb diff --git a/gems/gitlab-utils/Gemfile b/gems/gitlab-utils/Gemfile new file mode 100644 index 00000000000..2c7228c874c --- /dev/null +++ b/gems/gitlab-utils/Gemfile @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +# Specify your gem's dependencies in gitlab-utils.gemspec +gemspec + +group :development, :test do + gem 'gitlab-rspec', path: '../gitlab-rspec' +end diff --git a/gems/gitlab-utils/Gemfile.lock b/gems/gitlab-utils/Gemfile.lock new file mode 100644 index 00000000000..e7f954eeea3 --- /dev/null +++ b/gems/gitlab-utils/Gemfile.lock @@ -0,0 +1,193 @@ +PATH + remote: ../gitlab-rspec + specs: + gitlab-rspec (0.1.0) + rspec (~> 3.0) + +PATH + remote: . + specs: + gitlab-utils (0.1.0) + actionview (>= 6.1.7.2) + activesupport (>= 6.1.7.2) + addressable (~> 2.8) + nokogiri (~> 1.15.2) + rake (~> 13.0) + +GEM + remote: https://rubygems.org/ + specs: + actionpack (7.0.5) + actionview (= 7.0.5) + activesupport (= 7.0.5) + rack (~> 2.0, >= 2.2.4) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actionview (7.0.5) + activesupport (= 7.0.5) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activesupport (7.0.5) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) + ast (2.4.2) + benchmark-malloc (0.2.0) + benchmark-perf (0.6.0) + benchmark-trend (0.4.0) + binding_of_caller (1.0.0) + debug_inspector (>= 0.0.1) + builder (3.2.4) + coderay (1.1.3) + concurrent-ruby (1.2.2) + crass (1.0.6) + debug_inspector (1.1.0) + diff-lcs (1.5.0) + erubi (1.12.0) + factory_bot (6.2.1) + activesupport (>= 5.0.0) + factory_bot_rails (6.2.0) + factory_bot (~> 6.2.0) + railties (>= 5.0.0) + gitlab-styles (10.0.0) + rubocop (~> 1.43.0) + rubocop-graphql (~> 0.18) + rubocop-performance (~> 1.15) + rubocop-rails (~> 2.17) + rubocop-rspec (~> 2.18) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + json (2.6.3) + loofah (2.21.3) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + method_source (1.0.0) + mini_portile2 (2.8.2) + minitest (5.18.1) + nokogiri (1.15.2) + mini_portile2 (~> 2.8.2) + racc (~> 1.4) + parallel (1.22.1) + parser (3.2.0.0) + ast (~> 2.4.1) + proc_to_ast (0.1.0) + coderay + parser + unparser + public_suffix (5.0.0) + racc (1.7.1) + rack (2.2.7) + rack-test (2.1.0) + rack (>= 1.3) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (7.0.5) + actionpack (= 7.0.5) + activesupport (= 7.0.5) + method_source + rake (>= 12.2) + thor (~> 1.0) + zeitwerk (~> 2.5) + rainbow (3.1.1) + rake (13.0.6) + regexp_parser (2.6.0) + rexml (3.2.5) + rspec (3.12.0) + rspec-core (~> 3.12.0) + rspec-expectations (~> 3.12.0) + rspec-mocks (~> 3.12.0) + rspec-benchmark (0.6.0) + benchmark-malloc (~> 0.2) + benchmark-perf (~> 0.6) + benchmark-trend (~> 0.4) + rspec (>= 3.0) + rspec-core (3.12.0) + rspec-support (~> 3.12.0) + rspec-expectations (3.12.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.12.0) + rspec-mocks (3.12.3) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.12.0) + rspec-parameterized (1.0.0) + rspec-parameterized-core (< 2) + rspec-parameterized-table_syntax (< 2) + rspec-parameterized-core (1.0.0) + parser + proc_to_ast + rspec (>= 2.13, < 4) + unparser + rspec-parameterized-table_syntax (1.0.0) + binding_of_caller + rspec-parameterized-core (< 2) + rspec-rails (6.0.1) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.11) + rspec-expectations (~> 3.11) + rspec-mocks (~> 3.11) + rspec-support (~> 3.11) + rspec-support (3.12.0) + rubocop (1.43.0) + json (~> 2.3) + parallel (~> 1.10) + parser (>= 3.2.0.0) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.24.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.24.1) + parser (>= 3.1.1.0) + rubocop-capybara (2.18.0) + rubocop (~> 1.41) + rubocop-graphql (0.19.0) + rubocop (>= 0.87, < 2) + rubocop-performance (1.18.0) + rubocop (>= 1.7.0, < 2.0) + rubocop-ast (>= 0.4.0) + rubocop-rails (2.19.1) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.33.0, < 2.0) + rubocop-rspec (2.18.1) + rubocop (~> 1.33) + rubocop-capybara (~> 2.17) + ruby-progressbar (1.11.0) + thor (1.2.2) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (2.4.2) + unparser (0.6.7) + diff-lcs (~> 1.3) + parser (>= 3.2.0) + zeitwerk (2.6.8) + +PLATFORMS + ruby + +DEPENDENCIES + factory_bot_rails (~> 6.2.0) + gitlab-rspec! + gitlab-styles (~> 10.0.0) + gitlab-utils! + rspec-benchmark (~> 0.6.0) + rspec-parameterized (~> 1.0) + rspec-rails (~> 6.0.1) + rubocop (~> 1.21) + rubocop-rspec (~> 2.18.1) + +BUNDLED WITH + 2.4.4 diff --git a/gems/gitlab-utils/README.md b/gems/gitlab-utils/README.md new file mode 100644 index 00000000000..f7c7d83888b --- /dev/null +++ b/gems/gitlab-utils/README.md @@ -0,0 +1,8 @@ +# Gitlab::Utils + +This Gem contains all code that is not dependent on application code +or business logic and provides a generic functions like: + +- safe parsing of YAML +- version comparisions +- `strong_memoize` diff --git a/gems/gitlab-utils/Rakefile b/gems/gitlab-utils/Rakefile new file mode 100644 index 00000000000..cca71754493 --- /dev/null +++ b/gems/gitlab-utils/Rakefile @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require "bundler/gem_tasks" +require "rspec/core/rake_task" + +RSpec::Core::RakeTask.new(:spec) + +require "rubocop/rake_task" + +RuboCop::RakeTask.new + +task default: %i[spec rubocop] diff --git a/gems/gitlab-utils/gitlab-utils.gemspec b/gems/gitlab-utils/gitlab-utils.gemspec new file mode 100644 index 00000000000..15e40ecc279 --- /dev/null +++ b/gems/gitlab-utils/gitlab-utils.gemspec @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require_relative "lib/gitlab/utils/version" + +Gem::Specification.new do |spec| + spec.name = "gitlab-utils" + spec.version = Gitlab::Utils::Version::VERSION + spec.authors = ["group::tenant scale"] + spec.email = ["engineering@gitlab.com"] + + spec.summary = "GitLab's common helper methods" + spec.description = "A set of useful helpers methods to perform various conversions and checks." + spec.homepage = 'https://gitlab.com/gitlab-org/gitlab/-/tree/master/gems/gitlab-utils' + spec.license = 'MIT' + spec.required_ruby_version = ">= 3.0" + + spec.files = Dir['lib/**/*.rb'] + spec.test_files = Dir['spec/**/*'] + spec.require_paths = ["lib"] + + spec.add_runtime_dependency 'actionview', '>= 6.1.7.2' + spec.add_runtime_dependency 'activesupport', '>= 6.1.7.2' + spec.add_runtime_dependency 'addressable', '~> 2.8' + spec.add_runtime_dependency 'nokogiri', '~> 1.15.2' + spec.add_runtime_dependency 'rake', '~> 13.0' + + spec.add_development_dependency 'factory_bot_rails', '~> 6.2.0' + spec.add_development_dependency 'gitlab-styles', '~> 10.0.0' + spec.add_development_dependency 'rspec-benchmark', '~> 0.6.0' + spec.add_development_dependency 'rspec-parameterized', '~> 1.0' + spec.add_development_dependency 'rspec-rails', '~> 6.0.1' + spec.add_development_dependency 'rubocop', '~> 1.21' + spec.add_development_dependency 'rubocop-rspec', '~> 2.18.1' +end diff --git a/lib/gitlab/utils.rb b/gems/gitlab-utils/lib/gitlab/utils.rb index dc0112c14d6..4e08ee8fcaf 100644 --- a/lib/gitlab/utils.rb +++ b/gems/gitlab-utils/lib/gitlab/utils.rb @@ -1,9 +1,13 @@ # frozen_string_literal: true +require "addressable/uri" +require "active_support/all" +require "action_view" + module Gitlab module Utils extend self - DoubleEncodingError ||= Class.new(StandardError) + DoubleEncodingError = Class.new(StandardError) def allowlisted?(absolute_path, allowlist) path = absolute_path.downcase @@ -15,7 +19,7 @@ module Gitlab def decode_path(encoded_path) decoded = CGI.unescape(encoded_path) - if decoded != CGI.unescape(decoded) + if decoded != CGI.unescape(decoded) # rubocop:disable Style/IfUnlessModifier raise DoubleEncodingError, "path #{encoded_path} is not allowed" end @@ -31,7 +35,7 @@ module Gitlab raise ArgumentError, 'Negative string size provided!' if bytes < 0 truncated = str.each_char.each_with_object(+'') do |char, object| - if object.bytesize + char.bytesize > bytes + if object.bytesize + char.bytesize > bytes # rubocop:disable Style/GuardClause break object else object.concat(char) @@ -43,7 +47,7 @@ module Gitlab # Append path to host, making sure there's one single / in between def append_path(host, path) - "#{host.to_s.sub(%r{\/+$}, '')}/#{remove_leading_slashes(path)}" + "#{host.to_s.sub(%r{\/+$}, '')}/#{remove_leading_slashes(path)}" # rubocop:disable Style/RedundantRegexpEscape end def remove_leading_slashes(str) @@ -128,7 +132,7 @@ module Gitlab def deep_indifferent_access(data) case data when Array - data.map(&method(:deep_indifferent_access)) + data.map { |item| deep_indifferent_access(item) } when Hash data.with_indifferent_access else @@ -139,7 +143,7 @@ module Gitlab def deep_symbolized_access(data) case data when Array - data.map(&method(:deep_symbolized_access)) + data.map { |item| deep_symbolized_access(item) } when Hash data.deep_symbolize_keys else @@ -242,7 +246,7 @@ module Gitlab unless allow_nested # nested brackets check - return false if brackets.include?('[[') || brackets.include?(']]') + return false if brackets.include?('[[') || brackets.include?(']]') # rubocop:disable Style/SoleNestedConditional end # open / close brackets coherence check diff --git a/gems/gitlab-utils/lib/gitlab/utils/all.rb b/gems/gitlab-utils/lib/gitlab/utils/all.rb new file mode 100644 index 00000000000..200a21aad88 --- /dev/null +++ b/gems/gitlab-utils/lib/gitlab/utils/all.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +require_relative "../utils" +require_relative "../version_info" +require_relative "version" +require_relative "strong_memoize" diff --git a/lib/gitlab/utils/strong_memoize.rb b/gems/gitlab-utils/lib/gitlab/utils/strong_memoize.rb index 2b3841b8f09..2b3841b8f09 100644 --- a/lib/gitlab/utils/strong_memoize.rb +++ b/gems/gitlab-utils/lib/gitlab/utils/strong_memoize.rb diff --git a/gems/gitlab-utils/lib/gitlab/utils/version.rb b/gems/gitlab-utils/lib/gitlab/utils/version.rb new file mode 100644 index 00000000000..a9afe5bf845 --- /dev/null +++ b/gems/gitlab-utils/lib/gitlab/utils/version.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Gitlab + module Utils + module Version + VERSION = "0.1.0" + end + end +end diff --git a/lib/gitlab/version_info.rb b/gems/gitlab-utils/lib/gitlab/version_info.rb index 0351c9b30b3..0f94aea04ad 100644 --- a/lib/gitlab/version_info.rb +++ b/gems/gitlab-utils/lib/gitlab/version_info.rb @@ -6,7 +6,7 @@ module Gitlab attr_reader :major, :minor, :patch - VERSION_REGEX = /(\d+)\.(\d+)\.(\d+)/.freeze + VERSION_REGEX = /(\d+)\.(\d+)\.(\d+)/ # To mitigate ReDoS, limit the length of the version string we're # willing to check MAX_VERSION_LENGTH = 128 @@ -21,7 +21,7 @@ module Gitlab end end - def initialize(major = 0, minor = 0, patch = 0, suffix = nil) + def initialize(major = 0, minor = 0, patch = 0, suffix = nil) # rubocop:disable Metrics/ParameterLists @major = major @minor = minor @patch = patch @@ -59,7 +59,7 @@ module Gitlab def to_s if valid? - "%d.%d.%d%s" % [@major, @minor, @patch, @suffix_s] + "%d.%d.%d%s" % [@major, @minor, @patch, @suffix_s] # rubocop:disable Style/FormatString else 'Unknown' end diff --git a/spec/lib/gitlab/utils/strong_memoize_spec.rb b/gems/gitlab-utils/spec/gitlab/utils/strong_memoize_spec.rb index ea8083e7d7f..05b25681043 100644 --- a/spec/lib/gitlab/utils/strong_memoize_spec.rb +++ b/gems/gitlab-utils/spec/gitlab/utils/strong_memoize_spec.rb @@ -1,13 +1,9 @@ # frozen_string_literal: true -require 'fast_spec_helper' -require 'rspec-benchmark' -require 'rspec-parameterized' -require 'active_support/testing/time_helpers' +# rubocop:disable GitlabSecurity/PublicSend -RSpec.configure do |config| - config.include RSpec::Benchmark::Matchers -end +require 'spec_helper' +require 'active_support/testing/time_helpers' RSpec.describe Gitlab::Utils::StrongMemoize, feature_category: :shared do include ActiveSupport::Testing::TimeHelpers @@ -89,8 +85,8 @@ RSpec.describe Gitlab::Utils::StrongMemoize, feature_category: :shared do let(:member_name) { described_class.normalize_key(method_name) } it 'only calls the block once' do - value0 = object.send(method_name) - value1 = object.send(method_name) + value0 = object.public_send(method_name) + value1 = object.public_send(method_name) expect(value0).to eq(value) expect(value1).to eq(value) @@ -98,7 +94,7 @@ RSpec.describe Gitlab::Utils::StrongMemoize, feature_category: :shared do end it 'returns and defines the instance variable for the exact value' do - returned_value = object.send(method_name) + returned_value = object.public_send(method_name) memoized_value = object.instance_variable_get(:"@#{member_name}") expect(returned_value).to eql(value) @@ -125,7 +121,7 @@ RSpec.describe Gitlab::Utils::StrongMemoize, feature_category: :shared do end end - context "memory allocation", type: :benchmark do + context "with memory allocation", type: :benchmark do let(:value) { 'aaa' } before do @@ -171,7 +167,7 @@ RSpec.describe Gitlab::Utils::StrongMemoize, feature_category: :shared do end end - context 'value memoization test' do + context 'with value memoization test' do let(:value) { 'value' } it 'caches the value for specified number of seconds' do @@ -265,7 +261,7 @@ RSpec.describe Gitlab::Utils::StrongMemoize, feature_category: :shared do context "with value '#{value}'" do let(:value) { value } - context 'memoized after method definition' do + context 'with memoized after method definition' do let(:method_name) { :method_name_attr } it_behaves_like 'caching the value' @@ -372,3 +368,5 @@ RSpec.describe Gitlab::Utils::StrongMemoize, feature_category: :shared do end end end + +# rubocop:enable GitlabSecurity/PublicSend diff --git a/spec/lib/gitlab/utils_spec.rb b/gems/gitlab-utils/spec/gitlab/utils_spec.rb index 7b9504366ec..53593190eea 100644 --- a/spec/lib/gitlab/utils_spec.rb +++ b/gems/gitlab-utils/spec/gitlab/utils_spec.rb @@ -2,13 +2,14 @@ require 'spec_helper' -RSpec.describe Gitlab::Utils do +RSpec.describe Gitlab::Utils, feature_category: :shared do using RSpec::Parameterized::TableSyntax + include StubENV delegate :to_boolean, :boolean_to_yes_no, :slugify, :which, - :ensure_array_from_string, :bytes_to_megabytes, - :append_path, :remove_leading_slashes, :allowlisted?, - :decode_path, :ms_to_round_sec, to: :described_class + :ensure_array_from_string, :bytes_to_megabytes, + :append_path, :remove_leading_slashes, :allowlisted?, + :decode_path, :ms_to_round_sec, to: :described_class describe '.allowlisted?' do let(:allowed_paths) { ['/home/foo', '/foo/bar', '/etc/passwd'] } @@ -225,7 +226,7 @@ RSpec.describe Gitlab::Utils do end describe '.ensure_utf8_size' do - context 'string is has less bytes than expected' do + context 'with string is has less bytes than expected' do it 'backfills string with null characters' do transformed = described_class.ensure_utf8_size('a' * 10, bytes: 32) @@ -234,7 +235,7 @@ RSpec.describe Gitlab::Utils do end end - context 'string size is exactly the one that is expected' do + context 'with string size is exactly the one that is expected' do it 'returns original value' do transformed = described_class.ensure_utf8_size('a' * 32, bytes: 32) @@ -247,7 +248,7 @@ RSpec.describe Gitlab::Utils do it 'backfills string with null characters' do transformed = described_class.ensure_utf8_size('❤' * 6, bytes: 32) - expect(transformed).to eq '❤❤❤❤❤❤' + ('0' * 14) + expect(transformed).to eq '❤❤❤❤❤❤' + ('0' * 14) # rubocop:disable Style/StringConcatenation expect(transformed.bytesize).to eq 32 end end @@ -368,7 +369,7 @@ RSpec.describe Gitlab::Utils do nil | { b: 3, a: 2 } | '?a=2&b=3' 'https://gitlab.com' | nil | 'https://gitlab.com' 'https://gitlab.com' | { b: 3, a: 2 } | 'https://gitlab.com?a=2&b=3' - 'https://gitlab.com?a=1#foo' | { b: 3, 'a': 2 } | 'https://gitlab.com?a=2&b=3#foo' + 'https://gitlab.com?a=1#foo' | { b: 3, 'a' => 2 } | 'https://gitlab.com?a=2&b=3#foo' 'https://gitlab.com?a=1#foo' | [[:b, 3], [:a, 2]] | 'https://gitlab.com?a=2&b=3#foo' end @@ -391,7 +392,8 @@ RSpec.describe Gitlab::Utils do end it 'returns string with filtered access_token param' do - expect(described_class.removes_sensitive_data_from_url('http://gitlab.com/auth.html#access_token=secret_token')).to eq('http://gitlab.com/auth.html#access_token=filtered') + expect(described_class.removes_sensitive_data_from_url('http://gitlab.com/auth.html#access_token=secret_token')) + .to eq('http://gitlab.com/auth.html#access_token=filtered') end it 'returns string with filtered access_token param but other params preserved' do diff --git a/spec/lib/gitlab/version_info_spec.rb b/gems/gitlab-utils/spec/gitlab/version_info_spec.rb index 99c7a762392..2b5f6bcb4c1 100644 --- a/spec/lib/gitlab/version_info_spec.rb +++ b/gems/gitlab-utils/spec/gitlab/version_info_spec.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'fast_spec_helper' +require 'spec_helper' -RSpec.describe Gitlab::VersionInfo do +RSpec.describe Gitlab::VersionInfo, feature_category: :shared do before do @unknown = described_class.new @v0_0_1 = described_class.new(0, 0, 1) diff --git a/gems/gitlab-utils/spec/spec_helper.rb b/gems/gitlab-utils/spec/spec_helper.rb new file mode 100644 index 00000000000..5dc3859f77d --- /dev/null +++ b/gems/gitlab-utils/spec/spec_helper.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'rails' +require 'rspec/mocks' +require 'rspec-benchmark' +require 'rspec-parameterized' + +require 'gitlab/rspec/all' +require 'gitlab/utils/all' + +RSpec.configure do |config| + config.include RSpec::Benchmark::Matchers + + # Enable flags like --only-failures and --next-failure + config.example_status_persistence_file_path = ".rspec_status" + + # Disable RSpec exposing methods globally on `Module` and `main` + config.disable_monkey_patching! + + config.expect_with :rspec do |c| + c.syntax = :expect + end +end diff --git a/lib/gitlab/cluster/lifecycle_events.rb b/lib/gitlab/cluster/lifecycle_events.rb index b39d2a02f02..c6ce0aa6160 100644 --- a/lib/gitlab/cluster/lifecycle_events.rb +++ b/lib/gitlab/cluster/lifecycle_events.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative '../utils' # Gitlab::Utils +require 'gitlab/utils/all' # Gitlab::Utils module Gitlab module Cluster diff --git a/lib/gitlab/sidekiq_logging/structured_logger.rb b/lib/gitlab/sidekiq_logging/structured_logger.rb index c4566a6dc2a..ca52d588113 100644 --- a/lib/gitlab/sidekiq_logging/structured_logger.rb +++ b/lib/gitlab/sidekiq_logging/structured_logger.rb @@ -87,6 +87,7 @@ module Gitlab payload['message'] = "#{message}: #{job_status}: #{payload['duration_s']} sec" payload['job_status'] = job_status payload['job_deferred_by'] = job['deferred_by'] if job['deferred'] + payload['deferred_count'] = job['deferred_count'] if job['deferred'] Gitlab::ExceptionLogFormatter.format!(job_exception, payload) if job_exception diff --git a/lib/gitlab/sidekiq_middleware/defer_jobs.rb b/lib/gitlab/sidekiq_middleware/defer_jobs.rb index 0a12667865c..6a652f39349 100644 --- a/lib/gitlab/sidekiq_middleware/defer_jobs.rb +++ b/lib/gitlab/sidekiq_middleware/defer_jobs.rb @@ -22,6 +22,8 @@ module Gitlab # Referred in job_logger's 'log_job_done' method to compute proper 'job_status' job['deferred'] = true job['deferred_by'] = deferred_by + job['deferred_count'] ||= 0 + job['deferred_count'] += 1 worker.class.perform_in(delay, *job['args']) counter.increment({ worker: worker.class.name }) diff --git a/lib/gitlab/task_helpers.rb b/lib/gitlab/task_helpers.rb index b9800a4db73..f756d229ba1 100644 --- a/lib/gitlab/task_helpers.rb +++ b/lib/gitlab/task_helpers.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require 'rainbow/ext/string' -require_relative 'utils/strong_memoize' +require 'gitlab/utils/all' # rubocop:disable Rails/Output module Gitlab diff --git a/lib/gitlab/utils/override.rb b/lib/gitlab/utils/override.rb index 1d02bcbb2d2..10370811bb5 100644 --- a/lib/gitlab/utils/override.rb +++ b/lib/gitlab/utils/override.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative '../utils' +require 'gitlab/utils/all' require_relative '../environment' module Gitlab diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake index 825388461bc..1a659a930ab 100644 --- a/lib/tasks/gettext.rake +++ b/lib/tasks/gettext.rake @@ -42,7 +42,7 @@ namespace :gettext do desc 'Lint all po files in `locale/' task lint: :environment do require 'simple_po_parser' - require 'gitlab/utils' + require 'gitlab/utils/all' require 'parallel' FastGettext.silence_errors diff --git a/locale/gitlab.pot b/locale/gitlab.pot index a09096b6b92..e2b72fb0123 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1120,6 +1120,12 @@ msgstr "" msgid "%{spanStart}in%{spanEnd} %{errorFn}" msgstr "" +msgid "%{startDate} – %{dueDate}" +msgstr "" + +msgid "%{startDate} – No due date" +msgstr "" + msgid "%{start} to %{end}" msgstr "" @@ -17714,12 +17720,6 @@ msgstr "" msgid "Epics, issues, and merge requests" msgstr "" -msgid "Epics|%{startDate} – %{dueDate}" -msgstr "" - -msgid "Epics|%{startDate} – No due date" -msgstr "" - msgid "Epics|Add a new epic" msgstr "" @@ -17735,9 +17735,6 @@ msgstr "" msgid "Epics|Leave empty to inherit from milestone dates" msgstr "" -msgid "Epics|No start date – %{dueDate}" -msgstr "" - msgid "Epics|Remove epic" msgstr "" @@ -30792,6 +30789,9 @@ msgstr "" msgid "No starrers matched your search" msgstr "" +msgid "No start date – %{dueDate}" +msgstr "" + msgid "No suggestions found" msgstr "" diff --git a/metrics_server/dependencies.rb b/metrics_server/dependencies.rb index 233511eb505..c96fecd7cb7 100644 --- a/metrics_server/dependencies.rb +++ b/metrics_server/dependencies.rb @@ -11,11 +11,11 @@ require 'active_support/core_ext/numeric/bytes' require 'prometheus/client' require 'rack' +require 'gitlab/utils/all' + require_relative 'settings_overrides' require_relative '../lib/gitlab/daemon' -require_relative '../lib/gitlab/utils' -require_relative '../lib/gitlab/utils/strong_memoize' require_relative '../lib/prometheus/cleanup_multiproc_dir_service' require_relative '../lib/gitlab/metrics/prometheus' require_relative '../lib/gitlab/metrics' diff --git a/qa/Dockerfile b/qa/Dockerfile index e5308d78f83..213ec3450cb 100644 --- a/qa/Dockerfile +++ b/qa/Dockerfile @@ -40,6 +40,8 @@ WORKDIR /home/gitlab/qa # Install qa dependencies or fetch from cache if unchanged # COPY ./qa/Gemfile* /home/gitlab/qa/ +COPY ./vendor/gems/ /home/gitlab/vendor/gems/ +COPY ./gems/ /home/gitlab/gems/ RUN bundle config set --local without development \ && bundle install --retry=3 @@ -47,9 +49,7 @@ COPY ./config/initializers/0_inject_enterprise_edition_module.rb /home/gitlab/co COPY ./config/feature_flags /home/gitlab/config/feature_flags COPY ./config/bundler_setup.rb /home/gitlab/config/ COPY ./lib/gitlab_edition.rb /home/gitlab/lib/ -COPY ./lib/gitlab/utils.rb /home/gitlab/lib/gitlab/ COPY ./INSTALLATION_TYPE ./VERSION /home/gitlab/ -COPY ./gems /home/gitlab/ COPY ./qa /home/gitlab/qa diff --git a/qa/Gemfile b/qa/Gemfile index c907240333f..2a7f221f91f 100644 --- a/qa/Gemfile +++ b/qa/Gemfile @@ -4,6 +4,7 @@ source 'https://rubygems.org' gem 'gitlab-qa', '~> 11', '>= 11.2.0', require: 'gitlab/qa' gem 'gitlab_quality-test_tooling', '~> 0.8.2', require: false +gem 'gitlab-utils', path: '../gems/gitlab-utils' gem 'activesupport', '~> 6.1.7.2' # This should stay in sync with the root's Gemfile gem 'allure-rspec', '~> 2.20.0' gem 'capybara', '~> 3.39.2' diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index 94eae5f80bb..861bb1e0def 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -1,6 +1,22 @@ +PATH + remote: ../gems/gitlab-utils + specs: + gitlab-utils (0.1.0) + actionview (>= 6.1.7.2) + activesupport (>= 6.1.7.2) + addressable (~> 2.8) + nokogiri (~> 1.15.2) + rake (~> 13.0) + GEM remote: https://rubygems.org/ specs: + actionview (6.1.7.2) + activesupport (= 6.1.7.2) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) activesupport (6.1.7.2) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) @@ -55,6 +71,7 @@ GEM confiner (0.4.0) gitlab (>= 4.17) zeitwerk (>= 2.5, < 3) + crass (1.0.6) debug_inspector (1.1.0) declarative (0.0.20) deprecation_toolkit (2.0.3) @@ -62,6 +79,7 @@ GEM diff-lcs (1.3) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) + erubi (1.12.0) excon (0.92.4) faker (3.2.0) i18n (>= 1.8.11, < 2) @@ -176,6 +194,9 @@ GEM llhttp-ffi (0.4.0) ffi-compiler (~> 1.0) rake (~> 13.0) + loofah (2.21.3) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) macaddr (1.7.2) systemu (~> 2.6.5) matrix (0.4.2) @@ -214,10 +235,15 @@ GEM byebug (~> 11.0) pry (>= 0.13, < 0.15) public_suffix (5.0.1) - racc (1.6.2) + racc (1.7.1) rack (2.2.3.1) rack-test (1.1.0) rack (>= 1.0, < 3) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.5.0) + loofah (~> 2.19, >= 2.19.1) rainbow (3.1.1) rake (13.0.6) regexp_parser (2.1.1) @@ -324,6 +350,7 @@ DEPENDENCIES fog-core (= 2.1.0) fog-google (~> 1.19) gitlab-qa (~> 11, >= 11.2.0) + gitlab-utils! gitlab_quality-test_tooling (~> 0.8.2) influxdb-client (~> 2.9) knapsack (~> 4.0) diff --git a/qa/gdk/Dockerfile.gdk b/qa/gdk/Dockerfile.gdk index cdb693841cb..2b296535622 100644 --- a/qa/gdk/Dockerfile.gdk +++ b/qa/gdk/Dockerfile.gdk @@ -98,8 +98,8 @@ RUN set -eux; \ # Install gitlab gem dependencies # COPY --chown=gdk:gdk Gemfile Gemfile.lock ./gitlab/ -COPY --chown=gdk:gdk vendor/gems ./gitlab/vendor/gems -COPY --chown=gdk:gdk gems ./gitlab/gems +COPY --chown=gdk:gdk vendor/gems/ ./gitlab/vendor/gems/ +COPY --chown=gdk:gdk gems/ ./gitlab/gems/ RUN make .gitlab-bundle && rm -rf ${GEM_HOME}/cache # Install gitlab npm dependencies @@ -2,8 +2,9 @@ Encoding.default_external = 'UTF-8' +require 'gitlab/utils/all' + require_relative '../lib/gitlab_edition' -require_relative '../lib/gitlab/utils' require_relative '../config/initializers/0_inject_enterprise_edition_module' require_relative 'lib/gitlab' diff --git a/qa/qa/scenario/test/integration/oauth.rb b/qa/qa/scenario/test/integration/oauth.rb new file mode 100644 index 00000000000..912156fbc29 --- /dev/null +++ b/qa/qa/scenario/test/integration/oauth.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module QA + module Scenario + module Test + module Integration + class OAuth < Test::Instance::All + tags :oauth + end + end + end + end +end diff --git a/scripts/gitaly-test-build b/scripts/gitaly-test-build index 6901593009a..cfa089b327e 100755 --- a/scripts/gitaly-test-build +++ b/scripts/gitaly-test-build @@ -1,6 +1,7 @@ #!/usr/bin/env ruby # frozen_string_literal: true +require_relative '../config/bundler_setup' require 'fileutils' require_relative '../spec/support/helpers/gitaly_setup' diff --git a/scripts/gitaly-test-spawn b/scripts/gitaly-test-spawn index 475c7715bdd..9285b561ae0 100755 --- a/scripts/gitaly-test-spawn +++ b/scripts/gitaly-test-spawn @@ -3,6 +3,7 @@ # This script is used both in CI and in local development 'rspec' runs. +require_relative '../config/bundler_setup' require_relative '../spec/support/helpers/gitaly_setup' class GitalyTestSpawn diff --git a/scripts/merge-simplecov b/scripts/merge-simplecov index 24be731549b..7db12839382 100755 --- a/scripts/merge-simplecov +++ b/scripts/merge-simplecov @@ -1,6 +1,7 @@ #!/usr/bin/env ruby # frozen_string_literal: true +require_relative '../config/bundler_setup' require_relative '../spec/simplecov_env' SimpleCovEnv.configure_profile SimpleCovEnv.configure_formatter diff --git a/scripts/setup-test-env b/scripts/setup-test-env index ae00b569ce3..1c39483bb7a 100755 --- a/scripts/setup-test-env +++ b/scripts/setup-test-env @@ -25,8 +25,8 @@ require_relative '../lib/system_check/helpers' require 'omniauth' require 'omniauth-github' require 'etc' +require 'gitlab/utils/all' require_relative '../lib/gitlab/access' -require_relative '../lib/gitlab/utils' unless defined?(License) # This is needed to allow use of `Gitlab::ImportSources.values` in `1_settings.rb`. diff --git a/sidekiq_cluster/cli.rb b/sidekiq_cluster/cli.rb index 0d24f70c37d..fc065d799d4 100644 --- a/sidekiq_cluster/cli.rb +++ b/sidekiq_cluster/cli.rb @@ -5,11 +5,11 @@ require_relative '../config/bundler_setup' require 'optparse' require 'logger' require 'time' +require 'gitlab/utils/all' # In environments where code is preloaded and cached such as `spring`, # we may run into "already initialized" warnings, hence the check. require_relative '../lib/gitlab' -require_relative '../lib/gitlab/utils' require_relative '../lib/gitlab/sidekiq_config/cli_methods' require_relative '../lib/gitlab/sidekiq_config/worker_matcher' require_relative '../lib/gitlab/sidekiq_logging/json_formatter' diff --git a/spec/controllers/groups/uploads_controller_spec.rb b/spec/controllers/groups/uploads_controller_spec.rb index 6649e8f057c..7795fff5541 100644 --- a/spec/controllers/groups/uploads_controller_spec.rb +++ b/spec/controllers/groups/uploads_controller_spec.rb @@ -76,31 +76,17 @@ RSpec.describe Groups::UploadsController do context 'when uploader class does not match the upload' do let(:uploader_class) { FileUploader } - it 'responds with status 200 but logs a deprecation message' do - expect(Gitlab::AppJsonLogger).to receive(:info).with( - message: 'Deprecated usage of build_uploader_from_params', - uploader_class: uploader_class.name, - path: filename, - exists: true - ) - + it 'responds with status 404' do show_upload - expect(response).to have_gitlab_http_status(:ok) + expect(response).to have_gitlab_http_status(:not_found) end end context 'when filename does not match' do let(:invalid_filename) { 'invalid_filename.jpg' } - it 'responds with status 404 and logs a deprecation message' do - expect(Gitlab::AppJsonLogger).to receive(:info).with( - message: 'Deprecated usage of build_uploader_from_params', - uploader_class: uploader_class.name, - path: invalid_filename, - exists: false - ) - + it 'responds with status 404' do get :show, params: params.merge(secret: secret, filename: invalid_filename) expect(response).to have_gitlab_http_status(:not_found) diff --git a/spec/deprecation_warnings.rb b/spec/deprecation_warnings.rb index 45fed5fecca..abdd13ee8e7 100644 --- a/spec/deprecation_warnings.rb +++ b/spec/deprecation_warnings.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative '../lib/gitlab/utils' +require 'gitlab/utils/all' return if Gitlab::Utils.to_boolean(ENV['SILENCE_DEPRECATIONS'], default: false) # Enable deprecation warnings by default and make them more visible diff --git a/spec/fast_spec_helper.rb b/spec/fast_spec_helper.rb index 03c8919912c..47a90efab1e 100644 --- a/spec/fast_spec_helper.rb +++ b/spec/fast_spec_helper.rb @@ -18,13 +18,12 @@ RSpec.configure(&:disable_monkey_patching!) require 'active_support/all' require 'pry' +require 'gitlab/utils/all' require_relative 'rails_autoload' require_relative '../config/settings' require_relative 'support/rspec' require_relative '../lib/gitlab' -require_relative '../lib/gitlab/utils' -require_relative '../lib/gitlab/utils/strong_memoize' require_relative 'simplecov_env' SimpleCovEnv.start! diff --git a/spec/features/markdown/sandboxed_mermaid_spec.rb b/spec/features/markdown/sandboxed_mermaid_spec.rb index f8a535191da..87696eb82e5 100644 --- a/spec/features/markdown/sandboxed_mermaid_spec.rb +++ b/spec/features/markdown/sandboxed_mermaid_spec.rb @@ -16,8 +16,9 @@ RSpec.describe 'Sandboxed Mermaid rendering', :js, feature_category: :team_plann MERMAID end - let_it_be(:expected) do - %(<iframe src="/-/sandbox/mermaid" sandbox="allow-scripts allow-popups" frameborder="0" scrolling="no") + let(:expected) do + src = "http://#{Capybara.current_session.server.host}:#{Capybara.current_session.server.port}/-/sandbox/mermaid" + %(<iframe src="#{src}" sandbox="allow-scripts allow-popups" frameborder="0" scrolling="no") end context 'in an issue' do diff --git a/spec/frontend/behaviors/markdown/render_sandboxed_mermaid_spec.js b/spec/frontend/behaviors/markdown/render_sandboxed_mermaid_spec.js index de0e5063e49..88312a780d1 100644 --- a/spec/frontend/behaviors/markdown/render_sandboxed_mermaid_spec.js +++ b/spec/frontend/behaviors/markdown/render_sandboxed_mermaid_spec.js @@ -9,7 +9,7 @@ import renderMermaid, { describe('Mermaid diagrams renderer', () => { // Finders - const findMermaidIframes = () => document.querySelectorAll('iframe[src="/-/sandbox/mermaid"]'); + const findMermaidIframes = () => document.querySelectorAll('iframe[src*="/-/sandbox/mermaid"]'); const findDangerousMermaidAlert = () => createWrapper(document.querySelector('[data-testid="alert-warning"]')); diff --git a/spec/frontend/issuable/components/status_box_spec.js b/spec/frontend/issuable/components/status_box_spec.js index d26f287d90c..0d47595c9e6 100644 --- a/spec/frontend/issuable/components/status_box_spec.js +++ b/spec/frontend/issuable/components/status_box_spec.js @@ -18,6 +18,8 @@ describe('Merge request status box component', () => { ${'merge_request'} | ${'Merged'} | ${'merged'} | ${'issuable-status-badge-merged'} | ${'info'} | ${'merge'} ${'issue'} | ${'Open'} | ${'opened'} | ${'issuable-status-badge-open'} | ${'success'} | ${'issues'} ${'issue'} | ${'Closed'} | ${'closed'} | ${'issuable-status-badge-closed'} | ${'info'} | ${'issue-closed'} + ${'epic'} | ${'Open'} | ${'opened'} | ${'issuable-status-badge-open'} | ${'success'} | ${'epic'} + ${'epic'} | ${'Closed'} | ${'closed'} | ${'issuable-status-badge-closed'} | ${'info'} | ${'epic-closed'} `( 'with issuableType set to "$issuableType" and state set to "$initialState"', ({ issuableType, badgeText, initialState, badgeClass, badgeVariant, badgeIcon }) => { diff --git a/spec/frontend/issuable/popover/components/issue_popover_spec.js b/spec/frontend/issuable/popover/components/issue_popover_spec.js index a7605016039..0596433ce9a 100644 --- a/spec/frontend/issuable/popover/components/issue_popover_spec.js +++ b/spec/frontend/issuable/popover/components/issue_popover_spec.js @@ -26,7 +26,7 @@ describe('Issue Popover', () => { apolloProvider: createMockApollo([[issueQuery, queryResponse]]), propsData: { target: document.createElement('a'), - projectPath: 'foo/bar', + namespacePath: 'foo/bar', iid: '1', cachedTitle: 'Cached title', }, diff --git a/spec/frontend/issuable/popover/components/mr_popover_spec.js b/spec/frontend/issuable/popover/components/mr_popover_spec.js index 5b29ecfc0ba..4ed783da853 100644 --- a/spec/frontend/issuable/popover/components/mr_popover_spec.js +++ b/spec/frontend/issuable/popover/components/mr_popover_spec.js @@ -64,7 +64,7 @@ describe('MR Popover', () => { apolloProvider: createMockApollo([[mergeRequestQuery, queryResponse]]), propsData: { target: document.createElement('a'), - projectPath: 'foo/bar', + namespacePath: 'foo/bar', iid: '1', cachedTitle: 'Cached Title', }, diff --git a/spec/frontend/issuable/popover/index_spec.js b/spec/frontend/issuable/popover/index_spec.js index b1aa7f0f0b0..bf9dce4867f 100644 --- a/spec/frontend/issuable/popover/index_spec.js +++ b/spec/frontend/issuable/popover/index_spec.js @@ -1,6 +1,6 @@ import { setHTMLFixture } from 'helpers/fixtures'; import * as createDefaultClient from '~/lib/graphql'; -import initIssuablePopovers from '~/issuable/popover/index'; +import initIssuablePopovers, * as popover from '~/issuable/popover/index'; createDefaultClient.default = jest.fn(); @@ -9,6 +9,7 @@ describe('initIssuablePopovers', () => { let mr2; let mr3; let issue1; + let workItem1; beforeEach(() => { setHTMLFixture(` @@ -24,30 +25,69 @@ describe('initIssuablePopovers', () => { <div id="four" class="gfm-issue" title="title" data-iid="1" data-project-path="group/project" data-reference-type="issue"> MR3 </div> + <div id="five" class="gfm-work_item" title="title" data-iid="1" data-project-path="group/project" data-reference-type="work_item"> + MR3 + </div> `); mr1 = document.querySelector('#one'); mr2 = document.querySelector('#two'); mr3 = document.querySelector('#three'); issue1 = document.querySelector('#four'); - - mr1.addEventListener = jest.fn(); - mr2.addEventListener = jest.fn(); - mr3.addEventListener = jest.fn(); - issue1.addEventListener = jest.fn(); + workItem1 = document.querySelector('#five'); }); - it('does not add the same event listener twice', () => { - initIssuablePopovers([mr1, mr1, mr2, issue1]); + describe('init function', () => { + beforeEach(() => { + mr1.addEventListener = jest.fn(); + mr2.addEventListener = jest.fn(); + mr3.addEventListener = jest.fn(); + issue1.addEventListener = jest.fn(); + workItem1.addEventListener = jest.fn(); + }); + + it('does not add the same event listener twice', () => { + initIssuablePopovers([mr1, mr1, mr2, issue1, workItem1]); + + expect(mr1.addEventListener).toHaveBeenCalledTimes(1); + expect(mr2.addEventListener).toHaveBeenCalledTimes(1); + expect(issue1.addEventListener).toHaveBeenCalledTimes(1); + expect(workItem1.addEventListener).toHaveBeenCalledTimes(1); + }); - expect(mr1.addEventListener).toHaveBeenCalledTimes(1); - expect(mr2.addEventListener).toHaveBeenCalledTimes(1); - expect(issue1.addEventListener).toHaveBeenCalledTimes(1); + it('does not add listener if it does not have the necessary data attributes', () => { + initIssuablePopovers([mr1, mr2, mr3]); + + expect(mr3.addEventListener).not.toHaveBeenCalled(); + }); }); - it('does not add listener if it does not have the necessary data attributes', () => { - initIssuablePopovers([mr1, mr2, mr3]); + describe('mount function', () => { + const expectedMountObject = { + apolloProvider: expect.anything(), + iid: '1', + namespacePath: 'group/project', + title: 'title', + }; + + beforeEach(() => { + jest.spyOn(popover, 'handleIssuablePopoverMount').mockImplementation(jest.fn()); + }); + + it('calls popover mount function with components for Issue, MR, and Work Item', () => { + initIssuablePopovers([mr1, issue1, workItem1], popover.handleIssuablePopoverMount); + + [mr1, issue1, workItem1].forEach(async (el) => { + await el.dispatchEvent(new Event('mouseenter', { target: el })); - expect(mr3.addEventListener).not.toHaveBeenCalled(); + expect(popover.handleIssuablePopoverMount).toHaveBeenCalledWith( + expect.objectContaining({ + ...expectedMountObject, + referenceType: el.dataset.referenceType, + target: el, + }), + ); + }); + }); }); }); diff --git a/spec/frontend/lib/utils/datetime/date_format_utility_spec.js b/spec/frontend/lib/utils/datetime/date_format_utility_spec.js index e7a6367eeac..65018fe1625 100644 --- a/spec/frontend/lib/utils/datetime/date_format_utility_spec.js +++ b/spec/frontend/lib/utils/datetime/date_format_utility_spec.js @@ -152,3 +152,18 @@ describe('formatUtcOffset', () => { expect(utils.formatUtcOffset(offset)).toEqual(expected); }); }); + +describe('humanTimeframe', () => { + it.each` + startDate | dueDate | returnValue + ${'2021-1-1'} | ${'2021-2-28'} | ${'Jan 1 – Feb 28, 2021'} + ${'2021-1-1'} | ${'2022-2-28'} | ${'Jan 1, 2021 – Feb 28, 2022'} + ${'2021-1-1'} | ${null} | ${'Jan 1, 2021 – No due date'} + ${null} | ${'2021-2-28'} | ${'No start date – Feb 28, 2021'} + `( + 'returns string "$returnValue" when startDate is $startDate and dueDate is $dueDate', + ({ startDate, dueDate, returnValue }) => { + expect(utils.humanTimeframe(startDate, dueDate)).toBe(returnValue); + }, + ); +}); diff --git a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb index 1c23a619b38..5f2994165f2 100644 --- a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb +++ b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb @@ -436,6 +436,7 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do call_subject(job, 'test_queue') do job['deferred'] = true job['deferred_by'] = :feature_flag + job['deferred_count'] = 1 end end end diff --git a/spec/lib/gitlab/sidekiq_middleware/defer_jobs_spec.rb b/spec/lib/gitlab/sidekiq_middleware/defer_jobs_spec.rb index 195a79c22ec..88ba228b66b 100644 --- a/spec/lib/gitlab/sidekiq_middleware/defer_jobs_spec.rb +++ b/spec/lib/gitlab/sidekiq_middleware/defer_jobs_spec.rb @@ -43,6 +43,13 @@ RSpec.describe Gitlab::SidekiqMiddleware::DeferJobs, feature_category: :scalabil expect(TestDeferredWorker).to receive(:perform_in).with(described_class::DELAY, *job['args']) expect { |b| subject.call(TestDeferredWorker.new, job, queue, &b) }.not_to yield_control end + + it 'increments the defer_count' do + (1..5).each do |count| + subject.call(TestDeferredWorker.new, job, queue) + expect(job).to include('deferred_count' => count) + end + end end context 'for other workers' do @@ -51,7 +58,7 @@ RSpec.describe Gitlab::SidekiqMiddleware::DeferJobs, feature_category: :scalabil end end - it 'increments the counter' do + it 'increments the metric counter' do subject.call(TestDeferredWorker.new, job, queue) counter = ::Gitlab::Metrics.registry.get(:sidekiq_jobs_deferred_total) diff --git a/spec/simplecov_env.rb b/spec/simplecov_env.rb index bea312369f7..af722f45ae5 100644 --- a/spec/simplecov_env.rb +++ b/spec/simplecov_env.rb @@ -3,7 +3,7 @@ require 'simplecov' require 'simplecov-cobertura' require 'simplecov-lcov' -require_relative '../lib/gitlab/utils' +require 'gitlab/utils/all' module SimpleCovEnv extend self diff --git a/spec/support/ability_check.rb b/spec/support/ability_check.rb index 213944506bb..5b56b9925f6 100644 --- a/spec/support/ability_check.rb +++ b/spec/support/ability_check.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'gitlab/utils/strong_memoize' +require 'gitlab/utils/all' module Support module AbilityCheck diff --git a/spec/support/formatters/json_formatter.rb b/spec/support/formatters/json_formatter.rb index e9d65af710a..f477d5e9e6a 100644 --- a/spec/support/formatters/json_formatter.rb +++ b/spec/support/formatters/json_formatter.rb @@ -26,11 +26,15 @@ module Support hash[:exceptions] = exceptions.map do |exception| hash = { class: exception.class.name, - message: exception.message, - message_lines: strip_ansi_codes(notification.message_lines), - backtrace: notification.formatted_backtrace + message: exception.message } + hash[:backtrace] = notification.formatted_backtrace if notification.respond_to?(:backtrace) + + if notification.respond_to?(:message_lines) + hash[:message_lines] = strip_ansi_codes(notification.message_lines) + end + if loglinking hash.merge!( correlation_id: exception.message[match_data_after(loglinking::CORRELATION_ID_TITLE)], diff --git a/spec/support/helpers/gitaly_setup.rb b/spec/support/helpers/gitaly_setup.rb index 7db9e0aaf09..06390406efc 100644 --- a/spec/support/helpers/gitaly_setup.rb +++ b/spec/support/helpers/gitaly_setup.rb @@ -10,8 +10,7 @@ require 'securerandom' require 'socket' require 'logger' require 'fileutils' - -require_relative '../../../lib/gitlab/utils' +require 'gitlab/utils/all' module GitalySetup extend self diff --git a/spec/support/rspec.rb b/spec/support/rspec.rb index b34f8fe9a22..4479e679d67 100644 --- a/spec/support/rspec.rb +++ b/spec/support/rspec.rb @@ -8,6 +8,7 @@ require_relative "helpers/stub_object_storage" require_relative "helpers/fast_rails_root" require 'gitlab/rspec/all' +require 'gitlab/utils/all' RSpec::Expectations.configuration.on_potential_false_positives = :raise diff --git a/spec/support/shared_contexts/lib/gitlab/sidekiq_logging/structured_logger_shared_context.rb b/spec/support/shared_contexts/lib/gitlab/sidekiq_logging/structured_logger_shared_context.rb index 1b50ef3fcff..b3b376ff6fe 100644 --- a/spec/support/shared_contexts/lib/gitlab/sidekiq_logging/structured_logger_shared_context.rb +++ b/spec/support/shared_contexts/lib/gitlab/sidekiq_logging/structured_logger_shared_context.rb @@ -69,7 +69,8 @@ RSpec.shared_context 'structured_logger' do end_payload.merge( 'message' => 'TestWorker JID-da883554ee4fe414012f5f42: deferred: 0.0 sec', 'job_status' => 'deferred', - 'job_deferred_by' => :feature_flag + 'job_deferred_by' => :feature_flag, + 'deferred_count' => 1 ) end diff --git a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb index 0792ac14e47..772e03950da 100644 --- a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb +++ b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb @@ -94,14 +94,6 @@ RSpec.shared_examples 'handle uploads' do expect(response).to have_gitlab_http_status(:not_found) end - - it 'is a working exploit without the validation' do - allow_any_instance_of(FileUploader).to receive(:secret) { secret } - - show_upload - - expect(response).to have_gitlab_http_status(:ok) - end end context 'when accessing a specific upload via different model' do |