Commit 9ad5803b authored by Stan Hu's avatar Stan Hu

Merge branch 'ce-to-ee-2018-10-16' into 'master'

CE upstream - 2018-10-16 18:21 UTC

Closes gitlab-ce#52487

See merge request gitlab-org/gitlab-ee!7955
parents bbcacef1 a4411a75
<script>
import $ from 'jquery';
import IssueCardWeight from 'ee/boards/components/issue_card_weight.vue';
import Icon from '~/vue_shared/components/icon.vue';
import IssueCardWeight from 'ee/boards/components/issue_card_weight.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import eventHub from '../eventhub';
import tooltip from '../../vue_shared/directives/tooltip';
......@@ -10,8 +10,8 @@
export default {
components: {
UserAvatarLink,
IssueCardWeight,
Icon,
IssueCardWeight,
},
directives: {
tooltip,
......
import Visibility from 'visibilityjs';
import Vue from 'vue';
import PersistentUserCallout from '../persistent_user_callout';
import initDismissableCallout from '~/dismissable_callout';
import { s__, sprintf } from '../locale';
import Flash from '../flash';
import Poll from '../lib/utils/poll';
......@@ -62,7 +62,7 @@ export default class Clusters {
this.showTokenButton = document.querySelector('.js-show-cluster-token');
this.tokenField = document.querySelector('.js-cluster-token');
Clusters.initDismissableCallout();
initDismissableCallout('.js-cluster-security-warning');
initSettingsPanels();
setupToggleButtons(document.querySelector('.js-cluster-enable-toggle-area'));
this.initApplications();
......@@ -105,12 +105,6 @@ export default class Clusters {
});
}
static initDismissableCallout() {
const callout = document.querySelector('.js-cluster-security-warning');
if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
}
addListeners() {
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
eventHub.$on('installApplication', this.installApplication);
......
import createFlash from '~/flash';
import { __ } from '~/locale';
import setupToggleButtons from '~/toggle_buttons';
import PersistentUserCallout from '../persistent_user_callout';
import initDismissableCallout from '~/dismissable_callout';
import ClustersService from './services/clusters_service';
export default () => {
const clusterList = document.querySelector('.js-clusters-list');
const callout = document.querySelector('.gcp-signup-offer');
if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
initDismissableCallout('.gcp-signup-offer');
// The empty state won't have a clusterList
if (clusterList) {
......
import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import Flash from '~/flash';
export default function initDismissableCallout(alertSelector) {
const alertEl = document.querySelector(alertSelector);
if (!alertEl) {
return;
}
const closeButtonEl = alertEl.getElementsByClassName('close')[0];
const { dismissEndpoint, featureId } = closeButtonEl.dataset;
closeButtonEl.addEventListener('click', () => {
axios
.post(dismissEndpoint, {
feature_name: featureId,
})
.then(() => {
$(alertEl).alert('close');
})
.catch(() => {
Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.'));
});
});
}
......@@ -13,6 +13,7 @@ export default {
},
[types.SET_SELECTED_TEMPLATE_TYPE](state, type) {
state.selectedTemplateType = type;
state.templates = [];
},
[types.SET_UPDATE_SUCCESS](state, success) {
state.updateSuccess = success;
......
......@@ -53,10 +53,7 @@ export const slugify = str => str.trim().toLowerCase();
* @param {String} str
* @returns {String}
*/
export const slugifyWithHyphens = str => {
const regex = new RegExp(/\s+/, 'g');
return str.toLowerCase().replace(regex, '-');
};
export const slugifyWithHyphens = str => str.toLowerCase().replace(/\s+/g, '-');
/**
* Truncates given text
......
import initDismissableCallout from '~/dismissable_callout';
import initGkeDropdowns from '~/projects/gke_cluster_dropdowns';
import PersistentUserCallout from '../../persistent_user_callout';
import Project from './project';
import ShortcutsNavigation from '../../behaviors/shortcuts/shortcuts_navigation';
......@@ -12,9 +12,7 @@ document.addEventListener('DOMContentLoaded', () => {
];
if (newClusterViews.indexOf(page) > -1) {
const callout = document.querySelector('.gcp-signup-offer');
if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
initDismissableCallout('.gcp-signup-offer');
initGkeDropdowns();
}
......
// if the "projects dashboard" is a user's default dashboard, when they visit the
// instance root index, the dashboard will be served by the root controller instead
// of a dashboard controller. The root index redirects for all other default dashboards.
import '../dashboard/projects/index';
import axios from './lib/utils/axios_utils';
import { __ } from './locale';
import Flash from './flash';
export default class PersistentUserCallout {
constructor(container) {
const { dismissEndpoint, featureId } = container.dataset;
this.container = container;
this.dismissEndpoint = dismissEndpoint;
this.featureId = featureId;
this.init();
}
init() {
const closeButton = this.container.querySelector('.js-close');
closeButton.addEventListener('click', event => this.dismiss(event));
}
dismiss(event) {
event.preventDefault();
axios
.post(this.dismissEndpoint, {
feature_name: this.featureId,
})
.then(() => {
this.container.remove();
})
.catch(() => {
Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.'));
});
}
}
......@@ -269,11 +269,12 @@ export default {
:key="deployment.id"
:deployment="deployment"
/>
<grouped-test-reports-app
v-if="mr.testResultsPath"
class="js-reports-container"
:endpoint="mr.testResultsPath"
/>
<div class="mr-section-container">
<grouped-test-reports-app
v-if="mr.testResultsPath"
:endpoint="mr.testResultsPath"
/>
<div class="mr-widget-section">
<component
:is="componentName"
......
......@@ -1013,6 +1013,7 @@
.with-performance-bar & {
top: 135px;
max-height: calc(100vh - 135px);
}
}
......
......@@ -201,7 +201,6 @@
.mr-widget-icon {
font-size: 22px;
margin-right: $gl-btn-padding;
}
.ci-status-icon svg {
......
......@@ -12,7 +12,9 @@ class ApplicationController < ActionController::Base
include WorkhorseHelper
include EnforcesTwoFactorAuthentication
include WithPerformanceBar
include InvalidUTF8ErrorHandler
# this can be removed after switching to rails 5
# https://gitlab.com/gitlab-org/gitlab-ce/issues/51908
include InvalidUTF8ErrorHandler unless Gitlab.rails5?
before_action :authenticate_sessionless_user!
before_action :authenticate_user!
......
......@@ -9,7 +9,7 @@ class Projects::BuildArtifactsController < Projects::ApplicationController
before_action :validate_artifacts!, except: [:download]
def download
redirect_to download_project_job_artifacts_path(project, job)
redirect_to download_project_job_artifacts_path(project, job, params: request.query_parameters)
end
def browse
......
......@@ -21,29 +21,6 @@ module DashboardHelper
links.any? { |link| dashboard_nav_link?(link) }
end
def controller_action_to_child_dashboards(controller = controller_name, action = action_name)
case "#{controller}##{action}"
when 'projects#index', 'root#index', 'projects#starred', 'projects#trending'
%w(projects stars)
when 'dashboard#activity'
%w(starred_project_activity project_activity)
when 'groups#index'
%w(groups)
when 'todos#index'
%w(todos)
when 'dashboard#issues'
%w(issues)
when 'dashboard#merge_requests'
%w(merge_requests)
else
[]
end
end
def user_default_dashboard?(user = current_user)
controller_action_to_child_dashboards.any? {|dashboard| dashboard == user.dashboard }
end
private
def get_dashboard_nav_links
......
......@@ -120,6 +120,7 @@ class Notify < BaseMailer
add_unsubscription_headers_and_links
headers["X-GitLab-#{model.class.name}-ID"] = model.id
headers["X-GitLab-#{model.class.name}-IID"] = model.iid if model.respond_to?(:iid)
headers['X-GitLab-Reply-Key'] = reply_key
@reason = headers['X-GitLab-NotificationReason']
......
......@@ -52,8 +52,11 @@ class Project < ActiveRecord::Base
attachments: 2
}.freeze
# Valids ports to import from
VALID_IMPORT_PORTS = [22, 80, 443].freeze
VALID_IMPORT_PORTS = [80, 443].freeze
VALID_IMPORT_PROTOCOLS = %w(http https git).freeze
VALID_MIRROR_PORTS = [22, 80, 443].freeze
VALID_MIRROR_PROTOCOLS = %w(http https ssh git).freeze
cache_markdown_field :description, pipeline: :description
......@@ -310,10 +313,10 @@ class Project < ActiveRecord::Base
validates :namespace, presence: true
validates :name, uniqueness: { scope: :namespace_id }
validates :import_url, url: { protocols: %w(http https ssh git),
validates :import_url, url: { protocols: ->(project) { project.persisted? ? VALID_MIRROR_PROTOCOLS : VALID_IMPORT_PROTOCOLS },
ports: ->(project) { project.persisted? ? VALID_MIRROR_PORTS : VALID_IMPORT_PORTS },
allow_localhost: false,
enforce_user: true,
ports: VALID_IMPORT_PORTS }, if: [:external_import?, :import_url_changed?]
enforce_user: true }, if: [:external_import?, :import_url_changed?]
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
validate :check_repository_path_availability, on: :update, if: ->(project) { project.renamed? }
......
......@@ -6,8 +6,7 @@ class UserCallout < ActiveRecord::Base
enum feature_name: {
gke_cluster_integration: 1,
gcp_signup_offer: 2,
cluster_security_warning: 3,
gold_trial: 4
cluster_security_warning: 3
}
validates :user, presence: true
......
......@@ -4,9 +4,6 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
= content_for :above_breadcrumbs_content do
= render_if_exists "shared/gold_trial_callout"
- page_title "Activity"
- header_title "Activity", activity_dashboard_path
......
......@@ -3,9 +3,6 @@
- header_title "Groups", dashboard_groups_path
= render 'dashboard/groups_head'
= content_for :above_breadcrumbs_content do
= render_if_exists "shared/gold_trial_callout"
- if params[:filter].blank? && @groups.empty?
= render 'shared/groups/empty_state'
- else
......
......@@ -4,9 +4,6 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{current_user.name} issues")
= content_for :above_breadcrumbs_content do
= render_if_exists "shared/gold_trial_callout"
.top-area
= render 'shared/issuable/nav', type: :issues, display_count: !@no_filters_set
.nav-controls
......
......@@ -2,9 +2,6 @@
- page_title _("Merge Requests")
- @breadcrumb_link = merge_requests_dashboard_path(assignee_id: current_user.id)
= content_for :above_breadcrumbs_content do
= render_if_exists "shared/gold_trial_callout"
.top-area
= render 'shared/issuable/nav', type: :merge_requests, display_count: !@no_filters_set
.nav-controls
......
......@@ -4,9 +4,6 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
= content_for :above_breadcrumbs_content do
= render_if_exists "shared/gold_trial_callout"
- page_title "Projects"
- header_title "Projects", dashboard_projects_path
......
......@@ -4,9 +4,6 @@
- page_title "Starred Projects"
- header_title "Projects", dashboard_projects_path
= content_for :above_breadcrumbs_content do
= render_if_exists "shared/gold_trial_callout"
%div{ class: container_class }
= render "projects/last_push"
= render 'dashboard/projects_head'
......
......@@ -2,9 +2,6 @@
- page_title "Todos"
- header_title "Todos", dashboard_todos_path
= content_for :above_breadcrumbs_content do
= render_if_exists "shared/gold_trial_callout"
- if current_user.todos.any?
.top-area
%ul.nav-links.mobile-separator.nav.nav-tabs
......
......@@ -24,7 +24,7 @@
%p.gl-field-hint.text-secondary Minimum length is #{@minimum_password_length} characters
- if Gitlab::CurrentSettings.current_application_settings.enforce_terms?
.form-group
= check_box_tag :terms_opt_in, '1', false, required: true
= check_box_tag :terms_opt_in, '1', false, required: true, class: 'qa-new-user-accept-terms'
= label_tag :terms_opt_in do
- terms_link = link_to s_("I accept the|Terms of Service and Privacy Policy"), terms_path, target: "_blank"
- accept_terms_label = _("I accept the %{terms_link}") % { terms_link: terms_link }
......
......@@ -2,9 +2,6 @@
- page_title _("Groups")
- header_title _("Groups"), dashboard_groups_path
= content_for :above_breadcrumbs_content do
= render_if_exists "shared/gold_trial_callout"
- if current_user
= render 'dashboard/groups_head'
- else
......
......@@ -2,9 +2,6 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
= content_for :above_breadcrumbs_content do
= render_if_exists "shared/gold_trial_callout"
- if current_user
= render 'dashboard/projects_head'
- else
......
......@@ -2,9 +2,6 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
= content_for :above_breadcrumbs_content do
= render_if_exists "shared/gold_trial_callout"
- if current_user
= render 'dashboard/projects_head'
- else
......
......@@ -2,9 +2,6 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
= content_for :above_breadcrumbs_content do
= render_if_exists "shared/gold_trial_callout"
- if current_user
= render 'dashboard/projects_head'
- else
......
- container = @no_breadcrumb_container ? 'container-fluid' : container_class
- hide_top_links = @hide_top_links || false
= yield :above_breadcrumbs_content
%nav.breadcrumbs{ role: "navigation", class: [container, @content_class] }
.breadcrumbs-container
- if defined?(@left_sidebar)
......
......@@ -9,7 +9,7 @@
= s_("ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details")
- if show_cluster_security_warning?
.js-cluster-security-warning.alert.alert-block.alert-dismissable.bs-callout.bs-callout-warning{ data: { feature_id: UserCalloutsHelper::CLUSTER_SECURITY_WARNING, dismiss_endpoint: user_callouts_path } }
%button.close.js-close{ type: "button" } &times;
.js-cluster-security-warning.alert.alert-block.alert-dismissable.bs-callout.bs-callout-warning
%button.close{ type: "button", data: { feature_id: UserCalloutsHelper::CLUSTER_SECURITY_WARNING, dismiss_endpoint: user_callouts_path } } &times;
= s_("ClusterIntegration|The default cluster configuration grants access to many functionalities needed to successfully build and deploy a containerised application.")
= link_to s_("More information"), help_page_path('user/project/clusters/index.md', anchor: 'security-implications')
- link = link_to(s_('ClusterIntegration|sign up'), 'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral', target: '_blank', rel: 'noopener noreferrer')
.bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert', data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } }
%button.close.js-close{ type: "button" } &times;
.bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert' }
%button.close{ type: "button", data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } } &times;
.gcp-signup-offer--content
.gcp-signup-offer--icon.append-right-8
= sprite_icon("information", size: 16)
......
---
title: Removes extra border from test reports in the merge request widget
merge_request:
author:
type: fixed
---
title: Add IID headers to E-Mail notifications
merge_request: 22263
author:
type: changed
---
title: Use literal instead of constructor for creating regex
merge_request: 22367
author:
type: other
---
title: Does not allow a SSH URI when importing new projects
merge_request: 22309
author:
type: fixed
---
title: Fixed diff stats not showing when performance bar is enabled
merge_request:
author:
type: fixed
---
title: Clear fetched file templates when changing template type in Web IDE
merge_request:
author:
type: fixed
......@@ -33,7 +33,7 @@ provides solutions for all the stages of the DevOps lifecycle:
[plan](#plan), [create](#create), [verify](#verify), [package](#package),
[release](#release), [configure](#configure), [monitor](#monitor).
![DevOps Lifecycle](img/devops_lifecycle.png)
<img class="image-noshadow" src="img/devops_lifecycle.png" alt="DevOps Lifecycle">
### Plan
......
......@@ -197,9 +197,9 @@ stage has a job with a manual action.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21767) in GitLab 11.4.
When you do not want to run a job immediately, you can [delay the job to run after a certain period](yaml/README.md#delayed).
When you do not want to run a job immediately, you can [delay the job to run after a certain period](yaml/README.md#when-delayed).
This is especially useful for timed incremental rollout that new code is rolled out gradually.
For example, if you start rolling out new code and users do not experience trouble, GitLab automatically completes the deployment from 0% to 100%.
For example, if you start rolling out new code and users do not experience trouble, GitLab automatically completes the deployment from 0% to 100%.
Alternatively, if you start rolling out and you noticed that a few users experience trouble with the version,
you can stop the timed incremental rollout by canceling the pipeline, and [rolling](environments.md#rolling-back-changes) it back to the stable version.
......
......@@ -9,6 +9,7 @@ Most issues will have labels for at least one of the following:
- Type: ~"feature proposal", ~bug, ~customer, etc.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
- Team: ~"CI/CD", ~Plan, ~Manage, ~Quality, etc.
- Stage: ~"devops:plan", ~"devops:create", etc.
- Release Scoping: ~Deliverable, ~Stretch, ~"Next Patch Release"
- Priority: ~P1, ~P2, ~P3, ~P4
- Severity: ~S1, ~S2, ~S3, ~S4
......@@ -83,6 +84,39 @@ indicate if an issue needs backend work, frontend work, or both.
Team labels are always capitalized so that they show up as the first label for
any issue.
## Stage labels
Stage labels specify which [DevOps stage][devops-stages] the issue belongs to.
The current stage labels are:
- ~"devops:manage"
- ~"devops:plan"
- ~"devops:create"
- ~"devops:verify"
- ~"devops:package"
- ~"devops:release"
- ~"devops:configure"
- ~"devops:monitor"
- ~"devops:secure"
These labels should be mutually exclusive. If an issue belongs to multiple
stages, the most relevant should be used.
They differ from the [Team labels](#team-labels) because teams may work on
issues outside their stage.
Normally there is a 1:1 relationship between Stage labels and Team labels, but
any issue can be picked up by any team, depending on current priorities.
So, an issue labeled ~"devops:create" may be scheduled by the ~Plan team, for
example. In such cases, it's usual to include both team labels so each team can
be aware of the progress.
The Stage labels are used to generate the [direction pages][direction-pages] automatically.
[devops-stages]: https://about.gitlab.com/direction/#devops-stages
[direction-pages]: https://about.gitlab.com/direction/
## Release Scoping labels
Release Scoping labels help us clearly communicate expectations of the work for the
......
......@@ -75,7 +75,7 @@ Please see the table below for some examples:
| Latest stable version | Your version | Recommended upgrade path | Note |
| -------------- | ------------ | ------------------------ | ---------------- |
| 9.4.5 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.4.5` | `8.17.7` is the last version in version `8` |
| 10.1.4 | 8.13.4 | `8.13.4 -> 8.17.7 -> 9.5.8 -> 10.1.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9` |
| 10.1.4 | 8.13.4 | `8.13.4 -> 8.17.7 -> 9.5.10 -> 10.1.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9` |
| 11.3.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9`, `10.8.7` is the last version in version `10` |
More information about the release procedures can be found in our
......
......@@ -299,7 +299,6 @@ request to add new user to project through API will not be possible.
- **Projects**: view all projects within that group, add members to each project,
access each project's settings, and remove any project from the same screen.
- **Webhooks**: configure [webhooks](../project/integrations/webhooks.md) to your group.
- **Push rules**: configure [push rules](https://docs.gitlab.com/ee/push_rules/push_rules.html#push-rules) to your group. **[STARTER]**
- **Audit Events**: view [Audit Events](https://docs.gitlab.com/ee/administration/audit_events.html#audit-events)
for the group. **[STARTER ONLY]**
- **Pipelines quota**: keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
......@@ -166,7 +166,11 @@ minutes.
![Repository Languages bar](img/repository_languages.png)
Not all files are detected, among others; documentation,
vendored code, and most markup languages are excluded.
vendored code, and most markup languages are excluded. This behaviour can be
adjusted by overriding the default. For example, to enable `.proto` files to be
detected, add the following to `.gitattributes` in the root of your repository.
> *.proto linguist-detectable=true
## Compare
......
......@@ -270,6 +270,7 @@ export default {
<div class="mr-section-container">
<grouped-test-reports-app
v-if="mr.testResultsPath"
class="js-reports-container"
:endpoint="mr.testResultsPath"
/>
<div class="mr-widget-section">
......
......@@ -2,11 +2,21 @@ FROM ruby:2.4-stretch
LABEL maintainer "Grzegorz Bizon <grzegorz@gitlab.com>"
ENV DEBIAN_FRONTEND noninteractive
##
# Add support for stretch-backports
#
RUN echo "deb http://ftp.debian.org/debian stretch-backports main" >> /etc/apt/sources.list
##
# Update APT sources and install some dependencies
#
RUN sed -i "s/httpredir.debian.org/ftp.us.debian.org/" /etc/apt/sources.list
RUN apt-get update && apt-get install -y wget git unzip xvfb
RUN apt-get update && apt-get install -y wget unzip xvfb
##
# Install some packages from backports
#
RUN apt-get -y -t stretch-backports install git git-lfs
##
# Install Docker
......
......@@ -11,6 +11,7 @@ module QA
element :new_user_email_confirmation
element :new_user_password
element :new_user_register_button
element :new_user_accept_terms
end
def sign_up!(user)
......@@ -20,6 +21,8 @@ module QA
fill_element :new_user_email_confirmation, user.email
fill_element :new_user_password, user.password
check_element :new_user_accept_terms if has_element?(:new_user_accept_terms)
signed_in = with_retry do
click_element :new_user_register_button
......
......@@ -685,22 +685,34 @@ describe ApplicationController do
end
context 'html' do
subject { get :index, text: "hi \255" }
it 'renders 412' do
get :index, text: "hi \255"
if Gitlab.rails5?
expect { subject }.to raise_error(ActionController::BadRequest)
else
subject
expect(response).to have_gitlab_http_status(412)
expect(response).to render_template :precondition_failed
expect(response).to have_gitlab_http_status(412)
expect(response).to render_template :precondition_failed
end
end
end
context 'js' do
subject { get :index, text: "hi \255", format: :js }
it 'renders 412' do
get :index, text: "hi \255", format: :js
if Gitlab.rails5?
expect { subject }.to raise_error(ActionController::BadRequest)
else
subject
json_response = JSON.parse(response.body)
json_response = JSON.parse(response.body)
expect(response).to have_gitlab_http_status(412)
expect(json_response['error']).to eq('Invalid UTF-8')
expect(response).to have_gitlab_http_status(412)
expect(json_response['error']).to eq('Invalid UTF-8')
end
end
end
end
......
......@@ -423,7 +423,7 @@ describe 'Merge request > User sees merge widget', :js do
end
it 'shows test reports summary which includes the new failure' do
within(".mr-section-container") do
within(".js-reports-container") do
click_button 'Expand'
expect(page).to have_content('Test summary contained 1 failed test result out of 2 total tests')
......@@ -438,7 +438,7 @@ describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the new failure' do
it 'shows the test report detail' do
within(".mr-section-container") do
within(".js-reports-container") do
click_button 'Expand'
within(".js-report-section-container") do
......@@ -468,7 +468,7 @@ describe 'Merge request > User sees merge widget', :js do
end
it 'shows test reports summary which includes the existing failure' do
within(".mr-section-container") do
within(".js-reports-container") do
click_button 'Expand'
expect(page).to have_content('Test summary contained 1 failed test result out of 2 total tests')
......@@ -483,7 +483,7 @@ describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the existing failure' do
it 'shows test report detail of it' do
within(".mr-section-container") do
within(".js-reports-container") do
click_button 'Expand'
within(".js-report-section-container") do
......@@ -519,7 +519,7 @@ describe 'Merge request > User sees merge widget', :js do
end
it 'shows test reports summary which includes the resolved failure' do
within(".mr-section-container") do
within(".js-reports-container") do
click_button 'Expand'
expect(page).to have_content('Test summary contained 1 fixed test result out of 2 total tests')
......@@ -533,7 +533,7 @@ describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the resolved failure' do
it 'shows test report detail of it' do
within(".mr-section-container") do
within(".js-reports-container") do
click_button 'Expand'
within(".js-report-section-container") do
......
......@@ -49,6 +49,14 @@ describe('IDE file templates mutations', () => {
expect(state.selectedTemplateType).toBe('type');
});
it('clears templates', () => {
state.templates = ['test'];
mutations[types.SET_SELECTED_TEMPLATE_TYPE](state, 'type');
expect(state.templates).toEqual([]);
});
});
describe(types.SET_UPDATE_SUCCESS, () => {
......
......@@ -11,7 +11,7 @@ describe Gitlab::BitbucketImport::ProjectCreator do
owner: "asd",
full_name: 'Vim repo',
visibility_level: Gitlab::VisibilityLevel::PRIVATE,
clone_url: 'ssh://git@bitbucket.org/asd/vim.git',
clone_url: 'http://bitbucket.org/asd/vim.git',
has_wiki?: false)
end
......@@ -32,7 +32,7 @@ describe Gitlab::BitbucketImport::ProjectCreator do
project_creator = described_class.new(repo, 'vim', namespace, user, access_params)
project = project_creator.execute
expect(project.import_url).to eq("ssh://git@bitbucket.org/asd/vim.git")
expect(project.import_url).to eq("http://bitbucket.org/asd/vim.git")
expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
end
......@@ -256,54 +256,75 @@ describe Project do
end
it 'does not allow an invalid URI as import_url' do
project2 = build(:project, import_url: 'invalid://')
project = build(:project, import_url: 'invalid://')
expect(project2).not_to be_valid
expect(project).not_to be_valid
end
it 'does allow a SSH URI as import_url for persisted projects' do
project = create(:project)
project.import_url = 'ssh://test@gitlab.com/project.git'
expect(project).to be_valid
end
it 'does not allow a SSH URI as import_url for new projects' do
project = build(:project, import_url: 'ssh://test@gitlab.com/project.git')
expect(project).not_to be_valid
end
it 'does allow a valid URI as import_url' do
project2 = build(:project, import_url: 'ssh://test@gitlab.com/project.git')
project = build(:project, import_url: 'http://gitlab.com/project.git')
expect(project2).to be_valid
expect(project).to be_valid
end
it 'allows an empty URI' do
project2 = build(:project, import_url: '')
project = build(:project, import_url: '')
expect(project2).to be_valid
expect(project).to be_valid
end
it 'does not produce import data on an empty URI' do
project2 = build(:project, import_url: '')
project = build(:project, import_url: '')
expect(project2.import_data).to be_nil
expect(project.import_data).to be_nil
end
it 'does not produce import data on an invalid URI' do
project2 = build(:project, import_url: 'test://')
project = build(:project, import_url: 'test://')
expect(project2.import_data).to be_nil
expect(project.import_data).to be_nil
end
it "does not allow import_url pointing to localhost" do
project2 = build(:project, import_url: 'http://localhost:9000/t.git')
project = build(:project, import_url: 'http://localhost:9000/t.git')
expect(project).to be_invalid
expect(project.errors[:import_url].first).to include('Requests to localhost are not allowed')
end
it "does not allow import_url with invalid ports for new projects" do
project = build(:project, import_url: 'http://github.com:25/t.git')
expect(project2).to be_invalid
expect(project2.errors[:import_url].first).to include('Requests to localhost are not allowed')
expect(project).to be_invalid
expect(project.errors[:import_url].first).to include('Only allowed ports are 80, 443')
end
it "does not allow import_url with invalid ports" do
project2 = build(:project, import_url: 'http://github.com:25/t.git')
it "does not allow import_url with invalid ports for persisted projects" do
project = create(:project)
project.import_url = 'http://github.com:25/t.git'
expect(project2).to be_invalid
expect(project2.errors[:import_url].first).to include('Only allowed ports are 22, 80, 443')
expect(project).to be_invalid
expect(project.errors[:import_url].first).to include('Only allowed ports are 22, 80, 443')
end
it "does not allow import_url with invalid user" do
project2 = build(:project, import_url: 'http://$user:password@github.com/t.git')
project = build(:project, import_url: 'http://$user:password@github.com/t.git')
expect(project2).to be_invalid
expect(project2.errors[:import_url].first).to include('Username needs to start with an alphanumeric character')
expect(project).to be_invalid
expect(project.errors[:import_url].first).to include('Username needs to start with an alphanumeric character')
end
it 'creates import state when mirror gets enabled' do
......
......@@ -235,7 +235,7 @@ describe Projects::ImportService do
result = described_class.new(project, user).execute
expect(result[:status]).to eq :error
expect(result[:message]).to include('Only allowed ports are 22, 80, 443')
expect(result[:message]).to include('Only allowed ports are 80, 443')
end
end
......
......@@ -45,6 +45,20 @@ shared_examples 'an email that contains a header with author username' do
end
end
shared_examples 'an email with X-GitLab headers containing IDs' do
it 'has X-GitLab-*-ID header' do
is_expected.to have_header "X-GitLab-#{model.class.name}-ID", "#{model.id}"
end
it 'has X-GitLab-*-IID header if model has iid defined' do
if model.respond_to?(:iid)
is_expected.to have_header "X-GitLab-#{model.class.name}-IID", "#{model.iid}"
else
expect(subject.header["X-GitLab-#{model.class.name}-IID"]).to eq nil
end
end
end
shared_examples 'an email with X-GitLab headers containing project details' do
it 'has X-GitLab-Project headers' do
aggregate_failures do
......@@ -69,6 +83,7 @@ end
shared_examples 'a thread answer email with reply-by-email enabled' do
include_examples 'an email with X-GitLab headers containing project details'
include_examples 'an email with X-GitLab headers containing IDs'
it 'has the characteristics of a threaded reply' do
host = Gitlab.config.gitlab.host
......@@ -85,6 +100,7 @@ end
shared_examples 'an email starting a new thread with reply-by-email enabled' do
include_examples 'an email with X-GitLab headers containing project details'
include_examples 'an email with X-GitLab headers containing IDs'
include_examples 'a new thread email with reply-by-email enabled'
it 'includes "Reply to this email directly or <View it on GitLab>"' do
......@@ -109,6 +125,7 @@ end
shared_examples 'an answer to an existing thread with reply-by-email enabled' do
include_examples 'an email with X-GitLab headers containing project details'
include_examples 'an email with X-GitLab headers containing IDs'
include_examples 'a thread answer email with reply-by-email enabled'
context 'when reply-by-email is enabled with incoming address with %{key}' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment