Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml7
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml14
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml16
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml51
-rw-r--r--.gitlab/ci/setup.gitlab-ci.yml14
-rw-r--r--.gitlab/ci/test-metadata.gitlab-ci.yml14
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock6
-rw-r--r--app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue9
-rw-r--r--app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue6
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue5
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue22
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/constants.js27
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue5
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_url.vue3
-rw-r--r--app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue4
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue6
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue4
-rw-r--r--app/assets/javascripts/serverless/components/area.vue15
-rw-r--r--app/assets/javascripts/serverless/components/function_details.vue4
-rw-r--r--app/assets/javascripts/serverless/components/functions.vue47
-rw-r--r--app/controllers/groups_controller.rb3
-rw-r--r--app/controllers/projects/branches_controller.rb16
-rw-r--r--app/controllers/projects/issues_controller.rb1
-rw-r--r--app/mailers/emails/notes.rb4
-rw-r--r--app/models/application_setting.rb5
-rw-r--r--app/services/merge_requests/create_from_issue_service.rb36
-rw-r--r--app/services/system_note_service.rb7
-rw-r--r--app/views/notify/new_merge_request_email.text.erb2
-rw-r--r--changelogs/unreleased/44106-include-subgroups-in-group-activity.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-63910.yml5
-rw-r--r--config/initializers/6_validations.rb21
-rw-r--r--lib/banzai/filter/relative_link_filter.rb6
-rw-r--r--locale/gitlab.pot48
-rw-r--r--qa/qa/service/shellout.rb2
-rw-r--r--spec/controllers/groups_controller_spec.rb7
-rw-r--r--spec/controllers/projects/branches_controller_spec.rb71
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb44
-rw-r--r--spec/helpers/markup_helper_spec.rb37
-rw-r--r--spec/initializers/6_validations_spec.rb20
-rw-r--r--spec/mailers/notify_spec.rb14
-rw-r--r--spec/services/merge_requests/create_from_issue_service_spec.rb205
-rw-r--r--spec/services/system_note_service_spec.rb32
-rw-r--r--spec/support/helpers/email_helpers.rb15
-rw-r--r--spec/tasks/migrate/schema_check_rake_spec.rb12
45 files changed, 600 insertions, 299 deletions
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index 4747e51f776..d7f8d70699b 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -12,7 +12,9 @@
# Trigger a manual docs build in gitlab-docs only on non docs-only branches.
# Useful to preview the docs changes live.
review-docs-deploy-manual:
- <<: *review-docs
+ extends:
+ - .review-docs
+ - .no-docs-and-no-qa
stage: build
script:
- gem install gitlab --no-document
@@ -21,9 +23,6 @@ review-docs-deploy-manual:
only:
- branches@gitlab-org/gitlab-ce
- branches@gitlab-org/gitlab-ee
- except:
- - /(^docs[\/-].*|.*-docs$)/
- - /(^qa[\/-].*|.*-qa$)/
# Always trigger a docs build in gitlab-docs only on docs-only branches.
# Useful to preview the docs changes live.
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index cd6953a6ac2..8314c067d7a 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -70,9 +70,10 @@ gitlab:assets:compile pull-cache:
cache:
policy: pull
except:
- - master@gitlab-org/gitlab-ce
- - master@gitlab-org/gitlab-ee
- - /(^docs[\/-].*|.*-docs$)/
+ refs:
+ - master@gitlab-org/gitlab-ce
+ - master@gitlab-org/gitlab-ee
+ - /(^docs[\/-].*|.*-docs$)/
.compile-assets-metadata:
extends: .dedicated-runner
@@ -107,9 +108,10 @@ compile-assets pull-cache:
cache:
policy: pull
except:
- - master@gitlab-org/gitlab-ce
- - master@gitlab-org/gitlab-ee
- - /(^docs[\/-].*|.*-docs$)/
+ refs:
+ - master@gitlab-org/gitlab-ce
+ - master@gitlab-org/gitlab-ee
+ - /(^docs[\/-].*|.*-docs$)/
gitlab:ui:visual:
extends: .dedicated-runner
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index eb50f08c1a7..4da7f404767 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -30,7 +30,14 @@
.no-docs:
except:
- - /(^docs[\/-].*|.*-docs$)/
+ refs:
+ - /(^docs[\/-].*|.*-docs$)/
+
+.no-docs-and-no-qa:
+ except:
+ refs:
+ - /(^docs[\/-].*|.*-docs$)/
+ - /(^qa[\/-].*|.*-qa$)/
.dedicated-no-docs-pull-cache-job:
extends:
@@ -38,10 +45,9 @@
- .no-docs
.dedicated-no-docs-and-no-qa-pull-cache-job:
- extends: .dedicated-pull-cache-job
- except:
- - /(^docs[\/-].*|.*-docs$)/
- - /(^qa[\/-].*|.*-qa$)/
+ extends:
+ - .dedicated-pull-cache-job
+ - .no-docs-and-no-qa
# Jobs that do not need a DB
.dedicated-no-docs-no-db-pull-cache-job:
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 9dcc9479cca..009c18310e4 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -20,8 +20,9 @@
- master@gitlab/gitlab-ee
.gitlab-setup: &gitlab-setup
- extends: .dedicated-no-docs-and-no-qa-pull-cache-job
- <<: *use-pg
+ extends:
+ - .dedicated-no-docs-and-no-qa-pull-cache-job
+ - .use-pg
variables:
SETUP_DB: "false"
script:
@@ -43,7 +44,9 @@
- bundle exec rake $CI_JOB_NAME
.rspec-metadata: &rspec-metadata
- extends: .dedicated-pull-cache-job
+ extends:
+ - .dedicated-pull-cache-job
+ - .no-docs-and-no-qa
stage: test
script:
- JOB_NAME=( $CI_JOB_NAME )
@@ -76,9 +79,6 @@
- tmp/capybara/
reports:
junit: junit_rspec.xml
- except:
- - /(^docs[\/-].*|.*-docs$)/
- - /(^qa[\/-].*|.*-qa$)/
.rspec-metadata-pg: &rspec-metadata-pg
<<: *rspec-metadata
@@ -122,8 +122,10 @@
- setup-test-env
setup-test-env:
- extends: .dedicated-runner-default-cache
- <<: *use-pg
+ extends:
+ - .dedicated-runner-default-cache
+ - .no-docs
+ - .use-pg
stage: prepare
script:
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
@@ -134,8 +136,6 @@ setup-test-env:
- tmp/tests
- config/secrets.yml
- vendor/gitaly-ruby
- except:
- - /(^docs[\/-].*|.*-docs$)/
rspec unit pg:
<<: *rspec-metadata-pg
@@ -200,11 +200,12 @@ static-analysis:
downtime_check:
<<: *rake-exec
except:
- - master
- - tags
- - /^[\d-]+-stable(-ee)?$/
- - /(^docs[\/-].*|.*-docs$)/
- - /(^qa[\/-].*|.*-qa$)/
+ refs:
+ - master
+ - tags
+ - /^[\d-]+-stable(-ee)?$/
+ - /(^docs[\/-].*|.*-docs$)/
+ - /(^qa[\/-].*|.*-qa$)/
dependencies:
- setup-test-env
@@ -212,12 +213,13 @@ ee_compat_check:
<<: *rake-exec
dependencies: []
except:
- - master
- - tags
- - /[\d-]+-stable(-ee)?/
- - /^security-/
- - branches@gitlab-org/gitlab-ee
- - branches@gitlab/gitlab-ee
+ refs:
+ - master
+ - tags
+ - /[\d-]+-stable(-ee)?/
+ - /^security-/
+ - branches@gitlab-org/gitlab-ee
+ - branches@gitlab/gitlab-ee
retry: 0
artifacts:
name: "${CI_JOB_NAME}_${CI_COMIT_REF_NAME}_${CI_COMMIT_SHA}"
@@ -261,7 +263,9 @@ gitlab:setup-pg:
coverage:
# Don't include dedicated-no-docs-no-db-pull-cache-job here since we need to
# download artifacts from all the rspec jobs instead of from setup-test-env only
- extends: .dedicated-runner-default-cache
+ extends:
+ - .dedicated-runner-default-cache
+ - .no-docs-and-no-qa
cache:
policy: pull
variables:
@@ -276,6 +280,3 @@ coverage:
paths:
- coverage/index.html
- coverage/assets/
- except:
- - /(^docs[\/-].*|.*-docs$)/
- - /(^qa[\/-].*|.*-qa$)/
diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml
index debc90a1cb0..c1fc3a893ca 100644
--- a/.gitlab/ci/setup.gitlab-ci.yml
+++ b/.gitlab/ci/setup.gitlab-ci.yml
@@ -15,7 +15,9 @@ cache gems:
- setup-test-env
gitlab_git_test:
- extends: .dedicated-runner
+ extends:
+ - .dedicated-runner
+ - .no-docs-and-no-qa
variables:
SETUP_DB: "false"
before_script: []
@@ -23,12 +25,11 @@ gitlab_git_test:
cache: {}
script:
- spec/support/prepare-gitlab-git-test-for-commit --check-for-changes
- except:
- - /(^docs[\/-].*|.*-docs$)/
- - /(^qa[\/-].*|.*-qa$)/
no_ee_check:
- extends: .dedicated-runner
+ extends:
+ - .dedicated-runner
+ - .no-docs-and-no-qa
variables:
SETUP_DB: "false"
before_script: []
@@ -38,6 +39,3 @@ no_ee_check:
- scripts/no-ee-check
only:
- /.+/@gitlab-org/gitlab-ce
- except:
- - /(^docs[\/-].*|.*-docs$)/
- - /(^qa[\/-].*|.*-qa$)/
diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml
index c51f825f831..2454ea85652 100644
--- a/.gitlab/ci/test-metadata.gitlab-ci.yml
+++ b/.gitlab/ci/test-metadata.gitlab-ci.yml
@@ -12,7 +12,9 @@
- rspec_profiling/
retrieve-tests-metadata:
- <<: *tests-metadata-state
+ extends:
+ - .tests-metadata-state
+ - .no-docs-and-no-qa
stage: prepare
cache:
key: tests_metadata
@@ -25,9 +27,6 @@ retrieve-tests-metadata:
- mkdir -p rspec_profiling/
- wget -O $FLAKY_RSPEC_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$FLAKY_RSPEC_SUITE_REPORT_PATH || rm $FLAKY_RSPEC_SUITE_REPORT_PATH
- '[[ -f $FLAKY_RSPEC_SUITE_REPORT_PATH ]] || echo "{}" > ${FLAKY_RSPEC_SUITE_REPORT_PATH}'
- except:
- - /(^docs[\/-].*|.*-docs$)/
- - /(^qa[\/-].*|.*-qa$)/
update-tests-metadata:
<<: *tests-metadata-state
@@ -69,9 +68,10 @@ flaky-examples-check:
only:
- branches
except:
- - master
- - /(^docs[\/-].*|.*-docs$)/
- - /(^qa[\/-].*|.*-qa$)/
+ refs:
+ - master
+ - /(^docs[\/-].*|.*-docs$)/
+ - /(^qa[\/-].*|.*-qa$)/
artifacts:
expire_in: 30d
paths:
diff --git a/Gemfile b/Gemfile
index 5caae0c2ca9..1264d75eac6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -11,7 +11,7 @@ gem 'responders', '~> 2.0'
gem 'sprockets', '~> 3.7.0'
# Default values for AR models
-gem 'gitlab-default_value_for', '~> 3.1.1', require: 'default_value_for'
+gem 'default_value_for', '~> 3.2.0'
# Supported DBs
gem 'mysql2', '~> 0.4.10', group: :mysql
diff --git a/Gemfile.lock b/Gemfile.lock
index fd366ac16b0..5b648d43137 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -163,6 +163,8 @@ GEM
html-pipeline
declarative (0.0.10)
declarative-option (0.1.0)
+ default_value_for (3.2.0)
+ activerecord (>= 3.2.0, < 6.0)
derailed_benchmarks (1.3.5)
benchmark-ips (~> 2)
get_process_mem (~> 0)
@@ -304,8 +306,6 @@ GEM
gitaly-proto (1.32.0)
grpc (~> 1.0)
github-markup (1.7.0)
- gitlab-default_value_for (3.1.1)
- activerecord (>= 3.2.0, < 6.0)
gitlab-labkit (0.3.0)
actionpack (~> 5)
activesupport (~> 5)
@@ -1056,6 +1056,7 @@ DEPENDENCIES
creole (~> 0.5.0)
database_cleaner (~> 1.7.0)
deckar01-task_list (= 2.2.0)
+ default_value_for (~> 3.2.0)
derailed_benchmarks
device_detector
devise (~> 4.6)
@@ -1093,7 +1094,6 @@ DEPENDENCIES
gettext_i18n_rails_js (~> 1.3)
gitaly-proto (~> 1.32.0)
github-markup (~> 1.7.0)
- gitlab-default_value_for (~> 3.1.1)
gitlab-labkit (~> 0.3.0)
gitlab-markup (~> 1.7.0)
gitlab-sidekiq-fetcher (~> 0.4.0)
diff --git a/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue b/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
index 060d8e25227..ef1d1e49320 100644
--- a/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
+++ b/app/assets/javascripts/error_tracking_settings/components/error_tracking_form.vue
@@ -49,9 +49,9 @@ export default {
</p>
</div>
<div class="form-group" :class="{ 'gl-show-field-errors': connectError }">
- <label class="label-bold" for="error-tracking-token">{{
- s__('ErrorTracking|Auth Token')
- }}</label>
+ <label class="label-bold" for="error-tracking-token">
+ {{ s__('ErrorTracking|Auth Token') }}
+ </label>
<div class="row">
<div class="col-8 col-md-9 gl-pr-0">
<gl-form-input
@@ -65,9 +65,8 @@ export default {
<gl-button
class="js-error-tracking-connect prepend-left-5"
@click="$emit('handle-connect')"
+ >{{ __('Connect') }}</gl-button
>
- {{ __('Connect') }}
- </gl-button>
<icon
v-show="connectSuccessful"
class="js-error-tracking-connect-success prepend-left-5 text-success align-middle"
diff --git a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
index 19bc3313373..4757c4b1e43 100644
--- a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
+++ b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
@@ -59,7 +59,7 @@ export default {
<template>
<div>
<div v-if="!isLocalStorageAvailable" class="dropdown-info-note">
- This feature requires local storage to be enabled
+ {{ __('This feature requires local storage to be enabled') }}
</div>
<ul v-else-if="hasItems">
<li v-for="(item, index) in processedItems" :key="`processed-items-${index}`">
@@ -90,10 +90,10 @@ export default {
class="filtered-search-history-clear-button"
@click="onRequestClearRecentSearches($event)"
>
- Clear recent searches
+ {{ __('Clear recent searches') }}
</button>
</li>
</ul>
- <div v-else class="dropdown-info-note">You don't have any recent searches</div>
+ <div v-else class="dropdown-info-note">{{ __("You don't have any recent searches") }}</div>
</div>
</template>
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
index ff6dadeff7d..533065b2d4d 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
@@ -1,5 +1,6 @@
<script>
-import projectFeatureToggle from '../../../../../vue_shared/components/toggle_button.vue';
+import projectFeatureToggle from '~/vue_shared/components/toggle_button.vue';
+import { featureAccessLevelNone } from '../constants';
export default {
components: {
@@ -43,7 +44,7 @@ export default {
if (this.featureEnabled) {
return this.options;
}
- return [[0, 'Enable feature to choose access level']];
+ return [featureAccessLevelNone];
},
displaySelectInput() {
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index 0bcfb740469..b4d24f3aa36 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
@@ -1,11 +1,19 @@
<script>
import settingsMixin from 'ee_else_ce/pages/projects/shared/permissions/mixins/settings_pannel_mixin';
+import { __ } from '~/locale';
import projectFeatureSetting from './project_feature_setting.vue';
import projectFeatureToggle from '~/vue_shared/components/toggle_button.vue';
import projectSettingRow from './project_setting_row.vue';
-import { visibilityOptions, visibilityLevelDescriptions } from '../constants';
+import {
+ visibilityOptions,
+ visibilityLevelDescriptions,
+ featureAccessLevelMembers,
+ featureAccessLevelEveryone,
+} from '../constants';
import { toggleHiddenClassBySelector } from '../external';
+const PAGE_FEATURE_ACCESS_LEVEL = __('Everyone');
+
export default {
components: {
projectFeatureSetting,
@@ -102,9 +110,9 @@ export default {
computed: {
featureAccessLevelOptions() {
- const options = [[10, 'Only Project Members']];
+ const options = [featureAccessLevelMembers];
if (this.visibilityLevel !== visibilityOptions.PRIVATE) {
- options.push([20, 'Everyone With Access']);
+ options.push(featureAccessLevelEveryone);
}
return options;
},
@@ -117,7 +125,7 @@ export default {
pagesFeatureAccessLevelOptions() {
if (this.visibilityLevel !== visibilityOptions.PUBLIC) {
- return this.featureAccessLevelOptions.concat([[30, 'Everyone']]);
+ return this.featureAccessLevelOptions.concat([[30, PAGE_FEATURE_ACCESS_LEVEL]]);
}
return this.featureAccessLevelOptions;
},
@@ -200,17 +208,17 @@ export default {
<option
:value="visibilityOptions.PRIVATE"
:disabled="!visibilityAllowed(visibilityOptions.PRIVATE)"
- >Private</option
+ >{{ __('Private') }}</option
>
<option
:value="visibilityOptions.INTERNAL"
:disabled="!visibilityAllowed(visibilityOptions.INTERNAL)"
- >Internal</option
+ >{{ __('Internal') }}</option
>
<option
:value="visibilityOptions.PUBLIC"
:disabled="!visibilityAllowed(visibilityOptions.PUBLIC)"
- >Public</option
+ >{{ __('Public') }}</option
>
</select>
<i aria-hidden="true" data-hidden="true" class="fa fa-chevron-down"></i>
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/constants.js b/app/assets/javascripts/pages/projects/shared/permissions/constants.js
index ac0dca31c37..73269c6f3ba 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/constants.js
+++ b/app/assets/javascripts/pages/projects/shared/permissions/constants.js
@@ -15,3 +15,30 @@ export const visibilityLevelDescriptions = {
'The project can be accessed by anyone, regardless of authentication.',
),
};
+
+const featureAccessLevel = {
+ NOT_ENABLED: 0,
+ PROJECT_MEMBERS: 10,
+ EVERYONE: 20,
+};
+
+const featureAccessLevelDescriptions = {
+ [featureAccessLevel.NOT_ENABLED]: __('Enable feature to choose access level'),
+ [featureAccessLevel.PROJECT_MEMBERS]: __('Only Project Members'),
+ [featureAccessLevel.EVERYONE]: __('Everyone With Access'),
+};
+
+export const featureAccessLevelNone = [
+ featureAccessLevel.NOT_ENABLED,
+ featureAccessLevelDescriptions[featureAccessLevel.NOT_ENABLED],
+];
+
+export const featureAccessLevelMembers = [
+ featureAccessLevel.PROJECT_MEMBERS,
+ featureAccessLevelDescriptions[featureAccessLevel.PROJECT_MEMBERS],
+];
+
+export const featureAccessLevelEveryone = [
+ featureAccessLevel.EVERYONE,
+ featureAccessLevelDescriptions[featureAccessLevel.EVERYONE],
+];
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index b2e365e5cde..39afa87afc3 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -2,6 +2,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
import ciHeader from '../../vue_shared/components/header_ci_component.vue';
import eventHub from '../event_hub';
+import { __ } from '~/locale';
export default {
name: 'PipelineHeaderSection',
@@ -54,7 +55,7 @@ export default {
if (this.pipeline.retry_path) {
actions.push({
- label: 'Retry',
+ label: __('Retry'),
path: this.pipeline.retry_path,
cssClass: 'js-retry-button btn btn-inverted-secondary',
type: 'button',
@@ -64,7 +65,7 @@ export default {
if (this.pipeline.cancel_path) {
actions.push({
- label: 'Cancel running',
+ label: __('Cancel running'),
path: this.pipeline.cancel_path,
cssClass: 'js-btn-cancel-pipeline btn btn-danger',
type: 'button',
diff --git a/app/assets/javascripts/pipelines/components/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipeline_url.vue
index 65a2b61396c..3f021a26ec5 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_url.vue
@@ -94,9 +94,8 @@ export default {
tabindex="0"
class="js-pipeline-url-autodevops badge badge-info autodevops-badge"
role="button"
+ >{{ __('Auto DevOps') }}</gl-link
>
- Auto DevOps
- </gl-link>
<span v-if="pipeline.flags.stuck" class="js-pipeline-url-stuck badge badge-warning">
{{ __('stuck') }}
</span>
diff --git a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
index bfc55013a71..03281aa1317 100644
--- a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
+++ b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
@@ -3,7 +3,7 @@ import Visibility from 'visibilityjs';
import ciIcon from '~/vue_shared/components/ci_icon.vue';
import Poll from '~/lib/utils/poll';
import Flash from '~/flash';
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import { GlLoadingIcon } from '@gitlab/ui';
import CommitPipelineService from '../services/commit_pipeline_service';
@@ -56,7 +56,7 @@ export default {
},
errorCallback() {
this.ciStatus = {
- text: 'not found',
+ text: __('not found'),
icon: 'status_notfound',
group: 'notfound',
};
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index f510b905a2e..c82b65cd97b 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -4,7 +4,7 @@ import { GlTooltipDirective, GlLink, GlBadge } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
-import { sprintf } from '../../locale';
+import { __, sprintf } from '../../locale';
export default {
name: 'ReleaseBlock',
@@ -27,13 +27,13 @@ export default {
},
computed: {
releasedTimeAgo() {
- return sprintf('released %{time}', {
+ return sprintf(__('released %{time}'), {
time: this.timeFormated(this.release.created_at),
});
},
userImageAltDescription() {
return this.author && this.author.username
- ? sprintf("%{username}'s avatar", { username: this.author.username })
+ ? sprintf(__("%{username}'s avatar"), { username: this.author.username })
: null;
},
commit() {
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index c31e7fa71a2..3e060e9ecb6 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -110,9 +110,7 @@ export default {
<component :is="linkComponent" :to="routerLinkTo" :href="url" class="str-truncated">
{{ fullPath }}
</component>
- <gl-badge v-if="lfsOid" variant="default" class="label-lfs ml-1">
- LFS
- </gl-badge>
+ <gl-badge v-if="lfsOid" variant="default" class="label-lfs ml-1">LFS</gl-badge>
<template v-if="isSubmodule">
@ <gl-link href="#" class="commit-sha">{{ shortSha }}</gl-link>
</template>
diff --git a/app/assets/javascripts/serverless/components/area.vue b/app/assets/javascripts/serverless/components/area.vue
index 32c9d6eccb8..a1a8cd3acbd 100644
--- a/app/assets/javascripts/serverless/components/area.vue
+++ b/app/assets/javascripts/serverless/components/area.vue
@@ -4,6 +4,7 @@ import { debounceByAnimationFrame } from '~/lib/utils/common_utils';
import dateFormat from 'dateformat';
import { X_INTERVAL } from '../constants';
import { validateGraphData } from '../utils';
+import { __ } from '~/locale';
let debouncedResize;
@@ -42,7 +43,7 @@ export default {
},
generateSeries() {
return {
- name: 'Invocations',
+ name: __('Invocations'),
type: 'line',
data: this.chartData.requests.map(data => [data.time, data.value]),
symbolSize: 0,
@@ -124,7 +125,9 @@ export default {
<div class="prometheus-graph">
<div class="prometheus-graph-header">
<h5 ref="graphTitle" class="prometheus-graph-title">{{ graphData.title }}</h5>
- <div ref="graphWidgets" class="prometheus-graph-widgets"><slot></slot></div>
+ <div ref="graphWidgets" class="prometheus-graph-widgets">
+ <slot></slot>
+ </div>
</div>
<gl-area-chart
ref="areaChart"
@@ -135,12 +138,8 @@ export default {
:width="width"
:include-legend-avg-max="false"
>
- <template slot="tooltipTitle">
- {{ tooltipPopoverTitle }}
- </template>
- <template slot="tooltipContent">
- {{ tooltipPopoverContent }}
- </template>
+ <template slot="tooltipTitle">{{ tooltipPopoverTitle }}</template>
+ <template slot="tooltipContent">{{ tooltipPopoverContent }}</template>
</gl-area-chart>
</div>
</template>
diff --git a/app/assets/javascripts/serverless/components/function_details.vue b/app/assets/javascripts/serverless/components/function_details.vue
index b8906cfca4e..d542dad8119 100644
--- a/app/assets/javascripts/serverless/components/function_details.vue
+++ b/app/assets/javascripts/serverless/components/function_details.vue
@@ -89,7 +89,9 @@ export default {
}}
</p>
</div>
- <div v-else><p>No pods loaded at this time.</p></div>
+ <div v-else>
+ <p>{{ s__('ServerlessDetails|No pods loaded at this time.') }}</p>
+ </div>
<area-chart v-if="hasPrometheusData" :graph-data="graphData" :container-width="elWidth" />
<missing-prometheus
diff --git a/app/assets/javascripts/serverless/components/functions.vue b/app/assets/javascripts/serverless/components/functions.vue
index 94341050b86..9e66869515c 100644
--- a/app/assets/javascripts/serverless/components/functions.vue
+++ b/app/assets/javascripts/serverless/components/functions.vue
@@ -1,4 +1,5 @@
<script>
+import { sprintf, s__ } from '~/locale';
import { mapState, mapActions, mapGetters } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import FunctionRow from './function_row.vue';
@@ -37,6 +38,28 @@ export default {
isInstalled() {
return this.installed === true;
},
+ noServerlessConfigFile() {
+ return sprintf(
+ s__(
+ 'Serverless|Your repository does not have a corresponding %{startTag}serverless.yml%{endTag} file.',
+ ),
+ { startTag: '<code>', endTag: '</code>' },
+ );
+ },
+ noGitlabYamlConfigured() {
+ return sprintf(
+ s__('Serverless|Your %{startTag}.gitlab-ci.yml%{endTag} file is not properly configured.'),
+ { startTag: '<code>', endTag: '</code>' },
+ );
+ },
+ mismatchedServerlessFunctions() {
+ return sprintf(
+ s__(
+ "Serverless|The functions listed in the %{startTag}serverless.yml%{endTag} file don't match the namespace of your cluster.",
+ ),
+ { startTag: '<code>', endTag: '</code>' },
+ );
+ },
},
created() {
this.fetchFunctions({
@@ -82,25 +105,29 @@ export default {
<h4 class="state-title text-center">{{ s__('Serverless|No functions available') }}</h4>
<p class="state-description">
{{
- s__(`Serverless|There is currently no function data available from Knative.
- This could be for a variety of reasons including:`)
+ s__(
+ 'Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:',
+ )
}}
</p>
<ul>
- <li>Your repository does not have a corresponding <code>serverless.yml</code> file.</li>
- <li>Your <code>.gitlab-ci.yml</code> file is not properly configured.</li>
<li>
- The functions listed in the <code>serverless.yml</code> file don't match the namespace
- of your cluster.
+ {{ noServerlessConfigFile }}
+ </li>
+ <li>
+ {{ noGitlabYamlConfigured }}
+ </li>
+ <li>
+ {{ mismatchedServerlessFunctions }}
</li>
- <li>The deploy job has not finished.</li>
+ <li>{{ s__('Serverless|The deploy job has not finished.') }}</li>
</ul>
<p>
{{
- s__(`Serverless|If you believe none of these apply, please check
- back later as the function data may be in the process of becoming
- available.`)
+ s__(
+ 'Serverless|If you believe none of these apply, please check back later as the function data may be in the process of becoming available.',
+ )
}}
</p>
<div class="text-center">
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 316da8f129d..797833e3f91 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -201,8 +201,7 @@ class GroupsController < Groups::ApplicationController
params[:sort] ||= 'latest_activity_desc'
options = {}
- options[:only_owned] = true if params[:shared] == '0'
- options[:only_shared] = true if params[:shared] == '1'
+ options[:include_subgroups] = true
@projects = GroupProjectsFinder.new(params: params, group: group, options: options, current_user: current_user)
.execute
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index da5efe4f21c..d77f64a84f5 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -68,8 +68,9 @@ class Projects::BranchesController < Projects::ApplicationController
success = (result[:status] == :success)
if params[:issue_iid] && success
- issue = IssuesFinder.new(current_user, project_id: @project.id).find_by(iid: params[:issue_iid])
- SystemNoteService.new_issue_branch(issue, @project, current_user, branch_name) if issue
+ target_project = confidential_issue_project || @project
+ issue = IssuesFinder.new(current_user, project_id: target_project.id).find_by(iid: params[:issue_iid])
+ SystemNoteService.new_issue_branch(issue, target_project, current_user, branch_name, branch_project: @project) if issue
end
respond_to do |format|
@@ -166,4 +167,15 @@ class Projects::BranchesController < Projects::ApplicationController
@branches = Kaminari.paginate_array(@branches).page(params[:page])
end
end
+
+ def confidential_issue_project
+ return unless Feature.enabled?(:create_confidential_merge_request, @project)
+ return if params[:confidential_issue_project_id].blank?
+
+ confidential_issue_project = Project.find(params[:confidential_issue_project_id])
+
+ return unless can?(current_user, :update_issue, confidential_issue_project)
+
+ confidential_issue_project
+ end
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index f221f0363d3..e275b417784 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -172,6 +172,7 @@ class Projects::IssuesController < Projects::ApplicationController
def create_merge_request
create_params = params.slice(:branch_name, :ref).merge(issue_iid: issue.iid)
+ create_params[:target_project_id] = params[:target_project_id] if Feature.enabled?(:create_confidential_merge_request, @project)
result = ::MergeRequests::CreateFromIssueService.new(project, current_user, create_params).execute
if result[:status] == :success
diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb
index 506c8d251b7..04db1980b99 100644
--- a/app/mailers/emails/notes.rb
+++ b/app/mailers/emails/notes.rb
@@ -51,7 +51,7 @@ module Emails
def note_thread_options(recipient_id)
{
from: sender(@note.author_id),
- to: recipient(recipient_id, @group),
+ to: recipient(recipient_id, @project&.group || @group),
subject: subject("#{@note.noteable.title} (#{@note.noteable.reference_link_text})")
}
end
@@ -60,7 +60,7 @@ module Emails
# `note_id` is a `Note` when originating in `NotifyPreview`
@note = note_id.is_a?(Note) ? note_id : Note.find(note_id)
@project = @note.project
- @group = @project.try(:group) || @note.noteable.try(:group)
+ @group = @note.noteable.try(:group)
if (@project || @group) && @note.persisted?
@sent_notification = SentNotification.record_note(@note, recipient_id, reply_key)
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index cd645850af3..fbd8036653a 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -23,11 +23,6 @@ class ApplicationSetting < ApplicationRecord
serialize :domain_blacklist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :repository_storages # rubocop:disable Cop/ActiveRecordSerialize
- ignore_column :circuitbreaker_failure_count_threshold
- ignore_column :circuitbreaker_failure_reset_time
- ignore_column :circuitbreaker_storage_timeout
- ignore_column :circuitbreaker_access_retries
- ignore_column :circuitbreaker_check_interval
ignore_column :koding_url
ignore_column :koding_enabled
ignore_column :sentry_enabled
diff --git a/app/services/merge_requests/create_from_issue_service.rb b/app/services/merge_requests/create_from_issue_service.rb
index e69791872cc..2a217a6f689 100644
--- a/app/services/merge_requests/create_from_issue_service.rb
+++ b/app/services/merge_requests/create_from_issue_service.rb
@@ -6,17 +6,20 @@ module MergeRequests
# branch - the name of new branch
# ref - the source of new branch.
- @branch_name = params[:branch_name]
- @issue_iid = params[:issue_iid]
- @ref = params[:ref]
+ @branch_name = params[:branch_name]
+ @issue_iid = params[:issue_iid]
+ @ref = params[:ref]
+ @target_project_id = params[:target_project_id]
super(project, user)
end
def execute
+ return error('Project not found') if target_project.blank?
+ return error('Not allowed to create merge request') unless can_create_merge_request?
return error('Invalid issue iid') unless @issue_iid.present? && issue.present?
- result = CreateBranchService.new(project, current_user).execute(branch_name, ref)
+ result = CreateBranchService.new(target_project, current_user).execute(branch_name, ref)
return result if result[:status] == :error
new_merge_request = create(merge_request)
@@ -26,7 +29,7 @@ module MergeRequests
success(new_merge_request)
else
- SystemNoteService.new_issue_branch(issue, project, current_user, branch_name)
+ SystemNoteService.new_issue_branch(issue, project, current_user, branch_name, branch_project: target_project)
error(new_merge_request.errors)
end
@@ -34,6 +37,10 @@ module MergeRequests
private
+ def can_create_merge_request?
+ can?(current_user, :create_merge_request_from, target_project)
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def issue
@issue ||= IssuesFinder.new(current_user, project_id: project.id).find_by(iid: @issue_iid)
@@ -45,21 +52,21 @@ module MergeRequests
end
def ref
- return @ref if project.repository.branch_exists?(@ref)
+ return @ref if target_project.repository.branch_exists?(@ref)
- project.default_branch || 'master'
+ target_project.default_branch || 'master'
end
def merge_request
- MergeRequests::BuildService.new(project, current_user, merge_request_params).execute
+ MergeRequests::BuildService.new(target_project, current_user, merge_request_params).execute
end
def merge_request_params
{
issue_iid: @issue_iid,
- source_project_id: project.id,
+ source_project_id: target_project.id,
source_branch: branch_name,
- target_project_id: project.id,
+ target_project_id: target_project.id,
target_branch: ref
}
end
@@ -67,5 +74,14 @@ module MergeRequests
def success(merge_request)
super().merge(merge_request: merge_request)
end
+
+ def target_project
+ @target_project ||=
+ if @target_project_id.present?
+ project.forks.find_by_id(@target_project_id)
+ else
+ project
+ end
+ end
end
end
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 1390f7cdf46..8f7cfe582ca 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -404,8 +404,9 @@ module SystemNoteService
# Example note text:
#
# "created branch `201-issue-branch-button`"
- def new_issue_branch(issue, project, author, branch)
- link = url_helpers.project_compare_path(project, from: project.default_branch, to: branch)
+ def new_issue_branch(issue, project, author, branch, branch_project: nil)
+ branch_project ||= project
+ link = url_helpers.project_compare_path(branch_project, from: branch_project.default_branch, to: branch)
body = "created branch [`#{branch}`](#{link}) to address this issue"
@@ -413,7 +414,7 @@ module SystemNoteService
end
def new_merge_request(issue, project, author, merge_request)
- body = "created merge request #{merge_request.to_reference} to address this issue"
+ body = "created merge request #{merge_request.to_reference(project)} to address this issue"
create_note(NoteSummary.new(issue, project, author, body, action: 'merge'))
end
diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb
index c3f2902c78a..6c0d7b1e60b 100644
--- a/app/views/notify/new_merge_request_email.text.erb
+++ b/app/views/notify/new_merge_request_email.text.erb
@@ -1,7 +1,7 @@
<%= @merge_request.author_name %> <%= 'created a merge request:' %> <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
<%= merge_path_description(@merge_request, 'to') %>
-<%= 'Author' %>: <%= @merge_request.author_name %>
+<%= 'Author:' %> <%= @merge_request.author_name %>
<%= assignees_label(@merge_request) %>
<%= render_if_exists 'notify/merge_request_approvers', presenter: @mr_presenter %>
diff --git a/changelogs/unreleased/44106-include-subgroups-in-group-activity.yml b/changelogs/unreleased/44106-include-subgroups-in-group-activity.yml
new file mode 100644
index 00000000000..6e78d61ebc4
--- /dev/null
+++ b/changelogs/unreleased/44106-include-subgroups-in-group-activity.yml
@@ -0,0 +1,5 @@
+---
+title: Include events from subgroups in group's activity
+merge_request: 29953
+author: Fabian Schneider @fabsrc
+type: changed
diff --git a/changelogs/unreleased/sh-fix-issue-63910.yml b/changelogs/unreleased/sh-fix-issue-63910.yml
new file mode 100644
index 00000000000..50312558c57
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-issue-63910.yml
@@ -0,0 +1,5 @@
+---
+title: Fix attachments using the wrong URLs in e-mails
+merge_request: 30197
+author:
+type: fixed
diff --git a/config/initializers/6_validations.rb b/config/initializers/6_validations.rb
index bf9e5a50382..827b15e5c8d 100644
--- a/config/initializers/6_validations.rb
+++ b/config/initializers/6_validations.rb
@@ -1,24 +1,15 @@
-def storage_name_valid?(name)
- !!(name =~ /\A[a-zA-Z0-9\-_]+\z/)
-end
-
def storage_validation_error(message)
raise "#{message}. Please fix this in your gitlab.yml before starting GitLab."
end
def validate_storages_config
- storage_validation_error('No repository storage path defined') if Gitlab.config.repositories.storages.empty?
-
- Gitlab.config.repositories.storages.each do |name, repository_storage|
- storage_validation_error("\"#{name}\" is not a valid storage name") unless storage_name_valid?(name)
-
- %w(failure_count_threshold failure_reset_time storage_timeout).each do |setting|
- # Falling back to the defaults is fine!
- next if repository_storage[setting].nil?
+ if Gitlab.config.repositories.storages.empty?
+ storage_validation_error('No repository storage path defined')
+ end
- unless repository_storage[setting].to_f > 0
- storage_validation_error("`#{setting}` for storage `#{name}` needs to be greater than 0")
- end
+ Gitlab.config.repositories.storages.keys.each do |name|
+ unless /\A[a-zA-Z0-9\-_]+\z/.match?(name)
+ storage_validation_error("\"#{name}\" is not a valid storage name")
end
end
end
diff --git a/lib/banzai/filter/relative_link_filter.rb b/lib/banzai/filter/relative_link_filter.rb
index 80c84c0f622..88836e12e61 100644
--- a/lib/banzai/filter/relative_link_filter.rb
+++ b/lib/banzai/filter/relative_link_filter.rb
@@ -56,10 +56,10 @@ module Banzai
def process_link_to_upload_attr(html_attr)
path_parts = [Addressable::URI.unescape(html_attr.value)]
- if group
- path_parts.unshift(relative_url_root, 'groups', group.full_path, '-')
- elsif project
+ if project
path_parts.unshift(relative_url_root, project.full_path)
+ elsif group
+ path_parts.unshift(relative_url_root, 'groups', group.full_path, '-')
else
path_parts.unshift(relative_url_root)
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 46f2b54f485..b5c12188ad4 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -251,6 +251,9 @@ msgstr ""
msgid "%{user_name} profile page"
msgstr ""
+msgid "%{username}'s avatar"
+msgstr ""
+
msgid "%{verb} %{time_spent_value} spent time."
msgstr ""
@@ -1870,6 +1873,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel running"
+msgstr ""
+
msgid "Cancel this job"
msgstr ""
@@ -2149,6 +2155,9 @@ msgstr ""
msgid "Clear"
msgstr ""
+msgid "Clear recent searches"
+msgstr ""
+
msgid "Clear search"
msgstr ""
@@ -3917,6 +3926,9 @@ msgstr ""
msgid "Enable error tracking"
msgstr ""
+msgid "Enable feature to choose access level"
+msgstr ""
+
msgid "Enable for this project"
msgstr ""
@@ -4307,6 +4319,9 @@ msgstr ""
msgid "Everyone"
msgstr ""
+msgid "Everyone With Access"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
@@ -5556,6 +5571,9 @@ msgstr ""
msgid "Invite member"
msgstr ""
+msgid "Invocations"
+msgstr ""
+
msgid "Invoke Count"
msgstr ""
@@ -6980,6 +6998,9 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
+msgid "Only Project Members"
+msgstr ""
+
msgid "Only admins"
msgstr ""
@@ -9195,6 +9216,9 @@ msgstr ""
msgid "ServerlessDetails|More information"
msgstr ""
+msgid "ServerlessDetails|No pods loaded at this time."
+msgstr ""
+
msgid "ServerlessDetails|Number of Kubernetes pods in use over time based on necessity."
msgstr ""
@@ -9225,9 +9249,21 @@ msgstr ""
msgid "Serverless|No functions available"
msgstr ""
+msgid "Serverless|The deploy job has not finished."
+msgstr ""
+
+msgid "Serverless|The functions listed in the %{startTag}serverless.yml%{endTag} file don't match the namespace of your cluster."
+msgstr ""
+
msgid "Serverless|There is currently no function data available from Knative. This could be for a variety of reasons including:"
msgstr ""
+msgid "Serverless|Your %{startTag}.gitlab-ci.yml%{endTag} file is not properly configured."
+msgstr ""
+
+msgid "Serverless|Your repository does not have a corresponding %{startTag}serverless.yml%{endTag} file."
+msgstr ""
+
msgid "Service"
msgstr ""
@@ -10558,6 +10594,9 @@ msgstr ""
msgid "This domain is not verified. You will need to verify ownership before access is enabled."
msgstr ""
+msgid "This feature requires local storage to be enabled"
+msgstr ""
+
msgid "This field is required."
msgstr ""
@@ -12073,6 +12112,9 @@ msgstr ""
msgid "You don't have any deployments right now."
msgstr ""
+msgid "You don't have any recent searches"
+msgstr ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -12757,6 +12799,9 @@ msgstr ""
msgid "none"
msgstr ""
+msgid "not found"
+msgstr ""
+
msgid "notification emails"
msgstr ""
@@ -12806,6 +12851,9 @@ msgstr ""
msgid "register"
msgstr ""
+msgid "released %{time}"
+msgstr ""
+
msgid "remaining"
msgstr ""
diff --git a/qa/qa/service/shellout.rb b/qa/qa/service/shellout.rb
index 7065ab0e7f3..217df669db3 100644
--- a/qa/qa/service/shellout.rb
+++ b/qa/qa/service/shellout.rb
@@ -19,7 +19,7 @@ module QA
Open3.popen2e(*command) do |stdin, out, wait|
stdin.puts(stdin_data) if stdin_data
stdin.close if stdin_data
- out.each { |line| puts line }
+ out.each_char { |char| print char }
if wait.value.exited? && wait.value.exitstatus.nonzero?
raise CommandError, "Command `#{command}` failed!"
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 47d7e278183..d2faef5b12b 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -125,11 +125,14 @@ describe GroupsController do
end
context 'as json' do
- it 'includes all projects in event feed' do
- 3.times do
+ it 'includes all projects from groups and subgroups in event feed' do
+ 2.times do
project = create(:project, group: group)
create(:event, project: project)
end
+ subgroup = create(:group, parent: group)
+ project = create(:project, group: subgroup)
+ create(:event, project: project)
get :activity, params: { id: group.to_param }, format: :json
diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb
index 287ea9f425d..b30966e70a7 100644
--- a/spec/controllers/projects/branches_controller_spec.rb
+++ b/spec/controllers/projects/branches_controller_spec.rb
@@ -92,7 +92,7 @@ describe Projects::BranchesController do
end
it 'posts a system note' do
- expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, user, "1-feature-branch")
+ expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, user, "1-feature-branch", branch_project: project)
post :create,
params: {
@@ -103,6 +103,75 @@ describe Projects::BranchesController do
}
end
+ context 'confidential_issue_project_id is present' do
+ let(:confidential_issue_project) { create(:project) }
+
+ def create_branch_with_confidential_issue_project
+ post(
+ :create,
+ params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ branch_name: branch,
+ confidential_issue_project_id: confidential_issue_project.id,
+ issue_iid: issue.iid
+ }
+ )
+ end
+
+ context 'create_confidential_merge_request feature is enabled' do
+ before do
+ stub_feature_flags(create_confidential_merge_request: true)
+ end
+
+ context 'user cannot update issue' do
+ let(:issue) { create(:issue, project: confidential_issue_project) }
+
+ it 'does not post a system note' do
+ expect(SystemNoteService).not_to receive(:new_issue_branch)
+
+ create_branch_with_confidential_issue_project
+ end
+ end
+
+ context 'user can update issue' do
+ before do
+ confidential_issue_project.add_reporter(user)
+ end
+
+ context 'issue is under the specified project' do
+ let(:issue) { create(:issue, project: confidential_issue_project) }
+
+ it 'posts a system note' do
+ expect(SystemNoteService).to receive(:new_issue_branch).with(issue, confidential_issue_project, user, "1-feature-branch", branch_project: project)
+
+ create_branch_with_confidential_issue_project
+ end
+ end
+
+ context 'issue is not under the specified project' do
+ it 'does not post a system note' do
+ expect(SystemNoteService).not_to receive(:new_issue_branch)
+
+ create_branch_with_confidential_issue_project
+ end
+ end
+ end
+ end
+
+ context 'create_confidential_merge_request feature is disabled' do
+ before do
+ stub_feature_flags(create_confidential_merge_request: false)
+ end
+
+ it 'posts a system note on project' do
+ expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, user, "1-feature-branch", branch_project: project)
+
+ create_branch_with_confidential_issue_project
+ end
+ end
+ end
+
context 'repository-less project' do
let(:project) { create :project }
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index f82e3c8c7dc..bc5e0b4671e 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Projects::IssuesController do
+ include ProjectForksHelper
+
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:issue) { create(:issue, project: project) }
@@ -1130,6 +1132,7 @@ describe Projects::IssuesController do
end
describe 'POST create_merge_request' do
+ let(:target_project_id) { nil }
let(:project) { create(:project, :repository, :public) }
before do
@@ -1163,13 +1166,42 @@ describe Projects::IssuesController do
expect(response).to have_gitlab_http_status(404)
end
+ context 'target_project_id is set' do
+ let(:target_project) { fork_project(project, user, repository: true) }
+ let(:target_project_id) { target_project.id }
+
+ context 'create_confidential_merge_request feature is enabled' do
+ before do
+ stub_feature_flags(create_confidential_merge_request: true)
+ end
+
+ it 'creates a new merge request' do
+ expect { create_merge_request }.to change(target_project.merge_requests, :count).by(1)
+ end
+ end
+
+ context 'create_confidential_merge_request feature is disabled' do
+ before do
+ stub_feature_flags(create_confidential_merge_request: false)
+ end
+
+ it 'creates a new merge request' do
+ expect { create_merge_request }.to change(project.merge_requests, :count).by(1)
+ end
+ end
+ end
+
def create_merge_request
- post :create_merge_request, params: {
- namespace_id: project.namespace.to_param,
- project_id: project.to_param,
- id: issue.to_param
- },
- format: :json
+ post(
+ :create_merge_request,
+ params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ id: issue.to_param,
+ target_project_id: target_project_id
+ },
+ format: :json
+ )
end
end
diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb
index 597c8f836a9..6c6410cee9b 100644
--- a/spec/helpers/markup_helper_spec.rb
+++ b/spec/helpers/markup_helper_spec.rb
@@ -50,6 +50,43 @@ describe MarkupHelper do
expect(markdown(actual, project: second_project)).to match(expected)
end
end
+
+ describe 'uploads' do
+ let(:text) { "![ImageTest](/uploads/test.png)" }
+ let(:group) { create(:group) }
+
+ subject { helper.markdown(text) }
+
+ describe 'inside a project' do
+ it 'renders uploads relative to project' do
+ expect(subject).to include("#{project.full_path}/uploads/test.png")
+ end
+ end
+
+ describe 'inside a group' do
+ before do
+ helper.instance_variable_set(:@group, group)
+ helper.instance_variable_set(:@project, nil)
+ end
+
+ it 'renders uploads relative to the group' do
+ expect(subject).to include("#{group.full_path}/-/uploads/test.png")
+ end
+ end
+
+ describe "with a group in the context" do
+ let(:project_in_group) { create(:project, group: group) }
+
+ before do
+ helper.instance_variable_set(:@group, group)
+ helper.instance_variable_set(:@project, project_in_group)
+ end
+
+ it 'renders uploads relative to project' do
+ expect(subject).to include("#{project_in_group.path_with_namespace}/uploads/test.png")
+ end
+ end
+ end
end
describe '#markdown_field' do
diff --git a/spec/initializers/6_validations_spec.rb b/spec/initializers/6_validations_spec.rb
index f96e5a2133f..73fbd4c7a44 100644
--- a/spec/initializers/6_validations_spec.rb
+++ b/spec/initializers/6_validations_spec.rb
@@ -2,16 +2,6 @@ require 'spec_helper'
require_relative '../../config/initializers/6_validations.rb'
describe '6_validations' do
- before :all do
- FileUtils.mkdir_p('tmp/tests/paths/a/b/c/d')
- FileUtils.mkdir_p('tmp/tests/paths/a/b/c2')
- FileUtils.mkdir_p('tmp/tests/paths/a/b/d')
- end
-
- after :all do
- FileUtils.rm_rf('tmp/tests/paths')
- end
-
describe 'validate_storages_config' do
context 'with correct settings' do
before do
@@ -23,16 +13,6 @@ describe '6_validations' do
end
end
- context 'when one of the settings is incorrect' do
- before do
- mock_storages('foo' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/c', 'failure_count_threshold' => 'not a number'))
- end
-
- it 'throws an error' do
- expect { validate_storages_config }.to raise_error(/failure_count_threshold/)
- end
- end
-
context 'with invalid storage names' do
before do
mock_storages('name with spaces' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/c'))
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index fa1343fe759..56bbcc4c306 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -606,7 +606,7 @@ describe Notify do
it_behaves_like 'a user cannot unsubscribe through footer link'
it 'has the correct subject and body' do
- is_expected.to have_referable_subject(project_snippet, include_group: true, reply: true)
+ is_expected.to have_referable_subject(project_snippet, reply: true)
is_expected.to have_body_text project_snippet_note.note
end
end
@@ -813,7 +813,7 @@ describe Notify do
it 'has the correct subject and body' do
aggregate_failures do
- is_expected.to have_subject("Re: #{project.name} | #{project.group.name} | #{commit.title} (#{commit.short_id})")
+ is_expected.to have_subject("Re: #{project.name} | #{commit.title} (#{commit.short_id})")
is_expected.to have_body_text(commit.short_id)
end
end
@@ -839,7 +839,7 @@ describe Notify do
it 'has the correct subject and body' do
aggregate_failures do
- is_expected.to have_referable_subject(merge_request, include_group: true, reply: true)
+ is_expected.to have_referable_subject(merge_request, reply: true)
is_expected.to have_body_text note_on_merge_request_path
end
end
@@ -865,7 +865,7 @@ describe Notify do
it 'has the correct subject and body' do
aggregate_failures do
- is_expected.to have_referable_subject(issue, include_group: true, reply: true)
+ is_expected.to have_referable_subject(issue, reply: true)
is_expected.to have_body_text(note_on_issue_path)
end
end
@@ -931,7 +931,7 @@ describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject' do
- is_expected.to have_subject "Re: #{project.name} | #{project.group.name} | #{commit.title} (#{commit.short_id})"
+ is_expected.to have_subject "Re: #{project.name} | #{commit.title} (#{commit.short_id})"
end
it 'contains a link to the commit' do
@@ -959,7 +959,7 @@ describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject' do
- is_expected.to have_referable_subject(merge_request, include_group: true, reply: true)
+ is_expected.to have_referable_subject(merge_request, reply: true)
end
it 'contains a link to the merge request note' do
@@ -987,7 +987,7 @@ describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject' do
- is_expected.to have_referable_subject(issue, include_group: true, reply: true)
+ is_expected.to have_referable_subject(issue, reply: true)
end
it 'contains a link to the issue note' do
diff --git a/spec/services/merge_requests/create_from_issue_service_spec.rb b/spec/services/merge_requests/create_from_issue_service_spec.rb
index a0ac7dba89d..0e0da6a13ab 100644
--- a/spec/services/merge_requests/create_from_issue_service_spec.rb
+++ b/spec/services/merge_requests/create_from_issue_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe MergeRequests::CreateFromIssueService do
+ include ProjectForksHelper
+
let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
let(:label_ids) { create_pair(:label, project: project).map(&:id) }
@@ -10,139 +12,174 @@ describe MergeRequests::CreateFromIssueService do
let(:issue) { create(:issue, project: project, milestone_id: milestone_id) }
let(:custom_source_branch) { 'custom-source-branch' }
- subject(:service) { described_class.new(project, user, issue_iid: issue.iid) }
- subject(:service_with_custom_source_branch) { described_class.new(project, user, issue_iid: issue.iid, branch_name: custom_source_branch) }
+ subject(:service) { described_class.new(project, user, service_params) }
+ subject(:service_with_custom_source_branch) { described_class.new(project, user, branch_name: custom_source_branch, **service_params) }
before do
project.add_developer(user)
end
describe '#execute' do
- it 'returns an error with invalid issue iid' do
- result = described_class.new(project, user, issue_iid: -1).execute
+ shared_examples_for 'a service that creates a merge request from an issue' do
+ it 'returns an error when user can not create merge request on target project' do
+ result = described_class.new(project, create(:user), service_params).execute
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq('Invalid issue iid')
- end
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Not allowed to create merge request')
+ end
- it 'delegates issue search to IssuesFinder' do
- expect_any_instance_of(IssuesFinder).to receive(:find_by).once.and_call_original
+ it 'returns an error with invalid issue iid' do
+ result = described_class.new(project, user, issue_iid: -1).execute
- described_class.new(project, user, issue_iid: -1).execute
- end
-
- it "inherits labels" do
- issue.assign_attributes(label_ids: label_ids)
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Invalid issue iid')
+ end
- result = service.execute
+ it 'creates a branch based on issue title' do
+ service.execute
- expect(result[:merge_request].label_ids).to eq(label_ids)
- end
+ expect(target_project.repository.branch_exists?(issue.to_branch_name)).to be_truthy
+ end
- it "inherits milestones" do
- result = service.execute
+ it 'creates a branch using passed name' do
+ service_with_custom_source_branch.execute
- expect(result[:merge_request].milestone_id).to eq(milestone_id)
- end
+ expect(target_project.repository.branch_exists?(custom_source_branch)).to be_truthy
+ end
- it 'delegates the branch creation to CreateBranchService' do
- expect_any_instance_of(CreateBranchService).to receive(:execute).once.and_call_original
+ it 'creates the new_merge_request system note' do
+ expect(SystemNoteService).to receive(:new_merge_request).with(issue, project, user, instance_of(MergeRequest))
- service.execute
- end
+ service.execute
+ end
- it 'creates a branch based on issue title' do
- service.execute
+ it 'creates the new_issue_branch system note when the branch could be created but the merge_request cannot be created' do
+ expect_any_instance_of(MergeRequest).to receive(:valid?).at_least(:once).and_return(false)
- expect(project.repository.branch_exists?(issue.to_branch_name)).to be_truthy
- end
+ expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, user, issue.to_branch_name, branch_project: target_project)
- it 'creates a branch using passed name' do
- service_with_custom_source_branch.execute
+ service.execute
+ end
- expect(project.repository.branch_exists?(custom_source_branch)).to be_truthy
- end
+ it 'creates a merge request' do
+ expect { service.execute }.to change(target_project.merge_requests, :count).by(1)
+ end
- it 'creates the new_merge_request system note' do
- expect(SystemNoteService).to receive(:new_merge_request).with(issue, project, user, instance_of(MergeRequest))
+ it 'sets the merge request author to current user' do
+ result = service.execute
- service.execute
- end
+ expect(result[:merge_request].author).to eq(user)
+ end
- it 'creates the new_issue_branch system note when the branch could be created but the merge_request cannot be created' do
- project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
+ it 'sets the merge request source branch to the new issue branch' do
+ result = service.execute
- expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, user, issue.to_branch_name)
+ expect(result[:merge_request].source_branch).to eq(issue.to_branch_name)
+ end
- service.execute
- end
+ it 'sets the merge request source branch to the passed branch name' do
+ result = service_with_custom_source_branch.execute
- it 'creates a merge request' do
- expect { service.execute }.to change(project.merge_requests, :count).by(1)
- end
+ expect(result[:merge_request].source_branch).to eq(custom_source_branch)
+ end
- it 'sets the merge request title to: "WIP: Resolves "$issue-title"' do
- result = service.execute
+ it 'sets the merge request target branch to the project default branch' do
+ result = service.execute
- expect(result[:merge_request].title).to eq("WIP: Resolve \"#{issue.title}\"")
- end
+ expect(result[:merge_request].target_branch).to eq(target_project.default_branch)
+ end
- it 'sets the merge request author to current user' do
- result = service.execute
+ it 'executes quick actions if the build service sets them in the description' do
+ allow(service).to receive(:merge_request).and_wrap_original do |m, *args|
+ m.call(*args).tap do |merge_request|
+ merge_request.description = "/assign #{user.to_reference}"
+ end
+ end
- expect(result[:merge_request].author).to eq(user)
- end
+ result = service.execute
- it 'sets the merge request source branch to the new issue branch' do
- result = service.execute
+ expect(result[:merge_request].assignees).to eq([user])
+ end
- expect(result[:merge_request].source_branch).to eq(issue.to_branch_name)
- end
+ context 'when ref branch is set' do
+ subject { described_class.new(project, user, ref: 'feature', **service_params).execute }
- it 'sets the merge request source branch to the passed branch name' do
- result = service_with_custom_source_branch.execute
+ it 'sets the merge request source branch to the new issue branch' do
+ expect(subject[:merge_request].source_branch).to eq(issue.to_branch_name)
+ end
- expect(result[:merge_request].source_branch).to eq(custom_source_branch)
- end
+ it 'sets the merge request target branch to the ref branch' do
+ expect(subject[:merge_request].target_branch).to eq('feature')
+ end
- it 'sets the merge request target branch to the project default branch' do
- result = service.execute
+ context 'when ref branch does not exist' do
+ subject { described_class.new(project, user, ref: 'no-such-branch', **service_params).execute }
- expect(result[:merge_request].target_branch).to eq(project.default_branch)
- end
+ it 'creates a merge request' do
+ expect { subject }.to change(target_project.merge_requests, :count).by(1)
+ end
- it 'executes quick actions if the build service sets them in the description' do
- allow(service).to receive(:merge_request).and_wrap_original do |m, *args|
- m.call(*args).tap do |merge_request|
- merge_request.description = "/assign #{user.to_reference}"
+ it 'sets the merge request target branch to the project default branch' do
+ expect(subject[:merge_request].target_branch).to eq(target_project.default_branch)
+ end
end
end
+ end
- result = service.execute
+ context 'no target_project_id specified' do
+ let(:service_params) { { issue_iid: issue.iid } }
+ let(:target_project) { project }
- expect(result[:merge_request].assignees).to eq([user])
- end
+ it_behaves_like 'a service that creates a merge request from an issue'
- context 'when ref branch is set' do
- subject { described_class.new(project, user, issue_iid: issue.iid, ref: 'feature').execute }
+ it "inherits labels" do
+ issue.assign_attributes(label_ids: label_ids)
- it 'sets the merge request source branch to the new issue branch' do
- expect(subject[:merge_request].source_branch).to eq(issue.to_branch_name)
+ result = service.execute
+
+ expect(result[:merge_request].label_ids).to eq(label_ids)
end
- it 'sets the merge request target branch to the ref branch' do
- expect(subject[:merge_request].target_branch).to eq('feature')
+ it "inherits milestones" do
+ result = service.execute
+
+ expect(result[:merge_request].milestone_id).to eq(milestone_id)
end
- context 'when ref branch does not exist' do
- subject { described_class.new(project, user, issue_iid: issue.iid, ref: 'no-such-branch').execute }
+ it 'sets the merge request title to: "WIP: Resolves "$issue-title"' do
+ result = service.execute
- it 'creates a merge request' do
- expect { subject }.to change(project.merge_requests, :count).by(1)
+ expect(result[:merge_request].title).to eq("WIP: Resolve \"#{issue.title}\"")
+ end
+ end
+
+ context 'target_project_id is specified' do
+ let(:service_params) { { issue_iid: issue.iid, target_project_id: target_project.id } }
+
+ context 'target project is not a fork of the project' do
+ let(:target_project) { create(:project, :repository) }
+
+ it 'returns an error about not finding the project' do
+ result = service.execute
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Project not found')
end
- it 'sets the merge request target branch to the project default branch' do
- expect(subject[:merge_request].target_branch).to eq(project.default_branch)
+ it 'does not create merge request' do
+ expect { service.execute }.to change(target_project.merge_requests, :count).by(0)
+ end
+ end
+
+ context 'target project is a fork of project project' do
+ let(:target_project) { fork_project(project, user, repository: true) }
+
+ it_behaves_like 'a service that creates a merge request from an issue'
+
+ it 'sets the merge request title to: "WIP: $issue-branch-name' do
+ result = service.execute
+
+ expect(result[:merge_request].title).to eq("WIP: #{issue.to_branch_name.titleize.humanize}")
end
end
end
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 93fe3290d8b..97377c2f560 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -454,16 +454,32 @@ describe SystemNoteService do
end
describe '.new_issue_branch' do
- subject { described_class.new_issue_branch(noteable, project, author, "1-mepmep") }
+ let(:branch) { '1-mepmep' }
- it_behaves_like 'a system note' do
- let(:action) { 'branch' }
- end
+ subject { described_class.new_issue_branch(noteable, project, author, branch, branch_project: branch_project) }
- context 'when a branch is created from the new branch button' do
- it 'sets the note text' do
- expect(subject.note).to start_with("created branch [`1-mepmep`]")
+ shared_examples_for 'a system note for new issue branch' do
+ it_behaves_like 'a system note' do
+ let(:action) { 'branch' }
end
+
+ context 'when a branch is created from the new branch button' do
+ it 'sets the note text' do
+ expect(subject.note).to start_with("created branch [`#{branch}`]")
+ end
+ end
+ end
+
+ context 'branch_project is set' do
+ let(:branch_project) { create(:project, :repository) }
+
+ it_behaves_like 'a system note for new issue branch'
+ end
+
+ context 'branch_project is not set' do
+ let(:branch_project) { nil }
+
+ it_behaves_like 'a system note for new issue branch'
end
end
@@ -477,7 +493,7 @@ describe SystemNoteService do
end
it 'sets the new merge request note text' do
- expect(subject.note).to eq("created merge request #{merge_request.to_reference} to address this issue")
+ expect(subject.note).to eq("created merge request #{merge_request.to_reference(project)} to address this issue")
end
end
diff --git a/spec/support/helpers/email_helpers.rb b/spec/support/helpers/email_helpers.rb
index a7175491fa0..ed049daba80 100644
--- a/spec/support/helpers/email_helpers.rb
+++ b/spec/support/helpers/email_helpers.rb
@@ -37,19 +37,8 @@ module EmailHelpers
ActionMailer::Base.deliveries.find { |d| d.to.include?(user.notification_email) }
end
- def have_referable_subject(referable, include_project: true, include_group: false, reply: false)
- context = []
-
- context << referable.project.name if include_project && referable.project
- context << referable.project.group.name if include_group && referable.project.group
-
- prefix =
- if context.any?
- context.join(' | ') + ' | '
- else
- ''
- end
-
+ def have_referable_subject(referable, include_project: true, reply: false)
+ prefix = (include_project && referable.project ? "#{referable.project.name} | " : '').freeze
prefix = "Re: #{prefix}" if reply
suffix = "#{referable.title} (#{referable.to_reference})"
diff --git a/spec/tasks/migrate/schema_check_rake_spec.rb b/spec/tasks/migrate/schema_check_rake_spec.rb
index 72fb1363dfb..1097a43cd8a 100644
--- a/spec/tasks/migrate/schema_check_rake_spec.rb
+++ b/spec/tasks/migrate/schema_check_rake_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require 'rake'
-describe 'schema_version_check rake task', :quarantine do
+describe 'schema_version_check rake task' do
include StubENV
before :all do
@@ -15,8 +15,6 @@ describe 'schema_version_check rake task', :quarantine do
end
before do
- # Stub out db tasks
- allow(ActiveRecord::Tasks::DatabaseTasks).to receive(:migrate).and_return(true)
allow(ActiveRecord::Migrator).to receive(:current_version).and_return(Gitlab::Database::MIN_SCHEMA_VERSION)
# Ensure our check can re-run each time
@@ -24,23 +22,23 @@ describe 'schema_version_check rake task', :quarantine do
end
it 'allows migrations on databases meeting the min schema version requirement' do
- expect { run_rake_task('db:migrate') }.not_to raise_error
+ expect { run_rake_task('schema_version_check') }.not_to raise_error
end
it 'raises an error when schema version is too old to migrate' do
allow(ActiveRecord::Migrator).to receive(:current_version).and_return(25)
- expect { run_rake_task('db:migrate') }.to raise_error(RuntimeError, /current database version is too old to be migrated/)
+ expect { run_rake_task('schema_version_check') }.to raise_error(RuntimeError, /current database version is too old to be migrated/)
end
it 'skips running validation when passed the skip env variable' do
stub_env('SKIP_SCHEMA_VERSION_CHECK', 'true')
allow(ActiveRecord::Migrator).to receive(:current_version).and_return(25)
- expect { run_rake_task('db:migrate') }.not_to raise_error
+ expect { run_rake_task('schema_version_check') }.not_to raise_error
end
it 'allows migrations on fresh databases' do
allow(ActiveRecord::Migrator).to receive(:current_version).and_return(0)
- expect { run_rake_task('db:migrate') }.not_to raise_error
+ expect { run_rake_task('schema_version_check') }.not_to raise_error
end
def run_rake_task(task_name)