diff options
228 files changed, 1262 insertions, 371 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b2d75a829fc..0c662f42111 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -463,19 +463,19 @@ danger-review: rspec-pg: <<: *rspec-metadata-pg - parallel: 30 + parallel: 50 rspec-mysql: <<: *rspec-metadata-mysql - parallel: 30 + parallel: 50 rspec-pg-rails4: <<: *rspec-metadata-pg-rails4 - parallel: 30 + parallel: 50 rspec-mysql-rails4: <<: *rspec-metadata-mysql-rails4 - parallel: 30 + parallel: 50 static-analysis: <<: *dedicated-no-docs-no-db-pull-cache-job diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e5296e231e..54ea014a679 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 11.4.6 (2018-11-18) + +### Security (1 change) + +- Escape user fullname while rendering autocomplete template to prevent XSS. + + ## 11.4.5 (2018-11-04) ### Fixed (4 changes, 1 of them is from the community) @@ -271,6 +278,13 @@ entry. - Check frozen string in style builds. (gfyoung) +## 11.3.10 (2018-11-18) + +### Security (1 change) + +- Escape user fullname while rendering autocomplete template to prevent XSS. + + ## 11.3.9 (2018-10-31) ### Security (1 change) @@ -389,7 +389,7 @@ group :test do gem 'rails-controller-testing' if rails5? # Rails5 only gem. gem 'test_after_commit', '~> 1.1' unless rails5? # Remove this gem when migrated to rails 5.0. It's been integrated to rails 5.0. gem 'sham_rack', '~> 1.3.6' - gem 'concurrent-ruby', '~> 1.0.5' + gem 'concurrent-ruby', '~> 1.1' gem 'test-prof', '~> 0.2.5' gem 'rspec_junit_formatter' end diff --git a/Gemfile.lock b/Gemfile.lock index 975243f31d5..380f1dbc89f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -128,9 +128,9 @@ GEM concord (0.1.5) adamantium (~> 0.2.0) equalizer (~> 0.0.9) - concurrent-ruby (1.0.5) - concurrent-ruby-ext (1.0.5) - concurrent-ruby (= 1.0.5) + concurrent-ruby (1.1.3) + concurrent-ruby-ext (1.1.3) + concurrent-ruby (= 1.1.3) connection_pool (2.2.2) crack (0.4.3) safe_yaml (~> 1.0.0) @@ -379,7 +379,7 @@ GEM json (~> 1.8) multi_xml (>= 0.5.2) httpclient (2.8.3) - i18n (1.1.0) + i18n (1.1.1) concurrent-ruby (~> 1.0) icalendar (2.4.1) ice_nine (0.11.2) @@ -444,7 +444,7 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.2.2) + loofah (2.2.3) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.0) @@ -453,7 +453,7 @@ GEM memoist (0.16.0) memoizable (0.4.2) thread_safe (~> 0.3, >= 0.3.1) - method_source (0.9.0) + method_source (0.9.2) mime-types (3.2.2) mime-types-data (~> 3.2015) mime-types-data (3.2018.0812) @@ -475,7 +475,7 @@ GEM net-ssh (5.0.1) netrc (0.11.0) nio4r (2.3.1) - nokogiri (1.8.4) + nokogiri (1.8.5) mini_portile2 (~> 2.3.0) nokogumbo (1.5.0) nokogiri @@ -603,7 +603,7 @@ GEM get_process_mem (~> 0.2) puma (>= 2.7, < 4) pyu-ruby-sasl (0.0.3.3) - rack (2.0.5) + rack (2.0.6) rack-accept (0.4.5) rack (>= 0.4) rack-attack (4.4.1) @@ -767,8 +767,8 @@ GEM ruby-progressbar (1.9.0) ruby-saml (1.7.2) nokogiri (>= 1.5.10) - ruby_parser (3.9.0) - sexp_processor (~> 4.1) + ruby_parser (3.11.0) + sexp_processor (~> 4.9) rubyntlm (0.6.2) rubypants (0.2.0) rubyzip (1.2.2) @@ -808,7 +808,7 @@ GEM sentry-raven (2.7.2) faraday (>= 0.7.6, < 1.0) settingslogic (2.0.9) - sexp_processor (4.9.0) + sexp_processor (4.11.0) sham_rack (1.3.6) rack shoulda-matchers (3.1.2) @@ -967,7 +967,7 @@ DEPENDENCIES chronic (~> 0.10.2) chronic_duration (~> 0.10.6) commonmarker (~> 0.17) - concurrent-ruby (~> 1.0.5) + concurrent-ruby (~> 1.1) connection_pool (~> 2.0) creole (~> 0.5.0) database_cleaner (~> 1.5.0) diff --git a/Gemfile.rails4.lock b/Gemfile.rails4.lock index 657975da2a4..ead404c5f27 100644 --- a/Gemfile.rails4.lock +++ b/Gemfile.rails4.lock @@ -125,9 +125,9 @@ GEM concord (0.1.5) adamantium (~> 0.2.0) equalizer (~> 0.0.9) - concurrent-ruby (1.0.5) - concurrent-ruby-ext (1.0.5) - concurrent-ruby (= 1.0.5) + concurrent-ruby (1.1.3) + concurrent-ruby-ext (1.1.3) + concurrent-ruby (= 1.1.3) connection_pool (2.2.2) crack (0.4.3) safe_yaml (~> 1.0.0) @@ -441,7 +441,7 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.2.2) + loofah (2.2.3) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.0) @@ -471,7 +471,7 @@ GEM net-ldap (0.16.0) net-ssh (5.0.1) netrc (0.11.0) - nokogiri (1.8.4) + nokogiri (1.8.5) mini_portile2 (~> 2.3.0) nokogumbo (1.5.0) nokogiri @@ -759,8 +759,8 @@ GEM ruby-progressbar (1.9.0) ruby-saml (1.7.2) nokogiri (>= 1.5.10) - ruby_parser (3.9.0) - sexp_processor (~> 4.1) + ruby_parser (3.11.0) + sexp_processor (~> 4.9) rubyntlm (0.6.2) rubypants (0.2.0) rubyzip (1.2.2) @@ -800,7 +800,7 @@ GEM sentry-raven (2.7.2) faraday (>= 0.7.6, < 1.0) settingslogic (2.0.9) - sexp_processor (4.9.0) + sexp_processor (4.11.0) sham_rack (1.3.6) rack shoulda-matchers (3.1.2) @@ -958,7 +958,7 @@ DEPENDENCIES chronic (~> 0.10.2) chronic_duration (~> 0.10.6) commonmarker (~> 0.17) - concurrent-ruby (~> 1.0.5) + concurrent-ruby (~> 1.1) connection_pool (~> 2.0) creole (~> 0.5.0) database_cleaner (~> 1.5.0) diff --git a/PROCESS.md b/PROCESS.md index 5fc2c4cf1df..aadd6a321f0 100644 --- a/PROCESS.md +++ b/PROCESS.md @@ -95,6 +95,12 @@ picked into the stable branches) up to the 19th of the month. Such merge requests should have the ~"feature flag" label assigned, and don't require a corresponding exception request to be created. +In order to build the final package and present the feature for self-hosted +customers, the feature flag should be removed. This should happen before the +22nd, ideally _at least_ 2 days before. That means MRs with feature +flags being picked at the 19th would have a quite tight schedule, so picking +these _earlier_ is preferable. + While rare, release managers may decide to reject picking a change into a stable branch, even when feature flags are used. This might be necessary if the changes are deemed problematic, too invasive, or there simply isn't enough time to diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js index c0c21416275..8542a6e718a 100644 --- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js +++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js @@ -112,7 +112,7 @@ const JumpToDiscussion = Vue.extend({ if (!hasDiscussionsToJumpTo) { // If there are no discussions to jump to on the current page, - // switch to the notes tab and jump to the first disucssion there. + // switch to the notes tab and jump to the first discussion there. window.mrTabs.activateTab('show'); activeTab = 'show'; jumpToFirstDiscussion = true; diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js index 05e32e3c1f1..6a87b712b48 100644 --- a/app/assets/javascripts/diffs/store/getters.js +++ b/app/assets/javascripts/diffs/store/getters.js @@ -23,7 +23,7 @@ export const diffHasAllExpandedDiscussions = (state, getters) => diff => { }; /** - * Checks if the diff has all discussions collpased + * Checks if the diff has all discussions collapsed * @param {Object} diff * @returns {Boolean} */ diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js index 00b3d283570..6f8b73564d0 100644 --- a/app/assets/javascripts/gfm_auto_complete.js +++ b/app/assets/javascripts/gfm_auto_complete.js @@ -151,10 +151,16 @@ class GfmAutoComplete { // Team Members $input.atwho({ at: '@', + alias: 'users', displayTpl(value) { let tmpl = GfmAutoComplete.Loading.template; - if (value.username != null) { - tmpl = GfmAutoComplete.Members.template; + const { avatarTag, username, title } = value; + if (username != null) { + tmpl = GfmAutoComplete.Members.templateFunction({ + avatarTag, + username, + title, + }); } return tmpl; }, @@ -565,8 +571,9 @@ GfmAutoComplete.Emoji = { }; // Team Members GfmAutoComplete.Members = { - // eslint-disable-next-line no-template-curly-in-string - template: '<li>${avatarTag} ${username} <small>${title}</small></li>', + templateFunction({ avatarTag, username, title }) { + return `<li>${avatarTag} ${username} <small>${_.escape(title)}</small></li>`; + }, }; GfmAutoComplete.Labels = { template: diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js index c52cfb806a2..3618c6af7e2 100644 --- a/app/assets/javascripts/lib/utils/text_markdown.js +++ b/app/assets/javascripts/lib/utils/text_markdown.js @@ -39,7 +39,7 @@ function blockTagText(text, textArea, blockTag, selected) { } } -function moveCursor({ textArea, tag, wrapped, removedLastNewLine, select }) { +function moveCursor({ textArea, tag, positionBetweenTags, removedLastNewLine, select }) { var pos; if (!textArea.setSelectionRange) { return; @@ -51,7 +51,7 @@ function moveCursor({ textArea, tag, wrapped, removedLastNewLine, select }) { return textArea.setSelectionRange(startPosition, endPosition); } if (textArea.selectionStart === textArea.selectionEnd) { - if (wrapped) { + if (positionBetweenTags) { pos = textArea.selectionStart - tag.length; } else { pos = textArea.selectionStart; @@ -67,7 +67,6 @@ function moveCursor({ textArea, tag, wrapped, removedLastNewLine, select }) { export function insertMarkdownText({ textArea, text, tag, blockTag, selected, wrap, select }) { var textToInsert, - inserted, selectedSplit, startChar, removedLastNewLine, @@ -155,7 +154,7 @@ export function insertMarkdownText({ textArea, text, tag, blockTag, selected, wr return moveCursor({ textArea, tag: tag.replace(textPlaceholder, selected), - wrap, + positionBetweenTags: wrap && selected.length === 0, removedLastNewLine, select, }); @@ -171,10 +170,6 @@ function updateText({ textArea, tag, blockTag, wrap, select }) { return insertMarkdownText({ textArea, text, tag, blockTag, selected, wrap, select }); } -function replaceRange(s, start, end, substitute) { - return s.substring(0, start) + substitute + s.substring(end); -} - export function addMarkdownListeners(form) { return $('.js-md', form) .off('click') diff --git a/app/assets/javascripts/notebook/cells/output/index.vue b/app/assets/javascripts/notebook/cells/output/index.vue index d9f8604ed10..bd0bcc0d819 100644 --- a/app/assets/javascripts/notebook/cells/output/index.vue +++ b/app/assets/javascripts/notebook/cells/output/index.vue @@ -22,7 +22,7 @@ export default { }, output: { type: Object, - requred: true, + required: true, default: () => ({}), }, }, diff --git a/app/assets/javascripts/pages/users/user_overview_block.js b/app/assets/javascripts/pages/users/user_overview_block.js index 2ed177be558..eec2b5ca8e5 100644 --- a/app/assets/javascripts/pages/users/user_overview_block.js +++ b/app/assets/javascripts/pages/users/user_overview_block.js @@ -10,6 +10,7 @@ export default class UserOverviewBlock { limit: DEFAULT_LIMIT, ...options.requestParams, }; + this.postRenderCallback = options.postRenderCallback; this.loadData(); } @@ -43,5 +44,9 @@ export default class UserOverviewBlock { } loadingEl.classList.add('hide'); + + if (this.postRenderCallback) { + this.postRenderCallback.call(this); + } } } diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js index 04bcb16f036..aa537d4a43e 100644 --- a/app/assets/javascripts/pages/users/user_tabs.js +++ b/app/assets/javascripts/pages/users/user_tabs.js @@ -2,7 +2,8 @@ import $ from 'jquery'; import axios from '~/lib/utils/axios_utils'; import Activities from '~/activities'; import { localTimeAgo } from '~/lib/utils/datetime_utility'; -import { __, sprintf } from '~/locale'; +import AjaxCache from '~/lib/utils/ajax_cache'; +import { __ } from '~/locale'; import flash from '~/flash'; import ActivityCalendar from './activity_calendar'; import UserOverviewBlock from './user_overview_block'; @@ -62,23 +63,20 @@ import UserOverviewBlock from './user_overview_block'; * </div> */ -const CALENDAR_TEMPLATES = { - activity: ` - <div class="clearfix calendar"> - <div class="js-contrib-calendar"></div> - <div class="calendar-hint bottom-right"></div> - </div> - `, - overview: ` - <div class="clearfix calendar"> - <div class="calendar-hint"></div> - <div class="js-contrib-calendar prepend-top-20"></div> - </div> - `, -}; +const CALENDAR_TEMPLATE = ` + <div class="clearfix calendar"> + <div class="js-contrib-calendar"></div> + <div class="calendar-hint bottom-right"></div> + </div> +`; const CALENDAR_PERIOD_6_MONTHS = 6; const CALENDAR_PERIOD_12_MONTHS = 12; +/* computation based on + * width = (group + 1) * this.daySizeWithSpace + this.getExtraWidthPadding(group); + * (see activity_calendar.js) + */ +const OVERVIEW_CALENDAR_BREAKPOINT = 918; export default class UserTabs { constructor({ defaultAction, action, parentEl }) { @@ -105,6 +103,12 @@ export default class UserTabs { .off('shown.bs.tab', '.nav-links a[data-toggle="tab"]') .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event)) .on('click', '.gl-pagination a', event => this.changeProjectsPage(event)); + + window.addEventListener('resize', () => this.onResize()); + } + + onResize() { + this.loadActivityCalendar(); } changeProjectsPage(e) { @@ -167,8 +171,6 @@ export default class UserTabs { return; } - this.loadActivityCalendar('activity'); - // eslint-disable-next-line no-new new Activities('#activity'); @@ -180,10 +182,10 @@ export default class UserTabs { return; } - this.loadActivityCalendar('overview'); + this.loadActivityCalendar(); UserTabs.renderMostRecentBlocks('#js-overview .activities-block', { - requestParams: { limit: 5 }, + requestParams: { limit: 10 }, }); UserTabs.renderMostRecentBlocks('#js-overview .projects-block', { requestParams: { limit: 10, skip_pagination: true }, @@ -198,52 +200,39 @@ export default class UserTabs { container, url: $(`${container} .overview-content-list`).data('href'), ...options, + postRenderCallback: () => localTimeAgo($('.js-timeago', container)), }); } - loadActivityCalendar(action) { - const monthsAgo = action === 'overview' ? CALENDAR_PERIOD_6_MONTHS : CALENDAR_PERIOD_12_MONTHS; + loadActivityCalendar() { const $calendarWrap = this.$parentEl.find('.tab-pane.active .user-calendar'); const calendarPath = $calendarWrap.data('calendarPath'); + + AjaxCache.retrieve(calendarPath) + .then(data => UserTabs.renderActivityCalendar(data, $calendarWrap)) + .catch(() => flash(__('There was an error loading users activity calendar.'))); + } + + static renderActivityCalendar(data, $calendarWrap) { + const monthsAgo = UserTabs.getVisibleCalendarPeriod($calendarWrap); const calendarActivitiesPath = $calendarWrap.data('calendarActivitiesPath'); const utcOffset = $calendarWrap.data('utcOffset'); - let utcFormatted = 'UTC'; - if (utcOffset !== 0) { - utcFormatted = `UTC${utcOffset > 0 ? '+' : ''}${utcOffset / 3600}`; - } + const calendarHint = __('Issues, merge requests, pushes and comments.'); - axios - .get(calendarPath) - .then(({ data }) => { - $calendarWrap.html(CALENDAR_TEMPLATES[action]); - - let calendarHint = ''; - - if (action === 'activity') { - calendarHint = sprintf( - __( - 'Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})', - ), - { utcFormatted }, - ); - } else if (action === 'overview') { - calendarHint = __('Issues, merge requests, pushes and comments.'); - } - - $calendarWrap.find('.calendar-hint').text(calendarHint); - - // eslint-disable-next-line no-new - new ActivityCalendar( - '.tab-pane.active .js-contrib-calendar', - '.tab-pane.active .user-calendar-activities', - data, - calendarActivitiesPath, - utcOffset, - 0, - monthsAgo, - ); - }) - .catch(() => flash(__('There was an error loading users activity calendar.'))); + $calendarWrap.html(CALENDAR_TEMPLATE); + + $calendarWrap.find('.calendar-hint').text(calendarHint); + + // eslint-disable-next-line no-new + new ActivityCalendar( + '.tab-pane.active .js-contrib-calendar', + '.tab-pane.active .user-calendar-activities', + data, + calendarActivitiesPath, + utcOffset, + 0, + monthsAgo, + ); } toggleLoading(status) { @@ -267,4 +256,11 @@ export default class UserTabs { getCurrentAction() { return this.$parentEl.find('.nav-links a.active').data('action'); } + + static getVisibleCalendarPeriod($calendarWrap) { + const width = $calendarWrap.width(); + return width < OVERVIEW_CALENDAR_BREAKPOINT + ? CALENDAR_PERIOD_6_MONTHS + : CALENDAR_PERIOD_12_MONTHS; + } } diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue index 6f2f0f98690..05f9f960934 100644 --- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue @@ -34,14 +34,7 @@ export default { fileSizeReadable() { return numberToHumanSize(this.fileSize); }, - dimensionStyles() { - if (!this.isLoaded) return {}; - return { - width: `${this.width}px`, - height: `${this.height}px`, - }; - }, hasFileSize() { return this.fileSize > 0; }, @@ -89,7 +82,6 @@ export default { <div> <div :class="innerCssClasses" - :style="dimensionStyles" class="position-relative" > <img diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue index c3cfe54eb4d..57f373fca21 100644 --- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue @@ -25,7 +25,7 @@ export default { swipeMaxWidth: undefined, swipeMaxHeight: undefined, swipeBarPos: 1, - swipeWrapWidth: undefined, + swipeWrapWidth: 0, }; }, computed: { @@ -63,7 +63,7 @@ export default { leftValue = clientWidth - spaceLeft; } - this.swipeWrapWidth = this.swipeMaxWidth - leftValue; + this.swipeWrapWidth = (leftValue / clientWidth) * 100; this.swipeBarPos = leftValue; }, startDrag() { @@ -81,7 +81,6 @@ export default { // Add 2 for border width this.swipeMaxWidth = Math.max(this.swipeOldImgInfo.renderedWidth, this.swipeNewImgInfo.renderedWidth) + 2; - this.swipeWrapWidth = this.swipeMaxWidth; this.swipeMaxHeight = Math.max(this.swipeOldImgInfo.renderedHeight, this.swipeNewImgInfo.renderedHeight) + 2; @@ -107,10 +106,6 @@ export default { <div class="swipe view"> <div ref="swipeFrame" - :style="{ - 'width': swipeMaxPixelWidth, - 'height': swipeMaxPixelHeight, - }" class="swipe-frame"> <image-viewer key="swipeOldImg" @@ -123,14 +118,17 @@ export default { <div ref="swipeWrap" :style="{ - 'width': swipeWrapPixelWidth, - 'height': swipeMaxPixelHeight, + width: `${swipeWrapWidth}%` }" - class="swipe-wrap"> + class="swipe-wrap" + > <image-viewer key="swipeNewImg" :render-info="false" :path="newPath" + :style="{ + width: swipeMaxPixelWidth + }" class="frame added" @imgLoaded="swipeNewImgLoaded" > diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/two_up_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/two_up_viewer.vue index 9806d65e940..aafa88f4ff1 100644 --- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/two_up_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/two_up_viewer.vue @@ -19,18 +19,18 @@ export default { </script> <template> - <div class="two-up view"> + <div class="two-up view d-flex"> <image-viewer :path="oldPath" :render-info="true" inner-css-classes="frame deleted" - class="wrap" + class="wrap w-50" /> <image-viewer :path="newPath" :render-info="true" :inner-css-classes="['frame', 'added']" - class="wrap" + class="wrap w-50" > <slot slot="image-overlay" diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 3c7bf0b0e46..0163c795074 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -253,19 +253,6 @@ right: 7px; } - .frame { - top: 0; - right: 0; - position: absolute; - - &.deleted { - margin: 0; - display: block; - top: 13px; - right: 7px; - } - } - .swipe-bar { display: block; height: 100%; @@ -435,7 +422,7 @@ .onion-skin.view { .swipe-wrap { top: 0; - right: 0; + left: 0; } .frame.deleted { diff --git a/app/finders/events_finder.rb b/app/finders/events_finder.rb index 2e82bda8730..8df01f1dad9 100644 --- a/app/finders/events_finder.rb +++ b/app/finders/events_finder.rb @@ -58,7 +58,7 @@ class EventsFinder def by_target_type(events) return events unless Event::TARGET_TYPES[params[:target_type]] - events.where(target_type: Event::TARGET_TYPES[params[:target_type]]) + events.where(target_type: Event::TARGET_TYPES[params[:target_type]].name) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/finders/group_descendants_finder.rb b/app/finders/group_descendants_finder.rb index c96979619fd..a9ce5be13f3 100644 --- a/app/finders/group_descendants_finder.rb +++ b/app/finders/group_descendants_finder.rb @@ -178,7 +178,7 @@ class GroupDescendantsFinder end def sort - params.fetch(:sort, 'id_asc') + params.fetch(:sort, 'created_desc') end # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 9a28e245ebd..d60861dc95f 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -98,7 +98,7 @@ module Ci scope :matches_tag_ids, -> (tag_ids) do matcher = ::ActsAsTaggableOn::Tagging - .where(taggable_type: CommitStatus) + .where(taggable_type: CommitStatus.name) .where(context: 'tags') .where('taggable_id = ci_builds.id') .where.not(tag_id: tag_ids).select('1') @@ -108,7 +108,7 @@ module Ci scope :with_any_tags, -> do matcher = ::ActsAsTaggableOn::Tagging - .where(taggable_type: CommitStatus) + .where(taggable_type: CommitStatus.name) .where(context: 'tags') .where('taggable_id = ci_builds.id').select('1') diff --git a/app/models/concerns/avatarable.rb b/app/models/concerns/avatarable.rb index 0d5311a9985..b42236c1fa2 100644 --- a/app/models/concerns/avatarable.rb +++ b/app/models/concerns/avatarable.rb @@ -86,7 +86,7 @@ module Avatarable params[:model].upload_paths(params[:identifier]) end - Upload.where(uploader: AvatarUploader, path: paths).find_each do |upload| + Upload.where(uploader: AvatarUploader.name, path: paths).find_each do |upload| model = model_class.instantiate('id' => upload.model_id) loader.call({ model: model, identifier: File.basename(upload.path) }, upload) diff --git a/app/models/repository.rb b/app/models/repository.rb index 6e179f61a7b..fff6d4be275 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1049,11 +1049,19 @@ class Repository end def cache - @cache ||= Gitlab::RepositoryCache.new(self) + @cache ||= if is_wiki + Gitlab::RepositoryCache.new(self, extra_namespace: 'wiki') + else + Gitlab::RepositoryCache.new(self) + end end def request_store_cache - @request_store_cache ||= Gitlab::RepositoryCache.new(self, backend: Gitlab::SafeRequestStore) + @request_store_cache ||= if is_wiki + Gitlab::RepositoryCache.new(self, extra_namespace: 'wiki', backend: Gitlab::SafeRequestStore) + else + Gitlab::RepositoryCache.new(self, backend: Gitlab::SafeRequestStore) + end end def tags_sorted_by_committed_date diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb index fba252b0bae..a1d0cc0e568 100644 --- a/app/services/issues/update_service.rb +++ b/app/services/issues/update_service.rb @@ -11,6 +11,12 @@ module Issues move_issue_to_new_project(issue) || update(issue) end + def update(issue) + create_merge_request_from_quick_action + + super + end + def before_update(issue) spam_check(issue, current_user) end @@ -93,6 +99,13 @@ module Issues private + def create_merge_request_from_quick_action + create_merge_request_params = params.delete(:create_merge_request) + return unless create_merge_request_params + + MergeRequests::CreateFromIssueService.new(project, current_user, create_merge_request_params).execute + end + def handle_milestone_change(issue) return if skip_milestone_email diff --git a/app/services/merge_requests/create_from_issue_service.rb b/app/services/merge_requests/create_from_issue_service.rb index 020af0bb950..e69791872cc 100644 --- a/app/services/merge_requests/create_from_issue_service.rb +++ b/app/services/merge_requests/create_from_issue_service.rb @@ -19,13 +19,15 @@ module MergeRequests result = CreateBranchService.new(project, current_user).execute(branch_name, ref) return result if result[:status] == :error - SystemNoteService.new_issue_branch(issue, project, current_user, branch_name) - new_merge_request = create(merge_request) if new_merge_request.valid? + SystemNoteService.new_merge_request(issue, project, current_user, new_merge_request) + success(new_merge_request) else + SystemNoteService.new_issue_branch(issue, project, current_user, branch_name) + error(new_merge_request.errors) end end diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb index 9c81de7e90e..d248b10f41e 100644 --- a/app/services/quick_actions/interpret_service.rb +++ b/app/services/quick_actions/interpret_service.rb @@ -635,6 +635,22 @@ module QuickActions @updates[:tag_message] = message end + desc 'Create a merge request.' + explanation do |branch_name = nil| + branch_text = branch_name ? "branch '#{branch_name}'" : 'a branch' + "Creates #{branch_text} and a merge request to resolve this issue" + end + params "<branch name>" + condition do + issuable.is_a?(Issue) && current_user.can?(:create_merge_request_in, project) && current_user.can?(:push_code, project) + end + command :create_merge_request do |branch_name = nil| + @updates[:create_merge_request] = { + branch_name: branch_name, + issue_iid: issuable.iid + } + end + # rubocop: disable CodeReuse/ActiveRecord def extract_users(params) return [] if params.nil? diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 729bc991294..ec6c306227b 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -407,11 +407,17 @@ module SystemNoteService def new_issue_branch(issue, project, author, branch) link = url_helpers.project_compare_url(project, from: project.default_branch, to: branch) - body = "created branch [`#{branch}`](#{link})" + body = "created branch [`#{branch}`](#{link}) to address this issue" create_note(NoteSummary.new(issue, project, author, body, action: 'branch')) end + def new_merge_request(issue, project, author, merge_request) + body = "created merge request #{merge_request.to_reference} to address this issue" + + create_note(NoteSummary.new(issue, project, author, body, action: 'merge')) + end + # Called when a Mentionable references a Noteable # # noteable - Noteable object being referenced diff --git a/app/services/todos/destroy/entity_leave_service.rb b/app/services/todos/destroy/entity_leave_service.rb index e8d1bcdd142..ebfb20132d0 100644 --- a/app/services/todos/destroy/entity_leave_service.rb +++ b/app/services/todos/destroy/entity_leave_service.rb @@ -45,7 +45,7 @@ module Todos # rubocop: disable CodeReuse/ActiveRecord def remove_confidential_issue_todos Todo.where( - target_id: confidential_issues.select(:id), target_type: Issue, user_id: user.id + target_id: confidential_issues.select(:id), target_type: Issue.name, user_id: user.id ).delete_all end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/services/todos/destroy/private_features_service.rb b/app/services/todos/destroy/private_features_service.rb index a8c3fe0ef5a..bd49519d694 100644 --- a/app/services/todos/destroy/private_features_service.rb +++ b/app/services/todos/destroy/private_features_service.rb @@ -14,9 +14,9 @@ module Todos def execute ProjectFeature.where(project_id: project_ids).each do |project_features| target_types = [] - target_types << Issue if private?(project_features.issues_access_level) - target_types << MergeRequest if private?(project_features.merge_requests_access_level) - target_types << Commit if private?(project_features.repository_access_level) + target_types << Issue.name if private?(project_features.issues_access_level) + target_types << MergeRequest.name if private?(project_features.merge_requests_access_level) + target_types << Commit.name if private?(project_features.repository_access_level) next if target_types.empty? diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 61ed951dea9..dcef4dd5b69 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -5,7 +5,7 @@ .project-header.d-flex.flex-row.flex-wrap.align-items-center.append-bottom-8 .project-title-row.d-flex.align-items-center .avatar-container.project-avatar.float-none - = project_icon(@project, alt: @project.name, class: 'avatar avatar-tile') + = project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s24', width: 24, height: 24) %h1.project-title.d-flex.align-items-baseline.qa-project-name = @project.name .project-metadata.d-flex.flex-row.flex-wrap.align-items-baseline diff --git a/app/views/projects/diffs/_collapsed.html.haml b/app/views/projects/diffs/_collapsed.html.haml index 9bd1255fe00..94dcda38bd6 100644 --- a/app/views/projects/diffs/_collapsed.html.haml +++ b/app/views/projects/diffs/_collapsed.html.haml @@ -1,5 +1,5 @@ - diff_file = viewer.diff_file - url = url_for(safe_params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path, file_identifier: diff_file.file_identifier)) .nothing-here-block.diff-collapsed{ data: { diff_for_path: url } } - This diff is collapsed. - %button.click-to-expand.btn.btn-link Click to expand it. + = _("This diff is collapsed.") + %button.click-to-expand.btn.btn-link= _("Click to expand it.") diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index 077c6c68f7e..9de3c2db6e7 100644 --- a/app/views/projects/diffs/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -8,7 +8,7 @@ .files-changed-inner .inline-parallel-buttons.d-none.d-sm-none.d-md-block - if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? } - = link_to 'Expand all', url_for(safe_params.merge(expanded: 1, format: nil)), class: 'btn btn-default' + = link_to _('Expand all'), url_for(safe_params.merge(expanded: 1, format: nil)), class: 'btn btn-default' - if show_whitespace_toggle - if current_controller?(:commit) = commit_diff_whitespace_link(diffs.project, @commit, class: 'd-none d-sm-inline-block') diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml index b4df654c839..1f90acaabcc 100644 --- a/app/views/projects/diffs/_file.html.haml +++ b/app/views/projects/diffs/_file.html.haml @@ -12,7 +12,7 @@ - blob = diff_file.blob .file-actions.d-none.d-sm-block - if blob&.readable_text? - = link_to '#', class: 'js-toggle-diff-comments btn active has-tooltip', title: "Toggle comments for this file", disabled: @diff_notes_disabled do + = link_to '#', class: 'js-toggle-diff-comments btn active has-tooltip', title: _("Toggle comments for this file"), disabled: @diff_notes_disabled do = icon('comment') \ - if editable_diff?(diff_file) diff --git a/app/views/projects/diffs/_file_header.html.haml b/app/views/projects/diffs/_file_header.html.haml index 4cb04d744dc..6a1bff8640c 100644 --- a/app/views/projects/diffs/_file_header.html.haml +++ b/app/views/projects/diffs/_file_header.html.haml @@ -28,7 +28,7 @@ = diff_file.file_path - if diff_file.deleted_file? - deleted + = _("deleted") = copy_file_path_button(diff_file.file_path) diff --git a/app/views/projects/diffs/_render_error.html.haml b/app/views/projects/diffs/_render_error.html.haml index 47a9ac3ee6b..c3dc47a56a7 100644 --- a/app/views/projects/diffs/_render_error.html.haml +++ b/app/views/projects/diffs/_render_error.html.haml @@ -1,5 +1,5 @@ .nothing-here-block - This #{viewer.switcher_title} could not be displayed because #{diff_render_error_reason(viewer)}. + = _("This %{viewer} could not be displayed because %{reason}.") % { viewer: viewer.switcher_title, reason: diff_render_error_reason(viewer) } You can = diff_render_error_options(viewer).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ').html_safe diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml index 229a4574eeb..c9057f385da 100644 --- a/app/views/projects/diffs/_stats.html.haml +++ b/app/views/projects/diffs/_stats.html.haml @@ -38,4 +38,4 @@ \-#{diff_file.removed_lines} %li.dropdown-menu-empty-item.hidden %a - No files found. + = _("No files found.") diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index bc9f6c71fa8..56427a74d56 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -1,7 +1,7 @@ - too_big = diff_file.diff_lines.count > Commit::DIFF_SAFE_LINES - if too_big .suppressed-container - %a.show-suppressed-diff.js-show-suppressed-diff Changes suppressed. Click to show. + %a.show-suppressed-diff.js-show-suppressed-diff= _("Changes suppressed. Click to show.") %table.text-file.diff-wrap-lines.code.js-syntax-highlight.commit-diff{ data: diff_view_data, class: too_big ? 'hide' : '' } = render partial: "projects/diffs/line", diff --git a/app/views/projects/diffs/_warning.html.haml b/app/views/projects/diffs/_warning.html.haml index abe494f2974..2eef599cf84 100644 --- a/app/views/projects/diffs/_warning.html.haml +++ b/app/views/projects/diffs/_warning.html.haml @@ -1,14 +1,12 @@ .alert.alert-warning %h4 - Too many changes to show. + = _("Too many changes to show.") .float-right - if current_controller?(:commit) - = link_to "Plain diff", project_commit_path(@project, @commit, format: :diff), class: "btn btn-sm" - = link_to "Email patch", project_commit_path(@project, @commit, format: :patch), class: "btn btn-sm" + = link_to _("Plain diff"), project_commit_path(@project, @commit, format: :diff), class: "btn btn-sm" + = link_to _("Email patch"), project_commit_path(@project, @commit, format: :patch), class: "btn btn-sm" - elsif current_controller?('projects/merge_requests/diffs') && @merge_request&.persisted? - = link_to "Plain diff", merge_request_path(@merge_request, format: :diff), class: "btn btn-sm" - = link_to "Email patch", merge_request_path(@merge_request, format: :patch), class: "btn btn-sm" + = link_to _("Plain diff"), merge_request_path(@merge_request, format: :diff), class: "btn btn-sm" + = link_to _("Email patch"), merge_request_path(@merge_request, format: :patch), class: "btn btn-sm" %p - To preserve performance only - %strong #{diff_files.size} of #{diff_files.real_size} - files are displayed. + = _("To preserve performance only <strong>%{display_size} of ${real_size}</strong> files are displayed.").html_safe % { display_size: diff_files.size, real_size: diff_files.real_size } diff --git a/app/views/projects/diffs/viewers/_added.html.haml b/app/views/projects/diffs/viewers/_added.html.haml index 8004fe16688..f4c574a018f 100644 --- a/app/views/projects/diffs/viewers/_added.html.haml +++ b/app/views/projects/diffs/viewers/_added.html.haml @@ -1,2 +1,2 @@ .nothing-here-block - File added + = _("File added") diff --git a/app/views/projects/diffs/viewers/_deleted.html.haml b/app/views/projects/diffs/viewers/_deleted.html.haml index 0ac7b4ca8f6..b82ca4d0787 100644 --- a/app/views/projects/diffs/viewers/_deleted.html.haml +++ b/app/views/projects/diffs/viewers/_deleted.html.haml @@ -1,2 +1,2 @@ .nothing-here-block - File deleted + = _("File deleted") diff --git a/app/views/projects/diffs/viewers/_mode_changed.html.haml b/app/views/projects/diffs/viewers/_mode_changed.html.haml index 69bc96bbdad..a8d6f5fe400 100644 --- a/app/views/projects/diffs/viewers/_mode_changed.html.haml +++ b/app/views/projects/diffs/viewers/_mode_changed.html.haml @@ -1,3 +1,3 @@ - diff_file = viewer.diff_file .nothing-here-block - File mode changed from #{diff_file.a_mode} to #{diff_file.b_mode} + = _("File mode changed from %{a_mode} to %{b_mode}") % { a_mode: diff_file.a_mode, b_mode: diff_file.b_mode } diff --git a/app/views/projects/diffs/viewers/_no_preview.html.haml b/app/views/projects/diffs/viewers/_no_preview.html.haml index befe070af2b..b763ac34bf8 100644 --- a/app/views/projects/diffs/viewers/_no_preview.html.haml +++ b/app/views/projects/diffs/viewers/_no_preview.html.haml @@ -1,2 +1,2 @@ .nothing-here-block - No preview for this file type + = _("No preview for this file type") diff --git a/app/views/projects/diffs/viewers/_not_diffable.html.haml b/app/views/projects/diffs/viewers/_not_diffable.html.haml index b2c677ec59c..7c55e272f56 100644 --- a/app/views/projects/diffs/viewers/_not_diffable.html.haml +++ b/app/views/projects/diffs/viewers/_not_diffable.html.haml @@ -1,2 +1,2 @@ .nothing-here-block - This diff was suppressed by a .gitattributes entry. + = _("This diff was suppressed by a .gitattributes entry.") diff --git a/app/views/projects/diffs/viewers/_renamed.html.haml b/app/views/projects/diffs/viewers/_renamed.html.haml index ef05ee38d8d..b7336c356fe 100644 --- a/app/views/projects/diffs/viewers/_renamed.html.haml +++ b/app/views/projects/diffs/viewers/_renamed.html.haml @@ -1,2 +1,2 @@ .nothing-here-block - File moved + = _("File moved") diff --git a/app/views/projects/environments/_external_url.html.haml b/app/views/projects/environments/_external_url.html.haml index b3a82d1ef41..82567f88ccc 100644 --- a/app/views/projects/environments/_external_url.html.haml +++ b/app/views/projects/environments/_external_url.html.haml @@ -1,4 +1,4 @@ - if environment.external_url && can?(current_user, :read_environment, environment) = link_to environment.external_url, target: '_blank', rel: 'noopener noreferrer', class: 'btn external-url has-tooltip qa-view-deployment', title: s_('Environments|Open live environment') do = sprite_icon('external-link') - View deployment + = _("View deployment") diff --git a/app/views/projects/environments/_form.html.haml b/app/views/projects/environments/_form.html.haml index f942b936037..cbd5c54cecc 100644 --- a/app/views/projects/environments/_form.html.haml +++ b/app/views/projects/environments/_form.html.haml @@ -1,22 +1,21 @@ .row.prepend-top-default.append-bottom-default .col-lg-3 %h4.prepend-top-0 - Environments + = _("Environments") %p - Environments allow you to track deployments of your application - = succeed "." do - = link_to "Read more about environments", help_page_path("ci/environments") + - link_to_read_more = link_to(_("Read more about environments"), help_page_path("ci/environments")) + = _("Environments allow you to track deployments of your application %{link_to_read_more}.").html_safe % { link_to_read_more: link_to_read_more } = form_for [@project.namespace.becomes(Namespace), @project, @environment], html: { class: 'col-lg-9' } do |f| = form_errors(@environment) .form-group - = f.label :name, 'Name', class: 'label-bold' + = f.label :name, _('Name'), class: 'label-bold' = f.text_field :name, required: true, class: 'form-control' .form-group - = f.label :external_url, 'External URL', class: 'label-bold' + = f.label :external_url, _('External URL'), class: 'label-bold' = f.url_field :external_url, class: 'form-control' .form-actions - = f.submit 'Save', class: 'btn btn-success' - = link_to 'Cancel', project_environments_path(@project), class: 'btn btn-cancel' + = f.submit _('Save'), class: 'btn btn-save' + = link_to _('Cancel'), project_environments_path(@project), class: 'btn btn-cancel' diff --git a/app/views/projects/environments/_metrics_button.html.haml b/app/views/projects/environments/_metrics_button.html.haml index a4b27575095..c4f19ea79e7 100644 --- a/app/views/projects/environments/_metrics_button.html.haml +++ b/app/views/projects/environments/_metrics_button.html.haml @@ -2,6 +2,6 @@ - return unless can?(current_user, :read_environment, environment) -= link_to environment_metrics_path(environment), title: 'See metrics', class: 'btn metrics-button' do += link_to environment_metrics_path(environment), title: _('See metrics'), class: 'btn metrics-button' do = sprite_icon('chart') - Monitoring + = _("Monitoring") diff --git a/app/views/projects/environments/edit.html.haml b/app/views/projects/environments/edit.html.haml index d6ff3f729b4..d581bd3aeab 100644 --- a/app/views/projects/environments/edit.html.haml +++ b/app/views/projects/environments/edit.html.haml @@ -1,8 +1,8 @@ - @no_container = true -- page_title "Edit", @environment.name, "Environments" +- page_title _("Edit"), @environment.name, _("Environments") %div{ class: container_class } %h3.page-title - Edit environment + = _('Edit environment') %hr = render 'form' diff --git a/app/views/projects/environments/folder.html.haml b/app/views/projects/environments/folder.html.haml index 1ac7dab6775..b7e1cf85cb7 100644 --- a/app/views/projects/environments/folder.html.haml +++ b/app/views/projects/environments/folder.html.haml @@ -1,5 +1,5 @@ - @no_container = true -- page_title "Environments" +- page_title _("Environments") #environments-folder-list-view{ data: { endpoint: folder_project_environments_path(@project, @folder, format: :json), "folder-name" => @folder, diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml index 7ebe617766f..6c0ad34c486 100644 --- a/app/views/projects/environments/index.html.haml +++ b/app/views/projects/environments/index.html.haml @@ -1,6 +1,6 @@ - @no_container = true -- page_title "Environments" -- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project)) +- page_title _("Environments") +- add_to_breadcrumbs(_("Pipelines"), project_pipelines_path(@project)) #environments-list-view{ data: { environments_data: environments_list_data, "can-create-deployment" => can?(current_user, :create_deployment, @project).to_s, diff --git a/app/views/projects/environments/metrics.html.haml b/app/views/projects/environments/metrics.html.haml index 4222963a754..7b847a85686 100644 --- a/app/views/projects/environments/metrics.html.haml +++ b/app/views/projects/environments/metrics.html.haml @@ -1,5 +1,5 @@ - @no_container = true -- page_title "Metrics for environment", @environment.name +- page_title _("Metrics for environment"), @environment.name .prometheus-container{ class: container_class } #prometheus-graphs{ data: metrics_data(@project, @environment) } diff --git a/app/views/projects/environments/new.html.haml b/app/views/projects/environments/new.html.haml index 62b08e85e22..c1067fdff78 100644 --- a/app/views/projects/environments/new.html.haml +++ b/app/views/projects/environments/new.html.haml @@ -1,9 +1,9 @@ - @no_container = true -- breadcrumb_title "Environments" -- page_title 'New Environment' +- breadcrumb_title _("Environments") +- page_title _("New Environment") %div{ class: container_class } %h3.page-title - New environment + = _("New environment") %hr = render 'form' diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml index 8c5b6e089ea..d59b2d4fb01 100644 --- a/app/views/projects/environments/show.html.haml +++ b/app/views/projects/environments/show.html.haml @@ -1,7 +1,7 @@ - @no_container = true -- add_to_breadcrumbs "Environments", project_environments_path(@project) +- add_to_breadcrumbs _("Environments"), project_environments_path(@project) - breadcrumb_title @environment.name -- page_title "Environments" +- page_title _("Environments") %div{ class: container_class } - if can?(current_user, :stop_environment, @environment) @@ -10,7 +10,7 @@ .modal-content .modal-header %h4.modal-title.d-flex.mw-100 - Stopping + = s_("Environments|Stopping") %span.has-tooltip.text-truncate.ml-1.mr-1.flex-fill{ title: @environment.name, data: { container: '#stop-environment-modal' } } = @environment.name ? @@ -40,7 +40,7 @@ = render 'projects/environments/external_url', environment: @environment = render 'projects/environments/metrics_button', environment: @environment - if can?(current_user, :update_environment, @environment) - = link_to 'Edit', edit_project_environment_path(@project, @environment), class: 'btn' + = link_to _('Edit'), edit_project_environment_path(@project, @environment), class: 'btn' - if can?(current_user, :stop_environment, @environment) = button_tag class: 'btn btn-danger', type: 'button', data: { toggle: 'modal', target: '#stop-environment-modal' } do @@ -52,21 +52,19 @@ .empty-state .text-content %h4.state-title - You don't have any deployments right now. + = _("You don't have any deployments right now.") %p.blank-state-text - Define environments in the deploy stage(s) in - %code .gitlab-ci.yml - to track deployments here. + = _("Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here.").html_safe .text-center = link_to _("Read more"), help_page_path("ci/environments"), class: "btn btn-success" - else .table-holder .ci-table.environments{ role: 'grid' } .gl-responsive-table-row.table-row-header{ role: 'row' } - .table-section.section-10{ role: 'columnheader' } ID - .table-section.section-30{ role: 'columnheader' } Commit - .table-section.section-25{ role: 'columnheader' } Job - .table-section.section-15{ role: 'columnheader' } Created + .table-section.section-10{ role: 'columnheader' }= _('ID') + .table-section.section-30{ role: 'columnheader' }= _('Commit') + .table-section.section-25{ role: 'columnheader' }= _('Job') + .table-section.section-15{ role: 'columnheader' }= _('Created') = render @deployments diff --git a/app/views/projects/environments/terminal.html.haml b/app/views/projects/environments/terminal.html.haml index e40d631a1a1..e837d3d56ac 100644 --- a/app/views/projects/environments/terminal.html.haml +++ b/app/views/projects/environments/terminal.html.haml @@ -1,5 +1,5 @@ - @no_container = true -- page_title "Terminal for environment", @environment.name +- page_title _("Terminal for environment"), @environment.name - content_for :page_specific_javascripts do = stylesheet_link_tag "xterm.css" @@ -9,7 +9,7 @@ .row .col-sm-6 %h3.page-title - Terminal for environment + = _("Terminal for environment") = @environment.name .col-sm-6 diff --git a/app/views/projects/graphs/charts.html.haml b/app/views/projects/graphs/charts.html.haml index 3f1974d05f4..b0e22a35fe1 100644 --- a/app/views/projects/graphs/charts.html.haml +++ b/app/views/projects/graphs/charts.html.haml @@ -1,5 +1,5 @@ - @no_container = true -- page_title "Charts" +- page_title _("Contribution Charts") .repo-charts{ class: container_class } %h4.sub-header diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml index a86cb14960a..ec17eddba79 100644 --- a/app/views/projects/pipelines/charts.html.haml +++ b/app/views/projects/pipelines/charts.html.haml @@ -1,6 +1,5 @@ - @no_container = true -- breadcrumb_title "CI / CD Charts" -- page_title _("Charts"), _("Pipelines") +- page_title _("CI / CD Charts") %div{ class: container_class } .sub-header-block diff --git a/app/views/shared/_labels_row.html.haml b/app/views/shared/_labels_row.html.haml deleted file mode 100644 index 21b37a7c9ae..00000000000 --- a/app/views/shared/_labels_row.html.haml +++ /dev/null @@ -1,5 +0,0 @@ -- labels.each do |label| - %span.label-row.btn-group{ role: "group", aria: { label: label.name }, style: "color: #{text_color_for_bg(label.color)}" } - = link_to_label(label, subject: @project, css_class: 'btn btn-transparent') - %button.btn.btn-transparent.label-remove.js-label-filter-remove{ type: "button", style: "background-color: #{label.color};", data: { label: label.title } } - = icon("times") diff --git a/app/views/u2f/_authenticate.html.haml b/app/views/u2f/_authenticate.html.haml index 1c788b9a737..979f6862de3 100644 --- a/app/views/u2f/_authenticate.html.haml +++ b/app/views/u2f/_authenticate.html.haml @@ -1,18 +1,18 @@ #js-authenticate-u2f -%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' } Sign in via 2FA code +%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' }= _("Sign in via 2FA code") -# haml-lint:disable InlineJavaScript %script#js-authenticate-u2f-in-progress{ type: "text/template" } - %p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now. + %p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.") %script#js-authenticate-u2f-error{ type: "text/template" } %div - %p <%= error_message %> (error code: <%= error_code %>) - %a.btn.btn-block.btn-warning#js-u2f-try-again Try again? + %p <%= error_message %> (#{_("error code:")} <%= error_code %>) + %a.btn.btn-block.btn-warning#js-u2f-try-again= _("Try again?") %script#js-authenticate-u2f-authenticated{ type: "text/template" } %div - %p We heard back from your U2F device. You have been authenticated. + %p= _("We heard back from your U2F device. You have been authenticated.") = form_tag(new_user_session_path, method: :post, id: 'js-login-u2f-form') do |f| - resource_params = params[resource_name].presence || params = hidden_field_tag 'user[remember_me]', resource_params.fetch(:remember_me, 0) diff --git a/app/views/u2f/_register.html.haml b/app/views/u2f/_register.html.haml index 39d4d82a77d..f6724f72307 100644 --- a/app/views/u2f/_register.html.haml +++ b/app/views/u2f/_register.html.haml @@ -2,39 +2,39 @@ -# haml-lint:disable InlineJavaScript %script#js-register-u2f-not-supported{ type: "text/template" } - %p Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer). + %p= _("Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer).") %script#js-register-u2f-setup{ type: "text/template" } - if current_user.two_factor_otp_enabled? .row.append-bottom-10 .col-md-4 - %button#js-setup-u2f-device.btn.btn-info.btn-block Set up new U2F device + %button#js-setup-u2f-device.btn.btn-info.btn-block= _("Set up new U2F device") .col-md-8 - %p Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left. + %p= _("Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left.") - else .row.append-bottom-10 .col-md-4 - %button#js-setup-u2f-device.btn.btn-info.btn-block{ disabled: true } Set up new U2F device + %button#js-setup-u2f-device.btn.btn-info.btn-block{ disabled: true }= _("Set up new U2F device") .col-md-8 - %p.text-warning You need to register a two-factor authentication app before you can set up a U2F device. + %p.text-warning= _("You need to register a two-factor authentication app before you can set up a U2F device.") %script#js-register-u2f-in-progress{ type: "text/template" } - %p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now. + %p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.") %script#js-register-u2f-error{ type: "text/template" } %div %p - %span <%= error_message %> (error code: <%= error_code %>) - %a.btn.btn-warning#js-u2f-try-again Try again? + %span <%= error_message %> (#{_("error code:")} <%= error_code %>) + %a.btn.btn-warning#js-u2f-try-again= _("Try again?") %script#js-register-u2f-registered{ type: "text/template" } .row.append-bottom-10 .col-md-12 - %p Your device was successfully set up! Give it a name and register it with the GitLab server. + %p= _("Your device was successfully set up! Give it a name and register it with the GitLab server.") = form_tag(create_u2f_profile_two_factor_auth_path, method: :post) do .row.append-bottom-10 .col-md-3 - = text_field_tag 'u2f_registration[name]', nil, class: 'form-control', placeholder: "Pick a name" + = text_field_tag 'u2f_registration[name]', nil, class: 'form-control', placeholder: _("Pick a name") .col-md-3 = hidden_field_tag 'u2f_registration[device_response]', nil, class: 'form-control', required: true, id: "js-device-response" - = submit_tag "Register U2F device", class: "btn btn-success" + = submit_tag _("Register U2F device"), class: "btn btn-success" diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml index cf525f2bb2d..b5bc1180290 100644 --- a/app/views/users/_overview.html.haml +++ b/app/views/users/_overview.html.haml @@ -1,32 +1,30 @@ .row + .col-12 + .calendar-block.prepend-top-default.append-bottom-default + .user-calendar.d-none.d-sm-block{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } } + %h4.center.light + = spinner nil, true + .user-calendar-activities.d-none.d-sm-block +.row .col-md-12.col-lg-6 - .calendar-block - .content-block.hide-bottom-border - %h4 - = s_('UserProfile|Activity') - .user-calendar.d-none.d-sm-block.text-left{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } } - %h4.center.light - %i.fa.fa-spinner.fa-spin - .user-calendar-activities.d-none.d-sm-block - - if can?(current_user, :read_cross_project) .activities-block - .border-bottom.prepend-top-16 - %h5 - = s_('UserProfile|Recent contributions') + .prepend-top-16 + .d-flex.align-items-center.border-bottom + %h4.flex-grow + = s_('UserProfile|Activity') + = link_to s_('UserProfile|View all'), user_activity_path, class: "hide js-view-all" .overview-content-list{ data: { href: user_path } } .center.light.loading - %i.fa.fa-spinner.fa-spin - .prepend-top-10 - = link_to s_('UserProfile|View all'), user_activity_path, class: "hide js-view-all" + = spinner nil, true .col-md-12.col-lg-6 .projects-block - .border-bottom.prepend-top-16 - %h4 - = s_('UserProfile|Personal projects') + .prepend-top-16 + .d-flex.align-items-center.border-bottom + %h4.flex-grow + = s_('UserProfile|Personal projects') + = link_to s_('UserProfile|View all'), user_projects_path, class: "hide js-view-all" .overview-content-list{ data: { href: user_projects_path } } .center.light.loading - %i.fa.fa-spinner.fa-spin - .prepend-top-10 - = link_to s_('UserProfile|View all'), user_projects_path, class: "hide js-view-all" + = spinner nil, true diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index d6c8420b744..d11476738e4 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -124,12 +124,6 @@ - if profile_tab?(:activity) #activity.tab-pane - .row-content-block.calendar-block.white.second-block.d-none.d-sm-block - .user-calendar{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } } - %h4.center.light - %i.fa.fa-spinner.fa-spin - .user-calendar-activities - - if can?(current_user, :read_cross_project) %h4.prepend-top-20 = s_('UserProfile|Most Recent Activity') diff --git a/changelogs/unreleased/40085-add-a-create_merge_request-quick-action.yml b/changelogs/unreleased/40085-add-a-create_merge_request-quick-action.yml new file mode 100644 index 00000000000..e1614ac7669 --- /dev/null +++ b/changelogs/unreleased/40085-add-a-create_merge_request-quick-action.yml @@ -0,0 +1,5 @@ +--- +title: Creates /create_merge_request quickaction +merge_request: 22485 +author: Jacopo Beschi @jacopo-beschi +type: added diff --git a/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml b/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml new file mode 100644 index 00000000000..65aa9323d2e --- /dev/null +++ b/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml @@ -0,0 +1,5 @@ +--- +title: UI improvements to user's profile +merge_request: 22977 +author: +type: other diff --git a/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml b/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml new file mode 100644 index 00000000000..d076352a27b --- /dev/null +++ b/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml @@ -0,0 +1,5 @@ +--- +title: Fix default sorting for subgroups and projects list +merge_request: 23058 +author: Jacopo Beschi @jacopo-beschi +type: fixed diff --git a/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml b/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml new file mode 100644 index 00000000000..28e3fae01a9 --- /dev/null +++ b/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml @@ -0,0 +1,5 @@ +--- +title: Refine cursor positioning in Markdown Editor for wrap tags +merge_request: 23085 +author: Johann Hubert Sonntagbauer +type: changed diff --git a/changelogs/unreleased/docs-minor-aws-fixes.yml b/changelogs/unreleased/docs-minor-aws-fixes.yml new file mode 100644 index 00000000000..64fa6b12afe --- /dev/null +++ b/changelogs/unreleased/docs-minor-aws-fixes.yml @@ -0,0 +1,5 @@ +--- +title: Fixes to AWS documentation spelling and grammar +merge_request: 23198 +author: Brendan O'Leary +type: other diff --git a/changelogs/unreleased/drop-default-value-status-deployments.yml b/changelogs/unreleased/drop-default-value-status-deployments.yml new file mode 100644 index 00000000000..fdb826a0507 --- /dev/null +++ b/changelogs/unreleased/drop-default-value-status-deployments.yml @@ -0,0 +1,5 @@ +--- +title: Drop default value on status column in deployments table +merge_request: 22971 +author: +type: other diff --git a/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml b/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml new file mode 100644 index 00000000000..e718d716647 --- /dev/null +++ b/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml @@ -0,0 +1,5 @@ +--- +title: Enable even more frozen string for lib/gitlab +merge_request: +author: gfyoung +type: performance diff --git a/changelogs/unreleased/gt-change-breadcrumb-title-for-contribution-charts.yml b/changelogs/unreleased/gt-change-breadcrumb-title-for-contribution-charts.yml new file mode 100644 index 00000000000..233cc43117d --- /dev/null +++ b/changelogs/unreleased/gt-change-breadcrumb-title-for-contribution-charts.yml @@ -0,0 +1,5 @@ +--- +title: Change breadcrumb title for contribution charts +merge_request: 23071 +author: George Tsiolis +type: changed diff --git a/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml b/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml new file mode 100644 index 00000000000..60603905a2d --- /dev/null +++ b/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml @@ -0,0 +1,5 @@ +--- +title: Fix typo in notebook props +merge_request: 23103 +author: George Tsiolis +type: other diff --git a/changelogs/unreleased/project_identicon_fix.yml b/changelogs/unreleased/project_identicon_fix.yml new file mode 100644 index 00000000000..de4876fc4a5 --- /dev/null +++ b/changelogs/unreleased/project_identicon_fix.yml @@ -0,0 +1,5 @@ +--- +title: Fix project identicon aligning Harry Kiselev +merge_request: 23166 +author: Harry Kiselev +type: other diff --git a/changelogs/unreleased/rails5-active-record-class-value.yml b/changelogs/unreleased/rails5-active-record-class-value.yml new file mode 100644 index 00000000000..9f9fdf10cd1 --- /dev/null +++ b/changelogs/unreleased/rails5-active-record-class-value.yml @@ -0,0 +1,5 @@ +--- +title: 'Rails5: Passing a class as a value in an Active Record query is deprecated' +merge_request: 23164 +author: Jasper Maes +type: other diff --git a/changelogs/unreleased/security-2717-xss-username-autocomplete.yml b/changelogs/unreleased/security-2717-xss-username-autocomplete.yml new file mode 100644 index 00000000000..d9b1015eeb4 --- /dev/null +++ b/changelogs/unreleased/security-2717-xss-username-autocomplete.yml @@ -0,0 +1,5 @@ +--- +title: Escape user fullname while rendering autocomplete template to prevent XSS +merge_request: +author: +type: security diff --git a/changelogs/unreleased/sh-bump-gems-security.yml b/changelogs/unreleased/sh-bump-gems-security.yml new file mode 100644 index 00000000000..06489f6f979 --- /dev/null +++ b/changelogs/unreleased/sh-bump-gems-security.yml @@ -0,0 +1,5 @@ +--- +title: Bump nokogiri, loofah, and rack gems for security updates +merge_request: 23204 +author: +type: security diff --git a/changelogs/unreleased/sh-fix-issue-54189.yml b/changelogs/unreleased/sh-fix-issue-54189.yml new file mode 100644 index 00000000000..eee743aa5d9 --- /dev/null +++ b/changelogs/unreleased/sh-fix-issue-54189.yml @@ -0,0 +1,5 @@ +--- +title: Prevent templated services from being imported +merge_request: +author: +type: security diff --git a/danger/documentation/Dangerfile b/danger/documentation/Dangerfile index 1ee025f0972..87c61d6e90d 100644 --- a/danger/documentation/Dangerfile +++ b/danger/documentation/Dangerfile @@ -15,10 +15,10 @@ docs_paths_to_review = docs_paths_requiring_review(helper.all_changed_files) unless docs_paths_to_review.empty? message 'This merge request adds or changes files that require a ' \ - 'review from the docs team.' + 'review from the Docs team.' markdown(<<~MARKDOWN) -## Docs Review +## Docs review The following files require a review from the Documentation team: @@ -32,24 +32,15 @@ the documentation. GitLabbers are also welcome to use the [#docs](https://gitlab Who to ping [based on DevOps stages](https://about.gitlab.com/handbook/product/categories/#devops-stages): -| Stage | Tech writer | -| ------------- | ----------- | -| ~Create | `@marcia` | -| ~Configure | `@eread` | -| ~Distribution | `@axil` | -| ~Geo | `@eread` | -| ~Gitaly | `@axil` | -| ~Gitter | `@axil` | -| ~Manage | `@eread` | -| ~Monitoring | `@axil` | -| ~Packaging | `@axil` | -| ~Plan | `@mikelewis`| -| ~Release | `marcia` | -| ~Secure | `@axil` | -| ~Verify | `@eread` | +| Tech writer | Stage(s) | +| ------------ | ------------------------------------------------------------ | +| `@marcia` | ~Create ~Release | +| `@axil` | ~Distribution ~Gitaly ~Gitter ~Monitoring ~Packaging ~Secure | +| `@eread` | ~Manage ~Configure ~Geo ~Verify | +| `@mikelewis` | ~Plan | If you are not sure which category the change falls within, or the change is not -part of one of these categories, you can mention the whole team with `@gl-docsteam`. +part of one of these categories, you can mention one of the usernames above. MARKDOWN unless gitlab.mr_labels.include?('Documentation') diff --git a/db/migrate/20181112103239_drop_default_value_on_status_deployments.rb b/db/migrate/20181112103239_drop_default_value_on_status_deployments.rb new file mode 100644 index 00000000000..a480c15e66b --- /dev/null +++ b/db/migrate/20181112103239_drop_default_value_on_status_deployments.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class DropDefaultValueOnStatusDeployments < ActiveRecord::Migration + DOWNTIME = false + DEPLOYMENT_STATUS_SUCCESS = 2 # Equivalent to Deployment.state_machine.states['success'].value + + def up + change_column_default :deployments, :status, nil + end + + def down + change_column_default :deployments, :status, DEPLOYMENT_STATUS_SUCCESS + end +end diff --git a/db/schema.rb b/db/schema.rb index 276580e79d8..6b1ab367287 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20181107054254) do +ActiveRecord::Schema.define(version: 20181112103239) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -818,7 +818,7 @@ ActiveRecord::Schema.define(version: 20181107054254) do t.datetime "created_at" t.datetime "updated_at" t.string "on_stop" - t.integer "status", limit: 2, default: 2, null: false + t.integer "status", limit: 2, null: false t.datetime_with_timezone "finished_at" t.index ["created_at"], name: "index_deployments_on_created_at", using: :btree t.index ["deployable_type", "deployable_id"], name: "index_deployments_on_deployable_type_and_deployable_id", using: :btree diff --git a/doc/ci/environments.md b/doc/ci/environments.md index 4d740c32fd6..6874583256a 100644 --- a/doc/ci/environments.md +++ b/doc/ci/environments.md @@ -416,19 +416,18 @@ and/or `production`) you can see this information in the merge request itself. ### Go directly from source files to public pages on the environment -> Introduced in GitLab 8.17. +> Introduced in GitLab 8.17. In GitLab 11.5 the file links +are surfaced to the merge request widget. -To go one step further, we can specify a Route Map to get GitLab to show us "View on [environment URL]" buttons to go directly from a file to that file's representation on the deployed website. It will be exposed in a few places: - -| In the diff for a merge request, comparison or commit | In the file view | -| ------ | ------ | -| !["View on env" button in merge request diff](img/view_on_env_mr.png) | !["View on env" button in file view](img/view_on_env_blob.png) | +You can specify a Route Map to get GitLab to show "View on <environment URL>" +buttons to go directly from a file to that file's representation on the +[deployed website via Review Apps](review_apps/index.md). To get this to work, you need to tell GitLab how the paths of files in your repository map to paths of pages on your website, using a Route Map. A Route Map is a file inside the repository at `.gitlab/route-map.yml`, which contains a YAML array that maps `source` paths (in the repository) to `public` paths (on the website). - -This is an example of a route map for [Middleman](https://middlemanapp.com) static websites like [http://about.gitlab.com](https://gitlab.com/gitlab-com/www-gitlab-com): +Below is an example of a route map for [Middleman](https://middlemanapp.com) static websites +like <https://gitlab.com/gitlab-com/www-gitlab-com>: ```yaml # Team data @@ -467,6 +466,25 @@ In the example above, the fact that mappings are evaluated in order of their def --- +Once you have the route mapping set up, it will be exposed in a few places: + +- In the merge request widget. The **View app** button will take you to the + environment URL you have set up in `.gitlab-ci.yml`. The dropdown will render + the first 5 matched items from the route map, but you can filter them if more + than 5 are available. + + ![View app file list in merge request widget](img/view_on_mr_widget.png) + +- In the diff for a merge request, comparison, or commit. + + !["View on env" button in merge request diff](img/view_on_env_mr.png) + +- In the blob file view. + + !["View on env" button in file view](img/view_on_env_blob.png) | + +--- + We now have a full development cycle, where our app is tested, built, deployed as a Review app, deployed to a staging server once the merge request is merged, and finally manually deployed to the production server. What we just described diff --git a/doc/ci/img/view_on_env_blob.png b/doc/ci/img/view_on_env_blob.png Binary files differindex dd9ca40280a..acc457fbb38 100644 --- a/doc/ci/img/view_on_env_blob.png +++ b/doc/ci/img/view_on_env_blob.png diff --git a/doc/ci/img/view_on_mr_widget.png b/doc/ci/img/view_on_mr_widget.png Binary files differnew file mode 100644 index 00000000000..04f4b58df62 --- /dev/null +++ b/doc/ci/img/view_on_mr_widget.png diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index ec709280085..44eec43ef54 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -1682,6 +1682,11 @@ include: NOTE: **Note:** The remote file must be publicly accessible through a simple GET request, as we don't support authentication schemas in the remote URL. + NOTE: **Note:** + In order to include files from another repository inside your local network, + you may need to enable the **Allow requests to the local network from hooks and services** checkbox + located in the **Settings > Network > Outbound requests** section within the **Admin area**. + --- diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index e4e532bb4ed..a99267bfbba 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -134,9 +134,9 @@ should be more than enough. When removing an index make sure to use the method `remove_concurrent_index` instead of the regular `remove_index` method. The `remove_concurrent_index` method automatically drops concurrent indexes when using PostgreSQL, removing the -need for downtime. To use this method you must disable transactions by calling -the method `disable_ddl_transaction!` in the body of your migration class like -so: +need for downtime. To use this method you must disable single-transaction mode +by calling the method `disable_ddl_transaction!` in the body of your migration +class like so: ```ruby class MyMigration < ActiveRecord::Migration diff --git a/doc/university/bookclub/booklist.md b/doc/university/bookclub/booklist.md index 26c3851276b..84b1f643b91 100644 --- a/doc/university/bookclub/booklist.md +++ b/doc/university/bookclub/booklist.md @@ -10,7 +10,7 @@ List of books and resources, that may be worth reading. 1. **The Humble Programmer** - Edsger W. Dijkstra, 1972 ([paper](http://dl.acm.org/citation.cfm?id=361591)) + Edsger W. Dijkstra, 1972 ([paper](https://dl.acm.org/citation.cfm?id=361591)) ## Programming diff --git a/doc/university/high-availability/aws/README.md b/doc/university/high-availability/aws/README.md index 0a7ce922de1..b21cf27c1d3 100644 --- a/doc/university/high-availability/aws/README.md +++ b/doc/university/high-availability/aws/README.md @@ -9,7 +9,7 @@ in [significantly degraded performance](https://gitlab.com/gitlab-org/gitlab-ee/ GitLab on AWS can leverage many of the services that are already configurable with High Availability. These services have a lot of -flexibility and are able to adopt to most companies, best of all is the +flexibility and are able to adapt to most companies, best of all is the ability to automate both vertical and horizontal scaling. In this article we'll go through a basic HA setup where we'll start by @@ -55,9 +55,9 @@ and from the Actions dropdown choose Edit DNS Hostnames and select Yes. ### Subnet Now let's create some subnets in different Availability Zones. Make sure -that each subnet is associated the the VPC we just created, that it has +that each subnet is associated to the VPC we just created, that it has a distinct VPC and lastly that CIDR blocks don't overlap. This will also -allow us to enable multi AZ for redundancy. +allow us to enable multi-AZ for redundancy. We will create private and public subnets to match load balancers and RDS instances as well. @@ -98,7 +98,7 @@ traffic from any destination. ![Subnet Config](img/ig-rt.png) -Before leaving this screen select the next tab to the rgiht which is +Before leaving this screen select the next tab to the right which is Subnet Associations and add our public subnets. If you followed our naming convention they should be easy to find. @@ -106,8 +106,8 @@ naming convention they should be easy to find. ## Database with RDS -For our database server we will use Amazon RDS which offers Multi AZ -for redundancy. Lets start by creating a subnet group and then we'll +For our database server we will use Amazon RDS which offers Multi-AZ +for redundancy. Let's start by creating a subnet group and then we'll create the actual RDS instance. ### Subnet Group @@ -122,7 +122,7 @@ the VPC ID dropdown and at the bottom we can add our private subnets. Select the RDS service from the Database section and create a new PostgreSQL instance. After choosing between a Production or Development instance we'll start with the actual configuration. On the -image bellow we have the settings for this article but note the +image below we have the settings for this article but note the following two options which are of particular interest for HA: 1. Multi-AZ-Deployment is recommended as redundancy. Read more at @@ -133,7 +133,7 @@ IOPS (SSD) is best suited for HA. Read more about it at ![RDS Instance Specs](img/instance_specs.png) -The rest of the setting on this page request a DB identifier, username +The rest of the setting on this page request a DB identifier, username, and a master password. We've chosen to use `gitlab-ha`, `gitlab` and a very secure password respectively. Keep these in hand for later. @@ -152,7 +152,7 @@ EC is an in-memory hosted caching solution. Redis maintains its own persistence and is used for certain types of application. Let's choose the ElastiCache service in the Database section from our -AWS console. Now lets create a cache subnet group which will be very +AWS console. Now let's create a cache subnet group which will be very similar to the RDS subnet group. Make sure to select our VPC and its private subnets. @@ -160,7 +160,7 @@ private subnets. Now press the Launch a Cache Cluster and choose Redis for our DB engine. You'll be able to configure details such as replication, -Multi AZ and node types. The second section will allow us to choose our +Multi-AZ and node types. The second section will allow us to choose our subnet and security group and ![Redis Cluster details](img/redis-cluster-det.png) @@ -274,7 +274,7 @@ username, and password. gitlab_rails['db_password'] = "mypassword" gitlab_rails['db_host'] = "<rds-endpoint>" -Next we only need to configure the Redis section by adding the host and +Next, we only need to configure the Redis section by adding the host and uncommenting the port. @@ -285,7 +285,7 @@ to make the EFS integration easier to manage. gitlab_rails['redis_host'] = "<redis-endpoint>" gitlab_rails['redis_port'] = 6379 -Finally run reconfigure, you might find it useful to run a check and +Finally, run reconfigure. You might find it useful to run a check and a service status to make sure everything has been set up correctly. sudo gitlab-ctl reconfigure @@ -321,10 +321,10 @@ The Load Balancer Health will allow us to indicate where to ping and what makes up a healthy or unhealthy instance. We won't add the instance on the next session because we'll destroy it -momentarily as we'll be using the image we where creating. We will keep +momentarily as we'll be using the image we were creating. We will keep the Enable Cross-Zone and Enable Connection Draining active. -After we finish creating the Load Balancer we can re visit our Security +After we finish creating the Load Balancer we can revisit our Security Groups to improve access only through the ELB and any other requirement you might have. @@ -363,7 +363,7 @@ After this is launched we are able to start creating our Auto Scaling Group. Start by giving it a name and assigning it our VPC and private subnets. We also want to always start with two instances and if you scroll down to Advanced Details we can choose to receive traffic from ELBs. -Lets enable that option and select our ELB. We also want to use the ELB's +Let's enable that option and select our ELB. We also want to use the ELB's health check. ![Auto scaling](img/auto-scaling-det.png) @@ -388,9 +388,9 @@ we where aiming for. After you're done with the policies section have some fun trying to break instances. You should be able to see how the Auto Scaling Group and the -EC2 screen start bringing them up again. +EC2 screen starts bringing them up again. -High Availability is a very big area, we went mostly through scaling and +High Availability is a vast area, we went mostly through scaling and some redundancy options but it might also imply Geographic replication. There is a lot of ground yet to cover so have a read through these other resources and feel free to open an issue to request additional material. diff --git a/doc/user/project/clusters/runbooks/img/authorize-jupyter.png b/doc/user/project/clusters/runbooks/img/authorize-jupyter.png Binary files differnew file mode 100644 index 00000000000..64f95ed45f0 --- /dev/null +++ b/doc/user/project/clusters/runbooks/img/authorize-jupyter.png diff --git a/doc/user/project/clusters/runbooks/img/demo-runbook.png b/doc/user/project/clusters/runbooks/img/demo-runbook.png Binary files differnew file mode 100644 index 00000000000..25c9df4126d --- /dev/null +++ b/doc/user/project/clusters/runbooks/img/demo-runbook.png diff --git a/doc/user/project/clusters/runbooks/img/gitlab-variables.png b/doc/user/project/clusters/runbooks/img/gitlab-variables.png Binary files differnew file mode 100644 index 00000000000..f76ed21145f --- /dev/null +++ b/doc/user/project/clusters/runbooks/img/gitlab-variables.png diff --git a/doc/user/project/clusters/runbooks/img/helm-install.png b/doc/user/project/clusters/runbooks/img/helm-install.png Binary files differnew file mode 100644 index 00000000000..e39094bcbf7 --- /dev/null +++ b/doc/user/project/clusters/runbooks/img/helm-install.png diff --git a/doc/user/project/clusters/runbooks/img/ingress-install.png b/doc/user/project/clusters/runbooks/img/ingress-install.png Binary files differnew file mode 100644 index 00000000000..093c61f2d0e --- /dev/null +++ b/doc/user/project/clusters/runbooks/img/ingress-install.png diff --git a/doc/user/project/clusters/runbooks/img/jupyterhub-install.png b/doc/user/project/clusters/runbooks/img/jupyterhub-install.png Binary files differnew file mode 100644 index 00000000000..2115ec9745b --- /dev/null +++ b/doc/user/project/clusters/runbooks/img/jupyterhub-install.png diff --git a/doc/user/project/clusters/runbooks/img/postgres-query.png b/doc/user/project/clusters/runbooks/img/postgres-query.png Binary files differnew file mode 100644 index 00000000000..3880438c97a --- /dev/null +++ b/doc/user/project/clusters/runbooks/img/postgres-query.png diff --git a/doc/user/project/clusters/runbooks/img/sample-runbook.png b/doc/user/project/clusters/runbooks/img/sample-runbook.png Binary files differnew file mode 100644 index 00000000000..c12ce8990a4 --- /dev/null +++ b/doc/user/project/clusters/runbooks/img/sample-runbook.png diff --git a/doc/user/project/clusters/runbooks/index.md b/doc/user/project/clusters/runbooks/index.md index 3b81e439119..e1b8dc07b50 100644 --- a/doc/user/project/clusters/runbooks/index.md +++ b/doc/user/project/clusters/runbooks/index.md @@ -10,8 +10,8 @@ Historically, runbooks took the form of a decision tree or a detailed step-by-step guide depending on the condition or system. Modern implementations have introduced the concept of an "executable -runbooks", where along with a well define process, operators can execute -code blocks or database queries against a given environment. +runbooks", where, along with a well-defined process, operators can execute +pre-written code blocks or database queries against a given environment. ## Nurtch Executable Runbooks @@ -45,5 +45,93 @@ To create an executable runbook, you will need: Nurtch is the company behind the [Rubix library](https://github.com/Nurtch/rubix). Rubix is an open-source python library that makes it easy to perform common DevOps tasks inside Jupyter Notebooks. Tasks such as plotting Cloudwatch metrics and rolling your ECS/Kubernetes app are simplified -down to a couple of lines of code. Check the [Nurtch Documentation](http://docs.nurtch.com/en/latest) +down to a couple of lines of code. See the [Nurtch Documentation](http://docs.nurtch.com/en/latest) for more information. + +## Configure an executable runbook with GitLab + +Follow this step-by-step guide to configure an executable runbook in GitLab using +the components outlined above and the preloaded demo runbook. + +### 1. Add a Kubernetes cluster + +Follow the steps outlined in [Adding and creating a new GKE cluster via GitLab](https://docs.gitlab.com/ee/user/project/clusters/#adding-and-creating-a-new-gke-cluster-via-gitlab) +to add a Kubernetes cluster to your project. + +### 2. Install Helm Tiller, Ingress, and JupyterHub + +Once the cluster has been provisioned in GKE, click the **Install** button next to the **Helm Tiller** app. + +![install helm](img/helm-install.png) + +Once Tiller has been installed successfully, click the **Install** button next to the **Ingress** app. + +![install ingress](img/ingress-install.png) + +Once Ingress has been installed successfully, click the **Install** button next to the **JupyterHub** app. + +![install jupyterhub](img/jupyterhub-install.png) + +### 3. Login to JupyterHub and start the server + +Once JupyterHub has been installed successfully, navigate to the displayed **Jupyter Hostname** URL and click +**Sign in with GitLab**. Authentication is automatically enabled for any user of the GitLab instance via OAuth2. This +will redirect to GitLab in order to authorize JupyterHub to use your GitLab account. Click **Authorize**. + +![authorize jupyter](img/authorize-jupyter.png) + +Once the application has been authorized you will taken back to the JupyterHub application. Click **Start My Server**. +The server will take a couple of seconds to start. + +### 4. Configure access + +In order for the runbook to access your GitLab project, you will need to enter a +[GitLab Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) +as well as your Project ID in the **Setup** section of the demo runbook. + +Double-click the **DevOps-Runbook-Demo** folder located on the left panel. + +![demo runbook](img/demo-runbook.png) + +Double-click the "Nurtch-DevOps-Demo.ipynb" runbook. + +![sample runbook](img/sample-runbook.png) + +The contents on the runbook will be displayed on the right side of the screen. Under the "Setup" section, you will find +entries for both your `PRIVATE_TOKEN` and your `PROJECT_ID`. Enter both these values, conserving the single quotes as follows: + +```sql +PRIVATE_TOKEN = 'n671WNGecHugsdEDPsyo' +PROJECT_ID = '1234567' +``` + +Update the `VARIABLE_NAME` on the last line of this section to match the name of the variable you are using for your +access token. In this example our variable name is `PRIVATE_TOKEN`. + +```sql +VARIABLE_VALUE = project.variables.get('PRIVATE_TOKEN').value +``` + +### 5. Configure an operation + +For this example we'll use the "**Run SQL queries in Notebook**" section in the sample runbook to query +a postgres database. The first 4 lines of the section define the variables that are required for this query to function. + +```sql +%env DB_USER={project.variables.get('DB_USER').value} +%env DB_PASSWORD={project.variables.get('DB_PASSWORD').value} +%env DB_ENDPOINT={project.variables.get('DB_ENDPOINT').value} +%env DB_NAME={project.variables.get('DB_NAME').value} +``` + +Create the matching variables in your project's **Settings >> CI/CD >> Variables** + +![gitlab variables](img/gitlab-variables.png) + +Back in Jupyter, click the "Run SQL queries in Notebook" heading and the click *Run*. The results will be +displayed in-line as follows: + +![postgres query](img/postgres-query.png) + +You can try other operations such as running shell scripts or interacting with a Kubernetes cluster. Visit the +[Nurtch Documentation](http://docs.nurtch.com/) for more information.
\ No newline at end of file diff --git a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png Binary files differindex 3b3bf88df31..1cdac5ef573 100644 --- a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png +++ b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png diff --git a/doc/user/project/merge_requests/img/merge_request_pipeline.png b/doc/user/project/merge_requests/img/merge_request_pipeline.png Binary files differnew file mode 100644 index 00000000000..183d9cb910b --- /dev/null +++ b/doc/user/project/merge_requests/img/merge_request_pipeline.png diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index 8a68185798b..a0e7c1c99d5 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -231,9 +231,10 @@ have been marked as a **Work In Progress**. ## Merge request diff file navigation -The diff view has a file tree for file navigation. As you scroll through -diffs with a large number of files, you can easily jump to any changed file -using the file tree. +When reviewing changes in the **Changes** tab the diff can be navigated using +the file tree or file list. As you scroll through large diffs with many +changes, you can quickly jump to any changed file using the file tree or file +list. ![Merge request diff file navigation](img/merge_request_diff_file_navigation.png) @@ -258,6 +259,34 @@ all your changes will be available to preview by anyone with the Review Apps lin [Read more about Review Apps.](../../../ci/review_apps/index.md) +## Pipeline status in merge requests + +If you've set up [GitLab CI/CD](../../../ci/README.md) in your project, +you will be able to see: + +- Both pre and post-merge pipelines and the environment information if any. +- Which deployments are in progress. + +If there's an [environment](../../../ci/environments.md) and the application is +successfully deployed to it, the deployed environment and the link to the +Review App will be shown as well. + +### Post-merge pipeline status + +When a merge request is merged, you can see the post-merge pipeline status of +the branch the merge request was merged into. For example, when a merge request +is merged into the master branch and then triggers a deployment to the staging +environment. + +Deployments that are ongoing will be shown, as well as the deploying/deployed state +for environments. If it's the first time the branch is deployed, the link +will return a `404` error until done. During the deployment, the stop button will +be disabled. If the pipeline fails to deploy, the deployment info will be hidden. + +![Merge request pipeline](img/merge_request_pipeline.png) + +For more information, [read about pipelines](../../../ci/pipelines.md). + ## Bulk editing merge requests Find out about [bulk editing merge requests](../../project/bulk_editing.md). diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index 0a4542b71ed..85a03d125dd 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -53,6 +53,7 @@ discussions, and descriptions: | `/target_branch <Local branch Name>` | Set target branch | | ✓ | | `/wip` | Toggle the Work In Progress status | | ✓ | | `/merge` | Merge (when pipeline succeeds) | | ✓ | +| `/create_merge_request <branch name>` | Create a new merge request starting from the current issue | ✓ | | ## Quick actions for commit messages diff --git a/lib/gitlab/auth/saml/auth_hash.rb b/lib/gitlab/auth/saml/auth_hash.rb index 316354fd50c..1af9fa40c3a 100644 --- a/lib/gitlab/auth/saml/auth_hash.rb +++ b/lib/gitlab/auth/saml/auth_hash.rb @@ -28,7 +28,7 @@ module Gitlab end def extract_authn_context(document) - REXML::XPath.first(document, "//saml:AuthnStatement/saml:AuthnContext/saml:AuthnContextClassRef/text()").to_s + REXML::XPath.first(document, "//*[name()='saml:AuthnStatement' or name()='saml2:AuthnStatement']/*[name()='saml:AuthnContext' or name()='saml2:AuthnContext']/*[name()='saml:AuthnContextClassRef' or name()='saml2:AuthnContextClassRef']/text()").to_s end end end diff --git a/lib/gitlab/cache/ci/project_pipeline_status.rb b/lib/gitlab/cache/ci/project_pipeline_status.rb index dfbb83f7bb9..78b0eaac8cd 100644 --- a/lib/gitlab/cache/ci/project_pipeline_status.rb +++ b/lib/gitlab/cache/ci/project_pipeline_status.rb @@ -42,7 +42,7 @@ module Gitlab end def self.cache_key_for_project(project) - "#{Gitlab::Redis::Cache::CACHE_NAMESPACE}:projects/#{project.id}/pipeline_status/#{project.commit&.sha}" + "#{Gitlab::Redis::Cache::CACHE_NAMESPACE}:project:#{project.id}:pipeline_status:#{project.commit&.sha}" end def self.update_for_pipeline(pipeline) diff --git a/lib/gitlab/hook_data/base_builder.rb b/lib/gitlab/hook_data/base_builder.rb index 1a91301e8be..d54175bce81 100644 --- a/lib/gitlab/hook_data/base_builder.rb +++ b/lib/gitlab/hook_data/base_builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module HookData class BaseBuilder diff --git a/lib/gitlab/hook_data/issuable_builder.rb b/lib/gitlab/hook_data/issuable_builder.rb index 65389835ad7..0803df65632 100644 --- a/lib/gitlab/hook_data/issuable_builder.rb +++ b/lib/gitlab/hook_data/issuable_builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module HookData class IssuableBuilder < BaseBuilder diff --git a/lib/gitlab/hook_data/issue_builder.rb b/lib/gitlab/hook_data/issue_builder.rb index dd63db969f6..c99353b9d49 100644 --- a/lib/gitlab/hook_data/issue_builder.rb +++ b/lib/gitlab/hook_data/issue_builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module HookData class IssueBuilder < BaseBuilder diff --git a/lib/gitlab/hook_data/merge_request_builder.rb b/lib/gitlab/hook_data/merge_request_builder.rb index 3aa6a4f3767..ad38e26e40a 100644 --- a/lib/gitlab/hook_data/merge_request_builder.rb +++ b/lib/gitlab/hook_data/merge_request_builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module HookData class MergeRequestBuilder < BaseBuilder diff --git a/lib/gitlab/hook_data/note_builder.rb b/lib/gitlab/hook_data/note_builder.rb index 81873e345d5..ae30ef6364b 100644 --- a/lib/gitlab/hook_data/note_builder.rb +++ b/lib/gitlab/hook_data/note_builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module HookData class NoteBuilder < BaseBuilder diff --git a/lib/gitlab/hook_data/wiki_page_builder.rb b/lib/gitlab/hook_data/wiki_page_builder.rb index 59c94a61cf2..67f06b1ca46 100644 --- a/lib/gitlab/hook_data/wiki_page_builder.rb +++ b/lib/gitlab/hook_data/wiki_page_builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module HookData class WikiPageBuilder < BaseBuilder diff --git a/lib/gitlab/i18n/metadata_entry.rb b/lib/gitlab/i18n/metadata_entry.rb index 36fc1bcdcb7..3764e379681 100644 --- a/lib/gitlab/i18n/metadata_entry.rb +++ b/lib/gitlab/i18n/metadata_entry.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module I18n class MetadataEntry diff --git a/lib/gitlab/i18n/po_linter.rb b/lib/gitlab/i18n/po_linter.rb index d8e7269a2c2..644ef8c8589 100644 --- a/lib/gitlab/i18n/po_linter.rb +++ b/lib/gitlab/i18n/po_linter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module I18n class PoLinter diff --git a/lib/gitlab/i18n/translation_entry.rb b/lib/gitlab/i18n/translation_entry.rb index 54adb98f42d..19c10b2e402 100644 --- a/lib/gitlab/i18n/translation_entry.rb +++ b/lib/gitlab/i18n/translation_entry.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module I18n class TranslationEntry diff --git a/lib/gitlab/import/logger.rb b/lib/gitlab/import/logger.rb index 8414954d141..ab3e822a4e9 100644 --- a/lib/gitlab/import/logger.rb +++ b/lib/gitlab/import/logger.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Import class Logger < ::Gitlab::JsonLogger diff --git a/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb b/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb index 7cbf653dd97..d39b6fe5955 100644 --- a/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb +++ b/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport module AfterExportStrategies diff --git a/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb b/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb index 4371a7eff56..1b391314a74 100644 --- a/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb +++ b/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport module AfterExportStrategies diff --git a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb index 4f29bdcea2c..b30900f7c61 100644 --- a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb +++ b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport module AfterExportStrategies diff --git a/lib/gitlab/import_export/after_export_strategy_builder.rb b/lib/gitlab/import_export/after_export_strategy_builder.rb index 7eabcae2380..37394f46a99 100644 --- a/lib/gitlab/import_export/after_export_strategy_builder.rb +++ b/lib/gitlab/import_export/after_export_strategy_builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class AfterExportStrategyBuilder diff --git a/lib/gitlab/import_export/attribute_cleaner.rb b/lib/gitlab/import_export/attribute_cleaner.rb index 7c9fc5c15bb..93b37b7bc5f 100644 --- a/lib/gitlab/import_export/attribute_cleaner.rb +++ b/lib/gitlab/import_export/attribute_cleaner.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class AttributeCleaner diff --git a/lib/gitlab/import_export/attributes_finder.rb b/lib/gitlab/import_export/attributes_finder.rb index 0c8fda07294..409243e68a5 100644 --- a/lib/gitlab/import_export/attributes_finder.rb +++ b/lib/gitlab/import_export/attributes_finder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class AttributesFinder diff --git a/lib/gitlab/import_export/avatar_restorer.rb b/lib/gitlab/import_export/avatar_restorer.rb index 17796430811..be1b97bd7a7 100644 --- a/lib/gitlab/import_export/avatar_restorer.rb +++ b/lib/gitlab/import_export/avatar_restorer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class AvatarRestorer diff --git a/lib/gitlab/import_export/avatar_saver.rb b/lib/gitlab/import_export/avatar_saver.rb index 6ffebf83dd2..47ca898c690 100644 --- a/lib/gitlab/import_export/avatar_saver.rb +++ b/lib/gitlab/import_export/avatar_saver.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class AvatarSaver diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb index 3adc44f8044..c9e2a6a78d9 100644 --- a/lib/gitlab/import_export/command_line_util.rb +++ b/lib/gitlab/import_export/command_line_util.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport module CommandLineUtil diff --git a/lib/gitlab/import_export/error.rb b/lib/gitlab/import_export/error.rb index 788eedf2686..454dc778b6b 100644 --- a/lib/gitlab/import_export/error.rb +++ b/lib/gitlab/import_export/error.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport Error = Class.new(StandardError) diff --git a/lib/gitlab/import_export/file_importer.rb b/lib/gitlab/import_export/file_importer.rb index 7fd66b4e244..05432f433e7 100644 --- a/lib/gitlab/import_export/file_importer.rb +++ b/lib/gitlab/import_export/file_importer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class FileImporter diff --git a/lib/gitlab/import_export/group_project_object_builder.rb b/lib/gitlab/import_export/group_project_object_builder.rb index 6c2af770119..1c62591ed5a 100644 --- a/lib/gitlab/import_export/group_project_object_builder.rb +++ b/lib/gitlab/import_export/group_project_object_builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport # Given a class, it finds or creates a new object diff --git a/lib/gitlab/import_export/hash_util.rb b/lib/gitlab/import_export/hash_util.rb index d4adeeb3797..b6ce89a973b 100644 --- a/lib/gitlab/import_export/hash_util.rb +++ b/lib/gitlab/import_export/hash_util.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class HashUtil diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index 9790818ecaf..b40eac3de9a 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -154,6 +154,8 @@ excluded_attributes: - :encrypted_token_iv - :encrypted_url - :encrypted_url_iv + services: + - :template methods: labels: diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb index 72d5b9b830c..767f1b5de0e 100644 --- a/lib/gitlab/import_export/importer.rb +++ b/lib/gitlab/import_export/importer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class Importer diff --git a/lib/gitlab/import_export/json_hash_builder.rb b/lib/gitlab/import_export/json_hash_builder.rb index b48f63bcd7e..477499e1688 100644 --- a/lib/gitlab/import_export/json_hash_builder.rb +++ b/lib/gitlab/import_export/json_hash_builder.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport # Generates a hash that conforms with http://apidock.com/rails/Hash/to_json diff --git a/lib/gitlab/import_export/lfs_restorer.rb b/lib/gitlab/import_export/lfs_restorer.rb index b28c3c161b7..345c7880e30 100644 --- a/lib/gitlab/import_export/lfs_restorer.rb +++ b/lib/gitlab/import_export/lfs_restorer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class LfsRestorer diff --git a/lib/gitlab/import_export/lfs_saver.rb b/lib/gitlab/import_export/lfs_saver.rb index 29410e2331c..954f6f00078 100644 --- a/lib/gitlab/import_export/lfs_saver.rb +++ b/lib/gitlab/import_export/lfs_saver.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class LfsSaver diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index bcbaf00e11b..6be95a16513 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class MembersMapper diff --git a/lib/gitlab/import_export/merge_request_parser.rb b/lib/gitlab/import_export/merge_request_parser.rb index 62a1833b39c..040a70d6775 100644 --- a/lib/gitlab/import_export/merge_request_parser.rb +++ b/lib/gitlab/import_export/merge_request_parser.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class MergeRequestParser diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 99581eb0416..8cd4efd91cc 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class ProjectTreeRestorer diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb index 5510c0b8b2f..29f2dc80813 100644 --- a/lib/gitlab/import_export/project_tree_saver.rb +++ b/lib/gitlab/import_export/project_tree_saver.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class ProjectTreeSaver diff --git a/lib/gitlab/import_export/reader.rb b/lib/gitlab/import_export/reader.rb index e621c40fc7a..bc0d18e03fa 100644 --- a/lib/gitlab/import_export/reader.rb +++ b/lib/gitlab/import_export/reader.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class Reader diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 2486b1e4921..097c7653754 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class RelationFactory @@ -211,7 +213,7 @@ module Gitlab def update_note_for_missing_author(author_name) @relation_hash['note'] = '*Blank note*' if @relation_hash['note'].blank? - @relation_hash['note'] += missing_author_note(@relation_hash['updated_at'], author_name) + @relation_hash['note'] = "#{@relation_hash['note']}#{missing_author_note(@relation_hash['updated_at'], author_name)}" end def admin_user? diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb index 5a9bbceac67..921a06b4023 100644 --- a/lib/gitlab/import_export/repo_restorer.rb +++ b/lib/gitlab/import_export/repo_restorer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class RepoRestorer diff --git a/lib/gitlab/import_export/repo_saver.rb b/lib/gitlab/import_export/repo_saver.rb index 0c224bd1971..a60618dfcec 100644 --- a/lib/gitlab/import_export/repo_saver.rb +++ b/lib/gitlab/import_export/repo_saver.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class RepoSaver diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb index 59a74083395..72f575db095 100644 --- a/lib/gitlab/import_export/saver.rb +++ b/lib/gitlab/import_export/saver.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class Saver diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb index 6d7c36ce38b..c13e6c1d83b 100644 --- a/lib/gitlab/import_export/shared.rb +++ b/lib/gitlab/import_export/shared.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class Shared diff --git a/lib/gitlab/import_export/statistics_restorer.rb b/lib/gitlab/import_export/statistics_restorer.rb index bcdd9c12c85..3fafb01c37c 100644 --- a/lib/gitlab/import_export/statistics_restorer.rb +++ b/lib/gitlab/import_export/statistics_restorer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class StatisticsRestorer diff --git a/lib/gitlab/import_export/uploads_manager.rb b/lib/gitlab/import_export/uploads_manager.rb index 8511319cb1c..474e9d45566 100644 --- a/lib/gitlab/import_export/uploads_manager.rb +++ b/lib/gitlab/import_export/uploads_manager.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class UploadsManager diff --git a/lib/gitlab/import_export/uploads_restorer.rb b/lib/gitlab/import_export/uploads_restorer.rb index b4313ff4cb4..5f422dcbefa 100644 --- a/lib/gitlab/import_export/uploads_restorer.rb +++ b/lib/gitlab/import_export/uploads_restorer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class UploadsRestorer < UploadsSaver diff --git a/lib/gitlab/import_export/uploads_saver.rb b/lib/gitlab/import_export/uploads_saver.rb index 0275f686c5e..be1066c30b2 100644 --- a/lib/gitlab/import_export/uploads_saver.rb +++ b/lib/gitlab/import_export/uploads_saver.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class UploadsSaver diff --git a/lib/gitlab/import_export/version_checker.rb b/lib/gitlab/import_export/version_checker.rb index bd3c3ee3b2f..6d978d00ea5 100644 --- a/lib/gitlab/import_export/version_checker.rb +++ b/lib/gitlab/import_export/version_checker.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class VersionChecker diff --git a/lib/gitlab/import_export/version_saver.rb b/lib/gitlab/import_export/version_saver.rb index 7cf88298642..8230c0f1e77 100644 --- a/lib/gitlab/import_export/version_saver.rb +++ b/lib/gitlab/import_export/version_saver.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class VersionSaver diff --git a/lib/gitlab/import_export/wiki_repo_saver.rb b/lib/gitlab/import_export/wiki_repo_saver.rb index 2fd62c0fc7b..7303bcf61a4 100644 --- a/lib/gitlab/import_export/wiki_repo_saver.rb +++ b/lib/gitlab/import_export/wiki_repo_saver.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class WikiRepoSaver < RepoSaver diff --git a/lib/gitlab/import_export/wiki_restorer.rb b/lib/gitlab/import_export/wiki_restorer.rb index f33bfb332ab..28b5e7449cd 100644 --- a/lib/gitlab/import_export/wiki_restorer.rb +++ b/lib/gitlab/import_export/wiki_restorer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ImportExport class WikiRestorer < RepoRestorer diff --git a/lib/gitlab/kubernetes/config_map.rb b/lib/gitlab/kubernetes/config_map.rb index 9e55dae137c..0bcaaa03974 100644 --- a/lib/gitlab/kubernetes/config_map.rb +++ b/lib/gitlab/kubernetes/config_map.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Kubernetes class ConfigMap diff --git a/lib/gitlab/kubernetes/helm.rb b/lib/gitlab/kubernetes/helm.rb index 5a22b5e3364..03d38ec78fd 100644 --- a/lib/gitlab/kubernetes/helm.rb +++ b/lib/gitlab/kubernetes/helm.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Kubernetes module Helm diff --git a/lib/gitlab/kubernetes/helm/api.rb b/lib/gitlab/kubernetes/helm/api.rb index 7c026ac9e68..fd3d187cbc3 100644 --- a/lib/gitlab/kubernetes/helm/api.rb +++ b/lib/gitlab/kubernetes/helm/api.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Kubernetes module Helm diff --git a/lib/gitlab/kubernetes/helm/base_command.rb b/lib/gitlab/kubernetes/helm/base_command.rb index f2ce24fefa1..2bcb428b25d 100644 --- a/lib/gitlab/kubernetes/helm/base_command.rb +++ b/lib/gitlab/kubernetes/helm/base_command.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Kubernetes module Helm diff --git a/lib/gitlab/kubernetes/helm/client_command.rb b/lib/gitlab/kubernetes/helm/client_command.rb index 72bafc07bf0..9940272a8bf 100644 --- a/lib/gitlab/kubernetes/helm/client_command.rb +++ b/lib/gitlab/kubernetes/helm/client_command.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Kubernetes module Helm diff --git a/lib/gitlab/kubernetes/helm/init_command.rb b/lib/gitlab/kubernetes/helm/init_command.rb index 6691080deca..88ed8572ffc 100644 --- a/lib/gitlab/kubernetes/helm/init_command.rb +++ b/lib/gitlab/kubernetes/helm/init_command.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Kubernetes module Helm diff --git a/lib/gitlab/kubernetes/helm/install_command.rb b/lib/gitlab/kubernetes/helm/install_command.rb index 7e38c0a430b..a1ab5e048ac 100644 --- a/lib/gitlab/kubernetes/helm/install_command.rb +++ b/lib/gitlab/kubernetes/helm/install_command.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Kubernetes module Helm diff --git a/lib/gitlab/kubernetes/helm/pod.rb b/lib/gitlab/kubernetes/helm/pod.rb index e9c621d96f0..75484f80070 100644 --- a/lib/gitlab/kubernetes/helm/pod.rb +++ b/lib/gitlab/kubernetes/helm/pod.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Kubernetes module Helm diff --git a/lib/gitlab/kubernetes/namespace.rb b/lib/gitlab/kubernetes/namespace.rb index 783c8a24741..919f19c86d7 100644 --- a/lib/gitlab/kubernetes/namespace.rb +++ b/lib/gitlab/kubernetes/namespace.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Kubernetes class Namespace diff --git a/lib/gitlab/kubernetes/pod.rb b/lib/gitlab/kubernetes/pod.rb index f3842cdf762..81317e532b2 100644 --- a/lib/gitlab/kubernetes/pod.rb +++ b/lib/gitlab/kubernetes/pod.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Kubernetes module Pod diff --git a/lib/gitlab/legacy_github_import/base_formatter.rb b/lib/gitlab/legacy_github_import/base_formatter.rb index 11d1300e51e..0b19cf742ed 100644 --- a/lib/gitlab/legacy_github_import/base_formatter.rb +++ b/lib/gitlab/legacy_github_import/base_formatter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class BaseFormatter diff --git a/lib/gitlab/legacy_github_import/branch_formatter.rb b/lib/gitlab/legacy_github_import/branch_formatter.rb index 80fe1d67209..1177751457f 100644 --- a/lib/gitlab/legacy_github_import/branch_formatter.rb +++ b/lib/gitlab/legacy_github_import/branch_formatter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class BranchFormatter < BaseFormatter diff --git a/lib/gitlab/legacy_github_import/client.rb b/lib/gitlab/legacy_github_import/client.rb index d8ed0ebca9d..bc952147667 100644 --- a/lib/gitlab/legacy_github_import/client.rb +++ b/lib/gitlab/legacy_github_import/client.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class Client diff --git a/lib/gitlab/legacy_github_import/comment_formatter.rb b/lib/gitlab/legacy_github_import/comment_formatter.rb index d2c7a8ae9f4..d83cc4f6b3c 100644 --- a/lib/gitlab/legacy_github_import/comment_formatter.rb +++ b/lib/gitlab/legacy_github_import/comment_formatter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class CommentFormatter < BaseFormatter diff --git a/lib/gitlab/legacy_github_import/importer.rb b/lib/gitlab/legacy_github_import/importer.rb index c5bde681365..43695451b87 100644 --- a/lib/gitlab/legacy_github_import/importer.rb +++ b/lib/gitlab/legacy_github_import/importer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class Importer diff --git a/lib/gitlab/legacy_github_import/issuable_formatter.rb b/lib/gitlab/legacy_github_import/issuable_formatter.rb index 7db4a54267e..1a0aefbbd62 100644 --- a/lib/gitlab/legacy_github_import/issuable_formatter.rb +++ b/lib/gitlab/legacy_github_import/issuable_formatter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class IssuableFormatter < BaseFormatter diff --git a/lib/gitlab/legacy_github_import/issue_formatter.rb b/lib/gitlab/legacy_github_import/issue_formatter.rb index 4c8825ccf19..2f46e2e30d1 100644 --- a/lib/gitlab/legacy_github_import/issue_formatter.rb +++ b/lib/gitlab/legacy_github_import/issue_formatter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class IssueFormatter < IssuableFormatter diff --git a/lib/gitlab/legacy_github_import/label_formatter.rb b/lib/gitlab/legacy_github_import/label_formatter.rb index e9663650903..89200e794d8 100644 --- a/lib/gitlab/legacy_github_import/label_formatter.rb +++ b/lib/gitlab/legacy_github_import/label_formatter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class LabelFormatter < BaseFormatter diff --git a/lib/gitlab/legacy_github_import/milestone_formatter.rb b/lib/gitlab/legacy_github_import/milestone_formatter.rb index a565294384d..2fe1b4258d3 100644 --- a/lib/gitlab/legacy_github_import/milestone_formatter.rb +++ b/lib/gitlab/legacy_github_import/milestone_formatter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class MilestoneFormatter < BaseFormatter diff --git a/lib/gitlab/legacy_github_import/project_creator.rb b/lib/gitlab/legacy_github_import/project_creator.rb index 5e96eb16754..ca1a1b8e9bd 100644 --- a/lib/gitlab/legacy_github_import/project_creator.rb +++ b/lib/gitlab/legacy_github_import/project_creator.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class ProjectCreator diff --git a/lib/gitlab/legacy_github_import/pull_request_formatter.rb b/lib/gitlab/legacy_github_import/pull_request_formatter.rb index 94c2e99066a..5b847f13d4a 100644 --- a/lib/gitlab/legacy_github_import/pull_request_formatter.rb +++ b/lib/gitlab/legacy_github_import/pull_request_formatter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class PullRequestFormatter < IssuableFormatter diff --git a/lib/gitlab/legacy_github_import/release_formatter.rb b/lib/gitlab/legacy_github_import/release_formatter.rb index 3ed9d4f76da..8c0c17780ca 100644 --- a/lib/gitlab/legacy_github_import/release_formatter.rb +++ b/lib/gitlab/legacy_github_import/release_formatter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class ReleaseFormatter < BaseFormatter diff --git a/lib/gitlab/legacy_github_import/user_formatter.rb b/lib/gitlab/legacy_github_import/user_formatter.rb index 3794380e2d0..ec0e221b1ff 100644 --- a/lib/gitlab/legacy_github_import/user_formatter.rb +++ b/lib/gitlab/legacy_github_import/user_formatter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class UserFormatter diff --git a/lib/gitlab/legacy_github_import/wiki_formatter.rb b/lib/gitlab/legacy_github_import/wiki_formatter.rb index 27f45875c7c..ea52be5ee0f 100644 --- a/lib/gitlab/legacy_github_import/wiki_formatter.rb +++ b/lib/gitlab/legacy_github_import/wiki_formatter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module LegacyGithubImport class WikiFormatter diff --git a/lib/gitlab/manifest_import/manifest.rb b/lib/gitlab/manifest_import/manifest.rb index b69b9ac4b64..7208fe5bbc5 100644 --- a/lib/gitlab/manifest_import/manifest.rb +++ b/lib/gitlab/manifest_import/manifest.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Class to parse manifest file and build a list of repositories for import # # <manifest> diff --git a/lib/gitlab/manifest_import/project_creator.rb b/lib/gitlab/manifest_import/project_creator.rb index b5967c93735..837d65e5f7c 100644 --- a/lib/gitlab/manifest_import/project_creator.rb +++ b/lib/gitlab/manifest_import/project_creator.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module ManifestImport class ProjectCreator diff --git a/lib/gitlab/metrics/background_transaction.rb b/lib/gitlab/metrics/background_transaction.rb index 5919ebb1493..fe1722b1095 100644 --- a/lib/gitlab/metrics/background_transaction.rb +++ b/lib/gitlab/metrics/background_transaction.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics class BackgroundTransaction < Transaction diff --git a/lib/gitlab/metrics/delta.rb b/lib/gitlab/metrics/delta.rb index bcf28eed84d..ab2d9e46390 100644 --- a/lib/gitlab/metrics/delta.rb +++ b/lib/gitlab/metrics/delta.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics # Class for calculating the difference between two numeric values. diff --git a/lib/gitlab/metrics/influx_db.rb b/lib/gitlab/metrics/influx_db.rb index ce9d3ec3de4..1359e973590 100644 --- a/lib/gitlab/metrics/influx_db.rb +++ b/lib/gitlab/metrics/influx_db.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics module InfluxDb diff --git a/lib/gitlab/metrics/instrumentation.rb b/lib/gitlab/metrics/instrumentation.rb index 023e9963493..651e241362c 100644 --- a/lib/gitlab/metrics/instrumentation.rb +++ b/lib/gitlab/metrics/instrumentation.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics # Module for instrumenting methods. diff --git a/lib/gitlab/metrics/method_call.rb b/lib/gitlab/metrics/method_call.rb index f3290e3149c..85438011cb9 100644 --- a/lib/gitlab/metrics/method_call.rb +++ b/lib/gitlab/metrics/method_call.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics # Class for tracking timing information about method calls diff --git a/lib/gitlab/metrics/methods.rb b/lib/gitlab/metrics/methods.rb index f79eb0cd1bf..447d03bfca4 100644 --- a/lib/gitlab/metrics/methods.rb +++ b/lib/gitlab/metrics/methods.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # rubocop:disable Style/ClassVars module Gitlab diff --git a/lib/gitlab/metrics/methods/metric_options.rb b/lib/gitlab/metrics/methods/metric_options.rb index 70e122d4e15..8e6ceb74c09 100644 --- a/lib/gitlab/metrics/methods/metric_options.rb +++ b/lib/gitlab/metrics/methods/metric_options.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics module Methods diff --git a/lib/gitlab/metrics/metric.rb b/lib/gitlab/metrics/metric.rb index bd0afe53c51..9e4d70a71ff 100644 --- a/lib/gitlab/metrics/metric.rb +++ b/lib/gitlab/metrics/metric.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics # Class for storing details of a single metric (label, value, etc). diff --git a/lib/gitlab/metrics/null_metric.rb b/lib/gitlab/metrics/null_metric.rb index aabada5c21a..7dbd2a1f8e3 100644 --- a/lib/gitlab/metrics/null_metric.rb +++ b/lib/gitlab/metrics/null_metric.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics # Mocks ::Prometheus::Client::Metric and all derived metrics diff --git a/lib/gitlab/metrics/prometheus.rb b/lib/gitlab/metrics/prometheus.rb index d41a855bff1..cab1edab48f 100644 --- a/lib/gitlab/metrics/prometheus.rb +++ b/lib/gitlab/metrics/prometheus.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'prometheus/client' module Gitlab diff --git a/lib/gitlab/metrics/rack_middleware.rb b/lib/gitlab/metrics/rack_middleware.rb index 2d45765df3f..9aa97515961 100644 --- a/lib/gitlab/metrics/rack_middleware.rb +++ b/lib/gitlab/metrics/rack_middleware.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics # Rack middleware for tracking Rails and Grape requests. diff --git a/lib/gitlab/metrics/requests_rack_middleware.rb b/lib/gitlab/metrics/requests_rack_middleware.rb index 0dc19f31d03..74c956ab5af 100644 --- a/lib/gitlab/metrics/requests_rack_middleware.rb +++ b/lib/gitlab/metrics/requests_rack_middleware.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics class RequestsRackMiddleware diff --git a/lib/gitlab/metrics/samplers/base_sampler.rb b/lib/gitlab/metrics/samplers/base_sampler.rb index 37f90c4673d..6a062e93f0f 100644 --- a/lib/gitlab/metrics/samplers/base_sampler.rb +++ b/lib/gitlab/metrics/samplers/base_sampler.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'logger' module Gitlab diff --git a/lib/gitlab/metrics/samplers/influx_sampler.rb b/lib/gitlab/metrics/samplers/influx_sampler.rb index ad97632e4eb..c4c38b23a55 100644 --- a/lib/gitlab/metrics/samplers/influx_sampler.rb +++ b/lib/gitlab/metrics/samplers/influx_sampler.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics module Samplers diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb index 7b2b3bedf04..232a58a7d69 100644 --- a/lib/gitlab/metrics/samplers/ruby_sampler.rb +++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'prometheus/client/support/unicorn' module Gitlab diff --git a/lib/gitlab/metrics/samplers/unicorn_sampler.rb b/lib/gitlab/metrics/samplers/unicorn_sampler.rb index ea325651fbb..4c4ec026823 100644 --- a/lib/gitlab/metrics/samplers/unicorn_sampler.rb +++ b/lib/gitlab/metrics/samplers/unicorn_sampler.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics module Samplers diff --git a/lib/gitlab/metrics/sidekiq_metrics_exporter.rb b/lib/gitlab/metrics/sidekiq_metrics_exporter.rb index 47b4af5d649..56e106b9612 100644 --- a/lib/gitlab/metrics/sidekiq_metrics_exporter.rb +++ b/lib/gitlab/metrics/sidekiq_metrics_exporter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'webrick' require 'prometheus/client/rack/exporter' diff --git a/lib/gitlab/metrics/sidekiq_middleware.rb b/lib/gitlab/metrics/sidekiq_middleware.rb index df4bdf16847..0b4485feea9 100644 --- a/lib/gitlab/metrics/sidekiq_middleware.rb +++ b/lib/gitlab/metrics/sidekiq_middleware.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics # Sidekiq middleware for tracking jobs. diff --git a/lib/gitlab/metrics/subscribers/action_view.rb b/lib/gitlab/metrics/subscribers/action_view.rb index b600e8a2a50..c068f8017fd 100644 --- a/lib/gitlab/metrics/subscribers/action_view.rb +++ b/lib/gitlab/metrics/subscribers/action_view.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics module Subscribers diff --git a/lib/gitlab/metrics/subscribers/active_record.rb b/lib/gitlab/metrics/subscribers/active_record.rb index 04107296ae3..a02dd850582 100644 --- a/lib/gitlab/metrics/subscribers/active_record.rb +++ b/lib/gitlab/metrics/subscribers/active_record.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics module Subscribers diff --git a/lib/gitlab/metrics/subscribers/rails_cache.rb b/lib/gitlab/metrics/subscribers/rails_cache.rb index 250897a79c2..f633e1a9d7c 100644 --- a/lib/gitlab/metrics/subscribers/rails_cache.rb +++ b/lib/gitlab/metrics/subscribers/rails_cache.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics module Subscribers diff --git a/lib/gitlab/metrics/system.rb b/lib/gitlab/metrics/system.rb index e60e245cf89..426496855e3 100644 --- a/lib/gitlab/metrics/system.rb +++ b/lib/gitlab/metrics/system.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics # Module for gathering system/process statistics such as the memory usage. diff --git a/lib/gitlab/metrics/transaction.rb b/lib/gitlab/metrics/transaction.rb index 9f903e96585..468d7cb56fc 100644 --- a/lib/gitlab/metrics/transaction.rb +++ b/lib/gitlab/metrics/transaction.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics # Class for storing metrics information of a single transaction. diff --git a/lib/gitlab/metrics/web_transaction.rb b/lib/gitlab/metrics/web_transaction.rb index 723ca576aab..b2a43d46fb2 100644 --- a/lib/gitlab/metrics/web_transaction.rb +++ b/lib/gitlab/metrics/web_transaction.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Metrics class WebTransaction < Transaction @@ -40,7 +42,7 @@ module Gitlab # increasing the cardinality of our metrics, we limit the number of # possible suffixes. if suffix && ALLOWED_SUFFIXES.include?(suffix) - action += ".#{suffix}" + action = "#{action}.#{suffix}" end { controller: controller.class.name, action: action } diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb index 6943567fb6d..d1a87c3b3bb 100644 --- a/lib/gitlab/middleware/go.rb +++ b/lib/gitlab/middleware/go.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # A dumb middleware that returns a Go HTML document if the go-get=1 query string # is used irrespective if the namespace/project exists module Gitlab diff --git a/lib/gitlab/middleware/multipart.rb b/lib/gitlab/middleware/multipart.rb index 10cb1e7127e..84c2f0d5720 100644 --- a/lib/gitlab/middleware/multipart.rb +++ b/lib/gitlab/middleware/multipart.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Gitlab::Middleware::Multipart - a Rack::Multipart replacement # # Rack::Multipart leaves behind tempfiles in /tmp and uses valuable Ruby diff --git a/lib/gitlab/middleware/rails_queue_duration.rb b/lib/gitlab/middleware/rails_queue_duration.rb index bc70b2459ef..96c6a0a7d28 100644 --- a/lib/gitlab/middleware/rails_queue_duration.rb +++ b/lib/gitlab/middleware/rails_queue_duration.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This Rack middleware is intended to measure the latency between # gitlab-workhorse forwarding a request to the Rails application and the # time this middleware is reached. diff --git a/lib/gitlab/middleware/read_only.rb b/lib/gitlab/middleware/read_only.rb index 7f63e39b3aa..83c52a6c6e0 100644 --- a/lib/gitlab/middleware/read_only.rb +++ b/lib/gitlab/middleware/read_only.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Middleware class ReadOnly diff --git a/lib/gitlab/middleware/read_only/controller.rb b/lib/gitlab/middleware/read_only/controller.rb index 8dca431c005..89941a9efa0 100644 --- a/lib/gitlab/middleware/read_only/controller.rb +++ b/lib/gitlab/middleware/read_only/controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Middleware class ReadOnly diff --git a/lib/gitlab/middleware/release_env.rb b/lib/gitlab/middleware/release_env.rb index bfe8e113b5e..849cf8f759b 100644 --- a/lib/gitlab/middleware/release_env.rb +++ b/lib/gitlab/middleware/release_env.rb @@ -1,4 +1,7 @@ -module Gitlab # rubocop:disable Naming/FileName +# rubocop:disable Naming/FileName +# frozen_string_literal: true + +module Gitlab module Middleware # Some of middleware would hold env for no good reason even after the # request had already been processed, and we could not garbage collect diff --git a/lib/gitlab/middleware/static.rb b/lib/gitlab/middleware/static.rb index aa1e9dc0fdb..972fed2134c 100644 --- a/lib/gitlab/middleware/static.rb +++ b/lib/gitlab/middleware/static.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Gitlab module Middleware class Static < ActionDispatch::Static diff --git a/lib/gitlab/repository_cache.rb b/lib/gitlab/repository_cache.rb index 56007574b1b..6b0808f5304 100644 --- a/lib/gitlab/repository_cache.rb +++ b/lib/gitlab/repository_cache.rb @@ -7,13 +7,13 @@ module Gitlab def initialize(repository, extra_namespace: nil, backend: Rails.cache) @repository = repository - @namespace = "#{repository.full_path}:#{repository.project.id}" + @namespace = "project:#{repository.project.id}" @namespace = "#{@namespace}:#{extra_namespace}" if extra_namespace @backend = backend end def cache_key(type) - "#{type}:#{namespace}" + "#{namespace}:#{type}" end def expire(key) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 7a13169117c..8d796763b84 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1073,6 +1073,9 @@ msgstr "" msgid "CI / CD" msgstr "" +msgid "CI / CD Charts" +msgstr "" + msgid "CI / CD Settings" msgstr "" @@ -1169,6 +1172,9 @@ msgstr "" msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision." msgstr "" +msgid "Changes suppressed. Click to show." +msgstr "" + msgid "Charts" msgstr "" @@ -1962,6 +1968,9 @@ msgstr "" msgid "Contribution" msgstr "" +msgid "Contribution Charts" +msgstr "" + msgid "Contribution guide" msgstr "" @@ -2220,6 +2229,9 @@ msgstr "" msgid "Define a custom pattern with cron syntax" msgstr "" +msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here." +msgstr "" + msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes." msgstr "" @@ -2519,6 +2531,9 @@ msgstr "" msgid "Edit application" msgstr "" +msgid "Edit environment" +msgstr "" + msgid "Edit files in the editor and commit changes here" msgstr "" @@ -2597,6 +2612,9 @@ msgstr "" msgid "Environments" msgstr "" +msgid "Environments allow you to track deployments of your application %{link_to_read_more}." +msgstr "" + msgid "Environments|An error occurred while fetching the environments." msgstr "" @@ -2666,6 +2684,9 @@ msgstr "" msgid "Environments|Stop environment" msgstr "" +msgid "Environments|Stopping" +msgstr "" + msgid "Environments|Updated" msgstr "" @@ -2801,6 +2822,9 @@ msgstr "" msgid "Explore public groups" msgstr "" +msgid "External URL" +msgstr "" + msgid "Facebook" msgstr "" @@ -2849,6 +2873,18 @@ msgstr "" msgid "Fields on this page are now uneditable, you can configure" msgstr "" +msgid "File added" +msgstr "" + +msgid "File deleted" +msgstr "" + +msgid "File mode changed from %{a_mode} to %{b_mode}" +msgstr "" + +msgid "File moved" +msgstr "" + msgid "File templates" msgstr "" @@ -3890,6 +3926,9 @@ msgstr "" msgid "Metrics and profiling" msgstr "" +msgid "Metrics for environment" +msgstr "" + msgid "Metrics|Check out the CI/CD documentation on deploying to an environment" msgstr "" @@ -4034,6 +4073,9 @@ msgstr "" msgid "New Application" msgstr "" +msgid "New Environment" +msgstr "" + msgid "New Group" msgstr "" @@ -4066,6 +4108,9 @@ msgstr "" msgid "New directory" msgstr "" +msgid "New environment" +msgstr "" + msgid "New file" msgstr "" @@ -4156,6 +4201,9 @@ msgstr "" msgid "No other labels with such name or description" msgstr "" +msgid "No preview for this file type" +msgstr "" + msgid "No prioritised labels with such name or description" msgstr "" @@ -4443,6 +4491,9 @@ msgstr "" msgid "Personal Access Token" msgstr "" +msgid "Pick a name" +msgstr "" + msgid "Pipeline" msgstr "" @@ -5139,6 +5190,9 @@ msgstr "" msgid "Read more" msgstr "" +msgid "Read more about environments" +msgstr "" + msgid "Read more about project permissions <strong>%{link_to_help}</strong>" msgstr "" @@ -5165,6 +5219,9 @@ msgstr "" msgid "Register / Sign In" msgstr "" +msgid "Register U2F device" +msgstr "" + msgid "Register and see your runners for this group." msgstr "" @@ -5512,6 +5569,9 @@ msgstr "" msgid "Secret" msgstr "" +msgid "See metrics" +msgstr "" + msgid "Select" msgstr "" @@ -5605,6 +5665,9 @@ msgstr "" msgid "Set up a specific Runner automatically" msgstr "" +msgid "Set up new U2F device" +msgstr "" + msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically." msgstr "" @@ -5685,6 +5748,9 @@ msgstr "" msgid "Sign in / Register" msgstr "" +msgid "Sign in via 2FA code" +msgstr "" + msgid "Sign out" msgstr "" @@ -5970,9 +6036,6 @@ msgstr "" msgid "Subscribed" msgstr "" -msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})" -msgstr "" - msgid "Switch branch/tag" msgstr "" @@ -6086,6 +6149,9 @@ msgstr "" msgid "Templates" msgstr "" +msgid "Terminal for environment" +msgstr "" + msgid "Terms of Service Agreement and Privacy Policy" msgstr "" @@ -6236,6 +6302,9 @@ msgstr "" msgid "Third party offers" msgstr "" +msgid "This %{viewer} could not be displayed because %{reason}." +msgstr "" + msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area." msgstr "" @@ -6254,6 +6323,9 @@ msgstr "" msgid "This diff is collapsed." msgstr "" +msgid "This diff was suppressed by a .gitattributes entry." +msgstr "" + msgid "This directory" msgstr "" @@ -6609,6 +6681,9 @@ msgstr "" msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here." msgstr "" +msgid "To preserve performance only <strong>%{display_size} of ${real_size}</strong> files are displayed." +msgstr "" + msgid "To start serving your jobs you can add Runners to your group" msgstr "" @@ -6630,6 +6705,9 @@ msgstr "" msgid "Toggle Sidebar" msgstr "" +msgid "Toggle comments for this file" +msgstr "" + msgid "Toggle commit description" msgstr "" @@ -6690,6 +6768,12 @@ msgstr "" msgid "Try again" msgstr "" +msgid "Try again?" +msgstr "" + +msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now." +msgstr "" + msgid "Twitter" msgstr "" @@ -6846,9 +6930,6 @@ msgstr "" msgid "UserProfile|Personal projects" msgstr "" -msgid "UserProfile|Recent contributions" -msgstr "" - msgid "UserProfile|Report abuse" msgstr "" @@ -6894,6 +6975,9 @@ msgstr "" msgid "View app" msgstr "" +msgid "View deployment" +msgstr "" + msgid "View file @ " msgstr "" @@ -6957,6 +7041,9 @@ msgstr "" msgid "We don't have enough data to show this stage." msgstr "" +msgid "We heard back from your U2F device. You have been authenticated." +msgstr "" + msgid "We want to be sure it is you, please confirm you are not a robot." msgstr "" @@ -7191,6 +7278,9 @@ msgstr "" msgid "You don't have any authorized applications" msgstr "" +msgid "You don't have any deployments right now." +msgstr "" + msgid "You have no permissions" msgstr "" @@ -7206,6 +7296,9 @@ msgstr "" msgid "You need permission." msgstr "" +msgid "You need to register a two-factor authentication app before you can set up a U2F device." +msgstr "" + msgid "You will loose all changes you've made to this file. This action cannot be undone." msgstr "" @@ -7266,12 +7359,18 @@ msgstr "" msgid "Your Todos" msgstr "" +msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left." +msgstr "" + msgid "Your applications (%{size})" msgstr "" msgid "Your authorized applications" msgstr "" +msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)." +msgstr "" + msgid "Your changes can be committed to %{branch_name} because a merge request is open." msgstr "" @@ -7281,6 +7380,9 @@ msgstr "" msgid "Your comment will not be visible to the public." msgstr "" +msgid "Your device was successfully set up! Give it a name and register it with the GitLab server." +msgstr "" + msgid "Your groups" msgstr "" @@ -7322,6 +7424,9 @@ msgid_plural "days" msgstr[0] "" msgstr[1] "" +msgid "deleted" +msgstr "" + msgid "deploy token" msgstr "" @@ -7334,6 +7439,9 @@ msgstr "" msgid "enabled" msgstr "" +msgid "error code:" +msgstr "" + msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command." msgstr "" diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb index 16f0b311fa9..9be88ba4211 100644 --- a/qa/qa/resource/user.rb +++ b/qa/qa/resource/user.rb @@ -76,6 +76,17 @@ module QA } end + def self.fabricate_or_use(username, password) + if Runtime::Env.signup_disabled? + self.new.tap do |user| + user.username = username + user.password = password + end + else + self.fabricate! + end + end + private def fetch_id(username) diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb index c4500f9be90..1154eaca6a9 100644 --- a/qa/qa/runtime/env.rb +++ b/qa/qa/runtime/env.rb @@ -75,6 +75,22 @@ module QA ENV['GITLAB_FORKER_PASSWORD'] end + def gitlab_qa_username_1 + ENV['GITLAB_QA_USERNAME_1'] || 'gitlab-qa-user1' + end + + def gitlab_qa_password_1 + ENV['GITLAB_QA_PASSWORD_1'] + end + + def gitlab_qa_username_2 + ENV['GITLAB_QA_USERNAME_2'] || 'gitlab-qa-user2' + end + + def gitlab_qa_password_2 + ENV['GITLAB_QA_PASSWORD_2'] + end + def ldap_username ENV['GITLAB_LDAP_USERNAME'] end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb index bef89d5be24..4070a225260 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb @@ -7,7 +7,7 @@ module QA Runtime::Browser.visit(:gitlab, Page::Main::Login) Page::Main::Login.perform(&:sign_in_using_credentials) - user = Resource::User.fabricate! + user = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) project = Resource::Project.fabricate! do |resource| resource.name = 'add-member-project' diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb index a1f93bd3fbd..8cb9b57a049 100644 --- a/spec/features/calendar_spec.rb +++ b/spec/features/calendar_spec.rb @@ -64,7 +64,7 @@ describe 'Contributions Calendar', :js do end def selected_day_activities(visible: true) - find('.tab-pane#activity .user-calendar-activities', visible: visible).text + find('#js-overview .user-calendar-activities', visible: visible).text end before do @@ -74,16 +74,16 @@ describe 'Contributions Calendar', :js do describe 'calendar day selection' do before do visit user.username - page.find('.js-activity-tab a').click + page.find('.js-overview-tab a').click wait_for_requests end it 'displays calendar' do - expect(find('.tab-pane#activity')).to have_css('.js-contrib-calendar') + expect(find('#js-overview')).to have_css('.js-contrib-calendar') end describe 'select calendar day' do - let(:cells) { page.all('.tab-pane#activity .user-contrib-cell') } + let(:cells) { page.all('#js-overview .user-contrib-cell') } before do cells[0].click @@ -109,7 +109,7 @@ describe 'Contributions Calendar', :js do describe 'deselect calendar day' do before do cells[0].click - page.find('.js-activity-tab a').click + page.find('.js-overview-tab a').click wait_for_requests end @@ -124,7 +124,7 @@ describe 'Contributions Calendar', :js do shared_context 'visit user page' do before do visit user.username - page.find('.js-activity-tab a').click + page.find('.js-overview-tab a').click wait_for_requests end end @@ -133,12 +133,12 @@ describe 'Contributions Calendar', :js do include_context 'visit user page' it 'displays calendar activity square color for 1 contribution' do - expect(find('.tab-pane#activity')).to have_selector(get_cell_color_selector(contribution_count), count: 1) + expect(find('#js-overview')).to have_selector(get_cell_color_selector(contribution_count), count: 1) end it 'displays calendar activity square on the correct date' do today = Date.today.strftime(date_format) - expect(find('.tab-pane#activity')).to have_selector(get_cell_date_selector(contribution_count, today), count: 1) + expect(find('#js-overview')).to have_selector(get_cell_date_selector(contribution_count, today), count: 1) end end @@ -153,7 +153,7 @@ describe 'Contributions Calendar', :js do include_context 'visit user page' it 'displays calendar activity log' do - expect(find('.tab-pane#activity .content_list .event-target-title')).to have_content issue_title + expect(find('#js-overview .overview-content-list .event-target-title')).to have_content issue_title end end end @@ -185,17 +185,17 @@ describe 'Contributions Calendar', :js do include_context 'visit user page' it 'displays calendar activity squares for both days' do - expect(find('.tab-pane#activity')).to have_selector(get_cell_color_selector(1), count: 2) + expect(find('#js-overview')).to have_selector(get_cell_color_selector(1), count: 2) end it 'displays calendar activity square for yesterday' do yesterday = Date.yesterday.strftime(date_format) - expect(find('.tab-pane#activity')).to have_selector(get_cell_date_selector(1, yesterday), count: 1) + expect(find('#js-overview')).to have_selector(get_cell_date_selector(1, yesterday), count: 1) end it 'displays calendar activity square for today' do today = Date.today.strftime(date_format) - expect(find('.tab-pane#activity')).to have_selector(get_cell_date_selector(1, today), count: 1) + expect(find('#js-overview')).to have_selector(get_cell_date_selector(1, today), count: 1) end end end diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 605860b90cd..7c591dacce5 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -1,6 +1,10 @@ require 'rails_helper' describe 'GFM autocomplete', :js do + let(:issue_xss_title) { 'This will execute alert<img src=x onerror=alert(2)<img src=x onerror=alert(1)>' } + let(:user_xss_title) { 'eve <img src=x onerror=alert(2)<img src=x onerror=alert(1)>' } + + let(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') } let(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') } let(:project) { create(:project) } let(:label) { create(:label, project: project, title: 'special+') } @@ -9,6 +13,8 @@ describe 'GFM autocomplete', :js do before do project.add_maintainer(user) + project.add_maintainer(user_xss) + sign_in(user) visit project_issue_path(project, issue) @@ -35,9 +41,8 @@ describe 'GFM autocomplete', :js do expect(page).to have_selector('.atwho-container') end - it 'opens autocomplete menu when field starts with text with item escaping HTML characters' do - alert_title = 'This will execute alert<img src=x onerror=alert(2)<img src=x onerror=alert(1)>' - create(:issue, project: project, title: alert_title) + it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do + create(:issue, project: project, title: issue_xss_title) page.within '.timeline-content-form' do find('#note-body').native.send_keys('#') @@ -46,7 +51,19 @@ describe 'GFM autocomplete', :js do expect(page).to have_selector('.atwho-container') page.within '.atwho-container #at-view-issues' do - expect(page.all('li').first.text).to include(alert_title) + expect(page.all('li').first.text).to include(issue_xss_title) + end + end + + it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do + page.within '.timeline-content-form' do + find('#note-body').native.send_keys('@ev') + end + + expect(page).to have_selector('.atwho-container') + + page.within '.atwho-container #at-view-users' do + expect(find('li').text).to have_content(user_xss.username) end end @@ -107,7 +124,7 @@ describe 'GFM autocomplete', :js do wait_for_requests - expect(find('#at-view-64')).to have_selector('.cur:first-of-type') + expect(find('#at-view-users')).to have_selector('.cur:first-of-type') end it 'includes items for assignee dropdowns with non-ASCII characters in name' do @@ -120,7 +137,7 @@ describe 'GFM autocomplete', :js do wait_for_requests - expect(find('#at-view-64')).to have_content(user.name) + expect(find('#at-view-users')).to have_content(user.name) end it 'selects the first item for non-assignee dropdowns if a query is entered' do diff --git a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb index 297cd808460..32bc851f00f 100644 --- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb +++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb @@ -76,7 +76,7 @@ describe 'User creates branch and merge request on issue page', :js do visit project_issue_path(project, issue) - expect(page).to have_content('created branch 1-cherry-coloured-funk') + expect(page).to have_content("created merge request !1 to address this issue") expect(page).to have_content('mentioned in merge request !1') end @@ -106,7 +106,7 @@ describe 'User creates branch and merge request on issue page', :js do visit project_issue_path(project, issue) - expect(page).to have_content('created branch custom-branch-name') + expect(page).to have_content("created merge request !1 to address this issue") expect(page).to have_content('mentioned in merge request !1') end diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb index 5926e442f24..27cffdc5f8b 100644 --- a/spec/features/issues/user_uses_quick_actions_spec.rb +++ b/spec/features/issues/user_uses_quick_actions_spec.rb @@ -303,5 +303,63 @@ describe 'Issues > User uses quick actions', :js do end end end + + describe 'create a merge request starting from an issue' do + let(:project) { create(:project, :public, :repository) } + let(:issue) { create(:issue, project: project) } + + def expect_mr_quickaction(success) + expect(page).to have_content 'Commands applied' + + if success + expect(page).to have_content 'created merge request' + else + expect(page).not_to have_content 'created merge request' + end + end + + it "doesn't create a merge request when the branch name is invalid" do + add_note("/create_merge_request invalid branch name") + + wait_for_requests + + expect_mr_quickaction(false) + end + + it "doesn't create a merge request when a branch with that name already exists" do + add_note("/create_merge_request feature") + + wait_for_requests + + expect_mr_quickaction(false) + end + + it 'creates a new merge request using issue iid and title as branch name when the branch name is empty' do + add_note("/create_merge_request") + + wait_for_requests + + expect_mr_quickaction(true) + + created_mr = project.merge_requests.last + expect(created_mr.source_branch).to eq(issue.to_branch_name) + + visit project_merge_request_path(project, created_mr) + expect(page).to have_content %{WIP: Resolve "#{issue.title}"} + end + + it 'creates a merge request using the given branch name' do + branch_name = '1-feature' + add_note("/create_merge_request #{branch_name}") + + expect_mr_quickaction(true) + + created_mr = project.merge_requests.last + expect(created_mr.source_branch).to eq(branch_name) + + visit project_merge_request_path(project, created_mr) + expect(page).to have_content %{WIP: Resolve "#{issue.title}"} + end + end end end diff --git a/spec/features/users/overview_spec.rb b/spec/features/users/overview_spec.rb index b0ff53f9ccb..34ed771340f 100644 --- a/spec/features/users/overview_spec.rb +++ b/spec/features/users/overview_spec.rb @@ -54,15 +54,15 @@ describe 'Overview tab on a user profile', :js do end end - describe 'user has 10 activities' do + describe 'user has 11 activities' do before do - 10.times { push_code_contribution } + 11.times { push_code_contribution } end include_context 'visit overview tab' - it 'displays 5 entries in the list of activities' do - expect(find('#js-overview')).to have_selector('.event-item', count: 5) + it 'displays 10 entries in the list of activities' do + expect(find('#js-overview')).to have_selector('.event-item', count: 10) end it 'shows a link to the activity list' do diff --git a/spec/finders/group_descendants_finder_spec.rb b/spec/finders/group_descendants_finder_spec.rb index c64abdc3619..c28fd7cad11 100644 --- a/spec/finders/group_descendants_finder_spec.rb +++ b/spec/finders/group_descendants_finder_spec.rb @@ -74,6 +74,13 @@ describe GroupDescendantsFinder do end end + it 'sorts elements by latest created as default' do + project1 = create(:project, namespace: group, created_at: 1.hour.ago) + project2 = create(:project, namespace: group) + + expect(subject.execute).to eq([project2, project1]) + end + context 'sorting by name' do let!(:project1) { create(:project, namespace: group, name: 'a', path: 'project-a') } let!(:project2) { create(:project, namespace: group, name: 'z', path: 'project-z') } diff --git a/spec/finders/pending_todos_finder_spec.rb b/spec/finders/pending_todos_finder_spec.rb index 32fad5e225f..b41b1b46a93 100644 --- a/spec/finders/pending_todos_finder_spec.rb +++ b/spec/finders/pending_todos_finder_spec.rb @@ -46,7 +46,7 @@ describe PendingTodosFinder do create(:todo, :pending, user: user, target: note) - todos = described_class.new(user, target_type: issue.class).execute + todos = described_class.new(user, target_type: issue.class.name).execute expect(todos).to eq([todo]) end diff --git a/spec/fixtures/authentication/saml2_response.xml b/spec/fixtures/authentication/saml2_response.xml new file mode 100644 index 00000000000..67dea7209e9 --- /dev/null +++ b/spec/fixtures/authentication/saml2_response.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" Destination="https://example.hello.com/access/saml" ID="jVFQbyEpSfUwqhZtJtarIaGoshwuAQMDwLoiMhzJXsv" InResponseTo="cfeooghajnhofcmogakmlhpkohnmikicnfhdnjlc" IssueInstant="2011-06-21T13:54:38.661Z" Version="2.0"> + <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://idm.orademo.com</saml2:Issuer> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> + <ds:Reference URI="#jVFQbyEpSfUwqhZtJtarIaGoshwuAQMDwLoiMhzJXsv"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> + <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/> + </ds:Transform> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> + <ds:DigestValue>uHuSry39P16Yh7srS32xESmj4Lw=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>fdghdfggfd=</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>dfghjkl</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <saml2p:Status> + <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> + </saml2p:Status> + <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="emmCjammnYdAbMWDuMAJeZvQIMBayeeYqqwvQoDclKE" IssueInstant="2011-06-21T13:54:38.676Z" Version="2.0"> + <saml2:Issuer>https://idm.orademo.com</saml2:Issuer> + <saml2:Subject> + <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" NameQualifier="idp.example.org">someone@example.org</saml2:NameID> + <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> + <saml2:SubjectConfirmationData InResponseTo="cfeooghajnhofcmogakmlhpkohnmikicnfhdnjlc" NotOnOrAfter="2011-06-21T14:09:38.676Z" Recipient="https://example.hello.com/access/saml"/> + </saml2:SubjectConfirmation> + </saml2:Subject> + <saml2:Conditions NotBefore="2011-06-21T13:54:38.683Z" NotOnOrAfter="2011-06-21T14:09:38.683Z"> + <saml2:AudienceRestriction> + <saml2:Audience>hello.com</saml2:Audience> + </saml2:AudienceRestriction> + </saml2:Conditions> + <saml2:AuthnStatement AuthnInstant="2011-06-21T13:54:38.685Z" SessionIndex="perdkjfskdjfksdiertusfsdfsddeurtherukjdfgkdffg"> + <saml2:AuthnContext> + <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef> + </saml2:AuthnContext> + </saml2:AuthnStatement> + <saml2:AttributeStatement> + <saml2:Attribute Name="FirstName"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Someone</saml2:AttributeValue> + </saml2:Attribute> + <saml2:Attribute Name="LastName"> + <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Special</saml2:AttributeValue> + </saml2:Attribute> + </saml2:AttributeStatement> + </saml2:Assertion> +</saml2p:Response> diff --git a/spec/javascripts/lib/utils/text_markdown_spec.js b/spec/javascripts/lib/utils/text_markdown_spec.js index b9e805628f8..f71d27eb4e4 100644 --- a/spec/javascripts/lib/utils/text_markdown_spec.js +++ b/spec/javascripts/lib/utils/text_markdown_spec.js @@ -86,6 +86,29 @@ describe('init markdown', () => { expect(textArea.value).toEqual(`${initialValue}* `); }); + + it('places the cursor inside the tags', () => { + const start = 'lorem '; + const end = ' ipsum'; + const tag = '*'; + + textArea.value = `${start}${end}`; + textArea.setSelectionRange(start.length, start.length); + + insertMarkdownText({ + textArea, + text: textArea.value, + tag, + blockTag: null, + selected: '', + wrap: true, + }); + + expect(textArea.value).toEqual(`${start}**${end}`); + + // cursor placement should be between tags + expect(textArea.selectionStart).toBe(start.length + tag.length); + }); }); describe('with selection', () => { @@ -98,16 +121,22 @@ describe('init markdown', () => { }); it('applies the tag to the selected value', () => { + const selectedIndex = text.indexOf(selected); + const tag = '*'; + insertMarkdownText({ textArea, text: textArea.value, - tag: '*', + tag, blockTag: null, selected, wrap: true, }); expect(textArea.value).toEqual(text.replace(selected, `*${selected}*`)); + + // cursor placement should be after selection + 2 tag lengths + expect(textArea.selectionStart).toBe(selectedIndex + selected.length + 2 * tag.length); }); it('replaces the placeholder in the tag', () => { diff --git a/spec/javascripts/vue_shared/components/expand_button_spec.js b/spec/javascripts/vue_shared/components/expand_button_spec.js index 98fee9a74a5..2af4abc299a 100644 --- a/spec/javascripts/vue_shared/components/expand_button_spec.js +++ b/spec/javascripts/vue_shared/components/expand_button_spec.js @@ -18,7 +18,7 @@ describe('expand button', () => { vm.$destroy(); }); - it('renders a collpased button', () => { + it('renders a collapsed button', () => { expect(vm.$children[0].iconTestClass).toEqual('ic-ellipsis_h'); }); diff --git a/spec/lib/gitlab/auth/saml/auth_hash_spec.rb b/spec/lib/gitlab/auth/saml/auth_hash_spec.rb index 76f49e778fb..3620e1afe25 100644 --- a/spec/lib/gitlab/auth/saml/auth_hash_spec.rb +++ b/spec/lib/gitlab/auth/saml/auth_hash_spec.rb @@ -82,6 +82,17 @@ describe Gitlab::Auth::Saml::AuthHash do end end + context 'with SAML 2.0 response_object' do + before do + auth_hash_data[:extra][:response_object] = { document: + saml_xml(File.read('spec/fixtures/authentication/saml2_response.xml')) } + end + + it 'can extract authn_context' do + expect(saml_auth_hash.authn_context).to eq 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + end + end + context 'without response_object' do it 'returns an empty string' do expect(saml_auth_hash.authn_context).to be_nil diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index 3f2281f213f..58949f76bd6 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -2556,7 +2556,7 @@ "merge_request_diff_id": 27, "relative_order": 0, "sha": "bb5206fee213d983da88c47f9cf4cc6caf9c66dc", - "message": "Feature conflcit added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n", + "message": "Feature conflict added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n", "authored_date": "2014-08-06T08:35:52.000+02:00", "author_name": "Dmitriy Zaporozhets", "author_email": "dmitriy.zaporozhets@gmail.com", @@ -3605,7 +3605,7 @@ "merge_request_diff_id": 14, "relative_order": 8, "sha": "08f22f255f082689c0d7d39d19205085311542bc", - "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n", + "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n", "authored_date": "2015-11-13T06:00:16.000+01:00", "author_name": "윤민식", "author_email": "minsik.yoon@samsung.com", @@ -4290,7 +4290,7 @@ "merge_request_diff_id": 13, "relative_order": 8, "sha": "08f22f255f082689c0d7d39d19205085311542bc", - "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n", + "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n", "authored_date": "2015-11-13T06:00:16.000+01:00", "author_name": "윤민식", "author_email": "minsik.yoon@samsung.com", @@ -4799,7 +4799,7 @@ "merge_request_diff_id": 12, "relative_order": 8, "sha": "08f22f255f082689c0d7d39d19205085311542bc", - "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n", + "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n", "authored_date": "2015-11-13T06:00:16.000+01:00", "author_name": "윤민식", "author_email": "minsik.yoon@samsung.com", @@ -5507,7 +5507,7 @@ "merge_request_diff_id": 10, "relative_order": 8, "sha": "08f22f255f082689c0d7d39d19205085311542bc", - "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n", + "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n", "authored_date": "2015-11-13T06:00:16.000+01:00", "author_name": "윤민식", "author_email": "minsik.yoon@samsung.com", diff --git a/spec/lib/gitlab/import_export/project.light.json b/spec/lib/gitlab/import_export/project.light.json index ba2248073f5..2971ca0f0f8 100644 --- a/spec/lib/gitlab/import_export/project.light.json +++ b/spec/lib/gitlab/import_export/project.light.json @@ -101,6 +101,28 @@ ] } ], + "services": [ + { + "id": 100, + "title": "JetBrains TeamCity CI", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.315Z", + "updated_at": "2016-06-14T15:01:51.315Z", + "active": false, + "properties": {}, + "template": true, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "job_events": true, + "type": "TeamcityService", + "category": "ci", + "default": false, + "wiki_page_events": true + } + ], "snippets": [], "hooks": [] } diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 365bfae0d88..7171e12a849 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -297,7 +297,8 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do issues: 1, labels: 1, milestones: 1, - first_issue_labels: 1 + first_issue_labels: 1, + services: 1 context 'project.json file access check' do it 'does not read a symlink' do @@ -382,6 +383,12 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do project_tree_restorer.instance_variable_set(:@path, "spec/lib/gitlab/import_export/project.light.json") end + it 'does not import any templated services' do + restored_project_json + + expect(project.services.where(template: true).count).to eq(0) + end + it 'imports labels' do create(:group_label, name: 'Another label', group: project.group) diff --git a/spec/lib/gitlab/repository_cache_spec.rb b/spec/lib/gitlab/repository_cache_spec.rb index 741ee12633f..1b9a8b4ab0d 100644 --- a/spec/lib/gitlab/repository_cache_spec.rb +++ b/spec/lib/gitlab/repository_cache_spec.rb @@ -4,14 +4,14 @@ describe Gitlab::RepositoryCache do let(:backend) { double('backend').as_null_object } let(:project) { create(:project) } let(:repository) { project.repository } - let(:namespace) { "#{repository.full_path}:#{project.id}" } + let(:namespace) { "project:#{project.id}" } let(:cache) { described_class.new(repository, backend: backend) } describe '#cache_key' do subject { cache.cache_key(:foo) } it 'includes the namespace' do - expect(subject).to eq "foo:#{namespace}" + expect(subject).to eq "#{namespace}:foo" end context 'with a given namespace' do @@ -22,7 +22,7 @@ describe Gitlab::RepositoryCache do end it 'includes the full namespace' do - expect(subject).to eq "foo:#{namespace}:#{extra_namespace}" + expect(subject).to eq "#{namespace}:#{extra_namespace}:foo" end end end @@ -30,21 +30,21 @@ describe Gitlab::RepositoryCache do describe '#expire' do it 'expires the given key from the cache' do cache.expire(:foo) - expect(backend).to have_received(:delete).with("foo:#{namespace}") + expect(backend).to have_received(:delete).with("#{namespace}:foo") end end describe '#fetch' do it 'fetches the given key from the cache' do cache.fetch(:bar) - expect(backend).to have_received(:fetch).with("bar:#{namespace}") + expect(backend).to have_received(:fetch).with("#{namespace}:bar") end it 'accepts a block' do p = -> {} cache.fetch(:baz, &p) - expect(backend).to have_received(:fetch).with("baz:#{namespace}", &p) + expect(backend).to have_received(:fetch).with("#{namespace}:baz", &p) end end @@ -67,7 +67,7 @@ describe Gitlab::RepositoryCache do end it 'caches the value' do - expect(backend).to receive(:write).with("#{key}:#{namespace}", true) + expect(backend).to receive(:write).with("#{namespace}:#{key}", true) cache.fetch_without_caching_false(key) { true } end @@ -83,7 +83,7 @@ describe Gitlab::RepositoryCache do end it 'does not cache the value' do - expect(backend).not_to receive(:write).with("#{key}:#{namespace}", true) + expect(backend).not_to receive(:write).with("#{namespace}:#{key}", true) cache.fetch_without_caching_false(key, &p) end @@ -92,7 +92,7 @@ describe Gitlab::RepositoryCache do context 'when the cached value is truthy' do before do - backend.write("#{key}:#{namespace}", true) + backend.write("#{namespace}:#{key}", true) end it 'returns the cached value' do @@ -116,7 +116,7 @@ describe Gitlab::RepositoryCache do context 'when the cached value is falsey' do before do - backend.write("#{key}:#{namespace}", false) + backend.write("#{namespace}:#{key}", false) end it 'returns the result of the block' do @@ -126,7 +126,7 @@ describe Gitlab::RepositoryCache do end it 'writes the truthy value to the cache' do - expect(backend).to receive(:write).with("#{key}:#{namespace}", 'block result') + expect(backend).to receive(:write).with("#{namespace}:#{key}", 'block result') cache.fetch_without_caching_false(key) { 'block result' } end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 799a60ac62f..56edb0fd6da 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -2403,4 +2403,22 @@ describe Repository do repository.merge_base('master', 'fix') end end + + describe '#cache' do + subject(:cache) { repository.send(:cache) } + + it 'returns a RepositoryCache' do + expect(subject).to be_kind_of Gitlab::RepositoryCache + end + + it 'when is_wiki it includes wiki as part of key' do + allow(repository).to receive(:is_wiki) { true } + + expect(subject.namespace).to include('wiki') + end + + it 'when is_wiki is false extra_namespace is nil' do + expect(subject.namespace).not_to include('wiki') + end + end end diff --git a/spec/models/todo_spec.rb b/spec/models/todo_spec.rb index 2c01578aaca..82ff2a002e0 100644 --- a/spec/models/todo_spec.rb +++ b/spec/models/todo_spec.rb @@ -226,7 +226,7 @@ describe Todo do create(:todo, target: create(:merge_request)) - expect(described_class.for_type(Issue)).to eq([todo]) + expect(described_class.for_type(Issue.name)).to eq([todo]) end end diff --git a/spec/services/merge_requests/create_from_issue_service_spec.rb b/spec/services/merge_requests/create_from_issue_service_spec.rb index b1882df732d..393299cce00 100644 --- a/spec/services/merge_requests/create_from_issue_service_spec.rb +++ b/spec/services/merge_requests/create_from_issue_service_spec.rb @@ -61,7 +61,15 @@ describe MergeRequests::CreateFromIssueService do expect(project.repository.branch_exists?(custom_source_branch)).to be_truthy end - it 'creates a system note' do + it 'creates the new_merge_request system note' do + expect(SystemNoteService).to receive(:new_merge_request).with(issue, project, user, instance_of(MergeRequest)) + + service.execute + end + + it 'creates the new_issue_branch system note when the branch could be created but the merge_request cannot be created' do + project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED) + expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, user, issue.to_branch_name) service.execute diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index 5a7cafcb60f..938764f40b0 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -1222,6 +1222,37 @@ describe QuickActions::InterpretService do expect(commands).to be_empty expect(text).to eq("#{described_class::SHRUG}\n/close") end + + context '/create_merge_request command' do + let(:branch_name) { '1-feature' } + let(:content) { "/create_merge_request #{branch_name}" } + let(:issuable) { issue } + + context 'if issuable is not an Issue' do + let(:issuable) { merge_request } + + it_behaves_like 'empty command' + end + + context "when logged user cannot create_merge_requests in the project" do + let(:project) { create(:project, :archived) } + + it_behaves_like 'empty command' + end + + context 'when logged user cannot push code to the project' do + let(:project) { create(:project, :private) } + let(:service) { described_class.new(project, create(:user)) } + + it_behaves_like 'empty command' + end + + it 'populates create_merge_request with branch_name and issue iid' do + _, updates = service.execute(content, issuable) + + expect(updates).to eq(create_merge_request: { branch_name: branch_name, issue_iid: issuable.iid }) + end + end end describe '#explain' do @@ -1473,5 +1504,27 @@ describe QuickActions::InterpretService do end end end + + describe 'create a merge request' do + context 'with no branch name' do + let(:content) { '/create_merge_request' } + + it 'uses the default branch name' do + _, explanations = service.explain(content, issue) + + expect(explanations).to eq(['Creates a branch and a merge request to resolve this issue']) + end + end + + context 'with a branch name' do + let(:content) { '/create_merge_request foo' } + + it 'uses the given branch name' do + _, explanations = service.explain(content, issue) + + expect(explanations).to eq(["Creates branch 'foo' and a merge request to resolve this issue"]) + end + end + end end end diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index a18126ee339..0fbfcb34e50 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -432,6 +432,20 @@ describe SystemNoteService do end end + describe '.new_merge_request' do + subject { described_class.new_merge_request(noteable, project, author, merge_request) } + + let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } + + it_behaves_like 'a system note' do + let(:action) { 'merge' } + end + + it 'sets the new merge request note text' do + expect(subject.note).to eq("created merge request #{merge_request.to_reference} to address this issue") + end + end + describe '.cross_reference' do subject { described_class.cross_reference(noteable, mentioner, author) } diff --git a/spec/support/helpers/devise_helpers.rb b/spec/support/helpers/devise_helpers.rb index 66874e10f38..d32bc2424c0 100644 --- a/spec/support/helpers/devise_helpers.rb +++ b/spec/support/helpers/devise_helpers.rb @@ -8,8 +8,15 @@ module DeviseHelpers end def env_from_context(context) + # When we modify env_config, that is on the global + # Rails.application, and we need to stub it and allow it to be + # modified in-place, without polluting later tests. if context.respond_to?(:env_config) - context.env_config + context.env_config.deep_dup.tap do |env| + allow(context).to receive(:env_config).and_return(env) + end + # When we modify env, then the context is a request, or something + # else that only lives for a single spec. elsif context.respond_to?(:env) context.env end |