summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémy Coutable <remy@rymai.me>2017-01-27 17:28:58 +0100
committerRémy Coutable <remy@rymai.me>2017-01-27 17:28:58 +0100
commit2621458c6f859ed388e8b28fec5303cdbff969f3 (patch)
treef3d9ff3d3af5637cc3bd719b687b19b30094510e
parent47c21b50f7ad0e26576b723ae206315359383e4c (diff)
parent6ccc4eb42a05d4ce8b75773723305bd82305dfec (diff)
downloadgitlab-ce-2621458c6f859ed388e8b28fec5303cdbff969f3.tar.gz
Merge remote-tracking branch 'ce/master' into rc/friday-ce-to-ee
Signed-off-by: Rémy Coutable <remy@rymai.me>
-rw-r--r--CONTRIBUTING.md8
-rw-r--r--app/assets/javascripts/diff.js.es66
-rw-r--r--app/assets/javascripts/droplab/droplab_ajax.js41
-rw-r--r--app/assets/javascripts/droplab/droplab_ajax_filter.js61
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_token_keys.js.es615
-rw-r--r--app/assets/javascripts/line_highlighter.js5
-rw-r--r--app/assets/javascripts/profile/profile.js.es61
-rw-r--r--app/assets/stylesheets/framework/avatar.scss2
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss3
-rw-r--r--app/assets/stylesheets/framework/filters.scss9
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss4
-rw-r--r--app/controllers/explore/projects_controller.rb1
-rw-r--r--app/controllers/projects/builds_controller.rb2
-rw-r--r--app/controllers/projects/refs_controller.rb6
-rw-r--r--app/models/repository.rb13
-rw-r--r--app/presenters/README.md6
-rw-r--r--app/services/projects/update_service.rb2
-rw-r--r--app/views/projects/wikis/git_access.html.haml7
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml4
-rw-r--r--changelogs/unreleased/26844-new-search-bar-performs-a-new-request-for-each-tag.yml4
-rw-r--r--changelogs/unreleased/27044-fix-explore-sorting-on-trending.yml4
-rw-r--r--changelogs/unreleased/27277-small-mini-pipeline-graph-glitch-upon-hover.yml4
-rw-r--r--changelogs/unreleased/add_project_update_hook.yml4
-rw-r--r--changelogs/unreleased/get-rid-of-water-from-notification_service_spec-to-make-it-DRY.yml4
-rw-r--r--changelogs/unreleased/issue_27211.yml4
-rw-r--r--changelogs/unreleased/revert-filter-assigned-to-me.yml4
-rw-r--r--changelogs/unreleased/sh-fix-annotated-tags-pointing-to-blob.yml4
-rw-r--r--config/database.yml.mysql8
-rw-r--r--doc/administration/auth/ldap.md11
-rw-r--r--doc/administration/repository_checks.md10
-rw-r--r--doc/ci/examples/README.md6
-rw-r--r--doc/ci/examples/deployment/composer-npm-deploy.md156
-rw-r--r--doc/ci/yaml/README.md2
-rw-r--r--doc/development/README.md1
-rw-r--r--doc/development/gemfile.md14
-rw-r--r--doc/gitlab-basics/add-image.md50
-rw-r--r--doc/install/database_mysql.md205
-rw-r--r--doc/system_hooks/system_hooks.md19
-rw-r--r--doc/update/8.15-to-8.16.md2
-rw-r--r--doc/user/profile/account/two_factor_authentication.md118
-rw-r--r--lib/gitlab/ci/trace_reader.rb1
-rw-r--r--lib/gitlab/view/presenter/base.rb2
-rw-r--r--lib/gitlab/view/presenter/delegated.rb4
-rw-r--r--spec/controllers/explore/projects_controller_spec.rb30
-rw-r--r--spec/factories/trending_project.rb6
-rw-r--r--spec/features/issues/filtered_search/dropdown_assignee_spec.rb34
-rw-r--r--spec/features/issues/filtered_search/dropdown_author_spec.rb18
-rw-r--r--spec/features/issues/filtered_search/dropdown_label_spec.rb17
-rw-r--r--spec/features/issues/filtered_search/dropdown_milestone_spec.rb17
-rw-r--r--spec/javascripts/filtered_search/filtered_search_token_keys_spec.js.es66
-rw-r--r--spec/lib/gitlab/ci/trace_reader_spec.rb16
-rw-r--r--spec/lib/gitlab/view/presenter/delegated_spec.rb14
-rw-r--r--spec/lib/gitlab/view/presenter/factory_spec.rb7
-rw-r--r--spec/lib/gitlab/view/presenter/simple_spec.rb15
-rw-r--r--spec/models/ability_spec.rb10
-rw-r--r--spec/models/ci/build_spec.rb2
-rw-r--r--spec/models/ci/pipeline_spec.rb8
-rw-r--r--spec/models/ci/runner_spec.rb7
-rw-r--r--spec/models/commit_range_spec.rb2
-rw-r--r--spec/models/commit_spec.rb14
-rw-r--r--spec/models/commit_status_spec.rb2
-rw-r--r--spec/models/compare_spec.rb2
-rw-r--r--spec/models/concerns/issuable_spec.rb6
-rw-r--r--spec/models/concerns/mentionable_spec.rb8
-rw-r--r--spec/models/concerns/milestoneish_spec.rb2
-rw-r--r--spec/models/concerns/project_features_compatibility_spec.rb2
-rw-r--r--spec/models/cycle_analytics/code_spec.rb2
-rw-r--r--spec/models/cycle_analytics/issue_spec.rb2
-rw-r--r--spec/models/cycle_analytics/plan_spec.rb2
-rw-r--r--spec/models/cycle_analytics/production_spec.rb2
-rw-r--r--spec/models/cycle_analytics/review_spec.rb2
-rw-r--r--spec/models/cycle_analytics/staging_spec.rb3
-rw-r--r--spec/models/cycle_analytics/test_spec.rb2
-rw-r--r--spec/models/deploy_keys_project_spec.rb4
-rw-r--r--spec/models/deployment_spec.rb2
-rw-r--r--spec/models/diff_note_spec.rb4
-rw-r--r--spec/models/environment_spec.rb4
-rw-r--r--spec/models/event_spec.rb6
-rw-r--r--spec/models/forked_project_link_spec.rb4
-rw-r--r--spec/models/global_milestone_spec.rb6
-rw-r--r--spec/models/group_milestone_spec.rb2
-rw-r--r--spec/models/guest_spec.rb6
-rw-r--r--spec/models/hooks/system_hook_spec.rb2
-rw-r--r--spec/models/hooks/web_hook_spec.rb2
-rw-r--r--spec/models/issue/metrics_spec.rb2
-rw-r--r--spec/models/issue_collection_spec.rb2
-rw-r--r--spec/models/issue_spec.rb18
-rw-r--r--spec/models/member_spec.rb2
-rw-r--r--spec/models/members/project_member_spec.rb8
-rw-r--r--spec/models/merge_request/metrics_spec.rb4
-rw-r--r--spec/models/milestone_spec.rb6
-rw-r--r--spec/models/namespace_spec.rb4
-rw-r--r--spec/models/network/graph_spec.rb2
-rw-r--r--spec/models/note_spec.rb12
-rw-r--r--spec/models/project_feature_spec.rb4
-rw-r--r--spec/models/project_group_link_spec.rb2
-rw-r--r--spec/models/project_label_spec.rb2
-rw-r--r--spec/models/project_services/asana_service_spec.rb2
-rw-r--r--spec/models/project_services/assembla_service_spec.rb2
-rw-r--r--spec/models/project_services/campfire_service_spec.rb2
-rw-r--r--spec/models/project_services/drone_ci_service_spec.rb2
-rw-r--r--spec/models/project_services/external_wiki_service_spec.rb2
-rw-r--r--spec/models/project_services/flowdock_service_spec.rb2
-rw-r--r--spec/models/project_services/gemnasium_service_spec.rb2
-rw-r--r--spec/models/project_services/gitlab_issue_tracker_service_spec.rb6
-rw-r--r--spec/models/project_services/hipchat_service_spec.rb6
-rw-r--r--spec/models/project_services/irker_service_spec.rb2
-rw-r--r--spec/models/project_services/jira_service_spec.rb12
-rw-r--r--spec/models/project_services/pipeline_email_service_spec.rb2
-rw-r--r--spec/models/project_services/pushover_service_spec.rb2
-rw-r--r--spec/models/project_team_spec.rb10
-rw-r--r--spec/models/repository_spec.rb26
-rw-r--r--spec/models/service_spec.rb16
-rw-r--r--spec/models/snippet_spec.rb6
-rw-r--r--spec/models/todo_spec.rb8
-rw-r--r--spec/models/tree_spec.rb2
-rw-r--r--spec/models/user_spec.rb6
-rw-r--r--spec/requests/api/branches_spec.rb2
-rw-r--r--spec/requests/api/builds_spec.rb2
-rw-r--r--spec/requests/api/commit_statuses_spec.rb2
-rw-r--r--spec/requests/api/commits_spec.rb2
-rw-r--r--spec/requests/api/files_spec.rb4
-rw-r--r--spec/requests/api/fork_spec.rb21
-rw-r--r--spec/requests/api/internal_spec.rb2
-rw-r--r--spec/requests/api/merge_requests_spec.rb16
-rw-r--r--spec/requests/api/pipelines_spec.rb2
-rw-r--r--spec/requests/api/projects_spec.rb1
-rw-r--r--spec/requests/api/repositories_spec.rb14
-rw-r--r--spec/requests/api/tags_spec.rb6
-rw-r--r--spec/requests/api/triggers_spec.rb2
-rw-r--r--spec/requests/ci/api/triggers_spec.rb6
-rw-r--r--spec/requests/git_http_spec.rb2
-rw-r--r--spec/requests/projects/artifacts_controller_spec.rb2
-rw-r--r--spec/requests/projects/cycle_analytics_events_spec.rb2
-rw-r--r--spec/services/notification_service_spec.rb315
-rw-r--r--spec/services/system_hooks_service_spec.rb2
-rw-r--r--spec/support/cycle_analytics_helpers/test_generation.rb2
-rw-r--r--spec/support/mentionable_shared_examples.rb2
-rw-r--r--spec/support/slack_mattermost_notifications_shared_examples.rb6
-rw-r--r--spec/views/ci/lints/show.html.haml_spec.rb2
140 files changed, 1112 insertions, 630 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1eaa32de27f..d404f1b91df 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -286,14 +286,6 @@ request is as follows:
1. For tests that use Capybara or PhantomJS, see this [article on how
to write reliable asynchronous tests](https://robots.thoughtbot.com/write-reliable-asynchronous-integration-tests-with-capybara).
-The **official merge window** is in the beginning of the month from the 1st to
-the 7th day of the month. This is the best time to submit an MR and get
-feedback fast. Before this time the GitLab Inc. team is still dealing with work
-that is created by the monthly release such as regressions requiring patch
-releases. After the 7th it is already getting closer to the release date of the
-next version. This means there is less time to fix the issues created by
-merging large new features.
-
Please keep the change in a single MR **as small as possible**. If you want to
contribute a large feature think very hard what the minimum viable change is.
Can you split the functionality? Can you only submit the backend/API code? Can
diff --git a/app/assets/javascripts/diff.js.es6 b/app/assets/javascripts/diff.js.es6
index 5e1a4c948aa..35a029194d0 100644
--- a/app/assets/javascripts/diff.js.es6
+++ b/app/assets/javascripts/diff.js.es6
@@ -1,5 +1,7 @@
/* eslint-disable class-methods-use-this */
+//= require lib/utils/url_utility */
+
(() => {
const UNFOLD_COUNT = 20;
@@ -104,11 +106,11 @@
}
highlighSelectedLine() {
+ const hash = gl.utils.getLocationHash();
const $diffFiles = $('.diff-file');
$diffFiles.find('.hll').removeClass('hll');
- if (window.location.hash !== '') {
- const hash = window.location.hash.replace('#', '');
+ if (hash) {
$diffFiles
.find(`tr#${hash}:not(.match) td, td#${hash}, td[data-line-code="${hash}"]`)
.addClass('hll');
diff --git a/app/assets/javascripts/droplab/droplab_ajax.js b/app/assets/javascripts/droplab/droplab_ajax.js
index f7fed0987a2..c290e1a8355 100644
--- a/app/assets/javascripts/droplab/droplab_ajax.js
+++ b/app/assets/javascripts/droplab/droplab_ajax.js
@@ -9,6 +9,7 @@ require('../window')(function(w){
w.droplabAjax = {
_loadUrlData: function _loadUrlData(url) {
+ var self = this;
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest;
xhr.open('GET', url, true);
@@ -16,6 +17,7 @@ require('../window')(function(w){
if(xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
var data = JSON.parse(xhr.responseText);
+ self.cache[url] = data;
return resolve(data);
} else {
return reject([xhr.responseText, xhr.status]);
@@ -26,8 +28,21 @@ require('../window')(function(w){
});
},
+ _loadData: function _loadData(data, config, self) {
+ if (config.loadingTemplate) {
+ var dataLoadingTemplate = self.hook.list.list.querySelector('[data-loading-template]');
+
+ if (dataLoadingTemplate) {
+ dataLoadingTemplate.outerHTML = self.listTemplate;
+ }
+ }
+
+ self.hook.list[config.method].call(self.hook.list, data);
+ },
+
init: function init(hook) {
var self = this;
+ self.cache = self.cache || {};
var config = hook.config.droplabAjax;
this.hook = hook;
@@ -50,22 +65,16 @@ require('../window')(function(w){
dynamicList.outerHTML = loadingTemplate.outerHTML;
}
- this._loadUrlData(config.endpoint)
- .then(function(d) {
- if (config.loadingTemplate) {
- var dataLoadingTemplate = self.hook.list.list.querySelector('[data-loading-template]');
-
- if (dataLoadingTemplate) {
- dataLoadingTemplate.outerHTML = self.listTemplate;
- }
- }
-
- if (!self.hook.list.hidden) {
- self.hook.list[config.method].call(self.hook.list, d);
- }
- }).catch(function(e) {
- throw new droplabAjaxException(e.message || e);
- });
+ if (self.cache[config.endpoint]) {
+ self._loadData(self.cache[config.endpoint], config, self);
+ } else {
+ this._loadUrlData(config.endpoint)
+ .then(function(d) {
+ self._loadData(d, config, self);
+ }).catch(function(e) {
+ throw new droplabAjaxException(e.message || e);
+ });
+ }
},
destroy: function() {
diff --git a/app/assets/javascripts/droplab/droplab_ajax_filter.js b/app/assets/javascripts/droplab/droplab_ajax_filter.js
index 86a08d0d01d..b63d73066cb 100644
--- a/app/assets/javascripts/droplab/droplab_ajax_filter.js
+++ b/app/assets/javascripts/droplab/droplab_ajax_filter.js
@@ -72,32 +72,22 @@ require('../window')(function(w){
var params = config.params || {};
params[config.searchKey] = searchValue;
var self = this;
- this._loadUrlData(config.endpoint + this.buildParams(params)).then(function(data) {
- if (config.loadingTemplate && self.hook.list.data === undefined ||
- self.hook.list.data.length === 0) {
- const dataLoadingTemplate = self.hook.list.list.querySelector('[data-loading-template]');
-
- if (dataLoadingTemplate) {
- dataLoadingTemplate.outerHTML = self.listTemplate;
- }
- }
-
- if (!self.destroyed) {
- var hookListChildren = self.hook.list.list.children;
- var onlyDynamicList = hookListChildren.length === 1 && hookListChildren[0].hasAttribute('data-dynamic');
-
- if (onlyDynamicList && data.length === 0) {
- self.hook.list.hide();
- }
-
- self.hook.list.setData.call(self.hook.list, data);
- }
- self.notLoading();
- self.hook.list.currentIndex = 0;
- });
+ self.cache = self.cache || {};
+ var url = config.endpoint + this.buildParams(params);
+ var urlCachedData = self.cache[url];
+
+ if (urlCachedData) {
+ self._loadData(urlCachedData, config, self);
+ } else {
+ this._loadUrlData(url)
+ .then(function(data) {
+ self._loadData(data, config, self);
+ });
+ }
},
_loadUrlData: function _loadUrlData(url) {
+ var self = this;
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest;
xhr.open('GET', url, true);
@@ -105,6 +95,7 @@ require('../window')(function(w){
if(xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
var data = JSON.parse(xhr.responseText);
+ self.cache[url] = data;
return resolve(data);
} else {
return reject([xhr.responseText, xhr.status]);
@@ -115,6 +106,30 @@ require('../window')(function(w){
});
},
+ _loadData: function _loadData(data, config, self) {
+ if (config.loadingTemplate && self.hook.list.data === undefined ||
+ self.hook.list.data.length === 0) {
+ const dataLoadingTemplate = self.hook.list.list.querySelector('[data-loading-template]');
+
+ if (dataLoadingTemplate) {
+ dataLoadingTemplate.outerHTML = self.listTemplate;
+ }
+ }
+
+ if (!self.destroyed) {
+ var hookListChildren = self.hook.list.list.children;
+ var onlyDynamicList = hookListChildren.length === 1 && hookListChildren[0].hasAttribute('data-dynamic');
+
+ if (onlyDynamicList && data.length === 0) {
+ self.hook.list.hide();
+ }
+
+ self.hook.list.setData.call(self.hook.list, data);
+ }
+ self.notLoading();
+ self.hook.list.currentIndex = 0;
+ },
+
buildParams: function(params) {
if (!params) return '';
var paramsArray = Object.keys(params).map(function(param) {
diff --git a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js.es6 b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js.es6
index 55484499325..dd15c3d427b 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js.es6
+++ b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js.es6
@@ -26,6 +26,15 @@
symbol: '',
}];
+ const alternativeTokenKeys = [{
+ key: 'label',
+ type: 'string',
+ param: 'name',
+ symbol: '~',
+ }];
+
+ const tokenKeysWithAlternative = tokenKeys.concat(alternativeTokenKeys);
+
const conditions = [{
url: 'assignee_id=0',
tokenKey: 'assignee',
@@ -57,6 +66,10 @@
return tokenKeys;
}
+ static getAlternatives() {
+ return alternativeTokenKeys;
+ }
+
static getConditions() {
return conditions;
}
@@ -70,7 +83,7 @@
}
static searchByKeyParam(keyParam) {
- return tokenKeys.find((tokenKey) => {
+ return tokenKeysWithAlternative.find((tokenKey) => {
let tokenKeyParam = tokenKey.key;
if (tokenKey.param) {
diff --git a/app/assets/javascripts/line_highlighter.js b/app/assets/javascripts/line_highlighter.js
index 4620715a521..2f147704c22 100644
--- a/app/assets/javascripts/line_highlighter.js
+++ b/app/assets/javascripts/line_highlighter.js
@@ -74,8 +74,9 @@
// If not done this way, the line number anchor will sometimes keep its
// active state even when the event is cancelled, resulting in an ugly border
// around the link and/or a persisted underline text decoration.
- return $('#blob-content-holder').on('click', 'a[data-line-number]', function(event) {
- return event.preventDefault();
+ $('#blob-content-holder').on('click', 'a[data-line-number]', function(event) {
+ event.preventDefault();
+ event.stopPropagation();
});
};
diff --git a/app/assets/javascripts/profile/profile.js.es6 b/app/assets/javascripts/profile/profile.js.es6
index 6dbaae25f2a..5aec9c813fe 100644
--- a/app/assets/javascripts/profile/profile.js.es6
+++ b/app/assets/javascripts/profile/profile.js.es6
@@ -36,6 +36,7 @@
}
onSubmitForm(e) {
+ e.preventDefault();
return this.saveForm();
}
diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss
index 8392b98f0a7..1d59700543c 100644
--- a/app/assets/stylesheets/framework/avatar.scss
+++ b/app/assets/stylesheets/framework/avatar.scss
@@ -37,6 +37,8 @@
display: inline-block;
margin-left: 4px;
margin-bottom: 2px;
+ flex-shrink: 0;
+ -webkit-flex-shrink: 0;
&.s16 { margin-right: 4px; }
&.s24 { margin-right: 4px; }
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 3a47d51936d..6ed5f8b2dda 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -125,7 +125,8 @@
top: 100%;
left: 0;
z-index: 9;
- width: 240px;
+ max-width: 280px;
+ min-width: 240px;
margin-top: 2px;
margin-bottom: 0;
font-size: 14px;
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index 4b05ec691a8..e3da467a27c 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -132,6 +132,11 @@
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
+
+ &> span {
+ white-space: normal;
+ word-break: break-all;
+ }
}
}
@@ -141,10 +146,6 @@
}
}
-.hint-dropdown {
- width: 250px;
-}
-
.filter-dropdown-loading {
padding: 8px 16px;
}
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 5190faad308..47dfc22d533 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -214,9 +214,9 @@
&:not(:last-child) {
&::after {
content: '';
- width: 8px;
+ width: 7px;
position: absolute;
- right: -8px;
+ right: -7px;
top: 10px;
border-bottom: 2px solid $border-color;
}
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index a62c6211372..26e17a7553e 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -22,6 +22,7 @@ class Explore::ProjectsController < Explore::ApplicationController
def trending
@projects = filter_projects(Project.trending)
+ @projects = @projects.sort(@sort = params[:sort])
@projects = @projects.page(params[:page])
respond_to do |format|
diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb
index 9b45ed6b6af..886934a3f67 100644
--- a/app/controllers/projects/builds_controller.rb
+++ b/app/controllers/projects/builds_controller.rb
@@ -94,7 +94,7 @@ class Projects::BuildsController < Projects::ApplicationController
private
def build
- @build ||= project.builds.find_by!(id: params[:id]).present(user: current_user)
+ @build ||= project.builds.find_by!(id: params[:id]).present(current_user: current_user)
end
def build_path(build)
diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb
index 825185ee2cf..adee9182a79 100644
--- a/app/controllers/projects/refs_controller.rb
+++ b/app/controllers/projects/refs_controller.rb
@@ -33,12 +33,6 @@ class Projects::RefsController < Projects::ApplicationController
redirect_to new_path
end
- format.js do
- @ref = params[:ref]
- define_tree_vars
- tree
- render "tree"
- end
end
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 4fbb1505a25..56ef3d65321 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1337,7 +1337,18 @@ class Repository
end
def tags_sorted_by_committed_date
- tags.sort_by { |tag| tag.dereferenced_target.committed_date }
+ tags.sort_by do |tag|
+ # Annotated tags can point to any object (e.g. a blob), but generally
+ # tags point to a commit. If we don't have a commit, then just default
+ # to putting the tag at the end of the list.
+ target = tag.dereferenced_target
+
+ if target
+ target.committed_date
+ else
+ Time.now
+ end
+ end
end
def keep_around_ref_name(sha)
diff --git a/app/presenters/README.md b/app/presenters/README.md
index 3edd63451e7..a4d592b54d6 100644
--- a/app/presenters/README.md
+++ b/app/presenters/README.md
@@ -113,7 +113,7 @@ detects the presenter based on the presented subject's class.
class Projects::LabelsController < Projects::ApplicationController
def edit
@label = Gitlab::View::Presenter::Factory
- .new(@label, user: current_user)
+ .new(@label, current_user: current_user)
.fabricate!
end
end
@@ -132,7 +132,7 @@ and then in the controller:
```ruby
class Projects::LabelsController < Projects::ApplicationController
def edit
- @label = @label.present(user: current_user)
+ @label = @label.present(current_user: current_user)
end
end
```
@@ -147,7 +147,7 @@ end
You can also present the model in the view:
```ruby
-- label = @label.present(current_user)
+- label = @label.present(current_user: current_user)
%div{ class: label.text_color }
= render partial: label, label: label
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index ad39e766bf3..a98affd4db9 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -33,6 +33,8 @@ module Projects
if project.update_attributes(params)
if project.previous_changes.include?('path')
project.rename_repo
+ else
+ system_hook_service.execute_hooks_for(project, :update)
end
success
diff --git a/app/views/projects/wikis/git_access.html.haml b/app/views/projects/wikis/git_access.html.haml
index e25d6a48573..fb0efd85dcd 100644
--- a/app/views/projects/wikis/git_access.html.haml
+++ b/app/views/projects/wikis/git_access.html.haml
@@ -17,6 +17,13 @@
%pre.dark
:preserve
gem install gollum
+ %p
+ It is recommended to install
+ %code github-markdown
+ so that GFM features render locally:
+ %pre.dark
+ :preserve
+ gem install github-markdown
%h3 Clone your wiki
%pre.dark
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 7c4f35bbe53..73dff66caf5 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -47,10 +47,6 @@
%li.filter-dropdown-item{ 'data-value' => 'none' }
%button.btn.btn-link
No Assignee
- - if current_user
- %li.filter-dropdown-item{ 'data-value' => current_user.to_reference }
- %button.btn.btn-link
- Assigned to me
%li.divider
%ul.filter-dropdown{ 'data-dynamic' => true, 'data-dropdown' => true }
%li.filter-dropdown-item
diff --git a/changelogs/unreleased/26844-new-search-bar-performs-a-new-request-for-each-tag.yml b/changelogs/unreleased/26844-new-search-bar-performs-a-new-request-for-each-tag.yml
new file mode 100644
index 00000000000..4678297cfd4
--- /dev/null
+++ b/changelogs/unreleased/26844-new-search-bar-performs-a-new-request-for-each-tag.yml
@@ -0,0 +1,4 @@
+---
+title: Add caching of droplab ajax requests
+merge_request: 8725
+author:
diff --git a/changelogs/unreleased/27044-fix-explore-sorting-on-trending.yml b/changelogs/unreleased/27044-fix-explore-sorting-on-trending.yml
new file mode 100644
index 00000000000..0f0a8940f72
--- /dev/null
+++ b/changelogs/unreleased/27044-fix-explore-sorting-on-trending.yml
@@ -0,0 +1,4 @@
+---
+title: Fix /explore sorting
+merge_request:
+author:
diff --git a/changelogs/unreleased/27277-small-mini-pipeline-graph-glitch-upon-hover.yml b/changelogs/unreleased/27277-small-mini-pipeline-graph-glitch-upon-hover.yml
new file mode 100644
index 00000000000..9456251025b
--- /dev/null
+++ b/changelogs/unreleased/27277-small-mini-pipeline-graph-glitch-upon-hover.yml
@@ -0,0 +1,4 @@
+---
+title: fixed small mini pipeline graph line glitch
+merge_request: 8804
+author:
diff --git a/changelogs/unreleased/add_project_update_hook.yml b/changelogs/unreleased/add_project_update_hook.yml
new file mode 100644
index 00000000000..915c9538843
--- /dev/null
+++ b/changelogs/unreleased/add_project_update_hook.yml
@@ -0,0 +1,4 @@
+---
+title: Add system hook for when a project is updated (other than rename/transfer)
+merge_request: 5711
+author: Tommy Beadle
diff --git a/changelogs/unreleased/get-rid-of-water-from-notification_service_spec-to-make-it-DRY.yml b/changelogs/unreleased/get-rid-of-water-from-notification_service_spec-to-make-it-DRY.yml
new file mode 100644
index 00000000000..f60417d185e
--- /dev/null
+++ b/changelogs/unreleased/get-rid-of-water-from-notification_service_spec-to-make-it-DRY.yml
@@ -0,0 +1,4 @@
+---
+title: Make notification_service spec DRYer by making test reusable
+merge_request:
+author: YarNayar
diff --git a/changelogs/unreleased/issue_27211.yml b/changelogs/unreleased/issue_27211.yml
new file mode 100644
index 00000000000..ad48fec5d85
--- /dev/null
+++ b/changelogs/unreleased/issue_27211.yml
@@ -0,0 +1,4 @@
+---
+title: Remove unused js response from refs controller
+merge_request:
+author:
diff --git a/changelogs/unreleased/revert-filter-assigned-to-me.yml b/changelogs/unreleased/revert-filter-assigned-to-me.yml
new file mode 100644
index 00000000000..37f9d2f5fc4
--- /dev/null
+++ b/changelogs/unreleased/revert-filter-assigned-to-me.yml
@@ -0,0 +1,4 @@
+---
+title: Revert 3f17f29a
+merge_request: 8785
+author:
diff --git a/changelogs/unreleased/sh-fix-annotated-tags-pointing-to-blob.yml b/changelogs/unreleased/sh-fix-annotated-tags-pointing-to-blob.yml
new file mode 100644
index 00000000000..ff2b38f21f2
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-annotated-tags-pointing-to-blob.yml
@@ -0,0 +1,4 @@
+---
+title: Fix Error 500 when repositories contain annotated tags pointing to blobs
+merge_request:
+author:
diff --git a/config/database.yml.mysql b/config/database.yml.mysql
index d9702870249..a33e40e8eb3 100644
--- a/config/database.yml.mysql
+++ b/config/database.yml.mysql
@@ -3,8 +3,8 @@
#
production:
adapter: mysql2
- encoding: utf8mb4
- collation: utf8mb4_general_ci
+ encoding: utf8
+ collation: utf8_general_ci
reconnect: false
database: gitlabhq_production
pool: 10
@@ -18,8 +18,8 @@ production:
#
development:
adapter: mysql2
- encoding: utf8mb4
- collation: utf8mb4_general_ci
+ encoding: utf8
+ collation: utf8_general_ci
reconnect: false
database: gitlabhq_development
pool: 5
diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md
index c16dc10b06f..d693d5b93ce 100644
--- a/doc/administration/auth/ldap.md
+++ b/doc/administration/auth/ldap.md
@@ -79,11 +79,15 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
#
# Example: 'Paris' or 'Acme, Ltd.'
label: 'LDAP'
-
+
+ # Example: 'ldap.mydomain.com'
host: '_your_ldap_server'
+ # This port is an example, it is sometimes different but it is always an integer and not a string
port: 389
uid: 'sAMAccountName'
method: 'plain' # "tls" or "ssl" or "plain"
+
+ # Examples: 'america\\momo' or 'CN=Gitlab Git,CN=Users,DC=mydomain,DC=com'
bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
password: '_the_password_of_the_bind_user'
@@ -115,7 +119,7 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
# Base where we can search for users
#
- # Ex. ou=People,dc=gitlab,dc=example
+ # Ex. 'ou=People,dc=gitlab,dc=example' or 'DC=mydomain,DC=com'
#
base: ''
@@ -126,6 +130,9 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
#
# Note: GitLab does not support omniauth-ldap's custom filter syntax.
#
+ # Below an example for get only specific users
+ # Example: '(&(objectclass=user)(|(samaccountname=momo)(samaccountname=toto)))'
+ #
user_filter: ''
# LDAP attributes that GitLab will use to create an account for the LDAP user.
diff --git a/doc/administration/repository_checks.md b/doc/administration/repository_checks.md
index bc2b1f20ed3..ee37ea49874 100644
--- a/doc/administration/repository_checks.md
+++ b/doc/administration/repository_checks.md
@@ -13,12 +13,12 @@ checks failed you can see their output on the admin log page under
## Periodic checks
-GitLab periodically runs a repository check on all project repositories and
-wiki repositories in order to detect data corruption problems. A
-project will be checked no more than once per week. If any projects
+When enabled, GitLab periodically runs a repository check on all project
+repositories and wiki repositories in order to detect data corruption problems.
+A project will be checked no more than once per month. If any projects
fail their repository checks all GitLab administrators will receive an email
-notification of the situation. This notification is sent out no more
-than once a day.
+notification of the situation. This notification is sent out once a week on
+Sunday, by default.
## Disabling periodic checks
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index ffc310ec8c7..5377bf9ee80 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -14,6 +14,12 @@ Apart from those, here is an collection of tutorials and guides on setting up yo
- [Test a Phoenix application](test-phoenix-application.md)
- [Using `dpl` as deployment tool](deployment/README.md)
- [Example project that shows how to use Review Apps](https://gitlab.com/gitlab-examples/review-apps-nginx/)
+- [Run PHP Composer & NPM scripts then deploy them to a staging server](deployment/composer-npm-deploy.md)
+- Help your favorite programming language and GitLab by sending a merge request
+ with a guide for that language.
+
+## Outside the documentation
+
- [Blog post about using GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
- [Repositories with examples for various languages](https://gitlab.com/groups/gitlab-examples)
- [The .gitlab-ci.yml file for GitLab itself](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml)
diff --git a/doc/ci/examples/deployment/composer-npm-deploy.md b/doc/ci/examples/deployment/composer-npm-deploy.md
new file mode 100644
index 00000000000..5334a73e1f5
--- /dev/null
+++ b/doc/ci/examples/deployment/composer-npm-deploy.md
@@ -0,0 +1,156 @@
+## Running Composer and NPM scripts with deployment via SCP
+
+This guide covers the building dependencies of a PHP project while compiling assets via an NPM script.
+
+While is possible to create your own image with custom PHP and Node JS versions, for brevity, we will use an existing [Docker image](https://hub.docker.com/r/tetraweb/php/) that contains both PHP and NodeJS installed.
+
+
+```yaml
+image: tetraweb/php
+```
+
+The next step is to install zip/unzip packages and make composer available. We will place these in the `before_script` section:
+
+```yaml
+before_script:
+ - apt-get update
+ - apt-get install zip unzip
+ - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+ - php composer-setup.php
+ - php -r "unlink('composer-setup.php');"
+```
+
+This will make sure we have all requirements ready. Next, we want to run `composer update` to fetch all PHP dependencies and `npm install` to load node packages, then run the `npm` script. We need to append them into `before_script` section:
+
+```yaml
+before_script:
+ # ...
+ - php composer.phar update
+ - npm install
+ - npm run deploy
+```
+
+In this particular case, the `npm deploy` script is a Gulp script that does the following:
+
+1. Compile CSS & JS
+2. Create sprites
+3. Copy various assets (images, fonts) around
+4. Replace some strings
+
+All these operations will put all files into a `build` folder, which is ready to be deployed to a live server.
+
+### How to transfer files to a live server?
+
+You have multiple options: rsync, scp, sftp and so on. For now, we will use scp.
+
+To make this work, you need to add a GitLab Secret Variable (accessible on _gitlab.example/your-project-name/variables_). That variable will be called `STAGING_PRIVATE_KEY` and it's the **private** ssh key of your server.
+
+#### Security tip
+
+Create a user that has access **only** to the folder that needs to be updated!
+
+After you create that variable, you need to make sure that key will be added to the docker container on run:
+
+```yaml
+before_script:
+ # - ....
+ - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
+ - mkdir -p ~/.ssh
+ - eval $(ssh-agent -s)
+ - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
+```
+
+In order, this means that:
+
+1. We check if the `ssh-agent` is available and we install it if it's not;
+2. We create the `~/.ssh` folder;
+3. We make sure we're running bash;
+4. We disable host checking (we don't ask for user accept when we first connect to a server; and since every build will equal a first connect, we kind of need this)
+
+And this is basically all you need in the `before_script` section.
+
+## How to deploy things?
+
+As we stated above, we need to deploy the `build` folder from the docker image to our server. To do so, we create a new job:
+
+```yaml
+stage_deploy:
+ artifacts:
+ paths:
+ - build/
+ only:
+ - dev
+ script:
+ - ssh-add <(echo "$STAGING_PRIVATE_KEY")
+ - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
+ - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
+ - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
+ - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"
+```
+
+### What's going on here?
+
+1. `only:dev` means that this build will run only when something is pushed to the `dev` branch. You can remove this block completely and have everything be ran on every push (but probably this is something you don't want)
+2. `ssh-add ...` we will add that private key you added on the web UI to the docker container
+3. We will connect via `ssh` and create a new `_tmp` folder
+4. We will connect via `scp` and upload the `build` folder (which was generated by a `npm` script) to our previously created `_tmp` folder
+5. We will connect again to `ssh` and move the `live` folder to an `_old` folder, then move `_tmp` to `live`.
+6. We connect to ssh and remove the `_old` folder
+
+What's the deal with the artifacts? We just tell GitLab CI to keep the `build` directory (later on, you can download that as needed).
+
+#### Why we do it this way?
+
+If you're using this only for stage server, you could do this in two steps:
+
+```yaml
+- ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/live/*"
+- scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/live
+```
+
+The problem is that there will be a small period of time when you won't have the app on your server.
+
+So we use so many steps because we want to make sure that at any given time we have a functional app in place.
+
+## Where to go next?
+
+Since this was a WordPress project, I gave real life code snippets. Some ideas you can pursuit:
+
+- Having a slightly different script for `master` branch will allow you to deploy to a production server from that branch and to a stage server from any other branches;
+- Instead of pushing it live, you can push it to WordPress official repo (with creating a SVN commit & stuff);
+- You could generate i18n text domains on the fly.
+
+---
+
+Our final `.gitlab-ci.yml` will look like this:
+
+```yaml
+image: tetraweb/php
+
+before_script:
+ - apt-get update
+ - apt-get install zip unzip
+ - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+ - php composer-setup.php
+ - php -r "unlink('composer-setup.php');"
+ - php composer.phar update
+ - npm install
+ - npm run deploy
+ - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
+ - mkdir -p ~/.ssh
+ - eval $(ssh-agent -s)
+ - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
+
+stage_deploy:
+ artifacts:
+ paths:
+ - build/
+ only:
+ - dev
+ script:
+ - ssh-add <(echo "$STAGING_PRIVATE_KEY")
+ - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
+ - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
+ - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
+ - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"
+``` \ No newline at end of file
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 75a0897eb15..f11257be5c3 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -86,7 +86,7 @@ used for time of the build. The configuration of this feature is covered in
### before_script
`before_script` is used to define the command that should be run before all
-builds, including deploy builds. This can be an array or a multi-line string.
+builds, including deploy builds, but after the restoration of artifacts. This can be an array or a multi-line string.
### after_script
diff --git a/doc/development/README.md b/doc/development/README.md
index 2cf93ea1be3..20c40dbc82f 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -18,6 +18,7 @@
- [Frontend guidelines](frontend.md)
- [SQL guidelines](sql.md) for working with SQL queries
- [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers
+- [`Gemfile` guidelines](gemfile.md)
## Process
diff --git a/doc/development/gemfile.md b/doc/development/gemfile.md
new file mode 100644
index 00000000000..ec9718cea71
--- /dev/null
+++ b/doc/development/gemfile.md
@@ -0,0 +1,14 @@
+# `Gemfile` guidelines
+
+When adding a new entry to `Gemfile` or upgrading an existing dependency pay
+attention to the following rules.
+
+## No gems fetched from git repositories
+
+We do not allow gems that are fetched from git repositories. All gems have
+to be available in the RubyGems index. We want to minimize external build
+dependencies and build times.
+
+## License compliance
+
+Refer to [licensing guidelines](licensing.md) for ensuring license compliance.
diff --git a/doc/gitlab-basics/add-image.md b/doc/gitlab-basics/add-image.md
index 476b48a217c..1a44123aa81 100644
--- a/doc/gitlab-basics/add-image.md
+++ b/doc/gitlab-basics/add-image.md
@@ -1,62 +1,56 @@
# How to add an image
-The following are the steps to add images to your repository in
-GitLab:
+Using your standard tool for copying files (e.g. Finder in Mac OS, or Explorer
+in Windows, or...), put the image file into the GitLab project. You can find the
+project as a regular folder in your files.
-Find the image that you’d like to add.
+Go to your [shell](command-line-commands.md), and move into the folder of your
+Gitlab project. This usually means running the following command until you get
+to the desired destination:
-In your computer files, find the GitLab project to which you'd like to add the image
-(you'll find it as a regular file). Click on every file until you find exactly where you'd
-like to add the image. There, paste the image.
-
-Go to your [shell](command-line-commands.md), and add the following commands:
-
-Add this command for every directory that you'd like to open:
```
-cd NAME-OF-FILE-YOU'D-LIKE-TO-OPEN
+cd NAME-OF-FOLDER-YOU'D-LIKE-TO-OPEN
```
-Create a new branch:
-```
-git checkout -b NAME-OF-BRANCH
-```
+Check if your image is actually present in the directory (if you are in Windows,
+use `dir` instead):
-Check if your image was correctly added to the directory:
```
ls
```
You should see the name of the image in the list shown.
-Move up the hierarchy through directories:
-```
-cd ../
-```
+Check the status:
-Check the status and you should see your image’s name in red:
```
git status
```
-Add your changes:
+Your image's name should appear in red, so `git` took notice of it! Now add it
+to the repository:
+
```
git add NAME-OF-YOUR-IMAGE
```
-Check the status and you should see your image’s name in green:
+Check the status again, your image's name should have turned green:
+
```
git status
```
-Add the commit:
+Commit:
+
```
-git commit -m “DESCRIBE COMMIT IN A FEW WORDS”
+git commit -m "DESCRIBE COMMIT IN A FEW WORDS"
```
-Now you can push (send) your changes (in the branch NAME-OF-BRANCH) to GitLab (the git remote named 'origin'):
+Now you can push (send) your changes (in the branch NAME-OF-BRANCH) to GitLab
+(the git remote named 'origin'):
+
```
git push origin NAME-OF-BRANCH
```
-Your image will be added to your branch in your repository in GitLab. Create a [Merge Request](add-merge-request.md)
-to integrate your changes to your project.
+Your image will be added to your branch in your repository in GitLab.
diff --git a/doc/install/database_mysql.md b/doc/install/database_mysql.md
index 322680f0cf4..65bfb0f7d6e 100644
--- a/doc/install/database_mysql.md
+++ b/doc/install/database_mysql.md
@@ -4,7 +4,7 @@
We do not recommend using MySQL due to various issues. For example, case [(in)sensitivity](https://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html) and [problems](https://bugs.mysql.com/bug.php?id=65830) that [suggested](https://bugs.mysql.com/bug.php?id=50909) [fixes](https://bugs.mysql.com/bug.php?id=65830) [have](https://bugs.mysql.com/bug.php?id=63164).
-## MySQL
+## Initial database setup
# Install the database packages
sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
@@ -32,8 +32,11 @@ We do not recommend using MySQL due to various issues. For example, case [(in)se
# If this fails, check your MySQL config files (e.g. `/etc/mysql/*.cnf`, `/etc/mysql/conf.d/*`) for the setting "innodb = off"
mysql> SET storage_engine=INNODB;
+ # If you have MySQL < 5.7.7 and want to enable utf8mb4 character set support with your GitLab install, you must set the following NOW:
+ mysql> SET GLOBAL innodb_file_per_table=1, innodb_file_format=Barracuda, innodb_large_prefix=1;
+
# Create the GitLab production database
- mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
+ mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_general_ci`;
# Grant the GitLab user necessary permissions on the database
mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE TEMPORARY TABLES, DROP, INDEX, ALTER, LOCK TABLES, REFERENCES ON `gitlabhq_production`.* TO 'git'@'localhost';
@@ -51,7 +54,203 @@ We do not recommend using MySQL due to various issues. For example, case [(in)se
# Quit the database session
mysql> \q
- # You are done installing the database and can go back to the rest of the installation.
+ # You are done installing the database for now and can go back to the rest of the installation.
+
+Please proceed to the rest of the installation before running through the utf8mb4 support section.
+
+
+### MySQL utf8mb4 support
+
+After installation or upgrade, remember to [convert any new tables](#convert) to `utf8mb4`/`utf8mb4_general_ci`.
+
+---
+
+GitLab 8.14 has introduced [a feature](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7420) requiring `utf8mb4` encoding to be supported in your GitLab MySQL Database, which is not the case if you have setup your database before GitLab 8.16.
+
+Follow the below instructions to ensure you use the most up to date requirements for your GitLab MySQL Database.
+
+**We are about to do the following:**
+- Ensure you can enable `utf8mb4` encoding and `utf8mb4_general_ci` collation for your GitLab DB, tables and data.
+- Convert your GitLab tables and data from `utf8`/`utf8_general_ci` to `utf8mb4`/`utf8mb4_general_ci`
+
+### Check for utf8mb4 support
+
+#### Check for InnoDB File-Per-Table Tablespaces
+
+We need to check, enable and maybe convert your existing GitLab DB tables to the [InnoDB File-Per-Table Tablespaces](http://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) as a prerequise for supporting **utfb8mb4 with long indexes** required by recent GitLab databases.
+
+ # Login to MySQL
+ mysql -u root -p
+
+ # Type the MySQL root password
+ mysql > use gitlabhq_production;
+
+ # Check your MySQL version is >= 5.5.3 (GitLab requires 5.5.14+)
+ mysql > SHOW VARIABLES LIKE 'version';
+ +---------------+-----------------+
+ | Variable_name | Value |
+ +---------------+-----------------+
+ | version | 5.5.53-0+deb8u1 |
+ +---------------+-----------------+
+
+ # Note where is your MySQL data dir for later:
+ mysql > select @@datadir;
+ +----------------+
+ | @@datadir |
+ +----------------+
+ | /var/lib/mysql |
+ +----------------+
+
+ # Note whether your MySQL server runs with innodb_file_per_table ON or OFF:
+ mysql> SELECT @@innodb_file_per_table;
+ +-------------------------+
+ | @@innodb_file_per_table |
+ +-------------------------+
+ | 1 |
+ +-------------------------+
+
+ # You can now quit the database session
+ mysql> \q
+
+> You need **MySQL 5.5.3 or later** to perform this update.
+
+Whatever the results of your checks above, we now need to check if your GitLab database has been created using [InnoDB File-Per-Table Tablespaces](http://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) (i.e. `innodb_file_per_table` was set to **1** at initial setup time).
+
+> Note: This setting is [enabled by default](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_file_per_table) since MySQL 5.6.6.
+
+ # Run this command with root privileges, replace the data dir if different:
+ sudo ls -lh /var/lib/mysql/gitlabhq_production/*.ibd | wc -l
+
+ # Run this command with root privileges, replace the data dir if different:
+ sudo ls -lh /var/lib/mysql/gitlabhq_production/*.frm | wc -l
+
+
+- **Case 1: a result > 0 for both commands**
+
+Congrats, your GitLab database uses the right InnoDB tablespace format.
+
+However, you must still ensure that any **future tables** created by GitLab will still use the right format:
+
+- If `SELECT @@innodb_file_per_table` returned **1** previously, your server is running correctly.
+> It's however a requirement to check *now* that this setting is indeed persisted in your [my.cnf](https://dev.mysql.com/doc/refman/5.7/en/tablespace-enabling.html) file!
+
+- If `SELECT @@innodb_file_per_table` returned **0** previously, your server is not running correctly.
+> [Enable innodb_file_per_table](https://dev.mysql.com/doc/refman/5.7/en/tablespace-enabling.html) by running in a MySQL session as root the command `SET GLOBAL innodb_file_per_table=1, innodb_file_format=Barracuda;` and persist the two settings in your [my.cnf](https://dev.mysql.com/doc/refman/5.7/en/tablespace-enabling.html) file
+
+Now, if you have a **different result** returned by the 2 commands above, it means you have a **mix of tables format** uses in your GitLab database. This can happen if your MySQL server had different values for `innodb_file_per_table` in its life and you updated GitLab at different moments with those inconsistent values. So keep reading.
+
+- **Case 2: a result equals to "0" OR not the same result for both commands**
+
+Unfortunately, none or only some of your GitLab database tables use the GitLab requirement of [InnoDB File-Per-Table Tablespaces](http://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html).
+
+Let's enable what we need on the running server:
+
+ # Login to MySQL
+ mysql -u root -p
+
+ # Type the MySQL root password
+
+ # Enable innodb_file_per_table and set innodb_file_format on the running server:
+ mysql > SET GLOBAL innodb_file_per_table=1, innodb_file_format=Barracuda;
+
+ # You can now quit the database session
+ mysql> \q
+
+> Now, **persist** [innodb_file_per_table](https://dev.mysql.com/doc/refman/5.6/en/tablespace-enabling.html) and [innodb_file_format](https://dev.mysql.com/doc/refman/5.6/en/innodb-file-format-enabling.html) in your `my.cnf` file.
+
+Ensure at this stage that your GitLab instance is indeed **stopped**.
+
+Now, let's convert all the GitLab database tables to the new tablespace format:
+
+ # Login to MySQL
+ mysql -u root -p
+
+ # Type the MySQL root password
+ mysql > use gitlabhq_production;
+
+ # Safety check: you should still have those values set as follow:
+ mysql> SELECT @@innodb_file_per_table, @@innodb_file_format;
+ +-------------------------+----------------------+
+ | @@innodb_file_per_table | @@innodb_file_format |
+ +-------------------------+----------------------+
+ | 1 | Barracuda |
+ +-------------------------+----------------------+
+
+ mysql > SELECT CONCAT('ALTER TABLE `', TABLE_NAME,'` ENGINE=InnoDB;') AS 'Copy & run these SQL statements:' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="gitlabhq_production" AND TABLE_TYPE="BASE TABLE";
+
+ # If previous query returned results, copy & run all shown SQL statements
+
+ # You can now quit the database session
+ mysql> \q
+
+---
+
+#### Check for proper InnoDB File Format, Row Format, Large Prefix and tables conversion
+
+We need to check, enable and probably convert your existing GitLab DB tables to use the [Barracuda InnoDB file format](https://dev.mysql.com/doc/refman/5.6/en/innodb-file-format.html), the [DYNAMIC row format](https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_dynamic_row_format) and [innodb_large_prefix](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix) as a second prerequisite for supporting **utfb8mb4 with long indexes** used by recent GitLab databases.
+
+ # Login to MySQL
+ mysql -u root -p
+
+ # Type the MySQL root password
+ mysql > use gitlabhq_production;
+
+ # Set innodb_file_format and innodb_large_prefix on the running server:
+ # Note: These are the default settings only for MySQL 5.7.7 and later.
+
+ mysql > SET GLOBAL innodb_file_format=Barracuda, innodb_large_prefix=1;
+
+ # Your DB must be (still) using utf8/utf8_general_ci as default encoding and collation.
+ # We will NOT change the default encoding and collation on the DB in order to support future GitLab migrations creating tables
+ # that require "long indexes support" on installations using MySQL <= 5.7.9.
+ # However, when such migrations occur, you will have to follow this guide again to convert the newly created tables to the proper encoding/collation.
+
+ # This should return the following:
+ mysql> SELECT @@character_set_database, @@collation_database;
+ +--------------------------+----------------------+
+ | @@character_set_database | @@collation_database |
+ +--------------------------+----------------------+
+ | utf8 | utf8_general_ci |
+ +--------------------------+----------------------+
+
+> Now, ensure that [innodb_file_format](https://dev.mysql.com/doc/refman/5.6/en/tablespace-enabling.html) and [innodb_large_prefix](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix) are **persisted** in your `my.cnf` file.
+
+#### Tables and data conversion to utf8mb4
+<a name="convert"></a>
+
+Now that you have a persistent MySQL setup, you can safely upgrade tables after setup or upgrade time:
+
+ # Convert tables not using ROW_FORMAT DYNAMIC:
+
+ mysql> SELECT CONCAT('ALTER TABLE `', TABLE_NAME,'` ROW_FORMAT=DYNAMIC;') AS 'Copy & run these SQL statements:' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="gitlabhq_production" AND TABLE_TYPE="BASE TABLE" AND ROW_FORMAT!="Dynamic";
+
+ # !! If previous query returned results, copy & run all shown SQL statements
+
+ # Convert tables/columns not using utf8mb4/utf8mb4_general_ci as encoding/collation:
+
+ mysql > SET foreign_key_checks = 0;
+
+ mysql > SELECT CONCAT('ALTER TABLE `', TABLE_NAME,'` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;') AS 'Copy & run these SQL statements:' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="gitlabhq_production" AND TABLE_COLLATION != "utf8mb4_general_ci" AND TABLE_TYPE="BASE TABLE";
+
+ # !! If previous query returned results, copy & run all shown SQL statements
+
+ # Turn foreign key checks back on
+ mysql > SET foreign_key_checks = 1;
+
+ # You can now quit the database session
+ mysql> \q
+
+Ensure your GitLab database configuration file uses a proper connection encoding and collation:
+
+```sudo -u git -H editor config/database.yml```
+
+ production:
+ adapter: mysql2
+ encoding: utf8mb4
+ collation: utf8mb4_general_ci
+
+[Restart your GitLab instance](../administration/restart_gitlab.md).
+
## MySQL strings limits
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index c44930a4ceb..ec13c2446ef 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -1,6 +1,6 @@
# System hooks
-Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `project_rename`, `project_transfer`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create`, `key_destroy`, `group_create`, `group_destroy`, `user_add_to_group` and `user_remove_from_group`.
+Your GitLab instance can perform HTTP POST requests on the following events: `project_create`, `project_destroy`, `project_rename`, `project_transfer`, `project_update`, `user_add_to_team`, `user_remove_from_team`, `user_create`, `user_destroy`, `key_create`, `key_destroy`, `group_create`, `group_destroy`, `user_add_to_group` and `user_remove_from_group`.
System hooks can be used, e.g. for logging or changing information in a LDAP server.
@@ -88,6 +88,23 @@ X-Gitlab-Event: System Hook
}
```
+**Project updated:**
+
+```json
+{
+ "created_at": "2012-07-21T07:30:54Z",
+ "updated_at": "2012-07-21T07:38:22Z",
+ "event_name": "project_update",
+ "name": "StoreCloud",
+ "owner_email": "johnsmith@gmail.com",
+ "owner_name": "John Smith",
+ "path": "storecloud",
+ "path_with_namespace": "jsmith/storecloud",
+ "project_id": 74,
+ "project_visibility": "private",
+}
+```
+
**New Team Member:**
```json
diff --git a/doc/update/8.15-to-8.16.md b/doc/update/8.15-to-8.16.md
index 63f3c3fdda9..2695a16ac0b 100644
--- a/doc/update/8.15-to-8.16.md
+++ b/doc/update/8.15-to-8.16.md
@@ -97,6 +97,8 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
### 6. Update gitlab-workhorse
Install and compile gitlab-workhorse. This requires
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index 0f959b956a5..cc688a7f99c 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -140,75 +140,77 @@ into the password field.
## Recovery options
-If you lose your code generation device (such as your mobile phone) and you need
-to disable two-factor authentication on your account, you have several options.
+To disable two-factor authentication on your account (for example, if you
+have lost your code generation device) you can:
+* [Use a saved recovery code](#use-a-saved-recovery-code)
+* [Generate new recovery codes using SSH](#generate-new-recovery-codes-using-SSH)
+* [Ask a GitLab administrator to disable two-factor authentication on your account](#ask-a-gitlab-administrator-to-disable-two-factor-authentication-on-your-account)
### Use a saved recovery code
-When you enabled two-factor authentication for your account, a series of
-recovery codes were generated. If you saved those codes somewhere safe, you
-may use one to sign in.
+Enabling two-factor authentication for your account generated several recovery
+codes. If you saved these codes, you can use one of them to sign in.
-First, enter your username/email and password on the GitLab sign in page. When
-prompted for a two-factor code, enter one of the recovery codes you saved
-previously.
+To use a recovery code, enter your username/email and password on the GitLab
+sign-in page. When prompted for a two-factor code, enter the recovery code.
-> **Note:** Once a particular recovery code has been used, it cannot be used again.
- You may still use the other saved recovery codes at a later time.
+> **Note:** Once you use a recovery code, you cannot re-use it. You can still
+ use the other recovery codes you saved.
### Generate new recovery codes using SSH
-It's not uncommon for users to forget to save the recovery codes when enabling
-two-factor authentication. If you have an SSH key added to your GitLab account,
-you can generate a new set of recovery codes using SSH.
-
-Run `ssh git@gitlab.example.com 2fa_recovery_codes`. You will be prompted to
-confirm that you wish to generate new codes. If you choose to continue, any
-previously saved codes will be invalidated.
-
-```bash
-$ ssh git@gitlab.example.com 2fa_recovery_codes
-Are you sure you want to generate new two-factor recovery codes?
-Any existing recovery codes you saved will be invalidated. (yes/no)
-yes
-
-Your two-factor authentication recovery codes are:
-
-119135e5a3ebce8e
-11f6v2a498810dcd
-3924c7ab2089c902
-e79a3398bfe4f224
-34bd7b74adbc8861
-f061691d5107df1a
-169bf32a18e63e7f
-b510e7422e81c947
-20dbed24c5e74663
-df9d3b9403b9c9f0
-
-During sign in, use one of the codes above when prompted for
-your two-factor code. Then, visit your Profile Settings and add
-a new device so you do not lose access to your account again.
-```
-
-Next, go to the GitLab sign in page and enter your username/email and password.
-When prompted for a two-factor code, enter one of the recovery codes obtained
-from the command line output.
-
-> **Note:** After signing in, you should immediately visit your **Profile Settings
- -> Account** to set up two-factor authentication with a new device.
-
-### Ask a GitLab administrator to disable two-factor on your account
-
-If the above two methods are not possible, you may ask a GitLab global
-administrator to disable two-factor authentication for your account. Please
-be aware that this will temporarily leave your account in a less secure state.
-You should sign in and re-enable two-factor authentication as soon as possible
-after the administrator disables it.
+Users often forget to save their recovery codes when enabling two-factor
+authentication. If an SSH key is added to your GitLab account, you can generate
+a new set of recovery codes with SSH.
+
+1. Run `ssh git@gitlab.example.com 2fa_recovery_codes`.
+2. You are prompted to confirm that you want to generate new codes. Continuing this process invalidates previously saved codes.
+ ```
+ bash
+ $ ssh git@gitlab.example.com 2fa_recovery_codes
+ Are you sure you want to generate new two-factor recovery codes?
+ Any existing recovery codes you saved will be invalidated. (yes/no)
+
+ yes
+
+ Your two-factor authentication recovery codes are:
+
+ 119135e5a3ebce8e
+ 11f6v2a498810dcd
+ 3924c7ab2089c902
+ e79a3398bfe4f224
+ 34bd7b74adbc8861
+ f061691d5107df1a
+ 169bf32a18e63e7f
+ b510e7422e81c947
+ 20dbed24c5e74663
+ df9d3b9403b9c9f0
+
+ During sign in, use one of the codes above when prompted for your
+ two-factor code. Then, visit your Profile Settings and add a new device
+ so you do not lose access to your account again.
+ ```
+3. Go to the GitLab sign-in page and enter your username/email and password. When prompted for a two-factor code, enter one of the recovery codes obtained
+from the command-line output.
+
+> **Note:** After signing in, visit your **Profile Settings -> Account** immediately to set up two-factor authentication with a new
+ device.
+
+### Ask a GitLab administrator to disable two-factor authentication on your account
+
+If you cannot use a saved recovery code or generate new recovery codes, ask a
+GitLab global administrator to disable two-factor authentication for your
+account. This will temporarily leave your account in a less secure state.
+Sign in and re-enable two-factor authentication as soon as possible.
## Note to GitLab administrators
-You need to take special care to that 2FA keeps working after
-[restoring a GitLab backup](../../../raketasks/backup_restore.md).
+- You need to take special care to that 2FA keeps working after
+[restoring a GitLab backup](../raketasks/backup_restore.md).
+
+- To ensure 2FA authorizes correctly with TOTP server, you may want to ensure
+your GitLab server's time is synchronized via a service like NTP. Otherwise,
+you may have cases where authorization always fails because of time differences.
[Google Authenticator]: https://support.google.com/accounts/answer/1066447?hl=en
[FreeOTP]: https://fedorahosted.org/freeotp/
diff --git a/lib/gitlab/ci/trace_reader.rb b/lib/gitlab/ci/trace_reader.rb
index 37e51536e8f..1d7ddeb3e0f 100644
--- a/lib/gitlab/ci/trace_reader.rb
+++ b/lib/gitlab/ci/trace_reader.rb
@@ -42,6 +42,7 @@ module Gitlab
end
chunks.join.lines.last(max_lines).join
+ .force_encoding(Encoding.default_external)
end
end
end
diff --git a/lib/gitlab/view/presenter/base.rb b/lib/gitlab/view/presenter/base.rb
index 83c8ba5c1cf..dbfe0941e4d 100644
--- a/lib/gitlab/view/presenter/base.rb
+++ b/lib/gitlab/view/presenter/base.rb
@@ -1,6 +1,8 @@
module Gitlab
module View
module Presenter
+ CannotOverrideMethodError = Class.new(StandardError)
+
module Base
extend ActiveSupport::Concern
diff --git a/lib/gitlab/view/presenter/delegated.rb b/lib/gitlab/view/presenter/delegated.rb
index f4d330c590e..387ff0f5d43 100644
--- a/lib/gitlab/view/presenter/delegated.rb
+++ b/lib/gitlab/view/presenter/delegated.rb
@@ -8,6 +8,10 @@ module Gitlab
@subject = subject
attributes.each do |key, value|
+ if subject.respond_to?(key)
+ raise CannotOverrideMethodError.new("#{subject} already respond to #{key}!")
+ end
+
define_singleton_method(key) { value }
end
diff --git a/spec/controllers/explore/projects_controller_spec.rb b/spec/controllers/explore/projects_controller_spec.rb
new file mode 100644
index 00000000000..6128091f543
--- /dev/null
+++ b/spec/controllers/explore/projects_controller_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe Explore::ProjectsController do
+ let(:user) { create(:user) }
+ let(:visibility) { :public }
+
+ describe 'GET #trending' do
+ let!(:project_1) { create(:project, visibility, ci_id: 1) }
+ let!(:project_2) { create(:project, visibility, ci_id: 2) }
+
+ let!(:trending_project_1) { create(:trending_project, project: project_1) }
+ let!(:trending_project_2) { create(:trending_project, project: project_2) }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'sorting by update date' do
+ it 'sorts by last updated' do
+ get :trending, sort: 'updated_desc'
+ expect(assigns(:projects)).to eq [project_2, project_1]
+ end
+
+ it 'sorts by oldest updated' do
+ get :trending, sort: 'updated_asc'
+ expect(assigns(:projects)).to eq [project_1, project_2]
+ end
+ end
+ end
+end
diff --git a/spec/factories/trending_project.rb b/spec/factories/trending_project.rb
new file mode 100644
index 00000000000..246176611dc
--- /dev/null
+++ b/spec/factories/trending_project.rb
@@ -0,0 +1,6 @@
+FactoryGirl.define do
+ # TrendingProject
+ factory :trending_project, class: 'TrendingProject' do
+ project
+ end
+end
diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
index 8a155c3bfc5..93763f092fb 100644
--- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
@@ -43,14 +43,6 @@ describe 'Dropdown assignee', js: true, feature: true do
expect(page).to have_css(js_dropdown_assignee, visible: true)
end
- it 'shows assigned to me link' do
- filtered_search.set('assignee:')
-
- page.within js_dropdown_assignee do
- expect(page).to have_content('Assigned to me')
- end
- end
-
it 'closes when the search bar is unfocused' do
find('body').click()
@@ -129,14 +121,6 @@ describe 'Dropdown assignee', js: true, feature: true do
filtered_search.set('assignee:')
end
- it 'filters by current user' do
- page.within js_dropdown_assignee do
- click_button 'Assigned to me'
- end
-
- expect(filtered_search.value).to eq("assignee:#{user.to_reference} ")
- end
-
it 'fills in the assignee username when the assignee has not been filtered' do
click_assignee(user_jacob.name)
@@ -185,4 +169,22 @@ describe 'Dropdown assignee', js: true, feature: true do
expect(page).to have_css(js_dropdown_assignee, visible: true)
end
end
+
+ describe 'caching requests' do
+ it 'caches requests after the first load' do
+ filtered_search.set('assignee')
+ send_keys_to_filtered_search(':')
+ initial_size = dropdown_assignee_size
+
+ expect(initial_size).to be > 0
+
+ new_user = create(:user)
+ project.team << [new_user, :master]
+ find('.filtered-search-input-container .clear-search').click
+ filtered_search.set('assignee')
+ send_keys_to_filtered_search(':')
+
+ expect(dropdown_assignee_size).to eq(initial_size)
+ end
+ end
end
diff --git a/spec/features/issues/filtered_search/dropdown_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb
index a5d5d9d4c5e..59e302f0e2d 100644
--- a/spec/features/issues/filtered_search/dropdown_author_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb
@@ -157,4 +157,22 @@ describe 'Dropdown author', js: true, feature: true do
expect(page).to have_css(js_dropdown_author, visible: true)
end
end
+
+ describe 'caching requests' do
+ it 'caches requests after the first load' do
+ filtered_search.set('author')
+ send_keys_to_filtered_search(':')
+ initial_size = dropdown_author_size
+
+ expect(initial_size).to be > 0
+
+ new_user = create(:user)
+ project.team << [new_user, :master]
+ find('.filtered-search-input-container .clear-search').click
+ filtered_search.set('author')
+ send_keys_to_filtered_search(':')
+
+ expect(dropdown_author_size).to eq(initial_size)
+ end
+ end
end
diff --git a/spec/features/issues/filtered_search/dropdown_label_spec.rb b/spec/features/issues/filtered_search/dropdown_label_spec.rb
index f09ad2dd86b..5079eb8dd00 100644
--- a/spec/features/issues/filtered_search/dropdown_label_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_label_spec.rb
@@ -249,4 +249,21 @@ describe 'Dropdown label', js: true, feature: true do
expect(page).to have_css(js_dropdown_label, visible: true)
end
end
+
+ describe 'caching requests' do
+ it 'caches requests after the first load' do
+ filtered_search.set('label')
+ send_keys_to_filtered_search(':')
+ initial_size = dropdown_label_size
+
+ expect(initial_size).to be > 0
+
+ create(:label, project: project)
+ find('.filtered-search-input-container .clear-search').click
+ filtered_search.set('label')
+ send_keys_to_filtered_search(':')
+
+ expect(dropdown_label_size).to eq(initial_size)
+ end
+ end
end
diff --git a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
index 134e58ad586..0ce16715b86 100644
--- a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
@@ -219,4 +219,21 @@ describe 'Dropdown milestone', js: true, feature: true do
expect(page).to have_css(js_dropdown_milestone, visible: true)
end
end
+
+ describe 'caching requests' do
+ it 'caches requests after the first load' do
+ filtered_search.set('milestone')
+ send_keys_to_filtered_search(':')
+ initial_size = dropdown_milestone_size
+
+ expect(initial_size).to be > 0
+
+ create(:milestone, project: project)
+ find('.filtered-search-input-container .clear-search').click
+ filtered_search.set('milestone')
+ send_keys_to_filtered_search(':')
+
+ expect(dropdown_milestone_size).to eq(initial_size)
+ end
+ end
end
diff --git a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js.es6 b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js.es6
index 6df7c0e44ef..9d9097419ea 100644
--- a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js.es6
+++ b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js.es6
@@ -72,6 +72,12 @@
const result = gl.FilteredSearchTokenKeys.searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`);
expect(result).toEqual(tokenKeys[0]);
});
+
+ it('should return alternative tokenKey when found by key param', () => {
+ const tokenKeys = gl.FilteredSearchTokenKeys.getAlternatives();
+ const result = gl.FilteredSearchTokenKeys.searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`);
+ expect(result).toEqual(tokenKeys[0]);
+ });
});
describe('searchByConditionUrl', () => {
diff --git a/spec/lib/gitlab/ci/trace_reader_spec.rb b/spec/lib/gitlab/ci/trace_reader_spec.rb
index f06d78694d6..ff5551bf703 100644
--- a/spec/lib/gitlab/ci/trace_reader_spec.rb
+++ b/spec/lib/gitlab/ci/trace_reader_spec.rb
@@ -11,13 +11,25 @@ describe Gitlab::Ci::TraceReader do
last_lines = random_lines
expected = lines.last(last_lines).join
+ result = subject.read(last_lines: last_lines)
- expect(subject.read(last_lines: last_lines)).to eq(expected)
+ expect(result).to eq(expected)
+ expect(result.encoding).to eq(Encoding.default_external)
end
end
it 'returns everything if trying to get too many lines' do
- expect(build_subject.read(last_lines: lines.size * 2)).to eq(lines.join)
+ result = build_subject.read(last_lines: lines.size * 2)
+
+ expect(result).to eq(lines.join)
+ expect(result.encoding).to eq(Encoding.default_external)
+ end
+
+ it 'returns all contents if last_lines is not specified' do
+ result = build_subject.read
+
+ expect(result).to eq(lines.join)
+ expect(result.encoding).to eq(Encoding.default_external)
end
it 'raises an error if not passing an integer for last_lines' do
diff --git a/spec/lib/gitlab/view/presenter/delegated_spec.rb b/spec/lib/gitlab/view/presenter/delegated_spec.rb
index 888ab80cad5..e9d4af54389 100644
--- a/spec/lib/gitlab/view/presenter/delegated_spec.rb
+++ b/spec/lib/gitlab/view/presenter/delegated_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Gitlab::View::Presenter::Delegated do
- let(:project) { double(:project, bar: 'baz') }
+ let(:project) { double(:project, user: 'John Doe') }
let(:presenter_class) do
Class.new(described_class)
end
@@ -12,10 +12,14 @@ describe Gitlab::View::Presenter::Delegated do
describe '#initialize' do
it 'takes arbitrary key/values and exposes them' do
- presenter = presenter_class.new(project, user: 'user', foo: 'bar')
+ presenter = presenter_class.new(project, current_user: 'Jane Doe')
- expect(presenter.user).to eq('user')
- expect(presenter.foo).to eq('bar')
+ expect(presenter.current_user).to eq('Jane Doe')
+ end
+
+ it 'raise an error if the presentee already respond to method' do
+ expect { presenter_class.new(project, user: 'Jane Doe') }.
+ to raise_error Gitlab::View::Presenter::CannotOverrideMethodError
end
end
@@ -23,7 +27,7 @@ describe Gitlab::View::Presenter::Delegated do
it 'forwards missing methods to subject' do
presenter = presenter_class.new(project)
- expect(presenter.bar).to eq('baz')
+ expect(presenter.user).to eq('John Doe')
end
end
end
diff --git a/spec/lib/gitlab/view/presenter/factory_spec.rb b/spec/lib/gitlab/view/presenter/factory_spec.rb
index 55c5ecbf92f..70d2e22b48f 100644
--- a/spec/lib/gitlab/view/presenter/factory_spec.rb
+++ b/spec/lib/gitlab/view/presenter/factory_spec.rb
@@ -22,13 +22,6 @@ describe Gitlab::View::Presenter::Factory do
end
describe '#fabricate!' do
- it 'exposes given params' do
- presenter = described_class.new(build, user: 'user', foo: 'bar').fabricate!
-
- expect(presenter.user).to eq('user')
- expect(presenter.foo).to eq('bar')
- end
-
it 'detects the presenter based on the given subject' do
presenter = described_class.new(build).fabricate!
diff --git a/spec/lib/gitlab/view/presenter/simple_spec.rb b/spec/lib/gitlab/view/presenter/simple_spec.rb
index b489bdf1981..1795ed2405b 100644
--- a/spec/lib/gitlab/view/presenter/simple_spec.rb
+++ b/spec/lib/gitlab/view/presenter/simple_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Gitlab::View::Presenter::Simple do
- let(:project) { double(:project) }
+ let(:project) { double(:project, user: 'John Doe') }
let(:presenter_class) do
Class.new(described_class)
end
@@ -12,10 +12,15 @@ describe Gitlab::View::Presenter::Simple do
describe '#initialize' do
it 'takes arbitrary key/values and exposes them' do
- presenter = presenter_class.new(project, user: 'user', foo: 'bar')
+ presenter = presenter_class.new(project, current_user: 'Jane Doe')
- expect(presenter.user).to eq('user')
- expect(presenter.foo).to eq('bar')
+ expect(presenter.current_user).to eq('Jane Doe')
+ end
+
+ it 'override the presentee attributes' do
+ presenter = presenter_class.new(project, user: 'Jane Doe')
+
+ expect(presenter.user).to eq('Jane Doe')
end
end
@@ -23,7 +28,7 @@ describe Gitlab::View::Presenter::Simple do
it 'does not forward missing methods to subject' do
presenter = presenter_class.new(project)
- expect { presenter.foo }.to raise_error(NoMethodError)
+ expect { presenter.user }.to raise_error(NoMethodError)
end
end
end
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index 4d57efd3c53..2f4a33a1868 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Ability, lib: true do
describe '.can_edit_note?' do
let(:project) { create(:empty_project) }
- let!(:note) { create(:note_on_issue, project: project) }
+ let(:note) { create(:note_on_issue, project: project) }
context 'using an anonymous user' do
it 'returns false' do
@@ -60,7 +60,7 @@ describe Ability, lib: true do
describe '.users_that_can_read_project' do
context 'using a public project' do
it 'returns all the users' do
- project = create(:project, :public)
+ project = create(:empty_project, :public)
user = build(:user)
expect(described_class.users_that_can_read_project([user], project)).
@@ -69,7 +69,7 @@ describe Ability, lib: true do
end
context 'using an internal project' do
- let(:project) { create(:project, :internal) }
+ let(:project) { create(:empty_project, :internal) }
it 'returns users that are administrators' do
user = build(:user, admin: true)
@@ -120,7 +120,7 @@ describe Ability, lib: true do
end
context 'using a private project' do
- let(:project) { create(:project, :private) }
+ let(:project) { create(:empty_project, :private) }
it 'returns users that are administrators' do
user = build(:user, admin: true)
@@ -247,7 +247,7 @@ describe Ability, lib: true do
end
describe '.project_disabled_features_rules' do
- let(:project) { create(:project, wiki_access_level: ProjectFeature::DISABLED) }
+ let(:project) { create(:empty_project, wiki_access_level: ProjectFeature::DISABLED) }
subject { described_class.allowed(project.owner, project) }
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index f031876e812..47cd5075a7d 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Ci::Build, :models do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:build) { create(:ci_build, pipeline: pipeline) }
let(:test_trace) { 'This is a test' }
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 2bdd611aeed..426be74cd02 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -284,7 +284,7 @@ describe Ci::Pipeline, models: true do
end
describe 'merge request metrics' do
- let(:project) { FactoryGirl.create :project }
+ let(:project) { create(:project, :repository) }
let(:pipeline) { FactoryGirl.create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: project.repository.commit('master').id) }
let!(:merge_request) { create(:merge_request, source_project: project, source_branch: pipeline.ref) }
@@ -339,7 +339,7 @@ describe Ci::Pipeline, models: true do
end
context 'with non-empty project' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:pipeline) do
create(:ci_pipeline,
@@ -890,7 +890,7 @@ describe Ci::Pipeline, models: true do
end
describe "#merge_requests" do
- let(:project) { FactoryGirl.create :project }
+ let(:project) { create(:project, :repository) }
let(:pipeline) { FactoryGirl.create(:ci_empty_pipeline, status: 'created', project: project, ref: 'master', sha: project.repository.commit('master').id) }
it "returns merge requests whose `diff_head_sha` matches the pipeline's SHA" do
@@ -956,7 +956,7 @@ describe Ci::Pipeline, models: true do
end
describe 'notifications when pipeline success or failed' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:pipeline) do
create(:ci_pipeline,
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 2b856ca7af7..3f32248e52b 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -91,8 +91,7 @@ describe Ci::Runner, models: true do
end
describe '#can_pick?' do
- let(:project) { create(:project) }
- let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:pipeline) { create(:ci_pipeline) }
let(:build) { create(:ci_build, pipeline: pipeline) }
let(:runner) { create(:ci_runner) }
@@ -321,8 +320,8 @@ describe Ci::Runner, models: true do
describe '.assignable_for' do
let(:runner) { create(:ci_runner) }
- let(:project) { create(:project) }
- let(:another_project) { create(:project) }
+ let(:project) { create(:empty_project) }
+ let(:another_project) { create(:empty_project) }
before do
project.runners << runner
diff --git a/spec/models/commit_range_spec.rb b/spec/models/commit_range_spec.rb
index 30782ca75a0..e4bddf67096 100644
--- a/spec/models/commit_range_spec.rb
+++ b/spec/models/commit_range_spec.rb
@@ -7,7 +7,7 @@ describe CommitRange, models: true do
it { is_expected.to include_module(Referable) }
end
- let!(:project) { create(:project, :public) }
+ let!(:project) { create(:project, :public, :repository) }
let!(:commit1) { project.commit("HEAD~2") }
let!(:commit2) { project.commit }
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index b2202f0fd44..32f9366a14c 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Commit, models: true do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:project, :public, :repository) }
let(:commit) { project.commit }
describe 'modules' do
@@ -34,7 +34,7 @@ describe Commit, models: true do
end
describe '#to_reference' do
- let(:project) { create(:project, path: 'sample-project') }
+ let(:project) { create(:project, :repository, path: 'sample-project') }
let(:commit) { project.commit }
it 'returns a String reference to the object' do
@@ -42,13 +42,13 @@ describe Commit, models: true do
end
it 'supports a cross-project reference' do
- another_project = build(:project, name: 'another-project', namespace: project.namespace)
+ another_project = build(:project, :repository, name: 'another-project', namespace: project.namespace)
expect(commit.to_reference(another_project)).to eq "sample-project@#{commit.id}"
end
end
describe '#reference_link_text' do
- let(:project) { create(:project, path: 'sample-project') }
+ let(:project) { create(:project, :repository, path: 'sample-project') }
let(:commit) { project.commit }
it 'returns a String reference to the object' do
@@ -56,7 +56,7 @@ describe Commit, models: true do
end
it 'supports a cross-project reference' do
- another_project = build(:project, name: 'another-project', namespace: project.namespace)
+ another_project = build(:project, :repository, name: 'another-project', namespace: project.namespace)
expect(commit.reference_link_text(another_project)).to eq "sample-project@#{commit.short_id}"
end
end
@@ -131,7 +131,7 @@ eos
describe '#closes_issues' do
let(:issue) { create :issue, project: project }
- let(:other_project) { create :project, :public }
+ let(:other_project) { create(:empty_project, :public) }
let(:other_issue) { create :issue, project: other_project }
let(:commiter) { create :user }
@@ -154,7 +154,7 @@ eos
end
it_behaves_like 'a mentionable' do
- subject { create(:project).commit }
+ subject { create(:project, :repository).commit }
let(:author) { create(:user, email: subject.author_email) }
let(:backref_text) { "commit #{subject.id}" }
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 64ea607eb95..bf4394f7d5b 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe CommitStatus, models: true do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:pipeline) do
create(:ci_pipeline, project: project, sha: project.commit.id)
diff --git a/spec/models/compare_spec.rb b/spec/models/compare_spec.rb
index 49ab3c4b6e9..da003dbf794 100644
--- a/spec/models/compare_spec.rb
+++ b/spec/models/compare_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Compare, models: true do
include RepoHelpers
- let(:project) { create(:project, :public) }
+ let(:project) { create(:project, :public, :repository) }
let(:commit) { project.commit }
let(:start_commit) { sample_image_commit }
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index 972640fa2c3..a905528c535 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -318,7 +318,7 @@ describe Issue, "Issuable" do
end
describe '#labels_array' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:bug) { create(:label, project: project, title: 'bug') }
let(:issue) { create(:issue, project: project) }
@@ -332,7 +332,7 @@ describe Issue, "Issuable" do
end
describe '#user_notes_count' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:issue1) { create(:issue, project: project) }
let(:issue2) { create(:issue, project: project) }
@@ -376,7 +376,7 @@ describe Issue, "Issuable" do
end
describe ".with_label" do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:empty_project, :public) }
let(:bug) { create(:label, project: project, title: 'bug') }
let(:feature) { create(:label, project: project, title: 'feature') }
let(:enhancement) { create(:label, project: project, title: 'enhancement') }
diff --git a/spec/models/concerns/mentionable_spec.rb b/spec/models/concerns/mentionable_spec.rb
index b73028f0bc0..2092576e981 100644
--- a/spec/models/concerns/mentionable_spec.rb
+++ b/spec/models/concerns/mentionable_spec.rb
@@ -13,7 +13,7 @@ describe Mentionable do
end
describe 'references' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:mentionable) { Example.new }
it 'excludes JIRA references' do
@@ -83,13 +83,13 @@ describe Issue, "Mentionable" do
end
describe '#create_cross_references!' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:author) { build(:user) }
let(:commit) { project.commit }
let(:commit2) { project.commit }
let!(:issue) do
- create(:issue, project: project, description: commit.to_reference)
+ create(:issue, project: project, description: "See #{commit.to_reference}")
end
it 'correctly removes already-mentioned Commits' do
@@ -100,7 +100,7 @@ describe Issue, "Mentionable" do
end
describe '#create_new_cross_references!' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:author) { create(:author) }
let(:issues) { create_list(:issue, 2, project: project, author: author) }
diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb
index 0e097559b59..ad703a6c8bb 100644
--- a/spec/models/concerns/milestoneish_spec.rb
+++ b/spec/models/concerns/milestoneish_spec.rb
@@ -7,7 +7,7 @@ describe Milestone, 'Milestoneish' do
let(:member) { create(:user) }
let(:guest) { create(:user) }
let(:admin) { create(:admin) }
- let(:project) { create(:project, :public) }
+ let(:project) { create(:empty_project, :public) }
let(:milestone) { create(:milestone, project: project) }
let!(:issue) { create(:issue, project: project, milestone: milestone) }
let!(:security_issue_1) { create(:issue, :confidential, project: project, author: author, milestone: milestone) }
diff --git a/spec/models/concerns/project_features_compatibility_spec.rb b/spec/models/concerns/project_features_compatibility_spec.rb
index 9041690023f..6cf5877424d 100644
--- a/spec/models/concerns/project_features_compatibility_spec.rb
+++ b/spec/models/concerns/project_features_compatibility_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe ProjectFeaturesCompatibility do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:features) { %w(issues wiki builds merge_requests snippets) }
# We had issues_enabled, snippets_enabled, builds_enabled, merge_requests_enabled and issues_enabled fields on projects table
diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb
index 70f985afefb..3b7cc7d9e2e 100644
--- a/spec/models/cycle_analytics/code_spec.rb
+++ b/spec/models/cycle_analytics/code_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'CycleAnalytics#code', feature: true do
extend CycleAnalyticsHelpers::TestGeneration
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:from_date) { 10.days.ago }
let(:user) { create(:user, :admin) }
subject { CycleAnalytics.new(project, from: from_date) }
diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb
index e4b6a8f4518..5c73edbbc53 100644
--- a/spec/models/cycle_analytics/issue_spec.rb
+++ b/spec/models/cycle_analytics/issue_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'CycleAnalytics#issue', models: true do
extend CycleAnalyticsHelpers::TestGeneration
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:from_date) { 10.days.ago }
let(:user) { create(:user, :admin) }
subject { CycleAnalytics.new(project, from: from_date) }
diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb
index dc5b04852d6..55483fc876a 100644
--- a/spec/models/cycle_analytics/plan_spec.rb
+++ b/spec/models/cycle_analytics/plan_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'CycleAnalytics#plan', feature: true do
extend CycleAnalyticsHelpers::TestGeneration
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:from_date) { 10.days.ago }
let(:user) { create(:user, :admin) }
subject { CycleAnalytics.new(project, from: from_date) }
diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb
index 5e99188f318..591bbdddf55 100644
--- a/spec/models/cycle_analytics/production_spec.rb
+++ b/spec/models/cycle_analytics/production_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'CycleAnalytics#production', feature: true do
extend CycleAnalyticsHelpers::TestGeneration
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:from_date) { 10.days.ago }
let(:user) { create(:user, :admin) }
subject { CycleAnalytics.new(project, from: from_date) }
diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb
index 45baa5f7006..33d2c0a7416 100644
--- a/spec/models/cycle_analytics/review_spec.rb
+++ b/spec/models/cycle_analytics/review_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'CycleAnalytics#review', feature: true do
extend CycleAnalyticsHelpers::TestGeneration
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:from_date) { 10.days.ago }
let(:user) { create(:user, :admin) }
subject { CycleAnalytics.new(project, from: from_date) }
diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb
index 77625aad580..00693d67475 100644
--- a/spec/models/cycle_analytics/staging_spec.rb
+++ b/spec/models/cycle_analytics/staging_spec.rb
@@ -3,9 +3,10 @@ require 'spec_helper'
describe 'CycleAnalytics#staging', feature: true do
extend CycleAnalyticsHelpers::TestGeneration
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:from_date) { 10.days.ago }
let(:user) { create(:user, :admin) }
+
subject { CycleAnalytics.new(project, from: from_date) }
generate_cycle_analytics_spec(
diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb
index 27a117d2d76..f857ea6cbec 100644
--- a/spec/models/cycle_analytics/test_spec.rb
+++ b/spec/models/cycle_analytics/test_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'CycleAnalytics#test', feature: true do
extend CycleAnalyticsHelpers::TestGeneration
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:from_date) { 10.days.ago }
let(:user) { create(:user, :admin) }
subject { CycleAnalytics.new(project, from: from_date) }
diff --git a/spec/models/deploy_keys_project_spec.rb b/spec/models/deploy_keys_project_spec.rb
index 8a1e337c1a3..aacc178a19e 100644
--- a/spec/models/deploy_keys_project_spec.rb
+++ b/spec/models/deploy_keys_project_spec.rb
@@ -12,7 +12,7 @@ describe DeployKeysProject, models: true do
end
describe "Destroying" do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
subject { create(:deploy_keys_project, project: project) }
let(:deploy_key) { subject.deploy_key }
@@ -39,7 +39,7 @@ describe DeployKeysProject, models: true do
end
context "when the deploy key is used by more than one project" do
- let!(:other_project) { create(:project) }
+ let!(:other_project) { create(:empty_project) }
before do
other_project.deploy_keys << deploy_key
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index ca594a320c0..fc4435a2f64 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -17,7 +17,7 @@ describe Deployment, models: true do
it { is_expected.to validate_presence_of(:sha) }
describe '#includes_commit?' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:environment) { create(:environment, project: project) }
let(:deployment) do
create(:deployment, environment: environment, sha: project.commit.id)
diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb
index 3db5937a4f3..9ea3a4b7020 100644
--- a/spec/models/diff_note_spec.rb
+++ b/spec/models/diff_note_spec.rb
@@ -3,8 +3,8 @@ require 'spec_helper'
describe DiffNote, models: true do
include RepoHelpers
- let(:project) { create(:project) }
- let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:merge_request) { create(:merge_request) }
+ let(:project) { merge_request.project }
let(:commit) { project.commit(sample_commit.id) }
let(:path) { "files/ruby/popen.rb" }
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 96efe1696c3..b2e06541e66 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -32,7 +32,7 @@ describe Environment, models: true do
end
describe '#includes_commit?' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
context 'without a last deployment' do
it "returns false" do
@@ -81,7 +81,7 @@ describe Environment, models: true do
end
describe '#first_deployment_for' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let!(:deployment) { create(:deployment, environment: environment, ref: commit.parent.id) }
let!(:deployment1) { create(:deployment, environment: environment, ref: commit.id) }
let(:head_commit) { project.commit }
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index f8660da031d..349474bb656 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -27,7 +27,7 @@ describe Event, models: true do
end
describe "Push event" do
- let(:project) { create(:project, :private) }
+ let(:project) { create(:empty_project, :private) }
let(:user) { project.owner }
let(:event) { create_event(project, user) }
@@ -187,7 +187,7 @@ describe Event, models: true do
end
context 'merge request diff note event' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:empty_project, :public) }
let(:merge_request) { create(:merge_request, source_project: project, author: author, assignee: assignee) }
let(:note_on_merge_request) { create(:legacy_diff_note_on_merge_request, noteable: merge_request, project: project) }
let(:target) { note_on_merge_request }
@@ -202,7 +202,7 @@ describe Event, models: true do
end
context 'private project' do
- let(:project) { create(:project, :private) }
+ let(:project) { create(:empty_project, :private) }
it do
expect(event.visible_to_user?(non_member)).to eq false
diff --git a/spec/models/forked_project_link_spec.rb b/spec/models/forked_project_link_spec.rb
index 1863581f57b..454550c9710 100644
--- a/spec/models/forked_project_link_spec.rb
+++ b/spec/models/forked_project_link_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe ForkedProjectLink, "add link on fork" do
- let(:project_from) { create(:project) }
+ let(:project_from) { create(:project, :repository) }
let(:namespace) { create(:namespace) }
let(:user) { create(:user, namespace: namespace) }
@@ -21,7 +21,7 @@ end
describe '#forked?' do
let(:forked_project_link) { build(:forked_project_link) }
- let(:project_from) { create(:project) }
+ let(:project_from) { create(:project, :repository) }
let(:project_to) { create(:project, forked_project_link: forked_project_link) }
before :each do
diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb
index d87684fd49e..cacbab8bcb1 100644
--- a/spec/models/global_milestone_spec.rb
+++ b/spec/models/global_milestone_spec.rb
@@ -4,9 +4,9 @@ describe GlobalMilestone, models: true do
let(:user) { create(:user) }
let(:user2) { create(:user) }
let(:group) { create(:group) }
- let(:project1) { create(:project, group: group) }
- let(:project2) { create(:project, path: 'gitlab-ci', group: group) }
- let(:project3) { create(:project, path: 'cookbook-gitlab', group: group) }
+ let(:project1) { create(:empty_project, group: group) }
+ let(:project2) { create(:empty_project, path: 'gitlab-ci', group: group) }
+ let(:project3) { create(:empty_project, path: 'cookbook-gitlab', group: group) }
describe '.build_collection' do
let(:milestone1_due_date) { 2.weeks.from_now.to_date }
diff --git a/spec/models/group_milestone_spec.rb b/spec/models/group_milestone_spec.rb
index 601167c3bd3..916afb7aaf5 100644
--- a/spec/models/group_milestone_spec.rb
+++ b/spec/models/group_milestone_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe GroupMilestone, models: true do
let(:group) { create(:group) }
- let(:project) { create(:project, group: group) }
+ let(:project) { create(:empty_project, group: group) }
let(:project_milestone) do
create(:milestone, title: "Milestone v1.2", project: project)
end
diff --git a/spec/models/guest_spec.rb b/spec/models/guest_spec.rb
index d79f929f7a1..582b54c0712 100644
--- a/spec/models/guest_spec.rb
+++ b/spec/models/guest_spec.rb
@@ -1,9 +1,9 @@
require 'spec_helper'
describe Guest, lib: true do
- let(:public_project) { create(:project, :public) }
- let(:private_project) { create(:project, :private) }
- let(:internal_project) { create(:project, :internal) }
+ let(:public_project) { build_stubbed(:empty_project, :public) }
+ let(:private_project) { build_stubbed(:empty_project, :private) }
+ let(:internal_project) { build_stubbed(:empty_project, :internal) }
describe '.can_pull?' do
context 'when project is private' do
diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb
index ad2b710041a..e8caad00c44 100644
--- a/spec/models/hooks/system_hook_spec.rb
+++ b/spec/models/hooks/system_hook_spec.rb
@@ -4,7 +4,7 @@ describe SystemHook, models: true do
describe "execute" do
let(:system_hook) { create(:system_hook) }
let(:user) { create(:user) }
- let(:project) { create(:project, namespace: user.namespace) }
+ let(:project) { create(:empty_project, namespace: user.namespace) }
let(:group) { create(:group) }
before do
diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
index e52b9d75cef..9d4db1bfb52 100644
--- a/spec/models/hooks/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -25,7 +25,7 @@ describe WebHook, models: true do
end
describe "execute" do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:project_hook) { create(:project_hook) }
before(:each) do
diff --git a/spec/models/issue/metrics_spec.rb b/spec/models/issue/metrics_spec.rb
index 2459a49f095..08712f2a768 100644
--- a/spec/models/issue/metrics_spec.rb
+++ b/spec/models/issue/metrics_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Issue::Metrics, models: true do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
subject { create(:issue, project: project) }
diff --git a/spec/models/issue_collection_spec.rb b/spec/models/issue_collection_spec.rb
index d742c814680..d8aed25c041 100644
--- a/spec/models/issue_collection_spec.rb
+++ b/spec/models/issue_collection_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe IssueCollection do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:issue1) { create(:issue, project: project) }
let(:issue2) { create(:issue, project: project) }
let(:collection) { described_class.new([issue1, issue2]) }
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 61d72925736..40c0a75c364 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -35,7 +35,7 @@ describe Issue, models: true do
end
it 'supports a cross-project reference' do
- another_project = build(:project, name: 'another-project', namespace: project.namespace)
+ another_project = build(:empty_project, name: 'another-project', namespace: project.namespace)
expect(issue.to_reference(another_project)).to eq "sample-project#1"
end
end
@@ -60,9 +60,9 @@ describe Issue, models: true do
end
describe '#closed_by_merge_requests' do
- let(:project) { create(:project) }
- let(:issue) { create(:issue, project: project, state: "opened")}
- let(:closed_issue) { build(:issue, project: project, state: "closed")}
+ let(:project) { create(:project, :repository) }
+ let(:issue) { create(:issue, project: project)}
+ let(:closed_issue) { build(:issue, :closed, project: project)}
let(:mr) do
opts = {
@@ -104,7 +104,7 @@ describe Issue, models: true do
describe '#referenced_merge_requests' do
it 'returns the referenced merge requests' do
- project = create(:project, :public)
+ project = create(:empty_project, :public)
mr1 = create(:merge_request,
source_project: project,
@@ -137,7 +137,7 @@ describe Issue, models: true do
end
context 'user is reporter in project issue belongs to' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:issue) { create(:issue, project: project) }
before { project.team << [user, :reporter] }
@@ -151,7 +151,7 @@ describe Issue, models: true do
context 'checking destination project also' do
subject { issue.can_move?(user, to_project) }
- let(:to_project) { create(:project) }
+ let(:to_project) { create(:empty_project) }
context 'destination project allowed' do
before { to_project.team << [user, :reporter] }
@@ -246,7 +246,7 @@ describe Issue, models: true do
describe '#participants' do
context 'using a public project' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:empty_project, :public) }
let(:issue) { create(:issue, project: project) }
let!(:note1) do
@@ -268,7 +268,7 @@ describe Issue, models: true do
context 'using a private project' do
it 'does not include mentioned users that do not have access to the project' do
- project = create(:project)
+ project = create(:empty_project)
user = create(:user)
issue = create(:issue, project: project)
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index 4f7c8a36cb5..16e2144d6a1 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -481,7 +481,7 @@ describe Member, models: true do
describe "destroying a record", truncate: true do
it "refreshes user's authorized projects" do
- project = create(:project, :private)
+ project = create(:empty_project, :private)
user = create(:user)
member = project.team << [user, :reporter]
diff --git a/spec/models/members/project_member_spec.rb b/spec/models/members/project_member_spec.rb
index 68f72f5c86e..90d14c2c0b9 100644
--- a/spec/models/members/project_member_spec.rb
+++ b/spec/models/members/project_member_spec.rb
@@ -83,8 +83,8 @@ describe ProjectMember, models: true do
describe '.import_team' do
before do
- @project_1 = create :project
- @project_2 = create :project
+ @project_1 = create(:empty_project)
+ @project_2 = create(:empty_project)
@user_1 = create :user
@user_2 = create :user
@@ -131,8 +131,8 @@ describe ProjectMember, models: true do
describe '.truncate_teams' do
before do
- @project_1 = create :project
- @project_2 = create :project
+ @project_1 = create(:empty_project)
+ @project_2 = create(:empty_project)
@user_1 = create :user
@user_2 = create :user
diff --git a/spec/models/merge_request/metrics_spec.rb b/spec/models/merge_request/metrics_spec.rb
index 255db41cb19..9afed311e27 100644
--- a/spec/models/merge_request/metrics_spec.rb
+++ b/spec/models/merge_request/metrics_spec.rb
@@ -1,9 +1,7 @@
require 'spec_helper'
describe MergeRequest::Metrics, models: true do
- let(:project) { create(:project) }
-
- subject { create(:merge_request, source_project: project) }
+ subject { create(:merge_request) }
describe "when recording the default set of metrics on merge request save" do
it "records the merge time" do
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 064f29d2d66..3cee2b7714f 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -24,7 +24,7 @@ describe Milestone, models: true do
it { is_expected.to have_many(:issues) }
end
- let(:project) { create(:project, :public) }
+ let(:project) { create(:empty_project, :public) }
let(:milestone) { create(:milestone, project: project) }
let(:issue) { create(:issue, project: project) }
let(:user) { create(:user) }
@@ -44,7 +44,7 @@ describe Milestone, models: true do
end
it "accepts the same title in another project" do
- project = build(:project)
+ project = build(:empty_project)
new_milestone = Milestone.new(project: project, title: milestone.title)
expect(new_milestone).to be_valid
@@ -257,7 +257,7 @@ describe Milestone, models: true do
end
it 'supports a cross-project reference' do
- another_project = build(:project, name: 'another-project', namespace: project.namespace)
+ another_project = build(:empty_project, name: 'another-project', namespace: project.namespace)
expect(milestone.to_reference(another_project)).to eq "sample-project%1"
end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 6db3e62b36e..3b47b41f9ee 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -107,7 +107,7 @@ describe Namespace, models: true do
describe '#move_dir' do
before do
@namespace = create :namespace
- @project = create :project, namespace: @namespace
+ @project = create(:empty_project, namespace: @namespace)
allow(@namespace).to receive(:path_changed?).and_return(true)
end
@@ -151,7 +151,7 @@ describe Namespace, models: true do
end
describe :rm_dir do
- let!(:project) { create(:project, namespace: namespace) }
+ let!(:project) { create(:empty_project, namespace: namespace) }
let!(:path) { File.join(Gitlab.config.repositories.storages.default, namespace.path) }
it "removes its dirs when deleted" do
diff --git a/spec/models/network/graph_spec.rb b/spec/models/network/graph_spec.rb
index b76513d2a3c..492c4e01bd8 100644
--- a/spec/models/network/graph_spec.rb
+++ b/spec/models/network/graph_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Network::Graph, models: true do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let!(:note_on_commit) { create(:note_on_commit, project: project) }
it '#initialize' do
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 6f9ae655fed..1cde9e04951 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -42,7 +42,7 @@ describe Note, models: true do
context 'when noteable and note project differ' do
subject do
build(:note, noteable: build_stubbed(:issue),
- project: build_stubbed(:project))
+ project: build_stubbed(:empty_project))
end
it { is_expected.to be_invalid }
@@ -93,8 +93,8 @@ describe Note, models: true do
describe 'authorization' do
before do
- @p1 = create(:project)
- @p2 = create(:project)
+ @p1 = create(:empty_project)
+ @p2 = create(:empty_project)
@u1 = create(:user)
@u2 = create(:user)
@u3 = create(:user)
@@ -191,10 +191,10 @@ describe Note, models: true do
describe "cross_reference_not_visible_for?" do
let(:private_user) { create(:user) }
- let(:private_project) { create(:project, namespace: private_user.namespace).tap { |p| p.team << [private_user, :master] } }
+ let(:private_project) { create(:empty_project, namespace: private_user.namespace) { |p| p.team << [private_user, :master] } }
let(:private_issue) { create(:issue, project: private_project) }
- let(:ext_proj) { create(:project, :public) }
+ let(:ext_proj) { create(:empty_project, :public) }
let(:ext_issue) { create(:issue, project: ext_proj) }
let(:note) do
@@ -237,7 +237,7 @@ describe Note, models: true do
describe '#participants' do
it 'includes the note author' do
- project = create(:project, :public)
+ project = create(:empty_project, :public)
issue = create(:issue, project: project)
note = create(:note_on_issue, noteable: issue, project: project)
diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb
index a55d43ab2f9..8589f1eb712 100644
--- a/spec/models/project_feature_spec.rb
+++ b/spec/models/project_feature_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe ProjectFeature do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:user) { create(:user) }
describe '#feature_available?' do
@@ -35,7 +35,7 @@ describe ProjectFeature do
it "returns true when user is a member of project group" do
group = create(:group)
- project = create(:project, namespace: group)
+ project = create(:empty_project, namespace: group)
group.add_developer(user)
features.each do |feature|
diff --git a/spec/models/project_group_link_spec.rb b/spec/models/project_group_link_spec.rb
index 47397a822c1..59a4ae1b799 100644
--- a/spec/models/project_group_link_spec.rb
+++ b/spec/models/project_group_link_spec.rb
@@ -17,7 +17,7 @@ describe ProjectGroupLink do
describe "destroying a record", truncate: true do
it "refreshes group users' authorized projects" do
- project = create(:project, :private)
+ project = create(:empty_project, :private)
group = create(:group)
reporter = create(:user)
group_users = group.users
diff --git a/spec/models/project_label_spec.rb b/spec/models/project_label_spec.rb
index 4d538cac007..9cdbfa44e5b 100644
--- a/spec/models/project_label_spec.rb
+++ b/spec/models/project_label_spec.rb
@@ -100,7 +100,7 @@ describe ProjectLabel, models: true do
end
context 'cross project reference' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
context 'using name' do
it 'returns cross reference with label name' do
diff --git a/spec/models/project_services/asana_service_spec.rb b/spec/models/project_services/asana_service_spec.rb
index 8e5145e824b..48aef3a93f2 100644
--- a/spec/models/project_services/asana_service_spec.rb
+++ b/spec/models/project_services/asana_service_spec.rb
@@ -18,7 +18,7 @@ describe AsanaService, models: true do
describe 'Execute' do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
def create_data_for_commits(*messages)
{
diff --git a/spec/models/project_services/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb
index 4c5acb7990b..96f00af898e 100644
--- a/spec/models/project_services/assembla_service_spec.rb
+++ b/spec/models/project_services/assembla_service_spec.rb
@@ -8,7 +8,7 @@ describe AssemblaService, models: true do
describe "Execute" do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
before do
@assembla_service = AssemblaService.new
diff --git a/spec/models/project_services/campfire_service_spec.rb b/spec/models/project_services/campfire_service_spec.rb
index a3b9d084a75..953e664fb66 100644
--- a/spec/models/project_services/campfire_service_spec.rb
+++ b/spec/models/project_services/campfire_service_spec.rb
@@ -22,7 +22,7 @@ describe CampfireService, models: true do
describe "#execute" do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
before do
@campfire_service = CampfireService.new
diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/project_services/drone_ci_service_spec.rb
index 42c2ed668bc..f9307d6de7b 100644
--- a/spec/models/project_services/drone_ci_service_spec.rb
+++ b/spec/models/project_services/drone_ci_service_spec.rb
@@ -27,7 +27,7 @@ describe DroneCiService, models: true, caching: true do
shared_context :drone_ci_service do
let(:drone) { DroneCiService.new }
- let(:project) { create(:project, name: 'project') }
+ let(:project) { create(:project, :repository, name: 'project') }
let(:path) { "#{project.namespace.path}/#{project.path}" }
let(:drone_url) { 'http://drone.example.com' }
let(:sha) { '2ab7834c' }
diff --git a/spec/models/project_services/external_wiki_service_spec.rb b/spec/models/project_services/external_wiki_service_spec.rb
index 342d86aeca9..bdeea1db1e3 100644
--- a/spec/models/project_services/external_wiki_service_spec.rb
+++ b/spec/models/project_services/external_wiki_service_spec.rb
@@ -23,7 +23,7 @@ describe ExternalWikiService, models: true do
end
describe 'External wiki' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
context 'when it is active' do
before do
diff --git a/spec/models/project_services/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb
index d6db02d6e76..a97e8c6e4ce 100644
--- a/spec/models/project_services/flowdock_service_spec.rb
+++ b/spec/models/project_services/flowdock_service_spec.rb
@@ -22,7 +22,7 @@ describe FlowdockService, models: true do
describe "Execute" do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
before do
@flowdock_service = FlowdockService.new
diff --git a/spec/models/project_services/gemnasium_service_spec.rb b/spec/models/project_services/gemnasium_service_spec.rb
index 529044d1d8b..a13fbae03eb 100644
--- a/spec/models/project_services/gemnasium_service_spec.rb
+++ b/spec/models/project_services/gemnasium_service_spec.rb
@@ -24,7 +24,7 @@ describe GemnasiumService, models: true do
describe "Execute" do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
before do
@gemnasium_service = GemnasiumService.new
diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
index 9b80f0e7296..dcb70ee28a8 100644
--- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
+++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
@@ -8,21 +8,21 @@ describe GitlabIssueTrackerService, models: true do
describe 'Validations' do
context 'when service is active' do
- subject { described_class.new(project: create(:project), active: true) }
+ subject { described_class.new(project: create(:empty_project), active: true) }
it { is_expected.to validate_presence_of(:issues_url) }
it_behaves_like 'issue tracker service URL attribute', :issues_url
end
context 'when service is inactive' do
- subject { described_class.new(project: create(:project), active: false) }
+ subject { described_class.new(project: create(:empty_project), active: false) }
it { is_expected.not_to validate_presence_of(:issues_url) }
end
end
describe 'project and issue urls' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
context 'with absolute urls' do
before do
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
index 1e03e22f8f5..307fd06ab6c 100644
--- a/spec/models/project_services/hipchat_service_spec.rb
+++ b/spec/models/project_services/hipchat_service_spec.rb
@@ -22,8 +22,8 @@ describe HipchatService, models: true do
describe "Execute" do
let(:hipchat) { HipchatService.new }
- let(:user) { create(:user, username: 'username') }
- let(:project) { create(:project, name: 'project') }
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
let(:api_url) { 'https://hipchat.example.com/v2/room/123456/notification?auth_token=verySecret' }
let(:project_name) { project.name_with_namespace.gsub(/\s/, '') }
let(:token) { 'verySecret' }
@@ -178,7 +178,7 @@ describe HipchatService, models: true do
context "Note events" do
let(:user) { create(:user) }
- let(:project) { create(:project, creator_id: user.id) }
+ let(:project) { create(:project, :repository, creator: user) }
context 'when commit comment event triggered' do
let(:commit_note) do
diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb
index f8c45b37561..b9fb6f3f6f4 100644
--- a/spec/models/project_services/irker_service_spec.rb
+++ b/spec/models/project_services/irker_service_spec.rb
@@ -25,7 +25,7 @@ describe IrkerService, models: true do
describe 'Execute' do
let(:irker) { IrkerService.new }
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:sample_data) do
Gitlab::DataBuilder::Push.build_sample(project, user)
end
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index 9a4dc0b3911..908356de7cf 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -71,7 +71,7 @@ describe JiraService, models: true do
describe '#close_issue' do
let(:custom_base_url) { 'http://custom_url' }
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let(:merge_request) { create(:merge_request) }
before do
@@ -207,12 +207,12 @@ describe JiraService, models: true do
end
describe "Stored password invalidation" do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
context "when a password was previously set" do
before do
@jira_service = JiraService.create!(
- project: create(:project),
+ project: project,
properties: {
url: 'http://jira.example.com/rest/api/2',
username: 'mic',
@@ -252,7 +252,7 @@ describe JiraService, models: true do
context "when no password was previously set" do
before do
@jira_service = JiraService.create(
- project: create(:project),
+ project: project,
properties: {
url: 'http://jira.example.com/rest/api/2',
username: 'mic'
@@ -281,7 +281,7 @@ describe JiraService, models: true do
end
describe 'description and title' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
context 'when it is not set' do
before do
@@ -316,7 +316,7 @@ describe JiraService, models: true do
end
describe 'project and issue urls' do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
context 'when gitlab.yml was initialized' do
before do
diff --git a/spec/models/project_services/pipeline_email_service_spec.rb b/spec/models/project_services/pipeline_email_service_spec.rb
index 7c8824485f5..03932895b0e 100644
--- a/spec/models/project_services/pipeline_email_service_spec.rb
+++ b/spec/models/project_services/pipeline_email_service_spec.rb
@@ -7,7 +7,7 @@ describe PipelinesEmailService do
create(:ci_pipeline, project: project, sha: project.commit('master').sha)
end
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:recipient) { 'test@gitlab.com' }
let(:data) do
diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb
index 8fc92a9ab51..a7e7594a7d5 100644
--- a/spec/models/project_services/pushover_service_spec.rb
+++ b/spec/models/project_services/pushover_service_spec.rb
@@ -27,7 +27,7 @@ describe PushoverService, models: true do
describe 'Execute' do
let(:pushover) { PushoverService.new }
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:sample_data) do
Gitlab::DataBuilder::Push.build_sample(project, user)
end
diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb
index 0475cecaa2d..942eeab251d 100644
--- a/spec/models/project_team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -265,10 +265,10 @@ describe ProjectTeam, models: true do
let(:group) { create(:group) }
let(:developer) { create(:user) }
let(:master) { create(:user) }
- let(:personal_project) { create(:project, namespace: developer.namespace) }
- let(:group_project) { create(:project, namespace: group) }
- let(:members_project) { create(:project) }
- let(:shared_project) { create(:project) }
+ let(:personal_project) { create(:empty_project, namespace: developer.namespace) }
+ let(:group_project) { create(:empty_project, namespace: group) }
+ let(:members_project) { create(:empty_project) }
+ let(:shared_project) { create(:empty_project) }
before do
group.add_master(master)
@@ -330,7 +330,7 @@ describe ProjectTeam, models: true do
reporter = create(:user)
promoted_guest = create(:user)
guest = create(:user)
- project = create(:project)
+ project = create(:empty_project)
project.add_master(master)
project.add_reporter(reporter)
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 042d06adb2b..ebfc3b2d0c7 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -4,7 +4,7 @@ describe Repository, models: true do
include RepoHelpers
TestBlob = Struct.new(:name)
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
let(:user) { create(:user) }
@@ -90,6 +90,30 @@ describe Repository, models: true do
it { is_expected.to eq(['v1.1.0', 'v1.0.0']) }
end
+
+ context 'annotated tag pointing to a blob' do
+ let(:annotated_tag_name) { 'annotated-tag' }
+
+ subject { repository.tags_sorted_by('updated_asc').map(&:name) }
+
+ before do
+ options = { message: 'test tag message\n',
+ tagger: { name: 'John Smith', email: 'john@gmail.com' } }
+ repository.rugged.tags.create(annotated_tag_name, 'a48e4fc218069f68ef2e769dd8dfea3991362175', options)
+
+ double_first = double(committed_date: Time.now - 1.second)
+ double_last = double(committed_date: Time.now)
+
+ allow(tag_a).to receive(:dereferenced_target).and_return(double_last)
+ allow(tag_b).to receive(:dereferenced_target).and_return(double_first)
+ end
+
+ it { is_expected.to eq(['v1.1.0', 'v1.0.0', annotated_tag_name]) }
+
+ after do
+ repository.rugged.tags.delete(annotated_tag_name)
+ end
+ end
end
end
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index 56cf6920de4..8c1b98116f3 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -12,7 +12,7 @@ describe Service, models: true do
end
describe "Testable" do
- let(:project) { create :project }
+ let(:project) { create(:project, :repository) }
before do
allow(@service).to receive(:project).and_return(project)
@@ -35,7 +35,7 @@ describe Service, models: true do
end
describe "With commits" do
- let(:project) { create :project }
+ let(:project) { create(:project, :repository) }
before do
allow(@service).to receive(:project).and_return(project)
@@ -64,7 +64,7 @@ describe Service, models: true do
api_key: '123456789'
})
end
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
describe 'is prefilled for projects pushover service' do
it "has all fields prefilled" do
@@ -83,7 +83,7 @@ describe Service, models: true do
describe "{property}_changed?" do
let(:service) do
BambooService.create(
- project: create(:project),
+ project: create(:empty_project),
properties: {
bamboo_url: 'http://gitlab.com',
username: 'mic',
@@ -123,7 +123,7 @@ describe Service, models: true do
describe "{property}_touched?" do
let(:service) do
BambooService.create(
- project: create(:project),
+ project: create(:empty_project),
properties: {
bamboo_url: 'http://gitlab.com',
username: 'mic',
@@ -163,7 +163,7 @@ describe Service, models: true do
describe "{property}_was" do
let(:service) do
BambooService.create(
- project: create(:project),
+ project: create(:empty_project),
properties: {
bamboo_url: 'http://gitlab.com',
username: 'mic',
@@ -203,7 +203,7 @@ describe Service, models: true do
describe 'initialize service with no properties' do
let(:service) do
GitlabIssueTrackerService.create(
- project: create(:project),
+ project: create(:empty_project),
title: 'random title'
)
end
@@ -218,7 +218,7 @@ describe Service, models: true do
end
describe "callbacks" do
- let(:project) { create(:project) }
+ let(:project) { create(:empty_project) }
let!(:service) do
RedmineService.new(
project: project,
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 7425a897769..219ab1989ea 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -42,7 +42,7 @@ describe Snippet, models: true do
end
it 'supports a cross-project reference' do
- another_project = build(:project, name: 'another-project', namespace: project.namespace)
+ another_project = build(:empty_project, name: 'another-project', namespace: project.namespace)
expect(snippet.to_reference(another_project)).to eq "sample-project$1"
end
end
@@ -55,7 +55,7 @@ describe Snippet, models: true do
end
it 'still returns shortest reference when project arg present' do
- another_project = build(:project, name: 'another-project')
+ another_project = build(:empty_project, name: 'another-project')
expect(snippet.to_reference(another_project)).to eq "$1"
end
end
@@ -173,7 +173,7 @@ describe Snippet, models: true do
end
describe '#participants' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:empty_project, :public) }
let(:snippet) { create(:snippet, content: 'foo', project: project) }
let!(:note1) do
diff --git a/spec/models/todo_spec.rb b/spec/models/todo_spec.rb
index 623b82c01d8..8017d1c3324 100644
--- a/spec/models/todo_spec.rb
+++ b/spec/models/todo_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
describe Todo, models: true do
- let(:project) { create(:project) }
- let(:commit) { project.commit }
let(:issue) { create(:issue) }
describe 'relationships' do
@@ -82,6 +80,9 @@ describe Todo, models: true do
describe '#target' do
context 'for commits' do
+ let(:project) { create(:project, :repository) }
+ let(:commit) { project.commit }
+
it 'returns an instance of Commit when exists' do
subject.project = project
subject.target_type = 'Commit'
@@ -109,6 +110,9 @@ describe Todo, models: true do
describe '#target_reference' do
it 'returns the short commit id for commits' do
+ project = create(:project, :repository)
+ commit = project.commit
+
subject.project = project
subject.target_type = 'Commit'
subject.commit_id = commit.id
diff --git a/spec/models/tree_spec.rb b/spec/models/tree_spec.rb
index 0737999e125..a87983b7492 100644
--- a/spec/models/tree_spec.rb
+++ b/spec/models/tree_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Tree, models: true do
- let(:repository) { create(:project).repository }
+ let(:repository) { create(:project, :repository).repository }
let(:sha) { repository.root_ref }
subject { described_class.new(repository, '54fcc214') }
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 208aeb1f22c..399d408024d 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1446,14 +1446,14 @@ describe User, models: true do
let!(:user) { create(:user) }
let!(:group) { create(:group) }
let!(:nested_group) { create(:group, parent: group) }
- let!(:project) { create(:project, namespace: group) }
- let!(:nested_project) { create(:project, namespace: nested_group) }
+ let!(:project) { create(:empty_project, namespace: group) }
+ let!(:nested_project) { create(:empty_project, namespace: nested_group) }
before do
group.add_owner(user)
# Add more data to ensure method does not include wrong projects
- other_project = create(:project, namespace: create(:group, :nested))
+ other_project = create(:empty_project, namespace: create(:group, :nested))
other_project.add_developer(create(:user))
end
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index 730d5890f88..b2ece055a67 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -6,7 +6,7 @@ describe API::Branches, api: true do
let(:user) { create(:user) }
let(:user2) { create(:user) }
- let!(:project) { create(:project, creator_id: user.id) }
+ let!(:project) { create(:project, :repository, creator: user) }
let!(:master) { create(:project_member, :master, user: user, project: project) }
let!(:guest) { create(:project_member, :guest, user: user2, project: project) }
let!(:branch_name) { 'feature' }
diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb
index 6d18e5ca550..bd6e23ee769 100644
--- a/spec/requests/api/builds_spec.rb
+++ b/spec/requests/api/builds_spec.rb
@@ -5,7 +5,7 @@ describe API::Builds, api: true do
let(:user) { create(:user) }
let(:api_user) { user }
- let!(:project) { create(:project, creator_id: user.id, public_builds: false) }
+ let!(:project) { create(:project, :repository, creator: user, public_builds: false) }
let!(:developer) { create(:project_member, :developer, user: user, project: project) }
let(:reporter) { create(:project_member, :reporter, project: project) }
let(:guest) { create(:project_member, :guest, project: project) }
diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb
index c1c7c0882de..88361def3cf 100644
--- a/spec/requests/api/commit_statuses_spec.rb
+++ b/spec/requests/api/commit_statuses_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe API::CommitStatuses, api: true do
include ApiHelpers
- let!(:project) { create(:project) }
+ let!(:project) { create(:project, :repository) }
let(:commit) { project.repository.commit }
let(:commit_status) { create(:commit_status, pipeline: pipeline) }
let(:guest) { create_user(:guest) }
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index 7f8ea5251f0..af9028a8978 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -5,7 +5,7 @@ describe API::Commits, api: true do
include ApiHelpers
let(:user) { create(:user) }
let(:user2) { create(:user) }
- let!(:project) { create(:project, creator_id: user.id, namespace: user.namespace) }
+ let!(:project) { create(:project, :repository, creator: user, namespace: user.namespace) }
let!(:master) { create(:project_member, :master, user: user, project: project) }
let!(:guest) { create(:project_member, :guest, user: user2, project: project) }
let!(:note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'a comment on a commit') }
diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb
index 685da28c673..5e26e779366 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -3,8 +3,8 @@ require 'spec_helper'
describe API::Files, api: true do
include ApiHelpers
let(:user) { create(:user) }
- let!(:project) { create(:project, namespace: user.namespace ) }
- let(:guest) { create(:user).tap { |u| create(:project_member, :guest, user: u, project: project) } }
+ let!(:project) { create(:project, :repository, namespace: user.namespace ) }
+ let(:guest) { create(:user) { |u| project.add_guest(u) } }
let(:file_path) { 'files/ruby/popen.rb' }
let(:params) do
{
diff --git a/spec/requests/api/fork_spec.rb b/spec/requests/api/fork_spec.rb
index df29099bc2f..92ac4fd334d 100644
--- a/spec/requests/api/fork_spec.rb
+++ b/spec/requests/api/fork_spec.rb
@@ -4,7 +4,6 @@ describe API::Projects, api: true do
include ApiHelpers
let(:user) { create(:user) }
let(:user2) { create(:user) }
- let(:user3) { create(:user) }
let(:admin) { create(:admin) }
let(:group) { create(:group) }
let(:group2) do
@@ -13,17 +12,14 @@ describe API::Projects, api: true do
group
end
- let(:project) do
- create(:project, creator_id: user.id, namespace: user.namespace)
- end
-
- let(:project_user2) do
- create(:project_member, :reporter, user: user2, project: project)
- end
-
describe 'POST /projects/fork/:id' do
- before { project_user2 }
- before { user3 }
+ let(:project) do
+ create(:project, :repository, creator: user, namespace: user.namespace)
+ end
+
+ before do
+ project.add_reporter(user2)
+ end
context 'when authenticated' do
it 'forks if user has sufficient access to project' do
@@ -49,7 +45,8 @@ describe API::Projects, api: true do
end
it 'fails on missing project access for the project to fork' do
- post api("/projects/fork/#{project.id}", user3)
+ new_user = create(:user)
+ post api("/projects/fork/#{project.id}", new_user)
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Project Not Found')
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index a414d072fa9..9bfa42d2206 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -4,7 +4,7 @@ describe API::Internal, api: true do
include ApiHelpers
let(:user) { create(:user) }
let(:key) { create(:key, user: user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:secret_token) { Gitlab::Shell.secret_token }
describe "GET /internal/check", no_db: true do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index d1b00783e83..801f1a8c427 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -6,12 +6,10 @@ describe API::MergeRequests, api: true do
let(:user) { create(:user) }
let(:admin) { create(:user, :admin) }
let(:non_member) { create(:user) }
- let!(:project) { create(:project, :public, creator_id: user.id, namespace: user.namespace) }
- let!(:merge_request) { create(:merge_request, :simple, author: user, assignee: user, source_project: project, target_project: project, title: "Test", created_at: base_time) }
- let!(:merge_request_closed) { create(:merge_request, state: "closed", author: user, assignee: user, source_project: project, target_project: project, title: "Closed test", created_at: base_time + 1.second) }
- let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignee: user, source_project: project, target_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') }
- let!(:note) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "a comment on a MR") }
- let!(:note2) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "another comment on a MR") }
+ let!(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace) }
+ let!(:merge_request) { create(:merge_request, :simple, author: user, assignee: user, source_project: project, title: "Test", created_at: base_time) }
+ let!(:merge_request_closed) { create(:merge_request, state: "closed", author: user, assignee: user, source_project: project, title: "Closed test", created_at: base_time + 1.second) }
+ let!(:merge_request_merged) { create(:merge_request, state: "merged", author: user, assignee: user, source_project: project, title: "Merged test", created_at: base_time + 2.seconds, merge_commit_sha: '9999999999999999999999999999999999999999') }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
before do
@@ -616,11 +614,12 @@ describe API::MergeRequests, api: true do
original_count = merge_request.notes.size
post api("/projects/#{project.id}/merge_requests/#{merge_request.id}/comments", user), note: "My comment"
+
expect(response).to have_http_status(201)
expect(json_response['note']).to eq('My comment')
expect(json_response['author']['name']).to eq(user.name)
expect(json_response['author']['username']).to eq(user.username)
- expect(merge_request.notes.size).to eq(original_count + 1)
+ expect(merge_request.reload.notes.size).to eq(original_count + 1)
end
it "returns 400 if note is missing" do
@@ -636,6 +635,9 @@ describe API::MergeRequests, api: true do
end
describe "GET :id/merge_requests/:merge_request_id/comments" do
+ let!(:note) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "a comment on a MR") }
+ let!(:note2) { create(:note_on_merge_request, author: user, project: project, noteable: merge_request, note: "another comment on a MR") }
+
it "returns merge_request comments ordered by created_at" do
get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/comments", user)
expect(response).to have_http_status(200)
diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb
index 9a01f7fa1c4..b7a0b5a9e13 100644
--- a/spec/requests/api/pipelines_spec.rb
+++ b/spec/requests/api/pipelines_spec.rb
@@ -5,7 +5,7 @@ describe API::Pipelines, api: true do
let(:user) { create(:user) }
let(:non_member) { create(:user) }
- let(:project) { create(:project, creator_id: user.id) }
+ let(:project) { create(:project, :repository, creator: user) }
let!(:pipeline) do
create(:ci_empty_pipeline, project: project, sha: project.commit.id,
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 0e19f1b35d5..f4d831897ba 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -17,6 +17,7 @@ describe API::Projects, api: true do
let(:project3) do
create(:project,
:private,
+ :repository,
name: 'second_project',
path: 'second_project',
creator_id: user.id,
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index 0b19fa38c55..c61208e395c 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -8,7 +8,7 @@ describe API::Repositories, api: true do
let(:user) { create(:user) }
let(:guest) { create(:user).tap { |u| create(:project_member, :guest, user: u, project: project) } }
- let!(:project) { create(:project, creator_id: user.id) }
+ let!(:project) { create(:project, :repository, creator: user) }
let!(:master) { create(:project_member, :master, user: user, project: project) }
describe "GET /projects/:id/repository/tree" do
@@ -74,7 +74,7 @@ describe API::Repositories, api: true do
context 'when unauthenticated', 'and project is public' do
it_behaves_like 'repository tree' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:project, :public, :repository) }
let(:current_user) { nil }
end
end
@@ -144,7 +144,7 @@ describe API::Repositories, api: true do
context 'when unauthenticated', 'and project is public' do
it_behaves_like 'repository blob' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:project, :public, :repository) }
let(:current_user) { nil }
end
end
@@ -198,7 +198,7 @@ describe API::Repositories, api: true do
context 'when unauthenticated', 'and project is public' do
it_behaves_like 'repository raw blob' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:project, :public, :repository) }
let(:current_user) { nil }
end
end
@@ -273,7 +273,7 @@ describe API::Repositories, api: true do
context 'when unauthenticated', 'and project is public' do
it_behaves_like 'repository archive' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:project, :public, :repository) }
let(:current_user) { nil }
end
end
@@ -347,7 +347,7 @@ describe API::Repositories, api: true do
context 'when unauthenticated', 'and project is public' do
it_behaves_like 'repository compare' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:project, :public, :repository) }
let(:current_user) { nil }
end
end
@@ -394,7 +394,7 @@ describe API::Repositories, api: true do
context 'when unauthenticated', 'and project is public' do
it_behaves_like 'repository contributors' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:project, :public, :repository) }
let(:current_user) { nil }
end
end
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index a1c32ae65ba..898d2b27e5c 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -7,7 +7,7 @@ describe API::Tags, api: true do
let(:user) { create(:user) }
let(:user2) { create(:user) }
- let!(:project) { create(:project, creator_id: user.id) }
+ let!(:project) { create(:project, :repository, creator: user) }
let!(:master) { create(:project_member, :master, user: user, project: project) }
let!(:guest) { create(:project_member, :guest, user: user2, project: project) }
@@ -29,7 +29,7 @@ describe API::Tags, api: true do
context 'when unauthenticated' do
it_behaves_like 'repository tags' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:project, :public, :repository) }
let(:current_user) { nil }
end
end
@@ -88,7 +88,7 @@ describe API::Tags, api: true do
context 'when unauthenticated' do
it_behaves_like 'repository tag' do
- let(:project) { create(:project, :public) }
+ let(:project) { create(:project, :public, :repository) }
let(:current_user) { nil }
end
end
diff --git a/spec/requests/api/triggers_spec.rb b/spec/requests/api/triggers_spec.rb
index cd01283b655..84104aa66ee 100644
--- a/spec/requests/api/triggers_spec.rb
+++ b/spec/requests/api/triggers_spec.rb
@@ -7,7 +7,7 @@ describe API::Triggers do
let(:user2) { create(:user) }
let!(:trigger_token) { 'secure_token' }
let!(:trigger_token_2) { 'secure_token_2' }
- let!(:project) { create(:project, creator_id: user.id) }
+ let!(:project) { create(:project, :repository, creator: user) }
let!(:master) { create(:project_member, :master, user: user, project: project) }
let!(:developer) { create(:project_member, :developer, user: user2, project: project) }
let!(:trigger) { create(:ci_trigger, project: project, token: trigger_token) }
diff --git a/spec/requests/ci/api/triggers_spec.rb b/spec/requests/ci/api/triggers_spec.rb
index 2d434ab5dd8..a30be767119 100644
--- a/spec/requests/ci/api/triggers_spec.rb
+++ b/spec/requests/ci/api/triggers_spec.rb
@@ -5,9 +5,9 @@ describe Ci::API::Triggers do
describe 'POST /projects/:project_id/refs/:ref/trigger' do
let!(:trigger_token) { 'secure token' }
- let!(:project) { FactoryGirl.create(:project, ci_id: 10) }
- let!(:project2) { FactoryGirl.create(:empty_project, ci_id: 11) }
- let!(:trigger) { FactoryGirl.create(:ci_trigger, project: project, token: trigger_token) }
+ let!(:project) { create(:project, :repository, ci_id: 10) }
+ let!(:project2) { create(:empty_project, ci_id: 11) }
+ let!(:trigger) { create(:ci_trigger, project: project, token: trigger_token) }
let(:options) do
{
token: trigger_token
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index 1b9bc26d823..5565d739fd8 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -12,7 +12,7 @@ describe 'Git HTTP requests', lib: true do
describe "User with no identities" do
let(:user) { create(:user) }
- let(:project) { create(:project, path: 'project.git-project') }
+ let(:project) { create(:project, :repository, path: 'project.git-project') }
context "when the project doesn't exist" do
context "when no authentication is provided" do
diff --git a/spec/requests/projects/artifacts_controller_spec.rb b/spec/requests/projects/artifacts_controller_spec.rb
index e02f0eacc93..d20866c0d44 100644
--- a/spec/requests/projects/artifacts_controller_spec.rb
+++ b/spec/requests/projects/artifacts_controller_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Projects::ArtifactsController do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:pipeline) do
create(:ci_pipeline,
diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb
index 28b485e4b15..0edbffbcd3b 100644
--- a/spec/requests/projects/cycle_analytics_events_spec.rb
+++ b/spec/requests/projects/cycle_analytics_events_spec.rb
@@ -4,7 +4,7 @@ describe 'cycle analytics events' do
include ApiHelpers
let(:user) { create(:user) }
- let(:project) { create(:project, public_builds: false) }
+ let(:project) { create(:project, :repository, public_builds: false) }
let(:issue) { create(:issue, project: project, created_at: 2.days.ago) }
describe 'GET /:namespace/:project/cycle_analytics/events/issues' do
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 3794d36bca2..f232164f565 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -33,6 +33,49 @@ describe NotificationService, services: true do
end
end
+ # Next shared examples are intended to test notifications of "participants"
+ #
+ # they take the following parameters:
+ # * issuable
+ # * notification trigger
+ # * participant
+ #
+ shared_examples 'participating by note notification' do
+ it 'emails the participant' do
+ create(:note_on_issue, noteable: issuable, project_id: project.id, note: 'anything', author: participant)
+
+ notification_trigger
+
+ should_email(participant)
+ end
+ end
+
+ shared_examples 'participating by assignee notification' do
+ it 'emails the participant' do
+ issuable.update_attribute(:assignee, participant)
+
+ notification_trigger
+
+ should_email(participant)
+ end
+ end
+
+ shared_examples 'participating by author notification' do
+ it 'emails the participant' do
+ issuable.author = participant
+
+ notification_trigger
+
+ should_email(participant)
+ end
+ end
+
+ shared_examples_for 'participating notifications' do
+ it_should_behave_like 'participating by note notification'
+ it_should_behave_like 'participating by author notification'
+ it_should_behave_like 'participating by assignee notification'
+ end
+
describe 'Keys' do
describe '#new_key' do
let!(:key) { create(:personal_key) }
@@ -588,32 +631,10 @@ describe NotificationService, services: true do
should_not_email(@u_lazy_participant)
end
- context 'participating' do
- context 'by assignee' do
- before do
- issue.update_attribute(:assignee, @u_lazy_participant)
- notification.reassigned_issue(issue, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by note' do
- let!(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: 'anything', author: @u_lazy_participant) }
-
- before { notification.reassigned_issue(issue, @u_disabled) }
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by author' do
- before do
- issue.author = @u_lazy_participant
- notification.reassigned_issue(issue, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
+ it_behaves_like 'participating notifications' do
+ let(:participant) { create(:user, username: 'user-participant') }
+ let(:issuable) { issue }
+ let(:notification_trigger) { notification.reassigned_issue(issue, @u_disabled) }
end
end
@@ -720,32 +741,10 @@ describe NotificationService, services: true do
should_not_email(@u_lazy_participant)
end
- context 'participating' do
- context 'by assignee' do
- before do
- issue.update_attribute(:assignee, @u_lazy_participant)
- notification.close_issue(issue, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by note' do
- let!(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: 'anything', author: @u_lazy_participant) }
-
- before { notification.close_issue(issue, @u_disabled) }
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by author' do
- before do
- issue.author = @u_lazy_participant
- notification.close_issue(issue, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
+ it_behaves_like 'participating notifications' do
+ let(:participant) { create(:user, username: 'user-participant') }
+ let(:issuable) { issue }
+ let(:notification_trigger) { notification.close_issue(issue, @u_disabled) }
end
end
@@ -772,32 +771,10 @@ describe NotificationService, services: true do
should_not_email(@u_lazy_participant)
end
- context 'participating' do
- context 'by assignee' do
- before do
- issue.update_attribute(:assignee, @u_lazy_participant)
- notification.reopen_issue(issue, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by note' do
- let!(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: 'anything', author: @u_lazy_participant) }
-
- before { notification.reopen_issue(issue, @u_disabled) }
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by author' do
- before do
- issue.author = @u_lazy_participant
- notification.reopen_issue(issue, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
+ it_behaves_like 'participating notifications' do
+ let(:participant) { create(:user, username: 'user-participant') }
+ let(:issuable) { issue }
+ let(:notification_trigger) { notification.reopen_issue(issue, @u_disabled) }
end
end
end
@@ -893,31 +870,28 @@ describe NotificationService, services: true do
end
context 'participating' do
- context 'by assignee' do
- before do
- merge_request.update_attribute(:assignee, @u_lazy_participant)
- notification.new_merge_request(merge_request, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
+ it_should_behave_like 'participating by assignee notification' do
+ let(:participant) { create(:user, username: 'user-participant')}
+ let(:issuable) { merge_request }
+ let(:notification_trigger) { notification.new_merge_request(merge_request, @u_disabled) }
end
- context 'by note' do
- let!(:note) { create(:note_on_issue, noteable: merge_request, project_id: project.id, note: 'anything', author: @u_lazy_participant) }
-
- before { notification.new_merge_request(merge_request, @u_disabled) }
-
- it { should_email(@u_lazy_participant) }
+ it_should_behave_like 'participating by note notification' do
+ let(:participant) { create(:user, username: 'user-participant')}
+ let(:issuable) { merge_request }
+ let(:notification_trigger) { notification.new_merge_request(merge_request, @u_disabled) }
end
context 'by author' do
+ let(:participant) { create(:user, username: 'user-participant')}
+
before do
- merge_request.author = @u_lazy_participant
+ merge_request.author = participant
merge_request.save
notification.new_merge_request(merge_request, @u_disabled)
end
- it { should_not_email(@u_lazy_participant) }
+ it { should_not_email(participant) }
end
end
end
@@ -952,33 +926,10 @@ describe NotificationService, services: true do
should_not_email(@u_lazy_participant)
end
- context 'participating' do
- context 'by assignee' do
- before do
- merge_request.update_attribute(:assignee, @u_lazy_participant)
- notification.reassigned_merge_request(merge_request, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by note' do
- let!(:note) { create(:note_on_issue, noteable: merge_request, project_id: project.id, note: 'anything', author: @u_lazy_participant) }
-
- before { notification.reassigned_merge_request(merge_request, @u_disabled) }
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by author' do
- before do
- merge_request.author = @u_lazy_participant
- merge_request.save
- notification.reassigned_merge_request(merge_request, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
+ it_behaves_like 'participating notifications' do
+ let(:participant) { create(:user, username: 'user-participant') }
+ let(:issuable) { merge_request }
+ let(:notification_trigger) { notification.reassigned_merge_request(merge_request, @u_disabled) }
end
end
@@ -1049,33 +1000,10 @@ describe NotificationService, services: true do
should_not_email(@u_lazy_participant)
end
- context 'participating' do
- context 'by assignee' do
- before do
- merge_request.update_attribute(:assignee, @u_lazy_participant)
- notification.close_mr(merge_request, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by note' do
- let!(:note) { create(:note_on_issue, noteable: merge_request, project_id: project.id, note: 'anything', author: @u_lazy_participant) }
-
- before { notification.close_mr(merge_request, @u_disabled) }
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by author' do
- before do
- merge_request.author = @u_lazy_participant
- merge_request.save
- notification.close_mr(merge_request, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
+ it_behaves_like 'participating notifications' do
+ let(:participant) { create(:user, username: 'user-participant') }
+ let(:issuable) { merge_request }
+ let(:notification_trigger) { notification.close_mr(merge_request, @u_disabled) }
end
end
@@ -1116,33 +1044,10 @@ describe NotificationService, services: true do
should_not_email(@u_watcher)
end
- context 'participating' do
- context 'by assignee' do
- before do
- merge_request.update_attribute(:assignee, @u_lazy_participant)
- notification.merge_mr(merge_request, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by note' do
- let!(:note) { create(:note_on_issue, noteable: merge_request, project_id: project.id, note: 'anything', author: @u_lazy_participant) }
-
- before { notification.merge_mr(merge_request, @u_disabled) }
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by author' do
- before do
- merge_request.author = @u_lazy_participant
- merge_request.save
- notification.merge_mr(merge_request, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
+ it_behaves_like 'participating notifications' do
+ let(:participant) { create(:user, username: 'user-participant') }
+ let(:issuable) { merge_request }
+ let(:notification_trigger) { notification.merge_mr(merge_request, @u_disabled) }
end
end
@@ -1169,33 +1074,10 @@ describe NotificationService, services: true do
should_not_email(@u_lazy_participant)
end
- context 'participating' do
- context 'by assignee' do
- before do
- merge_request.update_attribute(:assignee, @u_lazy_participant)
- notification.reopen_mr(merge_request, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by note' do
- let!(:note) { create(:note_on_issue, noteable: merge_request, project_id: project.id, note: 'anything', author: @u_lazy_participant) }
-
- before { notification.reopen_mr(merge_request, @u_disabled) }
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by author' do
- before do
- merge_request.author = @u_lazy_participant
- merge_request.save
- notification.reopen_mr(merge_request, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
+ it_behaves_like 'participating notifications' do
+ let(:participant) { create(:user, username: 'user-participant') }
+ let(:issuable) { merge_request }
+ let(:notification_trigger) { notification.reopen_mr(merge_request, @u_disabled) }
end
end
@@ -1215,33 +1097,10 @@ describe NotificationService, services: true do
should_not_email(@u_lazy_participant)
end
- context 'participating' do
- context 'by assignee' do
- before do
- merge_request.update_attribute(:assignee, @u_lazy_participant)
- notification.resolve_all_discussions(merge_request, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by note' do
- let!(:note) { create(:note_on_issue, noteable: merge_request, project_id: project.id, note: 'anything', author: @u_lazy_participant) }
-
- before { notification.resolve_all_discussions(merge_request, @u_disabled) }
-
- it { should_email(@u_lazy_participant) }
- end
-
- context 'by author' do
- before do
- merge_request.author = @u_lazy_participant
- merge_request.save
- notification.resolve_all_discussions(merge_request, @u_disabled)
- end
-
- it { should_email(@u_lazy_participant) }
- end
+ it_behaves_like 'participating notifications' do
+ let(:participant) { create(:user, username: 'user-participant') }
+ let(:issuable) { merge_request }
+ let(:notification_trigger) { notification.resolve_all_discussions(merge_request, @u_disabled) }
end
end
end
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index fef211ded50..db9f1231682 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -12,6 +12,7 @@ describe SystemHooksService, services: true do
it { expect(event_data(user, :create)).to include(:event_name, :name, :created_at, :updated_at, :email, :user_id, :username) }
it { expect(event_data(user, :destroy)).to include(:event_name, :name, :created_at, :updated_at, :email, :user_id, :username) }
it { expect(event_data(project, :create)).to include(:event_name, :name, :created_at, :updated_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
+ it { expect(event_data(project, :update)).to include(:event_name, :name, :created_at, :updated_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
it { expect(event_data(project, :destroy)).to include(:event_name, :name, :created_at, :updated_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) }
it { expect(event_data(project_member, :create)).to include(:event_name, :created_at, :updated_at, :project_name, :project_path, :project_path_with_namespace, :project_id, :user_name, :user_username, :user_email, :user_id, :access_level, :project_visibility) }
it { expect(event_data(project_member, :destroy)).to include(:event_name, :created_at, :updated_at, :project_name, :project_path, :project_path_with_namespace, :project_id, :user_name, :user_username, :user_email, :user_id, :access_level, :project_visibility) }
@@ -68,6 +69,7 @@ describe SystemHooksService, services: true do
it { expect(event_name(project, :destroy)).to eq "project_destroy" }
it { expect(event_name(project, :rename)).to eq "project_rename" }
it { expect(event_name(project, :transfer)).to eq "project_transfer" }
+ it { expect(event_name(project, :update)).to eq "project_update" }
it { expect(event_name(project_member, :create)).to eq "user_add_to_team" }
it { expect(event_name(project_member, :destroy)).to eq "user_remove_from_team" }
it { expect(event_name(key, :create)).to eq 'key_create' }
diff --git a/spec/support/cycle_analytics_helpers/test_generation.rb b/spec/support/cycle_analytics_helpers/test_generation.rb
index 35b40d73191..10b90b40ba7 100644
--- a/spec/support/cycle_analytics_helpers/test_generation.rb
+++ b/spec/support/cycle_analytics_helpers/test_generation.rb
@@ -54,7 +54,7 @@ module CycleAnalyticsHelpers
end
context "when the data belongs to another project" do
- let(:other_project) { create(:project) }
+ let(:other_project) { create(:project, :repository) }
it "returns nil" do
# Use a stub to "trick" the data/condition functions
diff --git a/spec/support/mentionable_shared_examples.rb b/spec/support/mentionable_shared_examples.rb
index f57c82809a6..87936bb4859 100644
--- a/spec/support/mentionable_shared_examples.rb
+++ b/spec/support/mentionable_shared_examples.rb
@@ -12,7 +12,7 @@ shared_context 'mentionable context' do
let!(:mentioned_mr) { create(:merge_request, source_project: project) }
let(:mentioned_commit) { project.commit("HEAD~1") }
- let(:ext_proj) { create(:project, :public) }
+ let(:ext_proj) { create(:project, :public, :repository) }
let(:ext_issue) { create(:issue, project: ext_proj) }
let(:ext_mr) { create(:merge_request, :simple, source_project: ext_proj) }
let(:ext_commit) { ext_proj.commit("HEAD~2") }
diff --git a/spec/support/slack_mattermost_notifications_shared_examples.rb b/spec/support/slack_mattermost_notifications_shared_examples.rb
index 74d9b8c6313..704922b6cf4 100644
--- a/spec/support/slack_mattermost_notifications_shared_examples.rb
+++ b/spec/support/slack_mattermost_notifications_shared_examples.rb
@@ -26,7 +26,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do
describe "#execute" do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:username) { 'slack_username' }
let(:channel) { 'slack_channel' }
@@ -196,7 +196,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do
describe "Note events" do
let(:user) { create(:user) }
- let(:project) { create(:project, creator_id: user.id) }
+ let(:project) { create(:project, :repository, creator: user) }
before do
allow(chat_service).to receive_messages(
@@ -269,7 +269,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do
describe 'Pipeline events' do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:pipeline) do
create(:ci_pipeline,
diff --git a/spec/views/ci/lints/show.html.haml_spec.rb b/spec/views/ci/lints/show.html.haml_spec.rb
index 2dac5ee23c8..3390ae247ff 100644
--- a/spec/views/ci/lints/show.html.haml_spec.rb
+++ b/spec/views/ci/lints/show.html.haml_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe 'ci/lints/show' do
- include Devise::TestHelpers
+ include Devise::Test::ControllerHelpers
describe 'XSS protection' do
let(:config_processor) { Ci::GitlabCiYamlProcessor.new(YAML.dump(content)) }