summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml23
-rw-r--r--app/assets/javascripts/diffs/store/utils.js10
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue7
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue6
-rw-r--r--app/assets/javascripts/notes/stores/mutations.js7
-rw-r--r--app/assets/javascripts/notes/stores/utils.js4
-rw-r--r--app/assets/javascripts/pages/groups/clusters/edit/index.js (renamed from app/assets/javascripts/pages/groups/clusters/update/index.js)0
-rw-r--r--app/assets/javascripts/pages/projects/clusters/edit/index.js (renamed from app/assets/javascripts/pages/projects/clusters/update/index.js)0
-rw-r--r--app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue10
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue4
-rw-r--r--app/models/appearance.rb6
-rw-r--r--app/models/clusters/cluster.rb3
-rw-r--r--app/services/delete_branch_service.rb2
-rw-r--r--app/views/layouts/nav/sidebar/_profile.html.haml2
-rw-r--r--app/views/projects/buttons/_notifications.html.haml4
-rw-r--r--app/views/projects/protected_branches/shared/_protected_branch.html.haml2
-rw-r--r--app/views/sent_notifications/unsubscribe.html.haml13
-rw-r--r--app/views/shared/issuable/form/_merge_params.html.haml2
-rw-r--r--changelogs/unreleased/25569-changing-wording-to-delete-when-referring-to-removing-a-branch.yml5
-rw-r--r--changelogs/unreleased/52674-api-v4-projects-project_id-jobs-endpoint-hits-statement-timeout.yml5
-rw-r--r--changelogs/unreleased/56417-update-helm-to-2-12-2.yml5
-rw-r--r--changelogs/unreleased/dm-trim-discussion-truncated-line-first-chars.yml5
-rw-r--r--changelogs/unreleased/fix-55956-oversized-dropdown-button-custom-notifications.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-app-views-sent_notifications.yml5
-rw-r--r--changelogs/unreleased/mg-fix-bad-cluster-update-entrypoint.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-9357.yml5
-rw-r--r--changelogs/unreleased/yoginth-avatar-on-settings-sidebar.yml5
-rw-r--r--config/initializers/kaminari_active_record_relation_methods_with_limit.rb41
-rw-r--r--db/migrate/20190114172110_add_domain_to_cluster.rb9
-rw-r--r--db/schema.rb1
-rw-r--r--doc/api/README.md8
-rw-r--r--doc/development/testing_guide/img/review_apps_cicd_architecture.pngbin0 -> 73240 bytes
-rw-r--r--doc/development/testing_guide/review_apps.md111
-rw-r--r--doc/gitlab-basics/start-using-git.md48
-rw-r--r--doc/install/installation.md2
-rw-r--r--doc/update/10.0-to-10.1.md2
-rw-r--r--doc/update/10.1-to-10.2.md2
-rw-r--r--doc/update/10.2-to-10.3.md2
-rw-r--r--doc/update/10.3-to-10.4.md2
-rw-r--r--doc/update/10.4-to-10.5.md2
-rw-r--r--doc/update/10.5-to-10.6.md2
-rw-r--r--doc/update/10.6-to-10.7.md2
-rw-r--r--doc/update/10.7-to-10.8.md2
-rw-r--r--doc/update/10.8-to-11.0.md2
-rw-r--r--doc/update/11.0-to-11.1.md2
-rw-r--r--doc/update/11.1-to-11.2.md2
-rw-r--r--doc/update/11.2-to-11.3.md2
-rw-r--r--doc/update/11.3-to-11.4.md2
-rw-r--r--doc/update/11.4-to-11.5.md2
-rw-r--r--doc/update/11.5-to-11.6.md2
-rw-r--r--doc/update/11.6-to-11.7.md2
-rw-r--r--doc/update/11.7-to-11.8.md2
-rw-r--r--doc/update/6.9-to-7.0.md2
-rw-r--r--doc/update/6.x-or-7.x-to-7.14.md2
-rw-r--r--doc/update/7.0-to-7.1.md2
-rw-r--r--doc/update/8.10-to-8.11.md2
-rw-r--r--doc/update/8.11-to-8.12.md2
-rw-r--r--doc/update/8.12-to-8.13.md2
-rw-r--r--doc/update/8.13-to-8.14.md2
-rw-r--r--doc/update/8.14-to-8.15.md2
-rw-r--r--doc/update/8.15-to-8.16.md2
-rw-r--r--doc/update/8.16-to-8.17.md2
-rw-r--r--doc/update/8.17-to-9.0.md2
-rw-r--r--doc/update/9.0-to-9.1.md2
-rw-r--r--doc/update/9.1-to-9.2.md2
-rw-r--r--doc/update/9.2-to-9.3.md2
-rw-r--r--doc/update/9.3-to-9.4.md2
-rw-r--r--doc/update/9.4-to-9.5.md2
-rw-r--r--doc/update/9.5-to-10.0.md2
-rw-r--r--doc/user/project/clusters/serverless/index.md6
-rw-r--r--doc/user/project/integrations/slack.md52
-rw-r--r--lib/api/helpers/pagination.rb17
-rw-r--r--lib/api/merge_requests.rb2
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml2
-rw-r--r--lib/gitlab/kubernetes/helm.rb2
-rw-r--r--locale/gitlab.pot29
-rw-r--r--package.json8
-rw-r--r--qa/qa/resource/user.rb14
-rw-r--r--qa/qa/runtime/user.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb2
-rw-r--r--qa/spec/resource/user_spec.rb118
-rw-r--r--spec/controllers/projects/branches_controller_spec.rb6
-rw-r--r--spec/factories/clusters/clusters.rb4
-rw-r--r--spec/features/merge_request/user_accepts_merge_request_spec.rb4
-rw-r--r--spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb10
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb2
-rw-r--r--spec/features/merge_requests/user_squashes_merge_request_spec.rb2
-rw-r--r--spec/features/protected_branches_spec.rb2
-rw-r--r--spec/javascripts/diffs/store/utils_spec.js9
-rw-r--r--spec/javascripts/notes/stores/mutation_spec.js16
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js14
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js20
-rw-r--r--spec/javascripts/vue_mr_widget/mr_widget_options_spec.js6
-rw-r--r--spec/lib/api/helpers/pagination_spec.rb97
-rw-r--r--spec/lib/gitlab/kubernetes/helm/pod_spec.rb2
-rw-r--r--spec/models/appearance_spec.rb7
-rw-r--r--spec/models/clusters/cluster_spec.rb27
-rw-r--r--spec/support/shared_examples/features/editable_merge_request_shared_examples.rb4
-rw-r--r--yarn.lock112
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
new file mode 100644
index 00000000000..87e472076f3
--- /dev/null
+++ b/doc/development/testing_guide/img/review_apps_cicd_architecture.png
Binary files differ
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"