Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
1403e9bc45
commit
3538972a0a
|
@ -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
|
||||
|
|
|
@ -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"
|
|
@ -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"]
|
||||
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -1 +1 @@
|
|||
5ee7c55528f5833aec37ba4a6bfb2b4c3f64dc80
|
||||
2ff0039f15ef06063925ff6c0406f6e092ad2435
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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],
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -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'),
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -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.'),
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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.'),
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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.'),
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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}`,
|
||||
});
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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.')
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'}"
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
·
|
||||
= commit.short_id
|
||||
|
|
|
@ -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
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
03accc241b8955f0ccfa3b40168e9f194360704d8937cd531683191b8fe4f8c8
|
|
@ -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);
|
||||
|
|
|
@ -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 |
|
||||
|------------------------------------------|-------|-------------------------|------------------|----------------|-----------|
|
||||
|
|
|
@ -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 |
|
||||
|--------------|-------------------------|----------------|--------------|----------|
|
||||
|
|
|
@ -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 |
|
||||
|------------------------------------------|-------|-------------------------|------------------|--------------|-----------|
|
||||
|
|
|
@ -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 |
|
||||
|----------------------------|-------|------------------------|-----------------|--------------|----------|
|
||||
|
|
|
@ -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 |
|
||||
|-------------------------------------------|-------|-----------------------|-----------------|--------------|----------|
|
||||
|
|
|
@ -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 |
|
||||
|------------------------------------------|-------|-------------------------|------------------|---------------|-----------|
|
||||
|
|
|
@ -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 |
|
@ -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.
|
||||
|
||||

|
||||
<!-- 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>✅ <a href="https://cloud.google.com/storage" target="_blank">Cloud Storage</a></td>
|
||||
<td>✅ <a href="https://aws.amazon.com/s3/" target="_blank">S3</a></td>
|
||||
<td>✅ <a href="https://min.io/" target="_blank">MinIO</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Database</td>
|
||||
<td>✅ <a href="https://cloud.google.com/sql" target="_blank" rel="noopener noreferrer">Cloud SQL</a></td>
|
||||
<td>✅ <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>✅ <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>✅ <a href="https://cloud.google.com/storage" target="_blank">Cloud Storage</a></td>
|
||||
<td>✅ <a href="https://aws.amazon.com/s3/" target="_blank">S3</a></td>
|
||||
<td>✅ <a href="https://min.io/" target="_blank">MinIO</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Database</td>
|
||||
<td>✅ <a href="https://cloud.google.com/sql" target="_blank" rel="noopener noreferrer">Cloud SQL</a></td>
|
||||
<td>✅ <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>✅ <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).
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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']
|
||||
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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}"
|
||||
}
|
|
@ -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}
|
||||
}
|
|
@ -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) }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:35967a21e5d856eaea89d2e5dd55a5e3b5f4e1e4efe3b000ef6d60b31600f1d2
|
||||
size 7352215
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
# invalid variable (unknown keyword is used)
|
||||
variables:
|
||||
FOO:
|
||||
value: BAR
|
||||
desc: A single value variable
|
|
@ -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"
|
|
@ -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.`,
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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}`,
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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=
|
||||
|
|
Loading…
Reference in New Issue