Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-09-27 18:15:03 +00:00
parent 1403e9bc45
commit 3538972a0a
83 changed files with 806 additions and 588 deletions

1
.gitattributes vendored
View File

@ -1,5 +1,4 @@
VERSION merge=ours
Dangerfile gitlab-language=ruby
*.pdf filter=lfs diff=lfs merge=lfs -text
*.rb diff=ruby
workhorse/testdata/*.pdf -filter -diff -merge

View File

@ -0,0 +1,55 @@
cache-workhorse:
extends:
- .default-retry
- .default-before_script
- .rails-cache
- .setup-test-env-cache
- .caching:rules:cache-workhorse
stage: prepare
variables:
SETUP_DB: "false"
script:
- source scripts/gitlab_component_helpers.sh
- 'gitlab_workhorse_archive_doesnt_exist || { echoinfo "INFO: Exiting early as package exists."; exit 0; }'
- run_timed_command "scripts/setup-test-env"
- run_timed_command "select_gitlab_workhorse_essentials"
- run_timed_command "create_gitlab_workhorse_package"
- run_timed_command "upload_gitlab_workhorse_package"
artifacts:
expire_in: 7d
paths:
- ${TMP_TEST_GITLAB_WORKHORSE_PATH}/
.cache-assets-base:
extends:
- .compile-assets-base
- .caching:rules:cache-assets
stage: prepare
variables:
WEBPACK_REPORT: "false"
script:
- !reference [.yarn-install, script]
- export GITLAB_ASSETS_HASH=$(bundle exec rake gitlab:assets:hash_sum | tee assets-hash.txt)
- source scripts/gitlab_component_helpers.sh
- 'gitlab_assets_archive_doesnt_exist || { echoinfo "INFO: Exiting early as package exists."; exit 0; }'
# If we still use the legacy cache, we don't want to create a package from it as we don't check the sha sum in gitlab:assets:compile_with_new_strategy.
# This line can be removed once we stop downloading the legacy cache.
- rm -rf public/assets
- run_timed_command "bin/rake gitlab:assets:compile_with_new_strategy"
- run_timed_command "scripts/clean-old-cached-assets"
- run_timed_command "create_gitlab_assets_package"
- run_timed_command "upload_gitlab_assets_package"
cache-assets:test:
extends: .cache-assets-base
cache-assets:test as-if-foss:
extends:
- .cache-assets-base
- .as-if-foss
cache-assets:production:
extends: .cache-assets-base
variables:
NODE_ENV: "production"
RAILS_ENV: "production"

View File

@ -1,10 +1,12 @@
.yarn-install: &yarn-install
- source scripts/utils.sh
- run_timed_command "retry yarn install --frozen-lockfile"
.yarn-install:
script:
- source scripts/utils.sh
- run_timed_command "retry yarn install --frozen-lockfile"
.storybook-yarn-install: &storybook-yarn-install
- source scripts/utils.sh
- run_timed_command "retry yarn run storybook:install --frozen-lockfile"
.storybook-yarn-install:
script:
- source scripts/utils.sh
- run_timed_command "retry yarn run storybook:install --frozen-lockfile"
.compile-assets-base:
extends:
@ -21,8 +23,17 @@
WEBPACK_COMPILE_LOG_PATH: "tmp/webpack-output.log"
stage: prepare
script:
- *yarn-install
- run_timed_command "bin/rake gitlab:assets:compile"
- !reference [.yarn-install, script]
- |
# The new strategy to cache assets as generic packages is experimental and can be disabled by removing the `CACHE_ASSETS_AS_PACKAGE` variable
if [[ "${CACHE_ASSETS_AS_PACKAGE}" == "true" ]]; then
export GITLAB_ASSETS_HASH=$(bundle exec rake gitlab:assets:hash_sum | tee assets-hash.txt)
source scripts/gitlab_component_helpers.sh
run_timed_command "download_and_extract_gitlab_assets" || true
run_timed_command "bin/rake gitlab:assets:compile_with_new_strategy"
else
run_timed_command "bin/rake gitlab:assets:compile"
fi
- run_timed_command "scripts/clean-old-cached-assets"
compile-production-assets:
@ -42,8 +53,6 @@ compile-production-assets:
- public/assets/
- "${WEBPACK_COMPILE_LOG_PATH}"
when: always
before_script:
- !reference [.default-before_script, before_script]
after_script:
- rm -f /etc/apt/sources.list.d/google*.list # We don't need to update Chrome here
@ -88,7 +97,7 @@ update-yarn-cache:
- .shared:rules:update-cache
stage: prepare
script:
- *yarn-install
- !reference [.yarn-install, script]
update-storybook-yarn-cache:
extends:
@ -97,7 +106,7 @@ update-storybook-yarn-cache:
- .shared:rules:update-cache
stage: prepare
script:
- *storybook-yarn-install
- !reference [.storybook-yarn-install, script]
.frontend-fixtures-base:
extends:
@ -180,7 +189,7 @@ graphql-schema-dump as-if-foss:
SETUP_DB: "false"
before_script:
- !reference [.default-before_script, before_script]
- *yarn-install
- !reference [.yarn-install, script]
stage: test
.jest-base:
@ -256,7 +265,7 @@ coverage-frontend:
optional: true
stage: post-test
before_script:
- *yarn-install
- !reference [.yarn-install, script]
script:
- run_timed_command "yarn node scripts/frontend/merge_coverage_frontend.js"
# Removing the individual coverage results, as we just merged them.
@ -282,7 +291,7 @@ coverage-frontend:
stage: test
dependencies: []
script:
- *yarn-install
- !reference [.yarn-install, script]
- run_timed_command "retry yarn run webpack-prod"
qa-frontend-node:14:
@ -310,7 +319,7 @@ webpack-dev-server:
WEBPACK_MEMORY_TEST: "true"
WEBPACK_VENDOR_DLL: "true"
script:
- *yarn-install
- !reference [.yarn-install, script]
- run_timed_command "retry yarn webpack-vendor"
- run_timed_command "node --expose-gc node_modules/.bin/webpack-dev-server --config config/webpack.config.js"
artifacts:
@ -328,7 +337,7 @@ bundle-size-review:
stage: test
needs: []
script:
- *yarn-install
- !reference [.yarn-install, script]
- scripts/bundle_size_review
artifacts:
when: always
@ -366,7 +375,7 @@ startup-css-check as-if-foss:
- .frontend-test-base
- .storybook-yarn-cache
script:
- *storybook-yarn-install
- !reference [.storybook-yarn-install, script]
- yarn run storybook:build
needs: ["graphql-schema-dump"]

View File

@ -79,10 +79,12 @@
policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up.
.assets-cache: &assets-cache
key: "assets-debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-node-${NODE_ENV}-v2"
key: "assets-debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-node-${NODE_ENV}-v3"
# This list should match GITLAB_ASSETS_PATHS_LIST from scripts/gitlab_component_helpers.sh
paths:
- assets-hash.txt
- public/assets/webpack/
- app/assets/javascripts/locale/**/app.js
- public/assets/
- tmp/cache/assets/sprockets/
- tmp/cache/babel-loader/
- tmp/cache/vue-loader/

View File

@ -168,7 +168,7 @@ setup-test-env:
SETUP_DB: "false"
script:
- echo $CI_MERGE_REQUEST_APPROVED
- source scripts/gitlab_workhorse_component_helpers.sh
- source scripts/gitlab_component_helpers.sh
- run_timed_command "download_and_extract_gitlab_workhorse_package" || true
- run_timed_command "scripts/setup-test-env"
- run_timed_command "select_gitlab_workhorse_essentials"
@ -197,22 +197,6 @@ setup-test-env:
- ${TMP_TEST_GITLAB_WORKHORSE_PATH}/
when: always
build-components:
extends:
- setup-test-env
- .rails:rules:build-components
script:
- source scripts/gitlab_workhorse_component_helpers.sh
- 'gitlab_workhorse_archive_doesnt_exist || { echoinfo "INFO: Exiting early as package exists."; exit 0; }'
- run_timed_command "scripts/setup-test-env"
- run_timed_command "select_gitlab_workhorse_essentials"
- run_timed_command "create_gitlab_workhorse_package"
- run_timed_command "upload_gitlab_workhorse_package"
artifacts:
expire_in: 7d
paths:
- ${TMP_TEST_GITLAB_WORKHORSE_PATH}/
update-setup-test-env-cache:
extends:
- setup-test-env

View File

@ -249,8 +249,21 @@
- "babel.config.js"
- "config/webpack.config.js"
- "config/**/*.js"
- "vendor/assets/**/*"
- "{,ee/,jh/}app/assets/**/*"
- "vendor/assets/**/*"
# This list should match the list in Tasks::Gitlab::Assets.assets_impacting_compilation
.assets-compilation-patterns: &assets-compilation-patterns
- "{package.json,yarn.lock}"
- ".browserslistrc"
- "babel.config.js"
- "config/webpack.config.js"
- "*.js"
- "config/**/*.js"
- "locale/**/gitlab.po"
- "{,ee/,jh/}app/assets/**/*"
- "fixtures/emojis/**/*"
- "vendor/assets/**/*"
.frontend-patterns-for-as-if-foss: &frontend-patterns-for-as-if-foss
- "{package.json,yarn.lock}"
@ -652,6 +665,37 @@
- changes: *ci-build-images-patterns
- changes: *code-qa-patterns
#################
# Caching rules #
#################
.caching:rules:cache-workhorse:
rules:
- <<: *if-dot-com-ee-schedule
- <<: *if-dot-com-gitlab-org-default-branch
changes: ["workhorse/**/*"]
- <<: *if-dot-com-gitlab-org-merge-request
changes:
- ".gitlab/ci/caching.gitlab-ci.yml"
- "scripts/gitlab_component_helpers.sh"
when: manual
allow_failure: true
.caching:rules:cache-assets:
rules:
# The new strategy to cache assets as generic packages is experimental and can be disabled by removing the `CACHE_ASSETS_AS_PACKAGE` variable
- if: '$CACHE_ASSETS_AS_PACKAGE != "true"'
when: never
- <<: *if-dot-com-ee-schedule
- <<: *if-dot-com-gitlab-org-default-branch
changes: *assets-compilation-patterns
- <<: *if-dot-com-gitlab-org-merge-request
changes:
- ".gitlab/ci/caching.gitlab-ci.yml"
- "scripts/gitlab_component_helpers.sh"
- "lib/tasks/gitlab/assets.rake"
when: manual
allow_failure: true
######################
# CI Templates Rules #
######################
@ -969,16 +1013,6 @@
###############
# Rails rules #
###############
.rails:rules:build-components:
rules:
- <<: *if-dot-com-ee-schedule
- <<: *if-dot-com-gitlab-org-default-branch
changes:
- "workhorse/**/*"
- <<: *if-dot-com-gitlab-org-merge-request
when: manual
allow_failure: true
.rails:rules:setup-test-env:
rules:
- changes: *setup-test-env-patterns

View File

@ -1,8 +1,6 @@
---
Rails/HelperInstanceVariable:
# Offense count: 671
# Temporarily disabled due to too many offenses
Enabled: false
Details: grace period
Exclude:
- 'app/helpers/admin/user_actions_helper.rb'
- 'app/helpers/application_helper.rb'
@ -29,7 +27,6 @@ Rails/HelperInstanceVariable:
- 'app/helpers/icons_helper.rb'
- 'app/helpers/ide_helper.rb'
- 'app/helpers/import_helper.rb'
- 'app/helpers/integrations_helper.rb'
- 'app/helpers/issuables_description_templates_helper.rb'
- 'app/helpers/issuables_helper.rb'
- 'app/helpers/issues_helper.rb'
@ -40,6 +37,7 @@ Rails/HelperInstanceVariable:
- 'app/helpers/nav_helper.rb'
- 'app/helpers/notes_helper.rb'
- 'app/helpers/operations_helper.rb'
- 'app/helpers/packages_helper.rb'
- 'app/helpers/page_layout_helper.rb'
- 'app/helpers/projects_helper.rb'
- 'app/helpers/releases_helper.rb'
@ -59,11 +57,13 @@ Rails/HelperInstanceVariable:
- 'app/helpers/webpack_helper.rb'
- 'app/helpers/wiki_helper.rb'
- 'ee/app/helpers/ee/application_helper.rb'
- 'ee/app/helpers/ee/application_settings_helper.rb'
- 'ee/app/helpers/ee/boards_helper.rb'
- 'ee/app/helpers/ee/feature_flags_helper.rb'
- 'ee/app/helpers/ee/form_helper.rb'
- 'ee/app/helpers/ee/graph_helper.rb'
- 'ee/app/helpers/ee/groups/group_members_helper.rb'
- 'ee/app/helpers/ee/groups/settings_helper.rb'
- 'ee/app/helpers/ee/groups_helper.rb'
- 'ee/app/helpers/ee/integrations_helper.rb'
- 'ee/app/helpers/ee/kerberos_helper.rb'
@ -77,7 +77,8 @@ Rails/HelperInstanceVariable:
- 'ee/app/helpers/ee/projects_helper.rb'
- 'ee/app/helpers/ee/search_helper.rb'
- 'ee/app/helpers/ee/selects_helper.rb'
- 'ee/app/helpers/ee/sorting_helper.rb'
- 'ee/app/helpers/ee/subscribable_banner_helper.rb'
- 'ee/app/helpers/ee/wiki_helper.rb'
- 'ee/app/helpers/path_locks_helper.rb'
- 'ee/app/helpers/projects/security/discover_helper.rb'
- 'ee/app/helpers/seat_count_alert_helper.rb'

