diff options
102 files changed, 808 insertions, 242 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 383300a895f..5c5f3f589b9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -427,15 +427,7 @@ setup-test-env: - vendor/gitaly-ruby # GitLab Review apps -.review-base: &review-base - <<: *dedicated-no-docs-no-db-pull-cache-job - image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base - stage: test - cache: {} - dependencies: [] - environment: &review-environment - name: review/${CI_COMMIT_REF_NAME} - url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN} +.review-only: &review-only only: refs: - branches@gitlab-org/gitlab-ce @@ -445,6 +437,17 @@ setup-test-env: refs: - master - /(^docs[\/-].*|.*-docs$)/ + +.review-base: &review-base + <<: *dedicated-no-docs-no-db-pull-cache-job + <<: *review-only + image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base + stage: test + cache: {} + dependencies: [] + environment: &review-environment + name: review/${CI_COMMIT_REF_NAME} + url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN} before_script: [] .review-docker: &review-docker @@ -949,9 +952,11 @@ no_ee_check: # GitLab Review apps review-build-cng: <<: *single-script-job + <<: *review-only variables: <<: *single-script-job-variables SCRIPT_NAME: trigger-build + API_TOKEN: "${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}" script: - gem install gitlab --no-document - apk add --update openssl curl jq diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js index ada93b570b0..09afacc24df 100644 --- a/app/assets/javascripts/diffs/store/utils.js +++ b/app/assets/javascripts/diffs/store/utils.js @@ -181,8 +181,6 @@ export function addContextLines(options) { export function trimFirstCharOfLineContent(line = {}) { // eslint-disable-next-line no-param-reassign delete line.text; - // eslint-disable-next-line no-param-reassign - line.discussions = []; const parsedLine = Object.assign({}, line); @@ -222,10 +220,12 @@ export function prepareDiffData(diffData) { line.line_code = getLineCode(line, u); if (line.left) { line.left = trimFirstCharOfLineContent(line.left); + line.left.discussions = []; line.left.hasForm = false; } if (line.right) { line.right = trimFirstCharOfLineContent(line.right); + line.right.discussions = []; line.right.hasForm = false; } } @@ -235,7 +235,11 @@ export function prepareDiffData(diffData) { const linesLength = file.highlighted_diff_lines.length; for (let u = 0; u < linesLength; u += 1) { const line = file.highlighted_diff_lines[u]; - Object.assign(line, { ...trimFirstCharOfLineContent(line), hasForm: false }); + Object.assign(line, { + ...trimFirstCharOfLineContent(line), + discussions: [], + hasForm: false, + }); } showingLines += file.parallel_diff_lines.length; } diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue index af821df0fd2..376d4114efd 100644 --- a/app/assets/javascripts/notes/components/diff_with_note.vue +++ b/app/assets/javascripts/notes/components/diff_with_note.vue @@ -6,8 +6,6 @@ import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue'; import { GlSkeletonLoading } from '@gitlab/ui'; import { getDiffMode } from '~/diffs/store/utils'; -const FIRST_CHAR_REGEX = /^(\+|-| )/; - export default { components: { DiffFileHeader, @@ -54,9 +52,6 @@ export default { this.error = true; }); }, - trimChar(line) { - return line.replace(FIRST_CHAR_REGEX, ''); - }, }, userColorSchemeClass: window.gon.user_color_scheme, }; @@ -85,7 +80,7 @@ export default { > <td class="diff-line-num old_line">{{ line.old_line }}</td> <td class="diff-line-num new_line">{{ line.new_line }}</td> - <td :class="line.type" class="line_content" v-html="trimChar(line.rich_text)"></td> + <td :class="line.type" class="line_content" v-html="line.rich_text"></td> </tr> </template> <tr v-if="!hasTruncatedDiffLines" class="line_holder line-holder-placeholder"> diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index 4480ec74182..1a116161e3c 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -206,11 +206,15 @@ export default { return sprintf(text, { commitId, linkStart, linkEnd }, false); }, diffLine() { + if (this.line) { + return this.line; + } + if (this.discussion.diff_discussion && this.discussion.truncated_diff_lines) { return this.discussion.truncated_diff_lines.slice(-1)[0]; } - return this.line; + return null; }, }, watch: { diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js index 8992454be2e..33d39ad2ec9 100644 --- a/app/assets/javascripts/notes/stores/mutations.js +++ b/app/assets/javascripts/notes/stores/mutations.js @@ -105,7 +105,10 @@ export default { if (discussion.diff_file) { diffData.file_hash = discussion.diff_file.file_hash; - diffData.truncated_diff_lines = discussion.truncated_diff_lines || []; + + diffData.truncated_diff_lines = utils.prepareDiffLines( + discussion.truncated_diff_lines || [], + ); } // To support legacy notes, should be very rare case. @@ -243,7 +246,7 @@ export default { [types.SET_DISCUSSION_DIFF_LINES](state, { discussionId, diffLines }) { const discussion = utils.findNoteObjectById(state.discussions, discussionId); - discussion.truncated_diff_lines = diffLines; + discussion.truncated_diff_lines = utils.prepareDiffLines(diffLines); }, [types.DISABLE_COMMENTS](state, value) { diff --git a/app/assets/javascripts/notes/stores/utils.js b/app/assets/javascripts/notes/stores/utils.js index dd57539e4d8..4b0feb0f94d 100644 --- a/app/assets/javascripts/notes/stores/utils.js +++ b/app/assets/javascripts/notes/stores/utils.js @@ -1,4 +1,5 @@ import AjaxCache from '~/lib/utils/ajax_cache'; +import { trimFirstCharOfLineContent } from '~/diffs/store/utils'; const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm; @@ -28,3 +29,6 @@ export const getQuickActionText = note => { export const hasQuickActions = note => REGEX_QUICK_ACTIONS.test(note); export const stripQuickActions = note => note.replace(REGEX_QUICK_ACTIONS, '').trim(); + +export const prepareDiffLines = diffLines => + diffLines.map(line => ({ ...trimFirstCharOfLineContent(line) })); diff --git a/app/assets/javascripts/pages/groups/clusters/update/index.js b/app/assets/javascripts/pages/groups/clusters/edit/index.js index 8001d2dd1da..8001d2dd1da 100644 --- a/app/assets/javascripts/pages/groups/clusters/update/index.js +++ b/app/assets/javascripts/pages/groups/clusters/edit/index.js diff --git a/app/assets/javascripts/pages/projects/clusters/update/index.js b/app/assets/javascripts/pages/projects/clusters/edit/index.js index 8001d2dd1da..8001d2dd1da 100644 --- a/app/assets/javascripts/pages/projects/clusters/update/index.js +++ b/app/assets/javascripts/pages/projects/clusters/edit/index.js diff --git a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue index faea64c9841..c5cfa92f3c8 100644 --- a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue +++ b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue @@ -104,9 +104,7 @@ export default { </div> <div class="title hide-collapsed"> - {{ - sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName }) - }} + {{ sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName }) }} <button v-if="isEditable" class="float-right lock-edit" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue index dd940548e30..780ecdcdac4 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue @@ -7,7 +7,7 @@ export default { tooltip, }, created() { - this.removesBranchText = __('<strong>Removes</strong> source branch'); + this.removesBranchText = __('<strong>Deletes</strong> source branch'); this.tooltipTitle = __('A user with write access to the source branch selected this option'); }, }; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue index 02c76db4a50..1b3af2fccf2 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue @@ -106,11 +106,11 @@ export default { <a :href="mr.targetBranchPath" class="label-branch"> {{ mr.targetBranch }} </a> </p> <p v-if="mr.shouldRemoveSourceBranch"> - {{ s__('mrWidget|The source branch will be removed') }} + {{ s__('mrWidget|The source branch will be deleted') }} </p> <p v-else class="d-flex align-items-start"> <span class="append-right-10"> - {{ s__('mrWidget|The source branch will not be removed') }} + {{ s__('mrWidget|The source branch will not be deleted') }} </span> <a v-if="canRemoveSourceBranch" @@ -121,7 +121,7 @@ export default { @click.prevent="removeSourceBranch" > <i v-if="isRemovingSourceBranch" class="fa fa-spinner fa-spin" aria-hidden="true"> </i> - {{ s__('mrWidget|Remove source branch') }} + {{ s__('mrWidget|Delete source branch') }} </a> </p> </section> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue index fe83fe58b67..b9562fbc260 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue @@ -84,7 +84,7 @@ export default { .removeSourceBranch() .then(res => res.data) .then(data => { - if (data.message === 'Branch was removed') { + if (data.message === 'Branch was deleted') { eventHub.$emit('MRWidgetUpdateRequested', () => { this.isMakingRequest = false; }); @@ -174,22 +174,22 @@ export default { </template> </p> <p v-if="mr.sourceBranchRemoved"> - {{ s__('mrWidget|The source branch has been removed') }} + {{ s__('mrWidget|The source branch has been deleted') }} </p> <p v-if="shouldShowRemoveSourceBranch" class="space-children"> - <span>{{ s__('mrWidget|You can remove source branch now') }}</span> + <span>{{ s__('mrWidget|You can delete the source branch now') }}</span> <button :disabled="isMakingRequest" type="button" class="btn btn-sm btn-default js-remove-branch-button" @click="removeSourceBranch" > - {{ s__('mrWidget|Remove Source Branch') }} + {{ s__('mrWidget|Delete source branch') }} </button> </p> <p v-if="shouldShowSourceBranchRemoving"> <gl-loading-icon :inline="true" /> - <span> {{ s__('mrWidget|The source branch is being removed') }} </span> + <span> {{ s__('mrWidget|The source branch is being deleted') }} </span> </p> </section> </div> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue index 0cafa73362e..b8f29649eb5 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue @@ -223,7 +223,7 @@ export default { } }) .catch(() => { - new Flash('Something went wrong while removing the source branch. Please try again.'); // eslint-disable-line + new Flash('Something went wrong while deleting the source branch. Please try again.'); // eslint-disable-line }); }, }, @@ -297,7 +297,7 @@ export default { class="js-remove-source-branch-checkbox" type="checkbox" /> - Remove source branch + Delete source branch </label> <!-- Placeholder for EE extension of this component --> diff --git a/app/models/appearance.rb b/app/models/appearance.rb index e114c435b67..ff1ecfda684 100644 --- a/app/models/appearance.rb +++ b/app/models/appearance.rb @@ -44,7 +44,11 @@ class Appearance < ActiveRecord::Base private def logo_system_path(logo, mount_type) - return unless logo&.upload + # Legacy attachments may not have have an associated Upload record, + # so fallback to the AttachmentUploader#url if this is the + # case. AttachmentUploader#path doesn't work because for a local + # file, this is an absolute path to the file. + return logo&.url unless logo&.upload # If we're using a CDN, we need to use the full URL asset_host = ActionController::Base.asset_host diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 6050955fbd8..a2c48973fa5 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -49,8 +49,9 @@ module Clusters validates :name, cluster_name: true validates :cluster_type, presence: true - validate :restrict_modification, on: :update + validates :domain, allow_nil: true, hostname: { allow_numeric_hostname: true, require_valid_tld: true } + validate :restrict_modification, on: :update validate :no_groups, unless: :group_type? validate :no_projects, unless: :project_type? diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb index 44252f7b0a6..8322a3d74f4 100644 --- a/app/services/delete_branch_service.rb +++ b/app/services/delete_branch_service.rb @@ -14,7 +14,7 @@ class DeleteBranchService < BaseService end if repository.rm_branch(current_user, branch_name) - success('Branch was removed') + success('Branch was deleted') else error('Failed to remove branch') end diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml index 69167edb1df..1e3bb8f1224 100644 --- a/app/views/layouts/nav/sidebar/_profile.html.haml +++ b/app/views/layouts/nav/sidebar/_profile.html.haml @@ -3,7 +3,7 @@ .context-header = link_to profile_path, title: _('Profile Settings') do .avatar-container.s40.settings-avatar - = sprite_icon('user', size: 24) + = image_tag avatar_icon_for_user(current_user, 40), class: "avatar s40 avatar-tile", alt: current_user.name .sidebar-context-title User Settings %ul.sidebar-top-level-items = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do diff --git a/app/views/projects/buttons/_notifications.html.haml b/app/views/projects/buttons/_notifications.html.haml index 745983ace7e..a8b728527c8 100644 --- a/app/views/projects/buttons/_notifications.html.haml +++ b/app/views/projects/buttons/_notifications.html.haml @@ -12,8 +12,8 @@ %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } } = sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon") %span.js-notification-loading.fa.hidden - %button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } } - = sprite_icon("arrow-down", css_class: "icon") + %button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" }, class: "#{btn_class}" } + = sprite_icon("arrow-down", css_class: "icon mr-0") .sr-only Toggle dropdown - else %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting - #{notification_title(notification_setting.level)}", class: "#{btn_class}", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } } diff --git a/app/views/projects/protected_branches/shared/_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_protected_branch.html.haml index 81b07af22ad..bb7998f739d 100644 --- a/app/views/projects/protected_branches/shared/_protected_branch.html.haml +++ b/app/views/projects/protected_branches/shared/_protected_branch.html.haml @@ -15,7 +15,7 @@ = link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit-sha') = time_ago_with_tooltip(commit.committed_date) - else - (branch was removed from repository) + (branch was deleted from repository) = yield diff --git a/app/views/sent_notifications/unsubscribe.html.haml b/app/views/sent_notifications/unsubscribe.html.haml index 7d3e243495f..ca392e1adfc 100644 --- a/app/views/sent_notifications/unsubscribe.html.haml +++ b/app/views/sent_notifications/unsubscribe.html.haml @@ -1,17 +1,16 @@ - noteable = @sent_notification.noteable - noteable_type = @sent_notification.noteable_type.titleize.downcase - noteable_text = %(#{noteable.title} (#{noteable.to_reference})) -- page_title "Unsubscribe", noteable_text, noteable_type.pluralize, @sent_notification.project.full_name +- page_title _("Unsubscribe"), noteable_text, noteable_type.pluralize, @sent_notification.project.full_name %h3.page-title - Unsubscribe from #{noteable_type} + = _("Unsubscribe from %{type}") % { type: noteable_type } %p - = succeed '?' do - Are you sure you want to unsubscribe from the #{noteable_type}: - = link_to noteable_text, url_for([@sent_notification.project.namespace.becomes(Namespace), @sent_notification.project, noteable]) + - link_to_noteable_text = link_to(noteable_text, url_for([@sent_notification.project.namespace.becomes(Namespace), @sent_notification.project, noteable])) + = _("Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?").html_safe % { type: noteable_type, link_to_noteable_text: link_to_noteable_text } %p - = link_to 'Unsubscribe', unsubscribe_sent_notification_path(@sent_notification, force: true), + = link_to _('Unsubscribe'), unsubscribe_sent_notification_path(@sent_notification, force: true), class: 'btn btn-primary append-right-10' - = link_to 'Cancel', new_user_session_path, class: 'btn append-right-10' + = link_to _('Cancel'), new_user_session_path, class: 'btn append-right-10' diff --git a/app/views/shared/issuable/form/_merge_params.html.haml b/app/views/shared/issuable/form/_merge_params.html.haml index ca3141b2cc3..f0c4acdd07f 100644 --- a/app/views/shared/issuable/form/_merge_params.html.haml +++ b/app/views/shared/issuable/form/_merge_params.html.haml @@ -10,7 +10,7 @@ = hidden_field_tag 'merge_request[force_remove_source_branch]', '0', id: nil = check_box_tag 'merge_request[force_remove_source_branch]', '1', issuable.force_remove_source_branch?, class: 'form-check-input' = label_tag 'merge_request[force_remove_source_branch]', class: 'form-check-label' do - Remove source branch when merge request is accepted. + Delete source branch when merge request is accepted. .form-group.row .col-sm-10.offset-sm-2 diff --git a/changelogs/unreleased/25569-changing-wording-to-delete-when-referring-to-removing-a-branch.yml b/changelogs/unreleased/25569-changing-wording-to-delete-when-referring-to-removing-a-branch.yml new file mode 100644 index 00000000000..02a667073ca --- /dev/null +++ b/changelogs/unreleased/25569-changing-wording-to-delete-when-referring-to-removing-a-branch.yml @@ -0,0 +1,5 @@ +--- +title: Use delete instead of remove when referring to `git branch -D` +merge_request: !23966 +author: +type: changed diff --git a/changelogs/unreleased/52674-api-v4-projects-project_id-jobs-endpoint-hits-statement-timeout.yml b/changelogs/unreleased/52674-api-v4-projects-project_id-jobs-endpoint-hits-statement-timeout.yml new file mode 100644 index 00000000000..f79078c1fd9 --- /dev/null +++ b/changelogs/unreleased/52674-api-v4-projects-project_id-jobs-endpoint-hits-statement-timeout.yml @@ -0,0 +1,5 @@ +--- +title: "[API] Omit `X-Total` and `X-Total-Pages` headers when items count is more than 10,000" +merge_request: 23931 +author: +type: performance diff --git a/changelogs/unreleased/56417-update-helm-to-2-12-2.yml b/changelogs/unreleased/56417-update-helm-to-2-12-2.yml new file mode 100644 index 00000000000..f01915c532f --- /dev/null +++ b/changelogs/unreleased/56417-update-helm-to-2-12-2.yml @@ -0,0 +1,5 @@ +--- +title: Update Helm to 2.12.2 to address Helm client vulnerability +merge_request: 24418 +author: Takuya Noguchi +type: security diff --git a/changelogs/unreleased/dm-trim-discussion-truncated-line-first-chars.yml b/changelogs/unreleased/dm-trim-discussion-truncated-line-first-chars.yml new file mode 100644 index 00000000000..1e1fa8295c3 --- /dev/null +++ b/changelogs/unreleased/dm-trim-discussion-truncated-line-first-chars.yml @@ -0,0 +1,5 @@ +--- +title: Fix bug that caused Suggestion Markdown toolbar button to insert snippet with leading +/-/<space> +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/fix-55956-oversized-dropdown-button-custom-notifications.yml b/changelogs/unreleased/fix-55956-oversized-dropdown-button-custom-notifications.yml new file mode 100644 index 00000000000..e33699a2112 --- /dev/null +++ b/changelogs/unreleased/fix-55956-oversized-dropdown-button-custom-notifications.yml @@ -0,0 +1,5 @@ +--- +title: Fixed oversized custom project notification selector dropdown +merge_request: 24557 +author: +type: fixed diff --git a/changelogs/unreleased/gt-externalize-app-views-sent_notifications.yml b/changelogs/unreleased/gt-externalize-app-views-sent_notifications.yml new file mode 100644 index 00000000000..e77b5376fa8 --- /dev/null +++ b/changelogs/unreleased/gt-externalize-app-views-sent_notifications.yml @@ -0,0 +1,5 @@ +--- +title: Externalize strings from `/app/views/sent_notifications` +merge_request: 24576 +author: George Tsiolis +type: other diff --git a/changelogs/unreleased/mg-fix-bad-cluster-update-entrypoint.yml b/changelogs/unreleased/mg-fix-bad-cluster-update-entrypoint.yml new file mode 100644 index 00000000000..932850cc825 --- /dev/null +++ b/changelogs/unreleased/mg-fix-bad-cluster-update-entrypoint.yml @@ -0,0 +1,5 @@ +--- +title: Fix cluster page non-interactive on form validation error +merge_request: 24583 +author: +type: fixed diff --git a/changelogs/unreleased/sh-fix-issue-9357.yml b/changelogs/unreleased/sh-fix-issue-9357.yml new file mode 100644 index 00000000000..756cd6047b8 --- /dev/null +++ b/changelogs/unreleased/sh-fix-issue-9357.yml @@ -0,0 +1,5 @@ +--- +title: Fix 500 errors with legacy appearance logos +merge_request: 24615 +author: +type: fixed diff --git a/changelogs/unreleased/yoginth-avatar-on-settings-sidebar.yml b/changelogs/unreleased/yoginth-avatar-on-settings-sidebar.yml new file mode 100644 index 00000000000..0ec76f9ce02 --- /dev/null +++ b/changelogs/unreleased/yoginth-avatar-on-settings-sidebar.yml @@ -0,0 +1,5 @@ +--- +title: Added Avatar in the settings sidebar +merge_request: 24515 +author: Yoginth +type: changed diff --git a/config/initializers/kaminari_active_record_relation_methods_with_limit.rb b/config/initializers/kaminari_active_record_relation_methods_with_limit.rb new file mode 100644 index 00000000000..cc20b83b234 --- /dev/null +++ b/config/initializers/kaminari_active_record_relation_methods_with_limit.rb @@ -0,0 +1,41 @@ +module Kaminari + # Active Record specific page scope methods implementations + module ActiveRecordRelationMethodsWithLimit + MAX_COUNT_LIMIT = 10_000 + + # This is a modified version of + # https://github.com/kaminari/kaminari/blob/c5186f5d9b7f23299d115408e62047447fd3189d/kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#L17-L41 + # that limit the COUNT query to 10,000 to avoid query timeouts. + # rubocop: disable Gitlab/ModuleWithInstanceVariables + def total_count_with_limit(column_name = :all, _options = nil) #:nodoc: + return @total_count if defined?(@total_count) && @total_count + + # There are some cases that total count can be deduced from loaded records + if loaded? + # Total count has to be 0 if loaded records are 0 + return @total_count = 0 if (current_page == 1) && @records.empty? + # Total count is calculable at the last page + return @total_count = (current_page - 1) * limit_value + @records.length if @records.any? && (@records.length < limit_value) + end + + # #count overrides the #select which could include generated columns referenced in #order, so skip #order here, where it's irrelevant to the result anyway + c = except(:offset, :limit, :order) + # Remove includes only if they are irrelevant + c = c.except(:includes) unless references_eager_loaded_tables? + # .group returns an OrderedHash that responds to #count + # The following line was modified from `c = c.count(:all)` + c = c.limit(MAX_COUNT_LIMIT + 1).count(column_name) + @total_count = + if c.is_a?(Hash) || c.is_a?(ActiveSupport::OrderedHash) + c.count + elsif c.respond_to? :count + c.count(column_name) + else + c + end + end + # rubocop: enable Gitlab/ModuleWithInstanceVariables + + Kaminari::ActiveRecordRelationMethods.prepend(self) + end +end diff --git a/db/migrate/20190114172110_add_domain_to_cluster.rb b/db/migrate/20190114172110_add_domain_to_cluster.rb new file mode 100644 index 00000000000..58d7664b8c0 --- /dev/null +++ b/db/migrate/20190114172110_add_domain_to_cluster.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddDomainToCluster < ActiveRecord::Migration[5.0] + DOWNTIME = false + + def change + add_column :clusters, :domain, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index c6fef9b5d11..cd502d06bf4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -647,6 +647,7 @@ ActiveRecord::Schema.define(version: 20190115054216) do t.string "name", null: false t.string "environment_scope", default: "*", null: false t.integer "cluster_type", limit: 2, default: 3, null: false + t.string "domain" t.index ["enabled"], name: "index_clusters_on_enabled", using: :btree t.index ["user_id"], name: "index_clusters_on_user_id", using: :btree end diff --git a/doc/api/README.md b/doc/api/README.md index 6c5bb1c0940..7b83b0fed26 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -438,6 +438,14 @@ Additional pagination headers are also sent back. | `X-Next-Page` | The index of the next page | | `X-Prev-Page` | The index of the previous page | +CAUTION: **Caution:** +For performance reasons since +[GitLab 11.8][https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23931] +and **behind the `api_kaminari_count_with_limit` +[feature flag](../development/feature_flags.md)**, if the number of resources is +more than 10,000, the `X-Total` and `X-Total-Pages` headers as well as the +`rel="last"` `Link` are not present in the response headers. + ## Namespaced path encoding If using namespaced API calls, make sure that the `NAMESPACE/PROJECT_NAME` is diff --git a/doc/development/testing_guide/img/review_apps_cicd_architecture.png b/doc/development/testing_guide/img/review_apps_cicd_architecture.png Binary files differnew file mode 100644 index 00000000000..87e472076f3 --- /dev/null +++ b/doc/development/testing_guide/img/review_apps_cicd_architecture.png diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md index 309babb5f94..19aecedb27c 100644 --- a/doc/development/testing_guide/review_apps.md +++ b/doc/development/testing_guide/review_apps.md @@ -4,41 +4,79 @@ Review Apps are automatically deployed by each pipeline, both in [CE](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22010) and [EE](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6665). +CAUTION: **Warning:** +There's currently [an issue when using `/` in branch names][charts-1068] where +Review Apps fail to be deployed. + ## How does it work? +### CD/CD architecture diagram + +![Review Apps CI/CD architecture](img/review_apps_cicd_architecture.png) + +<details> +<summary>Show mermaid source</summary> +<pre> +graph TD + B1 -.->|2. once gitlab:assets:compile is done,<br />triggers a CNG-mirror pipeline and wait for it to be done| A2 + C1 -.->|2. once review-build-cng is done,<br />Helm deploys the Review App using the Cloud<br/>Native images built by the CNG-mirror pipeline| A3 + +subgraph gitlab-ce/ee `test` stage + A1[gitlab:assets:compile] + B1[review-build-cng] -->|1. wait for| A1 + C1[review-deploy] -->|1. wait for| B1 + D1[review-qa-smoke] -->|1. wait for| C1 + D1[review-qa-smoke] -.->|2. once review-deploy is done| E1>gitlab-qa runs the smoke<br/>suite against the Review App] + end + +subgraph CNG-mirror pipeline + A2>Cloud Native images are built]; + end + +subgraph GCP `gitlab-review-apps` project + A3>"Cloud Native images are deployed to the<br />`review-apps-ce` or `review-apps-ee` Kubernetes (GKE) cluster"]; + end +</pre> +</details> + +### Detailed explanation + 1. On every [pipeline][gitlab-pipeline] during the `test` stage, the - [`review-deploy`][review-deploy-job] job is automatically started. -1. The `review-deploy` job: - 1. Waits for the `gitlab:assets:compile` job to finish since the - [`CNG-mirror`][cng-mirror] pipeline triggerred in the following step - depends on it. - 1. [Triggers a pipeline][cng-pipeline] in the [`CNG-mirror`][cng-mirror] - project. - - We use the `CNG-mirror` project so that the `CNG`, (**C**loud - **N**ative **G**itLab), project's registry is not overloaded with a - lot of transient Docker images. - - The `CNG-mirror` pipeline creates the Docker images of each component - (e.g. `gitlab-rails-ee`, `gitlab-shell`, `gitaly` etc.) based on the - commit from the [GitLab pipeline][gitlab-pipeline] and store them in - its [registry][cng-mirror-registry]. - 1. Once all images are built by [`CNG-mirror`][cng-mirror], the Review App - is deployed using [the official GitLab Helm chart][helm-chart] to the - [`review-apps-ce`][review-apps-ce] / [`review-apps-ee`][review-apps-ee] - Kubernetes cluster on GCP. - - The actual scripts used to deploy the Review App can be found at - [`scripts/review_apps/review-apps.sh`][review-apps.sh]. - - These scripts are basically - [our official Auto DevOps scripts][Auto-DevOps.gitlab-ci.yml] where the - default CNG images are overridden with the images built and stored in the - [`CNG-mirror` project's registry][cng-mirror-registry]. - - Since we're using [the official GitLab Helm chart][helm-chart], this means - you get a dedicated environment for your branch that's very close to what - it would look in production. -1. Once the `review-deploy` job succeeds, you should be able to use your Review - App thanks to the direct link to it from the MR widget. The default username - is `root` and its password can be found in the 1Password secure note named - **gitlab-{ce,ee} Review App's root password** (note that there's currently - [a bug where the default password seems to be overridden][password-bug]). + [`review-build-cng`][review-build-cng] and + [`review-deploy`][review-deploy] jobs are automatically started. + - The [`review-deploy`][review-deploy] job waits for the + [`review-build-cng`][review-build-cng] job to finish. + - The [`review-build-cng`][review-build-cng] job waits for the + [`gitlab:assets:compile`][gitlab:assets:compile] job to finish since the + [`CNG-mirror`][cng-mirror] pipeline triggered in the following step depends on it. +1. Once the [`gitlab:assets:compile`][gitlab:assets:compile] job is done, + [`review-build-cng`][review-build-cng] [triggers a pipeline][cng-pipeline] + in the [`CNG-mirror`][cng-mirror] project. + - The [`CNG-mirror`][cng-pipeline] pipeline creates the Docker images of + each component (e.g. `gitlab-rails-ee`, `gitlab-shell`, `gitaly` etc.) + based on the commit from the [GitLab pipeline][gitlab-pipeline] and store + them in its [registry][cng-mirror-registry]. + - We use the [`CNG-mirror`][cng-mirror] project so that the `CNG`, (**C**loud + **N**ative **G**itLab), project's registry is not overloaded with a + lot of transient Docker images. +1. Once the [`review-build-cng`][review-build-cng] job is done, the + [`review-deploy`][review-deploy] job deploys the Review App using + [the official GitLab Helm chart][helm-chart] to the + [`review-apps-ce`][review-apps-ce] / [`review-apps-ee`][review-apps-ee] + Kubernetes cluster on GCP. + - The actual scripts used to deploy the Review App can be found at + [`scripts/review_apps/review-apps.sh`][review-apps.sh]. + - These scripts are basically + [our official Auto DevOps scripts][Auto-DevOps.gitlab-ci.yml] where the + default CNG images are overridden with the images built and stored in the + [`CNG-mirror` project's registry][cng-mirror-registry]. + - Since we're using [the official GitLab Helm chart][helm-chart], this means + you get a dedicated environment for your branch that's very close to what + it would look in production. +1. Once the [`review-deploy`][review-deploy] job succeeds, you should be able to + use your Review App thanks to the direct link to it from the MR widget. The + default username is `root` and its password can be found in the 1Password + secure note named **gitlab-{ce,ee} Review App's root password**. **Additional notes:** @@ -120,10 +158,13 @@ find a way to limit it to only us.** > This isn't enabled for forks. -[gitlab-pipeline]: https://gitlab.com/gitlab-org/gitlab-ce/pipelines/35850709 -[review-deploy-job]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/118076368 +[charts-1068]: https://gitlab.com/charts/gitlab/issues/1068 +[gitlab-pipeline]: https://gitlab.com/gitlab-org/gitlab-ce/pipelines/44362587 +[gitlab:assets:compile]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/149511610 +[review-build-cng]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/149511623 +[review-deploy]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/149511624 [cng-mirror]: https://gitlab.com/gitlab-org/build/CNG-mirror -[cng-pipeline]: https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/35883435 +[cng-pipeline]: https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657 [cng-mirror-registry]: https://gitlab.com/gitlab-org/build/CNG-mirror/container_registry [helm-chart]: https://gitlab.com/charts/gitlab/ [review-apps-ce]: https://console.cloud.google.com/kubernetes/clusters/details/us-central1-a/review-apps-ce?project=gitlab-review-apps diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md index 0d9994c9925..e30afdf8a40 100644 --- a/doc/gitlab-basics/start-using-git.md +++ b/doc/gitlab-basics/start-using-git.md @@ -68,6 +68,54 @@ git config --global --list ## Basic Git commands +Start using Git via the command line with the most basic +commands as described below. + +### Clone a repository + +To start working locally on an existing remote repository, +clone it with the command `git clone <repository path>`. +By cloning a repository, you'll download a copy of its +files into your local computer, preserving the Git +connection with the remote repository. + +You can either clone it via HTTPS or [SSH](../ssh/README.md). +If you chose to clone it via HTTPS, you'll have to enter your +credentials every time you pull and push. With SSH, you enter +your credentials once and can pull and push straightaway. + +You can find both paths (HTTPS and SSH) by navigating to +your project's landing page and clicking **Clone**. GitLab +will prompt you with both paths, from which you can copy +and paste in your command line. + +As an example, consider a repository path: + +- HTTPS: `https://gitlab.com/gitlab-org/gitlab-ce.git` +- SSH: `` git@gitlab.com:gitlab-org/gitlab-ce.git `` + +To get started, open a terminal window in the directory +you wish to clone the repository files into, and run one +of the following commands. + +Clone via HTTPS: + +```bash +git clone https://gitlab.com/gitlab-org/gitlab-ce.git +``` + +Clone via SSH: + +```bash +git clone git@gitlab.com:gitlab-org/gitlab-ce.git +``` + +Both commands will download a copy of the files in a +folder named after the project's name. + +You can then navigate to the directory and start working +on it locally. + ### Go to the master branch to pull the latest changes from there ```bash diff --git a/doc/install/installation.md b/doc/install/installation.md index 2eba2cc4847..b3ad1c5a91c 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -170,7 +170,7 @@ sudo make install Then install the Bundler Gem: ```sh -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ## 3. Go diff --git a/doc/update/10.0-to-10.1.md b/doc/update/10.0-to-10.1.md index 10cf02a984f..d4373ca3f23 100644 --- a/doc/update/10.0-to-10.1.md +++ b/doc/update/10.0-to-10.1.md @@ -49,7 +49,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/10.1-to-10.2.md b/doc/update/10.1-to-10.2.md index 20895a05567..0705b58ed7a 100644 --- a/doc/update/10.1-to-10.2.md +++ b/doc/update/10.1-to-10.2.md @@ -49,7 +49,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/10.2-to-10.3.md b/doc/update/10.2-to-10.3.md index 441a241d053..33a52d3e807 100644 --- a/doc/update/10.2-to-10.3.md +++ b/doc/update/10.2-to-10.3.md @@ -49,7 +49,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/10.3-to-10.4.md b/doc/update/10.3-to-10.4.md index 9f3efdd790e..3ba96535965 100644 --- a/doc/update/10.3-to-10.4.md +++ b/doc/update/10.3-to-10.4.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/10.4-to-10.5.md b/doc/update/10.4-to-10.5.md index 3766645a141..f00bbcaeaa6 100644 --- a/doc/update/10.4-to-10.5.md +++ b/doc/update/10.4-to-10.5.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/10.5-to-10.6.md b/doc/update/10.5-to-10.6.md index 986ecbf5ef0..6c3f8b663cc 100644 --- a/doc/update/10.5-to-10.6.md +++ b/doc/update/10.5-to-10.6.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/10.6-to-10.7.md b/doc/update/10.6-to-10.7.md index 10d29837bfb..9bd354a5bcd 100644 --- a/doc/update/10.6-to-10.7.md +++ b/doc/update/10.6-to-10.7.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/10.7-to-10.8.md b/doc/update/10.7-to-10.8.md index 0cc46fc5aa9..9aafd3f269f 100644 --- a/doc/update/10.7-to-10.8.md +++ b/doc/update/10.7-to-10.8.md @@ -52,7 +52,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/10.8-to-11.0.md b/doc/update/10.8-to-11.0.md index ad3305d8ebd..f6fdc342e3d 100644 --- a/doc/update/10.8-to-11.0.md +++ b/doc/update/10.8-to-11.0.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/11.0-to-11.1.md b/doc/update/11.0-to-11.1.md index 5b2dd48a744..25a7c1cf929 100644 --- a/doc/update/11.0-to-11.1.md +++ b/doc/update/11.0-to-11.1.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/11.1-to-11.2.md b/doc/update/11.1-to-11.2.md index cb09d0a2505..ced59c245b8 100644 --- a/doc/update/11.1-to-11.2.md +++ b/doc/update/11.1-to-11.2.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/11.2-to-11.3.md b/doc/update/11.2-to-11.3.md index 228ff6cb70e..fa0c6872182 100644 --- a/doc/update/11.2-to-11.3.md +++ b/doc/update/11.2-to-11.3.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/11.3-to-11.4.md b/doc/update/11.3-to-11.4.md index 5f64bf81127..18bbfe4747e 100644 --- a/doc/update/11.3-to-11.4.md +++ b/doc/update/11.3-to-11.4.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/11.4-to-11.5.md b/doc/update/11.4-to-11.5.md index fd7a8e5c2ae..6ad58ae8781 100644 --- a/doc/update/11.4-to-11.5.md +++ b/doc/update/11.4-to-11.5.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/11.5-to-11.6.md b/doc/update/11.5-to-11.6.md index 33e09e1915b..c890f7b6147 100644 --- a/doc/update/11.5-to-11.6.md +++ b/doc/update/11.5-to-11.6.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/11.6-to-11.7.md b/doc/update/11.6-to-11.7.md index 9e61d978631..fd7c3697e80 100644 --- a/doc/update/11.6-to-11.7.md +++ b/doc/update/11.6-to-11.7.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/11.7-to-11.8.md b/doc/update/11.7-to-11.8.md index 7ab98d80eb9..82293ff40a8 100644 --- a/doc/update/11.7-to-11.8.md +++ b/doc/update/11.7-to-11.8.md @@ -51,7 +51,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/6.9-to-7.0.md b/doc/update/6.9-to-7.0.md index 7f3abf74675..b54884c4682 100644 --- a/doc/update/6.9-to-7.0.md +++ b/doc/update/6.9-to-7.0.md @@ -47,7 +47,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 3. Get latest code diff --git a/doc/update/6.x-or-7.x-to-7.14.md b/doc/update/6.x-or-7.x-to-7.14.md index c20a72ce162..745df56bbb0 100644 --- a/doc/update/6.x-or-7.x-to-7.14.md +++ b/doc/update/6.x-or-7.x-to-7.14.md @@ -67,7 +67,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ## 3. Get latest code diff --git a/doc/update/7.0-to-7.1.md b/doc/update/7.0-to-7.1.md index fb4710faad5..8b69431dee1 100644 --- a/doc/update/7.0-to-7.1.md +++ b/doc/update/7.0-to-7.1.md @@ -47,7 +47,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 3. Get latest code diff --git a/doc/update/8.10-to-8.11.md b/doc/update/8.10-to-8.11.md index 12a465e1602..f8415b5159b 100644 --- a/doc/update/8.10-to-8.11.md +++ b/doc/update/8.10-to-8.11.md @@ -47,7 +47,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Get latest code diff --git a/doc/update/8.11-to-8.12.md b/doc/update/8.11-to-8.12.md index b9a7986d5ba..07ac8129b4f 100644 --- a/doc/update/8.11-to-8.12.md +++ b/doc/update/8.11-to-8.12.md @@ -47,7 +47,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Get latest code diff --git a/doc/update/8.12-to-8.13.md b/doc/update/8.12-to-8.13.md index 37e61794e7e..bf622deaba8 100644 --- a/doc/update/8.12-to-8.13.md +++ b/doc/update/8.12-to-8.13.md @@ -47,7 +47,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Get latest code diff --git a/doc/update/8.13-to-8.14.md b/doc/update/8.13-to-8.14.md index 927f453b9bf..43b636ea958 100644 --- a/doc/update/8.13-to-8.14.md +++ b/doc/update/8.13-to-8.14.md @@ -47,7 +47,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Get latest code diff --git a/doc/update/8.14-to-8.15.md b/doc/update/8.14-to-8.15.md index d98a60d31c8..eadf1743597 100644 --- a/doc/update/8.14-to-8.15.md +++ b/doc/update/8.14-to-8.15.md @@ -50,7 +50,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Get latest code diff --git a/doc/update/8.15-to-8.16.md b/doc/update/8.15-to-8.16.md index 94b0102ed48..4e8d54d5010 100644 --- a/doc/update/8.15-to-8.16.md +++ b/doc/update/8.15-to-8.16.md @@ -50,7 +50,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Get latest code diff --git a/doc/update/8.16-to-8.17.md b/doc/update/8.16-to-8.17.md index 5a4f620a164..cab28a4d1c6 100644 --- a/doc/update/8.16-to-8.17.md +++ b/doc/update/8.16-to-8.17.md @@ -50,7 +50,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/8.17-to-9.0.md b/doc/update/8.17-to-9.0.md index 38f7d22437a..55cf0842df4 100644 --- a/doc/update/8.17-to-9.0.md +++ b/doc/update/8.17-to-9.0.md @@ -49,7 +49,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/9.0-to-9.1.md b/doc/update/9.0-to-9.1.md index a4d2e7be23c..10214fd8aca 100644 --- a/doc/update/9.0-to-9.1.md +++ b/doc/update/9.0-to-9.1.md @@ -49,7 +49,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/9.1-to-9.2.md b/doc/update/9.1-to-9.2.md index dd808c51985..79d92f05257 100644 --- a/doc/update/9.1-to-9.2.md +++ b/doc/update/9.1-to-9.2.md @@ -49,7 +49,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/9.2-to-9.3.md b/doc/update/9.2-to-9.3.md index d2bcf45a28e..98443b8bfa6 100644 --- a/doc/update/9.2-to-9.3.md +++ b/doc/update/9.2-to-9.3.md @@ -49,7 +49,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/9.3-to-9.4.md b/doc/update/9.3-to-9.4.md index dae2162a964..640b9c3997e 100644 --- a/doc/update/9.3-to-9.4.md +++ b/doc/update/9.3-to-9.4.md @@ -49,7 +49,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/9.4-to-9.5.md b/doc/update/9.4-to-9.5.md index f2811e9471f..e6cfa70975e 100644 --- a/doc/update/9.4-to-9.5.md +++ b/doc/update/9.4-to-9.5.md @@ -49,7 +49,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/update/9.5-to-10.0.md b/doc/update/9.5-to-10.0.md index 333a6e35714..8b565f67cb1 100644 --- a/doc/update/9.5-to-10.0.md +++ b/doc/update/9.5-to-10.0.md @@ -49,7 +49,7 @@ sudo make install Install Bundler: ```bash -sudo gem install bundler --no-document +sudo gem install bundler --no-document --version '< 2' ``` ### 4. Update Node diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md index 9ecb109fa89..bebccf97987 100644 --- a/doc/user/project/clusters/serverless/index.md +++ b/doc/user/project/clusters/serverless/index.md @@ -121,9 +121,9 @@ In order to deploy functions to your Knative instance, the following files must runtime: https://gitlab.com/triggermesh/runtimes/raw/master/nodejs.yaml description: "echo function using node.js runtime" buildargs: - - DIRECTORY=echo - environment: - FUNCTION: echo + - DIRECTORY=echo + environment: + FUNCTION: echo ``` diff --git a/doc/user/project/integrations/slack.md b/doc/user/project/integrations/slack.md index af4ca35a215..bb8d276c2fc 100644 --- a/doc/user/project/integrations/slack.md +++ b/doc/user/project/integrations/slack.md @@ -23,4 +23,54 @@ The Slack Notifications Service allows your GitLab project to send events (e.g. Your Slack team will now start receiving GitLab event notifications as configured. -![Slack configuration](img/slack_configuration.png)
\ No newline at end of file +![Slack configuration](img/slack_configuration.png) + +## Troubleshooting + +If you're having trouble with the Slack integration not working, then start by +searching through the [Sidekiq logs](../../../administration/logs.md#sidekiqlog) +for errors relating to your Slack service. + +### Something went wrong on our end + +This is a generic error shown in the GitLab UI and doesn't mean much by itself. +You'll need to look in [the logs](../../../administration/logs.md#productionlog) to find +an error message and keep troubleshooting from there. + +### `certificate verify failed` + +You may see an entry similar to the following in your Sidekiq log: + +```text +2019-01-10_13:22:08.42572 2019-01-10T13:22:08.425Z 6877 TID-abcdefg ProjectServiceWorker JID-3bade5fb3dd47a85db6d78c5 ERROR: {:class=>"ProjectServiceWorker", :service_class=>"SlackService", :message=>"SSL_connect returned=1 errno=0 state=error: certificate verify failed"} +``` + +This is probably a problem either with GitLab communicating with Slack, or GitLab +communicating with itself. The former is less likely since Slack's security certificates +should _hopefully_ always be trusted. We can establish which we're dealing with by using +the below rails console script. + +```sh +# start a rails console: +sudo gitlab-rails console production + +# or for source installs: +bundle exec rails console production +``` + +```ruby +# run this in the Rails console +# replace <SLACK URL> with your actual Slack URL +result = Net::HTTP.get(URI('https://<SLACK URL>'));0 + +# replace <GITLAB URL> with your actual GitLab URL +result = Net::HTTP.get(URI('https://<GITLAB URL>'));0 +``` + +If it's an issue with GitLab not trusting HTTPS connections to itself, then you may simply +need to [add your certificate to GitLab's trusted certificates](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates). + +If it's an issue with GitLab not trusting connections to Slack, then the GitLab +OpenSSL trust store probably got messed up somehow. Typically this is from overriding +the trust store with `gitlab_rails['env'] = {"SSL_CERT_FILE" => "/path/to/file.pem"}` +or by accidentally modifying the default CA bundle `/opt/gitlab/embedded/ssl/certs/cacert.pem`. diff --git a/lib/api/helpers/pagination.rb b/lib/api/helpers/pagination.rb index d311cbb5f7e..cfcce6b66ad 100644 --- a/lib/api/helpers/pagination.rb +++ b/lib/api/helpers/pagination.rb @@ -178,15 +178,26 @@ module API end def paginate(relation) - relation = add_default_order(relation) - - relation.page(params[:page]).per(params[:per_page]).tap do |data| + paginate_with_limit_optimization(add_default_order(relation)).tap do |data| add_pagination_headers(data) end end private + def paginate_with_limit_optimization(relation) + pagination_data = relation.page(params[:page]).per(params[:per_page]) + return pagination_data unless pagination_data.is_a?(ActiveRecord::Relation) + return pagination_data unless Feature.enabled?(:api_kaminari_count_with_limit) + + limited_total_count = pagination_data.total_count_with_limit + if limited_total_count > Kaminari::ActiveRecordRelationMethods::MAX_COUNT_LIMIT + pagination_data.without_count + else + pagination_data + end + end + # rubocop: disable CodeReuse/ActiveRecord def add_default_order(relation) if relation.is_a?(ActiveRecord::Relation) && relation.order_values.empty? diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index 8c1951cc535..132b19164d0 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -179,7 +179,7 @@ module API optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request' optional :milestone_id, type: Integer, desc: 'The ID of a milestone to assign the merge request' optional :labels, type: String, desc: 'Comma-separated list of label names' - optional :remove_source_branch, type: Boolean, desc: 'Remove source branch when merging' + optional :remove_source_branch, type: Boolean, desc: 'Delete source branch when merging' optional :allow_collaboration, type: Boolean, desc: 'Allow commits from members who can merge to the target branch' optional :allow_maintainer_to_push, type: Boolean, as: :allow_collaboration, desc: '[deprecated] See allow_collaboration' optional :squash, type: Grape::API::Boolean, desc: 'When true, the commits will be squashed into a single commit on merge' diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml index 9362596eb60..47e3e8cd271 100644 --- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @@ -50,7 +50,7 @@ variables: POSTGRES_DB: $CI_ENVIRONMENT_SLUG KUBERNETES_VERSION: 1.11.6 - HELM_VERSION: 2.11.0 + HELM_VERSION: 2.12.2 DOCKER_DRIVER: overlay2 diff --git a/lib/gitlab/kubernetes/helm.rb b/lib/gitlab/kubernetes/helm.rb index 03d38ec78fd..bbac15c7710 100644 --- a/lib/gitlab/kubernetes/helm.rb +++ b/lib/gitlab/kubernetes/helm.rb @@ -3,7 +3,7 @@ module Gitlab module Kubernetes module Helm - HELM_VERSION = '2.11.0'.freeze + HELM_VERSION = '2.12.2'.freeze KUBECTL_VERSION = '1.11.0'.freeze NAMESPACE = 'gitlab-managed-apps'.freeze SERVICE_ACCOUNT = 'tiller'.freeze diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 55e2e82e13e..a72e921dcce 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -291,7 +291,7 @@ msgstr "" msgid "<strong>%{group_name}</strong> group members" msgstr "" -msgid "<strong>Removes</strong> source branch" +msgid "<strong>Deletes</strong> source branch" msgstr "" msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." @@ -735,6 +735,9 @@ msgstr "" msgid "Are you sure you want to stop this environment?" msgstr "" +msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?" +msgstr "" + msgid "Are you sure?" msgstr "" @@ -7557,6 +7560,9 @@ msgstr "" msgid "Unsubscribe at project level" msgstr "" +msgid "Unsubscribe from %{type}" +msgstr "" + msgid "Unverified" msgstr "" @@ -8334,6 +8340,9 @@ msgstr "" msgid "mrWidget|Create an issue to resolve them later" msgstr "" +msgid "mrWidget|Delete source branch" +msgstr "" + msgid "mrWidget|Deployment statistics are not available currently" msgstr "" @@ -8394,12 +8403,6 @@ msgstr "" msgid "mrWidget|Refreshing now" msgstr "" -msgid "mrWidget|Remove Source Branch" -msgstr "" - -msgid "mrWidget|Remove source branch" -msgstr "" - msgid "mrWidget|Request to merge" msgstr "" @@ -8433,19 +8436,19 @@ msgstr "" msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging" msgstr "" -msgid "mrWidget|The source branch has been removed" +msgid "mrWidget|The source branch has been deleted" msgstr "" msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch" msgstr "" -msgid "mrWidget|The source branch is being removed" +msgid "mrWidget|The source branch is being deleted" msgstr "" -msgid "mrWidget|The source branch will be removed" +msgid "mrWidget|The source branch will be deleted" msgstr "" -msgid "mrWidget|The source branch will not be removed" +msgid "mrWidget|The source branch will not be deleted" msgstr "" msgid "mrWidget|There are merge conflicts" @@ -8469,10 +8472,10 @@ msgstr "" msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes." msgstr "" -msgid "mrWidget|You can merge this merge request manually using the" +msgid "mrWidget|You can delete the source branch now" msgstr "" -msgid "mrWidget|You can remove source branch now" +msgid "mrWidget|You can merge this merge request manually using the" msgstr "" msgid "mrWidget|branch does not exist." diff --git a/package.json b/package.json index 21431b210cd..6c771e377b8 100644 --- a/package.json +++ b/package.json @@ -21,12 +21,12 @@ }, "dependencies": { "@babel/core": "^7.2.2", - "@babel/plugin-proposal-class-properties": "^7.2.3", + "@babel/plugin-proposal-class-properties": "^7.3.0", "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-private-methods": "^7.2.3", + "@babel/plugin-proposal-private-methods": "^7.3.0", "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-import-meta": "^7.2.0", - "@babel/preset-env": "^7.2.3", + "@babel/preset-env": "^7.3.1", "@gitlab/csslab": "^1.8.0", "@gitlab/svgs": "^1.47.0", "@gitlab/ui": "^1.20.0", @@ -162,7 +162,7 @@ "karma-webpack": "^4.0.0-beta.0", "nodemon": "^1.18.4", "pixelmatch": "^4.0.2", - "prettier": "1.15.3", + "prettier": "1.16.1", "vue-jest": "^3.0.2", "webpack-dev-server": "^3.1.14", "yarn-deduplicate": "^1.0.5" diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb index b9580d81171..6c5e91b6488 100644 --- a/qa/qa/resource/user.rb +++ b/qa/qa/resource/user.rb @@ -17,11 +17,11 @@ module QA end def username - @username ||= "qa-user-#{unique_id}" + @username || "qa-user-#{unique_id}" end def password - @password ||= 'password' + @password || 'password' end def name @@ -29,7 +29,15 @@ module QA end def email - @email ||= api_resource&.dig(:email) || "#{username}@example.com" + @email ||= "#{username}@example.com" + end + + def public_email + @public_email ||= begin + api_public_email = api_resource&.dig(:public_email) + + api_public_email && api_public_email != '' ? api_public_email : Runtime::User.default_email + end end def credentials_given? diff --git a/qa/qa/runtime/user.rb b/qa/qa/runtime/user.rb index 5eb7a210fce..e8bcb8a9f50 100644 --- a/qa/qa/runtime/user.rb +++ b/qa/qa/runtime/user.rb @@ -7,6 +7,10 @@ module QA 'root' end + def default_email + 'admin@example.com' + end + def default_password '5iveL!fe' end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb index 3a5d89e6b83..621cca0f9a5 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb @@ -47,7 +47,7 @@ module QA Page::Project::Commit::Show.perform(&:select_email_patches) - expect(page).to have_content("From: #{user.name} <#{user.email}>") + expect(page).to have_content("From: #{user.name} <#{user.public_email}>") expect(page).to have_content('Subject: [PATCH] Add second file') expect(page).to have_content('diff --git a/second b/second') end diff --git a/qa/spec/resource/user_spec.rb b/qa/spec/resource/user_spec.rb new file mode 100644 index 00000000000..d612dfc530e --- /dev/null +++ b/qa/spec/resource/user_spec.rb @@ -0,0 +1,118 @@ +# frozen_string_literal: true + +describe QA::Resource::User do + let(:api_resource) do + { + name: "GitLab QA", + username: "gitlab-qa", + web_url: "https://staging.gitlab.com/gitlab-qa", + public_email: "1614863-gitlab-qa@users.noreply.staging.gitlab.com" + } + end + + describe '#username' do + it 'generates a default username' do + expect(subject.username).to match(/qa-user-\w+/) + end + + it 'is possible to set the username' do + subject.username = 'johndoe' + + expect(subject.username).to eq('johndoe') + end + end + + describe '#password' do + it 'generates a default password' do + expect(subject.password).to eq('password') + end + + it 'is possible to set the password' do + subject.password = 'secret' + + expect(subject.password).to eq('secret') + end + end + + describe '#name' do + it 'defaults to the username' do + expect(subject.name).to eq(subject.username) + end + + it 'retrieves the name from the api_resource if present' do + subject.__send__(:api_resource=, api_resource) + + expect(subject.name).to eq(api_resource[:name]) + end + + it 'is possible to set the name' do + subject.name = 'John Doe' + + expect(subject.name).to eq('John Doe') + end + end + + describe '#email' do + it 'defaults to the <username>@example.com' do + expect(subject.email).to eq("#{subject.username}@example.com") + end + + it 'is possible to set the email' do + subject.email = 'johndoe@example.org' + + expect(subject.email).to eq('johndoe@example.org') + end + end + + describe '#public_email' do + it 'defaults to QA::Runtime::User.default_email' do + expect(subject.public_email).to eq(QA::Runtime::User.default_email) + end + + it 'retrieves the public_email from the api_resource if present' do + subject.__send__(:api_resource=, api_resource) + + expect(subject.public_email).to eq(api_resource[:public_email]) + end + + it 'defaults to QA::Runtime::User.default_email if the public_email from the api_resource is blank' do + subject.__send__(:api_resource=, api_resource.merge(public_email: '')) + + expect(subject.public_email).to eq(QA::Runtime::User.default_email) + end + end + + describe '#credentials_given?' do + it 'returns false when username and email have not been overridden' do + expect(subject).not_to be_credentials_given + end + + it 'returns false even after username and email have been called' do + # Call #username and #password to ensure this doesn't set their respective + # instance variable. + subject.username + subject.password + + expect(subject).not_to be_credentials_given + end + + it 'returns false if only the username has been overridden' do + subject.username = 'johndoe' + + expect(subject).not_to be_credentials_given + end + + it 'returns false if only the password has been overridden' do + subject.password = 'secret' + + expect(subject).not_to be_credentials_given + end + + it 'returns true if both the username and password have been overridden' do + subject.username = 'johndoe' + subject.password = 'secret' + + expect(subject).to be_credentials_given + end + end +end diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index 02b3d5269a6..52a20fa8d07 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -331,7 +331,7 @@ describe Projects::BranchesController do let(:branch) { "feature" } it 'returns JSON response with message' do - expect(json_response).to eql("message" => 'Branch was removed') + expect(json_response).to eql("message" => 'Branch was deleted') end it { expect(response).to have_gitlab_http_status(200) } @@ -341,7 +341,7 @@ describe Projects::BranchesController do let(:branch) { "improve/awesome" } it 'returns JSON response with message' do - expect(json_response).to eql('message' => 'Branch was removed') + expect(json_response).to eql('message' => 'Branch was deleted') end it { expect(response).to have_gitlab_http_status(200) } @@ -351,7 +351,7 @@ describe Projects::BranchesController do let(:branch) { 'improve%2Fawesome' } it 'returns JSON response with message' do - expect(json_response).to eql('message' => 'Branch was removed') + expect(json_response).to eql('message' => 'Branch was deleted') end it { expect(response).to have_gitlab_http_status(200) } diff --git a/spec/factories/clusters/clusters.rb b/spec/factories/clusters/clusters.rb index 3e2c0df8afb..a2e5f4862db 100644 --- a/spec/factories/clusters/clusters.rb +++ b/spec/factories/clusters/clusters.rb @@ -59,5 +59,9 @@ FactoryBot.define do trait :with_installed_helm do application_helm factory: %i(clusters_applications_helm installed) end + + trait :with_domain do + domain 'example.com' + end end end diff --git a/spec/features/merge_request/user_accepts_merge_request_spec.rb b/spec/features/merge_request/user_accepts_merge_request_spec.rb index 01aeed93947..00ac7c72a11 100644 --- a/spec/features/merge_request/user_accepts_merge_request_spec.rb +++ b/spec/features/merge_request/user_accepts_merge_request_spec.rb @@ -25,7 +25,7 @@ describe 'User accepts a merge request', :js do end it 'accepts a merge request' do - check('Remove source branch') + check('Delete source branch') click_button('Merge') expect(page).to have_content('The changes were merged into') @@ -60,7 +60,7 @@ describe 'User accepts a merge request', :js do end it 'accepts a merge request' do - check('Remove source branch') + check('Delete source branch') click_button('Merge') expect(page).to have_content('The changes were merged into') diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb index 29b3d2b629b..6e54aa6006b 100644 --- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb +++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb @@ -33,7 +33,7 @@ describe 'Merge request > User merges when pipeline succeeds', :js do click_button "Merge when pipeline succeeds" expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds" - expect(page).to have_content "The source branch will not be removed" + expect(page).to have_content "The source branch will not be deleted" expect(page).to have_selector ".js-cancel-auto-merge" visit project_merge_request_path(project, merge_request) # Needed to refresh the page expect(page).to have_content /enabled an automatic merge when the pipeline for \h{8} succeeds/i @@ -94,7 +94,7 @@ describe 'Merge request > User merges when pipeline succeeds', :js do click_link 'Merge when pipeline succeeds' expect(page).to have_content "Set by #{user.name} to be merged automatically when the pipeline succeeds" - expect(page).to have_content "The source branch will not be removed" + expect(page).to have_content "The source branch will not be deleted" expect(page).to have_link "Cancel automatic merge" end end @@ -127,10 +127,10 @@ describe 'Merge request > User merges when pipeline succeeds', :js do expect(page).to have_content "canceled the automatic merge" end - it 'allows to remove source branch' do - click_link "Remove source branch" + it 'allows to delete source branch' do + click_link "Delete source branch" - expect(page).to have_content "The source branch will be removed" + expect(page).to have_content "The source branch will be deleted" end context 'when pipeline succeeds' do diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index d8ebd3c92af..afb978d7c45 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -316,7 +316,7 @@ describe 'Merge request > User sees merge widget', :js do it 'user cannot remove source branch' do expect(page).not_to have_field('remove-source-branch-input') - expect(page).to have_content('Removes source branch') + expect(page).to have_content('Deletes source branch') end end diff --git a/spec/features/merge_requests/user_squashes_merge_request_spec.rb b/spec/features/merge_requests/user_squashes_merge_request_spec.rb index ec1153b7f7f..47f9f10815c 100644 --- a/spec/features/merge_requests/user_squashes_merge_request_spec.rb +++ b/spec/features/merge_requests/user_squashes_merge_request_spec.rb @@ -38,7 +38,7 @@ describe 'User squashes a merge request', :js do def accept_mr expect(page).to have_button('Merge') - uncheck 'Remove source branch' + uncheck 'Delete source branch' click_on 'Merge' end diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb index 63c38a25f4b..0aff916ec83 100644 --- a/spec/features/protected_branches_spec.rb +++ b/spec/features/protected_branches_spec.rb @@ -97,7 +97,7 @@ describe 'Protected Branches', :js do set_protected_branch_name('some-branch') click_on "Protect" - within(".protected-branches-list") { expect(page).to have_content('branch was removed') } + within(".protected-branches-list") { expect(page).to have_content('branch was deleted') } end end diff --git a/spec/javascripts/diffs/store/utils_spec.js b/spec/javascripts/diffs/store/utils_spec.js index ea86844ddca..3641946518b 100644 --- a/spec/javascripts/diffs/store/utils_spec.js +++ b/spec/javascripts/diffs/store/utils_spec.js @@ -251,45 +251,40 @@ describe('DiffsStoreUtils', () => { describe('trimFirstCharOfLineContent', () => { it('trims the line when it starts with a space', () => { expect(utils.trimFirstCharOfLineContent({ rich_text: ' diff' })).toEqual({ - discussions: [], rich_text: 'diff', }); }); it('trims the line when it starts with a +', () => { expect(utils.trimFirstCharOfLineContent({ rich_text: '+diff' })).toEqual({ - discussions: [], rich_text: 'diff', }); }); it('trims the line when it starts with a -', () => { expect(utils.trimFirstCharOfLineContent({ rich_text: '-diff' })).toEqual({ - discussions: [], rich_text: 'diff', }); }); it('does not trims the line when it starts with a letter', () => { expect(utils.trimFirstCharOfLineContent({ rich_text: 'diff' })).toEqual({ - discussions: [], rich_text: 'diff', }); }); it('does not modify the provided object', () => { const lineObj = { - discussions: [], rich_text: ' diff', }; utils.trimFirstCharOfLineContent(lineObj); - expect(lineObj).toEqual({ discussions: [], rich_text: ' diff' }); + expect(lineObj).toEqual({ rich_text: ' diff' }); }); it('handles a undefined or null parameter', () => { - expect(utils.trimFirstCharOfLineContent()).toEqual({ discussions: [] }); + expect(utils.trimFirstCharOfLineContent()).toEqual({}); }); }); diff --git a/spec/javascripts/notes/stores/mutation_spec.js b/spec/javascripts/notes/stores/mutation_spec.js index 3fbae82f16c..b6b2c7d60a5 100644 --- a/spec/javascripts/notes/stores/mutation_spec.js +++ b/spec/javascripts/notes/stores/mutation_spec.js @@ -179,11 +179,11 @@ describe('Notes Store mutations', () => { diff_file: { file_hash: 'a', }, - truncated_diff_lines: ['a'], + truncated_diff_lines: [{ text: '+a', rich_text: '+<span>a</span>' }], }, ]); - expect(state.discussions[0].truncated_diff_lines).toEqual(['a']); + expect(state.discussions[0].truncated_diff_lines).toEqual([{ rich_text: '<span>a</span>' }]); }); it('adds empty truncated_diff_lines when not in discussion', () => { @@ -420,9 +420,12 @@ describe('Notes Store mutations', () => { ], }; - mutations.SET_DISCUSSION_DIFF_LINES(state, { discussionId: 1, diffLines: ['test'] }); + mutations.SET_DISCUSSION_DIFF_LINES(state, { + discussionId: 1, + diffLines: [{ text: '+a', rich_text: '+<span>a</span>' }], + }); - expect(state.discussions[0].truncated_diff_lines).toEqual(['test']); + expect(state.discussions[0].truncated_diff_lines).toEqual([{ rich_text: '<span>a</span>' }]); }); it('keeps reactivity of discussion', () => { @@ -435,7 +438,10 @@ describe('Notes Store mutations', () => { ]); const discussion = state.discussions[0]; - mutations.SET_DISCUSSION_DIFF_LINES(state, { discussionId: 1, diffLines: ['test'] }); + mutations.SET_DISCUSSION_DIFF_LINES(state, { + discussionId: 1, + diffLines: [{ rich_text: '<span>a</span>' }], + }); discussion.expanded = true; diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js index d46ad0acc9b..b9718a78fa4 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js @@ -121,14 +121,14 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { expect(vm.$el.innerText).toContain('to be merged automatically when the pipeline succeeds'); expect(vm.$el.innerText).toContain('The changes will be merged into'); expect(vm.$el.innerText).toContain(targetBranch); - expect(vm.$el.innerText).toContain('The source branch will not be removed'); + expect(vm.$el.innerText).toContain('The source branch will not be deleted'); expect(vm.$el.querySelector('.js-cancel-auto-merge').innerText).toContain( 'Cancel automatic merge', ); expect(vm.$el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeFalsy(); expect(vm.$el.querySelector('.js-remove-source-branch').innerText).toContain( - 'Remove source branch', + 'Delete source branch', ); expect(vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled')).toBeFalsy(); @@ -143,19 +143,19 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { }); }); - it('should show source branch will be removed text when it source branch set to remove', done => { + it('should show source branch will be deleted text when it source branch set to remove', done => { vm.mr.shouldRemoveSourceBranch = true; Vue.nextTick(() => { const normalizedText = vm.$el.innerText.replace(/\s+/g, ' '); - expect(normalizedText).toContain('The source branch will be removed'); - expect(normalizedText).not.toContain('The source branch will not be removed'); + expect(normalizedText).toContain('The source branch will be deleted'); + expect(normalizedText).not.toContain('The source branch will not be deleted'); done(); }); }); - it('should not show remove source branch button when user not able to remove source branch', done => { + it('should not show delete source branch button when user not able to delete source branch', done => { vm.mr.currentUserId = 4; Vue.nextTick(() => { @@ -164,7 +164,7 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => { }); }); - it('should disable remove source branch button when the action is in progress', done => { + it('should disable delete source branch button when the action is in progress', done => { vm.isRemovingSourceBranch = true; Vue.nextTick(() => { diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js index da5cb752c6f..1683da805b9 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js @@ -128,7 +128,7 @@ describe('MRWidgetMerged', () => { new Promise(resolve => { resolve({ data: { - message: 'Branch was removed', + message: 'Branch was deleted', }, }); }), @@ -157,8 +157,8 @@ describe('MRWidgetMerged', () => { expect(vm.$el.textContent).toContain(targetBranch); }); - it('renders information about branch being removed', () => { - expect(vm.$el.textContent).toContain('The source branch has been removed'); + it('renders information about branch being deleted', () => { + expect(vm.$el.textContent).toContain('The source branch has been deleted'); }); it('shows revert and cherry-pick buttons', () => { @@ -189,24 +189,24 @@ describe('MRWidgetMerged', () => { expect(selectors.mergeCommitShaLink.href).toBe(vm.mr.mergeCommitPath); }); - it('should not show source branch removed text', done => { + it('should not show source branch deleted text', done => { vm.mr.sourceBranchRemoved = false; Vue.nextTick(() => { - expect(vm.$el.innerText).toContain('You can remove source branch now'); - expect(vm.$el.innerText).not.toContain('The source branch has been removed'); + expect(vm.$el.innerText).toContain('You can delete the source branch now'); + expect(vm.$el.innerText).not.toContain('The source branch has been deleted'); done(); }); }); - it('should show source branch removing text', done => { + it('should show source branch deleting text', done => { vm.mr.isRemovingSourceBranch = true; vm.mr.sourceBranchRemoved = false; Vue.nextTick(() => { - expect(vm.$el.innerText).toContain('The source branch is being removed'); - expect(vm.$el.innerText).not.toContain('You can remove source branch now'); - expect(vm.$el.innerText).not.toContain('The source branch has been removed'); + expect(vm.$el.innerText).toContain('The source branch is being deleted'); + expect(vm.$el.innerText).not.toContain('You can delete the source branch now'); + expect(vm.$el.innerText).not.toContain('The source branch has been deleted'); done(); }); }); diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js index 99b80df766a..34b90c23c19 100644 --- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js +++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js @@ -453,7 +453,7 @@ describe('mrWidgetOptions', () => { vm.$nextTick(() => { const tooltip = vm.$el.querySelector('.fa-question-circle'); - expect(vm.$el.textContent).toContain('Removes source branch'); + expect(vm.$el.textContent).toContain('Deletes source branch'); expect(tooltip.getAttribute('data-original-title')).toBe( 'A user with write access to the source branch selected this option', ); @@ -468,8 +468,8 @@ describe('mrWidgetOptions', () => { vm.mr.state = 'merged'; vm.$nextTick(() => { - expect(vm.$el.textContent).toContain('The source branch has been removed'); - expect(vm.$el.textContent).not.toContain('Removes source branch'); + expect(vm.$el.textContent).toContain('The source branch has been deleted'); + expect(vm.$el.textContent).not.toContain('Deletes source branch'); done(); }); diff --git a/spec/lib/api/helpers/pagination_spec.rb b/spec/lib/api/helpers/pagination_spec.rb index 0a7682d906b..2890aa4ae38 100644 --- a/spec/lib/api/helpers/pagination_spec.rb +++ b/spec/lib/api/helpers/pagination_spec.rb @@ -237,26 +237,89 @@ describe API::Helpers::Pagination do .and_return({ page: 1, per_page: 2 }) end - it 'returns appropriate amount of resources' do - expect(subject.paginate(resource).count).to eq 2 + shared_examples 'response with pagination headers' do + it 'adds appropriate headers' do + expect_header('X-Total', '3') + expect_header('X-Total-Pages', '2') + expect_header('X-Per-Page', '2') + expect_header('X-Page', '1') + expect_header('X-Next-Page', '2') + expect_header('X-Prev-Page', '') + + expect_header('Link', anything) do |_key, val| + expect(val).to include('rel="first"') + expect(val).to include('rel="last"') + expect(val).to include('rel="next"') + expect(val).not_to include('rel="prev"') + end + + subject.paginate(resource) + end end - it 'adds appropriate headers' do - expect_header('X-Total', '3') - expect_header('X-Total-Pages', '2') - expect_header('X-Per-Page', '2') - expect_header('X-Page', '1') - expect_header('X-Next-Page', '2') - expect_header('X-Prev-Page', '') + shared_examples 'paginated response' do + it 'returns appropriate amount of resources' do + expect(subject.paginate(resource).count).to eq 2 + end - expect_header('Link', anything) do |_key, val| - expect(val).to include('rel="first"') - expect(val).to include('rel="last"') - expect(val).to include('rel="next"') - expect(val).not_to include('rel="prev"') + it 'executes only one SELECT COUNT query' do + expect { subject.paginate(resource) }.to make_queries_matching(/SELECT COUNT/, 1) end + end - subject.paginate(resource) + context 'when the api_kaminari_count_with_limit feature flag is unset' do + it_behaves_like 'paginated response' + it_behaves_like 'response with pagination headers' + end + + context 'when the api_kaminari_count_with_limit feature flag is disabled' do + before do + stub_feature_flags(api_kaminari_count_with_limit: false) + end + + it_behaves_like 'paginated response' + it_behaves_like 'response with pagination headers' + end + + context 'when the api_kaminari_count_with_limit feature flag is enabled' do + before do + stub_feature_flags(api_kaminari_count_with_limit: true) + end + + context 'when resources count is less than MAX_COUNT_LIMIT' do + before do + stub_const("::Kaminari::ActiveRecordRelationMethods::MAX_COUNT_LIMIT", 4) + end + + it_behaves_like 'paginated response' + it_behaves_like 'response with pagination headers' + end + + context 'when resources count is more than MAX_COUNT_LIMIT' do + before do + stub_const("::Kaminari::ActiveRecordRelationMethods::MAX_COUNT_LIMIT", 2) + end + + it_behaves_like 'paginated response' + + it 'does not return the X-Total and X-Total-Pages headers' do + expect_no_header('X-Total') + expect_no_header('X-Total-Pages') + expect_header('X-Per-Page', '2') + expect_header('X-Page', '1') + expect_header('X-Next-Page', '2') + expect_header('X-Prev-Page', '') + + expect_header('Link', anything) do |_key, val| + expect(val).to include('rel="first"') + expect(val).not_to include('rel="last"') + expect(val).to include('rel="next"') + expect(val).not_to include('rel="prev"') + end + + subject.paginate(resource) + end + end end end @@ -348,6 +411,10 @@ describe API::Helpers::Pagination do expect(subject).to receive(:header).with(*args, &block) end + def expect_no_header(*args, &block) + expect(subject).not_to receive(:header).with(*args) + end + def expect_message(method) expect(subject).to receive(method) .at_least(:once).and_return(value) diff --git a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb index 2dd3a570a1d..9cb79148028 100644 --- a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb @@ -30,7 +30,7 @@ describe Gitlab::Kubernetes::Helm::Pod do it 'should generate the appropriate specifications for the container' do container = subject.generate.spec.containers.first expect(container.name).to eq('helm') - expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.11.0-kube-1.11.0') + expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.12.2-kube-1.11.0') expect(container.env.count).to eq(3) expect(container.env.map(&:name)).to match_array([:HELM_VERSION, :TILLER_NAMESPACE, :COMMAND_SCRIPT]) expect(container.command).to match_array(["/bin/sh"]) diff --git a/spec/models/appearance_spec.rb b/spec/models/appearance_spec.rb index ec2e7d672f0..cc76a2019ec 100644 --- a/spec/models/appearance_spec.rb +++ b/spec/models/appearance_spec.rb @@ -36,6 +36,13 @@ describe Appearance do expect(subject.send("#{logo_type}_path")).to be_nil end + it 'returns the path when the upload has been orphaned' do + appearance.send(logo_type).upload.destroy + appearance.reload + + expect(appearance.send("#{logo_type}_path")).to eq(expected_path) + end + it 'returns a local path using the system route' do expect(appearance.send("#{logo_type}_path")).to eq(expected_path) end diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb index f447e64b029..0161db740ee 100644 --- a/spec/models/clusters/cluster_spec.rb +++ b/spec/models/clusters/cluster_spec.rb @@ -113,7 +113,7 @@ describe Clusters::Cluster do end end - describe 'validation' do + describe 'validations' do subject { cluster.valid? } context 'when validates name' do @@ -252,6 +252,31 @@ describe Clusters::Cluster do end end end + + describe 'domain validation' do + let(:cluster) { build(:cluster) } + + subject { cluster } + + context 'when cluster has domain' do + let(:cluster) { build(:cluster, :with_domain) } + + it { is_expected.to be_valid } + end + + context 'when cluster has an invalid domain' do + let(:cluster) { build(:cluster, domain: 'not-valid-domain') } + + it 'should add an error on domain' do + expect(subject).not_to be_valid + expect(subject.errors[:domain].first).to eq('is not a fully qualified domain name') + end + end + + context 'when cluster does not have a domain' do + it { is_expected.to be_valid } + end + end end describe '.ancestor_clusters_for_clusterable' do diff --git a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb index a096627ee62..eef0327c9a6 100644 --- a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb +++ b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb @@ -129,12 +129,12 @@ RSpec.shared_examples 'an editable merge request' do expect(merge_request.merge_params['force_remove_source_branch']).to be_truthy visit edit_project_merge_request_path(target_project, merge_request) - uncheck 'Remove source branch when merge request is accepted' + uncheck 'Delete source branch when merge request is accepted' click_button 'Save changes' expect(page).to have_unchecked_field 'remove-source-branch-input' - expect(page).to have_content 'Remove source branch' + expect(page).to have_content 'Delete source branch' end end end diff --git a/yarn.lock b/yarn.lock index 1486f6f8642..bb948ad703c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -64,10 +64,10 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-create-class-features-plugin@^7.2.3": - version "7.2.3" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.2.3.tgz#f6e719abb90cb7f4a69591e35fd5eb89047c4a7c" - integrity sha512-xO/3Gn+2C7/eOUeb0VRnSP1+yvWHNxlpAot1eMhtoKDCN7POsyQP5excuT5UsV5daHxMWBeIIOeI5cmB8vMRgQ== +"@babel/helper-create-class-features-plugin@^7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.3.0.tgz#2b01a81b3adc2b1287f9ee193688ef8dc71e718f" + integrity sha512-DUsQNS2CGLZZ7I3W3fvh0YpPDd6BuWJlDl+qmZZpABZHza2ErE3LxtEzLJFHFC1ZwtlAXvHhbFYbtM5o5B0WBw== dependencies: "@babel/helper-function-name" "^7.1.0" "@babel/helper-member-expression-to-functions" "^7.0.0" @@ -238,12 +238,12 @@ "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-syntax-async-generators" "^7.2.0" -"@babel/plugin-proposal-class-properties@^7.2.3": - version "7.2.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.2.3.tgz#c9e1294363b346cff333007a92080f3203698461" - integrity sha512-FVuQngLoN2iDrpW7LmhPZ2sO4DJxf35FOcwidwB9Ru9tMvI5URthnkVHuG14IStV+TzkMTyLMoOUlSTtrdVwqw== +"@babel/plugin-proposal-class-properties@^7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.0.tgz#272636bc0fa19a0bc46e601ec78136a173ea36cd" + integrity sha512-wNHxLkEKTQ2ay0tnsam2z7fGZUi+05ziDJflEt3AZTP3oXLKHJp9HqhfroB/vdMvt3sda9fAbq7FsG8QPDrZBg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.2.3" + "@babel/helper-create-class-features-plugin" "^7.3.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-json-strings@^7.2.0": @@ -254,10 +254,10 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-json-strings" "^7.2.0" -"@babel/plugin-proposal-object-rest-spread@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.2.0.tgz#88f5fec3e7ad019014c97f7ee3c992f0adbf7fb8" - integrity sha512-1L5mWLSvR76XYUQJXkd/EEQgjq8HHRP6lQuZTTg0VA4tTGPpGemmCdAfQIz1rzEuWAm+ecP8PyyEm30jC1eQCg== +"@babel/plugin-proposal-object-rest-spread@^7.3.1": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.3.1.tgz#f69fb6a1ea6a4e1c503994a91d9cf76f3c4b36e8" + integrity sha512-Nmmv1+3LqxJu/V5jU9vJmxR/KIRWFk2qLHmbB56yRRRFhlaSuOVXscX3gUmhaKgUhzA3otOHVubbIEVYsZ0eZg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" @@ -270,12 +270,12 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" -"@babel/plugin-proposal-private-methods@^7.2.3": - version "7.2.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.2.3.tgz#aff0f5436df2c4365938c0309d551984e42c290c" - integrity sha512-jehrt1/TuLdLeBAVEv1VmTCNJcvSj+5Ozp7l21DN19Ylo0ATxpZ5bDk8i4WS9Ngvdgk/YTcqJCTp3uY2lwQoxw== +"@babel/plugin-proposal-private-methods@^7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.3.0.tgz#da373257a66525cb76544c37ab2ce4c611568841" + integrity sha512-j6luy/F0MX6kd71e9hz97my2tBXTa+czAz+sscJVCRmjB9e9g2D4JN+tyfcwMCXUM2afj/tYCjzNaxwWJ4SdYg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.2.3" + "@babel/helper-create-class-features-plugin" "^7.3.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex@^7.2.0": @@ -467,6 +467,13 @@ "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-named-capturing-groups-regex@^7.3.0": + version "7.3.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.3.0.tgz#140b52985b2d6ef0cb092ef3b29502b990f9cd50" + integrity sha512-NxIoNVhk9ZxS+9lSoAQ/LM0V2UEvARLttEHUrRDGKFaAxOYQcrkN/nLRE+BbbicCAvZPl7wMP0X60HsHE5DtQw== + dependencies: + regexp-tree "^0.1.0" + "@babel/plugin-transform-new-target@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz#ae8fbd89517fa7892d20e6564e641e8770c3aa4a" @@ -544,19 +551,20 @@ "@babel/helper-regex" "^7.0.0" regexpu-core "^4.1.3" -"@babel/preset-env@^7.2.3": - version "7.2.3" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.2.3.tgz#948c8df4d4609c99c7e0130169f052ea6a7a8933" - integrity sha512-AuHzW7a9rbv5WXmvGaPX7wADxFkZIqKlbBh1dmZUQp4iwiPpkE/Qnrji6SC4UQCQzvWY/cpHET29eUhXS9cLPw== +"@babel/preset-env@^7.3.1": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.3.1.tgz#389e8ca6b17ae67aaf9a2111665030be923515db" + integrity sha512-FHKrD6Dxf30e8xgHQO0zJZpUPfVZg+Xwgz5/RdSWCbza9QLNk4Qbp40ctRoqDxml3O8RMzB1DU55SXeDG6PqHQ== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-async-generator-functions" "^7.2.0" "@babel/plugin-proposal-json-strings" "^7.2.0" - "@babel/plugin-proposal-object-rest-spread" "^7.2.0" + "@babel/plugin-proposal-object-rest-spread" "^7.3.1" "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" "@babel/plugin-proposal-unicode-property-regex" "^7.2.0" "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" "@babel/plugin-transform-arrow-functions" "^7.2.0" @@ -576,6 +584,7 @@ "@babel/plugin-transform-modules-commonjs" "^7.2.0" "@babel/plugin-transform-modules-systemjs" "^7.2.0" "@babel/plugin-transform-modules-umd" "^7.2.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.3.0" "@babel/plugin-transform-new-target" "^7.0.0" "@babel/plugin-transform-object-super" "^7.2.0" "@babel/plugin-transform-parameters" "^7.2.0" @@ -2179,6 +2188,16 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-table3@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" + cli-width@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" @@ -2268,6 +2287,11 @@ colors@^1.1.0: resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= +colors@^1.1.2: + version "1.3.3" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" + integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== + combine-lists@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/combine-lists/-/combine-lists-1.0.1.tgz#458c07e09e0d900fc28b70a3fec2dacd1d2cb7f6" @@ -7881,10 +7905,10 @@ prettier@1.13.7: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281" integrity sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w== -prettier@1.15.3: - version "1.15.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.3.tgz#1feaac5bdd181237b54dbe65d874e02a1472786a" - integrity sha512-gAU9AGAPMaKb3NNSUUuhhFAS7SCO4ALTN4nRIn6PJ075Qd28Yn2Ig2ahEJWdJwJmlEBTUfC7mMUSFy8MwsOCfg== +prettier@1.16.1: + version "1.16.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.1.tgz#534c2c9d7853f8845e5e078384e71973bd74089f" + integrity sha512-XXUITwIkGb3CPJ2hforHah/zTINRyie5006Jd2HKy2qz7snEJXl0KLfsJZW/wst9g6R2rFvqba3VpNYdu1hDcA== pretty-format@^23.6.0: version "23.6.0" @@ -8286,6 +8310,15 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp-tree@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.0.tgz#a56ad7746097888ea16457479029ec9345b96ab0" + integrity sha512-rHQv+tzu+0l3KS/ERabas1yK49ahNVxuH40WcPg53CzP5p8TgmmyBgHELLyJcvjhTD0e5ahSY6C76LbEVtr7cg== + dependencies: + cli-table3 "^0.5.0" + colors "^1.1.2" + yargs "^10.0.3" + regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" @@ -10449,6 +10482,13 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" + integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== + dependencies: + camelcase "^4.1.0" + yargs-parser@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" @@ -10474,6 +10514,24 @@ yargs@12.0.2: y18n "^3.2.1 || ^4.0.0" yargs-parser "^10.1.0" +yargs@^10.0.3: + version "10.1.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" + integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^8.1.0" + yargs@^11.0.0: version "11.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" |