Merge branch 'master' into 28433-internationalise-cycle-analytics-page
This commit is contained in:
commit
302e855f52
3
Gemfile
3
Gemfile
|
@ -73,6 +73,9 @@ gem 'grape', '~> 0.19.0'
|
|||
gem 'grape-entity', '~> 0.6.0'
|
||||
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
|
||||
|
||||
# Disable strong_params so that Mash does not respond to :permitted?
|
||||
gem 'hashie-forbidden_attributes'
|
||||
|
||||
# Pagination
|
||||
gem 'kaminari', '~> 0.17.0'
|
||||
|
||||
|
|
|
@ -336,7 +336,7 @@ GEM
|
|||
grape-entity (0.6.0)
|
||||
activesupport
|
||||
multi_json (>= 1.3.2)
|
||||
grpc (1.2.2)
|
||||
grpc (1.1.2)
|
||||
google-protobuf (~> 3.1)
|
||||
googleauth (~> 0.5.1)
|
||||
haml (4.0.7)
|
||||
|
@ -352,6 +352,8 @@ GEM
|
|||
tilt
|
||||
hashdiff (0.3.2)
|
||||
hashie (3.5.5)
|
||||
hashie-forbidden_attributes (0.1.1)
|
||||
hashie (>= 3.0)
|
||||
health_check (2.6.0)
|
||||
rails (>= 4.0)
|
||||
hipchat (1.5.2)
|
||||
|
@ -925,6 +927,7 @@ DEPENDENCIES
|
|||
grape-entity (~> 0.6.0)
|
||||
haml_lint (~> 0.21.0)
|
||||
hamlit (~> 2.6.1)
|
||||
hashie-forbidden_attributes
|
||||
health_check (~> 2.6.0)
|
||||
hipchat (~> 1.5.0)
|
||||
html-pipeline (~> 1.11.0)
|
||||
|
|
|
@ -7,7 +7,6 @@ import boardBlankState from './board_blank_state';
|
|||
require('./board_delete');
|
||||
require('./board_list');
|
||||
|
||||
(() => {
|
||||
const Store = gl.issueBoards.BoardsStore;
|
||||
|
||||
window.gl = window.gl || {};
|
||||
|
@ -103,4 +102,3 @@ require('./board_list');
|
|||
this.sortable = Sortable.create(this.$el.parentNode, this.sortableOptions);
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import Vue from 'vue';
|
||||
|
||||
(() => {
|
||||
window.gl = window.gl || {};
|
||||
window.gl.issueBoards = window.gl.issueBoards || {};
|
||||
|
||||
|
@ -20,4 +19,3 @@ import Vue from 'vue';
|
|||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -8,7 +8,6 @@ import Vue from 'vue';
|
|||
|
||||
require('./sidebar/remove_issue');
|
||||
|
||||
(() => {
|
||||
const Store = gl.issueBoards.BoardsStore;
|
||||
|
||||
window.gl = window.gl || {};
|
||||
|
@ -70,4 +69,3 @@ require('./sidebar/remove_issue');
|
|||
removeBtn: gl.issueBoards.RemoveIssueBtn,
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Vue from 'vue';
|
||||
import eventHub from '../eventhub';
|
||||
|
||||
(() => {
|
||||
const Store = gl.issueBoards.BoardsStore;
|
||||
|
||||
window.gl = window.gl || {};
|
||||
|
@ -138,4 +137,3 @@ import eventHub from '../eventhub';
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
(() => {
|
||||
const ModalStore = gl.issueBoards.ModalStore;
|
||||
|
||||
gl.issueBoards.ModalEmptyState = Vue.extend({
|
||||
|
@ -68,4 +67,3 @@ import Vue from 'vue';
|
|||
</section>
|
||||
`,
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -5,7 +5,6 @@ import Vue from 'vue';
|
|||
|
||||
require('./lists_dropdown');
|
||||
|
||||
(() => {
|
||||
const ModalStore = gl.issueBoards.ModalStore;
|
||||
|
||||
gl.issueBoards.ModalFooter = Vue.extend({
|
||||
|
@ -81,4 +80,3 @@ require('./lists_dropdown');
|
|||
</footer>
|
||||
`,
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -3,7 +3,6 @@ import modalFilters from './filters';
|
|||
|
||||
require('./tabs');
|
||||
|
||||
(() => {
|
||||
const ModalStore = gl.issueBoards.ModalStore;
|
||||
|
||||
gl.issueBoards.ModalHeader = Vue.extend({
|
||||
|
@ -79,4 +78,3 @@ require('./tabs');
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -8,7 +8,6 @@ require('./list');
|
|||
require('./footer');
|
||||
require('./empty_state');
|
||||
|
||||
(() => {
|
||||
const ModalStore = gl.issueBoards.ModalStore;
|
||||
|
||||
gl.issueBoards.IssuesModal = Vue.extend({
|
||||
|
@ -164,4 +163,3 @@ require('./empty_state');
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import Vue from 'vue';
|
||||
|
||||
(() => {
|
||||
const ModalStore = gl.issueBoards.ModalStore;
|
||||
|
||||
gl.issueBoards.ModalList = Vue.extend({
|
||||
|
@ -158,4 +157,3 @@ import Vue from 'vue';
|
|||
</section>
|
||||
`,
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
(() => {
|
||||
const ModalStore = gl.issueBoards.ModalStore;
|
||||
|
||||
gl.issueBoards.ModalFooterListsDropdown = Vue.extend({
|
||||
|
@ -54,4 +53,3 @@ import Vue from 'vue';
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
(() => {
|
||||
const ModalStore = gl.issueBoards.ModalStore;
|
||||
|
||||
gl.issueBoards.ModalTabs = Vue.extend({
|
||||
|
@ -45,4 +44,3 @@ import Vue from 'vue';
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* eslint-disable comma-dangle, func-names, no-new, space-before-function-paren, one-var */
|
||||
|
||||
(() => {
|
||||
window.gl = window.gl || {};
|
||||
window.gl.issueBoards = window.gl.issueBoards || {};
|
||||
|
||||
|
@ -73,4 +72,3 @@
|
|||
});
|
||||
});
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import Vue from 'vue';
|
||||
|
||||
(() => {
|
||||
const Store = gl.issueBoards.BoardsStore;
|
||||
|
||||
window.gl = window.gl || {};
|
||||
|
@ -58,4 +57,3 @@ import Vue from 'vue';
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
(() => {
|
||||
const ModalStore = gl.issueBoards.ModalStore;
|
||||
|
||||
gl.issueBoards.ModalMixins = {
|
||||
|
@ -11,4 +10,3 @@
|
|||
},
|
||||
},
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* eslint-disable no-unused-vars, no-mixed-operators, comma-dangle */
|
||||
/* global DocumentTouch */
|
||||
|
||||
((w) => {
|
||||
window.gl = window.gl || {};
|
||||
window.gl.issueBoards = window.gl.issueBoards || {};
|
||||
|
||||
|
@ -36,4 +35,3 @@
|
|||
Object.keys(obj).forEach((key) => { defaultSortOptions[key] = obj[key]; });
|
||||
return defaultSortOptions;
|
||||
};
|
||||
})(window);
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import Cookies from 'js-cookie';
|
||||
|
||||
(() => {
|
||||
window.gl = window.gl || {};
|
||||
window.gl.issueBoards = window.gl.issueBoards || {};
|
||||
|
||||
|
@ -124,4 +123,3 @@ import Cookies from 'js-cookie';
|
|||
history.pushState(null, null, `?${this.filter.path}`);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
(() => {
|
||||
window.gl = window.gl || {};
|
||||
window.gl.issueBoards = window.gl.issueBoards || {};
|
||||
|
||||
|
@ -97,4 +96,3 @@
|
|||
}
|
||||
|
||||
gl.issueBoards.ModalStore = new ModalStore();
|
||||
})();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Vue from 'vue';
|
||||
|
||||
((global) => {
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageCodeComponent = Vue.extend({
|
||||
|
@ -44,4 +44,3 @@ import Vue from 'vue';
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Vue from 'vue';
|
||||
|
||||
((global) => {
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageIssueComponent = Vue.extend({
|
||||
|
@ -46,4 +46,3 @@ import Vue from 'vue';
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import Vue from 'vue';
|
||||
import iconCommit from '../svg/icon_commit.svg';
|
||||
|
||||
((global) => {
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StagePlanComponent = Vue.extend({
|
||||
|
@ -48,4 +48,3 @@ import iconCommit from '../svg/icon_commit.svg';
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Vue from 'vue';
|
||||
|
||||
((global) => {
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageProductionComponent = Vue.extend({
|
||||
|
@ -46,4 +46,3 @@ import Vue from 'vue';
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Vue from 'vue';
|
||||
|
||||
((global) => {
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageReviewComponent = Vue.extend({
|
||||
|
@ -56,4 +56,3 @@ import Vue from 'vue';
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import Vue from 'vue';
|
||||
import iconBranch from '../svg/icon_branch.svg';
|
||||
|
||||
((global) => {
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageStagingComponent = Vue.extend({
|
||||
|
@ -46,4 +46,3 @@ import iconBranch from '../svg/icon_branch.svg';
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -3,7 +3,7 @@ import Vue from 'vue';
|
|||
import iconBuildStatus from '../svg/icon_build_status.svg';
|
||||
import iconBranch from '../svg/icon_branch.svg';
|
||||
|
||||
((global) => {
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.StageTestComponent = Vue.extend({
|
||||
|
@ -47,4 +47,3 @@ import iconBranch from '../svg/icon_branch.svg';
|
|||
</div>
|
||||
`,
|
||||
});
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import Vue from 'vue';
|
||||
|
||||
((global) => {
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
global.cycleAnalytics.TotalTimeComponent = Vue.extend({
|
||||
|
@ -23,4 +23,3 @@ import Vue from 'vue';
|
|||
</span>
|
||||
`,
|
||||
});
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
((global) => {
|
||||
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
class CycleAnalyticsService {
|
||||
|
@ -38,4 +39,3 @@
|
|||
}
|
||||
|
||||
global.cycleAnalytics.CycleAnalyticsService = CycleAnalyticsService;
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
require('../lib/utils/text_utility');
|
||||
const DEFAULT_EVENT_OBJECTS = require('./default_event_objects');
|
||||
|
||||
((global) => {
|
||||
const global = window.gl || (window.gl = {});
|
||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||
|
||||
const EMPTY_STAGE_TEXTS = {
|
||||
|
@ -101,4 +101,3 @@ const DEFAULT_EVENT_OBJECTS = require('./default_event_objects');
|
|||
return this.state.stages.find(stage => stage.active);
|
||||
},
|
||||
};
|
||||
})(window.gl || (window.gl = {}));
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, max-len */
|
||||
|
||||
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, max-len, vars-on-top */
|
||||
require('vendor/latinise');
|
||||
|
||||
(function() {
|
||||
(function(w) {
|
||||
var base;
|
||||
var w = window;
|
||||
if (w.gl == null) {
|
||||
w.gl = {};
|
||||
}
|
||||
|
@ -188,5 +186,3 @@ require('vendor/latinise');
|
|||
gl.text.slugify = function(str) {
|
||||
return str.trim().toLowerCase().latinise();
|
||||
};
|
||||
})(window);
|
||||
}).call(window);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, one-var, one-var-declaration-per-line, no-void, guard-for-in, no-restricted-syntax, prefer-template, quotes, max-len */
|
||||
(function() {
|
||||
(function(w) {
|
||||
var base;
|
||||
var w = window;
|
||||
if (w.gl == null) {
|
||||
w.gl = {};
|
||||
}
|
||||
|
@ -89,5 +88,3 @@
|
|||
w.gl.utils.visitUrl = (url) => {
|
||||
document.location.href = url;
|
||||
};
|
||||
})(window);
|
||||
}).call(window);
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, max-len */
|
||||
|
||||
(function() {
|
||||
var bind = function(fn, me) { return function() { return fn.apply(me, arguments); }; };
|
||||
import '~/lib/utils/url_utility';
|
||||
|
||||
(function() {
|
||||
this.MergedButtons = (function() {
|
||||
function MergedButtons() {
|
||||
this.removeSourceBranch = bind(this.removeSourceBranch, this);
|
||||
this.removeSourceBranch = this.removeSourceBranch.bind(this);
|
||||
this.removeBranchSuccess = this.removeBranchSuccess.bind(this);
|
||||
this.removeBranchError = this.removeBranchError.bind(this);
|
||||
this.$removeBranchWidget = $('.remove_source_branch_widget');
|
||||
this.$removeBranchProgress = $('.remove_source_branch_in_progress');
|
||||
this.$removeBranchFailed = $('.remove_source_branch_widget.failed');
|
||||
|
@ -22,7 +24,7 @@
|
|||
MergedButtons.prototype.initEventListeners = function() {
|
||||
$(document).on('click', '.remove_source_branch', this.removeSourceBranch);
|
||||
$(document).on('ajax:success', '.remove_source_branch', this.removeBranchSuccess);
|
||||
return $(document).on('ajax:error', '.remove_source_branch', this.removeBranchError);
|
||||
$(document).on('ajax:error', '.remove_source_branch', this.removeBranchError);
|
||||
};
|
||||
|
||||
MergedButtons.prototype.removeSourceBranch = function() {
|
||||
|
@ -31,7 +33,7 @@
|
|||
};
|
||||
|
||||
MergedButtons.prototype.removeBranchSuccess = function() {
|
||||
return location.reload();
|
||||
gl.utils.refreshCurrentPage();
|
||||
};
|
||||
|
||||
MergedButtons.prototype.removeBranchError = function() {
|
||||
|
|
|
@ -246,17 +246,17 @@
|
|||
}
|
||||
}
|
||||
|
||||
.filtered-search-history-dropdown-toggle-button {
|
||||
.filtered-search-history-dropdown-wrapper {
|
||||
position: static;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: auto;
|
||||
height: 100%;
|
||||
padding-top: 0;
|
||||
padding-left: 0.75em;
|
||||
padding-bottom: 0;
|
||||
padding-right: 0.5em;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.filtered-search-history-dropdown-toggle-button {
|
||||
flex: 1;
|
||||
width: auto;
|
||||
padding-right: 10px;
|
||||
|
||||
background-color: transparent;
|
||||
border-radius: 0;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
|
@ -264,6 +264,7 @@
|
|||
border-right: 1px solid $border-color;
|
||||
|
||||
color: $gl-text-color-secondary;
|
||||
line-height: 1;
|
||||
|
||||
transition: color 0.1s linear;
|
||||
|
||||
|
@ -275,24 +276,21 @@
|
|||
}
|
||||
|
||||
.dropdown-toggle-text {
|
||||
display: inline-block;
|
||||
color: inherit;
|
||||
|
||||
.fa {
|
||||
vertical-align: middle;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.fa {
|
||||
position: initial;
|
||||
position: static;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.filtered-search-history-dropdown-wrapper {
|
||||
position: initial;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.filtered-search-history-dropdown {
|
||||
width: 40%;
|
||||
|
||||
|
|
|
@ -158,6 +158,7 @@
|
|||
li.task-list-item {
|
||||
list-style-type: none;
|
||||
position: relative;
|
||||
min-height: 22px;
|
||||
padding-left: 28px;
|
||||
margin-left: 0 !important;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ $gray-dark: darken($gray-light, $darken-dark-factor);
|
|||
$gray-darker: #eee;
|
||||
$gray-darkest: #c4c4c4;
|
||||
|
||||
$green-25: #f6fcf8;
|
||||
$green-50: #e4f5eb;
|
||||
$green-100: #bae6cc;
|
||||
$green-200: #8dd5aa;
|
||||
|
@ -37,6 +38,7 @@ $green-700: #12753a;
|
|||
$green-800: #0e5a2d;
|
||||
$green-900: #0a4020;
|
||||
|
||||
$blue-25: #f6fafd;
|
||||
$blue-50: #e4eff9;
|
||||
$blue-100: #bcd7f1;
|
||||
$blue-200: #8fbce8;
|
||||
|
@ -48,6 +50,7 @@ $blue-700: #17599c;
|
|||
$blue-800: #134a81;
|
||||
$blue-900: #0f3b66;
|
||||
|
||||
$orange-25: #fffcf8;
|
||||
$orange-50: #fff2e1;
|
||||
$orange-100: #fedfb3;
|
||||
$orange-200: #feca81;
|
||||
|
@ -59,6 +62,7 @@ $orange-700: #c26700;
|
|||
$orange-800: #a35100;
|
||||
$orange-900: #853b00;
|
||||
|
||||
$red-25: #fef7f6;
|
||||
$red-50: #fbe7e4;
|
||||
$red-100: #f4c4bc;
|
||||
$red-200: #ed9d90;
|
||||
|
@ -147,7 +151,7 @@ $gl-sidebar-padding: 22px;
|
|||
/*
|
||||
* Misc
|
||||
*/
|
||||
$row-hover: lighten($blue-50, 2%);
|
||||
$row-hover: $blue-25;
|
||||
$row-hover-border: $blue-100;
|
||||
$progress-color: #c0392b;
|
||||
$header-height: 50px;
|
||||
|
@ -223,18 +227,18 @@ $gl-btn-active-gradient: inset 0 2px 3px $gl-btn-active-background;
|
|||
/*
|
||||
* Commit Diff Colors
|
||||
*/
|
||||
$added: $green-300;
|
||||
$deleted: $red-300;
|
||||
$line-added: $green-50;
|
||||
$line-added-dark: $green-100;
|
||||
$line-removed: $red-50;
|
||||
$line-removed-dark: $red-100;
|
||||
$line-number-old: lighten($red-100, 5%);
|
||||
$line-number-new: lighten($green-100, 5%);
|
||||
$line-number-select: lighten($orange-100, 5%);
|
||||
$line-target-blue: $blue-50;
|
||||
$line-select-yellow: $orange-50;
|
||||
$line-select-yellow-dark: $orange-100;
|
||||
$added: #63c363;
|
||||
$deleted: #f77;
|
||||
$line-added: #ecfdf0;
|
||||
$line-added-dark: #c7f0d2;
|
||||
$line-removed: #fbe9eb;
|
||||
$line-removed-dark: #fac5cd;
|
||||
$line-number-old: #f9d7dc;
|
||||
$line-number-new: #ddfbe6;
|
||||
$line-number-select: #fbf2da;
|
||||
$line-target-blue: #f6faff;
|
||||
$line-select-yellow: #fcf8e7;
|
||||
$line-select-yellow-dark: #f0e2bd;
|
||||
$dark-diff-match-bg: rgba(255, 255, 255, 0.3);
|
||||
$dark-diff-match-color: rgba(255, 255, 255, 0.1);
|
||||
$file-mode-changed: #777;
|
||||
|
|
|
@ -627,7 +627,6 @@ ul.notes {
|
|||
}
|
||||
|
||||
&:not(.is-disabled):hover,
|
||||
&:not(.is-disabled):focus,
|
||||
&.is-active {
|
||||
color: $gl-text-green;
|
||||
|
||||
|
@ -641,6 +640,11 @@ ul.notes {
|
|||
height: 15px;
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.loading {
|
||||
margin: 0;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.discussion-next-btn {
|
||||
|
|
|
@ -60,7 +60,7 @@ class RegistrationsController < Devise::RegistrationsController
|
|||
end
|
||||
|
||||
def resource
|
||||
@resource ||= Users::CreateService.new(current_user, sign_up_params).build
|
||||
@resource ||= Users::BuildService.new(current_user, sign_up_params).execute
|
||||
end
|
||||
|
||||
def devise_mapping
|
||||
|
|
|
@ -20,7 +20,8 @@ class ContainerRepository < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def path
|
||||
@path ||= [project.full_path, name].select(&:present?).join('/')
|
||||
@path ||= [project.full_path, name]
|
||||
.select(&:present?).join('/').downcase
|
||||
end
|
||||
|
||||
def location
|
||||
|
|
|
@ -58,6 +58,9 @@ module Projects
|
|||
fail(error: @project.errors.full_messages.join(', '))
|
||||
end
|
||||
@project
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
message = "Unable to save #{e.record.type}: #{e.record.errors.full_messages.join(", ")} "
|
||||
fail(error: message)
|
||||
rescue => e
|
||||
fail(error: e.message)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
module Users
|
||||
# Service for building a new user.
|
||||
class BuildService < BaseService
|
||||
def initialize(current_user, params = {})
|
||||
@current_user = current_user
|
||||
@params = params.dup
|
||||
end
|
||||
|
||||
def execute
|
||||
raise Gitlab::Access::AccessDeniedError unless can_create_user?
|
||||
|
||||
user = User.new(build_user_params)
|
||||
|
||||
if current_user&.admin?
|
||||
if params[:reset_password]
|
||||
user.generate_reset_token
|
||||
params[:force_random_password] = true
|
||||
end
|
||||
|
||||
if params[:force_random_password]
|
||||
random_password = Devise.friendly_token.first(Devise.password_length.min)
|
||||
user.password = user.password_confirmation = random_password
|
||||
end
|
||||
end
|
||||
|
||||
identity_attrs = params.slice(:extern_uid, :provider)
|
||||
|
||||
if identity_attrs.any?
|
||||
user.identities.build(identity_attrs)
|
||||
end
|
||||
|
||||
user
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def can_create_user?
|
||||
(current_user.nil? && current_application_settings.signup_enabled?) || current_user&.admin?
|
||||
end
|
||||
|
||||
# Allowed params for creating a user (admins only)
|
||||
def admin_create_params
|
||||
[
|
||||
:access_level,
|
||||
:admin,
|
||||
:avatar,
|
||||
:bio,
|
||||
:can_create_group,
|
||||
:color_scheme_id,
|
||||
:email,
|
||||
:external,
|
||||
:force_random_password,
|
||||
:hide_no_password,
|
||||
:hide_no_ssh_key,
|
||||
:key_id,
|
||||
:linkedin,
|
||||
:name,
|
||||
:password,
|
||||
:password_automatically_set,
|
||||
:password_expires_at,
|
||||
:projects_limit,
|
||||
:remember_me,
|
||||
:skip_confirmation,
|
||||
:skype,
|
||||
:theme_id,
|
||||
:twitter,
|
||||
:username,
|
||||
:website_url
|
||||
]
|
||||
end
|
||||
|
||||
# Allowed params for user signup
|
||||
def signup_params
|
||||
[
|
||||
:email,
|
||||
:email_confirmation,
|
||||
:password_automatically_set,
|
||||
:name,
|
||||
:password,
|
||||
:username
|
||||
]
|
||||
end
|
||||
|
||||
def build_user_params
|
||||
if current_user&.admin?
|
||||
user_params = params.slice(*admin_create_params)
|
||||
user_params[:created_by_id] = current_user&.id
|
||||
|
||||
if params[:reset_password]
|
||||
user_params.merge!(force_random_password: true, password_expires_at: nil)
|
||||
end
|
||||
else
|
||||
user_params = params.slice(*signup_params)
|
||||
user_params[:skip_confirmation] = !current_application_settings.send_user_confirmation_email
|
||||
end
|
||||
|
||||
user_params
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,34 +6,10 @@ module Users
|
|||
@params = params.dup
|
||||
end
|
||||
|
||||
def build
|
||||
raise Gitlab::Access::AccessDeniedError unless can_create_user?
|
||||
|
||||
user = User.new(build_user_params)
|
||||
|
||||
if current_user&.admin?
|
||||
if params[:reset_password]
|
||||
@reset_token = user.generate_reset_token
|
||||
params[:force_random_password] = true
|
||||
end
|
||||
|
||||
if params[:force_random_password]
|
||||
random_password = Devise.friendly_token.first(Devise.password_length.min)
|
||||
user.password = user.password_confirmation = random_password
|
||||
end
|
||||
end
|
||||
|
||||
identity_attrs = params.slice(:extern_uid, :provider)
|
||||
|
||||
if identity_attrs.any?
|
||||
user.identities.build(identity_attrs)
|
||||
end
|
||||
|
||||
user
|
||||
end
|
||||
|
||||
def execute
|
||||
user = build
|
||||
user = Users::BuildService.new(current_user, params).execute
|
||||
|
||||
@reset_token = user.generate_reset_token if user.recently_sent_password_reset?
|
||||
|
||||
if user.save
|
||||
log_info("User \"#{user.name}\" (#{user.email}) was created")
|
||||
|
@ -43,70 +19,5 @@ module Users
|
|||
|
||||
user
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def can_create_user?
|
||||
(current_user.nil? && current_application_settings.signup_enabled?) || current_user&.admin?
|
||||
end
|
||||
|
||||
# Allowed params for creating a user (admins only)
|
||||
def admin_create_params
|
||||
[
|
||||
:access_level,
|
||||
:admin,
|
||||
:avatar,
|
||||
:bio,
|
||||
:can_create_group,
|
||||
:color_scheme_id,
|
||||
:email,
|
||||
:external,
|
||||
:force_random_password,
|
||||
:password_automatically_set,
|
||||
:hide_no_password,
|
||||
:hide_no_ssh_key,
|
||||
:key_id,
|
||||
:linkedin,
|
||||
:name,
|
||||
:password,
|
||||
:password_expires_at,
|
||||
:projects_limit,
|
||||
:remember_me,
|
||||
:skip_confirmation,
|
||||
:skype,
|
||||
:theme_id,
|
||||
:twitter,
|
||||
:username,
|
||||
:website_url
|
||||
]
|
||||
end
|
||||
|
||||
# Allowed params for user signup
|
||||
def signup_params
|
||||
[
|
||||
:email,
|
||||
:email_confirmation,
|
||||
:password_automatically_set,
|
||||
:name,
|
||||
:password,
|
||||
:username
|
||||
]
|
||||
end
|
||||
|
||||
def build_user_params
|
||||
if current_user&.admin?
|
||||
user_params = params.slice(*admin_create_params)
|
||||
user_params[:created_by_id] = current_user&.id
|
||||
|
||||
if params[:reset_password]
|
||||
user_params.merge!(force_random_password: true, password_expires_at: nil)
|
||||
end
|
||||
else
|
||||
user_params = params.slice(*signup_params)
|
||||
user_params[:skip_confirmation] = !current_application_settings.send_user_confirmation_email
|
||||
end
|
||||
|
||||
user_params
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
- @services.sort_by(&:title).each do |service|
|
||||
%tr
|
||||
%td
|
||||
= icon("copy", class: 'clgray')
|
||||
= boolean_to_icon service.activated?
|
||||
%td
|
||||
= link_to edit_admin_application_settings_service_path(service.id) do
|
||||
%strong= service.title
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
Registry
|
||||
|
||||
- if project_nav_tab? :issues
|
||||
= nav_link(controller: [:issues, :labels, :milestones, :boards]) do
|
||||
= nav_link(controller: @project.default_issues_tracker? ? [:issues, :labels, :milestones, :boards] : :issues) do
|
||||
= link_to namespace_project_issues_path(@project.namespace, @project), title: 'Issues', class: 'shortcuts-issues' do
|
||||
%span
|
||||
Issues
|
||||
|
@ -31,7 +31,7 @@
|
|||
%span.badge.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count)
|
||||
|
||||
- if project_nav_tab? :merge_requests
|
||||
= nav_link(controller: :merge_requests) do
|
||||
= nav_link(controller: @project.default_issues_tracker? ? :merge_requests : [:merge_requests, :labels, :milestones]) do
|
||||
= link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
|
||||
%span
|
||||
Merge Requests
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- @no_container = true
|
||||
- page_title "Edit", @label.name, "Labels"
|
||||
= render "projects/issues/head"
|
||||
= render "shared/mr_head"
|
||||
|
||||
%div{ class: container_class }
|
||||
%h3.page-title
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- @no_container = true
|
||||
- page_title "Labels"
|
||||
- hide_class = ''
|
||||
= render "projects/issues/head"
|
||||
= render "shared/mr_head"
|
||||
|
||||
- if @labels.exists? || @prioritized_labels.exists?
|
||||
%div{ class: container_class }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- @no_container = true
|
||||
- page_title "New Label"
|
||||
= render "projects/issues/head"
|
||||
= render "shared/mr_head"
|
||||
|
||||
%div{ class: container_class }
|
||||
%h3.page-title
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
= content_for :sub_nav do
|
||||
.scrolling-tabs-container.sub-nav-scroll
|
||||
= render 'shared/nav_scroll'
|
||||
.nav-links.sub-nav.scrolling-tabs
|
||||
%ul{ class: (container_class) }
|
||||
= nav_link(controller: :merge_requests) do
|
||||
= link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests' do
|
||||
%span
|
||||
List
|
||||
|
||||
- if project_nav_tab? :labels
|
||||
= nav_link(controller: :labels) do
|
||||
= link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do
|
||||
%span
|
||||
Labels
|
||||
|
||||
- if project_nav_tab? :milestones
|
||||
= nav_link(controller: :milestones) do
|
||||
= link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do
|
||||
%span
|
||||
Milestones
|
|
@ -2,6 +2,9 @@
|
|||
- @bulk_edit = can?(current_user, :admin_merge_request, @project)
|
||||
|
||||
- page_title "Merge Requests"
|
||||
- unless @project.default_issues_tracker?
|
||||
= content_for :sub_nav do
|
||||
= render "projects/merge_requests/head"
|
||||
= render 'projects/last_push'
|
||||
|
||||
- content_for :page_specific_javascripts do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- @no_container = true
|
||||
- page_title "Edit", @milestone.title, "Milestones"
|
||||
= render "projects/issues/head"
|
||||
= render "shared/mr_head"
|
||||
|
||||
%div{ class: container_class }
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- @no_container = true
|
||||
- page_title 'Milestones'
|
||||
= render 'projects/issues/head'
|
||||
= render "shared/mr_head"
|
||||
|
||||
%div{ class: container_class }
|
||||
.top-area
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- @no_container = true
|
||||
- page_title "New Milestone"
|
||||
= render "projects/issues/head"
|
||||
= render "shared/mr_head"
|
||||
|
||||
%div{ class: container_class }
|
||||
%h3.page-title
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
- @no_container = true
|
||||
- page_title @milestone.title, "Milestones"
|
||||
- page_description @milestone.description
|
||||
= render "projects/issues/head"
|
||||
= render "shared/mr_head"
|
||||
|
||||
%div{ class: container_class }
|
||||
.detail-page-header.milestone-page-header
|
||||
|
|
|
@ -52,11 +52,10 @@
|
|||
":aria-label" => "buttonText",
|
||||
"@click" => "resolve",
|
||||
":title" => "buttonText",
|
||||
"v-show" => "!loading",
|
||||
":ref" => "'button'" }
|
||||
= icon("spin spinner", "v-show" => "loading")
|
||||
|
||||
= render "shared/icons/icon_status_success.svg"
|
||||
= icon("spin spinner", "v-show" => "loading", class: 'loading')
|
||||
%div{ 'v-show' => '!loading' }= render "shared/icons/icon_status_success.svg"
|
||||
|
||||
- if current_user
|
||||
- if note.emoji_awardable?
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
= render "projects/last_push"
|
||||
= render "home_panel"
|
||||
|
||||
- if current_user && can?(current_user, :download_code, @project)
|
||||
- if can?(current_user, :download_code, @project)
|
||||
%nav.project-stats{ class: container_class }
|
||||
%ul.nav
|
||||
%li
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
= f.label :import_url, class: 'control-label' do
|
||||
%span Git repository URL
|
||||
.col-sm-10
|
||||
= f.text_field :import_url, autocomplete: 'off', class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git', disabled: true
|
||||
= f.text_field :import_url, autocomplete: 'off', class: 'form-control', placeholder: 'https://username:password@gitlab.company.com/group/project.git'
|
||||
|
||||
.well.prepend-top-20
|
||||
%ul
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
- if @project.default_issues_tracker?
|
||||
= render "projects/issues/head"
|
||||
- else
|
||||
= render "projects/merge_requests/head"
|
|
@ -16,6 +16,8 @@
|
|||
Also, issues are searchable and filterable.
|
||||
- if project_select_button
|
||||
= render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue'
|
||||
= link_to 'New issue', button_path, class: 'btn btn-new', title: 'New issue', id: 'new_issue_link'
|
||||
- else
|
||||
.text-center
|
||||
%h4 There are no issues to show.
|
||||
= link_to 'New issue', button_path, class: 'btn btn-new', title: 'New issue', id: 'new_issue_link'
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Implement Users::BuildService
|
||||
merge_request: 30349
|
||||
author: George Andrinopoulos
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Show sub-nav under Merge Requests when issue tracker is non-default.
|
||||
merge_request: 10658
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Fixed alignment of empty task list items
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Fix invalid encoding when showing some traces
|
||||
merge_request: 10681
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Centered issues empty state
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Add lighter colors and fix existing light colors
|
||||
merge_request: 10690
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Add hashie-forbidden_attributes gem
|
||||
merge_request: 10579
|
||||
author: Andy Brown
|
|
@ -50,20 +50,17 @@ update them are in [a separate document][omnidocker].
|
|||
|
||||
## Upgrading without downtime
|
||||
|
||||
Starting with GitLab 9.1.0 it's possible to upgrade to a newer version of GitLab
|
||||
Starting with GitLab 9.1.0 it's possible to upgrade to a newer major, minor, or patch version of GitLab
|
||||
without having to take your GitLab instance offline. However, for this to work
|
||||
there are the following requirements:
|
||||
|
||||
1. You can only upgrade 1 release at a time. For example, if 9.1.15 is the last
|
||||
release of 9.1 then you can safely upgrade from that version to 9.2.0.
|
||||
1. You can only upgrade 1 minor release at a time. So from 9.1 to 9.2, not to 9.3.
|
||||
2. You have to be on the most recent patch release. For example, if 9.1.15 is the last
|
||||
release of 9.1 then you can safely upgrade from that version to any 9.2.x version.
|
||||
However, if you are running 9.1.14 you first need to upgrade to 9.1.15.
|
||||
2. You have to use [post-deployment
|
||||
migrations](../development/post_deployment_migrations.md).
|
||||
3. You are using PostgreSQL. If you are using MySQL you will still need downtime
|
||||
when upgrading.
|
||||
|
||||
This applies to major, minor, and patch releases unless stated otherwise in a
|
||||
release post.
|
||||
3. You are using PostgreSQL. If you are using MySQL please look at the release post to see if downtime is required.
|
||||
|
||||
## Upgrading between editions
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ module Banzai
|
|||
issuables = extractor.extract([doc])
|
||||
|
||||
issuables.each do |node, issuable|
|
||||
if VISIBLE_STATES.include?(issuable.state)
|
||||
node.children.last.content += " [#{issuable.state}]"
|
||||
if VISIBLE_STATES.include?(issuable.state) && node.children.present?
|
||||
node.add_child(Nokogiri::XML::Text.new(" [#{issuable.state}]", doc))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ module ContainerRegistry
|
|||
LEVELS_SUPPORTED = 3
|
||||
|
||||
def initialize(path)
|
||||
@path = path
|
||||
@path = path.to_s.downcase
|
||||
end
|
||||
|
||||
def valid?
|
||||
|
@ -25,7 +25,7 @@ module ContainerRegistry
|
|||
end
|
||||
|
||||
def components
|
||||
@components ||= @path.to_s.split('/')
|
||||
@components ||= @path.split('/')
|
||||
end
|
||||
|
||||
def nodes
|
||||
|
|
|
@ -25,11 +25,10 @@ module Gitlab
|
|||
end
|
||||
|
||||
def limit(last_bytes = LIMIT_SIZE)
|
||||
stream_size = size
|
||||
if stream_size < last_bytes
|
||||
last_bytes = stream_size
|
||||
end
|
||||
if last_bytes < size
|
||||
stream.seek(-last_bytes, IO::SEEK_END)
|
||||
stream.readline
|
||||
end
|
||||
end
|
||||
|
||||
def append(data, offset)
|
||||
|
|
|
@ -148,7 +148,7 @@ module Gitlab
|
|||
|
||||
def build_new_user
|
||||
user_params = user_attributes.merge(extern_uid: auth_hash.uid, provider: auth_hash.provider, skip_confirmation: true)
|
||||
Users::CreateService.new(nil, user_params).build
|
||||
Users::BuildService.new(nil, user_params).execute
|
||||
end
|
||||
|
||||
def user_attributes
|
||||
|
|
|
@ -7,10 +7,10 @@ namespace :gitlab do
|
|||
abort %(Please specify the directory where you want to install gitaly:\n rake "gitlab:gitaly:install[/home/git/gitaly]")
|
||||
end
|
||||
|
||||
tag = "v#{Gitlab::GitalyClient.expected_server_version}"
|
||||
version = Gitlab::GitalyClient.expected_server_version
|
||||
repo = 'https://gitlab.com/gitlab-org/gitaly.git'
|
||||
|
||||
checkout_or_clone_tag(tag: tag, repo: repo, target_dir: args.dir)
|
||||
checkout_or_clone_version(version: version, repo: repo, target_dir: args.dir)
|
||||
|
||||
_, status = Gitlab::Popen.popen(%w[which gmake])
|
||||
command = status.zero? ? 'gmake' : 'make'
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
namespace :gitlab do
|
||||
namespace :shell do
|
||||
desc "GitLab | Install or upgrade gitlab-shell"
|
||||
task :install, [:tag, :repo] => :environment do |t, args|
|
||||
task :install, [:repo] => :environment do |t, args|
|
||||
warn_user_is_not_gitlab
|
||||
|
||||
default_version = Gitlab::Shell.version_required
|
||||
default_version_tag = "v#{default_version}"
|
||||
args.with_defaults(tag: default_version_tag, repo: 'https://gitlab.com/gitlab-org/gitlab-shell.git')
|
||||
args.with_defaults(repo: 'https://gitlab.com/gitlab-org/gitlab-shell.git')
|
||||
|
||||
gitlab_url = Gitlab.config.gitlab.url
|
||||
# gitlab-shell requires a / at the end of the url
|
||||
gitlab_url += '/' unless gitlab_url.end_with?('/')
|
||||
target_dir = Gitlab.config.gitlab_shell.path
|
||||
|
||||
checkout_or_clone_tag(tag: default_version_tag, repo: args.repo, target_dir: target_dir)
|
||||
checkout_or_clone_version(version: default_version, repo: args.repo, target_dir: target_dir)
|
||||
|
||||
# Make sure we're on the right tag
|
||||
Dir.chdir(target_dir) do
|
||||
|
|
|
@ -147,41 +147,30 @@ module Gitlab
|
|||
Rails.env.test? ? Rails.root.join('tmp/tests') : Gitlab.config.gitlab.user_home
|
||||
end
|
||||
|
||||
def checkout_or_clone_tag(tag:, repo:, target_dir:)
|
||||
if Dir.exist?(target_dir)
|
||||
checkout_tag(tag, target_dir)
|
||||
def checkout_or_clone_version(version:, repo:, target_dir:)
|
||||
version =
|
||||
if version.starts_with?("=")
|
||||
version.sub(/\A=/, '') # tag or branch
|
||||
else
|
||||
clone_repo(repo, target_dir)
|
||||
"v#{version}" # tag
|
||||
end
|
||||
|
||||
reset_to_tag(tag, target_dir)
|
||||
clone_repo(repo, target_dir) unless Dir.exist?(target_dir)
|
||||
checkout_version(version, target_dir)
|
||||
reset_to_version(version, target_dir)
|
||||
end
|
||||
|
||||
def clone_repo(repo, target_dir)
|
||||
run_command!(%W[#{Gitlab.config.git.bin_path} clone -- #{repo} #{target_dir}])
|
||||
end
|
||||
|
||||
def checkout_tag(tag, target_dir)
|
||||
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} fetch --tags --quiet])
|
||||
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} checkout --quiet #{tag}])
|
||||
def checkout_version(version, target_dir)
|
||||
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} fetch --quiet])
|
||||
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} checkout --quiet #{version}])
|
||||
end
|
||||
|
||||
def reset_to_tag(tag_wanted, target_dir)
|
||||
tag =
|
||||
begin
|
||||
# First try to checkout without fetching
|
||||
# to avoid stalling tests if the Internet is down.
|
||||
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} describe -- #{tag_wanted}])
|
||||
rescue Gitlab::TaskFailedError
|
||||
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} fetch origin])
|
||||
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} describe -- origin/#{tag_wanted}])
|
||||
end
|
||||
|
||||
if tag
|
||||
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} reset --hard #{tag.strip}])
|
||||
else
|
||||
raise Gitlab::TaskFailedError
|
||||
end
|
||||
def reset_to_version(version, target_dir)
|
||||
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} reset --hard #{version}])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,10 +7,10 @@ namespace :gitlab do
|
|||
abort %(Please specify the directory where you want to install gitlab-workhorse:\n rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]")
|
||||
end
|
||||
|
||||
tag = "v#{Gitlab::Workhorse.version}"
|
||||
version = Gitlab::Workhorse.version
|
||||
repo = 'https://gitlab.com/gitlab-org/gitlab-workhorse.git'
|
||||
|
||||
checkout_or_clone_tag(tag: tag, repo: repo, target_dir: args.dir)
|
||||
checkout_or_clone_version(version: version, repo: repo, target_dir: args.dir)
|
||||
|
||||
_, status = Gitlab::Popen.popen(%w[which gmake])
|
||||
command = status.zero? ? 'gmake' : 'make'
|
||||
|
|
|
@ -198,6 +198,8 @@ feature 'Diff notes resolve', feature: true, js: true do
|
|||
it 'does not mark discussion as resolved when resolving single note' do
|
||||
page.first '.diff-content .note' do
|
||||
first('.line-resolve-btn').click
|
||||
|
||||
expect(page).to have_selector('.note-action-button .loading')
|
||||
expect(first('.line-resolve-btn')['data-original-title']).to eq("Resolved by #{user.name}")
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[0m[01;34m.[0m
|
||||
[30;42m..[0m
|
||||
😺
|
||||
ヾ(´༎ຶД༎ຶ`)ノ
|
||||
[01;32m許功蓋[0m
|
|
@ -7,6 +7,7 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
|
|||
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
|
||||
let(:project) { create(:project, namespace: namespace, path: 'merge-requests-project') }
|
||||
let(:merge_request) { create(:merge_request, :with_diffs, source_project: project, target_project: project, description: '- [ ] Task List Item') }
|
||||
let(:merged_merge_request) { create(:merge_request, :merged, source_project: project, target_project: project) }
|
||||
let(:pipeline) do
|
||||
create(
|
||||
:ci_pipeline,
|
||||
|
@ -32,6 +33,12 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
|
|||
render_merge_request(example.description, merge_request)
|
||||
end
|
||||
|
||||
it 'merge_requests/merged_merge_request.html.raw' do |example|
|
||||
allow_any_instance_of(MergeRequest).to receive(:source_branch_exists?).and_return(true)
|
||||
allow_any_instance_of(MergeRequest).to receive(:can_remove_source_branch?).and_return(true)
|
||||
render_merge_request(example.description, merged_merge_request)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_merge_request(fixture_file_name, merge_request)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
require('~/lib/utils/text_utility');
|
||||
|
||||
(() => {
|
||||
describe('text_utility', () => {
|
||||
describe('gl.text.getTextWidth', () => {
|
||||
it('returns zero width when no text is passed', () => {
|
||||
|
@ -107,4 +106,3 @@ require('~/lib/utils/text_utility');
|
|||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/* global MergedButtons */
|
||||
|
||||
import '~/merged_buttons';
|
||||
|
||||
describe('MergedButtons', () => {
|
||||
const fixturesPath = 'merge_requests/merged_merge_request.html.raw';
|
||||
preloadFixtures(fixturesPath);
|
||||
|
||||
beforeEach(() => {
|
||||
loadFixtures(fixturesPath);
|
||||
this.mergedButtons = new MergedButtons();
|
||||
this.$removeBranchWidget = $('.remove_source_branch_widget:not(.failed)');
|
||||
this.$removeBranchProgress = $('.remove_source_branch_in_progress');
|
||||
this.$removeBranchFailed = $('.remove_source_branch_widget.failed');
|
||||
this.$removeBranchButton = $('.remove_source_branch');
|
||||
});
|
||||
|
||||
describe('removeSourceBranch', () => {
|
||||
it('shows loader', () => {
|
||||
$('.remove_source_branch').trigger('click');
|
||||
expect(this.$removeBranchProgress).toBeVisible();
|
||||
expect(this.$removeBranchWidget).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeBranchSuccess', () => {
|
||||
it('refreshes page when branch removed', () => {
|
||||
spyOn(gl.utils, 'refreshCurrentPage').and.stub();
|
||||
const response = { status: 200 };
|
||||
this.$removeBranchButton.trigger('ajax:success', response, 'xhr');
|
||||
expect(gl.utils.refreshCurrentPage).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeBranchError', () => {
|
||||
it('shows error message', () => {
|
||||
const response = { status: 500 };
|
||||
this.$removeBranchButton.trigger('ajax:error', response, 'xhr');
|
||||
expect(this.$removeBranchFailed).toBeVisible();
|
||||
expect(this.$removeBranchProgress).not.toBeVisible();
|
||||
expect(this.$removeBranchWidget).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -6,8 +6,8 @@ describe Banzai::Filter::IssuableStateFilter, lib: true do
|
|||
|
||||
let(:user) { create(:user) }
|
||||
|
||||
def create_link(data)
|
||||
link_to('text', '', class: 'gfm has-tooltip', data: data)
|
||||
def create_link(text, data)
|
||||
link_to(text, '', class: 'gfm has-tooltip', data: data)
|
||||
end
|
||||
|
||||
it 'ignores non-GFM links' do
|
||||
|
@ -19,16 +19,37 @@ describe Banzai::Filter::IssuableStateFilter, lib: true do
|
|||
|
||||
it 'ignores non-issuable links' do
|
||||
project = create(:empty_project, :public)
|
||||
link = create_link(project: project, reference_type: 'issue')
|
||||
link = create_link('text', project: project, reference_type: 'issue')
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').last.text).to eq('text')
|
||||
end
|
||||
|
||||
it 'ignores issuable links with empty content' do
|
||||
issue = create(:issue, :closed)
|
||||
link = create_link('', issue: issue.id, reference_type: 'issue')
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').last.text).to eq('')
|
||||
end
|
||||
|
||||
it 'adds text with standard formatting' do
|
||||
issue = create(:issue, :closed)
|
||||
link = create_link(
|
||||
'something <strong>else</strong>'.html_safe,
|
||||
issue: issue.id,
|
||||
reference_type: 'issue'
|
||||
)
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').last.inner_html).
|
||||
to eq('something <strong>else</strong> [closed]')
|
||||
end
|
||||
|
||||
context 'for issue references' do
|
||||
it 'ignores open issue references' do
|
||||
issue = create(:issue)
|
||||
link = create_link(issue: issue.id, reference_type: 'issue')
|
||||
link = create_link('text', issue: issue.id, reference_type: 'issue')
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').last.text).to eq('text')
|
||||
|
@ -36,7 +57,7 @@ describe Banzai::Filter::IssuableStateFilter, lib: true do
|
|||
|
||||
it 'ignores reopened issue references' do
|
||||
reopened_issue = create(:issue, :reopened)
|
||||
link = create_link(issue: reopened_issue.id, reference_type: 'issue')
|
||||
link = create_link('text', issue: reopened_issue.id, reference_type: 'issue')
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').last.text).to eq('text')
|
||||
|
@ -44,7 +65,7 @@ describe Banzai::Filter::IssuableStateFilter, lib: true do
|
|||
|
||||
it 'appends [closed] to closed issue references' do
|
||||
closed_issue = create(:issue, :closed)
|
||||
link = create_link(issue: closed_issue.id, reference_type: 'issue')
|
||||
link = create_link('text', issue: closed_issue.id, reference_type: 'issue')
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').last.text).to eq('text [closed]')
|
||||
|
@ -54,7 +75,7 @@ describe Banzai::Filter::IssuableStateFilter, lib: true do
|
|||
context 'for merge request references' do
|
||||
it 'ignores open merge request references' do
|
||||
mr = create(:merge_request)
|
||||
link = create_link(merge_request: mr.id, reference_type: 'merge_request')
|
||||
link = create_link('text', merge_request: mr.id, reference_type: 'merge_request')
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').last.text).to eq('text')
|
||||
|
@ -62,7 +83,7 @@ describe Banzai::Filter::IssuableStateFilter, lib: true do
|
|||
|
||||
it 'ignores reopened merge request references' do
|
||||
mr = create(:merge_request, :reopened)
|
||||
link = create_link(merge_request: mr.id, reference_type: 'merge_request')
|
||||
link = create_link('text', merge_request: mr.id, reference_type: 'merge_request')
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').last.text).to eq('text')
|
||||
|
@ -70,7 +91,7 @@ describe Banzai::Filter::IssuableStateFilter, lib: true do
|
|||
|
||||
it 'ignores locked merge request references' do
|
||||
mr = create(:merge_request, :locked)
|
||||
link = create_link(merge_request: mr.id, reference_type: 'merge_request')
|
||||
link = create_link('text', merge_request: mr.id, reference_type: 'merge_request')
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').last.text).to eq('text')
|
||||
|
@ -78,7 +99,7 @@ describe Banzai::Filter::IssuableStateFilter, lib: true do
|
|||
|
||||
it 'appends [closed] to closed merge request references' do
|
||||
mr = create(:merge_request, :closed)
|
||||
link = create_link(merge_request: mr.id, reference_type: 'merge_request')
|
||||
link = create_link('text', merge_request: mr.id, reference_type: 'merge_request')
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').last.text).to eq('text [closed]')
|
||||
|
@ -86,7 +107,7 @@ describe Banzai::Filter::IssuableStateFilter, lib: true do
|
|||
|
||||
it 'appends [merged] to merged merge request references' do
|
||||
mr = create(:merge_request, :merged)
|
||||
link = create_link(merge_request: mr.id, reference_type: 'merge_request')
|
||||
link = create_link('text', merge_request: mr.id, reference_type: 'merge_request')
|
||||
doc = filter(link, current_user: user)
|
||||
|
||||
expect(doc.css('a').last.text).to eq('text [merged]')
|
||||
|
|
|
@ -33,10 +33,20 @@ describe ContainerRegistry::Path do
|
|||
end
|
||||
|
||||
describe '#to_s' do
|
||||
context 'when path does not have uppercase characters' do
|
||||
let(:path) { 'some/image' }
|
||||
|
||||
it 'return a string with a repository path' do
|
||||
expect(subject.to_s).to eq path
|
||||
expect(subject.to_s).to eq 'some/image'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when path has uppercase characters' do
|
||||
let(:path) { 'SoMe/ImAgE' }
|
||||
|
||||
it 'return a string with a repository path' do
|
||||
expect(subject.to_s).to eq 'some/image'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -70,6 +80,12 @@ describe ContainerRegistry::Path do
|
|||
|
||||
it { is_expected.to be_valid }
|
||||
end
|
||||
|
||||
context 'when path contains uppercase letters' do
|
||||
let(:path) { 'Some/Registry' }
|
||||
|
||||
it { is_expected.to be_valid }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_repository?' do
|
||||
|
|
|
@ -17,12 +17,12 @@ describe Gitlab::Ci::Trace::Stream do
|
|||
describe '#limit' do
|
||||
let(:stream) do
|
||||
described_class.new do
|
||||
StringIO.new("12345678")
|
||||
StringIO.new((1..8).to_a.join("\n"))
|
||||
end
|
||||
end
|
||||
|
||||
it 'if size is larger we start from beggining' do
|
||||
stream.limit(10)
|
||||
it 'if size is larger we start from beginning' do
|
||||
stream.limit(20)
|
||||
|
||||
expect(stream.tell).to eq(0)
|
||||
end
|
||||
|
@ -30,7 +30,27 @@ describe Gitlab::Ci::Trace::Stream do
|
|||
it 'if size is smaller we start from the end' do
|
||||
stream.limit(2)
|
||||
|
||||
expect(stream.tell).to eq(6)
|
||||
expect(stream.raw).to eq("8")
|
||||
end
|
||||
|
||||
context 'when the trace contains ANSI sequence and Unicode' do
|
||||
let(:stream) do
|
||||
described_class.new do
|
||||
File.open(expand_fixture_path('trace/ansi-sequence-and-unicode'))
|
||||
end
|
||||
end
|
||||
|
||||
it 'forwards to the next linefeed, case 1' do
|
||||
stream.limit(7)
|
||||
|
||||
expect(stream.raw).to eq('')
|
||||
end
|
||||
|
||||
it 'forwards to the next linefeed, case 2' do
|
||||
stream.limit(29)
|
||||
|
||||
expect(stream.raw).to eq("\e[01;32m許功蓋\e[0m\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -34,11 +34,21 @@ describe ContainerRepository do
|
|||
end
|
||||
|
||||
describe '#path' do
|
||||
context 'when project path does not contain uppercase letters' do
|
||||
it 'returns a full path to the repository' do
|
||||
expect(repository.path).to eq('group/test/my_image')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when path contains uppercase letters' do
|
||||
let(:project) { create(:project, path: 'MY_PROJECT', group: group) }
|
||||
|
||||
it 'returns a full path without capital letters' do
|
||||
expect(repository.path).to eq('group/my_project/my_image')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#manifest' do
|
||||
it 'returns non-empty manifest' do
|
||||
expect(repository.manifest).not_to be_nil
|
||||
|
|
|
@ -144,6 +144,20 @@ describe Projects::CreateService, '#execute', services: true do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when a bad service template is created' do
|
||||
before do
|
||||
create(:service, type: 'DroneCiService', project: nil, template: true, active: true)
|
||||
end
|
||||
|
||||
it 'reports an error in the imported project' do
|
||||
opts[:import_url] = 'http://www.gitlab.com/gitlab-org/gitlab-ce'
|
||||
project = create_project(user, opts)
|
||||
|
||||
expect(project.errors.full_messages_for(:base).first).to match /Unable to save project. Error: Unable to save DroneCiService/
|
||||
expect(project.services.count).to eq 0
|
||||
end
|
||||
end
|
||||
|
||||
def create_project(user, opts)
|
||||
Projects::CreateService.new(user, opts).execute
|
||||
end
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Users::BuildService, services: true do
|
||||
describe '#execute' do
|
||||
let(:params) do
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass' }
|
||||
end
|
||||
|
||||
context 'with an admin user' do
|
||||
let(:admin_user) { create(:admin) }
|
||||
let(:service) { described_class.new(admin_user, params) }
|
||||
|
||||
it 'returns a valid user' do
|
||||
expect(service.execute).to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
context 'with non admin user' do
|
||||
let(:user) { create(:user) }
|
||||
let(:service) { described_class.new(user, params) }
|
||||
|
||||
it 'raises AccessDeniedError exception' do
|
||||
expect { service.execute }.to raise_error Gitlab::Access::AccessDeniedError
|
||||
end
|
||||
end
|
||||
|
||||
context 'with nil user' do
|
||||
let(:service) { described_class.new(nil, params) }
|
||||
|
||||
it 'returns a valid user' do
|
||||
expect(service.execute).to be_valid
|
||||
end
|
||||
|
||||
context 'when "send_user_confirmation_email" application setting is true' do
|
||||
before do
|
||||
stub_application_setting(send_user_confirmation_email: true, signup_enabled?: true)
|
||||
end
|
||||
|
||||
it 'does not confirm the user' do
|
||||
expect(service.execute).not_to be_confirmed
|
||||
end
|
||||
end
|
||||
|
||||
context 'when "send_user_confirmation_email" application setting is false' do
|
||||
before do
|
||||
stub_application_setting(send_user_confirmation_email: false, signup_enabled?: true)
|
||||
end
|
||||
|
||||
it 'confirms the user' do
|
||||
expect(service.execute).to be_confirmed
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,38 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Users::CreateService, services: true do
|
||||
describe '#build' do
|
||||
let(:params) do
|
||||
{ name: 'John Doe', username: 'jduser', email: 'jd@example.com', password: 'mydummypass' }
|
||||
end
|
||||
|
||||
context 'with an admin user' do
|
||||
let(:admin_user) { create(:admin) }
|
||||
let(:service) { described_class.new(admin_user, params) }
|
||||
|
||||
it 'returns a valid user' do
|
||||
expect(service.build).to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
context 'with non admin user' do
|
||||
let(:user) { create(:user) }
|
||||
let(:service) { described_class.new(user, params) }
|
||||
|
||||
it 'raises AccessDeniedError exception' do
|
||||
expect { service.build }.to raise_error Gitlab::Access::AccessDeniedError
|
||||
end
|
||||
end
|
||||
|
||||
context 'with nil user' do
|
||||
let(:service) { described_class.new(nil, params) }
|
||||
|
||||
it 'returns a valid user' do
|
||||
expect(service.build).to be_valid
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
let(:admin_user) { create(:admin) }
|
||||
|
||||
|
@ -185,27 +153,6 @@ describe Users::CreateService, services: true do
|
|||
end
|
||||
let(:service) { described_class.new(nil, params) }
|
||||
|
||||
context 'when "send_user_confirmation_email" application setting is true' do
|
||||
before do
|
||||
current_application_settings = double(:current_application_settings, send_user_confirmation_email: true, signup_enabled?: true)
|
||||
allow(service).to receive(:current_application_settings).and_return(current_application_settings)
|
||||
end
|
||||
|
||||
it 'does not confirm the user' do
|
||||
expect(service.execute).not_to be_confirmed
|
||||
end
|
||||
end
|
||||
|
||||
context 'when "send_user_confirmation_email" application setting is false' do
|
||||
before do
|
||||
current_application_settings = double(:current_application_settings, send_user_confirmation_email: false, signup_enabled?: true)
|
||||
allow(service).to receive(:current_application_settings).and_return(current_application_settings)
|
||||
end
|
||||
|
||||
it 'confirms the user' do
|
||||
expect(service.execute).to be_confirmed
|
||||
end
|
||||
|
||||
it 'persists the given attributes' do
|
||||
user = service.execute
|
||||
user.reload
|
||||
|
@ -222,4 +169,3 @@ describe Users::CreateService, services: true do
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,8 +9,14 @@ require 'rspec/rails'
|
|||
require 'shoulda/matchers'
|
||||
require 'rspec/retry'
|
||||
|
||||
if (ENV['RSPEC_PROFILING_POSTGRES_URL'] || ENV['RSPEC_PROFILING']) &&
|
||||
(!ENV.has_key?('CI') || ENV['CI_COMMIT_REF_NAME'] == 'master')
|
||||
rspec_profiling_is_configured =
|
||||
ENV['RSPEC_PROFILING_POSTGRES_URL'] ||
|
||||
ENV['RSPEC_PROFILING']
|
||||
branch_can_be_profiled =
|
||||
ENV['CI_COMMIT_REF_NAME'] == 'master' ||
|
||||
ENV['CI_COMMIT_REF_NAME'] =~ /rspec-profile/
|
||||
|
||||
if rspec_profiling_is_configured && (!ENV.key?('CI') || branch_can_be_profiled)
|
||||
require 'rspec_profiling/rspec'
|
||||
end
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
module FixtureHelpers
|
||||
def fixture_file(filename)
|
||||
return '' if filename.blank?
|
||||
file_path = File.expand_path(Rails.root.join('spec/fixtures/', filename))
|
||||
File.read(file_path)
|
||||
File.read(expand_fixture_path(filename))
|
||||
end
|
||||
|
||||
def expand_fixture_path(filename)
|
||||
File.expand_path(Rails.root.join('spec/fixtures/', filename))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ describe 'gitlab:gitaly namespace rake task' do
|
|||
describe 'install' do
|
||||
let(:repo) { 'https://gitlab.com/gitlab-org/gitaly.git' }
|
||||
let(:clone_path) { Rails.root.join('tmp/tests/gitaly').to_s }
|
||||
let(:tag) { "v#{File.read(Rails.root.join(Gitlab::GitalyClient::SERVER_VERSION_FILE)).chomp}" }
|
||||
let(:version) { File.read(Rails.root.join(Gitlab::GitalyClient::SERVER_VERSION_FILE)).chomp }
|
||||
|
||||
context 'no dir given' do
|
||||
it 'aborts and display a help message' do
|
||||
|
@ -21,7 +21,7 @@ describe 'gitlab:gitaly namespace rake task' do
|
|||
context 'when an underlying Git command fail' do
|
||||
it 'aborts and display a help message' do
|
||||
expect_any_instance_of(Object).
|
||||
to receive(:checkout_or_clone_tag).and_raise 'Git error'
|
||||
to receive(:checkout_or_clone_version).and_raise 'Git error'
|
||||
|
||||
expect { run_rake_task('gitlab:gitaly:install', clone_path) }.to raise_error 'Git error'
|
||||
end
|
||||
|
@ -32,9 +32,9 @@ describe 'gitlab:gitaly namespace rake task' do
|
|||
expect(Dir).to receive(:chdir).with(clone_path)
|
||||
end
|
||||
|
||||
it 'calls checkout_or_clone_tag with the right arguments' do
|
||||
it 'calls checkout_or_clone_version with the right arguments' do
|
||||
expect_any_instance_of(Object).
|
||||
to receive(:checkout_or_clone_tag).with(tag: tag, repo: repo, target_dir: clone_path)
|
||||
to receive(:checkout_or_clone_version).with(version: version, repo: repo, target_dir: clone_path)
|
||||
|
||||
run_rake_task('gitlab:gitaly:install', clone_path)
|
||||
end
|
||||
|
@ -48,7 +48,7 @@ describe 'gitlab:gitaly namespace rake task' do
|
|||
|
||||
context 'gmake is available' do
|
||||
before do
|
||||
expect_any_instance_of(Object).to receive(:checkout_or_clone_tag)
|
||||
expect_any_instance_of(Object).to receive(:checkout_or_clone_version)
|
||||
allow_any_instance_of(Object).to receive(:run_command!).with(['gmake']).and_return(true)
|
||||
end
|
||||
|
||||
|
@ -62,7 +62,7 @@ describe 'gitlab:gitaly namespace rake task' do
|
|||
|
||||
context 'gmake is not available' do
|
||||
before do
|
||||
expect_any_instance_of(Object).to receive(:checkout_or_clone_tag)
|
||||
expect_any_instance_of(Object).to receive(:checkout_or_clone_version)
|
||||
allow_any_instance_of(Object).to receive(:run_command!).with(['make']).and_return(true)
|
||||
end
|
||||
|
||||
|
|
|
@ -10,19 +10,38 @@ describe Gitlab::TaskHelpers do
|
|||
|
||||
let(:repo) { 'https://gitlab.com/gitlab-org/gitlab-test.git' }
|
||||
let(:clone_path) { Rails.root.join('tmp/tests/task_helpers_tests').to_s }
|
||||
let(:version) { '1.1.0' }
|
||||
let(:tag) { 'v1.1.0' }
|
||||
|
||||
describe '#checkout_or_clone_tag' do
|
||||
describe '#checkout_or_clone_version' do
|
||||
before do
|
||||
allow(subject).to receive(:run_command!)
|
||||
expect(subject).to receive(:reset_to_tag).with(tag, clone_path)
|
||||
end
|
||||
|
||||
context 'target_dir does not exist' do
|
||||
it 'clones the repo, retrieve the tag from origin, and checkout the tag' do
|
||||
it 'checkout the version and reset to it' do
|
||||
expect(subject).to receive(:checkout_version).with(tag, clone_path)
|
||||
expect(subject).to receive(:reset_to_version).with(tag, clone_path)
|
||||
|
||||
subject.checkout_or_clone_version(version: version, repo: repo, target_dir: clone_path)
|
||||
end
|
||||
|
||||
context 'with a branch version' do
|
||||
let(:version) { '=branch_name' }
|
||||
let(:branch) { 'branch_name' }
|
||||
|
||||
it 'checkout the version and reset to it with a branch name' do
|
||||
expect(subject).to receive(:checkout_version).with(branch, clone_path)
|
||||
expect(subject).to receive(:reset_to_version).with(branch, clone_path)
|
||||
|
||||
subject.checkout_or_clone_version(version: version, repo: repo, target_dir: clone_path)
|
||||
end
|
||||
end
|
||||
|
||||
context "target_dir doesn't exist" do
|
||||
it 'clones the repo' do
|
||||
expect(subject).to receive(:clone_repo).with(repo, clone_path)
|
||||
|
||||
subject.checkout_or_clone_tag(tag: tag, repo: repo, target_dir: clone_path)
|
||||
subject.checkout_or_clone_version(version: version, repo: repo, target_dir: clone_path)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -31,10 +50,10 @@ describe Gitlab::TaskHelpers do
|
|||
expect(Dir).to receive(:exist?).and_return(true)
|
||||
end
|
||||
|
||||
it 'fetch and checkout the tag' do
|
||||
expect(subject).to receive(:checkout_tag).with(tag, clone_path)
|
||||
it "doesn't clone the repository" do
|
||||
expect(subject).not_to receive(:clone_repo)
|
||||
|
||||
subject.checkout_or_clone_tag(tag: tag, repo: repo, target_dir: clone_path)
|
||||
subject.checkout_or_clone_version(version: version, repo: repo, target_dir: clone_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -48,49 +67,23 @@ describe Gitlab::TaskHelpers do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#checkout_tag' do
|
||||
describe '#checkout_version' do
|
||||
it 'clones the repo in the target dir' do
|
||||
expect(subject).
|
||||
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} fetch --tags --quiet])
|
||||
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} fetch --quiet])
|
||||
expect(subject).
|
||||
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} checkout --quiet #{tag}])
|
||||
|
||||
subject.checkout_tag(tag, clone_path)
|
||||
subject.checkout_version(tag, clone_path)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#reset_to_tag' do
|
||||
let(:tag) { 'v1.1.0' }
|
||||
before do
|
||||
describe '#reset_to_version' do
|
||||
it 'resets --hard to the given version' do
|
||||
expect(subject).
|
||||
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} reset --hard #{tag}])
|
||||
end
|
||||
|
||||
context 'when the tag is not checked out locally' do
|
||||
before do
|
||||
expect(subject).
|
||||
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} describe -- #{tag}]).and_raise(Gitlab::TaskFailedError)
|
||||
end
|
||||
|
||||
it 'fetch origin, ensure the tag exists, and resets --hard to the given tag' do
|
||||
expect(subject).
|
||||
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} fetch origin])
|
||||
expect(subject).
|
||||
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} describe -- origin/#{tag}]).and_return(tag)
|
||||
|
||||
subject.reset_to_tag(tag, clone_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the tag is checked out locally' do
|
||||
before do
|
||||
expect(subject).
|
||||
to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} describe -- #{tag}]).and_return(tag)
|
||||
end
|
||||
|
||||
it 'resets --hard to the given tag' do
|
||||
subject.reset_to_tag(tag, clone_path)
|
||||
end
|
||||
subject.reset_to_version(tag, clone_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ describe 'gitlab:workhorse namespace rake task' do
|
|||
describe 'install' do
|
||||
let(:repo) { 'https://gitlab.com/gitlab-org/gitlab-workhorse.git' }
|
||||
let(:clone_path) { Rails.root.join('tmp/tests/gitlab-workhorse').to_s }
|
||||
let(:tag) { "v#{File.read(Rails.root.join(Gitlab::Workhorse::VERSION_FILE)).chomp}" }
|
||||
let(:version) { File.read(Rails.root.join(Gitlab::Workhorse::VERSION_FILE)).chomp }
|
||||
|
||||
context 'no dir given' do
|
||||
it 'aborts and display a help message' do
|
||||
|
@ -21,7 +21,7 @@ describe 'gitlab:workhorse namespace rake task' do
|
|||
context 'when an underlying Git command fail' do
|
||||
it 'aborts and display a help message' do
|
||||
expect_any_instance_of(Object).
|
||||
to receive(:checkout_or_clone_tag).and_raise 'Git error'
|
||||
to receive(:checkout_or_clone_version).and_raise 'Git error'
|
||||
|
||||
expect { run_rake_task('gitlab:workhorse:install', clone_path) }.to raise_error 'Git error'
|
||||
end
|
||||
|
@ -32,9 +32,9 @@ describe 'gitlab:workhorse namespace rake task' do
|
|||
expect(Dir).to receive(:chdir).with(clone_path)
|
||||
end
|
||||
|
||||
it 'calls checkout_or_clone_tag with the right arguments' do
|
||||
it 'calls checkout_or_clone_version with the right arguments' do
|
||||
expect_any_instance_of(Object).
|
||||
to receive(:checkout_or_clone_tag).with(tag: tag, repo: repo, target_dir: clone_path)
|
||||
to receive(:checkout_or_clone_version).with(version: version, repo: repo, target_dir: clone_path)
|
||||
|
||||
run_rake_task('gitlab:workhorse:install', clone_path)
|
||||
end
|
||||
|
@ -48,7 +48,7 @@ describe 'gitlab:workhorse namespace rake task' do
|
|||
|
||||
context 'gmake is available' do
|
||||
before do
|
||||
expect_any_instance_of(Object).to receive(:checkout_or_clone_tag)
|
||||
expect_any_instance_of(Object).to receive(:checkout_or_clone_version)
|
||||
allow_any_instance_of(Object).to receive(:run_command!).with(['gmake']).and_return(true)
|
||||
end
|
||||
|
||||
|
@ -62,7 +62,7 @@ describe 'gitlab:workhorse namespace rake task' do
|
|||
|
||||
context 'gmake is not available' do
|
||||
before do
|
||||
expect_any_instance_of(Object).to receive(:checkout_or_clone_tag)
|
||||
expect_any_instance_of(Object).to receive(:checkout_or_clone_version)
|
||||
allow_any_instance_of(Object).to receive(:run_command!).with(['make']).and_return(true)
|
||||
end
|
||||
|
||||
|
|
|
@ -699,6 +699,48 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|||
//
|
||||
//
|
||||
|
||||
var renderer = new _marked2.default.Renderer();
|
||||
|
||||
/*
|
||||
Regex to match KaTex blocks.
|
||||
|
||||
Supports the following:
|
||||
|
||||
\begin{equation}<math>\end{equation}
|
||||
$$<math>$$
|
||||
inline $<math>$
|
||||
|
||||
The matched text then goes through the KaTex renderer & then outputs the HTML
|
||||
*/
|
||||
var katexRegexString = '(\n ^\\\\begin{[a-zA-Z]+}\\s\n |\n ^\\$\\$\n |\n \\s\\$(?!\\$)\n)\n (.+?)\n(\n \\s\\\\end{[a-zA-Z]+}$\n |\n \\$\\$$\n |\n \\$\n)\n'.replace(/\s/g, '').trim();
|
||||
|
||||
renderer.paragraph = function (t) {
|
||||
var text = t;
|
||||
var inline = false;
|
||||
|
||||
if (typeof katex !== 'undefined') {
|
||||
var katexString = text.replace(/\\/g, '\\');
|
||||
var matches = new RegExp(katexRegexString, 'gi').exec(katexString);
|
||||
|
||||
if (matches && matches.length > 0) {
|
||||
if (matches[1].trim() === '$' && matches[3].trim() === '$') {
|
||||
inline = true;
|
||||
|
||||
text = katexString.replace(matches[0], '') + ' ' + katex.renderToString(matches[2]);
|
||||
} else {
|
||||
text = katex.renderToString(matches[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '<p class="' + (inline ? 'inline-katex' : '') + '">' + text + '</p>';
|
||||
};
|
||||
|
||||
_marked2.default.setOptions({
|
||||
sanitize: true,
|
||||
renderer: renderer
|
||||
});
|
||||
|
||||
exports.default = {
|
||||
components: {
|
||||
prompt: _prompt2.default
|
||||
|
@ -711,20 +753,7 @@ exports.default = {
|
|||
},
|
||||
computed: {
|
||||
markdown: function markdown() {
|
||||
var regex = new RegExp('^\\$\\$(.*)\\$\\$$', 'g');
|
||||
|
||||
var source = this.cell.source.map(function (line) {
|
||||
var matches = regex.exec(line.trim());
|
||||
|
||||
// Only render use the Katex library if it is actually loaded
|
||||
if (matches && matches.length > 0 && typeof katex !== 'undefined') {
|
||||
return katex.renderToString(matches[1]);
|
||||
}
|
||||
|
||||
return line;
|
||||
});
|
||||
|
||||
return (0, _marked2.default)(source.join(''));
|
||||
return (0, _marked2.default)(this.cell.source.join(''));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -3047,7 +3076,7 @@ exports = module.exports = __webpack_require__(1)(undefined);
|
|||
|
||||
|
||||
// module
|
||||
exports.push([module.i, ".markdown .katex{display:block;text-align:center}", ""]);
|
||||
exports.push([module.i, ".markdown .katex{display:block;text-align:center}.markdown .inline-katex .katex{display:inline;text-align:initial}", ""]);
|
||||
|
||||
// exports
|
||||
|
||||
|
|
Loading…
Reference in New Issue