View File

@ -1,9 +1,7 @@
---
# Cop supports --auto-correct.
Style/StringLiteralsInInterpolation:
# Offense count: 119
# Temporarily disabled due to too many offenses
Enabled: false
Details: grace period
Exclude:
- 'app/graphql/mutations/base_mutation.rb'
- 'app/helpers/colors_helper.rb'
@ -23,11 +21,16 @@ Style/StringLiteralsInInterpolation:
- 'ee/app/helpers/ee/merge_requests_helper.rb'
- 'ee/app/models/license.rb'
- 'ee/app/services/epics/tree_reorder_service.rb'
- 'ee/lib/ee/api/helpers/issues_helpers.rb'
- 'ee/lib/gitlab/elastic/helper.rb'
- 'ee/lib/tasks/gitlab/elastic.rake'
- 'ee/spec/features/admin/admin_settings_spec.rb'
- 'ee/spec/features/subscriptions/expiring_subscription_message_spec.rb'
- 'ee/spec/lib/gitlab/expiring_subscription_message_spec.rb'
- 'lib/api/helpers/snippets_helpers.rb'
- 'lib/api/validations/validators/check_assignees_count.rb'
- 'lib/banzai/filter/references/abstract_reference_filter.rb'
- 'lib/banzai/filter/syntax_highlight_filter.rb'
- 'lib/generators/gitlab/usage_metric_definition_generator.rb'
- 'lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb'
- 'lib/gitlab/ci/config/entry/job.rb'
@ -36,6 +39,7 @@ Style/StringLiteralsInInterpolation:
- 'lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb'
- 'lib/gitlab/doctor/secrets.rb'
- 'lib/gitlab/endpoint_attributes/config.rb'
- 'lib/gitlab/gitaly_client/ref_service.rb'
- 'lib/gitlab/graphql/queries.rb'
- 'lib/gitlab/quick_actions/extractor.rb'
- 'lib/gitlab/sanitizers/exif.rb'
@ -43,13 +47,11 @@ Style/StringLiteralsInInterpolation:
- 'lib/gitlab/tracking/destinations/snowplow.rb'
- 'lib/tasks/gitlab/info.rake'
- 'lib/tasks/gitlab/sidekiq.rake'
- 'lib/tasks/gitlab/tw/codeowners.rake'
- 'qa/qa/ee/page/component/secure_report.rb'
- 'qa/qa/ee/page/group/secure/show.rb'
- 'qa/qa/resource/events/base.rb'
- 'qa/qa/service/cluster_provider/base.rb'
- 'qa/qa/service/cluster_provider/gcloud.rb'
- 'qa/qa/service/docker_run/gitlab_runner.rb'
- 'qa/qa/specs/helpers/context_selector.rb'
- 'qa/qa/tools/generate_perf_testdata.rb'
- 'rubocop/cop/migration/prevent_index_creation.rb'
@ -59,9 +61,12 @@ Style/StringLiteralsInInterpolation:
- 'spec/finders/serverless_domain_finder_spec.rb'
- 'spec/lib/banzai/filter/references/commit_reference_filter_spec.rb'
- 'spec/lib/banzai/filter/references/issue_reference_filter_spec.rb'
- 'spec/lib/gitlab/background_migration/batched_migration_job_spec.rb'
- 'spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb'
- 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
- 'spec/lib/gitlab/gitaly_client/ref_service_spec.rb'
- 'spec/lib/object_storage/direct_upload_spec.rb'
- 'spec/models/serverless/domain_spec.rb'
- 'spec/requests/api/keys_spec.rb'
- 'spec/support/database/prevent_cross_joins.rb'
- 'spec/views/notify/import_issues_csv_email.html.haml_spec.rb'

View File

@ -1 +1 @@
5ee7c55528f5833aec37ba4a6bfb2b4c3f64dc80
2ff0039f15ef06063925ff6c0406f6e092ad2435

View File

