summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryce Johnson <bryce@gitlab.com>2016-09-05 12:22:31 +0200
committerBryce Johnson <bryce@gitlab.com>2016-09-05 12:22:31 +0200
commit545e2078c423b44b800d53d61c98eead177bcf57 (patch)
tree8180a081c021321818202119676c291fb51b180a
parentbaf2cd72b344823b91ef39d0344375e9dbb84208 (diff)
parentbeb0b666dc000d51b7ed0eb264bd04ca466117d1 (diff)
downloadgitlab-ce-545e2078c423b44b800d53d61c98eead177bcf57.tar.gz
Merge branch 'master' into repository-page-ui-issues
-rw-r--r--.gitlab/issue_templates/Bug.md2
-rw-r--r--CHANGELOG12
-rw-r--r--app/assets/images/icon-link.pngbin729 -> 0 bytes
-rw-r--r--app/assets/images/icon_anchor.svg1
-rw-r--r--app/assets/javascripts/issue.js3
-rw-r--r--app/assets/javascripts/project_new.js20
-rw-r--r--app/assets/stylesheets/framework/buttons.scss4
-rw-r--r--app/assets/stylesheets/framework/common.scss4
-rw-r--r--app/assets/stylesheets/framework/files.scss2
-rw-r--r--app/assets/stylesheets/framework/mixins.scss2
-rw-r--r--app/assets/stylesheets/framework/tw_bootstrap_variables.scss2
-rw-r--r--app/assets/stylesheets/framework/typography.scss27
-rw-r--r--app/assets/stylesheets/framework/variables.scss139
-rw-r--r--app/assets/stylesheets/pages/builds.scss12
-rw-r--r--app/assets/stylesheets/pages/commits.scss6
-rw-r--r--app/assets/stylesheets/pages/events.scss4
-rw-r--r--app/assets/stylesheets/pages/issues.scss4
-rw-r--r--app/assets/stylesheets/pages/labels.scss1
-rw-r--r--app/assets/stylesheets/pages/merge_conflicts.scss2
-rw-r--r--app/assets/stylesheets/pages/todos.scss2
-rw-r--r--app/assets/stylesheets/pages/tree.scss4
-rw-r--r--app/assets/stylesheets/pages/xterm.scss3
-rw-r--r--app/controllers/projects/builds_controller.rb4
-rw-r--r--app/helpers/projects_helper.rb2
-rw-r--r--app/models/ci/build.rb27
-rw-r--r--app/services/merge_requests/build_service.rb2
-rw-r--r--app/views/groups/group_members/update.js.haml2
-rw-r--r--app/views/projects/_merge_request_settings.html.haml25
-rw-r--r--app/views/projects/builds/_sidebar.html.haml73
-rw-r--r--app/views/projects/buttons/_fork.html.haml4
-rw-r--r--app/views/projects/forks/index.html.haml4
-rw-r--r--app/views/projects/issues/_new_branch.html.haml17
-rw-r--r--app/views/projects/new.html.haml2
-rw-r--r--app/views/projects/project_members/update.js.haml2
-rw-r--r--doc/api/README.md3
-rw-r--r--lib/api/internal.rb14
-rw-r--r--spec/features/expand_collapse_diffs_spec.rb7
-rw-r--r--spec/features/projects/builds_spec.rb114
-rw-r--r--spec/features/projects/edit_spec.rb57
-rw-r--r--spec/javascripts/datetime_utility_spec.js.coffee50
-rw-r--r--spec/javascripts/datetime_utility_spec.js.es664
-rw-r--r--spec/models/ci/build_spec.rb60
-rw-r--r--spec/requests/api/internal_spec.rb4
-rw-r--r--spec/services/merge_requests/build_service_spec.rb4
44 files changed, 528 insertions, 269 deletions
diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
index b676916fdf4..ac38f0c9521 100644
--- a/.gitlab/issue_templates/Bug.md
+++ b/.gitlab/issue_templates/Bug.md
@@ -10,7 +10,7 @@
(What you should see instead)
-### Actual behaviour
+### Actual behavior
(What actually happens)
diff --git a/CHANGELOG b/CHANGELOG
index c249c750ad6..0b92412b065 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
Please view this file on the master branch, on stable branches it's out of date.
v 8.12.0 (unreleased)
+ - Prepend blank line to `Closes` message on merge request linked to issue (lukehowell)
- Filter tags by name !6121
- Make push events have equal vertical spacing.
- Add two-factor recovery endpoint to internal API !5510
@@ -15,11 +16,14 @@ v 8.12.0 (unreleased)
- Set path for all JavaScript cookies to honor GitLab's subdirectory setting !5627 (Mike Greiling)
- Fix bug where pagination is still displayed despite all todos marked as done (ClemMakesApps)
- Center build stage columns in pipeline overview (ClemMakesApps)
+ - Rename behaviour to behavior in bug issue template for consistency (ClemMakesApps)
+ - Remove suggested colors hover underline (ClemMakesApps)
- Shorten task status phrase (ClemMakesApps)
- Add hover color to emoji icon (ClemMakesApps)
- Fix branches page dropdown sort alignment (ClemMakesApps)
- Add white background for no readme container (ClemMakesApps)
- API: Expose issue confidentiality flag. (Robert Schilling)
+ - Fix markdown anchor icon interaction (ClemMakesApps)
- Optimistic locking for Issues and Merge Requests (title and description overriding prevention)
- Add `wiki_page_events` to project hook APIs (Ben Boeckel)
- Remove Gitorious import
@@ -41,12 +45,14 @@ v 8.12.0 (unreleased)
- Remove redundant js-timeago-pending from user activity log (ClemMakesApps)
- Ability to manage project issues, snippets, wiki, merge requests and builds access level
- Remove inconsistent font weight for sidebar's labels (ClemMakesApps)
+ - Align add button on repository view (ClemMakesApps)
- Added tests for diff notes
- Add a button to download latest successful artifacts for branches and tags !5142
- Remove redundant pipeline tooltips (ClemMakesApps)
- Expire commit info views after one day, instead of two weeks, to allow for user email updates
- Add delimiter to project stars and forks count (ClemMakesApps)
- Fix badge count alignment (ClemMakesApps)
+ - Remove green outline from `New branch unavailable` button on issue page !5858 (winniehell)
- Fix repo title alignment (ClemMakesApps)
- Fix branch title trailing space on hover (ClemMakesApps)
- Award emoji tooltips containing more than 10 usernames are now truncated !4780 (jlogandavison)
@@ -58,11 +64,13 @@ v 8.12.0 (unreleased)
- Move to project dropdown with infinite scroll for better performance
- Fix leaking of submit buttons outside the width of a main container !18731 (originally by @pavelloz)
- Load branches asynchronously in Cherry Pick and Revert dialogs.
+ - Convert datetime coffeescript spec to ES6 (ClemMakesApps)
- Add merge request versions !5467
- Change using size to use count and caching it for number of group members. !5935
- Replace play icon font with svg (ClemMakesApps)
- Added 'only_allow_merge_if_build_succeeds' project setting in the API. !5930 (Duck)
- Reduce number of database queries on builds tab
+ - Wrap text in commit message containers
- Capitalize mentioned issue timeline notes (ClemMakesApps)
- Fix inconsistent checkbox alignment (ClemMakesApps)
- Use the default branch for displaying the project icon instead of master !5792 (Hannes Rosenögger)
@@ -71,10 +79,13 @@ v 8.12.0 (unreleased)
- User can edit closed MR with deleted fork (Katarzyna Kobierska Ula Budziszewska) !5496
- Fix repository page ui issues
- Fixed invisible scroll controls on build page on iPhone
+ - Fix error on raw build trace download for old builds stored in database !4822
v 8.11.5 (unreleased)
- Optimize branch lookups and force a repository reload for Repository#find_branch
+ - Fix member expiration date picker after update
- Fix suggested colors options for new labels in the admin area. !6138
+ - Fix GitLab import button
v 8.11.4
- Fix resolving conflicts on forks. !6082
@@ -171,6 +182,7 @@ v 8.11.0
- Get issue and merge request description templates from repositories
- Add hover state to todos !5361 (winniehell)
- Fix icon alignment of star and fork buttons !5451 (winniehell)
+ - Fix alignment of icon buttons !5887 (winniehell)
- Enforce 2FA restrictions on API authentication endpoints !5820
- Limit git rev-list output count to one in forced push check
- Show deployment status on merge requests with external URLs
diff --git a/app/assets/images/icon-link.png b/app/assets/images/icon-link.png
deleted file mode 100644
index 5b55e12571c..00000000000
--- a/app/assets/images/icon-link.png
+++ /dev/null
Binary files differ
diff --git a/app/assets/images/icon_anchor.svg b/app/assets/images/icon_anchor.svg
new file mode 100644
index 00000000000..7e242586bad
--- /dev/null
+++ b/app/assets/images/icon_anchor.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#333" fill-rule="evenodd" d="M9.683 6.676l-.047-.048C8.27 5.26 6.07 5.243 4.726 6.588l-2.29 2.29c-1.344 1.344-1.328 3.544.04 4.91 1.366 1.368 3.564 1.385 4.908.04l1.753-1.752c-.695.074-1.457-.078-2.176-.444L5.934 12.66c-.634.634-1.67.625-2.312-.017-.642-.643-.65-1.677-.017-2.312L6.035 7.9c.634-.634 1.67-.625 2.312.017.024.024.048.05.07.075l.003-.002c.36.36.943.366 1.3.01.355-.356.35-.938-.01-1.3l-.027-.024zM6.58 9.586l.048.05c1.367 1.366 3.565 1.384 4.91.04l2.29-2.292c1.344-1.343 1.328-3.542-.04-4.91-1.366-1.366-3.564-1.384-4.908-.04L7.127 4.187c.695-.074 1.457.078 2.176.444l1.028-1.027c.635-.634 1.67-.624 2.313.017.643.644.652 1.678.018 2.312l-2.43 2.432c-.635.634-1.67.624-2.313-.018-.024-.024-.048-.05-.07-.075l-.003.004c-.36-.362-.943-.367-1.3-.01-.355.355-.35.937.01 1.3.01.007.018.015.027.023z"/></svg> \ No newline at end of file
diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js
index 6838d9d8da1..e6422602ce8 100644
--- a/app/assets/javascripts/issue.js
+++ b/app/assets/javascripts/issue.js
@@ -127,7 +127,7 @@
Issue.prototype.initCanCreateBranch = function() {
var $container;
- $container = $('div#new-branch');
+ $container = $('#new-branch');
if ($container.length === 0) {
return;
}
@@ -139,7 +139,6 @@
if (data.can_create_branch) {
$container.find('.checking').hide();
$container.find('.available').show();
- return $container.find('a').attr('disabled', false);
} else {
$container.find('.checking').hide();
return $container.find('.unavailable').show();
diff --git a/app/assets/javascripts/project_new.js b/app/assets/javascripts/project_new.js
index 798f15e40a0..a787b11f2a9 100644
--- a/app/assets/javascripts/project_new.js
+++ b/app/assets/javascripts/project_new.js
@@ -4,6 +4,8 @@
this.ProjectNew = (function() {
function ProjectNew() {
this.toggleSettings = bind(this.toggleSettings, this);
+ this.$selects = $('.features select');
+
$('.project-edit-container').on('ajax:before', (function(_this) {
return function() {
$('.project-edit-container').hide();
@@ -15,18 +17,24 @@
}
ProjectNew.prototype.toggleSettings = function() {
- this._showOrHide('#project_builds_enabled', '.builds-feature');
- return this._showOrHide('#project_merge_requests_enabled', '.merge-requests-feature');
+ var self = this;
+
+ this.$selects.each(function () {
+ var $select = $(this),
+ className = $select.data('field').replace(/_/g, '-')
+ .replace('access-level', 'feature');
+ self._showOrHide($select, '.' + className);
+ });
};
ProjectNew.prototype.toggleSettingsOnclick = function() {
- return $('#project_builds_enabled, #project_merge_requests_enabled').on('click', this.toggleSettings);
+ this.$selects.on('change', this.toggleSettings);
};
ProjectNew.prototype._showOrHide = function(checkElement, container) {
- var $container;
- $container = $(container);
- if ($(checkElement).prop('checked')) {
+ var $container = $(container);
+
+ if ($(checkElement).val() !== '0') {
return $container.show();
} else {
return $container.hide();
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index cd3ddf5fee9..4618687a4be 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -206,7 +206,9 @@
}
svg, .fa {
- margin-right: 3px;
+ &:not(:last-child) {
+ margin-right: 3px;
+ }
}
}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 8984bce616c..5957dce89bc 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -53,7 +53,7 @@ pre {
&.well-pre {
border: 1px solid #eee;
- background: #f9f9f9;
+ background: $gray-light;
border-radius: 0;
color: #555;
}
@@ -225,7 +225,7 @@ li.note {
.milestone {
&.milestone-closed {
- background: #f9f9f9;
+ background: $gray-light;
}
.progress {
margin-bottom: 0;
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index d3e3fc50736..e3be45ba1dc 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -115,7 +115,7 @@
padding: 0;
}
td.blame-commit {
- background: #f9f9f9;
+ background: $gray-light;
min-width: 350px;
.commit-author-link {
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 62dc2cb3fdc..00f92cef9a4 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -44,7 +44,7 @@
}
&.active {
- background: #f9f9f9;
+ background: $gray-light;
a {
font-weight: 600;
}
diff --git a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
index 371c1bf17e1..915aa631ef8 100644
--- a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
+++ b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
@@ -125,7 +125,7 @@ $panel-inner-border: $border-color;
//
//##
-$well-bg: #f9f9f9;
+$well-bg: $gray-light;
$well-border: #eee;
//== Code
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 06874a993fa..3f8433a0e7f 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -159,25 +159,18 @@
position: relative;
a.anchor {
- // Setting `display: none` would prevent the anchor being scrolled to, so
- // instead we set the height to 0 and it gets updated on hover.
- height: 0;
+ left: -16px;
+ position: absolute;
+ text-decoration: none;
+
+ &:after {
+ content: url('icon_anchor.svg');
+ visibility: hidden;
+ }
}
- &:hover > a.anchor {
- $size: 14px;
- position: absolute;
- right: 100%;
- top: 50%;
- margin-top: -11px;
- margin-right: 0;
- padding-right: 15px;
- display: inline-block;
- width: $size;
- height: $size;
- background-image: image-url("icon-link.png");
- background-size: contain;
- background-repeat: no-repeat;
+ &:hover > a.anchor:after {
+ visibility: visible;
}
}
}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index abfae2e00fb..9f563a4de35 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -10,12 +10,78 @@ $sidebar-transition-duration: .15s;
$sidebar-breakpoint: 1024px;
/*
+ * Color schema
+ */
+$white-light: #fff;
+$white-normal: #ededed;
+$white-dark: #ececec;
+
+$gray-light: #fafafa;
+$gray-normal: #f5f5f5;
+$gray-dark: #ededed;
+$gray-darkest: #c9c9c9;
+
+$green-light: #38ae67;
+$green-normal: #2faa60;
+$green-dark: #2ca05b;
+
+$blue-light: #2ea8e5;
+$blue-normal: #2d9fd8;
+$blue-dark: #2897ce;
+
+$blue-medium-light: #3498cb;
+$blue-medium: #2f8ebf;
+$blue-medium-dark: #2d86b4;
+
+$orange-light: #fc8a51;
+$orange-normal: #e75e40;
+$orange-dark: #ce5237;
+
+$red-light: #e52c5a;
+$red-normal: #d22852;
+$red-dark: darken($red-normal, 5%);
+
+$black: #000;
+$black-transparent: rgba(0, 0, 0, 0.3);
+
+$border-white-light: #f1f2f4;
+$border-white-normal: #d6dae2;
+$border-white-dark: #c6cacf;
+
+$border-gray-light: #dcdcdc;
+$border-gray-normal: #d7d7d7;
+$border-gray-dark: #c6cacf;
+
+$border-green-light: #2faa60;
+$border-green-normal: #2ca05b;
+$border-green-dark: #279654;
+
+$border-blue-light: #2d9fd8;
+$border-blue-normal: #2897ce;
+$border-blue-dark: #258dc1;
+
+$border-orange-light: #fc6d26;
+$border-orange-normal: #ce5237;
+$border-orange-dark: #c14e35;
+
+$border-red-light: #d22852;
+$border-red-normal: #ca264f;
+$border-red-dark: darken($border-red-normal, 5%);
+
+$help-well-bg: $gray-light;
+$help-well-border: #e5e5e5;
+
+$warning-message-bg: #fbf2d9;
+$warning-message-color: #9e8e60;
+$warning-message-border: #f0e2bb;
+
+/*
* UI elements
*/
$border-color: #e5e5e5;
$focus-border-color: #3aabf0;
$table-border-color: #f0f0f0;
-$background-color: #fafafa;
+$background-color: $gray-light;
$dark-background-color: #f5f5f5;
$table-text-gray: #8f8f8f;
@@ -91,73 +157,6 @@ $btn-side-margin: 10px;
$btn-sm-side-margin: 7px;
$btn-xs-side-margin: 5px;
-/*
- * Color schema
- */
-
-$white-light: #fff;
-$white-normal: #ededed;
-$white-dark: #ececec;
-
-$gray-light: #faf9f9;
-$gray-normal: #f5f5f5;
-$gray-dark: #ededed;
-$gray-darkest: #c9c9c9;
-
-$green-light: #38ae67;
-$green-normal: #2faa60;
-$green-dark: #2ca05b;
-
-$blue-light: #2ea8e5;
-$blue-normal: #2d9fd8;
-$blue-dark: #2897ce;
-
-$blue-medium-light: #3498cb;
-$blue-medium: #2f8ebf;
-$blue-medium-dark: #2d86b4;
-
-$orange-light: #fc8a51;
-$orange-normal: #e75e40;
-$orange-dark: #ce5237;
-
-$red-light: #e52c5a;
-$red-normal: #d22852;
-$red-dark: darken($red-normal, 5%);
-
-$black: #000;
-$black-transparent: rgba(0, 0, 0, 0.3);
-
-$border-white-light: #f1f2f4;
-$border-white-normal: #d6dae2;
-$border-white-dark: #c6cacf;
-
-$border-gray-light: #dcdcdc;
-$border-gray-normal: #d7d7d7;
-$border-gray-dark: #c6cacf;
-
-$border-green-light: #2faa60;
-$border-green-normal: #2ca05b;
-$border-green-dark: #279654;
-
-$border-blue-light: #2d9fd8;
-$border-blue-normal: #2897ce;
-$border-blue-dark: #258dc1;
-
-$border-orange-light: #fc6d26;
-$border-orange-normal: #ce5237;
-$border-orange-dark: #c14e35;
-
-$border-red-light: #d22852;
-$border-red-normal: #ca264f;
-$border-red-dark: darken($border-red-normal, 5%);
-
-$help-well-bg: #fafafa;
-$help-well-border: #e5e5e5;
-
-$warning-message-bg: #fbf2d9;
-$warning-message-color: #9e8e60;
-$warning-message-border: #f0e2bb;
-
/* tanuki logo colors */
$tanuki-red: #e24329;
$tanuki-orange: #fc6d26;
@@ -187,7 +186,7 @@ $line-removed-dark: #fac5cd;
$line-number-old: #f9d7dc;
$line-number-new: #ddfbe6;
$line-number-select: #fbf2da;
-$match-line: #fafafa;
+$match-line: $gray-light;
$table-border-gray: #f0f0f0;
$line-target-blue: #eaf3fc;
$line-select-yellow: #fcf8e7;
@@ -268,7 +267,7 @@ $zen-control-hover-color: #111;
$calendar-header-color: #b8b8b8;
$calendar-hover-bg: #ecf3fe;
$calendar-border-color: rgba(#000, .1);
-$calendar-unselectable-bg: #faf9f9;
+$calendar-unselectable-bg: $gray-light;
/*
* Personal Access Tokens
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index cee198691c2..23255f34710 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -108,7 +108,7 @@
}
.blocks-container {
- padding: $gl-padding;
+ padding: 0 $gl-padding;
}
.block {
@@ -123,6 +123,13 @@
}
}
+ .retry-link {
+ color: $gl-link-color;
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+
.stage-item {
cursor: pointer;
@@ -132,7 +139,7 @@
}
.build-dropdown {
- padding: 0 $gl-padding;
+ padding: $gl-padding 0;
.dropdown-menu-toggle {
margin-top: 8px;
@@ -146,7 +153,6 @@
}
.builds-container {
- margin-top: $gl-padding;
background-color: $white-light;
border-top: 1px solid $border-color;
border-bottom: 1px solid $border-color;
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 6a58b445afa..b369f5c0805 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -113,11 +113,13 @@
.commit-row-description {
font-size: 14px;
- border-left: 1px solid #eee;
+ border-left: 1px solid $btn-gray-hover;
padding: 10px 15px;
margin: 10px 0;
- background: #f9f9f9;
+ background: $gray-light;
display: none;
+ white-space: pre-line;
+ word-break: normal;
pre {
border: none;
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 0cd45fb90bf..1d00da1266c 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -60,7 +60,7 @@
pre {
border: none;
- background: #f9f9f9;
+ background: $gray-light;
border-radius: 0;
color: #777;
margin: 0 20px;
@@ -92,7 +92,7 @@
border: 1px solid #eee;
padding: 5px;
@include border-radius(5px);
- background: #f9f9f9;
+ background: $gray-light;
margin-left: 10px;
top: -6px;
img {
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 3a3bb10feac..910700b0206 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -72,12 +72,12 @@ form.edit-issue {
}
&.closed {
- background: #f9f9f9;
+ background: $gray-light;
border-color: #e5e5e5;
}
&.merged {
- background: #f9f9f9;
+ background: $gray-light;
border-color: #e5e5e5;
}
}
diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss
index 606459f82cd..38c7cd98e41 100644
--- a/app/assets/stylesheets/pages/labels.scss
+++ b/app/assets/stylesheets/pages/labels.scss
@@ -7,6 +7,7 @@
display: inline-block;
margin-right: 10px;
margin-bottom: 10px;
+ text-decoration: none;
}
&.suggest-colors-dropdown {
diff --git a/app/assets/stylesheets/pages/merge_conflicts.scss b/app/assets/stylesheets/pages/merge_conflicts.scss
index 1f499897c16..5ec660799e3 100644
--- a/app/assets/stylesheets/pages/merge_conflicts.scss
+++ b/app/assets/stylesheets/pages/merge_conflicts.scss
@@ -16,7 +16,7 @@ $colors: (
white_button_origin_chosen : #268ced,
white_header_not_chosen : #f0f0f0,
- white_line_not_chosen : #f9f9f9,
+ white_line_not_chosen : $gray-light,
dark_header_head_neutral : rgba(#3f3, .2),
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index 0340526a53a..68a5d1ae06c 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -99,7 +99,7 @@
pre {
border: none;
- background: #f9f9f9;
+ background: $gray-light;
border-radius: 0;
color: #777;
margin: 0 20px;
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index e330300f9a1..1778c069706 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -11,6 +11,10 @@
}
}
+ .add-to-tree {
+ vertical-align: top;
+ }
+
.tree-table {
margin-bottom: 0;
diff --git a/app/assets/stylesheets/pages/xterm.scss b/app/assets/stylesheets/pages/xterm.scss
index 8d855ce99b0..c9846103762 100644
--- a/app/assets/stylesheets/pages/xterm.scss
+++ b/app/assets/stylesheets/pages/xterm.scss
@@ -20,6 +20,9 @@
$l-cyan: #8abeb7;
$l-white: $ci-text-color;
+ .term-bold {
+ font-weight: bold;
+ }
.term-italic {
font-style: italic;
}
diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb
index 12195c3cbb8..77934ff9962 100644
--- a/app/controllers/projects/builds_controller.rb
+++ b/app/controllers/projects/builds_controller.rb
@@ -78,8 +78,8 @@ class Projects::BuildsController < Projects::ApplicationController
end
def raw
- if @build.has_trace?
- send_file @build.path_to_trace, type: 'text/plain; charset=utf-8', disposition: 'inline'
+ if @build.has_trace_file?
+ send_file @build.trace_file_path, type: 'text/plain; charset=utf-8', disposition: 'inline'
else
render_404
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index d6efa603223..4c685b97c03 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -431,6 +431,6 @@ module ProjectsHelper
options.delete('Everyone with access') if @project.private? && level != ProjectFeature::ENABLED
options = options_for_select(options, selected: @project.project_feature.public_send(field) || ProjectFeature::ENABLED)
- content_tag(:select, options, name: "project[project_feature_attributes][#{field.to_s}]", id: "project_project_feature_attributes_#{field.to_s}", class: "pull-right form-control").html_safe
+ content_tag(:select, options, name: "project[project_feature_attributes][#{field.to_s}]", id: "project_project_feature_attributes_#{field.to_s}", class: "pull-right form-control", data: { field: field }).html_safe
end
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 23c8de6f650..61052437318 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -208,22 +208,31 @@ module Ci
end
end
+ def has_trace_file?
+ File.exist?(path_to_trace) || has_old_trace_file?
+ end
+
def has_trace?
raw_trace.present?
end
def raw_trace
- if File.file?(path_to_trace)
- File.read(path_to_trace)
- elsif project.ci_id && File.file?(old_path_to_trace)
- # Temporary fix for build trace data integrity
- File.read(old_path_to_trace)
+ if File.exist?(trace_file_path)
+ File.read(trace_file_path)
else
# backward compatibility
read_attribute :trace
end
end
+ ##
+ # Deprecated
+ #
+ # This is a hotfix for CI build data integrity, see #4246
+ def has_old_trace_file?
+ project.ci_id && File.exist?(old_path_to_trace)
+ end
+
def trace
trace = raw_trace
if project && trace.present? && project.runners_token.present?
@@ -262,6 +271,14 @@ module Ci
end
end
+ def trace_file_path
+ if has_old_trace_file?
+ old_path_to_trace
+ else
+ path_to_trace
+ end
+ end
+
def dir_to_trace
File.join(
Settings.gitlab_ci.builds_path,
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 290742f1506..e57791f6818 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -83,7 +83,7 @@ module MergeRequests
closes_issue = "Closes ##{iid}"
if merge_request.description.present?
- merge_request.description += closes_issue.prepend("\n")
+ merge_request.description += closes_issue.prepend("\n\n")
else
merge_request.description = closes_issue
end
diff --git a/app/views/groups/group_members/update.js.haml b/app/views/groups/group_members/update.js.haml
index 742f9d7a433..3be7ed8432c 100644
--- a/app/views/groups/group_members/update.js.haml
+++ b/app/views/groups/group_members/update.js.haml
@@ -1,3 +1,3 @@
:plain
$("##{dom_id(@group_member)}").replaceWith('#{escape_javascript(render('shared/members/member', member: @group_member))}');
- new MemberExpirationDate();
+ new gl.MemberExpirationDate();
diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml
index 19b4249374b..14eb47089b1 100644
--- a/app/views/projects/_merge_request_settings.html.haml
+++ b/app/views/projects/_merge_request_settings.html.haml
@@ -1,11 +1,14 @@
-%fieldset.builds-feature
- %h5.prepend-top-0
- Merge Requests
- .form-group
- .checkbox
- = f.label :only_allow_merge_if_build_succeeds do
- = f.check_box :only_allow_merge_if_build_succeeds
- %strong Only allow merge requests to be merged if the build succeeds
- .help-block
- Builds need to be configured to enable this feature.
- = link_to icon('question-circle'), help_page_path('workflow/merge_requests', anchor: 'only-allow-merge-requests-to-be-merged-if-the-build-succeeds')
+.merge-requests-feature
+ %fieldset.builds-feature
+ %hr
+ %h5.prepend-top-0
+ Merge Requests
+ .form-group
+ .checkbox
+ = f.label :only_allow_merge_if_build_succeeds do
+ = f.check_box :only_allow_merge_if_build_succeeds
+ %strong Only allow merge requests to be merged if the build succeeds
+ %br
+ %span.descr
+ Builds need to be configured to enable this feature.
+ = link_to icon('question-circle'), help_page_path('workflow/merge_requests', anchor: 'only-allow-merge-requests-to-be-merged-if-the-build-succeeds')
diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml
index 5b0b58e087b..5ce36a475a9 100644
--- a/app/views/projects/builds/_sidebar.html.haml
+++ b/app/views/projects/builds/_sidebar.html.haml
@@ -1,3 +1,6 @@
+- builds = @build.pipeline.builds.latest.to_a
+- statuses = ["failed", "pending", "running", "canceled", "success", "skipped"]
+
%aside.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar
.block.build-sidebar-header.visible-xs-block.visible-sm-block.append-bottom-default
Build
@@ -11,40 +14,6 @@
%p.build-detail-row
#{@build.coverage}%
- - builds = @build.pipeline.builds.latest.to_a
- - statuses = ["failed", "pending", "running", "canceled", "success", "skipped"]
- - if builds.size > 1
- .dropdown.build-dropdown
- .build-light-text Stage
- %button.dropdown-menu-toggle{type: 'button', 'data-toggle' => 'dropdown'}
- %span.stage-selection More
- = icon('caret-down')
- %ul.dropdown-menu
- - builds.map(&:stage).uniq.each do |stage|
- %li
- %a.stage-item= stage
-
- .builds-container
- - statuses.each do |build_status|
- - builds.select{|build| build.status == build_status}.each do |build|
- .build-job{class: ('active' if build == @build), data: {stage: build.stage}}
- = link_to namespace_project_build_path(@project.namespace, @project, build) do
- = icon('check')
- = ci_icon_for_status(build.status)
- %span
- - if build.name
- = build.name
- - else
- = build.id
-
- - if @build.retried?
- %li.active
- %a
- Build ##{@build.id}
- &middot;
- %i.fa.fa-warning
- This build was retried.
-
.blocks-container
- if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?)
.block{ class: ("block-first" if !@build.coverage) }
@@ -76,7 +45,7 @@
.title
Build details
- if can?(current_user, :update_build, @build) && @build.retryable?
- = link_to "Retry", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'pull-right', method: :post
+ = link_to "Retry", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'pull-right retry-link', method: :post
- if @build.merge_request
%p.build-detail-row
%span.build-light-text Merge Request:
@@ -100,7 +69,7 @@
- elsif @build.runner
\##{@build.runner.id}
.btn-group.btn-group-justified{ role: :group }
- - if @build.has_trace?
+ - if @build.has_trace_file?
= link_to 'Raw', raw_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default'
- if @build.active?
= link_to "Cancel", cancel_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post
@@ -141,3 +110,35 @@
- @build.tag_list.each do |tag|
%span.label.label-primary
= tag
+
+ - if builds.size > 1
+ .dropdown.build-dropdown
+ .title Stage
+ %button.dropdown-menu-toggle{type: 'button', 'data-toggle' => 'dropdown'}
+ %span.stage-selection More
+ = icon('caret-down')
+ %ul.dropdown-menu
+ - builds.map(&:stage).uniq.each do |stage|
+ %li
+ %a.stage-item= stage
+
+ .builds-container
+ - statuses.each do |build_status|
+ - builds.select{|build| build.status == build_status}.each do |build|
+ .build-job{class: ('active' if build == @build), data: {stage: build.stage}}
+ = link_to namespace_project_build_path(@project.namespace, @project, build) do
+ = icon('check')
+ = ci_icon_for_status(build.status)
+ %span
+ - if build.name
+ = build.name
+ - else
+ = build.id
+
+ - if @build.retried?
+ %li.active
+ %a
+ Build ##{@build.id}
+ &middot;
+ %i.fa.fa-warning
+ This build was retried.
diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml
index d78888e9fe4..22db33498f1 100644
--- a/app/views/projects/buttons/_fork.html.haml
+++ b/app/views/projects/buttons/_fork.html.haml
@@ -3,11 +3,11 @@
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has-tooltip' do
= custom_icon('icon_fork')
- Fork
+ %span Fork
- else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has-tooltip' do
= custom_icon('icon_fork')
- Fork
+ %span Fork
%div.count-with-arrow
%span.arrow
= link_to namespace_project_forks_path(@project.namespace, @project), class: "count" do
diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml
index a1d79bdabda..bacc5708e4b 100644
--- a/app/views/projects/forks/index.html.haml
+++ b/app/views/projects/forks/index.html.haml
@@ -32,11 +32,11 @@
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do
= custom_icon('icon_fork')
- Fork
+ %span Fork
- else
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-new' do
= custom_icon('icon_fork')
- Fork
+ %span Fork
= render 'projects', projects: @forks
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index 24749699c6d..33556a1a2b3 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -1,13 +1,12 @@
- if can?(current_user, :push_code, @project)
.pull-right
#new-branch{'data-path' => can_create_branch_namespace_project_issue_path(@project.namespace, @project, @issue)}
+ = link_to '#', class: 'checking btn btn-grouped', disabled: 'disabled' do
+ = icon('spinner spin')
+ Checking branches
= link_to namespace_project_branches_path(@project.namespace, @project, branch_name: @issue.to_branch_name, issue_iid: @issue.iid),
- method: :post, class: 'btn btn-new btn-inverted has-tooltip', title: @issue.to_branch_name, disabled: 'disabled' do
- .checking
- = icon('spinner spin')
- Checking branches
- .available.hide
- New branch
- .unavailable.hide
- = icon('exclamation-triangle')
- New branch unavailable
+ method: :post, class: 'btn btn-new btn-inverted btn-grouped has-tooltip available hide', title: @issue.to_branch_name do
+ New branch
+ = link_to '#', class: 'unavailable btn btn-grouped hide', disabled: 'disabled' do
+ = icon('exclamation-triangle')
+ New branch unavailable
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 0a1e2bb2cc6..fda0592dd41 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -55,7 +55,7 @@
= render 'bitbucket_import_modal'
%div
- if gitlab_import_enabled?
- = link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless bitbucket_import_configured?}" do
+ = link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}" do
= icon('gitlab', text: 'GitLab.com')
- unless gitlab_import_configured?
= render 'gitlab_import_modal'
diff --git a/app/views/projects/project_members/update.js.haml b/app/views/projects/project_members/update.js.haml
index 833954bc039..37e55dc72a3 100644
--- a/app/views/projects/project_members/update.js.haml
+++ b/app/views/projects/project_members/update.js.haml
@@ -1,3 +1,3 @@
:plain
$("##{dom_id(@project_member)}").replaceWith('#{escape_javascript(render('shared/members/member', member: @project_member))}');
- new MemberExpirationDate();
+ new gl.MemberExpirationDate();
diff --git a/doc/api/README.md b/doc/api/README.md
index 3e79cce0120..96d94e08487 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -11,9 +11,10 @@ following locations:
- [Award Emoji](award_emoji.md)
- [Branches](branches.md)
- [Builds](builds.md)
-- [Build triggers](build_triggers.md)
+- [Build Triggers](build_triggers.md)
- [Build Variables](build_variables.md)
- [Commits](commits.md)
+- [Deployments](deployments.md)
- [Deploy Keys](deploy_keys.md)
- [Groups](groups.md)
- [Group Access Requests](access_requests.md)
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index 5b54c11ef62..6e6efece7c4 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -105,15 +105,19 @@ module API
post '/two_factor_recovery_codes' do
status 200
- key = Key.find(params[:key_id])
- user = key.user
+ key = Key.find_by(id: params[:key_id])
+
+ unless key
+ return { 'success' => false, 'message' => 'Could not find the given key' }
+ end
- # Make sure this isn't a deploy key
- unless key.type.nil?
+ if key.is_a?(DeployKey)
return { success: false, message: 'Deploy keys cannot be used to retrieve recovery codes' }
end
- unless user.present?
+ user = key.user
+
+ unless user
return { success: false, message: 'Could not find a user for the given key' }
end
diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb
index 688f68d3cff..8863554ee91 100644
--- a/spec/features/expand_collapse_diffs_spec.rb
+++ b/spec/features/expand_collapse_diffs_spec.rb
@@ -211,6 +211,13 @@ feature 'Expand and collapse diffs', js: true, feature: true do
context 'expanding all diffs' do
before do
click_link('Expand all')
+
+ # Wait for elements to appear to ensure full page reload
+ expect(page).to have_content('This diff was suppressed by a .gitattributes entry')
+ expect(page).to have_content('This diff could not be displayed because it is too large.')
+ expect(page).to have_content('too_large_image.jpg')
+ find('.note-textarea')
+
wait_for_ajax
execute_script('window.ajaxUris = []; $(document).ajaxSend(function(event, xhr, settings) { ajaxUris.push(settings.url) });')
end
diff --git a/spec/features/projects/builds_spec.rb b/spec/features/projects/builds_spec.rb
index 0cfeb2e57d8..d5d571e49bc 100644
--- a/spec/features/projects/builds_spec.rb
+++ b/spec/features/projects/builds_spec.rb
@@ -1,4 +1,5 @@
require 'spec_helper'
+require 'tempfile'
describe "Builds" do
let(:artifacts_file) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') }
@@ -6,7 +7,7 @@ describe "Builds" do
before do
login_as(:user)
@commit = FactoryGirl.create :ci_pipeline
- @build = FactoryGirl.create :ci_build, pipeline: @commit
+ @build = FactoryGirl.create :ci_build, :trace, pipeline: @commit
@build2 = FactoryGirl.create :ci_build
@project = @commit.project
@project.team << [@user, :developer]
@@ -156,7 +157,6 @@ describe "Builds" do
context 'Build raw trace' do
before do
@build.run!
- @build.trace = 'BUILD TRACE'
visit namespace_project_build_path(@project.namespace, @project, @build)
end
@@ -255,35 +255,101 @@ describe "Builds" do
end
end
- describe "GET /:project/builds/:id/raw" do
- context "Build from project" do
- before do
- Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
- @build.run!
- @build.trace = 'BUILD TRACE'
- visit namespace_project_build_path(@project.namespace, @project, @build)
- page.within('.js-build-sidebar') { click_link 'Raw' }
+ describe 'GET /:project/builds/:id/raw' do
+ context 'access source' do
+ context 'build from project' do
+ before do
+ Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
+ @build.run!
+ visit namespace_project_build_path(@project.namespace, @project, @build)
+ page.within('.js-build-sidebar') { click_link 'Raw' }
+ end
+
+ it 'sends the right headers' do
+ expect(page.status_code).to eq(200)
+ expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
+ expect(page.response_headers['X-Sendfile']).to eq(@build.path_to_trace)
+ end
end
- it 'sends the right headers' do
- expect(page.status_code).to eq(200)
- expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
- expect(page.response_headers['X-Sendfile']).to eq(@build.path_to_trace)
+ context 'build from other project' do
+ before do
+ Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
+ @build2.run!
+ visit raw_namespace_project_build_path(@project.namespace, @project, @build2)
+ end
+
+ it 'sends the right headers' do
+ expect(page.status_code).to eq(404)
+ end
end
end
- context "Build from other project" do
- before do
- Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
- @build2.run!
- @build2.trace = 'BUILD TRACE'
- visit raw_namespace_project_build_path(@project.namespace, @project, @build2)
- puts page.status_code
- puts current_url
+ context 'storage form' do
+ let(:existing_file) { Tempfile.new('existing-trace-file').path }
+ let(:non_existing_file) do
+ file = Tempfile.new('non-existing-trace-file')
+ path = file.path
+ file.unlink
+ path
end
- it 'sends the right headers' do
- expect(page.status_code).to eq(404)
+ context 'when build has trace in file' do
+ before do
+ Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
+ @build.run!
+ visit namespace_project_build_path(@project.namespace, @project, @build)
+
+ allow_any_instance_of(Project).to receive(:ci_id).and_return(nil)
+ allow_any_instance_of(Ci::Build).to receive(:path_to_trace).and_return(existing_file)
+ allow_any_instance_of(Ci::Build).to receive(:old_path_to_trace).and_return(non_existing_file)
+
+ page.within('.js-build-sidebar') { click_link 'Raw' }
+ end
+
+ it 'sends the right headers' do
+ expect(page.status_code).to eq(200)
+ expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
+ expect(page.response_headers['X-Sendfile']).to eq(existing_file)
+ end
+ end
+
+ context 'when build has trace in old file' do
+ before do
+ Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
+ @build.run!
+ visit namespace_project_build_path(@project.namespace, @project, @build)
+
+ allow_any_instance_of(Project).to receive(:ci_id).and_return(999)
+ allow_any_instance_of(Ci::Build).to receive(:path_to_trace).and_return(non_existing_file)
+ allow_any_instance_of(Ci::Build).to receive(:old_path_to_trace).and_return(existing_file)
+
+ page.within('.js-build-sidebar') { click_link 'Raw' }
+ end
+
+ it 'sends the right headers' do
+ expect(page.status_code).to eq(200)
+ expect(page.response_headers['Content-Type']).to eq('text/plain; charset=utf-8')
+ expect(page.response_headers['X-Sendfile']).to eq(existing_file)
+ end
+ end
+
+ context 'when build has trace in DB' do
+ before do
+ Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile')
+ @build.run!
+ visit namespace_project_build_path(@project.namespace, @project, @build)
+
+ allow_any_instance_of(Project).to receive(:ci_id).and_return(nil)
+ allow_any_instance_of(Ci::Build).to receive(:path_to_trace).and_return(non_existing_file)
+ allow_any_instance_of(Ci::Build).to receive(:old_path_to_trace).and_return(non_existing_file)
+
+ page.within('.js-build-sidebar') { click_link 'Raw' }
+ end
+
+ it 'sends the right headers' do
+ expect(page.status_code).to eq(404)
+ end
end
end
end
diff --git a/spec/features/projects/edit_spec.rb b/spec/features/projects/edit_spec.rb
new file mode 100644
index 00000000000..a1643fd1f43
--- /dev/null
+++ b/spec/features/projects/edit_spec.rb
@@ -0,0 +1,57 @@
+require 'rails_helper'
+
+feature 'Project edit', feature: true, js: true do
+ include WaitForAjax
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+
+ before do
+ project.team << [user, :master]
+ login_as(user)
+
+ visit edit_namespace_project_path(project.namespace, project)
+ end
+
+ context 'feature visibility' do
+ context 'merge requests select' do
+ it 'hides merge requests section' do
+ select('Disabled', from: 'project_project_feature_attributes_merge_requests_access_level')
+
+ expect(page).to have_selector('.merge-requests-feature', visible: false)
+ end
+
+ it 'hides merge requests section after save' do
+ select('Disabled', from: 'project_project_feature_attributes_merge_requests_access_level')
+
+ expect(page).to have_selector('.merge-requests-feature', visible: false)
+
+ click_button 'Save changes'
+
+ wait_for_ajax
+
+ expect(page).to have_selector('.merge-requests-feature', visible: false)
+ end
+ end
+
+ context 'builds select' do
+ it 'hides merge requests section' do
+ select('Disabled', from: 'project_project_feature_attributes_builds_access_level')
+
+ expect(page).to have_selector('.builds-feature', visible: false)
+ end
+
+ it 'hides merge requests section after save' do
+ select('Disabled', from: 'project_project_feature_attributes_builds_access_level')
+
+ expect(page).to have_selector('.builds-feature', visible: false)
+
+ click_button 'Save changes'
+
+ wait_for_ajax
+
+ expect(page).to have_selector('.builds-feature', visible: false)
+ end
+ end
+ end
+end
diff --git a/spec/javascripts/datetime_utility_spec.js.coffee b/spec/javascripts/datetime_utility_spec.js.coffee
deleted file mode 100644
index 8bd113e7d86..00000000000
--- a/spec/javascripts/datetime_utility_spec.js.coffee
+++ /dev/null
@@ -1,50 +0,0 @@
-#= require lib/utils/datetime_utility
-
-describe 'Date time utils', ->
- describe 'get day name', ->
- it 'should return Sunday', ->
- day = gl.utils.getDayName(new Date('07/17/2016'))
- expect(day).toBe('Sunday')
-
- it 'should return Monday', ->
- day = gl.utils.getDayName(new Date('07/18/2016'))
- expect(day).toBe('Monday')
-
- it 'should return Tuesday', ->
- day = gl.utils.getDayName(new Date('07/19/2016'))
- expect(day).toBe('Tuesday')
-
- it 'should return Wednesday', ->
- day = gl.utils.getDayName(new Date('07/20/2016'))
- expect(day).toBe('Wednesday')
-
- it 'should return Thursday', ->
- day = gl.utils.getDayName(new Date('07/21/2016'))
- expect(day).toBe('Thursday')
-
- it 'should return Friday', ->
- day = gl.utils.getDayName(new Date('07/22/2016'))
- expect(day).toBe('Friday')
-
- it 'should return Saturday', ->
- day = gl.utils.getDayName(new Date('07/23/2016'))
- expect(day).toBe('Saturday')
-
- describe 'get day difference', ->
- it 'should return 7', ->
- firstDay = new Date('07/01/2016')
- secondDay = new Date('07/08/2016')
- difference = gl.utils.getDayDifference(firstDay, secondDay)
- expect(difference).toBe(7)
-
- it 'should return 31', ->
- firstDay = new Date('07/01/2016')
- secondDay = new Date('08/01/2016')
- difference = gl.utils.getDayDifference(firstDay, secondDay)
- expect(difference).toBe(31)
-
- it 'should return 365', ->
- firstDay = new Date('07/02/2015')
- secondDay = new Date('07/01/2016')
- difference = gl.utils.getDayDifference(firstDay, secondDay)
- expect(difference).toBe(365) \ No newline at end of file
diff --git a/spec/javascripts/datetime_utility_spec.js.es6 b/spec/javascripts/datetime_utility_spec.js.es6
new file mode 100644
index 00000000000..a2d1b0a7732
--- /dev/null
+++ b/spec/javascripts/datetime_utility_spec.js.es6
@@ -0,0 +1,64 @@
+//= require lib/utils/datetime_utility
+(() => {
+ describe('Date time utils', () => {
+ describe('get day name', () => {
+ it('should return Sunday', () => {
+ const day = gl.utils.getDayName(new Date('07/17/2016'));
+ expect(day).toBe('Sunday');
+ });
+
+ it('should return Monday', () => {
+ const day = gl.utils.getDayName(new Date('07/18/2016'));
+ expect(day).toBe('Monday');
+ });
+
+ it('should return Tuesday', () => {
+ const day = gl.utils.getDayName(new Date('07/19/2016'));
+ expect(day).toBe('Tuesday');
+ });
+
+ it('should return Wednesday', () => {
+ const day = gl.utils.getDayName(new Date('07/20/2016'));
+ expect(day).toBe('Wednesday');
+ });
+
+ it('should return Thursday', () => {
+ const day = gl.utils.getDayName(new Date('07/21/2016'));
+ expect(day).toBe('Thursday');
+ });
+
+ it('should return Friday', () => {
+ const day = gl.utils.getDayName(new Date('07/22/2016'));
+ expect(day).toBe('Friday');
+ });
+
+ it('should return Saturday', () => {
+ const day = gl.utils.getDayName(new Date('07/23/2016'));
+ expect(day).toBe('Saturday');
+ });
+ });
+
+ describe('get day difference', () => {
+ it('should return 7', () => {
+ const firstDay = new Date('07/01/2016');
+ const secondDay = new Date('07/08/2016');
+ const difference = gl.utils.getDayDifference(firstDay, secondDay);
+ expect(difference).toBe(7);
+ });
+
+ it('should return 31', () => {
+ const firstDay = new Date('07/01/2016');
+ const secondDay = new Date('08/01/2016');
+ const difference = gl.utils.getDayDifference(firstDay, secondDay);
+ expect(difference).toBe(31);
+ });
+
+ it('should return 365', () => {
+ const firstDay = new Date('07/02/2015');
+ const secondDay = new Date('07/01/2016');
+ const difference = gl.utils.getDayDifference(firstDay, secondDay);
+ expect(difference).toBe(365);
+ });
+ });
+ });
+})();
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 36d10636ae9..bce18b4e99e 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -19,4 +19,64 @@ describe Ci::Build, models: true do
expect(build.trace).to eq(test_trace)
end
end
+
+ describe '#has_trace_file?' do
+ context 'when there is no trace' do
+ it { expect(build.has_trace_file?).to be_falsey }
+ it { expect(build.trace).to be_nil }
+ end
+
+ context 'when there is a trace' do
+ context 'when trace is stored in file' do
+ let(:build_with_trace) { create(:ci_build, :trace) }
+
+ it { expect(build_with_trace.has_trace_file?).to be_truthy }
+ it { expect(build_with_trace.trace).to eq('BUILD TRACE') }
+ end
+
+ context 'when trace is stored in old file' do
+ before do
+ allow(build.project).to receive(:ci_id).and_return(999)
+ allow(File).to receive(:exist?).with(build.path_to_trace).and_return(false)
+ allow(File).to receive(:exist?).with(build.old_path_to_trace).and_return(true)
+ allow(File).to receive(:read).with(build.old_path_to_trace).and_return(test_trace)
+ end
+
+ it { expect(build.has_trace_file?).to be_truthy }
+ it { expect(build.trace).to eq(test_trace) }
+ end
+
+ context 'when trace is stored in DB' do
+ before do
+ allow(build.project).to receive(:ci_id).and_return(nil)
+ allow(build).to receive(:read_attribute).with(:trace).and_return(test_trace)
+ allow(File).to receive(:exist?).with(build.path_to_trace).and_return(false)
+ allow(File).to receive(:exist?).with(build.old_path_to_trace).and_return(false)
+ end
+
+ it { expect(build.has_trace_file?).to be_falsey }
+ it { expect(build.trace).to eq(test_trace) }
+ end
+ end
+ end
+
+ describe '#trace_file_path' do
+ context 'when trace is stored in file' do
+ before do
+ allow(build).to receive(:has_trace_file?).and_return(true)
+ allow(build).to receive(:has_old_trace_file?).and_return(false)
+ end
+
+ it { expect(build.trace_file_path).to eq(build.path_to_trace) }
+ end
+
+ context 'when trace is stored in old file' do
+ before do
+ allow(build).to receive(:has_trace_file?).and_return(true)
+ allow(build).to receive(:has_old_trace_file?).and_return(true)
+ end
+
+ it { expect(build.trace_file_path).to eq(build.old_path_to_trace) }
+ end
+ end
end
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index 5d06abcfeb3..46d1b868782 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -44,8 +44,8 @@ describe API::API, api: true do
secret_token: secret_token,
key_id: 12345
- expect(response).to have_http_status(404)
- expect(json_response['message']).to eq('404 Not found')
+ expect(json_response['success']).to be_falsey
+ expect(json_response['message']).to eq('Could not find the given key')
end
it 'returns an error message when the key is a deploy key' do
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
index 232508cda23..0d586e2216b 100644
--- a/spec/services/merge_requests/build_service_spec.rb
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -99,14 +99,14 @@ describe MergeRequests::BuildService, services: true do
let(:source_branch) { "#{issue.iid}-fix-issue" }
it 'appends "Closes #$issue-iid" to the description' do
- expect(merge_request.description).to eq("#{commit_1.safe_message.split(/\n+/, 2).last}\nCloses ##{issue.iid}")
+ expect(merge_request.description).to eq("#{commit_1.safe_message.split(/\n+/, 2).last}\n\nCloses ##{issue.iid}")
end
context 'merge request already has a description set' do
let(:description) { 'Merge request description' }
it 'appends "Closes #$issue-iid" to the description' do
- expect(merge_request.description).to eq("#{description}\nCloses ##{issue.iid}")
+ expect(merge_request.description).to eq("#{description}\n\nCloses ##{issue.iid}")
end
end