summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/cng.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml7
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/test-metadata.gitlab-ci.yml2
-rw-r--r--.ruby-version2
-rw-r--r--app/assets/javascripts/main.js2
-rw-r--r--app/assets/javascripts/notes/stores/actions.js17
-rw-r--r--app/assets/javascripts/notes/stores/utils.js7
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js42
-rw-r--r--app/assets/javascripts/profile/profile.js11
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue4
-rw-r--r--app/assets/stylesheets/framework/ci_variable_list.scss1
-rw-r--r--app/assets/stylesheets/framework/header.scss7
-rw-r--r--app/assets/stylesheets/framework/modal.scss6
-rw-r--r--app/assets/stylesheets/pages/notes.scss5
-rw-r--r--app/controllers/profiles/preferences_controller.rb4
-rw-r--r--app/controllers/profiles_controller.rb7
-rw-r--r--app/graphql/gitlab_schema.rb42
-rw-r--r--app/models/project_services/jira_service.rb1
-rw-r--r--app/models/repository.rb2
-rw-r--r--app/models/user.rb3
-rw-r--r--app/models/user_preference.rb4
-rw-r--r--app/policies/project_policy.rb4
-rw-r--r--app/services/git/branch_push_service.rb2
-rw-r--r--app/services/members/create_service.rb11
-rw-r--r--app/services/projects/after_import_service.rb2
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_link_list_service.rb12
-rw-r--r--app/services/projects/repository_languages_service.rb2
-rw-r--r--app/views/admin/projects/show.html.haml2
-rw-r--r--app/views/ci/variables/_index.html.haml1
-rw-r--r--app/views/ci/variables/_variable_header.html.haml16
-rw-r--r--app/views/ci/variables/_variable_row.html.haml18
-rw-r--r--app/views/groups/group_members/index.html.haml2
-rw-r--r--app/views/layouts/_piwik.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml2
-rw-r--r--app/views/profiles/preferences/show.html.haml26
-rw-r--r--app/views/profiles/show.html.haml26
-rw-r--r--app/views/repository_check_mailer/notify.text.haml2
-rw-r--r--app/views/shared/issuable/form/_contribution.html.haml2
-rw-r--r--app/workers/detect_repository_languages_worker.rb7
-rw-r--r--changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml5
-rw-r--r--changelogs/unreleased/53973-fix-subpixel-border-issue.yml5
-rw-r--r--changelogs/unreleased/57654-add-time-preferences-for-user-fe.yml5
-rw-r--r--changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml5
-rw-r--r--changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml5
-rw-r--r--changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml5
-rw-r--r--changelogs/unreleased/61494-set-status-modal-visual-bugs.yml5
-rw-r--r--changelogs/unreleased/61550-next-badge.yml5
-rw-r--r--changelogs/unreleased/add-warning-to-backup-rake-task.yml5
-rw-r--r--changelogs/unreleased/antonyliu-i18n-user-profile.yml5
-rw-r--r--changelogs/unreleased/sh-fix-invited-members.yml5
-rw-r--r--changelogs/unreleased/sh-fix-lfs-download-errors.yml5
-rw-r--r--changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml5
-rw-r--r--changelogs/unreleased/winh-notes-error-handling.yml5
-rw-r--r--config/initializers/01_secret_token.rb18
-rw-r--r--db/migrate/20190325105715_add_fields_to_user_preferences.rb24
-rw-r--r--db/migrate/20190412155659_add_merge_request_blocks.rb25
-rw-r--r--db/schema.rb14
-rw-r--r--doc/administration/integration/plantuml.md3
-rw-r--r--doc/ci/caching/index.md2
-rw-r--r--doc/development/architecture.md179
-rw-r--r--doc/install/installation.md6
-rw-r--r--doc/install/requirements.md7
-rw-r--r--doc/update/mysql_to_postgresql.md16
-rw-r--r--doc/update/upgrading_from_source.md6
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md3
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md2
-rw-r--r--doc/user/project/pages/lets_encrypt_for_gitlab_pages.md4
-rw-r--r--lib/gitlab/bitbucket_import/importer.rb2
-rw-r--r--lib/tasks/gitlab/backup.rake8
-rw-r--r--locale/gitlab.pot75
-rw-r--r--qa/Dockerfile2
-rw-r--r--spec/controllers/projects/graphs_controller_spec.rb15
-rw-r--r--spec/features/dashboard/user_filters_projects_spec.rb56
-rw-r--r--spec/features/issuables/markdown_references/jira_spec.rb2
-rw-r--r--spec/features/profiles/user_edit_preferences_spec.rb32
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb32
-rw-r--r--spec/frontend/notes/components/discussion_notes_spec.js7
-rw-r--r--spec/frontend/notes/stores/utils_spec.js17
-rw-r--r--spec/graphql/gitlab_schema_spec.rb86
-rw-r--r--spec/initializers/secret_token_spec.rb11
-rw-r--r--spec/javascripts/ci_variable_list/ajax_variable_list_spec.js2
-rw-r--r--spec/javascripts/fixtures/abuse_reports.rb3
-rw-r--r--spec/javascripts/fixtures/admin_users.rb3
-rw-r--r--spec/javascripts/fixtures/application_settings.rb3
-rw-r--r--spec/javascripts/fixtures/autocomplete_sources.rb3
-rw-r--r--spec/javascripts/fixtures/balsamiq.rb18
-rw-r--r--spec/javascripts/fixtures/blob.rb3
-rw-r--r--spec/javascripts/fixtures/boards.rb3
-rw-r--r--spec/javascripts/fixtures/branches.rb3
-rw-r--r--spec/javascripts/fixtures/clusters.rb3
-rw-r--r--spec/javascripts/fixtures/commit.rb3
-rw-r--r--spec/javascripts/fixtures/deploy_keys.rb3
-rw-r--r--spec/javascripts/fixtures/groups.rb6
-rw-r--r--spec/javascripts/fixtures/issues.rb25
-rw-r--r--spec/javascripts/fixtures/jobs.rb6
-rw-r--r--spec/javascripts/fixtures/labels.rb6
-rw-r--r--spec/javascripts/fixtures/merge_requests.rb43
-rw-r--r--spec/javascripts/fixtures/merge_requests_diffs.rb15
-rw-r--r--spec/javascripts/fixtures/pdf.rb18
-rw-r--r--spec/javascripts/fixtures/pipeline_schedules.rb6
-rw-r--r--spec/javascripts/fixtures/pipelines.rb3
-rw-r--r--spec/javascripts/fixtures/projects.rb15
-rw-r--r--spec/javascripts/fixtures/prometheus_service.rb3
-rw-r--r--spec/javascripts/fixtures/raw.rb27
-rw-r--r--spec/javascripts/fixtures/search.rb3
-rw-r--r--spec/javascripts/fixtures/services.rb3
-rw-r--r--spec/javascripts/fixtures/sessions.rb3
-rw-r--r--spec/javascripts/fixtures/snippet.rb3
-rw-r--r--spec/javascripts/fixtures/todos.rb6
-rw-r--r--spec/javascripts/fixtures/u2f.rb6
-rw-r--r--spec/javascripts/notes/stores/actions_spec.js45
-rw-r--r--spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js77
-rw-r--r--spec/lib/gitlab/bitbucket_import/importer_spec.rb40
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb4
-rw-r--r--spec/models/project_services/jira_service_spec.rb7
-rw-r--r--spec/models/user_preference_spec.rb6
-rw-r--r--spec/requests/api/graphql/gitlab_schema_spec.rb40
-rw-r--r--spec/services/members/create_service_spec.rb13
-rw-r--r--spec/services/projects/after_import_service_spec.rb2
-rw-r--r--spec/services/projects/detect_repository_languages_service_spec.rb2
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb20
-rw-r--r--spec/services/projects/repository_languages_service_spec.rb4
-rw-r--r--spec/services/users/update_service_spec.rb9
-rw-r--r--spec/spec_helper.rb2
-rw-r--r--spec/support/features/variable_list_shared_examples.rb36
-rw-r--r--spec/support/helpers/graphql_helpers.rb6
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb18
-rw-r--r--spec/support/helpers/project_forks_helper.rb23
-rw-r--r--spec/workers/detect_repository_languages_worker_spec.rb11
134 files changed, 1160 insertions, 505 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 44beccd966a..c971df3ba5f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-9.6-graphicsmagick-1.3.29"
+image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-9.6-graphicsmagick-1.3.29"
variables:
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
diff --git a/.gitlab/ci/cng.gitlab-ci.yml b/.gitlab/ci/cng.gitlab-ci.yml
index c384bcdcdfc..d624e8d09f6 100644
--- a/.gitlab/ci/cng.gitlab-ci.yml
+++ b/.gitlab/ci/cng.gitlab-ci.yml
@@ -1,5 +1,5 @@
cloud-native-image:
- image: ruby:2.5-alpine
+ image: ruby:2.6-alpine
before_script: []
dependencies: []
stage: post-test
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index fbf8925e30a..986ba7558d5 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -16,7 +16,7 @@
gitlab:assets:compile:
<<: *assets-compile-cache
extends: .dedicated-no-docs-pull-cache-job
- image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-git-2.21-chrome-73.0-node-8.x-yarn-1.12-graphicsmagick-1.3.29-docker-18.06.1
+ image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-git-2.21-chrome-73.0-node-8.x-yarn-1.12-graphicsmagick-1.3.29-docker-18.06.1
dependencies:
- setup-test-env
services:
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index 466c47b37c7..cf87f5eb39c 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -9,7 +9,7 @@
- gitlab-org
.default-cache: &default-cache
- key: "debian-stretch-ruby-2.5.3-node-10.x"
+ key: "debian-stretch-ruby-2.6.3-node-10.x"
paths:
- vendor/ruby
- .yarn-cache/
@@ -47,7 +47,7 @@
.single-script-job-dedicated-runner:
extends: .dedicated-runner
- image: ruby:2.5-alpine
+ image: ruby:2.6-alpine
stage: test
cache: {}
dependencies: []
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index 85c6409186e..122ed622ee2 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -1,5 +1,5 @@
package-and-qa:
- image: ruby:2.5-alpine
+ image: ruby:2.6-alpine
stage: qa
when: manual
before_script: []
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 35c5f67427e..29534e40a14 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -86,7 +86,7 @@
.rspec-metadata-pg-10: &rspec-metadata-pg-10
<<: *rspec-metadata
<<: *use-pg-10
- image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-10-graphicsmagick-1.3.29"
+ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-10-graphicsmagick-1.3.29"
.rspec-metadata-mysql: &rspec-metadata-mysql
<<: *rspec-metadata
@@ -108,7 +108,8 @@
- git fetch https://gitlab.com/gitlab-org/gitlab-ce.git v9.3.0
- git checkout -f FETCH_HEAD
- sed -i "s/gem 'oj', '~> 2.17.4'//" Gemfile
- - bundle update google-protobuf grpc
+ - sed -i "s/gem 'bootsnap', '~> 1.0.0'/gem 'bootsnap'/" Gemfile
+ - bundle update google-protobuf grpc bootsnap
- bundle install $BUNDLE_INSTALL_FLAGS
- date
- cp config/gitlab.yml.example config/gitlab.yml
@@ -183,7 +184,7 @@ static-analysis:
script:
- scripts/static-analysis
cache:
- key: "debian-stretch-ruby-2.5.3-node-10.x-and-rubocop"
+ key: "debian-stretch-ruby-2.6.3-node-10.x-and-rubocop"
paths:
- vendor/ruby
- .yarn-cache/
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index ae16549ef6b..3a024c44fe2 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -54,7 +54,7 @@ build-qa-image:
- time docker push ${QA_IMAGE}
.review-build-cng-base: &review-build-cng-base
- image: ruby:2.5-alpine
+ image: ruby:2.6-alpine
stage: test
when: manual
before_script:
diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml
index 3ba7af956b5..4b595083ec6 100644
--- a/.gitlab/ci/test-metadata.gitlab-ci.yml
+++ b/.gitlab/ci/test-metadata.gitlab-ci.yml
@@ -56,7 +56,7 @@ update-tests-metadata:
flaky-examples-check:
extends: .dedicated-runner
- image: ruby:2.5-alpine
+ image: ruby:2.6-alpine
services: []
before_script: []
variables:
diff --git a/.ruby-version b/.ruby-version
index aedc15bb0c6..ec1cf33c3f6 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.5.3
+2.6.3
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index b503c746801..213d5c6521a 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -147,7 +147,7 @@ function deferredInitialisation() {
const canaryBadge = document.querySelector('.js-canary-badge');
const canaryLink = document.querySelector('.js-canary-link');
if (canaryBadge) {
- canaryBadge.classList.remove('hidden');
+ canaryBadge.classList.add('hidden');
}
if (canaryLink) {
canaryLink.classList.add('hidden');
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index bac124be34c..63658d49a05 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -268,11 +268,20 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
const { errors } = res;
const commandsChanges = res.commands_changes;
- if (hasQuickActions && errors && Object.keys(errors).length) {
- eTagPoll.makeRequest();
+ if (errors && Object.keys(errors).length) {
+ /*
+ The following reply means that quick actions have been successfully applied:
- $('.js-gfm-input').trigger('clear-commands-cache.atwho');
- Flash(__('Commands applied'), 'notice', noteData.flashContainer);
+ {"commands_changes":{},"valid":false,"errors":{"commands_only":["Commands applied"]}}
+ */
+ if (hasQuickActions) {
+ eTagPoll.makeRequest();
+
+ $('.js-gfm-input').trigger('clear-commands-cache.atwho');
+ Flash(__('Commands applied'), 'notice', noteData.flashContainer);
+ } else {
+ throw new Error(__('Failed to save comment!'));
+ }
}
if (commandsChanges) {
diff --git a/app/assets/javascripts/notes/stores/utils.js b/app/assets/javascripts/notes/stores/utils.js
index 029fde348fb..ed4cef4a917 100644
--- a/app/assets/javascripts/notes/stores/utils.js
+++ b/app/assets/javascripts/notes/stores/utils.js
@@ -2,7 +2,8 @@ import AjaxCache from '~/lib/utils/ajax_cache';
import { trimFirstCharOfLineContent } from '~/diffs/store/utils';
import { sprintf, __ } from '~/locale';
-const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
+// factory function because global flag makes RegExp stateful
+const createQuickActionsRegex = () => /^\/\w+.*$/gm;
export const findNoteObjectById = (notes, id) => notes.filter(n => n.id === id)[0];
@@ -27,9 +28,9 @@ export const getQuickActionText = note => {
return text;
};
-export const hasQuickActions = note => REGEX_QUICK_ACTIONS.test(note);
+export const hasQuickActions = note => createQuickActionsRegex().test(note);
-export const stripQuickActions = note => note.replace(REGEX_QUICK_ACTIONS, '').trim();
+export const stripQuickActions = note => note.replace(createQuickActionsRegex(), '').trim();
export const prepareDiffLines = diffLines =>
diffLines.map(line => ({ ...trimFirstCharOfLineContent(line) }));
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
index c1f6edf2f27..a20a0526f12 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
@@ -1,4 +1,10 @@
-const defaultTimezone = 'UTC';
+const defaultTimezone = { name: 'UTC', offset: 0 };
+const defaults = {
+ $inputEl: null,
+ $dropdownEl: null,
+ onSelectTimezone: null,
+ displayFormat: item => item.name,
+};
export const formatUtcOffset = offset => {
const parsed = parseInt(offset, 10);
@@ -11,23 +17,28 @@ export const formatUtcOffset = offset => {
export const formatTimezone = item => `[UTC ${formatUtcOffset(item.offset)}] ${item.name}`;
-const defaults = {
- $inputEl: null,
- $dropdownEl: null,
- onSelectTimezone: null,
+export const findTimezoneByIdentifier = (tzList = [], identifier = null) => {
+ if (tzList && tzList.length && identifier && identifier.length) {
+ return tzList.find(tz => tz.identifier === identifier) || null;
+ }
+ return null;
};
export default class TimezoneDropdown {
- constructor({ $dropdownEl, $inputEl, onSelectTimezone } = defaults) {
+ constructor({ $dropdownEl, $inputEl, onSelectTimezone, displayFormat } = defaults) {
this.$dropdown = $dropdownEl;
this.$dropdownToggle = this.$dropdown.find('.dropdown-toggle-text');
this.$input = $inputEl;
this.timezoneData = this.$dropdown.data('data');
+ this.onSelectTimezone = onSelectTimezone;
+ this.displayFormat = displayFormat || defaults.displayFormat;
+
+ this.initialTimezone =
+ findTimezoneByIdentifier(this.timezoneData, this.$input.val()) || defaultTimezone;
+
this.initDefaultTimezone();
this.initDropdown();
-
- this.onSelectTimezone = onSelectTimezone;
}
initDropdown() {
@@ -35,7 +46,7 @@ export default class TimezoneDropdown {
data: this.timezoneData,
filterable: true,
selectable: true,
- toggleLabel: item => item.name,
+ toggleLabel: this.displayFormat,
search: {
fields: ['name'],
},
@@ -43,20 +54,17 @@ export default class TimezoneDropdown {
text: item => formatTimezone(item),
});
- this.setDropdownToggle();
+ this.setDropdownToggle(this.displayFormat(this.initialTimezone));
}
initDefaultTimezone() {
- const initialValue = this.$input.val();
-
- if (!initialValue) {
- this.$input.val(defaultTimezone);
+ if (!this.$input.val()) {
+ this.$input.val(defaultTimezone.name);
}
}
- setDropdownToggle() {
- const initialValue = this.$input.val();
- this.$dropdownToggle.text(initialValue);
+ setDropdownToggle(dropdownText) {
+ this.$dropdownToggle.text(dropdownText);
}
updateInputValue({ selectedObj, e }) {
diff --git a/app/assets/javascripts/profile/profile.js b/app/assets/javascripts/profile/profile.js
index deacff5abe7..6e3800021b4 100644
--- a/app/assets/javascripts/profile/profile.js
+++ b/app/assets/javascripts/profile/profile.js
@@ -2,6 +2,9 @@ import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import flash from '../flash';
import { parseBoolean } from '~/lib/utils/common_utils';
+import TimezoneDropdown, {
+ formatTimezone,
+} from '~/pages/projects/pipeline_schedules/shared/components/timezone_dropdown';
export default class Profile {
constructor({ form } = {}) {
@@ -10,6 +13,14 @@ export default class Profile {
this.setRepoRadio();
this.bindEvents();
this.initAvatarGlCrop();
+
+ this.$inputEl = $('#user_timezone');
+
+ this.timezoneDropdown = new TimezoneDropdown({
+ $inputEl: this.$inputEl,
+ $dropdownEl: $('.js-timezone-dropdown'),
+ displayFormat: selectedItem => formatTimezone(selectedItem),
+ });
}
initAvatarGlCrop() {
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
index c0659a0173a..10e2c8453e2 100644
--- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -178,7 +178,7 @@ export default {
/>
<div ref="userStatusForm" class="form-group position-relative m-0">
<div class="input-group">
- <span class="input-group-btn">
+ <span class="input-group-prepend">
<button
ref="toggleEmojiMenuButton"
v-gl-tooltip.bottom
@@ -211,7 +211,7 @@ export default {
@keyup.enter.prevent
@click="hideEmojiMenu"
/>
- <span v-show="isDirty" class="input-group-btn">
+ <span v-show="isDirty" class="input-group-append">
<button
v-gl-tooltip.bottom
:title="s__('SetStatusModal|Clear status')"
diff --git a/app/assets/stylesheets/framework/ci_variable_list.scss b/app/assets/stylesheets/framework/ci_variable_list.scss
index d9b0e4558ad..28d7492b99c 100644
--- a/app/assets/stylesheets/framework/ci_variable_list.scss
+++ b/app/assets/stylesheets/framework/ci_variable_list.scss
@@ -47,6 +47,7 @@
display: flex;
align-items: flex-start;
width: 100%;
+ padding-bottom: $gl-padding;
@include media-breakpoint-down(xs) {
display: block;
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index a6179e2a96e..a57cd6737f8 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -581,10 +581,15 @@
.emoji-menu-toggle-button {
@include emoji-menu-toggle-button;
+ padding: $gl-vert-padding $gl-btn-padding;
}
.input-group {
- height: 34px;
+ &,
+ .input-group-prepend,
+ .input-group-append {
+ height: $input-height;
+ }
}
}
diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss
index 323a3dbecd5..e2bb1eb67c0 100644
--- a/app/assets/stylesheets/framework/modal.scss
+++ b/app/assets/stylesheets/framework/modal.scss
@@ -66,12 +66,6 @@
margin-top: $grid-size;
}
}
-
- @include media-breakpoint-up(sm) {
- .btn:nth-child(1) {
- margin-left: auto;
- }
- }
}
body.modal-open {
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 09f75cd827f..f2b67a693c3 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -471,6 +471,11 @@ $note-form-margin-left: 72px;
vertical-align: top;
white-space: normal;
+ // Fixes subpixel rounding issue https://gitlab.com/gitlab-org/gitlab-ce/issues/53973
+ // background-color is needed for dark code preference
+ padding-bottom: 1px;
+ background-color: $white-light;
+
&.parallel {
border-width: 1px;
diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb
index 0e30df1b15b..62f98d9e549 100644
--- a/app/controllers/profiles/preferences_controller.rb
+++ b/app/controllers/profiles/preferences_controller.rb
@@ -44,7 +44,9 @@ class Profiles::PreferencesController < Profiles::ApplicationController
:project_view,
:theme_id,
:first_day_of_week,
- :preferred_language
+ :preferred_language,
+ :time_display_relative,
+ :time_format_in_24h
]
end
end
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index b9c52618d4b..1d16ddb1608 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -15,7 +15,7 @@ class ProfilesController < Profiles::ApplicationController
result = Users::UpdateService.new(current_user, user_params.merge(user: @user)).execute
if result[:status] == :success
- message = "Profile was successfully updated"
+ message = s_("Profiles|Profile was successfully updated")
format.html { redirect_back_or_default(default: { action: 'show' }, options: { notice: message }) }
format.json { render json: { message: message } }
@@ -31,7 +31,7 @@ class ProfilesController < Profiles::ApplicationController
user.reset_incoming_email_token!
end
- flash[:notice] = "Incoming email token was successfully reset"
+ flash[:notice] = s_("Profiles|Incoming email token was successfully reset")
redirect_to profile_personal_access_tokens_path
end
@@ -41,7 +41,7 @@ class ProfilesController < Profiles::ApplicationController
user.reset_feed_token!
end
- flash[:notice] = 'Feed token was successfully reset'
+ flash[:notice] = s_('Profiles|Feed token was successfully reset')
redirect_to profile_personal_access_tokens_path
end
@@ -106,6 +106,7 @@ class ProfilesController < Profiles::ApplicationController
:organization,
:private_profile,
:include_private_contributions,
+ :timezone,
status: [:emoji, :message]
)
end
diff --git a/app/graphql/gitlab_schema.rb b/app/graphql/gitlab_schema.rb
index a12568d5d31..897e12c1b56 100644
--- a/app/graphql/gitlab_schema.rb
+++ b/app/graphql/gitlab_schema.rb
@@ -7,6 +7,9 @@ class GitlabSchema < GraphQL::Schema
AUTHENTICATED_COMPLEXITY = 250
ADMIN_COMPLEXITY = 300
+ ANONYMOUS_MAX_DEPTH = 10
+ AUTHENTICATED_MAX_DEPTH = 15
+
use BatchLoader::GraphQL
use Gitlab::Graphql::Authorize
use Gitlab::Graphql::Present
@@ -23,21 +26,36 @@ class GitlabSchema < GraphQL::Schema
mutation(Types::MutationType)
- def self.execute(query_str = nil, **kwargs)
- kwargs[:max_complexity] ||= max_query_complexity(kwargs[:context])
+ class << self
+ def execute(query_str = nil, **kwargs)
+ kwargs[:max_complexity] ||= max_query_complexity(kwargs[:context])
+ kwargs[:max_depth] ||= max_query_depth(kwargs[:context])
- super(query_str, **kwargs)
- end
+ super(query_str, **kwargs)
+ end
+
+ private
+
+ def max_query_complexity(ctx)
+ current_user = ctx&.fetch(:current_user, nil)
+
+ if current_user&.admin
+ ADMIN_COMPLEXITY
+ elsif current_user
+ AUTHENTICATED_COMPLEXITY
+ else
+ DEFAULT_MAX_COMPLEXITY
+ end
+ end
- def self.max_query_complexity(ctx)
- current_user = ctx&.fetch(:current_user, nil)
+ def max_query_depth(ctx)
+ current_user = ctx&.fetch(:current_user, nil)
- if current_user&.admin
- ADMIN_COMPLEXITY
- elsif current_user
- AUTHENTICATED_COMPLEXITY
- else
- DEFAULT_MAX_COMPLEXITY
+ if current_user
+ AUTHENTICATED_MAX_DEPTH
+ else
+ ANONYMOUS_MAX_DEPTH
+ end
end
end
end
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index ebf28dc842c..7b4832b84a8 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -265,6 +265,7 @@ class JiraService < IssueTrackerService
def find_remote_link(issue, url)
links = jira_request { issue.remotelink.all }
+ return unless links
links.find { |link| link.object["url"] == url }
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index be17b54ff12..1c02e68f2f6 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -465,7 +465,7 @@ class Repository
def after_import
expire_content_cache
- DetectRepositoryLanguagesWorker.perform_async(project.id, project.owner.id)
+ DetectRepositoryLanguagesWorker.perform_async(project.id)
end
# Runs code after a new commit has been pushed.
diff --git a/app/models/user.rb b/app/models/user.rb
index 4a1bf5514fe..60f69659a6b 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -230,6 +230,9 @@ class User < ApplicationRecord
delegate :notes_filter_for, to: :user_preference
delegate :set_notes_filter, to: :user_preference
delegate :first_day_of_week, :first_day_of_week=, to: :user_preference
+ delegate :timezone, :timezone=, to: :user_preference
+ delegate :time_display_relative, :time_display_relative=, to: :user_preference
+ delegate :time_format_in_24h, :time_format_in_24h=, to: :user_preference
accepts_nested_attributes_for :user_preference, update_only: true
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
index 282b192167f..f1326f4c8cb 100644
--- a/app/models/user_preference.rb
+++ b/app/models/user_preference.rb
@@ -10,6 +10,10 @@ class UserPreference < ApplicationRecord
validates :issue_notes_filter, :merge_request_notes_filter, inclusion: { in: NOTES_FILTERS.values }, presence: true
+ default_value_for :timezone, value: Time.zone.tzinfo.name, allows_nil: false
+ default_value_for :time_display_relative, value: true, allows_nil: false
+ default_value_for :time_format_in_24h, value: false, allows_nil: false
+
class << self
def notes_filters
{
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 76544249688..3218c04b219 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -488,6 +488,10 @@ class ProjectPolicy < BasePolicy
def team_access_level
return -1 if @user.nil?
+ lookup_access_level!
+ end
+
+ def lookup_access_level!
# NOTE: max_member_access has its own cache
project.team.max_member_access(@user.id)
end
diff --git a/app/services/git/branch_push_service.rb b/app/services/git/branch_push_service.rb
index da053ce80c7..abf11f253f6 100644
--- a/app/services/git/branch_push_service.rb
+++ b/app/services/git/branch_push_service.rb
@@ -48,7 +48,7 @@ module Git
def enqueue_detect_repository_languages
return unless default_branch?
- DetectRepositoryLanguagesWorker.perform_async(project.id, current_user.id)
+ DetectRepositoryLanguagesWorker.perform_async(project.id)
end
# Only stop environments if the ref is a branch that is being deleted
diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb
index f6bad74736c..d6b17ec10be 100644
--- a/app/services/members/create_service.rb
+++ b/app/services/members/create_service.rb
@@ -23,7 +23,16 @@ module Members
members.each do |member|
if member.errors.any?
- errors << "#{member.user.username}: #{member.errors.full_messages.to_sentence}"
+ current_error =
+ # Invited users may not have an associated user
+ if member.user.present?
+ "#{member.user.username}: "
+ else
+ ""
+ end
+
+ current_error += member.errors.full_messages.to_sentence
+ errors << current_error
else
after_execute(member: member)
end
diff --git a/app/services/projects/after_import_service.rb b/app/services/projects/after_import_service.rb
index afb9048e87b..bbdde4408d2 100644
--- a/app/services/projects/after_import_service.rb
+++ b/app/services/projects/after_import_service.rb
@@ -9,7 +9,7 @@ module Projects
end
def execute
- Projects::HousekeepingService.new(@project, :gc).execute do
+ Projects::HousekeepingService.new(@project).execute do
repository.delete_all_refs_except(RESERVED_REF_PREFIXES)
end
rescue Projects::HousekeepingService::LeaseTaken => e
diff --git a/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb b/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
index 05974948505..9b72480d18b 100644
--- a/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb
@@ -37,7 +37,17 @@ module Projects
raise DownloadLinksError, response.message unless response.success?
- parse_response_links(response['objects'])
+ # Since the LFS Batch API may return a Content-Ttpe of
+ # application/vnd.git-lfs+json
+ # (https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md#requests),
+ # HTTParty does not know this is actually JSON.
+ data = JSON.parse(response.body)
+
+ raise DownloadLinksError, "LFS Batch API did return any objects" unless data.is_a?(Hash) && data.key?('objects')
+
+ parse_response_links(data['objects'])
+ rescue JSON::ParserError
+ raise DownloadLinksError, "LFS Batch API response is not JSON"
end
def parse_response_links(objects_response)
diff --git a/app/services/projects/repository_languages_service.rb b/app/services/projects/repository_languages_service.rb
index e75851c7da4..05f43c2264b 100644
--- a/app/services/projects/repository_languages_service.rb
+++ b/app/services/projects/repository_languages_service.rb
@@ -11,7 +11,7 @@ module Projects
def perform_language_detection
if persisted_repository_languages.blank?
- ::DetectRepositoryLanguagesWorker.perform_async(project.id, current_user.id)
+ ::DetectRepositoryLanguagesWorker.perform_async(project.id)
else
project.update_column(:detected_repository_languages, true)
end
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index bc34af88928..f016a157daf 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -100,6 +100,8 @@
%span.light archived:
%strong project is read-only
+ = render_if_exists "shared_runner_status", project: @project
+
%li
%span.light access:
%strong
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index dc9ccb6cc39..464b9faf282 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -10,6 +10,7 @@
.hide.alert.alert-danger.js-ci-variable-error-box
%ul.ci-variable-list
+ = render 'ci/variables/variable_header'
- @variables.each.each do |variable|
= render 'ci/variables/variable_row', form_field: 'variables', variable: variable
= render 'ci/variables/variable_row', form_field: 'variables'
diff --git a/app/views/ci/variables/_variable_header.html.haml b/app/views/ci/variables/_variable_header.html.haml
new file mode 100644
index 00000000000..d3b7a5ae883
--- /dev/null
+++ b/app/views/ci/variables/_variable_header.html.haml
@@ -0,0 +1,16 @@
+- only_key_value = local_assigns.fetch(:only_key_value, false)
+
+%li.ci-variable-row.m-0.d-none.d-sm-block
+ .d-flex.w-100.align-items-center.pb-2
+ .bold.table-section.section-15.append-right-10
+ = s_('CiVariables|Type')
+ .bold.table-section.section-15.append-right-10
+ = s_('CiVariables|Key')
+ .bold.table-section.section-15.append-right-10
+ = s_('CiVariables|Value')
+ - unless only_key_value
+ .bold.table-section.section-20
+ = s_('CiVariables|State')
+ .bold.table-section.section-20
+ = s_('CiVariables|Masked')
+ = render_if_exists 'ci/variables/environment_scope_header'
diff --git a/app/views/ci/variables/_variable_row.html.haml b/app/views/ci/variables/_variable_row.html.haml
index 37257b3aa1c..b4930b41c09 100644
--- a/app/views/ci/variables/_variable_row.html.haml
+++ b/app/views/ci/variables/_variable_row.html.haml
@@ -20,18 +20,18 @@
- masked_input_name = "#{form_field}[variables_attributes][][masked]"
%li.js-row.ci-variable-row{ data: { is_persisted: "#{!id.nil?}" } }
- .ci-variable-row-body
+ .ci-variable-row-body.border-bottom
%input.js-ci-variable-input-id{ type: "hidden", name: id_input_name, value: id }
%input.js-ci-variable-input-destroy{ type: "hidden", name: destroy_input_name }
- %select.js-ci-variable-input-variable-type.ci-variable-body-item.form-control.select-control{ name: variable_type_input_name }
+ %select.js-ci-variable-input-variable-type.ci-variable-body-item.form-control.select-control.table-section.section-15{ name: variable_type_input_name }
= options_for_select(ci_variable_type_options, variable_type)
- %input.js-ci-variable-input-key.ci-variable-body-item.qa-ci-variable-input-key.form-control{ type: "text",
+ %input.js-ci-variable-input-key.ci-variable-body-item.qa-ci-variable-input-key.form-control.table-section.section-15{ type: "text",
name: key_input_name,
value: key,
placeholder: s_('CiVariables|Input variable key') }
- .ci-variable-body-item.gl-show-field-errors
+ .ci-variable-body-item.gl-show-field-errors.table-section.section-15.border-top-0.p-0
.form-control.js-secret-value-placeholder.qa-ci-variable-input-value{ class: ('hide' unless id) }
- = '*' * 20
+ = '*' * 17
%textarea.js-ci-variable-input-value.js-secret-value.qa-ci-variable-input-value.form-control{ class: ('hide' if id),
rows: 1,
name: value_input_name,
@@ -41,7 +41,7 @@
= s_("CiVariables|Cannot use Masked Variable with current value")
= link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'masked-variables'), target: '_blank', rel: 'noopener noreferrer'
- unless only_key_value
- .ci-variable-body-item.ci-variable-protected-item
+ .ci-variable-body-item.ci-variable-protected-item.table-section.section-20.mr-0.border-top-0
.append-right-default
= s_("CiVariable|Protected")
%button{ type: 'button',
@@ -55,7 +55,7 @@
%span.toggle-icon
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
= sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
- .ci-variable-body-item.ci-variable-masked-item
+ .ci-variable-body-item.ci-variable-masked-item.table-section.section-20.mr-0.border-top-0
.append-right-default
= s_("CiVariable|Masked")
%button{ type: 'button',
@@ -70,5 +70,5 @@
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
= sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
= render_if_exists 'ci/variables/environment_scope', form_field: form_field, variable: variable
- %button.js-row-remove-button.ci-variable-row-remove-button{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
- = icon('minus-circle')
+ %button.js-row-remove-button.ci-variable-row-remove-button.table-section.section-5.border-top-0{ type: 'button', 'aria-label': s_('CiVariables|Remove variable row') }
+ = icon('minus-circle')
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index 09cc713e3af..021c0b6c429 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -14,6 +14,8 @@
= render 'shared/members/requests', membership_source: @group, requesters: @requesters
+ = render_if_exists 'groups/group_members/ldap_sync'
+
.clearfix
%h5.member.existing-title
Existing members
diff --git a/app/views/layouts/_piwik.html.haml b/app/views/layouts/_piwik.html.haml
index a888e8ae187..473b14ce626 100644
--- a/app/views/layouts/_piwik.html.haml
+++ b/app/views/layouts/_piwik.html.haml
@@ -7,7 +7,7 @@
(function() {
var u="//#{extra_config.piwik_url}/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
- _paq.push(['setSiteId', #{extra_config.piwik_site_id}]);
+ _paq.push(['setSiteId', "#{extra_config.piwik_site_id}"]);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml
index 1e3bb8f1224..2061eac917f 100644
--- a/app/views/layouts/nav/sidebar/_profile.html.haml
+++ b/app/views/layouts/nav/sidebar/_profile.html.haml
@@ -4,7 +4,7 @@
= link_to profile_path, title: _('Profile Settings') do
.avatar-container.s40.settings-avatar
= image_tag avatar_icon_for_user(current_user, 40), class: "avatar s40 avatar-tile", alt: current_user.name
- .sidebar-context-title User Settings
+ .sidebar-context-title= _('User Settings')
%ul.sidebar-top-level-items
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path do
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index bfe1c3ddf33..58f2eb229ba 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -82,5 +82,31 @@
= f.label :first_day_of_week, class: 'label-bold' do
= _('First day of the week')
= f.select :first_day_of_week, first_day_of_week_choices_with_default, {}, class: 'form-control'
+ - if Feature.enabled?(:user_time_settings)
+ .col-sm-12
+ %hr
+ .col-lg-4.profile-settings-sidebar
+ %h4.prepend-top-0= s_('Preferences|Time preferences')
+ %p= s_('Preferences|These settings will update how dates and times are displayed for you.')
+ .col-lg-8
+ .form-group
+ %h5= s_('Preferences|Time format')
+ .checkbox-icon-inline-wrapper.form-check
+ - time_format_label = capture do
+ = s_('Preferences|Display time in 24-hour format')
+ = f.check_box :time_format_in_24h, class: 'form-check-input'
+ = f.label :time_format_in_24h do
+ = time_format_label
+ %h5= s_('Preferences|Time display')
+ .checkbox-icon-inline-wrapper.form-check
+ - time_display_label = capture do
+ = s_('Preferences|Use relative times')
+ = f.check_box :time_display_relative, class: 'form-check-input'
+ = f.label :time_display_relative do
+ = time_display_label
+ .text-muted
+ = s_('Preferences|For example: 30 mins ago.')
+ .col-lg-4.profile-settings-sidebar
+ .col-lg-8
.form-group
= f.submit _('Save changes'), class: 'btn btn-success'
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 02c750a92c3..917e7acc353 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -64,6 +64,18 @@
prepend: emoji_button,
append: reset_message_button,
placeholder: s_("Profiles|What's your status?")
+ - if Feature.enabled?(:user_time_settings)
+ %hr
+ .row.user-time-preferences
+ .col-lg-4.profile-settings-sidebar
+ %h4.prepend-top-0= s_("Profiles|Time settings")
+ %p= s_("Profiles|You can set your current timezone here")
+ .col-lg-8
+ -# TODO: might need an entry in user/profile.md to describe some of these settings
+ -# https://gitlab.com/gitlab-org/gitlab-ce/issues/60070
+ %h5= ("Time zone")
+ = dropdown_tag(_("Select a timezone"), options: { toggle_class: 'btn js-timezone-dropdown input-lg', title: _("Select a timezone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
+ %input.hidden{ :type => 'hidden', :id => 'user_timezone', :name => 'user[timezone]', value: @user.timezone }
%hr
.row
@@ -80,8 +92,8 @@
= f.text_field :name, required: true, readonly: true, wrapper: { class: 'col-md-9 qa-full-name' },
help: s_("Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you") % { provider_label: attribute_provider_label(:name) }
- else
- = f.text_field :name, label: 'Full name', required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you")
- = f.text_field :id, readonly: true, label: 'User ID', wrapper: { class: 'col-md-3' }
+ = f.text_field :name, label: s_('Profiles|Full name'), required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you")
+ = f.text_field :id, readonly: true, label: s_('Profiles|User ID'), wrapper: { class: 'col-md-3' }
= render_if_exists 'profiles/email_settings', form: f
= f.text_field :skype, class: 'input-md', placeholder: s_("Profiles|username")
@@ -91,18 +103,18 @@
- if @user.read_only_attribute?(:location)
= f.text_field :location, readonly: true, help: s_("Profiles|Your location was automatically set based on your %{provider_label} account") % { provider_label: attribute_provider_label(:location) }
- else
- = f.text_field :location, class: 'input-lg', placeholder: s_("Profiles|City, country")
- = f.text_field :organization, class: 'input-md', help: s_("Profiles|Who you represent or work for")
- = f.text_area :bio, rows: 4, maxlength: 250, help: s_("Profiles|Tell us about yourself in fewer than 250 characters")
+ = f.text_field :location, label: s_('Profiles|Location'), class: 'input-lg', placeholder: s_("Profiles|City, country")
+ = f.text_field :organization, label: s_('Profiles|Organization'), class: 'input-md', help: s_("Profiles|Who you represent or work for")
+ = f.text_area :bio, label: s_('Profiles|Bio'), rows: 4, maxlength: 250, help: s_("Profiles|Tell us about yourself in fewer than 250 characters")
%hr
- %h5= ("Private profile")
+ %h5= s_("Private profile")
.checkbox-icon-inline-wrapper
- private_profile_label = capture do
= s_("Profiles|Don't display activity-related personal information on your profiles")
= f.check_box :private_profile, label: private_profile_label, inline: true, wrapper_class: 'mr-0'
= link_to icon('question-circle'), help_page_path('user/profile/index.md', anchor: 'private-profile')
%h5= s_("Profiles|Private contributions")
- = f.check_box :include_private_contributions, label: 'Include private contributions on my profile', wrapper_class: 'mb-2', inline: true
+ = f.check_box :include_private_contributions, label: s_('Profiles|Include private contributions on my profile'), wrapper_class: 'mb-2', inline: true
.help-block
= s_("Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information")
.prepend-top-default.append-bottom-default
diff --git a/app/views/repository_check_mailer/notify.text.haml b/app/views/repository_check_mailer/notify.text.haml
index 6b64b337b0e..a2e04fa710f 100644
--- a/app/views/repository_check_mailer/notify.text.haml
+++ b/app/views/repository_check_mailer/notify.text.haml
@@ -3,3 +3,5 @@
= _("View details: %{details_url}") % { details_url: admin_projects_url(last_repository_check_failed: 1) }
= _("You are receiving this message because you are a GitLab administrator for %{url}.") % { url: Gitlab.config.gitlab.url }
+
+= render_if_exists 'repository_check_mailer/email_additional_text'
diff --git a/app/views/shared/issuable/form/_contribution.html.haml b/app/views/shared/issuable/form/_contribution.html.haml
index bc9a1edc39c..a78231b37ce 100644
--- a/app/views/shared/issuable/form/_contribution.html.haml
+++ b/app/views/shared/issuable/form/_contribution.html.haml
@@ -15,6 +15,6 @@
= form.check_box :allow_collaboration, disabled: !issuable.can_allow_collaboration?(current_user), class: 'form-check-input'
= form.label :allow_collaboration, class: 'form-check-label' do
= _('Allow commits from members who can merge to the target branch.')
- = link_to 'About this feature', help_page_path('user/project/merge_requests/allow_collaboration')
+ = link_to 'About this feature', help_page_path('user/project/merge_requests/allow_collaboration'), target: '_blank', rel: 'noopener noreferrer nofollow'
.form-text.text-muted
= allow_collaboration_unavailable_reason(issuable)
diff --git a/app/workers/detect_repository_languages_worker.rb b/app/workers/detect_repository_languages_worker.rb
index 64bc9776d48..838c3be78f0 100644
--- a/app/workers/detect_repository_languages_worker.rb
+++ b/app/workers/detect_repository_languages_worker.rb
@@ -12,13 +12,12 @@ class DetectRepositoryLanguagesWorker
attr_reader :project
# rubocop: disable CodeReuse/ActiveRecord
- def perform(project_id, user_id)
+ def perform(project_id, user_id = nil)
@project = Project.find_by(id: project_id)
- user = User.find_by(id: user_id)
- return unless project && user
+ return unless project
try_obtain_lease do
- ::Projects::DetectRepositoryLanguagesService.new(project, user).execute
+ ::Projects::DetectRepositoryLanguagesService.new(project).execute
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml b/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml
new file mode 100644
index 00000000000..8d3501e0171
--- /dev/null
+++ b/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml
@@ -0,0 +1,5 @@
+---
+title: Use FindOrCreateService to create labels and check for existing ones
+merge_request: 27987
+author: Matt Duren
+type: fixed
diff --git a/changelogs/unreleased/53973-fix-subpixel-border-issue.yml b/changelogs/unreleased/53973-fix-subpixel-border-issue.yml
new file mode 100644
index 00000000000..0dae7047236
--- /dev/null
+++ b/changelogs/unreleased/53973-fix-subpixel-border-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Fix MR discussion border missing in chrome sometimes
+merge_request: 28185
+author:
+type: fixed
diff --git a/changelogs/unreleased/57654-add-time-preferences-for-user-fe.yml b/changelogs/unreleased/57654-add-time-preferences-for-user-fe.yml
new file mode 100644
index 00000000000..f4ce3a51724
--- /dev/null
+++ b/changelogs/unreleased/57654-add-time-preferences-for-user-fe.yml
@@ -0,0 +1,5 @@
+---
+title: Add time preferences for user
+merge_request: 25381
+author:
+type: added
diff --git a/changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml b/changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml
new file mode 100644
index 00000000000..7e95158a0e0
--- /dev/null
+++ b/changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml
@@ -0,0 +1,5 @@
+---
+title: 58404 - setup max depth for GraphQL
+merge_request: 25737
+author: Ken Ding
+type: added
diff --git a/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml b/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml
new file mode 100644
index 00000000000..6891a9ca83c
--- /dev/null
+++ b/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml
@@ -0,0 +1,5 @@
+---
+title: 'Resolved JIRA service: NoMethodError: undefined method ''find'' for nil:NilClass'
+merge_request: 28206
+author:
+type: fixed
diff --git a/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml b/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml
new file mode 100644
index 00000000000..4274dc5918c
--- /dev/null
+++ b/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml
@@ -0,0 +1,5 @@
+---
+title: "Fix 500 error when accessing charts with an anonymous user"
+merge_request: 28091
+author: Diego Silva
+type: fixed
diff --git a/changelogs/unreleased/61494-set-status-modal-visual-bugs.yml b/changelogs/unreleased/61494-set-status-modal-visual-bugs.yml
new file mode 100644
index 00000000000..4126b8f93c1
--- /dev/null
+++ b/changelogs/unreleased/61494-set-status-modal-visual-bugs.yml
@@ -0,0 +1,5 @@
+---
+title: Fix visual issues in set status modal
+merge_request: 28147
+author:
+type: fixed
diff --git a/changelogs/unreleased/61550-next-badge.yml b/changelogs/unreleased/61550-next-badge.yml
new file mode 100644
index 00000000000..122e394a68c
--- /dev/null
+++ b/changelogs/unreleased/61550-next-badge.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes next badge being always visible
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/add-warning-to-backup-rake-task.yml b/changelogs/unreleased/add-warning-to-backup-rake-task.yml
new file mode 100644
index 00000000000..7ddeae3f9fd
--- /dev/null
+++ b/changelogs/unreleased/add-warning-to-backup-rake-task.yml
@@ -0,0 +1,5 @@
+---
+title: Add warning that gitlab-secrets isn't included in backup
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/antonyliu-i18n-user-profile.yml b/changelogs/unreleased/antonyliu-i18n-user-profile.yml
new file mode 100644
index 00000000000..f9065ee5697
--- /dev/null
+++ b/changelogs/unreleased/antonyliu-i18n-user-profile.yml
@@ -0,0 +1,5 @@
+---
+title: 'i18n: externalize strings from user profile settings'
+merge_request: 28088
+author: Antony Liu
+type: other
diff --git a/changelogs/unreleased/sh-fix-invited-members.yml b/changelogs/unreleased/sh-fix-invited-members.yml
new file mode 100644
index 00000000000..96e43e1aa53
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-invited-members.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Error 500 when inviting user already present
+merge_request: 28198
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-lfs-download-errors.yml b/changelogs/unreleased/sh-fix-lfs-download-errors.yml
new file mode 100644
index 00000000000..ad67df6bb06
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-lfs-download-errors.yml
@@ -0,0 +1,5 @@
+---
+title: Properly handle LFS Batch API response in project import
+merge_request: 28223
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml b/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml
new file mode 100644
index 00000000000..9ad5c9ebb64
--- /dev/null
+++ b/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade Ruby version to 2.6.3
+merge_request: 28117
+author:
+type: performance
diff --git a/changelogs/unreleased/winh-notes-error-handling.yml b/changelogs/unreleased/winh-notes-error-handling.yml
new file mode 100644
index 00000000000..6f23dd459d4
--- /dev/null
+++ b/changelogs/unreleased/winh-notes-error-handling.yml
@@ -0,0 +1,5 @@
+---
+title: Handle errors in successful notes reply
+merge_request: 28082
+author:
+type: fixed
diff --git a/config/initializers/01_secret_token.rb b/config/initializers/01_secret_token.rb
index 02bded43083..e24b5cbd510 100644
--- a/config/initializers/01_secret_token.rb
+++ b/config/initializers/01_secret_token.rb
@@ -1,3 +1,14 @@
+# WARNING: If you add a new secret to this file, make sure you also
+# update Omnibus GitLab or updates will fail. Omnibus is responsible for
+# writing the `secrets.yml` file. If Omnibus doesn't know about a
+# secret, Rails will attempt to write to the file, but this will fail
+# because Rails doesn't have write access.
+#
+# As an example:
+# * https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27581
+# * https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/3267
+#
+#
# This file needs to be loaded BEFORE any initializers that attempt to
# prepend modules that require access to secrets (e.g. EE's 0_as_concern.rb).
#
@@ -28,7 +39,8 @@ def create_tokens
secret_key_base: file_secret_key || generate_new_secure_token,
otp_key_base: env_secret_key || file_secret_key || generate_new_secure_token,
db_key_base: generate_new_secure_token,
- openid_connect_signing_key: generate_new_rsa_private_key
+ openid_connect_signing_key: generate_new_rsa_private_key,
+ lets_encrypt_private_key: generate_lets_encrypt_private_key
}
missing_secrets = set_missing_keys(defaults)
@@ -49,6 +61,10 @@ def generate_new_rsa_private_key
OpenSSL::PKey::RSA.new(2048).to_pem
end
+def generate_lets_encrypt_private_key
+ OpenSSL::PKey::RSA.new(4096).to_pem
+end
+
def warn_missing_secret(secret)
warn "Missing Rails.application.secrets.#{secret} for #{Rails.env} environment. The secret will be generated and stored in config/secrets.yml."
end
diff --git a/db/migrate/20190325105715_add_fields_to_user_preferences.rb b/db/migrate/20190325105715_add_fields_to_user_preferences.rb
new file mode 100644
index 00000000000..9ea3b4f9cd8
--- /dev/null
+++ b/db/migrate/20190325105715_add_fields_to_user_preferences.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddFieldsToUserPreferences < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+
+ def up
+ add_column(:user_preferences, :timezone, :string)
+ add_column(:user_preferences, :time_display_relative, :boolean)
+ add_column(:user_preferences, :time_format_in_24h, :boolean)
+ end
+
+ def down
+ remove_column(:user_preferences, :timezone)
+ remove_column(:user_preferences, :time_display_relative)
+ remove_column(:user_preferences, :time_format_in_24h)
+ end
+end
diff --git a/db/migrate/20190412155659_add_merge_request_blocks.rb b/db/migrate/20190412155659_add_merge_request_blocks.rb
new file mode 100644
index 00000000000..9e7f370d1cf
--- /dev/null
+++ b/db/migrate/20190412155659_add_merge_request_blocks.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class AddMergeRequestBlocks < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :merge_request_blocks, id: :bigserial do |t|
+ t.references :blocking_merge_request,
+ index: false, null: false,
+ foreign_key: { to_table: :merge_requests, on_delete: :cascade }
+
+ t.references :blocked_merge_request,
+ index: true, null: false,
+ foreign_key: { to_table: :merge_requests, on_delete: :cascade }
+
+ t.index [:blocking_merge_request_id, :blocked_merge_request_id],
+ unique: true,
+ name: 'index_mr_blocks_on_blocking_and_blocked_mr_ids'
+
+ t.timestamps_with_timezone
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index deaf406fe3d..159e7e03cf4 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -1227,6 +1227,15 @@ ActiveRecord::Schema.define(version: 20190506135400) do
t.index ["user_id"], name: "index_merge_request_assignees_on_user_id", using: :btree
end
+ create_table "merge_request_blocks", force: :cascade do |t|
+ t.integer "blocking_merge_request_id", null: false
+ t.integer "blocked_merge_request_id", null: false
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.index ["blocked_merge_request_id"], name: "index_merge_request_blocks_on_blocked_merge_request_id", using: :btree
+ t.index ["blocking_merge_request_id", "blocked_merge_request_id"], name: "index_mr_blocks_on_blocking_and_blocked_mr_ids", unique: true, using: :btree
+ end
+
create_table "merge_request_diff_commits", id: false, force: :cascade do |t|
t.datetime_with_timezone "authored_date"
t.datetime_with_timezone "committed_date"
@@ -2246,6 +2255,9 @@ ActiveRecord::Schema.define(version: 20190506135400) do
t.integer "first_day_of_week"
t.string "issues_sort"
t.string "merge_requests_sort"
+ t.string "timezone"
+ t.boolean "time_display_relative"
+ t.boolean "time_format_in_24h"
t.index ["user_id"], name: "index_user_preferences_on_user_id", unique: true, using: :btree
end
@@ -2511,6 +2523,8 @@ ActiveRecord::Schema.define(version: 20190506135400) do
add_foreign_key "members", "users", name: "fk_2e88fb7ce9", on_delete: :cascade
add_foreign_key "merge_request_assignees", "merge_requests", on_delete: :cascade
add_foreign_key "merge_request_assignees", "users", on_delete: :cascade
+ add_foreign_key "merge_request_blocks", "merge_requests", column: "blocked_merge_request_id", on_delete: :cascade
+ add_foreign_key "merge_request_blocks", "merge_requests", column: "blocking_merge_request_id", on_delete: :cascade
add_foreign_key "merge_request_diff_commits", "merge_request_diffs", on_delete: :cascade
add_foreign_key "merge_request_diff_files", "merge_request_diffs", on_delete: :cascade
add_foreign_key "merge_request_diffs", "merge_requests", name: "fk_8483f3258f", on_delete: :cascade
diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md
index d383d1efe70..b7b820abb40 100644
--- a/doc/administration/integration/plantuml.md
+++ b/doc/administration/integration/plantuml.md
@@ -57,8 +57,7 @@ you can change these defaults by editing the `/etc/tomcat7/server.xml` file.
You need to enable PlantUML integration from Settings under Admin Area. To do
that, login with an Admin account and do following:
- - in GitLab go to **Admin Area** and then **Settings**
- - scroll to bottom of the page until PlantUML section
+ - in GitLab go to **Admin Area**->**Settings**->**Integrations**->**PlantUML**
- check **Enable PlantUML** checkbox
- set the PlantUML instance as **PlantUML URL**
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index e079483e2b5..3f72fe3e9eb 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -289,7 +289,7 @@ jobs inherit it. Gems are installed in `vendor/ruby/` and are cached per-branch:
#
# https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
#
-image: ruby:2.5
+image: ruby:2.6
# Cache gems in between builds
cache:
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 7945a48fe40..88c16a8db22 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -1,6 +1,3 @@
-<script src="https://unpkg.com/mermaid@8.0.0/dist/mermaid.min.js"></script>
-<script>mermaid.initialize({startOnLoad:true});</script>
-
# GitLab Architecture Overview
## Software delivery
@@ -213,107 +210,75 @@ To serve repositories over SSH there's an add-on application called gitlab-shell
### Components
-<div class="mermaid">
+```mermaid
graph TB
- HTTP[HTTP/HTTPS] -- TCP 80, 443 --> NGINX(NGINX)
- SSH --TCP 22 --> GitLabShell(GitLab Shell)
- SMTP(SMTP Gateway)
- Geo(GitLab Geo Node) -- TCP 22, 80, 443 --> NGINX
-
- subgraph GitLab
- GitLabShell --TCP 8080 -->Unicorn["Unicorn (GitLab Rails)"]
- GitLabShell --> Gitaly
- GitLabShell --> Redis
- Unicorn --> PgBouncer(PgBouncer)
- Unicorn --> Redis
- Unicorn --> Gitaly
- Redis --> Sidekiq
- Sidekiq("Sidekiq (GitLab Rails, ES Indexer)") --> PgBouncer
- GitLabWorkhorse(GitLab Workhorse) --> Unicorn
- GitLabWorkhorse --> Redis
- GitLabWorkhorse --> Gitaly
- Gitaly --> Redis
- NGINX --> GitLabWorkhorse
- NGINX -- TCP 8090 --> GitLabPages(GitLab Pages)
- NGINX --> Grafana(Grafana)
- Grafana -- TCP 9090 --> Prometheus(Prometheus)
- Prometheus -- TCP 80, 443 --> Unicorn
- RedisExporter(Redis Exporter) --> Redis
- Prometheus -- TCP 9121 --> RedisExporter
- PostgreSQLExporter(PostgreSQL Exporter) --> PostgreSQL
- PgBouncerExporter(PgBouncer Exporter) --> PgBouncer
- Prometheus -- TCP 9187 --> PostgreSQLExporter
- Prometheus -- TCP 9100 --> NodeExporter(Node Exporter)
- Prometheus -- TCP 9168 --> GitLabMonitor(GitLab Monitor)
- Prometheus -- TCP 9127 --> PgBouncerExporter
- GitLabMonitor --> PostgreSQL
- GitLabMonitor --> GitLabShell
- GitLabMonitor --> Sidekiq
- PgBouncer --> Consul(Consul)
- PostgreSQL --> Consul
- PgBouncer --> PostgreSQL
- NGINX --> Registry(Registry)
- Unicorn --> Registry
- NGINX --> Mattermost(Mattermost)
- Mattermost --- Unicorn
- Prometheus --> Alertmanager
- Migrations --> PostgreSQL
- Runner(Runner) --> NGINX
- Unicorn -- TCP 9200 --> ElasticSearch
- Sidekiq -- TCP 9200 --> ElasticSearch
- Sidekiq -- TCP 80, 443 --> Sentry
- Unicorn -- TCP 80, 443 --> Sentry
- Sidekiq -- UDP 6831 --> Jaeger
- Unicorn -- UDP 6831 --> Jaeger
- Gitaly -- UDP 6831 --> Jaeger
- GitLabShell -- UDP 6831 --> Jaeger
- GitLabWorkhorse -- UDP 6831 --> Jaeger
- Alertmanager -- TCP 25 --> SMTP
- Sidekiq -- TCP 25 --> SMTP
- Unicorn -- TCP 25 --> SMTP
- Unicorn -- TCP 369 --> LDAP
- Sidekiq -- TCP 369 --> LDAP
- Unicorn -- TCP 443 --> ObjectStorage("Object Storage")
- Sidekiq -- TCP 443 --> ObjectStorage
- GitLabWorkhorse -- TCP 443 --> ObjectStorage
- Registry -- TCP 443 --> ObjectStorage
- Geo -- TCP 5432 --> PostgreSQL
- end
-
- HTTPK8s(HTTP/HTTPS) -- TCP 80, 443 --> LoadBalancerK8s(Load Balancer)
- LoadBalancerK8s -- TCP 80, 443 --> nginx-ingressK8s
- subgraph Kubernetes
- PrometheusK8s(Prometheus)
- TillerK8s(Tiller)
- nginx-ingressK8s(NGINX Ingress)
- Cert-ManagerK8s(Cert-Manager)
- GitLabRunnerK8s(GitLab Runner)
- GitLabRunnerK8s --> NGINX
- JupyterHubK8s(JupyterHub)
- nginx-ingressK8s --> JupyterHubK8s
- KnativeK8s(Knative)
- end
-
-classDef defaultoff stroke-dasharray: 5, 5
-class ElasticSearch defaultoff
-class Grafana defaultoff
-class PrometheusK8s defaultoff
-class TillerK8s defaultoff
-class nginx-ingressK8s defaultoff
-class Cert-ManagerK8s defaultoff
-class GitLabRunnerK8s defaultoff
-class JupyterHubK8s defaultoff
-class KnativeK8s defaultoff
-class HTTPK8s defaultoff
-class LoadBalancerK8s defaultoff
-class Sentry defaultoff
-class Jaeger defaultoff
-class Alertmanager defaultoff
-class SMTP defaultoff
-class ObjectStorage defaultoff
-class Geo defaultoff
-</div>
+ HTTP[HTTP/HTTPS] -- TCP 80, 443 --> NGINX[NGINX]
+ SSH -- TCP 22 --> GitLabShell[GitLab Shell]
+ SMTP[SMTP Gateway]
+ Geo[GitLab Geo Node] -- TCP 22, 80, 443 --> NGINX
+
+ GitLabShell --TCP 8080 -->Unicorn["Unicorn (GitLab Rails)"]
+ GitLabShell --> Gitaly
+ GitLabShell --> Redis
+ Unicorn --> PgBouncer[PgBouncer]
+ Unicorn --> Redis
+ Unicorn --> Gitaly
+ Redis --> Sidekiq
+ Sidekiq["Sidekiq (GitLab Rails, ES Indexer)"] --> PgBouncer
+ GitLabWorkhorse[GitLab Workhorse] --> Unicorn
+ GitLabWorkhorse --> Redis
+ GitLabWorkhorse --> Gitaly
+ Gitaly --> Redis
+ NGINX --> GitLabWorkhorse
+ NGINX -- TCP 8090 --> GitLabPages[GitLab Pages]
+ NGINX --> Grafana[Grafana]
+ Grafana -- TCP 9090 --> Prometheus[Prometheus]
+ Prometheus -- TCP 80, 443 --> Unicorn
+ RedisExporter[Redis Exporter] --> Redis
+ Prometheus -- TCP 9121 --> RedisExporter
+ PostgreSQLExporter[PostgreSQL Exporter] --> PostgreSQL
+ PgBouncerExporter[PgBouncer Exporter] --> PgBouncer
+ Prometheus -- TCP 9187 --> PostgreSQLExporter
+ Prometheus -- TCP 9100 --> NodeExporter[Node Exporter]
+ Prometheus -- TCP 9168 --> GitLabMonito[GitLab Monitor]
+ Prometheus -- TCP 9127 --> PgBouncerExporter
+ GitLabMonitor --> PostgreSQL
+ GitLabMonitor --> GitLabShell
+ GitLabMonitor --> Sidekiq
+ PgBouncer --> Consul
+ PostgreSQL --> Consul
+ PgBouncer --> PostgreSQL
+ NGINX --> Registry
+ Unicorn --> Registry
+ NGINX --> Mattermost
+ Mattermost --- Unicorn
+ Prometheus --> Alertmanager
+ Migrations --> PostgreSQL
+ Runner -- TCP 443 --> NGINX
+ Unicorn -- TCP 9200 --> ElasticSearch
+ Sidekiq -- TCP 9200 --> ElasticSearch
+ Sidekiq -- TCP 80, 443 --> Sentry
+ Unicorn -- TCP 80, 443 --> Sentry
+ Sidekiq -- UDP 6831 --> Jaeger
+ Unicorn -- UDP 6831 --> Jaeger
+ Gitaly -- UDP 6831 --> Jaeger
+ GitLabShell -- UDP 6831 --> Jaeger
+ GitLabWorkhorse -- UDP 6831 --> Jaeger
+ Alertmanager -- TCP 25 --> SMTP
+ Sidekiq -- TCP 25 --> SMTP
+ Unicorn -- TCP 25 --> SMTP
+ Unicorn -- TCP 369 --> LDAP
+ Sidekiq -- TCP 369 --> LDAP
+ Unicorn -- TCP 443 --> ObjectStorage["Object Storage"]
+ Sidekiq -- TCP 443 --> ObjectStorage
+ GitLabWorkhorse -- TCP 443 --> ObjectStorage
+ Registry -- TCP 443 --> ObjectStorage
+ Geo -- TCP 5432 --> PostgreSQL
+
+```
+
+---
**Legend**:
@@ -324,7 +289,7 @@ class Geo defaultoff
| Component | Description | [Omnibus GitLab](https://docs.gitlab.com/omnibus/README.html) | [GitLab chart](https://docs.gitlab.com/charts/) | [Minikube Minimal](https://docs.gitlab.com/charts/development/minikube/#deploying-gitlab-with-minimal-settings) | [GitLab.com](https://gitlab.com) | CE/EE |
| --------- | ----------- |:--------------------:|:------------------:|:-----:|:--------:|:--------:|
-| NGINX | Routes requests to appropriate components, terminates SSL | [✅](https://docs.gitlab.com/omnibus/settings/nginx.html) | [✅](https://docs.gitlab.com/charts/charts/nginx/index.html) | [⚙](https://docs.gitlab.com/charts/charts/nginx/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) |CE & EE |
+| NGINX | Routes requests to appropriate components, terminates SSL | [✅](https://docs.gitlab.com/omnibus/settings/nginx.html) | [✅](https://docs.gitlab.com/charts/charts/nginx/index.html) | [⚙](https://docs.gitlab.com/charts/charts/nginx/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | CE & EE |
| Unicorn (GitLab Rails) | Handles requests for the web interface and API | [✅](https://docs.gitlab.com/omnibus/settings/unicorn.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/unicorn/index.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/unicorn/index.html) | [✅](https://docs.gitlab.com/ee/user/gitlab_com/#unicorn) | CE & EE |
| Sidekiq | Background jobs processor | [✅](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) | [✅](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/index.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/index.html) | [✅](https://docs.gitlab.com/ee/user/gitlab_com/#sidekiq) | CE & EE |
| Gitaly | Git RPC service for handling all git calls made by GitLab | [✅](https://docs.gitlab.com/ee/administration/gitaly/) | [✅](https://docs.gitlab.com/charts/charts/gitlab/gitaly/index.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/gitaly/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | CE & EE |
@@ -342,18 +307,18 @@ class Geo defaultoff
| Redis Exporter | Prometheus endpoint with Redis metrics | [✅](https://docs.gitlab.com/ee/administration/monitoring/prometheus/redis_exporter.html) | [✅](https://docs.gitlab.com/charts/charts/redis/index.html) | [✅](https://docs.gitlab.com/charts/charts/redis/index.html) | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | CE & EE |
| PostgreSQL Exporter | Prometheus endpoint with PostgreSQL metrics | [✅](https://docs.gitlab.com/ee/administration/monitoring/prometheus/postgres_exporter.html) | [✅](https://github.com/helm/charts/tree/master/stable/postgresql) | [✅](https://github.com/helm/charts/tree/master/stable/postgresql) | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | CE & EE |
| PgBouncer Exporter | Prometheus endpoint with PgBouncer metrics | [⚙](https://docs.gitlab.com/ee/administration/monitoring/prometheus/pgbouncer_exporter.html) | [❌](https://docs.gitlab.com/charts/installation/deployment.html#postgresql) | [❌](https://docs.gitlab.com/charts/installation/deployment.html#postgresql) | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | CE & EE |
-| GitLab Monitor | Tracks a variety of GitLab metrics | [✅](https://docs.gitlab.com/ee/administration/monitoring/prometheus/gitlab_monitor_exporter.html) | [❌](https://gitlab.com/charts/gitlab/issues/319) | [❌](https://gitlab.com/charts/gitlab/issues/319) | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | CE & EE |
+| GitLab Monitor | Generates a variety of GitLab metrics | [✅](https://docs.gitlab.com/ee/administration/monitoring/prometheus/gitlab_monitor_exporter.html) | [❌](https://gitlab.com/charts/gitlab/issues/319) | [❌](https://gitlab.com/charts/gitlab/issues/319) | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | CE & EE |
| Mattermost | Open-source Slack alternative | [⚙](https://docs.gitlab.com/omnibus/gitlab-mattermost/) | [⤓](https://docs.mattermost.com/install/install-mmte-helm-gitlab-helm.html) | [⤓](https://docs.mattermost.com/install/install-mmte-helm-gitlab-helm.html) | [⤓](https://docs.gitlab.com/ee/user/project/integrations/mattermost_slash_commands.html#manual-configuration), [⤓](https://docs.gitlab.com/ee/user/project/integrations/mattermost.html) | CE & EE |
-| Minio | Object storage service | [⤓](https://min.io/download) | [✅](https://docs.gitlab.com/charts/charts/minio/index.html) | [✅](https://docs.gitlab.com/charts/charts/minio/index.html) | [❌](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#storage-architecture) | CE & EE |
+| Minio | Object storage service | [⤓](https://min.io/download) | [✅](https://docs.gitlab.com/charts/charts/minio/index.html) | [✅](https://docs.gitlab.com/charts/charts/minio/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#storage-architecture) | CE & EE |
| Runner | Executes GitLab CI jobs | [⤓](https://docs.gitlab.com/runner/) | [✅](https://docs.gitlab.com/runner/) | [⚙](https://docs.gitlab.com/runner/) | [✅](https://docs.gitlab.com/ee/user/gitlab_com/#shared-runners) | CE & EE |
-| Migrations | Database migrations | [✅](https://docs.gitlab.com/omnibus/settings/database.html#disabling-automatic-database-migration) | [✅](https://docs.gitlab.com/charts/charts/gitlab/migrations/index.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/migrations/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#database-architecture) | CE & EE |
+| DB Migrations | Database migrations | [✅](https://docs.gitlab.com/omnibus/settings/database.html#disabling-automatic-database-migration) | [✅](https://docs.gitlab.com/charts/charts/gitlab/migrations/index.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/migrations/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#database-architecture) | CE & EE |
| Certificate Management | TLS Settings, Let's Encrypt | [✅](https://docs.gitlab.com/omnibus/settings/ssl.html) | [✅](https://docs.gitlab.com/charts/installation/tls.html) | [⚙](https://docs.gitlab.com/charts/installation/tls.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#secrets-management) | CE & EE |
| GitLab Geo Node | Geographically distributed GitLab nodes | [⚙](https://docs.gitlab.com/ee/administration/geo/replication/index.html#setup-instructions) | [❌](https://gitlab.com/charts/gitlab/issues/8) | [❌](https://gitlab.com/charts/gitlab/issues/8) | ✅ | EE Only |
| LDAP Authentication | Authenticate users against centralized LDAP directory | [⤓](https://docs.gitlab.com/ee/administration/auth/ldap.html) | [⤓](https://docs.gitlab.com/charts/charts/globals.html#ldap) | [⤓](https://docs.gitlab.com/charts/charts/globals.html#ldap) | [❌](https://about.gitlab.com/pricing/#gitlab-com) | CE & EE |
| Outbound email (SMTP) | Send email messages to users | [⤓](https://docs.gitlab.com/omnibus/settings/smtp.html) | [⤓](https://docs.gitlab.com/charts/installation/command-line-options.html#outgoing-email-configuration) | [⤓](https://docs.gitlab.com/charts/installation/command-line-options.html#outgoing-email-configuration) | [✅](https://docs.gitlab.com/ee/user/gitlab_com/#mail-configuration) | CE & EE |
| Inbound email (SMTP) | Receive messages to update issues | [⤓](https://docs.gitlab.com/ee/administration/incoming_email.html) | [⤓](https://docs.gitlab.com/charts/installation/command-line-options.html#incoming-email-configuration) | [⤓](https://docs.gitlab.com/charts/installation/command-line-options.html#incoming-email-configuration) | [✅](https://docs.gitlab.com/ee/user/gitlab_com/#mail-configuration) | CE & EE |
| ElasticSearch | Improved search within GitLab | [⤓](https://docs.gitlab.com/ee/integration/elasticsearch.html) | [⤓](https://docs.gitlab.com/ee/integration/elasticsearch.html) | [⤓](https://docs.gitlab.com/ee/integration/elasticsearch.html) | [❌](https://gitlab.com/groups/gitlab-org/-/epics/153) | EE Only |
-| Sentry: GitLab instance | Tracking errors generated by the GitLab instance | [⤓](https://docs.gitlab.com/omnibus/settings/configuration.html#error-reporting-and-logging-with-sentry) | [❌](https://gitlab.com/charts/gitlab/issues/1319) | [❌](https://gitlab.com/charts/gitlab/issues/1319) | [✅](https://about.gitlab.com/handbook/support/workflows/services/gitlab_com/500_errors.html#searching-sentry) | CE & EE |
+| Sentry: GitLab instance | Track errors generated by the GitLab instance | [⤓](https://docs.gitlab.com/omnibus/settings/configuration.html#error-reporting-and-logging-with-sentry) | [❌](https://gitlab.com/charts/gitlab/issues/1319) | [❌](https://gitlab.com/charts/gitlab/issues/1319) | [✅](https://about.gitlab.com/handbook/support/workflows/services/gitlab_com/500_errors.html#searching-sentry) | CE & EE |
| Jaeger: GitLab instance | View traces generated by the GitLab instance | [❌](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4104) | [❌](https://gitlab.com/charts/gitlab/issues/1320) | [❌](https://gitlab.com/charts/gitlab/issues/1320) | [❌](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4104) | CE & EE |
| Sentry: deployed apps | Error tracking for deployed apps | [⤓](https://docs.gitlab.com/ee/user/project/operations/error_tracking.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/error_tracking.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/error_tracking.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/error_tracking.html) | CE & EE |
| Jaeger: deployed apps | Distributed tracing for deployed apps | [⤓](https://docs.gitlab.com/ee/user/project/operations/tracing.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/tracing.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/tracing.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/tracing.html) | EE Only |
diff --git a/doc/install/installation.md b/doc/install/installation.md
index c694f0ed691..f16bc04af34 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -163,9 +163,9 @@ Download Ruby and compile it:
```sh
mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz
-echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz
-cd ruby-2.5.3
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.3.tar.gz
+echo '2347ed6ca5490a104ebd5684d2b9b5eefa6cd33c ruby-2.6.3.tar.gz' | shasum -c - && tar xzf ruby-2.6.3.tar.gz
+cd ruby-2.6.3
./configure --disable-install-rdoc
make
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 672723aaf12..f6a52205a0e 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -169,7 +169,7 @@ So for a machine with 2 cores, 3 unicorn workers is ideal.
For all machines that have 2GB and up we recommend a minimum of three unicorn workers.
If you have a 1GB machine we recommend to configure only two Unicorn workers to prevent excessive swapping.
-To change the Unicorn workers when you have the Omnibus package (which defaults to the recommendation above) please see [the Unicorn settings in the Omnibus GitLab documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.md#unicorn-settings).
+To change the Unicorn workers when you have the Omnibus package (which defaults to the recommendation above) please see [the Unicorn settings in the Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/unicorn.html).
## Redis and Sidekiq
@@ -201,14 +201,13 @@ you decide to run GitLab Runner and the GitLab Rails application on the same
machine.
It is also not safe to install everything on a single machine, because of the
-[security reasons] - especially when you plan to use shell executor with GitLab
+[security reasons](https://docs.gitlab.com/runner/security/)
+- especially when you plan to use shell executor with GitLab
Runner.
We recommend using a separate machine for each GitLab Runner, if you plan to
use the CI features.
-[security reasons]: https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/security/index.md
-
## Supported web browsers
We support the current and the previous major release of:
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index e607dbceeea..b83abcd36f7 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -45,6 +45,22 @@ For other distributions, follow the instructions in PostgreSQL's
[download page](https://www.postgresql.org/download/) to add their repository
and then install `pgloader`.
+If you are migrating to a Docker based installation, you will need to install
+pgloader within the container as it is not included in the container image.
+
+1. Start a shell session in the context of the running container:
+
+ ``` bash
+ docker exec -it gitlab bash
+ ```
+
+1. Install pgloader:
+
+ ``` bash
+ apt-get update
+ apt-get -y install pgloader
+ ```
+
## Omnibus GitLab installations
For [Omnibus GitLab packages](https://about.gitlab.com/install/), you'll first
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index fea89669831..5118726cb0a 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -52,9 +52,9 @@ Download Ruby and compile it:
```bash
mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz
-echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz
-cd ruby-2.5.3
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.3.tar.gz
+echo '2347ed6ca5490a104ebd5684d2b9b5eefa6cd33c ruby-2.6.3.tar.gz' | shasum -c - && tar xzf ruby-2.6.3.tar.gz
+cd ruby-2.6.3
./configure --disable-install-rdoc
make
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index 834a1e2423a..42fc4efa4ce 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -98,8 +98,7 @@ the group.
NOTE: **Note:**
Only available on GitLab.com.
-If you have a Group with a [paid plan](https://about.gitlab.com/pricing/#gitlab-com) on GitLab.com,
-then you can purchase additional CI minutes so your pipelines will not be blocked after you have
+You can purchase additional CI minutes so your pipelines will not be blocked after you have
used all your CI minutes from your main quota.
In order to purchase additional minutes, you should follow these steps:
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index e165a120162..8b5d80efb0d 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -48,6 +48,8 @@ You can view the exact JSON payload in the administration panel. To view the pay
1. Expand **Settings** in the left sidebar and click on **Metrics and profiling**.
1. Expand **Usage statistics** and click on the **Preview payload** button.
+You can see how [the usage ping data maps to different stages of the product](https://gitlab.com/gitlab-data/analytics/blob/master/transform/snowflake-dbt/data/ping_metrics_to_stage_mapping_data.csv).
+
### Deactivate the usage ping
The usage ping is opt-out. If you want to deactivate this feature, go to
diff --git a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
index ea22f3e905b..da1b7c59c8e 100644
--- a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
+++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
@@ -145,8 +145,8 @@ Now that your certificate has been issued, let's add it to your Pages site:
1. Visit your website at `https://example.com`.
To force `https` connections on your site, navigate to your
-project's **Settings > Pages** and check **Force domains with SSL
-certificates to use HTTPS**.
+project's **Settings > Pages** and check **Force HTTPS (requires
+valid certificates)**.
## Renewal
diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb
index 769d3279f91..c9f0ed66a54 100644
--- a/lib/gitlab/bitbucket_import/importer.rb
+++ b/lib/gitlab/bitbucket_import/importer.rb
@@ -135,7 +135,7 @@ module Gitlab
def create_labels
LABELS.each do |label_params|
- label = ::Labels::CreateService.new(label_params).execute(project: project)
+ label = ::Labels::FindOrCreateService.new(nil, project, label_params).execute(skip_authorization: true)
if label.valid?
@labels[label_params[:title]] = label
else
diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake
index 3977fc7ad8c..c531eb1d216 100644
--- a/lib/tasks/gitlab/backup.rake
+++ b/lib/tasks/gitlab/backup.rake
@@ -20,6 +20,11 @@ namespace :gitlab do
backup.pack
backup.cleanup
backup.remove_old
+
+ puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \
+ "and are not included in this backup. You will need these files to restore a backup.\n" \
+ "Please back them up manually.".color(:red)
+ puts "Backup task is done."
end
# Restore backup of GitLab system
@@ -68,6 +73,9 @@ namespace :gitlab do
Rake::Task['cache:clear'].invoke
backup.cleanup
+ puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \
+ "and are not included in this backup. You will need to restore these files manually.".color(:red)
+ puts "Restore task is done."
end
namespace :repo do
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 2907430bd51..71ec8bcb9ba 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1894,9 +1894,24 @@ msgstr ""
msgid "CiVariables|Input variable value"
msgstr ""
+msgid "CiVariables|Key"
+msgstr ""
+
+msgid "CiVariables|Masked"
+msgstr ""
+
msgid "CiVariables|Remove variable row"
msgstr ""
+msgid "CiVariables|State"
+msgstr ""
+
+msgid "CiVariables|Type"
+msgstr ""
+
+msgid "CiVariables|Value"
+msgstr ""
+
msgid "CiVariable|* (All environments)"
msgstr ""
@@ -4196,6 +4211,9 @@ msgstr ""
msgid "Failed to remove user key."
msgstr ""
+msgid "Failed to save comment!"
+msgstr ""
+
msgid "Failed to save merge conflicts resolutions. Please try again!"
msgstr ""
@@ -6974,12 +6992,33 @@ msgstr ""
msgid "Preferences saved."
msgstr ""
+msgid "Preferences|Display time in 24-hour format"
+msgstr ""
+
+msgid "Preferences|For example: 30 mins ago."
+msgstr ""
+
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Preferences|These settings will update how dates and times are displayed for you."
+msgstr ""
+
msgid "Preferences|This feature is experimental and translations are not complete yet"
msgstr ""
+msgid "Preferences|Time display"
+msgstr ""
+
+msgid "Preferences|Time format"
+msgstr ""
+
+msgid "Preferences|Time preferences"
+msgstr ""
+
+msgid "Preferences|Use relative times"
+msgstr ""
+
msgid "Press %{key}-C to copy"
msgstr ""
@@ -7022,6 +7061,9 @@ msgstr ""
msgid "Private - The group and its projects can only be viewed by members."
msgstr ""
+msgid "Private profile"
+msgstr ""
+
msgid "Private projects can be created in your personal namespace with:"
msgstr ""
@@ -7061,6 +7103,9 @@ msgstr ""
msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
+msgid "Profiles|Bio"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
@@ -7121,6 +7166,18 @@ msgstr ""
msgid "Profiles|Enter your name, so people you know can recognize you"
msgstr ""
+msgid "Profiles|Feed token was successfully reset"
+msgstr ""
+
+msgid "Profiles|Full name"
+msgstr ""
+
+msgid "Profiles|Include private contributions on my profile"
+msgstr ""
+
+msgid "Profiles|Incoming email token was successfully reset"
+msgstr ""
+
msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)"
msgstr ""
@@ -7133,6 +7190,9 @@ msgstr ""
msgid "Profiles|Learn more"
msgstr ""
+msgid "Profiles|Location"
+msgstr ""
+
msgid "Profiles|Made a private contribution"
msgstr ""
@@ -7142,6 +7202,9 @@ msgstr ""
msgid "Profiles|No file chosen"
msgstr ""
+msgid "Profiles|Organization"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
@@ -7151,6 +7214,9 @@ msgstr ""
msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Profile was successfully updated"
+msgstr ""
+
msgid "Profiles|Public Avatar"
msgstr ""
@@ -7190,6 +7256,9 @@ msgstr ""
msgid "Profiles|This information will appear on your profile"
msgstr ""
+msgid "Profiles|Time settings"
+msgstr ""
+
msgid "Profiles|Two-Factor Authentication"
msgstr ""
@@ -7211,6 +7280,9 @@ msgstr ""
msgid "Profiles|Use a private email - %{email}"
msgstr ""
+msgid "Profiles|User ID"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -7232,6 +7304,9 @@ msgstr ""
msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
msgstr ""
+msgid "Profiles|You can set your current timezone here"
+msgstr ""
+
msgid "Profiles|You can upload your avatar here"
msgstr ""
diff --git a/qa/Dockerfile b/qa/Dockerfile
index ca7f9accb70..74be373b8e8 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -1,4 +1,4 @@
-FROM ruby:2.5-stretch
+FROM ruby:2.6-stretch
LABEL maintainer "Grzegorz Bizon <grzegorz@gitlab.com>"
ENV DEBIAN_FRONTEND noninteractive
diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb
index d390e84c9b0..b5248c7f0c8 100644
--- a/spec/controllers/projects/graphs_controller_spec.rb
+++ b/spec/controllers/projects/graphs_controller_spec.rb
@@ -28,6 +28,21 @@ describe Projects::GraphsController do
end
describe 'charts' do
+ context 'with an anonymous user' do
+ let(:project) { create(:project, :repository, :public) }
+
+ before do
+ sign_out(user)
+ end
+
+ it 'renders charts with 200 status code' do
+ get(:charts, params: { namespace_id: project.namespace.path, project_id: project.path, id: 'master' })
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:charts)
+ end
+ end
+
context 'when languages were previously detected' do
let(:project) { create(:project, :repository, detected_repository_languages: true) }
let!(:repository_language) { create(:repository_language, project: project) }
diff --git a/spec/features/dashboard/user_filters_projects_spec.rb b/spec/features/dashboard/user_filters_projects_spec.rb
index 5b17c49db2d..4410c8f887f 100644
--- a/spec/features/dashboard/user_filters_projects_spec.rb
+++ b/spec/features/dashboard/user_filters_projects_spec.rb
@@ -151,34 +151,22 @@ describe 'Dashboard > User filters projects' do
end
describe 'Sorting' do
- before do
- [
- { name: 'Red ribbon army', created_at: 2.days.ago },
- { name: 'Cell saga', created_at: Time.now },
- { name: 'Frieza saga', created_at: 10.days.ago }
- ].each do |item|
- project = create(:project, name: item[:name], namespace: user.namespace, created_at: item[:created_at])
- project.add_developer(user)
- end
+ let(:desc_sorted_project_names) { %w[Treasure Victorialand] }
+ before do
user.toggle_star(project)
user.toggle_star(project2)
user2.toggle_star(project2)
end
- it 'includes sorting direction' do
+ it 'has all sorting options', :js do
sorting_dropdown = page.find('.filtered-search-block #filtered-search-sorting-dropdown')
expect(sorting_dropdown).to have_css '.reverse-sort-btn'
- end
-
- it 'has all sorting options', :js do
- sorting_dropdown = page.find('.filtered-search-block #filtered-search-sorting-dropdown')
- sorting_option_labels = ['Last updated', 'Created date', 'Name', 'Stars']
sorting_dropdown.click
- sorting_option_labels.each do |label|
+ ['Last updated', 'Created date', 'Name', 'Stars'].each do |label|
expect(sorting_dropdown).to have_content(label)
end
end
@@ -194,16 +182,11 @@ describe 'Dashboard > User filters projects' do
it 'sorts the project list' do
select_dropdown_option '#filtered-search-sorting-dropdown', 'Name'
- desc = ['Victorialand', 'Treasure', 'Red ribbon army', 'Frieza saga', 'Cell saga']
- asc = ['Cell saga', 'Frieza saga', 'Red ribbon army', 'Treasure', 'Victorialand']
-
- click_sort_direction
-
- expect_to_see_projects(desc)
+ expect_to_see_projects(desc_sorted_project_names)
click_sort_direction
- expect_to_see_projects(asc)
+ expect_to_see_projects(desc_sorted_project_names.reverse)
end
end
@@ -211,16 +194,11 @@ describe 'Dashboard > User filters projects' do
it 'sorts the project list' do
select_dropdown_option '#filtered-search-sorting-dropdown', 'Last updated'
- desc = ["Frieza saga", "Red ribbon army", "Victorialand", "Treasure", "Cell saga"]
- asc = ["Cell saga", "Treasure", "Victorialand", "Red ribbon army", "Frieza saga"]
+ expect_to_see_projects(desc_sorted_project_names)
click_sort_direction
- expect_to_see_projects(desc)
-
- click_sort_direction
-
- expect_to_see_projects(asc)
+ expect_to_see_projects(desc_sorted_project_names.reverse)
end
end
@@ -228,16 +206,11 @@ describe 'Dashboard > User filters projects' do
it 'sorts the project list' do
select_dropdown_option '#filtered-search-sorting-dropdown', 'Created date'
- desc = ["Frieza saga", "Red ribbon army", "Victorialand", "Treasure", "Cell saga"]
- asc = ["Cell saga", "Treasure", "Victorialand", "Red ribbon army", "Frieza saga"]
-
- click_sort_direction
-
- expect_to_see_projects(desc)
+ expect_to_see_projects(desc_sorted_project_names)
click_sort_direction
- expect_to_see_projects(asc)
+ expect_to_see_projects(desc_sorted_project_names.reverse)
end
end
@@ -245,16 +218,11 @@ describe 'Dashboard > User filters projects' do
it 'sorts the project list' do
select_dropdown_option '#filtered-search-sorting-dropdown', 'Stars'
- desc = ["Red ribbon army", "Cell saga", "Frieza saga", "Victorialand", "Treasure"]
- asc = ["Treasure", "Victorialand", "Red ribbon army", "Cell saga", "Frieza saga"]
-
- click_sort_direction
-
- expect_to_see_projects(desc)
+ expect_to_see_projects(desc_sorted_project_names)
click_sort_direction
- expect_to_see_projects(asc)
+ expect_to_see_projects(desc_sorted_project_names.reverse)
end
end
end
diff --git a/spec/features/issuables/markdown_references/jira_spec.rb b/spec/features/issuables/markdown_references/jira_spec.rb
index cc04798248c..8eaccfc0949 100644
--- a/spec/features/issuables/markdown_references/jira_spec.rb
+++ b/spec/features/issuables/markdown_references/jira_spec.rb
@@ -1,6 +1,6 @@
require "rails_helper"
-describe "Jira", :js, :quarantine do
+describe "Jira", :js do
let(:user) { create(:user) }
let(:actual_project) { create(:project, :public, :repository) }
let(:merge_request) { create(:merge_request, target_project: actual_project, source_project: actual_project) }
diff --git a/spec/features/profiles/user_edit_preferences_spec.rb b/spec/features/profiles/user_edit_preferences_spec.rb
new file mode 100644
index 00000000000..2d2da222998
--- /dev/null
+++ b/spec/features/profiles/user_edit_preferences_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe 'User edit preferences profile' do
+ let(:user) { create(:user) }
+
+ before do
+ stub_feature_flags(user_time_settings: true)
+ sign_in(user)
+ visit(profile_preferences_path)
+ end
+
+ it 'allows the user to toggle their time format preference' do
+ field = page.find_field("user[time_format_in_24h]")
+
+ expect(field).not_to be_checked
+
+ field.click
+
+ expect(field).to be_checked
+ end
+
+ it 'allows the user to toggle their time display preference' do
+ field = page.find_field("user[time_display_relative]")
+
+ expect(field).to be_checked
+
+ field.click
+
+ expect(field).not_to be_checked
+ end
+end
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index b43711f6ef6..a53da94ef7d 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -327,5 +327,37 @@ describe 'User edit profile' do
end
end
end
+
+ context 'User time preferences', :js do
+ let(:issue) { create(:issue, project: project)}
+ let(:project) { create(:project) }
+
+ before do
+ stub_feature_flags(user_time_settings: true)
+ end
+
+ it 'shows the user time preferences form' do
+ expect(page).to have_content('Time settings')
+ end
+
+ it 'allows the user to select a time zone from a dropdown list of options' do
+ expect(page.find('.user-time-preferences .dropdown')).not_to have_css('.show')
+
+ page.find('.user-time-preferences .js-timezone-dropdown').click
+
+ expect(page.find('.user-time-preferences .dropdown')).to have_css('.show')
+
+ page.find("a", text: "Nuku'alofa").click
+
+ tz = page.find('.user-time-preferences #user_timezone', visible: false)
+
+ expect(tz.value).to eq('Pacific/Tongatapu')
+ end
+
+ it 'timezone defaults to servers default' do
+ timezone_name = Time.zone.tzinfo.name
+ expect(page.find('.user-time-preferences #user_timezone', visible: false).value).to eq(timezone_name)
+ end
+ end
end
end
diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js
index 392c1b6533e..7e037beca9d 100644
--- a/spec/frontend/notes/components/discussion_notes_spec.js
+++ b/spec/frontend/notes/components/discussion_notes_spec.js
@@ -1,4 +1,4 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import '~/behaviors/markdown/render_gfm';
import { SYSTEM_NOTE } from '~/notes/constants';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
@@ -8,6 +8,7 @@ import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_sys
import SystemNote from '~/vue_shared/components/notes/system_note.vue';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import createStore from '~/notes/stores';
+import { setTestTimeout } from 'helpers/timeout';
import {
noteableDataMock,
discussionMock,
@@ -17,6 +18,8 @@ import {
const localVue = createLocalVue();
describe('DiscussionNotes', () => {
+ setTestTimeout(500);
+
let wrapper;
const createComponent = props => {
@@ -24,7 +27,7 @@ describe('DiscussionNotes', () => {
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
- wrapper = mount(DiscussionNotes, {
+ wrapper = shallowMount(DiscussionNotes, {
localVue,
store,
propsData: {
diff --git a/spec/frontend/notes/stores/utils_spec.js b/spec/frontend/notes/stores/utils_spec.js
new file mode 100644
index 00000000000..b31b7491334
--- /dev/null
+++ b/spec/frontend/notes/stores/utils_spec.js
@@ -0,0 +1,17 @@
+import { hasQuickActions } from '~/notes/stores/utils';
+
+describe('hasQuickActions', () => {
+ it.each`
+ input | expected
+ ${'some comment'} | ${false}
+ ${'/quickaction'} | ${true}
+ ${'some comment with\n/quickaction'} | ${true}
+ `('returns $expected for $input', ({ input, expected }) => {
+ expect(hasQuickActions(input)).toBe(expected);
+ });
+
+ it('is stateless', () => {
+ expect(hasQuickActions('some comment')).toBe(hasQuickActions('some comment'));
+ expect(hasQuickActions('/quickaction')).toBe(hasQuickActions('/quickaction'));
+ });
+});
diff --git a/spec/graphql/gitlab_schema_spec.rb b/spec/graphql/gitlab_schema_spec.rb
index 05f10fb40f0..c138c87c4ac 100644
--- a/spec/graphql/gitlab_schema_spec.rb
+++ b/spec/graphql/gitlab_schema_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe GitlabSchema do
+ let(:user) { build :user }
+
it 'uses batch loading' do
expect(field_instrumenters).to include(BatchLoader::GraphQL)
end
@@ -33,43 +35,75 @@ describe GitlabSchema do
expect(connection).to eq(Gitlab::Graphql::Connections::KeysetConnection)
end
- context 'for different types of users' do
- it 'returns DEFAULT_MAX_COMPLEXITY for no context' do
- expect(GraphQL::Schema)
- .to receive(:execute)
- .with('query', hash_including(max_complexity: GitlabSchema::DEFAULT_MAX_COMPLEXITY))
+ describe '.execute' do
+ context 'for different types of users' do
+ context 'when no context' do
+ it 'returns DEFAULT_MAX_COMPLEXITY' do
+ expect(GraphQL::Schema)
+ .to receive(:execute)
+ .with('query', hash_including(max_complexity: GitlabSchema::DEFAULT_MAX_COMPLEXITY))
- described_class.execute('query')
- end
+ described_class.execute('query')
+ end
+ end
- it 'returns DEFAULT_MAX_COMPLEXITY for no user' do
- expect(GraphQL::Schema)
- .to receive(:execute)
- .with('query', hash_including(max_complexity: GitlabSchema::DEFAULT_MAX_COMPLEXITY))
+ context 'when no user' do
+ it 'returns DEFAULT_MAX_COMPLEXITY' do
+ expect(GraphQL::Schema)
+ .to receive(:execute)
+ .with('query', hash_including(max_complexity: GitlabSchema::DEFAULT_MAX_COMPLEXITY))
- described_class.execute('query', context: {})
- end
+ described_class.execute('query', context: {})
+ end
- it 'returns AUTHENTICATED_COMPLEXITY for a logged in user' do
- user = build :user
+ it 'returns ANONYMOUS_MAX_DEPTH' do
+ expect(GraphQL::Schema)
+ .to receive(:execute)
+ .with('query', hash_including(max_depth: GitlabSchema::ANONYMOUS_MAX_DEPTH))
- expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_complexity: GitlabSchema::AUTHENTICATED_COMPLEXITY))
+ described_class.execute('query', context: {})
+ end
+ end
- described_class.execute('query', context: { current_user: user })
- end
+ context 'when a logged in user' do
+ it 'returns AUTHENTICATED_COMPLEXITY' do
+ expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_complexity: GitlabSchema::AUTHENTICATED_COMPLEXITY))
- it 'returns ADMIN_COMPLEXITY for an admin user' do
- user = build :user, :admin
+ described_class.execute('query', context: { current_user: user })
+ end
- expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_complexity: GitlabSchema::ADMIN_COMPLEXITY))
+ it 'returns AUTHENTICATED_MAX_DEPTH' do
+ expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_depth: GitlabSchema::AUTHENTICATED_MAX_DEPTH))
- described_class.execute('query', context: { current_user: user })
- end
+ described_class.execute('query', context: { current_user: user })
+ end
+ end
+
+ context 'when an admin user' do
+ it 'returns ADMIN_COMPLEXITY' do
+ user = build :user, :admin
+
+ expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_complexity: GitlabSchema::ADMIN_COMPLEXITY))
+
+ described_class.execute('query', context: { current_user: user })
+ end
+ end
+
+ context 'when max_complexity passed on the query' do
+ it 'returns what was passed on the query' do
+ expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_complexity: 1234))
+
+ described_class.execute('query', max_complexity: 1234)
+ end
+ end
- it 'returns what was passed on the query' do
- expect(GraphQL::Schema).to receive(:execute).with('query', { max_complexity: 1234 })
+ context 'when max_depth passed on the query' do
+ it 'returns what was passed on the query' do
+ expect(GraphQL::Schema).to receive(:execute).with('query', hash_including(max_depth: 1234))
- described_class.execute('query', max_complexity: 1234)
+ described_class.execute('query', max_depth: 1234)
+ end
+ end
end
end
diff --git a/spec/initializers/secret_token_spec.rb b/spec/initializers/secret_token_spec.rb
index 726ce07a2d1..77bc28a6b07 100644
--- a/spec/initializers/secret_token_spec.rb
+++ b/spec/initializers/secret_token_spec.rb
@@ -45,11 +45,21 @@ describe 'create_tokens' do
expect(keys).to all(match(RSA_KEY))
end
+ it "generates private key for Let's Encrypt" do
+ create_tokens
+
+ keys = secrets.values_at(:lets_encrypt_private_key)
+
+ expect(keys.uniq).to eq(keys)
+ expect(keys).to all(match(RSA_KEY))
+ end
+
it 'warns about the secrets to add to secrets.yml' do
expect(self).to receive(:warn_missing_secret).with('secret_key_base')
expect(self).to receive(:warn_missing_secret).with('otp_key_base')
expect(self).to receive(:warn_missing_secret).with('db_key_base')
expect(self).to receive(:warn_missing_secret).with('openid_connect_signing_key')
+ expect(self).to receive(:warn_missing_secret).with('lets_encrypt_private_key')
create_tokens
end
@@ -78,6 +88,7 @@ describe 'create_tokens' do
before do
secrets.db_key_base = 'db_key_base'
secrets.openid_connect_signing_key = 'openid_connect_signing_key'
+ secrets.lets_encrypt_private_key = 'lets_encrypt_private_key'
allow(File).to receive(:exist?).with('.secret').and_return(true)
allow(File).to receive(:read).with('.secret').and_return('file_key')
diff --git a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js b/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
index 481b1a4d4b0..2839922fbd3 100644
--- a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
@@ -113,7 +113,7 @@ describe('AjaxFormVariableList', () => {
it('hides secret values', done => {
mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(200, {});
- const row = container.querySelector('.js-row:first-child');
+ const row = container.querySelector('.js-row');
const valueInput = row.querySelector('.js-ci-variable-input-value');
const valuePlaceholder = row.querySelector('.js-secret-value-placeholder');
diff --git a/spec/javascripts/fixtures/abuse_reports.rb b/spec/javascripts/fixtures/abuse_reports.rb
index 54b6419bcdb..e0aaecf626a 100644
--- a/spec/javascripts/fixtures/abuse_reports.rb
+++ b/spec/javascripts/fixtures/abuse_reports.rb
@@ -18,10 +18,9 @@ describe Admin::AbuseReportsController, '(JavaScript fixtures)', type: :controll
sign_in(admin)
end
- it 'abuse_reports/abuse_reports_list.html' do |example|
+ it 'abuse_reports/abuse_reports_list.html' do
get :index
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/admin_users.rb b/spec/javascripts/fixtures/admin_users.rb
index 76dbdf603da..22a5de66577 100644
--- a/spec/javascripts/fixtures/admin_users.rb
+++ b/spec/javascripts/fixtures/admin_users.rb
@@ -17,13 +17,12 @@ describe Admin::UsersController, '(JavaScript fixtures)', type: :controller do
clean_frontend_fixtures('admin/users')
end
- it 'admin/users/new_with_internal_user_regex.html' do |example|
+ it 'admin/users/new_with_internal_user_regex.html' do
stub_application_setting(user_default_external: true)
stub_application_setting(user_default_internal_regex: '^(?:(?!\.ext@).)*$\r?')
get :new
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/application_settings.rb b/spec/javascripts/fixtures/application_settings.rb
index c535e598e12..d4651fa6ece 100644
--- a/spec/javascripts/fixtures/application_settings.rb
+++ b/spec/javascripts/fixtures/application_settings.rb
@@ -23,12 +23,11 @@ describe Admin::ApplicationSettingsController, '(JavaScript fixtures)', type: :c
remove_repository(project)
end
- it 'application_settings/accounts_and_limit.html' do |example|
+ it 'application_settings/accounts_and_limit.html' do
stub_application_setting(user_default_external: false)
get :show
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/autocomplete_sources.rb b/spec/javascripts/fixtures/autocomplete_sources.rb
index c117fb7cd24..b20a0159d7d 100644
--- a/spec/javascripts/fixtures/autocomplete_sources.rb
+++ b/spec/javascripts/fixtures/autocomplete_sources.rb
@@ -18,7 +18,7 @@ describe Projects::AutocompleteSourcesController, '(JavaScript fixtures)', type:
sign_in(admin)
end
- it 'autocomplete_sources/labels.json' do |example|
+ it 'autocomplete_sources/labels.json' do
issue.labels << create(:label, project: project, title: 'bug')
issue.labels << create(:label, project: project, title: 'critical')
@@ -35,6 +35,5 @@ describe Projects::AutocompleteSourcesController, '(JavaScript fixtures)', type:
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/balsamiq.rb b/spec/javascripts/fixtures/balsamiq.rb
deleted file mode 100644
index 234e246119a..00000000000
--- a/spec/javascripts/fixtures/balsamiq.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'spec_helper'
-
-describe 'Balsamiq file', '(JavaScript fixtures)', type: :controller do
- include JavaScriptFixturesHelpers
-
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
- let(:project) { create(:project, :repository, namespace: namespace, path: 'balsamiq-project') }
-
- before(:all) do
- clean_frontend_fixtures('blob/balsamiq/')
- end
-
- it 'blob/balsamiq/test.bmpr' do |example|
- blob = project.repository.blob_at('b89b56d79', 'files/images/balsamiq.bmpr')
-
- store_frontend_fixture(blob.data.force_encoding('utf-8'), example.description)
- end
-end
diff --git a/spec/javascripts/fixtures/blob.rb b/spec/javascripts/fixtures/blob.rb
index db7749bc000..07670552cd5 100644
--- a/spec/javascripts/fixtures/blob.rb
+++ b/spec/javascripts/fixtures/blob.rb
@@ -22,7 +22,7 @@ describe Projects::BlobController, '(JavaScript fixtures)', type: :controller do
remove_repository(project)
end
- it 'blob/show.html' do |example|
+ it 'blob/show.html' do
get(:show, params: {
namespace_id: project.namespace,
project_id: project,
@@ -30,6 +30,5 @@ describe Projects::BlobController, '(JavaScript fixtures)', type: :controller do
})
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/boards.rb b/spec/javascripts/fixtures/boards.rb
index c4390e89578..5835721d3d5 100644
--- a/spec/javascripts/fixtures/boards.rb
+++ b/spec/javascripts/fixtures/boards.rb
@@ -17,13 +17,12 @@ describe Projects::BoardsController, '(JavaScript fixtures)', type: :controller
sign_in(admin)
end
- it 'boards/show.html' do |example|
+ it 'boards/show.html' do
get(:index, params: {
namespace_id: project.namespace,
project_id: project
})
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/branches.rb b/spec/javascripts/fixtures/branches.rb
index 5d2d6c7ec0e..204aa9b7c7a 100644
--- a/spec/javascripts/fixtures/branches.rb
+++ b/spec/javascripts/fixtures/branches.rb
@@ -21,13 +21,12 @@ describe Projects::BranchesController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'branches/new_branch.html' do |example|
+ it 'branches/new_branch.html' do
get :new, params: {
namespace_id: project.namespace.to_param,
project_id: project
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/clusters.rb b/spec/javascripts/fixtures/clusters.rb
index 8ebd8a41366..1076404e0e3 100644
--- a/spec/javascripts/fixtures/clusters.rb
+++ b/spec/javascripts/fixtures/clusters.rb
@@ -22,7 +22,7 @@ describe Projects::ClustersController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'clusters/show_cluster.html' do |example|
+ it 'clusters/show_cluster.html' do
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -30,6 +30,5 @@ describe Projects::ClustersController, '(JavaScript fixtures)', type: :controlle
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/commit.rb b/spec/javascripts/fixtures/commit.rb
index ab10f559e4b..ff9a4bc1adc 100644
--- a/spec/javascripts/fixtures/commit.rb
+++ b/spec/javascripts/fixtures/commit.rb
@@ -19,7 +19,7 @@ describe Projects::CommitController, '(JavaScript fixtures)', type: :controller
allow(SecureRandom).to receive(:hex).and_return('securerandomhex:thereisnospoon')
end
- it 'commit/show.html' do |example|
+ it 'commit/show.html' do
params = {
namespace_id: project.namespace,
project_id: project,
@@ -29,6 +29,5 @@ describe Projects::CommitController, '(JavaScript fixtures)', type: :controller
get :show, params: params
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/deploy_keys.rb b/spec/javascripts/fixtures/deploy_keys.rb
index a333d9c0150..38eab853da2 100644
--- a/spec/javascripts/fixtures/deploy_keys.rb
+++ b/spec/javascripts/fixtures/deploy_keys.rb
@@ -24,7 +24,7 @@ describe Projects::DeployKeysController, '(JavaScript fixtures)', type: :control
render_views
- it 'deploy_keys/keys.json' do |example|
+ it 'deploy_keys/keys.json' do
create(:rsa_deploy_key_2048, public: true)
project_key = create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCdMHEHyhRjbhEZVddFn6lTWdgEy5Q6Bz4nwGB76xWZI5YT/1WJOMEW+sL5zYd31kk7sd3FJ5L9ft8zWMWrr/iWXQikC2cqZK24H1xy+ZUmrRuJD4qGAaIVoyyzBL+avL+lF8J5lg6YSw8gwJY/lX64/vnJHUlWw2n5BF8IFOWhiw== dummy@gitlab.com')
internal_key = create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDNd/UJWhPrpb+b/G5oL109y57yKuCxE+WUGJGYaj7WQKsYRJmLYh1mgjrl+KVyfsWpq4ylOxIfFSnN9xBBFN8mlb0Fma5DC7YsSsibJr3MZ19ZNBprwNcdogET7aW9I0In7Wu5f2KqI6e5W/spJHCy4JVxzVMUvk6Myab0LnJ2iQ== dummy@gitlab.com')
@@ -39,6 +39,5 @@ describe Projects::DeployKeysController, '(JavaScript fixtures)', type: :control
}, format: :json
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/groups.rb b/spec/javascripts/fixtures/groups.rb
index 16e31028b05..4d0afc3ce1a 100644
--- a/spec/javascripts/fixtures/groups.rb
+++ b/spec/javascripts/fixtures/groups.rb
@@ -18,20 +18,18 @@ describe 'Groups (JavaScript fixtures)', type: :controller do
end
describe GroupsController, '(JavaScript fixtures)', type: :controller do
- it 'groups/edit.html' do |example|
+ it 'groups/edit.html' do
get :edit, params: { id: group }
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
describe Groups::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
- it 'groups/ci_cd_settings.html' do |example|
+ it 'groups/ci_cd_settings.html' do
get :show, params: { group_id: group }
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/fixtures/issues.rb b/spec/javascripts/fixtures/issues.rb
index 0f3f9a10f94..d8d77f767de 100644
--- a/spec/javascripts/fixtures/issues.rb
+++ b/spec/javascripts/fixtures/issues.rb
@@ -21,26 +21,26 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller
remove_repository(project)
end
- it 'issues/open-issue.html' do |example|
- render_issue(example.description, create(:issue, project: project))
+ it 'issues/open-issue.html' do
+ render_issue(create(:issue, project: project))
end
- it 'issues/closed-issue.html' do |example|
- render_issue(example.description, create(:closed_issue, project: project))
+ it 'issues/closed-issue.html' do
+ render_issue(create(:closed_issue, project: project))
end
- it 'issues/issue-with-task-list.html' do |example|
+ it 'issues/issue-with-task-list.html' do
issue = create(:issue, project: project, description: '- [ ] Task List Item')
- render_issue(example.description, issue)
+ render_issue(issue)
end
- it 'issues/issue_with_comment.html' do |example|
+ it 'issues/issue_with_comment.html' do
issue = create(:issue, project: project)
create(:note, project: project, noteable: issue, note: '- [ ] Task List Item').save
- render_issue(example.description, issue)
+ render_issue(issue)
end
- it 'issues/issue_list.html' do |example|
+ it 'issues/issue_list.html' do
create(:issue, project: project)
get :index, params: {
@@ -49,12 +49,11 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
private
- def render_issue(fixture_file_name, issue)
+ def render_issue(issue)
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -62,7 +61,6 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller
}
expect(response).to be_success
- store_frontend_fixture(response, fixture_file_name)
end
end
@@ -89,7 +87,7 @@ describe API::Issues, '(JavaScript fixtures)', type: :request do
end
end
- it 'issues/related_merge_requests.json' do |example|
+ it 'issues/related_merge_requests.json' do
user = create(:user)
project = create(:project, :public, creator_id: user.id, namespace: user.namespace)
issue_title = 'foo'
@@ -120,6 +118,5 @@ describe API::Issues, '(JavaScript fixtures)', type: :request do
get_related_merge_requests(project.id, issue.iid, user)
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/jobs.rb b/spec/javascripts/fixtures/jobs.rb
index 941235190b5..46ccd6f8c8a 100644
--- a/spec/javascripts/fixtures/jobs.rb
+++ b/spec/javascripts/fixtures/jobs.rb
@@ -32,7 +32,7 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do
remove_repository(project)
end
- it 'builds/build-with-artifacts.html' do |example|
+ it 'builds/build-with-artifacts.html' do
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -40,10 +40,9 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
- it 'jobs/delayed.json' do |example|
+ it 'jobs/delayed.json' do
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -51,6 +50,5 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do
}, format: :json
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/labels.rb b/spec/javascripts/fixtures/labels.rb
index 9420194e675..4d1b7317274 100644
--- a/spec/javascripts/fixtures/labels.rb
+++ b/spec/javascripts/fixtures/labels.rb
@@ -30,13 +30,12 @@ describe 'Labels (JavaScript fixtures)' do
sign_in(admin)
end
- it 'labels/group_labels.json' do |example|
+ it 'labels/group_labels.json' do
get :index, params: {
group_id: group
}, format: 'json'
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
@@ -47,14 +46,13 @@ describe 'Labels (JavaScript fixtures)' do
sign_in(admin)
end
- it 'labels/project_labels.json' do |example|
+ it 'labels/project_labels.json' do
get :index, params: {
namespace_id: group,
project_id: project
}, format: 'json'
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/fixtures/merge_requests.rb b/spec/javascripts/fixtures/merge_requests.rb
index 7df1e5cb512..05860be2291 100644
--- a/spec/javascripts/fixtures/merge_requests.rb
+++ b/spec/javascripts/fixtures/merge_requests.rb
@@ -42,52 +42,52 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
remove_repository(project)
end
- it 'merge_requests/merge_request_of_current_user.html' do |example|
+ it 'merge_requests/merge_request_of_current_user.html' do
merge_request.update(author: admin)
- render_merge_request(example.description, merge_request)
+ render_merge_request(merge_request)
end
- it 'merge_requests/merge_request_with_task_list.html' do |example|
+ it 'merge_requests/merge_request_with_task_list.html' do
create(:ci_build, :pending, pipeline: pipeline)
- render_merge_request(example.description, merge_request)
+ render_merge_request(merge_request)
end
- it 'merge_requests/merged_merge_request.html' do |example|
+ it 'merge_requests/merged_merge_request.html' do
expect_next_instance_of(MergeRequest) do |merge_request|
allow(merge_request).to receive(:source_branch_exists?).and_return(true)
allow(merge_request).to receive(:can_remove_source_branch?).and_return(true)
end
- render_merge_request(example.description, merged_merge_request)
+ render_merge_request(merged_merge_request)
end
- it 'merge_requests/diff_comment.html' do |example|
+ it 'merge_requests/diff_comment.html' do
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
create(:note_on_merge_request, author: admin, project: project, noteable: merge_request)
- render_merge_request(example.description, merge_request)
+ render_merge_request(merge_request)
end
- it 'merge_requests/merge_request_with_comment.html' do |example|
+ it 'merge_requests/merge_request_with_comment.html' do
create(:note_on_merge_request, author: admin, project: project, noteable: merge_request, note: '- [ ] Task List Item')
- render_merge_request(example.description, merge_request)
+ render_merge_request(merge_request)
end
- it 'merge_requests/discussions.json' do |example|
+ it 'merge_requests/discussions.json' do
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
- render_discussions_json(merge_request, example.description)
+ render_discussions_json(merge_request)
end
- it 'merge_requests/diff_discussion.json' do |example|
+ it 'merge_requests/diff_discussion.json' do
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
- render_discussions_json(merge_request, example.description)
+ render_discussions_json(merge_request)
end
- it 'merge_requests/resolved_diff_discussion.json' do |example|
+ it 'merge_requests/resolved_diff_discussion.json' do
note = create(:discussion_note_on_merge_request, :resolved, project: project, author: admin, position: position, noteable: merge_request)
create(:system_note, project: project, author: admin, noteable: merge_request, discussion_id: note.discussion.id)
- render_discussions_json(merge_request, example.description)
+ render_discussions_json(merge_request)
end
context 'with image diff' do
@@ -106,25 +106,23 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
)
end
- it 'merge_requests/image_diff_discussion.json' do |example|
+ it 'merge_requests/image_diff_discussion.json' do
create(:diff_note_on_merge_request, project: project, noteable: merge_request2, position: image_position)
- render_discussions_json(merge_request2, example.description)
+ render_discussions_json(merge_request2)
end
end
private
- def render_discussions_json(merge_request, fixture_file_name)
+ def render_discussions_json(merge_request)
get :discussions, params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: merge_request.to_param
}, format: :json
-
- store_frontend_fixture(response, fixture_file_name)
end
- def render_merge_request(fixture_file_name, merge_request)
+ def render_merge_request(merge_request)
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -132,6 +130,5 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
}, format: :html
expect(response).to be_success
- store_frontend_fixture(response, fixture_file_name)
end
end
diff --git a/spec/javascripts/fixtures/merge_requests_diffs.rb b/spec/javascripts/fixtures/merge_requests_diffs.rb
index 57462e74bb2..03b9b713fd8 100644
--- a/spec/javascripts/fixtures/merge_requests_diffs.rb
+++ b/spec/javascripts/fixtures/merge_requests_diffs.rb
@@ -34,29 +34,29 @@ describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)', type
remove_repository(project)
end
- it 'merge_request_diffs/with_commit.json' do |example|
+ it 'merge_request_diffs/with_commit.json' do
# Create a user that matches the selected commit author
# This is so that the "author" information will be populated
create(:user, email: selected_commit.author_email, name: selected_commit.author_name)
- render_merge_request(example.description, merge_request, commit_id: selected_commit.sha)
+ render_merge_request(merge_request, commit_id: selected_commit.sha)
end
- it 'merge_request_diffs/inline_changes_tab_with_comments.json' do |example|
+ it 'merge_request_diffs/inline_changes_tab_with_comments.json' do
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
create(:note_on_merge_request, author: admin, project: project, noteable: merge_request)
- render_merge_request(example.description, merge_request)
+ render_merge_request(merge_request)
end
- it 'merge_request_diffs/parallel_changes_tab_with_comments.json' do |example|
+ it 'merge_request_diffs/parallel_changes_tab_with_comments.json' do
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
create(:note_on_merge_request, author: admin, project: project, noteable: merge_request)
- render_merge_request(example.description, merge_request, view: 'parallel')
+ render_merge_request(merge_request, view: 'parallel')
end
private
- def render_merge_request(fixture_file_name, merge_request, view: 'inline', **extra_params)
+ def render_merge_request(merge_request, view: 'inline', **extra_params)
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -66,6 +66,5 @@ describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)', type
}, format: :json
expect(response).to be_success
- store_frontend_fixture(response, fixture_file_name)
end
end
diff --git a/spec/javascripts/fixtures/pdf.rb b/spec/javascripts/fixtures/pdf.rb
deleted file mode 100644
index ef9976b9fd3..00000000000
--- a/spec/javascripts/fixtures/pdf.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'spec_helper'
-
-describe 'PDF file', '(JavaScript fixtures)', type: :controller do
- include JavaScriptFixturesHelpers
-
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
- let(:project) { create(:project, :repository, namespace: namespace, path: 'pdf-project') }
-
- before(:all) do
- clean_frontend_fixtures('blob/pdf/')
- end
-
- it 'blob/pdf/test.pdf' do |example|
- blob = project.repository.blob_at('e774ebd33', 'files/pdf/test.pdf')
-
- store_frontend_fixture(blob.data.force_encoding("utf-8"), example.description)
- end
-end
diff --git a/spec/javascripts/fixtures/pipeline_schedules.rb b/spec/javascripts/fixtures/pipeline_schedules.rb
index e5176a58273..aecd56e6198 100644
--- a/spec/javascripts/fixtures/pipeline_schedules.rb
+++ b/spec/javascripts/fixtures/pipeline_schedules.rb
@@ -21,7 +21,7 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: :
sign_in(admin)
end
- it 'pipeline_schedules/edit.html' do |example|
+ it 'pipeline_schedules/edit.html' do
get :edit, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -29,10 +29,9 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: :
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
- it 'pipeline_schedules/edit_with_variables.html' do |example|
+ it 'pipeline_schedules/edit_with_variables.html' do
get :edit, params: {
namespace_id: project.namespace.to_param,
project_id: project,
@@ -40,6 +39,5 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: :
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/pipelines.rb b/spec/javascripts/fixtures/pipelines.rb
index 42b552e81c0..de6fcfe10f4 100644
--- a/spec/javascripts/fixtures/pipelines.rb
+++ b/spec/javascripts/fixtures/pipelines.rb
@@ -23,13 +23,12 @@ describe Projects::PipelinesController, '(JavaScript fixtures)', type: :controll
sign_in(admin)
end
- it 'pipelines/pipelines.json' do |example|
+ it 'pipelines/pipelines.json' do
get :index, params: {
namespace_id: namespace,
project_id: project
}, format: :json
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/projects.rb b/spec/javascripts/fixtures/projects.rb
index 446da83a7f9..94c59207898 100644
--- a/spec/javascripts/fixtures/projects.rb
+++ b/spec/javascripts/fixtures/projects.rb
@@ -28,49 +28,45 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
end
describe ProjectsController, '(JavaScript fixtures)', type: :controller do
- it 'projects/dashboard.html' do |example|
+ it 'projects/dashboard.html' do
get :show, params: {
namespace_id: project.namespace.to_param,
id: project
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
- it 'projects/overview.html' do |example|
+ it 'projects/overview.html' do
get :show, params: {
namespace_id: project_with_repo.namespace.to_param,
id: project_with_repo
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
- it 'projects/edit.html' do |example|
+ it 'projects/edit.html' do
get :edit, params: {
namespace_id: project.namespace.to_param,
id: project
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
describe Projects::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
- it 'projects/ci_cd_settings.html' do |example|
+ it 'projects/ci_cd_settings.html' do
get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
- it 'projects/ci_cd_settings_with_variables.html' do |example|
+ it 'projects/ci_cd_settings_with_variables.html' do
create(:ci_variable, project: project_variable_populated)
create(:ci_variable, project: project_variable_populated)
@@ -80,7 +76,6 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/fixtures/prometheus_service.rb b/spec/javascripts/fixtures/prometheus_service.rb
index 29dc95305b7..f3171fdd97b 100644
--- a/spec/javascripts/fixtures/prometheus_service.rb
+++ b/spec/javascripts/fixtures/prometheus_service.rb
@@ -22,7 +22,7 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'services/prometheus/prometheus_service.html' do |example|
+ it 'services/prometheus/prometheus_service.html' do
get :edit, params: {
namespace_id: namespace,
project_id: project,
@@ -30,6 +30,5 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/raw.rb b/spec/javascripts/fixtures/raw.rb
index 82770beb39b..801c80a0112 100644
--- a/spec/javascripts/fixtures/raw.rb
+++ b/spec/javascripts/fixtures/raw.rb
@@ -1,34 +1,39 @@
require 'spec_helper'
-describe 'Raw files', '(JavaScript fixtures)', type: :controller do
+describe 'Raw files', '(JavaScript fixtures)' do
include JavaScriptFixturesHelpers
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, :repository, namespace: namespace, path: 'raw-project') }
+ let(:response) { @blob.data.force_encoding('UTF-8') }
before(:all) do
+ clean_frontend_fixtures('blob/balsamiq/')
clean_frontend_fixtures('blob/notebook/')
+ clean_frontend_fixtures('blob/pdf/')
end
after do
remove_repository(project)
end
- it 'blob/notebook/basic.json' do |example|
- blob = project.repository.blob_at('6d85bb69', 'files/ipython/basic.ipynb')
-
- store_frontend_fixture(blob.data, example.description)
+ it 'blob/balsamiq/test.bmpr' do
+ @blob = project.repository.blob_at('b89b56d79', 'files/images/balsamiq.bmpr')
end
- it 'blob/notebook/worksheets.json' do |example|
- blob = project.repository.blob_at('6d85bb69', 'files/ipython/worksheets.ipynb')
+ it 'blob/notebook/basic.json' do
+ @blob = project.repository.blob_at('6d85bb69', 'files/ipython/basic.ipynb')
+ end
- store_frontend_fixture(blob.data, example.description)
+ it 'blob/notebook/worksheets.json' do
+ @blob = project.repository.blob_at('6d85bb69', 'files/ipython/worksheets.ipynb')
end
- it 'blob/notebook/math.json' do |example|
- blob = project.repository.blob_at('93ee732', 'files/ipython/math.ipynb')
+ it 'blob/notebook/math.json' do
+ @blob = project.repository.blob_at('93ee732', 'files/ipython/math.ipynb')
+ end
- store_frontend_fixture(blob.data, example.description)
+ it 'blob/pdf/test.pdf' do
+ @blob = project.repository.blob_at('e774ebd33', 'files/pdf/test.pdf')
end
end
diff --git a/spec/javascripts/fixtures/search.rb b/spec/javascripts/fixtures/search.rb
index 5f5b4d4e60d..22fc546d761 100644
--- a/spec/javascripts/fixtures/search.rb
+++ b/spec/javascripts/fixtures/search.rb
@@ -9,10 +9,9 @@ describe SearchController, '(JavaScript fixtures)', type: :controller do
clean_frontend_fixtures('search/')
end
- it 'search/show.html' do |example|
+ it 'search/show.html' do
get :show
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/services.rb b/spec/javascripts/fixtures/services.rb
index dc7ee484c22..2237702ccca 100644
--- a/spec/javascripts/fixtures/services.rb
+++ b/spec/javascripts/fixtures/services.rb
@@ -22,7 +22,7 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
remove_repository(project)
end
- it 'services/edit_service.html' do |example|
+ it 'services/edit_service.html' do
get :edit, params: {
namespace_id: namespace,
project_id: project,
@@ -30,6 +30,5 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
}
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/sessions.rb b/spec/javascripts/fixtures/sessions.rb
index 8656dea696a..92b74c01c89 100644
--- a/spec/javascripts/fixtures/sessions.rb
+++ b/spec/javascripts/fixtures/sessions.rb
@@ -16,11 +16,10 @@ describe 'Sessions (JavaScript fixtures)' do
set_devise_mapping(context: @request)
end
- it 'sessions/new.html' do |example|
+ it 'sessions/new.html' do
get :new
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/fixtures/snippet.rb b/spec/javascripts/fixtures/snippet.rb
index ebc5b793166..ace84b14eb7 100644
--- a/spec/javascripts/fixtures/snippet.rb
+++ b/spec/javascripts/fixtures/snippet.rb
@@ -23,12 +23,11 @@ describe SnippetsController, '(JavaScript fixtures)', type: :controller do
remove_repository(project)
end
- it 'snippets/show.html' do |example|
+ it 'snippets/show.html' do
create(:discussion_note_on_snippet, noteable: snippet, project: project, author: admin, note: '- [ ] Task List Item')
get(:show, params: { id: snippet.to_param })
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
diff --git a/spec/javascripts/fixtures/todos.rb b/spec/javascripts/fixtures/todos.rb
index 6e37a2e5a4c..d0c8a6eca01 100644
--- a/spec/javascripts/fixtures/todos.rb
+++ b/spec/javascripts/fixtures/todos.rb
@@ -26,11 +26,10 @@ describe 'Todos (JavaScript fixtures)' do
sign_in(admin)
end
- it 'todos/todos.html' do |example|
+ it 'todos/todos.html' do
get :index
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
@@ -41,7 +40,7 @@ describe 'Todos (JavaScript fixtures)' do
sign_in(admin)
end
- it 'todos/todos.json' do |example|
+ it 'todos/todos.json' do
post :create, params: {
namespace_id: namespace,
project_id: project,
@@ -50,7 +49,6 @@ describe 'Todos (JavaScript fixtures)' do
}, format: 'json'
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/fixtures/u2f.rb b/spec/javascripts/fixtures/u2f.rb
index 15866d65a4f..f52832b6efb 100644
--- a/spec/javascripts/fixtures/u2f.rb
+++ b/spec/javascripts/fixtures/u2f.rb
@@ -18,13 +18,12 @@ context 'U2F' do
set_devise_mapping(context: @request)
end
- it 'u2f/authenticate.html' do |example|
+ it 'u2f/authenticate.html' do
allow(controller).to receive(:find_user).and_return(user)
post :create, params: { user: { login: user.username, password: user.password } }
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
@@ -36,11 +35,10 @@ context 'U2F' do
allow_any_instance_of(Profiles::TwoFactorAuthsController).to receive(:build_qr_code).and_return('qrcode:blackandwhitesquares')
end
- it 'u2f/register.html' do |example|
+ it 'u2f/register.html' do
get :show
expect(response).to be_success
- store_frontend_fixture(response, example.description)
end
end
end
diff --git a/spec/javascripts/notes/stores/actions_spec.js b/spec/javascripts/notes/stores/actions_spec.js
index 39901276b8c..7a9f32ddcff 100644
--- a/spec/javascripts/notes/stores/actions_spec.js
+++ b/spec/javascripts/notes/stores/actions_spec.js
@@ -794,6 +794,51 @@ describe('Actions Notes Store', () => {
});
});
+ describe('saveNote', () => {
+ const payload = { endpoint: TEST_HOST, data: { 'note[note]': 'some text' } };
+
+ describe('if response contains errors', () => {
+ const res = { errors: { something: ['went wrong'] } };
+
+ it('throws an error', done => {
+ actions
+ .saveNote(
+ {
+ commit() {},
+ dispatch: () => Promise.resolve(res),
+ },
+ payload,
+ )
+ .then(() => done.fail('Expected error to be thrown!'))
+ .catch(error => {
+ expect(error.message).toBe('Failed to save comment!');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('if response contains no errors', () => {
+ const res = { valid: true };
+
+ it('returns the response', done => {
+ actions
+ .saveNote(
+ {
+ commit() {},
+ dispatch: () => Promise.resolve(res),
+ },
+ payload,
+ )
+ .then(data => {
+ expect(data).toBe(res);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+ });
+
describe('submitSuggestion', () => {
const discussionId = 'discussion-id';
const noteId = 'note-id';
diff --git a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
index a89952ee435..5f4dba5ecb9 100644
--- a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
+++ b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown_spec.js
@@ -3,6 +3,7 @@ import GLDropdown from '~/gl_dropdown'; // eslint-disable-line no-unused-vars
import TimezoneDropdown, {
formatUtcOffset,
formatTimezone,
+ findTimezoneByIdentifier,
} from '~/pages/projects/pipeline_schedules/shared/components/timezone_dropdown';
describe('Timezone Dropdown', function() {
@@ -12,6 +13,7 @@ describe('Timezone Dropdown', function() {
let $dropdownEl = null;
let $wrapper = null;
const tzListSel = '.dropdown-content ul li a.is-active';
+ const tzDropdownToggleText = '.dropdown-toggle-text';
describe('Initialize', () => {
describe('with dropdown already loaded', () => {
@@ -94,6 +96,36 @@ describe('Timezone Dropdown', function() {
expect(onSelectTimezone).toHaveBeenCalled();
});
+
+ it('will correctly set the dropdown label if a timezone identifier is set on the inputEl', () => {
+ $inputEl.val('America/St_Johns');
+
+ // eslint-disable-next-line no-new
+ new TimezoneDropdown({
+ $inputEl,
+ $dropdownEl,
+ displayFormat: selectedItem => formatTimezone(selectedItem),
+ });
+
+ expect($wrapper.find(tzDropdownToggleText).html()).toEqual('[UTC - 2.5] Newfoundland');
+ });
+
+ it('will call a provided `displayFormat` handler to format the dropdown value', () => {
+ const displayFormat = jasmine.createSpy('displayFormat');
+ // eslint-disable-next-line no-new
+ new TimezoneDropdown({
+ $inputEl,
+ $dropdownEl,
+ displayFormat,
+ });
+
+ $wrapper
+ .find(tzListSel)
+ .first()
+ .trigger('click');
+
+ expect(displayFormat).toHaveBeenCalled();
+ });
});
});
@@ -164,4 +196,49 @@ describe('Timezone Dropdown', function() {
).toEqual('[UTC 0] Accra');
});
});
+
+ describe('findTimezoneByIdentifier', () => {
+ const tzList = [
+ {
+ identifier: 'Asia/Tokyo',
+ name: 'Sapporo',
+ offset: 32400,
+ },
+ {
+ identifier: 'Asia/Hong_Kong',
+ name: 'Hong Kong',
+ offset: 28800,
+ },
+ {
+ identifier: 'Asia/Dhaka',
+ name: 'Dhaka',
+ offset: 21600,
+ },
+ ];
+
+ const identifier = 'Asia/Dhaka';
+ it('returns the correct object if the identifier exists', () => {
+ const res = findTimezoneByIdentifier(tzList, identifier);
+
+ expect(res).toBeTruthy();
+ expect(res).toBe(tzList[2]);
+ });
+
+ it('returns null if it doesnt find the identifier', () => {
+ const res = findTimezoneByIdentifier(tzList, 'Australia/Melbourne');
+
+ expect(res).toBeNull();
+ });
+
+ it('returns null if there is no identifier given', () => {
+ expect(findTimezoneByIdentifier(tzList)).toBeNull();
+ expect(findTimezoneByIdentifier(tzList, '')).toBeNull();
+ });
+
+ it('returns null if there is an empty or invalid array given', () => {
+ expect(findTimezoneByIdentifier([], identifier)).toBeNull();
+ expect(findTimezoneByIdentifier(null, identifier)).toBeNull();
+ expect(findTimezoneByIdentifier(undefined, identifier)).toBeNull();
+ });
+ });
});
diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
index e1a2bae5fe8..a02c00e3340 100644
--- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
@@ -222,6 +222,46 @@ describe Gitlab::BitbucketImport::Importer do
body: {}.to_json)
end
+ context 'creating labels on project' do
+ before do
+ allow(importer).to receive(:import_wiki)
+ end
+
+ it 'creates labels as expected' do
+ expect { importer.execute }.to change { Label.count }.from(0).to(Gitlab::BitbucketImport::Importer::LABELS.size)
+ end
+
+ it 'does not fail if label is already existing' do
+ label = Gitlab::BitbucketImport::Importer::LABELS.first
+ ::Labels::CreateService.new(label).execute(project: project)
+
+ expect { importer.execute }.not_to raise_error
+ end
+
+ it 'does not create new labels' do
+ Gitlab::BitbucketImport::Importer::LABELS.each do |label|
+ create(:label, project: project, title: label[:title])
+ end
+
+ expect { importer.execute }.not_to change { Label.count }
+ end
+
+ it 'does not update existing ones' do
+ label_title = Gitlab::BitbucketImport::Importer::LABELS.first[:title]
+ existing_label = create(:label, project: project, title: label_title)
+ # Reload label from database so we avoid timestamp comparison issues related to time precision when comparing
+ # attributes later.
+ existing_label.reload
+
+ Timecop.freeze(Time.now + 1.minute) do
+ importer.execute
+
+ label_after_import = project.labels.find(existing_label.id)
+ expect(label_after_import.attributes).to eq(existing_label.attributes)
+ end
+ end
+ end
+
it 'maps statuses to open or closed' do
allow(importer).to receive(:import_wiki)
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 4e910e67ac2..aa975c8bb0b 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -35,7 +35,7 @@ describe Gitlab::UsageData do
subject { described_class.data }
it "gathers usage data" do
- expect(subject.keys).to match_array(%i(
+ expect(subject.keys).to include(*%i(
active_user_count
counts
recorded_at
@@ -68,7 +68,7 @@ describe Gitlab::UsageData do
expect(count_data[:boards]).to eq(1)
expect(count_data[:projects]).to eq(3)
- expect(count_data.keys).to match_array(%i(
+ expect(count_data.keys).to include(*%i(
assignee_lists
boards
ci_builds
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index 4a7eee1fbf3..04ae9390436 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -166,6 +166,13 @@ describe JiraService do
).once
end
+ it 'does not fail if remote_link.all on issue returns nil' do
+ allow(JIRA::Resource::Remotelink).to receive(:all).and_return(nil)
+
+ expect { @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project)) }
+ .not_to raise_error(NoMethodError)
+ end
+
# Check https://developer.atlassian.com/jiradev/jira-platform/guides/other/guide-jira-remote-issue-links/fields-in-remote-issue-links
# for more information
it 'creates Remote Link reference in JIRA for comment' do
diff --git a/spec/models/user_preference_spec.rb b/spec/models/user_preference_spec.rb
index b2ef17a81d4..e09c91e874a 100644
--- a/spec/models/user_preference_spec.rb
+++ b/spec/models/user_preference_spec.rb
@@ -73,4 +73,10 @@ describe UserPreference do
it_behaves_like 'a sort_by preference'
end
end
+
+ describe '#timezone' do
+ it 'returns server time as default' do
+ expect(user_preference.timezone).to eq(Time.zone.tzinfo.name)
+ end
+ end
end
diff --git a/spec/requests/api/graphql/gitlab_schema_spec.rb b/spec/requests/api/graphql/gitlab_schema_spec.rb
index b63b4fb34df..dd518274f82 100644
--- a/spec/requests/api/graphql/gitlab_schema_spec.rb
+++ b/spec/requests/api/graphql/gitlab_schema_spec.rb
@@ -3,15 +3,43 @@ require 'spec_helper'
describe 'GitlabSchema configurations' do
include GraphqlHelpers
- it 'shows an error if complexity is too high' do
- project = create(:project, :repository)
- query = graphql_query_for('project', { 'fullPath' => project.full_path }, %w(id name description))
+ let(:project) { create(:project, :repository) }
+ let(:query) { graphql_query_for('project', { 'fullPath' => project.full_path }, %w(id name description)) }
+ let(:current_user) { create(:user) }
- allow(GitlabSchema).to receive(:max_query_complexity).and_return 1
+ describe '#max_complexity' do
+ context 'when complexity is too high' do
+ it 'shows an error' do
+ allow(GitlabSchema).to receive(:max_query_complexity).and_return 1
- post_graphql(query, current_user: nil)
+ post_graphql(query, current_user: nil)
- expect(graphql_errors.first['message']).to include('which exceeds max complexity of 1')
+ expect(graphql_errors.first['message']).to include('which exceeds max complexity of 1')
+ end
+ end
+ end
+
+ describe '#max_depth' do
+ context 'when query depth is too high' do
+ it 'shows error' do
+ errors = [{ "message" => "Query has depth of 2, which exceeds max depth of 1" }]
+ allow(GitlabSchema).to receive(:max_query_depth).and_return 1
+
+ post_graphql(query)
+
+ expect(graphql_errors).to eq(errors)
+ end
+ end
+
+ context 'when query depth is within range' do
+ it 'has no error' do
+ allow(GitlabSchema).to receive(:max_query_depth).and_return 5
+
+ post_graphql(query)
+
+ expect(graphql_errors).to be_nil
+ end
+ end
end
context 'when IntrospectionQuery' do
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index 2c4fb131ed9..674fe0f666e 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -44,7 +44,18 @@ describe Members::CreateService do
result = described_class.new(user, params).execute(project)
expect(result[:status]).to eq(:error)
- expect(result[:message]).to include(project_user.username)
+ expect(result[:message]).to include("#{project_user.username}: Access level is not included in the list")
expect(project.users).not_to include project_user
end
+
+ it 'does not add a member with an existing invite' do
+ invited_member = create(:project_member, :invited, project: project)
+
+ params = { user_ids: invited_member.invite_email,
+ access_level: Gitlab::Access::GUEST }
+ result = described_class.new(user, params).execute(project)
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Invite email has already been taken')
+ end
end
diff --git a/spec/services/projects/after_import_service_spec.rb b/spec/services/projects/after_import_service_spec.rb
index 95c11f71c5e..51d3fd18881 100644
--- a/spec/services/projects/after_import_service_spec.rb
+++ b/spec/services/projects/after_import_service_spec.rb
@@ -15,7 +15,7 @@ describe Projects::AfterImportService do
describe '#execute' do
before do
allow(Projects::HousekeepingService)
- .to receive(:new).with(project, :gc).and_return(housekeeping_service)
+ .to receive(:new).with(project).and_return(housekeeping_service)
allow(housekeeping_service)
.to receive(:execute).and_yield
diff --git a/spec/services/projects/detect_repository_languages_service_spec.rb b/spec/services/projects/detect_repository_languages_service_spec.rb
index e3e561c971c..df5eed18ac0 100644
--- a/spec/services/projects/detect_repository_languages_service_spec.rb
+++ b/spec/services/projects/detect_repository_languages_service_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
describe Projects::DetectRepositoryLanguagesService, :clean_gitlab_redis_shared_state do
set(:project) { create(:project, :repository) }
- subject { described_class.new(project, project.owner) }
+ subject { described_class.new(project) }
describe '#execute' do
context 'without previous detection' do
diff --git a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
index d8427d0bf78..80debcd3a7a 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
@@ -33,7 +33,10 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do
before do
allow(project).to receive(:lfs_enabled?).and_return(true)
- allow(Gitlab::HTTP).to receive(:post).and_return(objects_response)
+ response = instance_double(HTTParty::Response)
+ allow(response).to receive(:body).and_return(objects_response.to_json)
+ allow(response).to receive(:success?).and_return(true)
+ allow(Gitlab::HTTP).to receive(:post).and_return(response)
end
describe '#execute' do
@@ -89,6 +92,21 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do
expect { subject.send(:get_download_links, new_oids) }.to raise_error(described_class::DownloadLinksError)
end
+
+ shared_examples 'JSON parse errors' do |body|
+ it 'raises error' do
+ response = instance_double(HTTParty::Response)
+ allow(response).to receive(:body).and_return(body)
+ allow(response).to receive(:success?).and_return(true)
+ allow(Gitlab::HTTP).to receive(:post).and_return(response)
+
+ expect { subject.send(:get_download_links, new_oids) }.to raise_error(described_class::DownloadLinksError)
+ end
+ end
+
+ it_behaves_like 'JSON parse errors', '{'
+ it_behaves_like 'JSON parse errors', '{}'
+ it_behaves_like 'JSON parse errors', '{ foo: 123 }'
end
describe '#parse_response_links' do
diff --git a/spec/services/projects/repository_languages_service_spec.rb b/spec/services/projects/repository_languages_service_spec.rb
index 09c61363ad2..46c5095327d 100644
--- a/spec/services/projects/repository_languages_service_spec.rb
+++ b/spec/services/projects/repository_languages_service_spec.rb
@@ -10,7 +10,7 @@ describe Projects::RepositoryLanguagesService do
context 'when a project is without detected programming languages' do
it 'schedules a worker and returns the empty result' do
- expect(::DetectRepositoryLanguagesWorker).to receive(:perform_async).with(project.id, project.owner.id)
+ expect(::DetectRepositoryLanguagesWorker).to receive(:perform_async).with(project.id)
expect(service.execute).to eq([])
end
end
@@ -19,7 +19,7 @@ describe Projects::RepositoryLanguagesService do
let!(:repository_language) { create(:repository_language, project: project) }
it 'does not schedule a worker and returns the detected languages' do
- expect(::DetectRepositoryLanguagesWorker).not_to receive(:perform_async).with(project.id, project.owner.id)
+ expect(::DetectRepositoryLanguagesWorker).not_to receive(:perform_async).with(project.id)
languages = service.execute
diff --git a/spec/services/users/update_service_spec.rb b/spec/services/users/update_service_spec.rb
index e04c05418b0..9384287f98a 100644
--- a/spec/services/users/update_service_spec.rb
+++ b/spec/services/users/update_service_spec.rb
@@ -13,6 +13,15 @@ describe Users::UpdateService do
expect(user.name).to eq('New Name')
end
+ it 'updates time preferences' do
+ result = update_user(user, timezone: 'Europe/Warsaw', time_display_relative: true, time_format_in_24h: false)
+
+ expect(result).to eq(status: :success)
+ expect(user.reload.timezone).to eq('Europe/Warsaw')
+ expect(user.time_display_relative).to eq(true)
+ expect(user.time_format_in_24h).to eq(false)
+ end
+
it 'returns an error result when record cannot be updated' do
result = {}
expect do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 9266bee34d6..69589c9aa33 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -138,7 +138,7 @@ RSpec.configure do |config|
.and_return(false)
end
- config.before(:example, :quarantine) do
+ config.around(:example, :quarantine) do
# Skip tests in quarantine unless we explicitly focus on them.
skip('In quarantine') unless config.inclusion_filter[:quarantine]
end
diff --git a/spec/support/features/variable_list_shared_examples.rb b/spec/support/features/variable_list_shared_examples.rb
index 693b796fbdc..92a19dd22a2 100644
--- a/spec/support/features/variable_list_shared_examples.rb
+++ b/spec/support/features/variable_list_shared_examples.rb
@@ -17,7 +17,7 @@ shared_examples 'variable list' do
visit page_path
# We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-key').value).to eq('key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
end
@@ -38,7 +38,7 @@ shared_examples 'variable list' do
visit page_path
# We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-key').value).to eq('key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
@@ -59,7 +59,7 @@ shared_examples 'variable list' do
visit page_path
# We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-key').value).to eq('key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
@@ -116,19 +116,19 @@ shared_examples 'variable list' do
page.within('.js-ci-variable-list-section') do
expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
expect(first('.js-ci-variable-input-value', visible: false).value).to eq(variable.value)
- expect(page).to have_content('*' * 20)
+ expect(page).to have_content('*' * 17)
click_button('Reveal value')
expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
expect(first('.js-ci-variable-input-value').value).to eq(variable.value)
- expect(page).not_to have_content('*' * 20)
+ expect(page).not_to have_content('*' * 17)
click_button('Hide value')
expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
expect(first('.js-ci-variable-input-value', visible: false).value).to eq(variable.value)
- expect(page).to have_content('*' * 20)
+ expect(page).to have_content('*' * 17)
end
end
@@ -149,7 +149,7 @@ shared_examples 'variable list' do
page.within('.js-ci-variable-list-section') do
click_button('Reveal value')
- page.within('.js-row:nth-child(1)') do
+ page.within('.js-row:nth-child(2)') do
find('.js-ci-variable-input-key').set('new_key')
find('.js-ci-variable-input-value').set('new_value')
end
@@ -159,7 +159,7 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-row:nth-child(1)') do
+ page.within('.js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-key').value).to eq('new_key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('new_value')
end
@@ -181,7 +181,7 @@ shared_examples 'variable list' do
visit page_path
# We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(3)') do
find('.ci-variable-protected-item .js-project-feature-toggle').click
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
@@ -193,7 +193,7 @@ shared_examples 'variable list' do
visit page_path
# We check the first row because it re-sorts to alphabetical order on refresh
- page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(3)') do
expect(find('.js-ci-variable-input-key').value).to eq('unprotected_key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('unprotected_value')
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
@@ -215,7 +215,7 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
find('.ci-variable-protected-item .js-project-feature-toggle').click
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('false')
@@ -226,7 +226,7 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-key').value).to eq('protected_key')
expect(find('.js-ci-variable-input-value', visible: false).value).to eq('protected_value')
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('false')
@@ -234,7 +234,7 @@ shared_examples 'variable list' do
end
it 'edits variable to be unmasked' do
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
find('.ci-variable-masked-item .js-project-feature-toggle').click
@@ -247,13 +247,13 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
end
end
it 'edits variable to be masked' do
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
find('.ci-variable-masked-item .js-project-feature-toggle').click
@@ -266,7 +266,7 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('false')
find('.ci-variable-masked-item .js-project-feature-toggle').click
@@ -279,7 +279,7 @@ shared_examples 'variable list' do
visit page_path
- page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
+ page.within('.js-ci-variable-list-section .js-row:nth-child(2)') do
expect(find('.js-ci-variable-input-masked', visible: false).value).to eq('true')
end
end
@@ -302,7 +302,7 @@ shared_examples 'variable list' do
expect(page).to have_selector('.js-row', count: 4)
# Remove the `akey` variable
- page.within('.js-row:nth-child(2)') do
+ page.within('.js-row:nth-child(3)') do
first('.js-row-remove-button').click
end
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index b49d743fb9a..f15944652fd 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -102,6 +102,7 @@ module GraphqlHelpers
def all_graphql_fields_for(class_name, parent_types = Set.new)
allow_unlimited_graphql_complexity
+ allow_unlimited_graphql_depth
type = GitlabSchema.types[class_name.to_s]
return "" unless type
@@ -190,4 +191,9 @@ module GraphqlHelpers
allow_any_instance_of(GitlabSchema).to receive(:max_complexity).and_return nil
allow(GitlabSchema).to receive(:max_query_complexity).with(any_args).and_return nil
end
+
+ def allow_unlimited_graphql_depth
+ allow_any_instance_of(GitlabSchema).to receive(:max_depth).and_return nil
+ allow(GitlabSchema).to receive(:max_query_depth).with(any_args).and_return nil
+ end
end
diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index 494398dc4de..cdd7724cc13 100644
--- a/spec/support/helpers/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
@@ -11,6 +11,10 @@ module JavaScriptFixturesHelpers
base.around do |example|
# pick an arbitrary date from the past, so tests are not time dependent
Timecop.freeze(Time.utc(2015, 7, 3, 10)) { example.run }
+
+ raise NoMethodError.new('You need to set `response` for the fixture generator! This will automatically happen with `type: :controller` or `type: :request`.', 'response') unless respond_to?(:response)
+
+ store_frontend_fixture(response, example.description)
end
end
@@ -29,7 +33,13 @@ module JavaScriptFixturesHelpers
end
end
- # Public: Store a response object as fixture file
+ def remove_repository(project)
+ Gitlab::Shell.new.remove_repository(project.repository_storage, project.disk_path)
+ end
+
+ private
+
+ # Private: Store a response object as fixture file
#
# response - string or response object to store
# fixture_file_name - file name to store the fixture in (relative to .fixture_root_path)
@@ -42,12 +52,6 @@ module JavaScriptFixturesHelpers
File.write(full_fixture_path, fixture)
end
- def remove_repository(project)
- Gitlab::Shell.new.remove_repository(project.repository_storage, project.disk_path)
- end
-
- private
-
# Private: Prepare a response object for use as a frontend fixture
#
# response - response object to prepare
diff --git a/spec/support/helpers/project_forks_helper.rb b/spec/support/helpers/project_forks_helper.rb
index 9a86560da2a..bcb11a09b36 100644
--- a/spec/support/helpers/project_forks_helper.rb
+++ b/spec/support/helpers/project_forks_helper.rb
@@ -1,5 +1,11 @@
module ProjectForksHelper
def fork_project(project, user = nil, params = {})
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ fork_project_direct(project, user, params)
+ end
+ end
+
+ def fork_project_direct(project, user = nil, params = {})
# Load the `fork_network` for the project to fork as there might be one that
# wasn't loaded yet.
project.reload unless project.fork_network
@@ -44,11 +50,16 @@ module ProjectForksHelper
end
def fork_project_with_submodules(project, user = nil, params = {})
- forked_project = fork_project(project, user, params)
- TestEnv.copy_repo(forked_project,
- bare_repo: TestEnv.forked_repo_path_bare,
- refs: TestEnv::FORKED_BRANCH_SHA)
- forked_project.repository.after_import
- forked_project
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ forked_project = fork_project_direct(project, user, params)
+ TestEnv.copy_repo(
+ forked_project,
+ bare_repo: TestEnv.forked_repo_path_bare,
+ refs: TestEnv::FORKED_BRANCH_SHA
+ )
+ forked_project.repository.after_import
+
+ forked_project
+ end
end
end
diff --git a/spec/workers/detect_repository_languages_worker_spec.rb b/spec/workers/detect_repository_languages_worker_spec.rb
index dbf32555985..755eb8dbf6b 100644
--- a/spec/workers/detect_repository_languages_worker_spec.rb
+++ b/spec/workers/detect_repository_languages_worker_spec.rb
@@ -4,7 +4,6 @@ require 'spec_helper'
describe DetectRepositoryLanguagesWorker do
set(:project) { create(:project) }
- let(:user) { project.owner }
subject { described_class.new }
@@ -14,19 +13,13 @@ describe DetectRepositoryLanguagesWorker do
allow(::Projects::DetectRepositoryLanguagesService).to receive(:new).and_return(service)
expect(service).to receive(:execute)
- subject.perform(project.id, user.id)
+ subject.perform(project.id)
end
context 'when invalid ids are used' do
it 'does not raise when the project could not be found' do
expect do
- subject.perform(-1, user.id)
- end.not_to raise_error
- end
-
- it 'does not raise when the user could not be found' do
- expect do
- subject.perform(project.id, -1)
+ subject.perform(-1)
end.not_to raise_error
end
end