@ -585,30 +585,30 @@
}
},
"globalVariables": {
"markdownDescription": "Defines environment variables globally. Job level property overrides global variables. If a job sets `variables: {}`, all global variables are turned off. You can use the value and description keywords to define variables that are prefilled when running a pipeline manually. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variables).",
"anyOf": [
{"type": "object"},
{
"type": "array",
"items": {
"type": "string"
}
}
],
"additionalProperties": {
"anyOf": [
{"type": ["string", "integer", "array"]},
{
"type": "object",
"properties": {
"value": { "type": "string" },
"description": {
"type": "string",
"description": "Explains what the variable is used for, what the acceptable values are."
}
"markdownDescription": "Defines default variables for all jobs. Job level property overrides global variables. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variables).",
"type": "object",
"patternProperties": {
".*": {
"oneOf": [
{
"type": ["string", "number"]
},
{
"type": "object",
"properties": {
"value": {
"type": "string"
},
"description": {
"type": "string",
"markdownDescription": "Explains what the variable is used for, what the acceptable values are. Variables with `description` are prefilled when running a pipeline manually. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variablesdescription)."
}
},
"additionalProperties": false
}
}
]
]
},
"additionalProperties": false
}
},
"if": {
@ -652,21 +652,14 @@
}
},
"variables": {
"markdownDescription": "Defines environment variables for specific jobs. Job level property overrides global variables. If a job sets `variables: {}`, all global variables are turned off. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#rulesvariables).",
"anyOf": [
{
"type": "object",
"additionalProperties": {
"type": ["string", "integer", "array"]
}
"markdownDescription": "Defines environment variables. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variables).",
"type": "object",
"patternProperties": {
".*": {
"type": ["string", "number"]
},
{
"type": "array",
"items": {
"type": "string"
}
}
]
"additionalProperties": false
}
},
"timeout": {
"type": "string",

View File

@ -1,7 +1,6 @@
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import $ from 'jquery';
import { setCookie } from '~/lib/utils/common_utils';
import { loadCSSFile } from '~/lib/utils/css_utils';
import UsersSelect from '~/users_select';
export default class IssuableContext {
@ -9,24 +8,6 @@ export default class IssuableContext {
this.userSelect = new UsersSelect(currentUser);
this.reviewersSelect = new UsersSelect(currentUser, '.js-reviewer-search');
const $select2 = $('select.select2');
if ($select2.length) {
import(/* webpackChunkName: 'select2' */ 'select2/select2')
.then(() => {
// eslint-disable-next-line promise/no-nesting
loadCSSFile(gon.select2_css_path)
.then(() => {
$select2.select2({
width: 'resolve',
dropdownAutoWidth: true,
});
})
.catch(() => {});
})
.catch(() => {});
}
$('.issuable-sidebar .inline-update').on('change', 'select', function onClickSelect() {
return $(this).submit();
});

View File

@ -5,7 +5,7 @@ import $ from 'jquery';
import { mapActions, mapGetters, mapState } from 'vuex';
import Autosave from '~/autosave';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import createFlash from '~/flash';
import { createAlert } from '~/flash';
import { badgeState } from '~/issuable/components/status_box.vue';
import httpStatusCodes from '~/lib/utils/http_status';
import {
@ -276,7 +276,7 @@ export default {
.then(() => badgeState.updateStatus && badgeState.updateStatus())
.then(refreshUserMergeRequestCounts)
.catch(() =>
createFlash({
createAlert({
message: constants.toggleStateErrorMessage[this.noteableType][this.openState],
}),
);

View File

@ -3,7 +3,7 @@ import { GlTooltipDirective, GlIcon, GlButton, GlDropdownItem } from '@gitlab/ui
import { mapActions, mapGetters, mapState } from 'vuex';
import Api from '~/api';
import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status';
import createFlash from '~/flash';
import { createAlert } from '~/flash';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { __, sprintf } from '~/locale';
import eventHub from '~/sidebar/event_hub';
@ -238,7 +238,7 @@ export default {
})
.then(() => this.handleAssigneeUpdate(assignees))
.catch(() =>
createFlash({
createAlert({
message: __('Something went wrong while updating assignees'),
}),
);

View File

@ -1,6 +1,6 @@
<script>
import { mapActions, mapGetters } from 'vuex';
import createFlash from '~/flash';
import { createAlert } from '~/flash';
import { __ } from '~/locale';
import AwardsList from '~/vue_shared/components/awards_list.vue';
@ -49,7 +49,7 @@ export default {
};
this.toggleAwardRequest(data).catch(() =>
createFlash({
createAlert({
message: __('Something went wrong on our end.'),
}),
);

View File

@ -2,7 +2,7 @@
import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { mapActions, mapGetters } from 'vuex';
import DraftNote from '~/batch_comments/components/draft_note.vue';
import createFlash from '~/flash';
import { createAlert } from '~/flash';
import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave';
import { isLoggedIn } from '~/lib/utils/common_utils';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
@ -247,7 +247,7 @@ export default {
const msg = __(
'Your comment could not be submitted! Please check your network connection and try again.',
);
createFlash({
createAlert({
message: msg,
parent: this.$el,
});

View File

@ -5,7 +5,7 @@ import { escape, isEmpty } from 'lodash';
import { mapGetters, mapActions } from 'vuex';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { INLINE_DIFF_LINES_KEY } from '~/diffs/constants';
import createFlash from '~/flash';
import { createAlert } from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending';
import { truncateSha } from '~/lib/utils/text_utility';
@ -270,7 +270,7 @@ export default {
this.isDeleting = false;
})
.catch(() => {
createFlash({
createAlert({
message: __('Something went wrong while deleting your note. Please try again.'),
});
this.isDeleting = false;
@ -349,7 +349,7 @@ export default {
},
handleUpdateError() {
const msg = __('Something went wrong while editing your comment. Please try again.');
createFlash({
createAlert({
message: msg,
parent: this.$el,
});

View File

@ -1,7 +1,7 @@
<script>
import { mapGetters, mapActions } from 'vuex';
import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
import createFlash from '~/flash';
import { createAlert } from '~/flash';
import { __ } from '~/locale';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
@ -221,7 +221,7 @@ export default {
.catch(() => {
this.setLoadingState(false);
this.setNotesFetchedState(true);
createFlash({
createAlert({
message: __('Something went wrong while fetching comments. Please try again.'),
});
});

View File

@ -1,7 +1,7 @@
import { mapActions, mapGetters, mapState } from 'vuex';
import { getDraftReplyFormData, getDraftFormData } from '~/batch_comments/utils';
import { TEXT_DIFF_POSITION_TYPE, IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
import createFlash from '~/flash';
import { createAlert } from '~/flash';
import { clearDraft } from '~/lib/utils/autosave';
import { s__ } from '~/locale';
import { formatLineRange } from '~/notes/components/multiline_comment_utils';
@ -42,7 +42,7 @@ export default {
this.handleClearForm(this.discussion.line_code);
})
.catch(() => {
createFlash({
createAlert({
message: s__('MergeRequests|An error occurred while saving the draft comment.'),
});
});
@ -82,7 +82,7 @@ export default {
}
})
.catch(() => {
createFlash({
createAlert({
message: s__('MergeRequests|An error occurred while saving the draft comment.'),
});
});

View File

@ -1,4 +1,4 @@
import createFlash from '~/flash';
import { createAlert } from '~/flash';
import { __ } from '~/locale';
export default {
@ -46,7 +46,7 @@ export default {
this.isResolving = false;
const msg = __('Something went wrong while resolving this discussion. Please try again.');
createFlash({
createAlert({
message: msg,
parent: this.$el,
});

View File

@ -1,4 +1,4 @@
import createFlash from '~/flash';
import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
@ -35,7 +35,7 @@ export const receiveSaveChangesError = (_, error) => {
const { response = {} } = error;
const message = response.data && response.data.message ? response.data.message : '';
createFlash({
createAlert({
message: `${__('There was an error saving your changes.')} ${message}`,
});
};

View File

@ -15,7 +15,7 @@ module Packages
result = base.nuget
.has_version
.with_name_like(@params[:package_name])
result = result.with_version(@params[:package_version]) if @params[:package_version].present?
result = result.with_case_insensitive_version(@params[:package_version]) if @params[:package_version].present?
result
end
end

View File

@ -693,7 +693,7 @@ class Note < ApplicationRecord
# Method necesary while we transition into the new format for task system notes
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/369923
def note
return super unless system? && for_issue? && super.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN)
return super unless system? && for_issue? && super&.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN)
super.sub!('task', 'checklist item')
end
@ -701,7 +701,7 @@ class Note < ApplicationRecord
# Method necesary while we transition into the new format for task system notes
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/369923
def note_html
return super unless system? && for_issue? && super.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN)
return super unless system? && for_issue? && super&.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN)
super.sub!('task', 'checklist item')
end

View File

@ -114,6 +114,10 @@ class Packages::Package < ApplicationRecord
)
end
scope :with_case_insensitive_version, ->(version) do
where('LOWER(version) = ?', version.downcase)
end
scope :search_by_name, ->(query) { fuzzy_search(query, [:name], use_minimum_char_limit: false) }
scope :with_version, ->(version) { where(version: version) }
scope :without_version_like, -> (version) { where.not(arel_table[:version].matches(version)) }

View File

@ -27,18 +27,13 @@ module Ci
end
def pipeline_artifact_params
attributes = {
{
pipeline: pipeline,
file_type: :code_coverage,
file: carrierwave_file,
size: carrierwave_file['tempfile'].size
size: carrierwave_file['tempfile'].size,
locked: pipeline.locked
}
if ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, pipeline.project)
attributes[:locked] = pipeline.locked
end
attributes
end
def carrierwave_file

View File

@ -23,20 +23,15 @@ module Ci
def artifact_attributes
file = build_carrierwave_file!
attributes = {
{
project_id: pipeline.project_id,
file_type: :code_quality_mr_diff,
file_format: Ci::PipelineArtifact::REPORT_TYPES.fetch(:code_quality_mr_diff),
size: file["tempfile"].size,
file: file,
expire_at: Ci::PipelineArtifact::EXPIRATION_DATE.from_now
expire_at: Ci::PipelineArtifact::EXPIRATION_DATE.from_now,
locked: pipeline.locked
}
if ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, pipeline.project)
attributes[:locked] = pipeline.locked
end
attributes
end
def merge_requests

View File

@ -11,8 +11,6 @@ module Ci
unlocked_pipeline_artifacts: 0
}
unlock_pipeline_artifacts_enabled = ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, ci_ref.project)
if ::Feature.enabled?(:ci_update_unlocked_job_artifacts, ci_ref.project)
loop do
unlocked_pipelines = []
@ -22,9 +20,7 @@ module Ci
unlocked_pipelines = unlock_pipelines(ci_ref, before_pipeline)
unlocked_job_artifacts = unlock_job_artifacts(unlocked_pipelines)
if unlock_pipeline_artifacts_enabled
results[:unlocked_pipeline_artifacts] += unlock_pipeline_artifacts(unlocked_pipelines)
end
results[:unlocked_pipeline_artifacts] += unlock_pipeline_artifacts(unlocked_pipelines)
end
break if unlocked_pipelines.empty?

View File

@ -1,4 +1,4 @@
= form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-gitaly-settings'), html: { class: 'fieldset-form' } do |f|
= gitlab_ui_form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-gitaly-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
@ -18,4 +18,4 @@
.form-text.text-muted
= _('Timeout for moderately fast Gitaly operations (in seconds). Provide a value between Default timeout and Fast timeout.')
= f.submit _('Save changes'), class: "gl-button btn btn-confirm"
= f.submit _('Save changes'), pajamas_button: true

View File

@ -17,4 +17,4 @@
= f.label :sentry_environment, _('Environment'), class: 'label-light'
= f.text_field :sentry_environment, class: 'form-control gl-form-input', placeholder: Rails.env
= f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
= f.submit _('Save changes'), pajamas_button: true

View File

@ -35,7 +35,7 @@
= link_to(s_('AdminArea|New project'), new_project_path, class: "btn gl-button btn-default")
= c.footer do
.d-flex.align-items-center
= link_to(s_('AdminArea|View latest projects'), admin_projects_path)
= link_to(s_('AdminArea|View latest projects'), admin_projects_path(sort: 'created_desc'))
= sprite_icon('chevron-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2')
.col-md-4.gl-mb-6
= render Pajamas::CardComponent.new(**component_params) do |c|
@ -71,7 +71,7 @@
= link_to(s_('AdminArea|New group'), new_admin_group_path, class: "btn gl-button btn-default")
= c.footer do
.d-flex.align-items-center
= link_to(s_('AdminArea|View latest groups'), admin_groups_path)
= link_to(s_('AdminArea|View latest groups'), admin_groups_path(sort: 'created_desc'))
= sprite_icon('chevron-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2')
.row
.col-md-4.gl-mb-6

View File

@ -3,8 +3,9 @@
%hr
%div
= form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f|
= gitlab_ui_form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f|
= render partial: 'shared/deploy_keys/form', locals: { form: f, deploy_key: @deploy_key }
.form-actions
= f.submit 'Create', class: 'btn gl-button btn-confirm', data: { qa_selector: "add_deploy_key_button" }
= link_to _('Cancel'), admin_deploy_keys_path, class: 'btn gl-button btn-default btn-cancel'
= f.submit 'Create', data: { qa_selector: "add_deploy_key_button" }, pajamas_button: true
= render Pajamas::ButtonComponent.new(href: admin_deploy_keys_path) do
= _('Cancel')

View File

@ -1,7 +1,7 @@
- show_password_form = local_assigns.fetch(:show_password_form, password_authentication_enabled_for_web?)
- render_signup_link = local_assigns.fetch(:render_signup_link, true)
%ul.nav-links.new-session-tabs.nav-tabs.nav{ class: "#{"custom-provider-tabs" if any_form_based_providers_enabled?} #{"nav-links-unboxed" if Feature.enabled?(:restyle_login_page, @project)}" }
%ul.nav-links.new-session-tabs.nav-tabs.nav{ class: "#{'custom-provider-tabs' if any_form_based_providers_enabled?} #{'nav-links-unboxed' if Feature.enabled?(:restyle_login_page, @project)}" }
- if crowd_enabled?
%li.nav-item
= link_to _("Crowd"), "#crowd", class: "nav-link #{active_when(form_based_auth_provider_has_active_class?(:crowd))}", 'data-toggle' => 'tab', role: 'tab'

View File

@ -24,4 +24,4 @@
= menu_item.fetch(:title)
- if menu_item.fetch(:emoji)
-# We need to insert a space between the title and emoji
= " #{emoji_icon(menu_item.fetch(:emoji), 'aria-hidden': true, class: "gl-font-base gl-vertical-align-baseline")}".html_safe
= " #{emoji_icon(menu_item.fetch(:emoji), 'aria-hidden': true, class: 'gl-font-base gl-vertical-align-baseline')}".html_safe

View File

@ -24,7 +24,7 @@
- if @reply_by_email
= _('Reply to this email directly or %{view_it_on_gitlab}.').html_safe % { view_it_on_gitlab: link_to(_("view it on GitLab"), @target_url) }
- else
#{link_to _("View it on GitLab"), @target_url}.
#{link_to _('View it on GitLab'), @target_url}.
%br
= notification_reason_text(reason: @reason, show_manage_notifications_link: !@labels_url, show_help_link: true, manage_label_subscriptions_url: @labels_url, unsubscribe_url: @unsubscribe_url, format: :html)

View File

@ -13,7 +13,7 @@
\- - - - -
\
\
#{pluralize @message.diffs_count, "changed file"}:
#{pluralize @message.diffs_count, 'changed file'}:
\
- @message.diffs.each do |diff_file|
- if diff_file.deleted_file?

View File

@ -1,2 +1,2 @@
%p
You have been unsubscribed from receiving GitLab administrator notifications.
= s_('Notify|You have been unsubscribed from receiving GitLab administrator notifications.')

View File

@ -10,12 +10,12 @@
.col-lg-8
%h4.gl-mt-0
= _('Add email address')
= form_for 'email', url: profile_emails_path do |f|
= gitlab_ui_form_for 'email', url: profile_emails_path do |f|
.form-group
= f.label :email, _('Email'), class: 'label-bold'
= f.text_field :email, class: 'form-control gl-form-input', data: { qa_selector: 'email_address_field' }
.gl-mt-3
= f.submit _('Add email address'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'add_email_address_button' }
= f.submit _('Add email address'), data: { qa_selector: 'add_email_address_button' }, pajamas_button: true
%hr
%h4.gl-mt-0
= _('Linked emails (%{email_count})') % { email_count: @emails.load.size }

View File

@ -1,5 +1,5 @@
%div
= form_for [:profile, @gpg_key], html: { class: 'js-requires-input' } do |f|
= gitlab_ui_form_for [:profile, @gpg_key], html: { class: 'js-requires-input' } do |f|
= form_errors(@gpg_key)
.form-group
@ -7,4 +7,4 @@
= f.text_area :key, class: "form-control gl-form-input", rows: 8, required: true, placeholder: _("Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'.")
.gl-mt-3
= f.submit s_('Profiles|Add key'), class: "gl-button btn btn-confirm"
= f.submit s_('Profiles|Add key'), pajamas_button: true

View File

@ -1,4 +1,4 @@
.btn-group.ml-0.w-100
- Gitlab::Workhorse::ARCHIVE_FORMATS.each_with_index do |fmt, index|
- archive_path = project_archive_path(project, id: tree_join(ref, archive_prefix), path: path, format: fmt)
= link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "gl-button btn btn-sm #{index == 0 ? "btn-confirm" : "btn-default"}"
= link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "gl-button btn btn-sm #{index == 0 ? 'btn-confirm' : 'btn-default'}"

View File

@ -1,3 +1,3 @@
- if signature
- uri = "projects/commit/#{"x509/" if x509_signature?(signature)}"
- uri = "projects/commit/#{'x509/' if x509_signature?(signature)}"
= render partial: "#{uri}#{signature.verification_status}_signature_badge", locals: { signature: signature }

View File

@ -17,7 +17,7 @@
- content = capture do
- if show_user
.clearfix
- uri_signature_badge_user = "projects/commit/#{"x509/" if x509_signature?(signature)}signature_badge_user"
- uri_signature_badge_user = "projects/commit/#{'x509/' if x509_signature?(signature)}signature_badge_user"
= render partial: "#{uri_signature_badge_user}", locals: { signature: signature }
- if x509_signature?(signature)

View File

@ -29,7 +29,7 @@
- if view_details && merge_request
= link_to commit.title, project_commit_path(project, commit.id, merge_request_iid: merge_request.iid), class: ["commit-row-message item-title js-onboarding-commit-item", ("font-italic" if commit.message.empty?)]
- else
= link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item #{"font-italic" if commit.message.empty?}", data: link_data_attrs)
= link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item #{'font-italic' if commit.message.empty?}", data: link_data_attrs)
%span.commit-row-message.d-inline.d-sm-none
&middot;
= commit.short_id

View File

@ -1,8 +0,0 @@
---
name: ci_update_unlocked_pipeline_artifacts
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97228
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372835
milestone: '15.4'
type: development
group: group::pipeline insights
default_enabled: false

View File

@ -2,6 +2,15 @@
Gitlab::Application.configure do |config|
config.middleware.use(Gitlab::Database::LoadBalancing::RackMiddleware)
# We need re-rerun the setup when code reloads in development
config.reloader.to_prepare do
if Gitlab.dev_or_test_env?
Gitlab::Database::LoadBalancing.base_models.each do |model|
Gitlab::Database::LoadBalancing::Setup.new(model).setup
end
end
end
end
Gitlab::Database::LoadBalancing.base_models.each do |model|
@ -14,13 +23,6 @@ Gitlab::Database::LoadBalancing.base_models.each do |model|
# information.
Gitlab::Database::LoadBalancing::Setup.new(model).setup
# We need re-rerun the setup when code reloads in development
Rails.application.reloader.to_prepare do
if Rails.env.development? || Rails.env.test?
Gitlab::Database::LoadBalancing::Setup.new(model).setup
end
end
# Database queries may be run before we fork, so we must set up the load
# balancer as early as possible. When we do fork, we need to make sure all the
# hosts are disconnected.

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
class AddIndexPackagesPackagesOnProjectIdAndLowerVersionToPackages < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
INDEX_NAME = 'index_packages_packages_on_project_id_and_lower_version'
NUGET_PACKAGE_TYPE = 4
def up
add_concurrent_index(
:packages_packages,
'project_id, LOWER(version)',
name: INDEX_NAME,
where: "package_type = #{NUGET_PACKAGE_TYPE}"
)
end
def down
remove_concurrent_index_by_name(:packages_packages, INDEX_NAME)
end
end

View File

@ -0,0 +1 @@
03accc241b8955f0ccfa3b40168e9f194360704d8937cd531683191b8fe4f8c8

View File

@ -29667,6 +29667,8 @@ CREATE INDEX index_packages_packages_on_name_trigram ON packages_packages USING
CREATE INDEX index_packages_packages_on_project_id_and_created_at ON packages_packages USING btree (project_id, created_at);
CREATE INDEX index_packages_packages_on_project_id_and_lower_version ON packages_packages USING btree (project_id, lower((version)::text)) WHERE (package_type = 4);
CREATE INDEX index_packages_packages_on_project_id_and_package_type ON packages_packages USING btree (project_id, package_type);
CREATE INDEX index_packages_packages_on_project_id_and_status_and_id ON packages_packages USING btree (project_id, status, id);

View File

@ -17,6 +17,7 @@ full list of reference architectures, see
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git (Pull): 20 RPS, Git (Push): 4 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k)**
> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|-------|-------------------------|------------------|----------------|-----------|

View File

@ -12,7 +12,7 @@ full list of reference architectures, see
If you are serving up to 1,000 users and you don't have strict availability
requirements, a single-node solution with
[frequent backups](index.md#automated-backups) is appropriate for
[frequent backups](index.md#backups) is appropriate for
many organizations.
> - **Supported users (approximate):** 1,000
@ -24,6 +24,7 @@ many organizations.
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 20 RPS, Web: 2 RPS, Git (Pull): 2 RPS, Git (Push): 1 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/1k)**
> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
| Users | Configuration | GCP | AWS | Azure |
|--------------|-------------------------|----------------|--------------|----------|

View File

@ -17,6 +17,7 @@ full list of reference architectures, see
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 500 RPS, Web: 50 RPS, Git (Pull): 50 RPS, Git (Push): 10 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/25k)**
> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|-------|-------------------------|------------------|--------------|-----------|

View File

@ -18,6 +18,7 @@ For a full list of reference architectures, see
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git (Pull): 4 RPS, Git (Push): 1 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/2k)**
> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
| Service | Nodes | Configuration | GCP | AWS | Azure |
|----------------------------|-------|------------------------|-----------------|--------------|----------|

View File

@ -27,6 +27,7 @@ For a full list of reference architectures, see
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 60 RPS, Web: 6 RPS, Git (Pull): 6 RPS, Git (Push): 1 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k)**
> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
| Service | Nodes | Configuration | GCP | AWS | Azure |
|-------------------------------------------|-------|-----------------------|-----------------|--------------|----------|

View File

@ -17,6 +17,7 @@ full list of reference architectures, see
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 1000 RPS, Web: 100 RPS, Git (Pull): 100 RPS, Git (Push): 20 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k)**
> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
| Service | Nodes | Configuration | GCP | AWS | Azure |
|------------------------------------------|-------|-------------------------|------------------|---------------|-----------|

View File

@ -24,6 +24,7 @@ costly-to-operate environment by using the
> - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant
> - **Test requests per second (RPS) rates:** API: 100 RPS, Web: 10 RPS, Git (Pull): 10 RPS, Git (Push): 2 RPS
> - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k)**
> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use).
| Service | Nodes | Configuration | GCP | AWS | Azure |
|-------------------------------------------|-------|-------------------------|-----------------|--------------|----------|

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -7,39 +7,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Reference architectures **(FREE SELF)**
You can set up GitLab on a single server or scale it up to serve many users.
This page details the recommended Reference Architectures that were built and
verified by the GitLab Quality and Support teams.
Below is a chart representing each architecture tier and the number of users
they can handle. As your number of users grow with time, it's recommended that
you scale GitLab accordingly.
![Reference Architectures](img/reference-architectures.png)
<!-- Internal link: https://docs.google.com/spreadsheets/d/1obYP4fLKkVVDOljaI3-ozhmCiPtEeMblbBKkf2OADKs/edit#gid=1403207183 -->
For GitLab instances with less than 2,000 users, it's recommended that you use
the [default setup](#automated-backups) by
[installing GitLab](../../install/index.md) on a single machine to minimize
maintenance and resource costs.
If your organization has more than 2,000 users, the recommendation is to scale the
GitLab components to multiple machine nodes. The machine nodes are grouped by
components. The addition of these nodes increases the performance and
scalability of to your GitLab instance.
When scaling GitLab, there are several factors to consider:
- Multiple application nodes to handle frontend traffic.
- A load balancer is added in front to distribute traffic across the application nodes.
- The application nodes connects to a shared file server and PostgreSQL and Redis services on the backend.
The GitLab Reference Architectures have been designed and tested by the
GitLab Quality and Support teams to provide recommended deployments at scale.
## Available reference architectures
Depending on your workflow, the following recommended reference architectures
may need to be adapted accordingly. Your workload is influenced by factors
including how active your users are, how much automation you use, mirroring,
and repository/change size. Additionally the displayed memory values are
and repository/change size. Additionally, the displayed memory values are
provided by [GCP machine types](https://cloud.google.com/compute/docs/machine-types).
For different cloud vendors, attempt to select options that best match the
provided architecture.
@ -72,6 +48,169 @@ to get assistance from Support with troubleshooting the [2,000 users](2k_users.m
and higher reference architectures.
[Read more about our definition of scaled architectures](https://about.gitlab.com/support/#definition-of-scaled-architecture).
## Deciding which architecture to use
The Reference Architectures are designed to strike a balance between two important factors--performance and resilience.
While they are designed to make it easier to set up GitLab at scale, it can still be a challenge to know which one will meet your requirements.
As a general guide, **the more performant and/or resilient you want your environment to be, the more involved it will be**.
This section explains the designs you can choose from. It begins with the least complexity, goes to the most, and ends with a decision tree.
### Backups
For environments serving 2,000 or fewer users we generally recommend that an [automated backup](../../raketasks/backup_gitlab.md#configuring-cron-to-make-daily-backups) strategy is used instead of HA.
Backups can provide a good level of RPO / RTO while avoiding the complexities that come with HA.
### High Availability (HA)
High Availability ensures every component in the GitLab setup can handle failures through various mechanisms. To achieve this however is involved, and the environments required can be sizable.
For environments serving 3,000 or more users we generally recommend that a HA strategy is used as at this level outages will have a bigger impact against more users. All the architectures in this range have HA built in by design for this reason.
For users who still need to have HA for a lower number of users this can also be achieved with an [adjusted 3K architecture as detailed here](3k_users.md#supported-modifications-for-lower-user-counts-ha).
#### Do you need High Availability (HA)?
As mentioned above, achieving HA does come at a cost. The environment's required are sizable as each component needs to be multiplied, which comes with additional actual and maintenance costs.
For a lot of our customers with fewer than 3,000 users, we've found a backup strategy is sufficient and even preferable. While this does have a slower recovery time, it also means you have a much smaller architecture and less maintenance costs as a result.
In general then, we'd only recommend you employ HA in the following scenarios:
- When you have 3,000 or more users.
- When GitLab being down would critically impact your workflow.
#### Zero Downtime Upgrades
[Zero Downtime Upgrades](../../update/zero_downtime.md) are available for standard Reference Architecture environments with HA (Cloud Native Hybrid is not supported at this time). This allows for an environment to stay up during an upgrade, but the process is more involved as a result and has some limitations as detailed in the documentation.
When going through this process it's worth noting that there may still be brief moments of downtime when the HA mechanisms tale effect.
In most cases the downtime required for doing an upgrade in general shouldn't be substantial, so this is only recommended if it's a key requirement for you.
### Cloud Native Hybrid (Kubernetes HA)
As an additional layer of HA resilience you can deploy select components in Kubernetes, known as a Cloud Native Hybrid Reference Architecture.
Note that this is an alternative and more **advanced** setup compared to a standard Reference Architecture. Running services in Kubernetes is well known to be complex. **This setup is only recommended** if you have strong working knowledge and experience in Kubernetes.
### GitLab Geo (Cross Regional Distribution / Disaster Recovery)
With [GitLab Geo](../geo/index.md) you can have both distributed environments in different regions and a full Disaster Recovery (DR) setup in place. With this setup you would have 2 or more separate environments, with one being a primary that gets replicated to the others. In the rare event the primary site went down completely you could fail over to one of the other environments.
This is an **advanced and involved** setup and should only be undertaken if you have DR as a key requirement. Decisions then on how each environment are configured would also need to be taken, such as if each environment itself would be the full size and / or have HA.
### Decision Tree
Below you can find the above guidance in the form of a decision tree. It's recommended you read through the above guidance in full first before though.
```mermaid
%%{init: { 'theme': 'base' } }%%
graph TD
L1A(<b>What Reference Architecture should I use?</b>) --> L2A(More than 3000 users?)
L2A -->|No| L3A("<a href=#do-you-need-high-availability-ha>Do you need HA?</a><br>(or Zero-Downtime Upgrades)") --> |Yes| L4A><b>Recommendation</b><br><br>3K architecture with HA<br>including supported modifications]
L3A -->|No| L4B><b>Recommendation</b><br><br>Architecture closest to user<br>count with Backups]
L2A -->|Yes| L3B[Do you have experience with<br/>and want additional resilience<br/>with select components in Kubernetes?]
L3B -->|No| L4C><b>Recommendation</b><br><br>Architecture closest to user<br>count with HA]
L3B -->|Yes| L4D><b>Recommendation</b><br><br>Cloud Native Hybrid architecture<br>closest to user count]
L5A("<a href=#gitlab-geo-cross-regional-distribution-disaster-recovery>Do you need cross regional distribution or disaster recovery?"</a>) --> |Yes| L6A><b>Additional Recommendation</b><br><br> GitLab Geo]
L4A -.- L5A
L4B -.- L5A
L4C -.- L5A
L4D -.- L5A
classDef default fill:#FCA326
linkStyle default fill:none,stroke:#7759C2
```
## Recommended cloud providers and services
NOTE:
The following lists are non-exhaustive. Generally, other cloud providers not listed
here likely work with the same specs, but this hasn't been validated.
Additionally, when it comes to other cloud provider services not listed here,
it's advised to be cautious as each implementation can be notably different
and should be tested thoroughly before production use.
Through testing and real life usage, the Reference Architectures are validated and supported on the following cloud providers:
<table>
<thead>
<tr>
<th>Reference Architecture</th>
<th>GCP</th>
<th>AWS</th>
<th>Azure</th>
<th>Bare Metal</th>
</tr>
</thead>
<tbody>
<tr>
<td>Omnibus</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Cloud Native Hybrid</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Additionally, the following cloud provider services are validated and supported for use as part of the Reference Architectures:
<table>
<thead>
<tr>
<th>Cloud Service</th>
<th>GCP</th>
<th>AWS</th>
<th>Bare Metal</th>
</tr>
</thead>
<tbody>
<tr>
<td>Object Storage</td>
<td>&nbsp; <a href="https://cloud.google.com/storage" target="_blank">Cloud Storage</a></td>
<td>&nbsp; <a href="https://aws.amazon.com/s3/" target="_blank">S3</a></td>
<td>&nbsp; <a href="https://min.io/" target="_blank">MinIO</a></td>
</tr>
<tr>
<td>Database</td>
<td>&nbsp; <a href="https://cloud.google.com/sql" target="_blank" rel="noopener noreferrer">Cloud SQL</a></td>
<td>&nbsp; <a href="https://aws.amazon.com/rds/" target="_blank" rel="noopener noreferrer">RDS</a></td>
<td></td>
</tr>
<tr>
<td>Redis</td>
<td></td>
<td>&nbsp; <a href="https://aws.amazon.com/elasticache/" target="_blank" rel="noopener noreferrer">ElastiCache</a></td>
<td></td>
</tr>
</tbody>
</table>
The following specific cloud provider services have been found to have issues in terms of either functionality or performance. As such, they either have caveats that should be considered or are not recommended:
- [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details.
- [Azure Blob Storage](https://azure.microsoft.com/en-gb/services/storage/blobs/) has been found to have performance limits that can impact production use at certain times. For larger Reference Architectures the service may not be sufficient for production use and an alternative is recommended for use instead.
- [Azure Database for PostgreSQL Server](https://azure.microsoft.com/en-gb/services/postgresql/#overview) (Single / Flexible) is not recommended for use due to notable performance issues or missing functionality.
NOTE:
As a general rule we unfortunately don't recommend Azure Services at this time.
If required, we advise thorough testing is done at your intended scale
over a sustained period to validate if the service is suitable.
## Validation and test results
The [Quality Engineering team](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/)
@ -97,7 +236,7 @@ Network latency on the test environments between components on all Cloud Provide
We aim to have a "test smart" approach where architectures tested have a good range that can also apply to others. Testing focuses on 10k Omnibus on GCP as the testing has shown this is a good bellwether for the other architectures and cloud providers as well as Cloud Native Hybrids.
The Standard Reference Architectures are designed to be platform agnostic, with everything being run on VMs via [Omnibus GitLab](https://docs.gitlab.com/omnibus/). While testing occurs primarily on GCP, ad-hoc testing has shown that they perform similarly on equivalently specced hardware on other Cloud Providers or if run on premises (bare-metal).
The Standard Reference Architectures are designed to be platform-agnostic, with everything being run on VMs via [Omnibus GitLab](https://docs.gitlab.com/omnibus/). While testing occurs primarily on GCP, ad-hoc testing has shown that they perform similarly on equivalently specced hardware on other Cloud Providers or if run on premises (bare-metal).
Testing on these reference architectures is performed with the
[GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance)
@ -111,14 +250,14 @@ per 1,000 users:
- API: 20 RPS
- Web: 2 RPS
- Git (Pull): 2 RPS
- Git (Push): 0.4 RPS (rounded to nearest integer)
- Git (Push): 0.4 RPS (rounded to the nearest integer)
### How to interpret the results
NOTE:
Read our blog post on [how our QA team leverages GitLab performance testing tool](https://about.gitlab.com/blog/2020/02/18/how-were-building-up-performance-testing-of-gitlab/).
Testing is done publicly and all results are shared.
Testing is done publicly, and all results are shared.
The following table details the testing done against the reference architectures along with the frequency and results. Additional testing is continuously evaluated, and the table is updated accordingly.
@ -292,171 +431,6 @@ The following table details the cost to run the different reference architecture
</tr>
</table>
## Recommended cloud providers and services
NOTE:
The following lists are non exhaustive. Generally, other cloud providers not listed
here likely work with the same specs, but this hasn't been validated.
Additionally, when it comes to other cloud provider services not listed here,
it's advised to be cautious as each implementation can be notably different
and should be tested thoroughly before production use.
Through testing and real life usage, the Reference Architectures are validated and supported on the following cloud providers:
<table>
<thead>
<tr>
<th>Reference Architecture</th>
<th>GCP</th>
<th>AWS</th>
<th>Azure</th>
<th>Bare Metal</th>
</tr>
</thead>
<tbody>
<tr>
<td>Omnibus</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Cloud Native Hybrid</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
Additionally, the following cloud provider services are validated and supported for use as part of the Reference Architectures:
<table>
<thead>
<tr>
<th>Cloud Service</th>
<th>GCP</th>
<th>AWS</th>
<th>Bare Metal</th>
</tr>
</thead>
<tbody>
<tr>
<td>Object Storage</td>
<td>&nbsp; <a href="https://cloud.google.com/storage" target="_blank">Cloud Storage</a></td>
<td>&nbsp; <a href="https://aws.amazon.com/s3/" target="_blank">S3</a></td>
<td>&nbsp; <a href="https://min.io/" target="_blank">MinIO</a></td>
</tr>
<tr>
<td>Database</td>
<td>&nbsp; <a href="https://cloud.google.com/sql" target="_blank" rel="noopener noreferrer">Cloud SQL</a></td>
<td>&nbsp; <a href="https://aws.amazon.com/rds/" target="_blank" rel="noopener noreferrer">RDS</a></td>
<td></td>
</tr>
<tr>
<td>Redis</td>
<td></td>
<td>&nbsp; <a href="https://aws.amazon.com/elasticache/" target="_blank" rel="noopener noreferrer">ElastiCache</a></td>
<td></td>
</tr>
</tbody>
</table>
The following specific cloud provider services have been found to have issues in terms of either functionality or performance. As such, they either have caveats that should be considered or are not recommended:
- [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo.
- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details.
- [Azure Blob Storage](https://azure.microsoft.com/en-gb/services/storage/blobs/) has been found to have performance limits that can impact production use at certain times. For larger Reference Architectures the service may not be sufficient for production use and an alternative is recommended for use instead.
- [Azure Database for PostgreSQL Server](https://azure.microsoft.com/en-gb/services/postgresql/#overview) (Single / Flexible) is not recommended for use due to notable performance issues or missing functionality.
NOTE:
As a general rule we unfortunately don't recommend Azure Services at this time.
If required, we advise thorough testing is done at your intended scale
over a sustained period to validate if the service is suitable.
## Availability Components
GitLab comes with the following components for your use, listed from least to
most complex:
- [Automated backups](#automated-backups)
- [Traffic load balancer](#traffic-load-balancer)
- [Zero downtime updates](#zero-downtime-updates)
- [Automated database failover](#automated-database-failover)
- [Instance level replication with GitLab Geo](#instance-level-replication-with-gitlab-geo)
As you implement these components, begin with a single server and then do
backups. Only after completing the first server should you proceed to the next.
Also, not implementing extra servers for GitLab doesn't necessarily mean that you have
more downtime. Depending on your needs and experience level, single servers can
have more actual perceived uptime for your users.
### Automated backups
> - Level of complexity: **Low**
> - Required domain knowledge: PostgreSQL, GitLab configurations, Git
This solution is appropriate for many teams that have the default GitLab installation.
With automatic backups of the GitLab repositories, configuration, and the database,
this can be an optimal solution if you don't have strict requirements.
[Automated backups](../../raketasks/backup_gitlab.md#configuring-cron-to-make-daily-backups)
is the least complex to setup. This provides a point-in-time recovery of a predetermined schedule.
### Traffic load balancer **(PREMIUM SELF)**
> - Level of complexity: **Medium**
> - Required domain knowledge: HAProxy, shared storage, distributed systems
This requires separating out GitLab into multiple application nodes with an added
[load balancer](../load_balancer.md). The load balancer distributes traffic
across GitLab application nodes. Meanwhile, each application node connects to a
shared file server and database systems on the back end. This way, if one of the
application servers fails, the workflow is not interrupted.
[HAProxy](https://www.haproxy.org/) is recommended as the load balancer.
With this added component you have a number of advantages compared
to the default installation:
- Increase the number of users.
- Enable zero-downtime upgrades.
- Increase availability.
For more details on how to configure a traffic load balancer with GitLab, you can refer
to any of the [available reference architectures](#available-reference-architectures) with more than 1,000 users.
### Zero downtime updates **(PREMIUM SELF)**
> - Level of complexity: **Medium**
> - Required domain knowledge: PostgreSQL, HAProxy, shared storage, distributed systems
GitLab supports [zero-downtime upgrades](../../update/zero_downtime.md).
Single GitLab nodes can be updated with only a [few minutes of downtime](../../update/index.md#upgrade-based-on-installation-method).
To avoid this, we recommend to separate GitLab into several application nodes.
As long as at least one of each component is online and capable of handling the instance's usage load, your team's productivity is not interrupted during the update.
### Automated database failover **(PREMIUM SELF)**
> - Level of complexity: **High**
> - Required domain knowledge: PgBouncer, Patroni, shared storage, distributed systems
By adding automatic failover for database systems, you can enable higher uptime
with additional database nodes. This extends the default database with
cluster management and failover policies.
[PgBouncer in conjunction with Patroni](../postgresql/replication_and_failover.md)
is recommended.
### Instance level replication with GitLab Geo **(PREMIUM SELF)**
> - Level of complexity: **Very High**
> - Required domain knowledge: Storage replication
[GitLab Geo](../geo/index.md) allows you to replicate your GitLab
instance to other geographical locations as a read-only fully operational instance
that can also be promoted in case of disaster.
## Deviating from the suggested reference architectures
As a general guideline, the further away you move from the Reference Architectures,
@ -476,11 +450,3 @@ However, it is still an additional layer and may still add some support complexi
Other technologies, like [Docker swarm](https://docs.docker.com/engine/swarm/)
are not officially supported, but can be implemented at your own risk. In that
case, GitLab Support is not able to help you.
## Supported modifications for lower user count HA reference architectures
The reference architectures for user counts [3,000](3k_users.md) and up support High Availability (HA).
In the specific case you have the requirement to achieve HA but have a lower user count, select modifications to the [3,000 user](3k_users.md) architecture are supported.
For more details, [refer to this section in the architecture's documentation](3k_users.md#supported-modifications-for-lower-user-counts-ha).

View File

@ -370,8 +370,11 @@ access-service:
curlimages/curl:7.74.0 curl "http://tutum-wordpress"
```
For this solution to work, you must use
[the networking mode that creates a new network for each job](https://docs.gitlab.com/runner/executors/docker.html#create-a-network-for-each-job).
For this solution to work, you must:
- Use [the networking mode that creates a new network for each job](https://docs.gitlab.com/runner/executors/docker.html#create-a-network-for-each-job).
- [Not use the Docker executor with Docker socket binding](../docker/using_docker_build.md#use-the-docker-executor-with-docker-socket-binding).
If you must, then in the above example, instead of `host`, use the dynamic network name created for this job.
## How Docker integration works

View File

@ -358,6 +358,10 @@ analyzer to use the latest available schemas.
After the deprecation period for a schema version, the file is removed from GitLab. Reports that
declare removed versions are rejected, and an error message displays on the corresponding pipeline.
If a report uses a `PATCH` version that doesn't match any vendored schema version, it is validated against
the latest vendored `PATCH` version. For example, if a report version is 14.0.23 and the latest vendored
version is 14.0.6, the report is validated against version 14.0.6.
GitLab uses the
[`json_schemer`](https://www.rubydoc.info/gems/json_schemer) gem to perform validation.

View File

@ -755,30 +755,65 @@ We limit the artifacts that are saved and retrieved by jobs to the minimum in or
### Components caching
Some external components (currently only GitLab Workhorse) of GitLab need to be built from source as a preliminary step for running tests.
Some external components (GitLab Workhorse and frontend assets) of GitLab need to be built from source as a preliminary step for running tests.
In [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79766), we introduced a new `build-components` job that:
#### `cache-workhorse`
In [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79766), and then
[this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96297),
we introduced a new `cache-workhorse` job that:
- runs automatically for all GitLab.com `gitlab-org/gitlab` scheduled pipelines
- runs automatically for any `master` commit that touches the `workhorse/` folder
- is manual for GitLab.com's `gitlab-org`'s MRs
- is manual for GitLab.com's `gitlab-org`'s MRs that touches caching-related files
This job tries to download a generic package that contains GitLab Workhorse binaries needed in the GitLab test suite (under `tmp/tests/gitlab-workhorse`).
- If the package URL returns a 404:
1. It runs `scripts/setup-test-env`, so that the GitLab Workhorse binaries are built.
1. It then creates an archive which contains the binaries and upload it [as a generic package](https://gitlab.com/gitlab-org/gitlab/-/packages/).
- Otherwise, if the package already exists, it exit the job successfully.
- Otherwise, if the package already exists, it exits the job successfully.
We also changed the `setup-test-env` job to:
1. First download the GitLab Workhorse generic package build and uploaded by `build-components`.
1. First download the GitLab Workhorse generic package build and uploaded by `cache-workhorse`.
1. If the package is retrieved successfully, its content is placed in the right folder (for example, `tmp/tests/gitlab-workhorse`), preventing the building of the binaries when `scripts/setup-test-env` is run later on.
1. If the package URL returns a 404, the behavior doesn't change compared to the current one: the GitLab Workhorse binaries are built as part of `scripts/setup-test-env`.
NOTE:
The version of the package is the workhorse tree SHA (for example, `git rev-parse HEAD:workhorse`).
#### `cache-assets`
In [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96297),
we introduced three new `cache-assets:test`, `cache-assets:test as-if-foss`,
and `cache-assets:production` jobs that:
- never run unless `$CACHE_ASSETS_AS_PACKAGE == "true"`
- runs automatically for all GitLab.com `gitlab-org/gitlab` scheduled pipelines
- runs automatically for any `master` commit that touches the assets-related folders
- is manual for GitLab.com's `gitlab-org`'s MRs that touches caching-related files
This job tries to download a generic package that contains GitLab compiled assets
needed in the GitLab test suite (under `app/assets/javascripts/locale/**/app.js`,
`public/assets`, `tmp/cache/assets/sprockets/`, `tmp/cache/babel-loader/`,
and `tmp/cache/vue-loader/`).
- If the package URL returns a 404:
1. It runs `bin/rake gitlab:assets:compile_with_new_strategy`, so that the GitLab assets are compiled.
1. It then creates an archive which contains the assets and upload it [as a generic package](https://gitlab.com/gitlab-org/gitlab/-/packages/).
- Otherwise, if the package already exists, it exits the job successfully.
We also changed the `compile-test-assets`, `compile-test-assets as-if-foss`,
and `compile-production-assets` jobs to:
1. First download the GitLab assets generic package build and uploaded by `cache-assets:*`.
1. If the package is retrieved successfully, assets aren't compiled.
1. If the package URL returns a 404, the behavior doesn't change compared to the current one: the GitLab assets are compiled as part of `bin/rake gitlab:assets:compile_with_new_strategy`.
NOTE:
The version of the package is the assets folders hash sum.
### Pre-clone step
NOTE:

View File

@ -82,8 +82,7 @@ the tiers are no longer mentioned in GitLab documentation:
- Rake tasks:
- [Displaying GitLab license information](../administration/raketasks/maintenance.md#show-gitlab-license-information)
- Reference Architecture information:
- [Traffic load balancers](../administration/reference_architectures/index.md#traffic-load-balancer)
- [Zero downtime updates](../administration/reference_architectures/index.md#zero-downtime-updates)
- [Zero downtime upgrades](../administration/reference_architectures/index.md#zero-downtime-upgrades)
- Repositories:
- [Repository size limit](../user/admin_area/settings/account_and_limit_settings.md#repository-size-limit)
- Repository mirroring:

View File

@ -5,28 +5,37 @@ require 'fileutils'
module Tasks
module Gitlab
module Assets
FOSS_ASSET_FOLDERS = %w[app/assets fixtures/emojis vendor/assets/javascripts].freeze
FOSS_ASSET_FOLDERS = %w[app/assets fixtures/emojis vendor/assets].freeze
EE_ASSET_FOLDERS = %w[ee/app/assets].freeze
JH_ASSET_FOLDERS = %w[jh/app/assets].freeze
JS_ASSET_PATTERNS = %w[*.js config/**/*.js].freeze
JS_ASSET_FILES = %w[package.json yarn.lock].freeze
# In the new caching strategy, we check the assets hash sum *before* compiling
# the app/assets/javascripts/locale/**/app.js files. That means the hash sum
# must depend on locale/**/gitlab.po.
JS_ASSET_PATTERNS = %w[*.js config/**/*.js locale/**/gitlab.po].freeze
JS_ASSET_FILES = %w[
package.json
yarn.lock
babel.config.js
config/webpack.config.js
].freeze
EXCLUDE_PATTERNS = %w[
app/assets/javascripts/locale/**/app.js
].freeze
MASTER_SHA256_HASH_FILE = 'master-assets-hash.txt'
HEAD_SHA256_HASH_FILE = 'assets-hash.txt'
PUBLIC_ASSETS_WEBPACK_DIR = 'public/assets/webpack'
PUBLIC_ASSETS_DIR = 'public/assets'
def self.sha256_of_assets_impacting_webpack_compilation
def self.sha256_of_assets_impacting_compilation(verbose: true)
start_time = Time.now
asset_files = assets_impacting_webpack_compilation
puts "Generating the SHA256 hash for #{assets_impacting_webpack_compilation.size} Webpack-related assets..."
asset_files = assets_impacting_compilation
puts "Generating the SHA256 hash for #{asset_files.size} Webpack-related assets..." if verbose
asset_file_sha256s = asset_files.map do |asset_file|
Digest::SHA256.file(asset_file).hexdigest
end
assets_sha256 = asset_files.map { |asset_file| Digest::SHA256.file(asset_file).hexdigest }.join
Digest::SHA256.hexdigest(asset_file_sha256s.join).tap { |sha256| puts "=> SHA256 generated in #{Time.now - start_time}: #{sha256}" }
Digest::SHA256.hexdigest(assets_sha256).tap { |sha256| puts "=> SHA256 generated in #{Time.now - start_time}: #{sha256}" if verbose }
end
def self.assets_impacting_webpack_compilation
def self.assets_impacting_compilation
assets_folders = FOSS_ASSET_FOLDERS
assets_folders += EE_ASSET_FOLDERS if ::Gitlab.ee?
assets_folders += JH_ASSET_FOLDERS if ::Gitlab.jh?
@ -38,32 +47,35 @@ module Tasks
asset_files.concat(Dir.glob(["#{folder}/**/*.*"]))
end
asset_files
asset_files - Dir.glob(EXCLUDE_PATTERNS)
end
private_class_method :assets_impacting_webpack_compilation
private_class_method :assets_impacting_compilation
end
end
end
namespace :gitlab do
namespace :assets do
desc 'GitLab | Assets | Return the hash sum of all frontend assets'
task :hash_sum do
head_assets_sha256 = Tasks::Gitlab::Assets.sha256_of_assets_impacting_compilation(verbose: false)
puts head_assets_sha256
end
desc 'GitLab | Assets | Compile all frontend assets'
task :compile do
require_dependency 'gitlab/task_helpers'
%w[
yarn:check
gettext:po_to_json
rake:assets:precompile
gitlab:assets:compile_webpack_if_needed
gitlab:assets:compile_if_needed_with_old_strategy
gitlab:assets:fix_urls
gitlab:assets:check_page_bundle_mixins_css_for_sideeffects
].each(&::Gitlab::TaskHelpers.method(:invoke_and_time_task))
end
desc 'GitLab | Assets | Compile all Webpack assets'
task :compile_webpack_if_needed do
desc 'GitLab | Assets | Compile all assets'
task :compile_if_needed_with_old_strategy do
# The hash file is stored as assets-hash.txt in the cache, so we rename it before generating the one for HEAD.
FileUtils.mv(Tasks::Gitlab::Assets::HEAD_SHA256_HASH_FILE, Tasks::Gitlab::Assets::MASTER_SHA256_HASH_FILE, force: true)
master_assets_sha256 =
@ -73,17 +85,20 @@ namespace :gitlab do
'missing!'
end
head_assets_sha256 = Tasks::Gitlab::Assets.sha256_of_assets_impacting_webpack_compilation.tap do |sha256|
head_assets_sha256 = Tasks::Gitlab::Assets.sha256_of_assets_impacting_compilation.tap do |sha256|
File.write(Tasks::Gitlab::Assets::HEAD_SHA256_HASH_FILE, sha256)
end
puts "Webpack assets SHA256 for `master`: #{master_assets_sha256}"
puts "Webpack assets SHA256 for `HEAD`: #{head_assets_sha256}"
puts "Assets SHA256 for `master`: #{master_assets_sha256}"
puts "Assets SHA256 for `HEAD`: #{head_assets_sha256}"
public_assets_webpack_dir_exists = Dir.exist?(Tasks::Gitlab::Assets::PUBLIC_ASSETS_WEBPACK_DIR)
public_assets_dir_exists = Dir.exist?(Tasks::Gitlab::Assets::PUBLIC_ASSETS_DIR)
if head_assets_sha256 != master_assets_sha256 || !public_assets_webpack_dir_exists
FileUtils.rm_r(Tasks::Gitlab::Assets::PUBLIC_ASSETS_WEBPACK_DIR) if public_assets_webpack_dir_exists
if head_assets_sha256 != master_assets_sha256 || !public_assets_dir_exists
FileUtils.rm_r(Tasks::Gitlab::Assets::PUBLIC_ASSETS_DIR) if public_assets_dir_exists
Gitlab::TaskHelpers.invoke_and_time_task('gettext:po_to_json')
Gitlab::TaskHelpers.invoke_and_time_task('rake:assets:precompile')
log_path = ENV['WEBPACK_COMPILE_LOG_PATH']
@ -99,6 +114,31 @@ namespace :gitlab do
end
end
# With this new strategy, we don't have to run `gettext:po_to_json` prior to check the assets hash sum
desc 'GitLab | Assets | Compile all frontend assets'
task :compile_with_new_strategy do
require_dependency 'gitlab/task_helpers'
%w[
gitlab:assets:compile_if_needed_with_new_strategy
gitlab:assets:check_page_bundle_mixins_css_for_sideeffects
].each(&::Gitlab::TaskHelpers.method(:invoke_and_time_task))
end
desc 'GitLab | Assets | Compile all assets'
task :compile_if_needed_with_new_strategy do
unless Dir.exist?(Tasks::Gitlab::Assets::PUBLIC_ASSETS_DIR)
Gitlab::TaskHelpers.invoke_and_time_task('gettext:po_to_json')
Gitlab::TaskHelpers.invoke_and_time_task('rake:assets:precompile')
unless system('yarn webpack')
abort 'Error: Unable to compile webpack production bundle.'.color(:red)
end
Gitlab::TaskHelpers.invoke_and_time_task('gitlab:assets:fix_urls')
end
end
desc 'GitLab | Assets | Clean up old compiled frontend assets'
task clean: ['rake:assets:clean']

View File

@ -27399,6 +27399,9 @@ msgstr ""
msgid "Notify|You have been mentioned in merge request %{mr_link}"
msgstr ""
msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications."
msgstr ""
msgid "Notify|Your CSV import for project %{project_link} has been completed."
msgstr ""
@ -27647,6 +27650,9 @@ msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role."
msgstr ""
msgid "OnCallSchedules|Select participant"
msgstr ""

View File

@ -0,0 +1,150 @@
#!/usr/bin/env bash
set -euo pipefail
export CURL_TOKEN_HEADER="${CURL_TOKEN_HEADER:-"JOB-TOKEN"}"
export GITLAB_COM_CANONICAL_PROJECT_ID="278964" # https://gitlab.com/gitlab-org/gitlab
export JIHULAB_COM_CANONICAL_PROJECT_ID="13953" # https://jihulab.com/gitlab-cn/gitlab
export CANONICAL_PROJECT_ID="${GITLAB_COM_CANONICAL_PROJECT_ID}"
# By default, we only want to store/retrieve packages from GitLab.com...
export API_V4_URL="https://gitlab.com/api/v4"
# Unless we're in the JiHu project, which needs to use its own package registry
if [[ "${CI_SERVER_HOST}" = "jihulab.com" ]]; then
export API_V4_URL="${CI_API_V4_URL}"
export CANONICAL_PROJECT_ID="${JIHULAB_COM_CANONICAL_PROJECT_ID}"
fi
export API_PACKAGES_BASE_URL="${API_V4_URL}/projects/${CANONICAL_PROJECT_ID}/packages/generic"
export UPLOAD_TO_CURRENT_SERVER="false"
# We only want to upload artifacts to https://gitlab.com and https://jihulab.com instances
if [[ "${CI_SERVER_HOST}" = "gitlab.com" ]] || [[ "${CI_SERVER_HOST}" = "jihulab.com" ]]; then
export UPLOAD_TO_CURRENT_SERVER="true"
fi
export UPLOAD_PACKAGE_FLAG="false"
# And only if we're in a pipeline from the canonical project
if [[ "${UPLOAD_TO_CURRENT_SERVER}" = "true" ]] && [[ "${CI_PROJECT_ID}" = "${CANONICAL_PROJECT_ID}" ]]; then
export UPLOAD_PACKAGE_FLAG="true"
fi
# Workhorse constants
export GITLAB_WORKHORSE_BINARIES_LIST="gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata gitlab-workhorse"
export GITLAB_WORKHORSE_PACKAGE_FILES_LIST="${GITLAB_WORKHORSE_BINARIES_LIST} WORKHORSE_TREE"
export GITLAB_WORKHORSE_TREE=${GITLAB_WORKHORSE_TREE:-$(git rev-parse HEAD:workhorse)}
export GITLAB_WORKHORSE_PACKAGE="workhorse-${GITLAB_WORKHORSE_TREE}.tar.gz"
export GITLAB_WORKHORSE_PACKAGE_URL="${API_PACKAGES_BASE_URL}/${GITLAB_WORKHORSE_FOLDER}/${GITLAB_WORKHORSE_TREE}/${GITLAB_WORKHORSE_PACKAGE}"
# Assets constants
export GITLAB_ASSETS_PATHS_LIST="assets-hash.txt app/assets/javascripts/locale/**/app.js public/assets/ tmp/cache/assets/sprockets/ tmp/cache/babel-loader/ tmp/cache/vue-loader/"
export GITLAB_EDITION="ee"
if [[ "${FOSS_ONLY:-no}" = "1" ]] || [[ "${CI_PROJECT_NAME}" = "gitlab-foss" ]]; then
export GITLAB_EDITION="foss"
fi
export GITLAB_ASSETS_HASH="${GITLAB_ASSETS_HASH:-"NO_HASH"}"
export GITLAB_ASSETS_PACKAGE="assets-${NODE_ENV}-${GITLAB_EDITION}-${GITLAB_ASSETS_HASH}.tar.gz"
export GITLAB_ASSETS_PACKAGE_URL="${API_PACKAGES_BASE_URL}/assets/${NODE_ENV}-${GITLAB_EDITION}-${GITLAB_ASSETS_HASH}/${GITLAB_ASSETS_PACKAGE}"
# Generic helper functions
function archive_doesnt_exist() {
local package_url="${1}"
status=$(curl -I --silent --retry 3 --output /dev/null -w "%{http_code}" "${package_url}")
[[ "${status}" != "200" ]]
}
function create_package() {
local archive_filename="${1}"
local paths_to_archive="${2}"
local tar_working_folder="${3:-.}"
echoinfo "Running 'tar -czvf ${archive_filename} -C ${tar_working_folder} ${paths_to_archive}'"
tar -czf ${archive_filename} -C ${tar_working_folder} ${paths_to_archive}
du -h ${archive_filename}
}
function upload_package() {
local archive_filename="${1}"
local package_url="${2}"
local token_header="${CURL_TOKEN_HEADER}"
local token="${CI_JOB_TOKEN}"
if [[ "${UPLOAD_PACKAGE_FLAG}" = "false" ]]; then
echoerr "The archive ${archive_filename} isn't supposed to be uploaded for this instance (${CI_SERVER_HOST}) & project (${CI_PROJECT_PATH})!"
exit 1
fi
echoinfo "Uploading ${archive_filename} to ${package_url} ..."
curl --fail --silent --retry 3 --header "${token_header}: ${token}" --upload-file "${archive_filename}" "${package_url}"
}
function read_curl_package() {
local package_url="${1}"
local token_header="${CURL_TOKEN_HEADER}"
local token="${CI_JOB_TOKEN}"
echoinfo "Downloading from ${package_url} ..."
curl --fail --silent --retry 3 --header "${token_header}: ${token}" "${package_url}"
}
function extract_package() {
local tar_working_folder="${1:-.}"
mkdir -p "${tar_working_folder}"
echoinfo "Extracting archive to ${tar_working_folder}"
tar -xz -C ${tar_working_folder} < /dev/stdin
}
# Workhorse functions
function gitlab_workhorse_archive_doesnt_exist() {
archive_doesnt_exist "${GITLAB_WORKHORSE_PACKAGE_URL}"
}
function create_gitlab_workhorse_package() {
create_package "${GITLAB_WORKHORSE_PACKAGE}" "${GITLAB_WORKHORSE_FOLDER}" "${TMP_TEST_FOLDER}"
}
function upload_gitlab_workhorse_package() {
upload_package "${GITLAB_WORKHORSE_PACKAGE}" "${GITLAB_WORKHORSE_PACKAGE_URL}"
}
function download_and_extract_gitlab_workhorse_package() {
read_curl_package "${GITLAB_WORKHORSE_PACKAGE_URL}" | extract_package "${TMP_TEST_FOLDER}"
}
function select_gitlab_workhorse_essentials() {
local tmp_path="${CI_PROJECT_DIR}/tmp/${GITLAB_WORKHORSE_FOLDER}"
local original_gitlab_workhorse_path="${TMP_TEST_GITLAB_WORKHORSE_PATH}"
mkdir -p ${tmp_path}
cd ${original_gitlab_workhorse_path} && mv ${GITLAB_WORKHORSE_PACKAGE_FILES_LIST} ${tmp_path} && cd -
rm -rf ${original_gitlab_workhorse_path}
# Move the temp folder to its final destination
mv ${tmp_path} ${TMP_TEST_FOLDER}
}
# Assets functions
function gitlab_assets_archive_doesnt_exist() {
archive_doesnt_exist "${GITLAB_ASSETS_PACKAGE_URL}"
}
function download_and_extract_gitlab_assets() {
read_curl_package "${GITLAB_ASSETS_PACKAGE_URL}" | extract_package
}
function create_gitlab_assets_package() {
create_package "${GITLAB_ASSETS_PACKAGE}" "${GITLAB_ASSETS_PATHS_LIST}"
}
function upload_gitlab_assets_package() {
upload_package "${GITLAB_ASSETS_PACKAGE}" "${GITLAB_ASSETS_PACKAGE_URL}"
}

View File

@ -1,74 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
export CURL_TOKEN_HEADER="${CURL_TOKEN_HEADER:-"JOB-TOKEN"}"
export GITLAB_WORKHORSE_BINARIES_LIST="gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata gitlab-workhorse"
export GITLAB_WORKHORSE_PACKAGE_FILES_LIST="${GITLAB_WORKHORSE_BINARIES_LIST} WORKHORSE_TREE"
export GITLAB_WORKHORSE_TREE=${GITLAB_WORKHORSE_TREE:-$(git rev-parse HEAD:workhorse)}
export GITLAB_WORKHORSE_PACKAGE="workhorse-${GITLAB_WORKHORSE_TREE}.tar.gz"
export GITLAB_WORKHORSE_PACKAGE_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${GITLAB_WORKHORSE_FOLDER}/${GITLAB_WORKHORSE_TREE}/${GITLAB_WORKHORSE_PACKAGE}"
function gitlab_workhorse_archive_doesnt_exist() {
local package_url="${GITLAB_WORKHORSE_PACKAGE_URL}"
status=$(curl -I --silent --retry 3 --output /dev/null -w "%{http_code}" "${package_url}")
[[ "${status}" != "200" ]]
}
function create_gitlab_workhorse_package() {
local archive_filename="${GITLAB_WORKHORSE_PACKAGE}"
local folder_to_archive="${GITLAB_WORKHORSE_FOLDER}"
local workhorse_folder_path="${TMP_TEST_GITLAB_WORKHORSE_PATH}"
local tar_working_folder="${TMP_TEST_FOLDER}"
echoinfo "Running 'tar -czvf ${archive_filename} -C ${tar_working_folder} ${folder_to_archive}'"
tar -czvf ${archive_filename} -C ${tar_working_folder} ${folder_to_archive}
du -h ${archive_filename}
}
function extract_gitlab_workhorse_package() {
local tar_working_folder="${TMP_TEST_FOLDER}"
mkdir -p "${tar_working_folder}"
echoinfo "Extracting archive to ${tar_working_folder}"
tar -xzv -C ${tar_working_folder} < /dev/stdin
}
function upload_gitlab_workhorse_package() {
local archive_filename="${GITLAB_WORKHORSE_PACKAGE}"
local package_url="${GITLAB_WORKHORSE_PACKAGE_URL}"
local token_header="${CURL_TOKEN_HEADER}"
local token="${CI_JOB_TOKEN}"
echoinfo "Uploading ${archive_filename} to ${package_url} ..."
curl --fail --silent --retry 3 --header "${token_header}: ${token}" --upload-file "${archive_filename}" "${package_url}"
}
function read_curl_gitlab_workhorse_package() {
local package_url="${GITLAB_WORKHORSE_PACKAGE_URL}"
local token_header="${CURL_TOKEN_HEADER}"
local token="${CI_JOB_TOKEN}"
echoinfo "Downloading from ${package_url} ..."
curl --fail --silent --retry 3 --header "${token_header}: ${token}" "${package_url}"
}
function download_and_extract_gitlab_workhorse_package() {
read_curl_gitlab_workhorse_package | extract_gitlab_workhorse_package
}
function select_gitlab_workhorse_essentials() {
local tmp_path="${CI_PROJECT_DIR}/tmp/${GITLAB_WORKHORSE_FOLDER}"
local original_gitlab_workhorse_path="${TMP_TEST_GITLAB_WORKHORSE_PATH}"
mkdir -p ${tmp_path}
cd ${original_gitlab_workhorse_path} && mv ${GITLAB_WORKHORSE_PACKAGE_FILES_LIST} ${tmp_path} && cd -
rm -rf ${original_gitlab_workhorse_path}
# Move the temp folder to its final destination
mv ${tmp_path} ${TMP_TEST_FOLDER}
}

View File

@ -216,7 +216,7 @@ RSpec.describe UploadsController do
end
context 'for PDF files' do
let(:filename) { 'git-cheat-sheet.pdf' }
let(:filename) { 'sample.pdf' }
let(:expected_disposition) { 'inline;' }
let(:note) { create(:note, :with_pdf_attachment, project: project) }

View File

@ -184,7 +184,7 @@ FactoryBot.define do
end
trait :with_pdf_attachment do
attachment { fixture_file_upload("spec/fixtures/git-cheat-sheet.pdf", "application/pdf") }
attachment { fixture_file_upload("spec/fixtures/sample.pdf", "application/pdf") }
end
trait :confidential do

View File

@ -7,7 +7,7 @@ RSpec.describe Packages::Nuget::PackageFinder do
let_it_be(:subgroup) { create(:group, parent: group) }
let_it_be(:project) { create(:project, namespace: subgroup) }
let_it_be_with_refind(:package1) { create(:nuget_package, project: project) }
let_it_be(:package2) { create(:nuget_package, name: package1.name, version: '2.0.0', project: project) }
let_it_be(:package2) { create(:nuget_package, name: package1.name, version: '2.0.0-ABC', project: project) }
let_it_be(:package3) { create(:nuget_package, name: 'Another.Dummy.Package', project: project) }
let_it_be(:other_package_1) { create(:nuget_package, name: package1.name, version: package1.version) }
let_it_be(:other_package_2) { create(:nuget_package, name: package1.name, version: package2.version) }
@ -43,7 +43,13 @@ RSpec.describe Packages::Nuget::PackageFinder do
end
context 'with valid version' do
let(:package_version) { '2.0.0' }
let(:package_version) { '2.0.0-ABC' }
it { is_expected.to match_array([package2]) }
end
context 'with varying case version' do
let(:package_version) { '2.0.0-abC' }
it { is_expected.to match_array([package2]) }
end

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:35967a21e5d856eaea89d2e5dd55a5e3b5f4e1e4efe3b000ef6d60b31600f1d2
size 7352215

13
spec/fixtures/sample.pdf vendored Normal file
View File

@ -0,0 +1,13 @@
%PDF-1.3
%<25><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
4 0 obj
<< /Length 5 0 R /Filter /FlateDecode >>
stream
xe<><65><0E>0 <0C><><>@<1A><><EFBFBD>
ba<EFBFBD>d<EFBFBD>1U<31>V<EFBFBD><10>_8<5F><38>n<EFBFBD>e}<7D><> fXU<58>`\F<>d2<64><32><EFBFBD><EFBFBD><07>S%,<15>Q]<5D>;XC<58>9<07>+Qy<51><79><EFBFBD>k>a2>31B4<42>;<3B><><EFBFBD>d)!Md<4D>M<4D>-<2D>B<EFBFBD><42>F<EFBFBD><46><10>N<EFBFBD>[v<05><>~<7E><>E<>5<EFBFBD><35><EFBFBD>^<08>Z_<03><> ΢<1F>o<EFBFBD>l.<2E>
endstream
endobj
5 0 obj
155
endobj
2 0 obj

View File

@ -29,12 +29,14 @@ import CacheYaml from './yaml_tests/positive_tests/cache.yml';
import FilterYaml from './yaml_tests/positive_tests/filter.yml';
import IncludeYaml from './yaml_tests/positive_tests/include.yml';
import RulesYaml from './yaml_tests/positive_tests/rules.yml';
import VariablesYaml from './yaml_tests/positive_tests/variables.yml';
// YAML NEGATIVE TEST
import ArtifactsNegativeYaml from './yaml_tests/negative_tests/artifacts.yml';
import CacheNegativeYaml from './yaml_tests/negative_tests/cache.yml';
import IncludeNegativeYaml from './yaml_tests/negative_tests/include.yml';
import RulesNegativeYaml from './yaml_tests/negative_tests/rules.yml';
import VariablesNegativeYaml from './yaml_tests/negative_tests/variables.yml';
const ajv = new Ajv({
strictTypes: false,
@ -67,6 +69,7 @@ describe('positive tests', () => {
FilterYaml,
IncludeYaml,
RulesYaml,
VariablesYaml,
}),
)('schema validates %s', (_, input) => {
expect(input).toValidateJsonSchema(schema);
@ -90,6 +93,7 @@ describe('negative tests', () => {
CacheNegativeYaml,
IncludeNegativeYaml,
RulesNegativeYaml,
VariablesNegativeYaml,
}),
)('schema validates %s', (_, input) => {
expect(input).not.toValidateJsonSchema(schema);

View File

@ -0,0 +1,5 @@
# invalid variable (unknown keyword is used)
variables:
FOO:
value: BAR
desc: A single value variable

View File

@ -0,0 +1,8 @@
variables:
TEST_VAR: "hello world!"
123456: "123456"
FOO:
value: "BAR"
description: "A single value variable"
DEPLOY_ENVIRONMENT:
description: "A multi-value variable"

View File

@ -7,7 +7,7 @@ import Vuex from 'vuex';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import batchComments from '~/batch_comments/stores/modules/batch_comments';
import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests';
import createFlash from '~/flash';
import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import CommentForm from '~/notes/components/comment_form.vue';
import CommentTypeDropdown from '~/notes/components/comment_type_dropdown.vue';
@ -490,7 +490,7 @@ describe('issue_comment_form component', () => {
await nextTick();
await nextTick();
expect(createFlash).toHaveBeenCalledWith({
expect(createAlert).toHaveBeenCalledWith({
message: `Something went wrong while closing the ${type}. Please try again later.`,
});
});
@ -526,7 +526,7 @@ describe('issue_comment_form component', () => {
await nextTick();
await nextTick();
expect(createFlash).toHaveBeenCalledWith({
expect(createAlert).toHaveBeenCalledWith({
message: `Something went wrong while reopening the ${type}. Please try again later.`,
});
});

View File

@ -2,7 +2,7 @@ import { GlButton, GlLink, GlFormGroup, GlFormInput, GlFormSelect } from '@gitla
import { mount, shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { TEST_HOST } from 'helpers/test_constants';
import createFlash from '~/flash';
import { createAlert } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import { timezones } from '~/monitoring/format_date';
@ -52,7 +52,7 @@ describe('operation settings external dashboard component', () => {
}
axios.patch.mockReset();
refreshCurrentPage.mockReset();
createFlash.mockReset();
createAlert.mockReset();
});
it('renders header text', () => {
@ -208,7 +208,7 @@ describe('operation settings external dashboard component', () => {
await nextTick();
await jest.runAllTicks();
expect(createFlash).toHaveBeenCalledWith({
expect(createAlert).toHaveBeenCalledWith({
message: `There was an error saving your changes. ${message}`,
});
});

View File

@ -70,7 +70,7 @@ RSpec.describe Gitlab::GithubImport::MarkdownText do
let(:doc_extension) { described_class::DOC_TYPES.sample }
let(:doc_attachment) do
"[some-doc](https://github.com/nickname/public-test-repo/"\
"files/9020437/git-cheat-sheet.#{doc_extension})"
"files/9020437/sample.#{doc_extension})"
end
let(:text) do

View File

@ -1839,6 +1839,12 @@ RSpec.describe Note do
let(:note) { create(:note, :system, :on_issue, note: original_note_body) }
it { is_expected.to eq(expected_text_replacement) }
context 'context when note and cache are null (happens in bulk insert)' do
let(:note) { build(:note, :system, :on_issue, note: nil, note_html: nil).tap { |note| note.save!(validate: false) } }
it { is_expected.to be_in([nil, '']) }
end
end
end
end
@ -1868,7 +1874,7 @@ RSpec.describe Note do
let(:expected_text_replacement) { '<p data-sourcepos="1:1-1:48" dir="auto">marked the checklist item <strong>task 1</strong> as completed</p>' }
before do
note.update_columns(note_html: unchanged_note_body)
note.update_columns(note_html: unchanged_note_body) unless note.note.nil?
end
end
@ -1878,7 +1884,7 @@ RSpec.describe Note do
let(:expected_text_replacement) { '<p data-sourcepos="1:1-1:48" dir="auto">marked the checklist item <strong>task 1</strong> as incomplete</p>' }
before do
note.update_columns(note_html: unchanged_note_body)
note.update_columns(note_html: unchanged_note_body) unless note.note.nil?
end
end
end

View File

@ -904,6 +904,14 @@ RSpec.describe Packages::Package, type: :model do
it { is_expected.to match_array([pypi_package]) }
end
describe '.with_case_insensitive_version' do
let_it_be(:nuget_package) { create(:nuget_package, version: '1.0.0-ABC') }
subject { described_class.with_case_insensitive_version('1.0.0-abC') }
it { is_expected.to match_array([nuget_package]) }
end
context 'status scopes' do
let_it_be(:default_package) { create(:maven_package, :default) }
let_it_be(:hidden_package) { create(:maven_package, :hidden) }

View File

@ -52,28 +52,12 @@ RSpec.describe Ci::PipelineArtifacts::CoverageReportService do
it_behaves_like 'creating or updating a pipeline coverage report'
context 'when ci_update_unlocked_pipeline_artifacts feature flag is enabled' do
it "artifact has pipeline's locked status" do
subject
it "artifact has pipeline's locked status" do
subject
artifact = Ci::PipelineArtifact.first
artifact = Ci::PipelineArtifact.first
expect(artifact.locked).to eq(pipeline.locked)
end
end
context 'when ci_update_unlocked_pipeline_artifacts is disabled' do
before do
stub_feature_flags(ci_update_unlocked_pipeline_artifacts: false)
end
it 'artifact has unknown locked status' do
subject
artifact = Ci::PipelineArtifact.first
expect(artifact.locked).to eq('unknown')
end
expect(artifact.locked).to eq(pipeline.locked)
end
end

View File

@ -51,28 +51,12 @@ RSpec.describe ::Ci::PipelineArtifacts::CreateCodeQualityMrDiffReportService do
end
end
context 'when ci_update_unlocked_pipeline_artifacts feature flag is enabled' do
it "artifact has pipeline's locked status" do
subject
it "artifact has pipeline's locked status" do
subject
artifact = Ci::PipelineArtifact.first
artifact = Ci::PipelineArtifact.first
expect(artifact.locked).to eq(head_pipeline.locked)
end
end
context 'when ci_update_unlocked_pipeline_artifacts is disabled' do
before do
stub_feature_flags(ci_update_unlocked_pipeline_artifacts: false)
end
it 'artifact has unknown locked status' do
subject
artifact = Ci::PipelineArtifact.first
expect(artifact.locked).to eq('unknown')
end
expect(artifact.locked).to eq(head_pipeline.locked)
end
it 'does not persist the same artifact twice' do

View File

@ -5,15 +5,11 @@ require 'spec_helper'
RSpec.describe Ci::UnlockArtifactsService do
using RSpec::Parameterized::TableSyntax
where(:tag, :ci_update_unlocked_job_artifacts, :ci_update_unlocked_pipeline_artifacts) do
false | false | false
false | true | false
true | false | false
true | true | false
false | false | true
false | true | true
true | false | true
true | true | true
where(:tag, :ci_update_unlocked_job_artifacts) do
false | false
false | true
true | false
true | true
end
with_them do
@ -35,8 +31,7 @@ RSpec.describe Ci::UnlockArtifactsService do
before do
stub_const("#{described_class}::BATCH_SIZE", 1)
stub_feature_flags(ci_update_unlocked_job_artifacts: ci_update_unlocked_job_artifacts,
ci_update_unlocked_pipeline_artifacts: ci_update_unlocked_pipeline_artifacts)
stub_feature_flags(ci_update_unlocked_job_artifacts: ci_update_unlocked_job_artifacts)
end
describe '#execute' do
@ -80,7 +75,7 @@ RSpec.describe Ci::UnlockArtifactsService do
end
it 'unlocks pipeline artifact records' do
if ci_update_unlocked_job_artifacts && ci_update_unlocked_pipeline_artifacts
if ci_update_unlocked_job_artifacts
expect { execute }.to change { ::Ci::PipelineArtifact.artifact_unlocked.count }.from(0).to(1)
else
expect { execute }.not_to change { ::Ci::PipelineArtifact.artifact_unlocked.count }
@ -122,7 +117,7 @@ RSpec.describe Ci::UnlockArtifactsService do
end
it 'unlocks pipeline artifact records' do
if ci_update_unlocked_job_artifacts && ci_update_unlocked_pipeline_artifacts
if ci_update_unlocked_job_artifacts
expect { execute }.to change { ::Ci::PipelineArtifact.artifact_unlocked.count }.from(0).to(1)
else
expect { execute }.not_to change { ::Ci::PipelineArtifact.artifact_unlocked.count }

View File

@ -288,7 +288,7 @@ RSpec.shared_examples 'wiki controller actions' do
context 'when page is a file' do
include WikiHelpers
where(:file_name) { ['dk.png', 'unsanitized.svg', 'git-cheat-sheet.pdf'] }
where(:file_name) { ['dk.png', 'unsanitized.svg', 'sample.pdf'] }
with_them do
let(:id) { upload_file_to_wiki(wiki, user, file_name) }

View File

@ -77,9 +77,9 @@ RSpec.shared_examples 'it uploads and commits a new pdf file' do |drop: false|
end
if drop
find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'git-cheat-sheet.pdf'))
find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'sample.pdf'))
else
attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'git-cheat-sheet.pdf'), make_visible: true)
attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'sample.pdf'), make_visible: true)
end
page.within('#modal-upload-blob') do
@ -90,7 +90,7 @@ RSpec.shared_examples 'it uploads and commits a new pdf file' do |drop: false|
wait_for_all_requests
visit(project_blob_path(project, 'upload_image/git-cheat-sheet.pdf'))
visit(project_blob_path(project, 'upload_image/sample.pdf'))
expect(page).to have_css('.js-pdf-viewer')
end

View File

@ -6,7 +6,7 @@ require (
github.com/Azure/azure-storage-blob-go v0.14.0
github.com/BurntSushi/toml v1.2.0
github.com/FZambia/sentinel v1.1.1
github.com/alecthomas/chroma/v2 v2.2.0
github.com/alecthomas/chroma/v2 v2.3.0
github.com/aws/aws-sdk-go v1.43.31
github.com/disintegration/imaging v1.6.2
github.com/getsentry/raven-go v0.2.0

View File

@ -156,10 +156,10 @@ github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrU
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY=
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae h1:zzGwJfFlFGD94CyyYwCJeSuD32Gj9GTaSi5y9hoVzdY=
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/alecthomas/chroma/v2 v2.3.0 h1:83xfxrnjv8eK+Cf8qZDzNo3PPF9IbTWHs7z28GY6D0U=
github.com/alecthomas/chroma/v2 v2.3.0/go.mod h1:mZxeWZlxP2Dy+/8cBob2PYd8O2DwNAzave5AY7A2eQw=
github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=