Commit 13c1859a authored by Lin Jen-Shin's avatar Lin Jen-Shin

Merge remote-tracking branch 'upstream/master' into show-status-from-branch

* upstream/master: (67 commits)
  Stop unauthized users dragging on issue boards
  Capitalize Git
  Add docker-compose environment initialization command
  Improve readability and add specs for label filtering
  Improve label filtering implementation
  Allow the use of params[:name] when filtering labels
  Fix Rubocop offenses in issue move specs
  Add spec in Issues::MoveService to fix label assignment regression
  Fix bug where labels would be assigned to issues that were moved
  Fix `User#to_reference`
  Fix rubocop build error
  Remove redundant class_name and foreign_key overrides
  Enable SingleLinePerSelector in scss-lint
  Escape ref and path for relative links (!6050)
  Add failing test for #21420
  Enable SpaceAfterVariableColon in scss-lint
  Enable SpaceAroundOperator in scss-lint
  Enable trailingWhitespace in scss-lint
  Disable Rails/Output cop since it makes no sense here
  Use File.write instead of File.open + File#write
  ...
parents 7fac0e17 3b93574a
...@@ -210,7 +210,7 @@ rake brakeman: *exec ...@@ -210,7 +210,7 @@ rake brakeman: *exec
rake flay: *exec rake flay: *exec
license_finder: *exec license_finder: *exec
rake downtime_check: *exec rake downtime_check: *exec
rake ce_to_ee_merge_check: rake ee_compat_check:
<<: *exec <<: *exec
only: only:
- branches - branches
......
...@@ -172,7 +172,7 @@ linters: ...@@ -172,7 +172,7 @@ linters:
# Split selectors onto separate lines after each comma, and have each # Split selectors onto separate lines after each comma, and have each
# individual selector occupy a single line. # individual selector occupy a single line.
SingleLinePerSelector: SingleLinePerSelector:
enabled: false enabled: true
# Commas in lists should be followed by a space. # Commas in lists should be followed by a space.
SpaceAfterComma: SpaceAfterComma:
...@@ -191,7 +191,7 @@ linters: ...@@ -191,7 +191,7 @@ linters:
# Variables should be formatted with a single space separating the colon # Variables should be formatted with a single space separating the colon
# from the variable's value. # from the variable's value.
SpaceAfterVariableColon: SpaceAfterVariableColon:
enabled: false enabled: true
# Variables should be formatted with no space between the name and the # Variables should be formatted with no space between the name and the
# colon. # colon.
...@@ -201,7 +201,7 @@ linters: ...@@ -201,7 +201,7 @@ linters:
# Operators should be formatted with a single space on both sides of an # Operators should be formatted with a single space on both sides of an
# infix operator. # infix operator.
SpaceAroundOperator: SpaceAroundOperator:
enabled: false enabled: true
# Opening braces should be preceded by a single space. # Opening braces should be preceded by a single space.
SpaceBeforeBrace: SpaceBeforeBrace:
...@@ -223,7 +223,7 @@ linters: ...@@ -223,7 +223,7 @@ linters:
# Reports lines containing trailing whitespace. # Reports lines containing trailing whitespace.
TrailingWhitespace: TrailingWhitespace:
enabled: false enabled: true
# Don't write trailing zeros for numeric values with a decimal point. # Don't write trailing zeros for numeric values with a decimal point.
TrailingZero: TrailingZero:
......
...@@ -3,19 +3,31 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -3,19 +3,31 @@ Please view this file on the master branch, on stable branches it's out of date.
## 8.14.0 (2016-11-22) ## 8.14.0 (2016-11-22)
- Adds user project membership expired event to clarify why user was removed (Callum Dryden) - Adds user project membership expired event to clarify why user was removed (Callum Dryden)
- Trim leading and trailing whitespace on project_path (Linus Thiel) - Trim leading and trailing whitespace on project_path (Linus Thiel)
- Prevent award emoji via notes for issues/MRs authored by user (barthc)
- Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO)
- Fix extra space on Build sidebar on Firefox !7060
- Fix HipChat notifications rendering (airatshigapov, eisnerd) - Fix HipChat notifications rendering (airatshigapov, eisnerd)
- Add hover to trash icon in notes !7008 (blackst0ne) - Add hover to trash icon in notes !7008 (blackst0ne)
- Escape ref and path for relative links !6050 (winniehell)
- Simpler arguments passed to named_route on toggle_award_url helper method - Simpler arguments passed to named_route on toggle_award_url helper method
- Fix: Backup restore doesn't clear cache - Fix: Backup restore doesn't clear cache
- Fix showing pipeline status from correct branch !7034 - Fix showing pipeline status from correct branch !7034
- Use MergeRequestsClosingIssues cache data on Issue#closed_by_merge_requests method - Use MergeRequestsClosingIssues cache data on Issue#closed_by_merge_requests method
- Fix Sign in page 'Forgot your password?' link overlaps on medium-large screens
- Fix documents and comments on Build API `scope` - Fix documents and comments on Build API `scope`
- Refactor email, use setter method instead AR callbacks for email attribute (Semyon Pupkov) - Refactor email, use setter method instead AR callbacks for email attribute (Semyon Pupkov)
## 8.13.1 (unreleased) ## 8.13.1 (unreleased)
- Fix bug where labels would be assigned to issues that were moved
- Fix error in generating labels - Fix error in generating labels
- Fix reply-by-email not working due to queue name mismatch - Fix reply-by-email not working due to queue name mismatch
- Fixed hidden pipeline graph on commit and MR page !6895
- Expire and build repository cache after project import - Expire and build repository cache after project import
- Fix 404 for group pages when GitLab setup uses relative url
- Simpler arguments passed to named_route on toggle_award_url helper method
- Fix unauthorized users dragging on issue boards
- Better handle when no users were selected for adding to group or project. (Linus Thiel)
- Only show register tab if signup enabled.
## 8.13.0 (2016-10-22) ## 8.13.0 (2016-10-22)
- Removes extra line for empty issue description. (!7045) - Removes extra line for empty issue description. (!7045)
...@@ -97,6 +109,7 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -97,6 +109,7 @@ Please view this file on the master branch, on stable branches it's out of date.
- Add visibility level to project repository - Add visibility level to project repository
- Fix robots.txt disallowing access to groups starting with "s" (Matt Harrison) - Fix robots.txt disallowing access to groups starting with "s" (Matt Harrison)
- Close open merge request without source project (Katarzyna Kobierska Ula Budziszewska) - Close open merge request without source project (Katarzyna Kobierska Ula Budziszewska)
- Fix showing commits from source project for merge request !6658
- Fix that manual jobs would no longer block jobs in the next stage. !6604 - Fix that manual jobs would no longer block jobs in the next stage. !6604
- Add configurable email subject suffix (Fu Xu) - Add configurable email subject suffix (Fu Xu)
- Use defined colour for a language when available !6748 (nilsding) - Use defined colour for a language when available !6748 (nilsding)
...@@ -391,6 +404,7 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -391,6 +404,7 @@ Please view this file on the master branch, on stable branches it's out of date.
- Fix inconsistent checkbox alignment (ClemMakesApps) - Fix inconsistent checkbox alignment (ClemMakesApps)
- Use the default branch for displaying the project icon instead of master !5792 (Hannes Rosenögger) - Use the default branch for displaying the project icon instead of master !5792 (Hannes Rosenögger)
- Adds response mime type to transaction metric action when it's not HTML - Adds response mime type to transaction metric action when it's not HTML
- Fix branch protection API !6215
- Fix hover leading space bug in pipeline graph !5980 - Fix hover leading space bug in pipeline graph !5980
- Avoid conflict with admin labels when importing GitHub labels - Avoid conflict with admin labels when importing GitHub labels
- User can edit closed MR with deleted fork (Katarzyna Kobierska Ula Budziszewska) !5496 - User can edit closed MR with deleted fork (Katarzyna Kobierska Ula Budziszewska) !5496
......
...@@ -83,14 +83,15 @@ ...@@ -83,14 +83,15 @@
}; };
// Disable button if text field is empty // Disable button if text field is empty
window.disableButtonIfEmptyField = function(field_selector, button_selector) { window.disableButtonIfEmptyField = function(field_selector, button_selector, event_name) {
event_name = event_name || 'input';
var closest_submit, field; var closest_submit, field;
field = $(field_selector); field = $(field_selector);
closest_submit = field.closest('form').find(button_selector); closest_submit = field.closest('form').find(button_selector);
if (rstrip(field.val()) === "") { if (rstrip(field.val()) === "") {
closest_submit.disable(); closest_submit.disable();
} }
return field.on('input', function() { return field.on(event_name, function() {
if (rstrip($(this).val()) === "") { if (rstrip($(this).val()) === "") {
return closest_submit.disable(); return closest_submit.disable();
} else { } else {
......
...@@ -148,7 +148,7 @@ ...@@ -148,7 +148,7 @@
}; };
Build.prototype.translateSidebar = function(e) { Build.prototype.translateSidebar = function(e) {
var newPosition = this.sidebarTranslationLimits.max - document.body.scrollTop; var newPosition = this.sidebarTranslationLimits.max - (document.body.scrollTop || document.documentElement.scrollTop);
if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min; if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min;
this.$sidebar.css({ this.$sidebar.css({
top: newPosition top: newPosition
......
...@@ -117,6 +117,9 @@ ...@@ -117,6 +117,9 @@
new ZenMode(); new ZenMode();
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
break; break;
case 'projects:commit:builds':
new gl.Pipelines();
break;
case 'projects:commits:show': case 'projects:commits:show':
case 'projects:activity': case 'projects:activity':
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
......
...@@ -137,8 +137,11 @@ ...@@ -137,8 +137,11 @@
} }
initValidators () { initValidators () {
// select all non-hidden inputs in form // register selectors here as needed
this.state.inputs = this.form.find(':input:not([type=hidden])').toArray() const validateSelectors = [':text', ':password', '[type=email]']
.map((selector) => `input${selector}`).join(',');
this.state.inputs = this.form.find(validateSelectors).toArray()
.filter((input) => !input.classList.contains(customValidationFlag)) .filter((input) => !input.classList.contains(customValidationFlag))
.map((input) => new GlFieldError({ input, formErrors: this })); .map((input) => new GlFieldError({ input, formErrors: this }));
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
$('.project_member, .group_member').off('ajax:success').on('ajax:success', this.removeRow); $('.project_member, .group_member').off('ajax:success').on('ajax:success', this.removeRow);
$('.js-member-update-control').off('change').on('change', this.formSubmit); $('.js-member-update-control').off('change').on('change', this.formSubmit);
$('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess); $('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess);
disableButtonIfEmptyField('#user_ids', 'input[name=commit]', 'change');
} }
removeRow(e) { removeRow(e) {
......
...@@ -282,6 +282,7 @@ ...@@ -282,6 +282,7 @@
document.querySelector("div#builds").innerHTML = data.html; document.querySelector("div#builds").innerHTML = data.html;
gl.utils.localTimeAgo($('.js-timeago', 'div#builds')); gl.utils.localTimeAgo($('.js-timeago', 'div#builds'));
_this.buildsLoaded = true; _this.buildsLoaded = true;
if (!this.pipelines) this.pipelines = new gl.Pipelines();
return _this.scrollToElement("#builds"); return _this.scrollToElement("#builds");
}; };
})(this) })(this)
......
...@@ -37,7 +37,8 @@ ...@@ -37,7 +37,8 @@
} }
@include keyframes(pulse) { @include keyframes(pulse) {
from, to { from,
to {
@include webkit-prefix(transform, scale3d(1, 1, 1)); @include webkit-prefix(transform, scale3d(1, 1, 1));
} }
......
...@@ -128,7 +128,8 @@ ...@@ -128,7 +128,8 @@
position: relative; position: relative;
.avatar-holder { .avatar-holder {
.avatar, .identicon { .avatar,
.identicon {
margin: 0 auto; margin: 0 auto;
float: none; float: none;
} }
......
...@@ -213,7 +213,8 @@ ...@@ -213,7 +213,8 @@
top: 2px; top: 2px;
} }
svg, .fa { svg,
.fa {
&:not(:last-child) { &:not(:last-child) {
margin-right: 3px; margin-right: 3px;
} }
......
...@@ -143,7 +143,8 @@ li.note { ...@@ -143,7 +143,8 @@ li.note {
} }
} }
.wiki_content code, .readme code { .wiki_content code,
.readme code {
background-color: inherit; background-color: inherit;
} }
...@@ -350,7 +351,8 @@ table { ...@@ -350,7 +351,8 @@ table {
margin-right: 10px; margin-right: 10px;
} }
.alert, .progress { .alert,
.progress {
margin-bottom: $gl-padding; margin-bottom: $gl-padding;
} }
......
...@@ -275,7 +275,8 @@ ...@@ -275,7 +275,8 @@
a { a {
padding-left: 25px; padding-left: 25px;
&.is-indeterminate, &.is-active { &.is-indeterminate,
&.is-active {
&::before { &::before {
position: absolute; position: absolute;
left: 5px; left: 5px;
...@@ -373,7 +374,8 @@ ...@@ -373,7 +374,8 @@
} }
} }
.dropdown-input-field, .default-dropdown-input { .dropdown-input-field,
.default-dropdown-input {
width: 100%; width: 100%;
min-height: 30px; min-height: 30px;
padding: 0 7px; padding: 0 7px;
...@@ -402,7 +404,7 @@ ...@@ -402,7 +404,7 @@
.dropdown-content { .dropdown-content {
max-height: 215px; max-height: 215px;
overflow-y: scroll; overflow-y: auto;
} }
.dropdown-footer { .dropdown-footer {
......
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
margin: 0; margin: 0;
} }
.flash-notice, .flash-alert { .flash-notice,
.flash-alert {
border-radius: $border-radius-default; border-radius: $border-radius-default;
.container-fluid, .container-fluid,
...@@ -30,7 +31,8 @@ ...@@ -30,7 +31,8 @@
&.flash-container-page { &.flash-container-page {
margin-bottom: 0; margin-bottom: 0;
.flash-notice, .flash-alert { .flash-notice,
.flash-alert {
border-radius: 0; border-radius: 0;
} }
} }
......
...@@ -25,7 +25,9 @@ ...@@ -25,7 +25,9 @@
a { a {
color: $color-light; color: $color-light;
&:hover, &:focus, &:active { &:hover,
&:focus,
&:active {
background: $color-dark; background: $color-dark;
} }
......
...@@ -15,7 +15,8 @@ header { ...@@ -15,7 +15,8 @@ header {
margin: 8px 0; margin: 8px 0;
text-align: center; text-align: center;
.tanuki-logo, img { .tanuki-logo,
img {
height: 36px; height: 36px;
} }
} }
...@@ -54,7 +55,9 @@ header { ...@@ -54,7 +55,9 @@ header {
line-height: 28px; line-height: 28px;
text-align: center; text-align: center;
&:hover, &:focus, &:active { &:hover,
&:focus,
&:active {
background-color: $background-color; background-color: $background-color;
} }
...@@ -125,7 +128,8 @@ header { ...@@ -125,7 +128,8 @@ header {
left: -50%; left: -50%;
} }
svg, img { svg,
img {
height: 36px; height: 36px;
} }
...@@ -222,7 +226,8 @@ header { ...@@ -222,7 +226,8 @@ header {
margin: 0; margin: 0;
float: none !important; float: none !important;
.visible-xs, .visable-sm { .visible-xs,
.visable-sm {
display: table-cell !important; display: table-cell !important;
} }
} }
......
...@@ -76,14 +76,16 @@ ...@@ -76,14 +76,16 @@
/** light list with border-bottom between li **/ /** light list with border-bottom between li **/
ul.bordered-list, ul.unstyled-list { ul.bordered-list,
ul.unstyled-list {
@include basic-list; @include basic-list;
&.top-list { &.top-list {
li:first-child { li:first-child {
padding-top: 0; padding-top: 0;
h4, h5 { h4,
h5 {
margin-top: 0; margin-top: 0;
} }
} }
......
...@@ -79,7 +79,8 @@ ...@@ -79,7 +79,8 @@
padding-left: 15px !important; padding-left: 15px !important;
} }
.nav-links, .nav-links { .nav-links,
.nav-links {
li a { li a {
font-size: 14px; font-size: 14px;
padding: 19px 10px; padding: 19px 10px;
...@@ -99,18 +100,21 @@ ...@@ -99,18 +100,21 @@
@media (max-width: $screen-sm-max) { @media (max-width: $screen-sm-max) {
.issues-filters { .issues-filters {
.milestone-filter, .labels-filter { .milestone-filter,
.labels-filter {
display: none; display: none;
} }
} }
.page-title { .page-title {
.note-created-ago, .new-issue-link { .note-created-ago,
.new-issue-link {
display: none; display: none;
} }
} }
.issue_edited_ago, .note_edited_ago { .issue_edited_ago,
.note_edited_ago {
display: none; display: none;
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
padding: 15px; padding: 15px;
.form-actions { .form-actions {
margin: -$gl-padding+1; margin: -$gl-padding + 1;
margin-top: 15px; margin-top: 15px;
} }
......
...@@ -54,7 +54,9 @@ ...@@ -54,7 +54,9 @@
color: #959494; color: #959494;
border-bottom: 2px solid transparent; border-bottom: 2px solid transparent;
&:hover, &:active, &:focus { &:hover,
&:active,
&:focus {
text-decoration: none; text-decoration: none;
outline: none; outline: none;
} }
...@@ -211,7 +213,11 @@ ...@@ -211,7 +213,11 @@
padding-bottom: 0; padding-bottom: 0;
width: 100%; width: 100%;
.btn, form, .dropdown, .dropdown-menu-toggle, .form-control { .btn,
form,
.dropdown,
.dropdown-menu-toggle,
.form-control {
margin: 0 0 10px; margin: 0 0 10px;
display: block; display: block;
width: 100%; width: 100%;
...@@ -245,7 +251,8 @@ ...@@ -245,7 +251,8 @@
} }
&.adjust { &.adjust {
.nav-text, .nav-controls { .nav-text,
.nav-controls {
width: auto; width: auto;
} }
} }
...@@ -309,13 +316,15 @@ ...@@ -309,13 +316,15 @@
padding-top: 10px; padding-top: 10px;
} }
a, i { a,
i {
color: $layout-link-gray; color: $layout-link-gray;
} }
&.active { &.active {
a, i { a,
i {
color: $black; color: $black;
} }
...@@ -328,7 +337,8 @@ ...@@ -328,7 +337,8 @@
} }
&:hover { &:hover {
a, i { a,
i {
color: $black; color: $black;
} }
} }
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
width: 100% !important; width: 100% !important;
} }
.select2-container, .select2-container.select2-drop-above { .select2-container,
.select2-container.select2-drop-above {
.select2-choice { .select2-choice {
background: #fff; background: #fff;
border-color: $input-border; border-color: $input-border;
...@@ -71,7 +72,8 @@ ...@@ -71,7 +72,8 @@
} }
.select2-container-active { .select2-container-active {
.select2-choice, .select2-choices { .select2-choice,
.select2-choices {
box-shadow: none; box-shadow: none;
} }
} }
......
...@@ -23,7 +23,8 @@ table { ...@@ -23,7 +23,8 @@ table {
} }
tr { tr {
td, th { td,
th {
padding: 10px $gl-padding; padding: 10px $gl-padding;
line-height: 20px; line-height: 20px;
vertical-align: middle; vertical-align: middle;
......
...@@ -126,7 +126,8 @@ ...@@ -126,7 +126,8 @@
box-shadow: none; box-shadow: none;
.panel-body { .panel-body {
form, pre { form,
pre {
margin: 0; margin: 0;
} }
......
...@@ -131,12 +131,14 @@ ...@@ -131,12 +131,14 @@
font-weight: inherit; font-weight: inherit;
} }
ul, ol { ul,
ol {
padding: 0; padding: 0;
margin: 3px 0 3px 28px !important; margin: 3px 0 3px 28px !important;
} }
ul:dir(rtl), ol:dir(rtl) { ul:dir(rtl),
ol:dir(rtl) {
margin: 3px 28px 3px 0 !important; margin: 3px 28px 3px 0 !important;
} }
...@@ -144,7 +146,8 @@ ...@@ -144,7 +146,8 @@
line-height: 1.6em; line-height: 1.6em;
} }
a[href*="/uploads/"], a[href*="storage.googleapis.com/google-code-attachments/"] { a[href*="/uploads/"],
a[href*="storage.googleapis.com/google-code-attachments/"] {
&:before { &:before {
margin-right: 4px; margin-right: 4px;
...@@ -167,7 +170,12 @@ ...@@ -167,7 +170,12 @@
} }
/* Link to current header. */ /* Link to current header. */
h1, h2, h3, h4, h5, h6 { h1,
h2,
h3,
h4,
h5,
h6 {
position: relative; position: relative;
a.anchor { a.anchor {
...@@ -215,7 +223,12 @@ body { ...@@ -215,7 +223,12 @@ body {
margin: 12px 7px; margin: 12px 7px;
} }
h1, h2, h3, h4, h5, h6 { h1,
h2,
h3,
h4,
h5,
h6 {
color: $gl-title-color; color: $gl-title-color;
font-weight: 600; font-weight: 600;
} }
...@@ -273,7 +286,10 @@ a > code { ...@@ -273,7 +286,10 @@ a > code {
text-decoration: line-through; text-decoration: line-through;
} }
h1, h2, h3, h4 { h1,
h2,
h3,
h4 {
small { small {
color: $gl-gray; color: $gl-gray;
} }
......
/* https://github.com/MozMorris/tomorrow-pygments */ /* https://github.com/MozMorris/tomorrow-pygments */
.code.dark { .code.dark {
// Line numbers // Line numbers
.line-numbers, .diff-line-num { .line-numbers,
.diff-line-num {
background-color: #1d1f21; background-color: #1d1f21;
} }
.diff-line-num, .diff-line-num a { .diff-line-num,
.diff-line-num a {
color: rgba(255, 255, 255, 0.3); color: rgba(255, 255, 255, 0.3);
} }
// Code itself // Code itself
pre.code, .diff-line-num { pre.code,
.diff-line-num {
border-color: #666; border-color: #666;
} }
&, pre.code, .line_holder .line_content { &,
pre.code,
.line_holder .line_content {
background-color: #1d1f21; background-color: #1d1f21;
color: #c5c8c6; color: #c5c8c6;
} }
...@@ -31,11 +36,13 @@ ...@@ -31,11 +36,13 @@
border-color: darken(#557, 15%); border-color: darken(#557, 15%);
} }
.diff-line-num.new, .line_content.new { .diff-line-num.new,
.line_content.new {
@include diff_background(rgba(51, 255, 51, 0.1), rgba(51, 255, 51, 0.2), #808080); @include diff_background(rgba(51, 255, 51, 0.1), rgba(51, 255, 51, 0.2), #808080);
} }
.diff-line-num.old, .line_content.old { .diff-line-num.old,
.line_content.old {
@include diff_background(rgba(255, 51, 51, 0.2), rgba(255, 51, 51, 0.25), #808080); @include diff_background(rgba(255, 51, 51, 0.2), rgba(255, 51, 51, 0.25), #808080);
} }
......
/* https://github.com/richleland/pygments-css/blob/master/monokai.css */ /* https://github.com/richleland/pygments-css/blob/master/monokai.css */
.code.monokai { .code.monokai {
// Line numbers // Line numbers
.line-numbers, .diff-line-num { .line-numbers,
.diff-line-num {
background-color: #272822; background-color: #272822;
} }
.diff-line-num, .diff-line-num a { .diff-line-num,
.diff-line-num a {
color: rgba(255, 255, 255, 0.3); color: rgba(255, 255, 255, 0.3);
} }
// Code itself // Code itself
pre.code, .diff-line-num { pre.code,
.diff-line-num {
border-color: #555; border-color: #555;
} }
&, pre.code, .line_holder .line_content { &,
pre.code,
.line_holder .line_content {
background-color: #272822; background-color: #272822;
color: #f8f8f2; color: #f8f8f2;
} }
...@@ -31,11 +36,13 @@ ...@@ -31,11 +36,13 @@
border-color: darken(#49483e, 15%); border-color: darken(#49483e, 15%);
} }
.diff-line-num.new, .line_content.new { .diff-line-num.new,
.line_content.new {
@include diff_background(rgba(166, 226, 46, 0.1), rgba(166, 226, 46, 0.15), #808080); @include diff_background(rgba(166, 226, 46, 0.1), rgba(166, 226, 46, 0.15), #808080);
} }
.diff-line-num.old, .line_content.old { .diff-line-num.old,
.line_content.old {
@include diff_background(rgba(254, 147, 140, 0.15), rgba(254, 147, 140, 0.2), #808080); @include diff_background(rgba(254, 147, 140, 0.15), rgba(254, 147, 140, 0.2), #808080);
} }
......
/* https://gist.github.com/qguv/7936275 */ /* https://gist.github.com/qguv/7936275 */
.code.solarized-dark { .code.solarized-dark {
// Line numbers // Line numbers
.line-numbers, .diff-line-num { .line-numbers,
.diff-line-num {
background-color: #002b36; background-color: #002b36;
} }
.diff-line-num, .diff-line-num a { .diff-line-num,
.diff-line-num a {
color: rgba(255, 255, 255, 0.3); color: rgba(255, 255, 255, 0.3);
} }
// Code itself // Code itself
pre.code, .diff-line-num { pre.code,
.diff-line-num {
border-color: #113b46; border-color: #113b46;
} }
&, pre.code, .line_holder .line_content { &,
pre.code,
.line_holder .line_content {
background-color: #002b36; background-color: #002b36;
color: #93a1a1; color: #93a1a1;
} }
...@@ -31,11 +36,13 @@ ...@@ -31,11 +36,13 @@
border-color: darken(#174652, 15%); border-color: darken(#174652, 15%);
} }
.diff-line-num.new, .line_content.new { .diff-line-num.new,
.line_content.new {
@include diff_background(rgba(133, 153, 0, 0.15), rgba(133, 153, 0, 0.25), #113b46); @include diff_background(rgba(133, 153, 0, 0.15), rgba(133, 153, 0, 0.25), #113b46);
} }
.diff-line-num.old, .line_content.old { .diff-line-num.old,
.line_content.old {
@include diff_background(rgba(220, 50, 47, 0.3), rgba(220, 50, 47, 0.25), #113b46); @include diff_background(rgba(220, 50, 47, 0.3), rgba(220, 50, 47, 0.25), #113b46);
} }
......
...@@ -7,20 +7,25 @@ ...@@ -7,20 +7,25 @@
.code.solarized-light { .code.solarized-light {
// Line numbers // Line numbers
.line-numbers, .diff-line-num { .line-numbers,
.diff-line-num {
background-color: #fdf6e3; background-color: #fdf6e3;
} }
.diff-line-num, .diff-line-num a { .diff-line-num,
.diff-line-num a {
color: $black-transparent; color: $black-transparent;
} }
// Code itself // Code itself
pre.code, .diff-line-num { pre.code,
.diff-line-num {
border-color: #c5d0d4; border-color: #c5d0d4;
} }
&, pre.code, .line_holder .line_content { &,
pre.code,
.line_holder .line_content {
background-color: #fdf6e3; background-color: #fdf6e3;
color: #586e75; color: #586e75;
} }
...@@ -37,11 +42,13 @@ ...@@ -37,11 +42,13 @@
border-color: darken(#ddd8c5, 15%); border-color: darken(#ddd8c5, 15%);
} }
.diff-line-num.new, .line_content.new { .diff-line-num.new,
.line_content.new {
@include diff_background(rgba(133, 153, 0, 0.2), rgba(133, 153, 0, 0.25), #c5d0d4); @include diff_background(rgba(133, 153, 0, 0.2), rgba(133, 153, 0, 0.25), #c5d0d4);
} }
.diff-line-num.old, .line_content.old { .diff-line-num.old,
.line_content.old {
@include diff_background(rgba(220, 50, 47, 0.2), rgba(220, 50, 47, 0.25), #c5d0d4); @include diff_background(rgba(220, 50, 47, 0.2), rgba(220, 50, 47, 0.25), #c5d0d4);
} }
......
...@@ -7,20 +7,25 @@ ...@@ -7,20 +7,25 @@
.code.white { .code.white {
// Line numbers // Line numbers
.line-numbers, .diff-line-num { .line-numbers,
.diff-line-num {
background-color: $background-color; background-color: $background-color;
} }
.diff-line-num, .diff-line-num a { .diff-line-num,
.diff-line-num a {
color: $black-transparent; color: $black-transparent;
} }
// Code itself // Code itself
pre.code, .diff-line-num { pre.code,
.diff-line-num {
border-color: $table-border-gray; border-color: $table-border-gray;
} }
&, pre.code, .line_holder .line_content { &,
pre.code,
.line_holder .line_content {
background-color: #fff; background-color: #fff;
color: #333; color: #333;
} }
......
...@@ -56,7 +56,8 @@ ...@@ -56,7 +56,8 @@
padding: 10px; padding: 10px;
text-align: center; text-align: center;
> div, p { > div,
p {
display: inline; display: inline;
margin: 0; margin: 0;
......
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
border-color: $border-color; border-color: $border-color;
} }
th, td { th,
td {
padding: 10px $gl-padding; padding: 10px $gl-padding;
} }
......
...@@ -2,14 +2,16 @@ ...@@ -2,14 +2,16 @@
display: block; display: block;
} }
.commit-author, .commit-committer { .commit-author,
.commit-committer {
display: block; display: block;
color: #999; color: #999;
font-weight: normal; font-weight: normal;
font-style: italic; font-style: italic;
} }
.commit-author strong, .commit-committer strong { .commit-author strong,
.commit-committer strong {
font-weight: bold; font-weight: bold;
font-style: normal; font-style: normal;
} }
......
...@@ -63,7 +63,8 @@ ...@@ -63,7 +63,8 @@
display: inline-block; display: inline-block;
} }
.btn-clipboard, .btn-transparent { .btn-clipboard,
.btn-transparent {
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
} }
...@@ -162,7 +163,8 @@ ...@@ -162,7 +163,8 @@
.branch-commit { .branch-commit {
color: $gl-gray; color: $gl-gray;
.commit-id, .commit-row-message { .commit-id,
.commit-row-message {
color: $gl-gray; color: $gl-gray;
} }
} }
......
...@@ -2,7 +2,12 @@ ...@@ -2,7 +2,12 @@
margin-bottom: 20px; margin-bottom: 20px;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
> h1, h2, h3, h4, h5, h6 { > h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 400; font-weight: 400;
} }
...@@ -10,7 +15,8 @@ ...@@ -10,7 +15,8 @@
margin-bottom: 20px; margin-bottom: 20px;
} }
ul, ol { ul,
ol {
padding-left: 0; padding-left: 0;
} }
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
color: #5c5d5e; color: #5c5d5e;
} }
.issue_created_ago, .author_link { .issue_created_ago,
.author_link {
white-space: nowrap; white-space: nowrap;
} }
} }
......
...@@ -124,7 +124,8 @@ ...@@ -124,7 +124,8 @@
} }
} }
.old_line, .new_line { .old_line,
.new_line {
margin: 0; margin: 0;
padding: 0; padding: 0;
border: none; border: none;
...@@ -281,7 +282,8 @@ ...@@ -281,7 +282,8 @@
position: relative; position: relative;
} }
.frame.added, .frame.deleted { .frame.added,
.frame.deleted {
position: absolute; position: absolute;
display: block; display: block;
top: 0; top: 0;
...@@ -347,7 +349,8 @@ ...@@ -347,7 +349,8 @@
text-align: center; text-align: center;
background: #eee; background: #eee;
ul, li { ul,
li {
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 0; padding: 0;
......
...@@ -91,7 +91,9 @@ ...@@ -91,7 +91,9 @@
} }
} }
.gitignore-selector, .license-selector, .gitlab-ci-yml-selector { .gitignore-selector,
.license-selector,
.gitlab-ci-yml-selector {
.dropdown { .dropdown {
line-height: 21px; line-height: 21px;
} }
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
max-width: 400px; max-width: 400px;
margin: 0 auto; margin: 0 auto;
h1, h2, h3 { h1,
h2,
h3 {
text-align: center; text-align: center;
} }
......
...@@ -43,7 +43,8 @@ ul.related-merge-requests > li { ...@@ -43,7 +43,8 @@ ul.related-merge-requests > li {
} }
} }
.merge-requests-title, .related-branches-title { .merge-requests-title,
.related-branches-title {
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
} }
......
...@@ -41,7 +41,8 @@ ...@@ -41,7 +41,8 @@
font-size: 13px; font-size: 13px;
} }
.login-box, .omniauth-container { .login-box,
.omniauth-container {
box-shadow: 0 0 0 1px $border-color; box-shadow: 0 0 0 1px $border-color;
border-bottom-right-radius: 2px; border-bottom-right-radius: 2px;
border-bottom-left-radius: 2px; border-bottom-left-radius: 2px;
...@@ -198,7 +199,8 @@ ...@@ -198,7 +199,8 @@
.form-control { .form-control {
&:active, &:focus { &:active,
&:focus {
background-color: #fff; background-color: #fff;
} }
} }
...@@ -261,7 +263,8 @@ ...@@ -261,7 +263,8 @@
position: relative; position: relative;
} }
.footer-container, hr.footer-fixed { .footer-container,
hr.footer-fixed {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0; left: 0;
...@@ -286,6 +289,13 @@ ...@@ -286,6 +289,13 @@
.new_user { .new_user {
position: relative; position: relative;
padding-bottom: 35px; padding-bottom: 35px;
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
.forgot-password {
float: none !important;
margin-top: 5px;
}
}
} }
.move-submit-down { .move-submit-down {
......
...@@ -101,7 +101,8 @@ $colors: ( ...@@ -101,7 +101,8 @@ $colors: (
@mixin color-scheme($color) { @mixin color-scheme($color) {
.header.line_content, .diff-line-num { .header.line_content,
.diff-line-num {
&.origin { &.origin {
background-color: map-get($colors, #{$color}_header_origin_neutral); background-color: map-get($colors, #{$color}_header_origin_neutral);
border-color: map-get($colors, #{$color}_header_origin_neutral); border-color: map-get($colors, #{$color}_header_origin_neutral);
......
...@@ -50,7 +50,8 @@ ...@@ -50,7 +50,8 @@
} }
} }
.issues-sortable-list, .merge_requests-sortable-list { .issues-sortable-list,
.merge_requests-sortable-list {
.issuable-detail { .issuable-detail {
display: block; display: block;
margin-top: 7px; margin-top: 7px;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
.diff-file .diff-content { .diff-file .diff-content {
tr.line_holder:hover > td .line_note_link { tr.line_holder:hover > td .line_note_link {
opacity: 1.0; opacity: 1.0;
filter: alpha(opacity=100); filter: alpha(opacity = 100);
} }
} }
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
display: none; display: none;
} }
.new-note, .note-edit-form { .new-note,
.note-edit-form {
.note-form-actions { .note-form-actions {
margin-top: $gl-padding; margin-top: $gl-padding;
} }
......
...@@ -28,7 +28,8 @@ ul.notes { ...@@ -28,7 +28,8 @@ ul.notes {
} }
} }
.note-created-ago, .note-updated-at { .note-created-ago,
.note-updated-at {
white-space: nowrap; white-space: nowrap;
} }
......
...@@ -248,7 +248,8 @@ ...@@ -248,7 +248,8 @@
font-size: 14px; font-size: 14px;
} }
svg, .fa { svg,
.fa {
margin-right: 0; margin-right: 0;
} }
} }
...@@ -529,7 +530,8 @@ ...@@ -529,7 +530,8 @@
// Connect each build (except for first) with curved lines // Connect each build (except for first) with curved lines
&:not(:first-child) { &:not(:first-child) {
&::after, &::before { &::after,
&::before {
content: ''; content: '';
top: -49px; top: -49px;
position: absolute; position: absolute;
...@@ -555,7 +557,8 @@ ...@@ -555,7 +557,8 @@
// Connect second build to first build with smaller curved line // Connect second build to first build with smaller curved line
&:nth-child(2) { &:nth-child(2) {
&::after, &::before { &::after,
&::before {
height: 29px; height: 29px;
top: -9px; top: -9px;
} }
...@@ -570,7 +573,8 @@ ...@@ -570,7 +573,8 @@
.build { .build {
// Remove right connecting horizontal line from first build in last stage // Remove right connecting horizontal line from first build in last stage
&:first-child { &:first-child {
&::after, &::before { &::after,
&::before {
border: none; border: none;
} }
} }
......
...@@ -253,7 +253,8 @@ ...@@ -253,7 +253,8 @@
} }
table.u2f-registrations { table.u2f-registrations {
th:not(:last-child), td:not(:last-child) { th:not(:last-child),
td:not(:last-child) {
border-right: solid 1px transparent; border-right: solid 1px transparent;
} }
} }
\ No newline at end of file
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
} }
} }
.no-ssh-key-message, .project-limit-message { .no-ssh-key-message,
.project-limit-message {
background-color: #f28d35; background-color: #f28d35;
margin-bottom: 0; margin-bottom: 0;
} }
...@@ -385,7 +386,8 @@ a.deploy-project-label { ...@@ -385,7 +386,8 @@ a.deploy-project-label {
text-align: center; text-align: center;
width: 169px; width: 169px;
&:hover, &.forked { &:hover,
&.forked {
background-color: $row-hover; background-color: $row-hover;
border-color: $row-hover-border; border-color: $row-hover-border;
} }
...@@ -734,7 +736,8 @@ pre.light-well { ...@@ -734,7 +736,8 @@ pre.light-well {
.table-bordered { .table-bordered {
border-radius: 1px; border-radius: 1px;
th:not(:last-child), td:not(:last-child) { th:not(:last-child),
td:not(:last-child) {
border-right: solid 1px transparent; border-right: solid 1px transparent;
} }
} }
...@@ -757,7 +760,8 @@ pre.light-well { ...@@ -757,7 +760,8 @@ pre.light-well {
} }
} }
.project-refs-form .dropdown-menu, .dropdown-menu-projects { .project-refs-form .dropdown-menu,
.dropdown-menu-projects {
width: 300px; width: 300px;
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
......
...@@ -65,7 +65,8 @@ ...@@ -65,7 +65,8 @@
.search-input-wrap { .search-input-wrap {
width: 100%; width: 100%;
.search-icon, .clear-icon { .search-icon,
.clear-icon {
position: absolute; position: absolute;
right: 5px; right: 5px;
top: 0; top: 0;
...@@ -185,7 +186,8 @@ ...@@ -185,7 +186,8 @@
padding-right: $gl-padding + 15px; padding-right: $gl-padding + 15px;
} }
.btn-search, .btn-new { .btn-search,
.btn-new {
width: 100%; width: 100%;
margin-top: 5px; margin-top: 5px;
......
...@@ -23,7 +23,8 @@ ...@@ -23,7 +23,8 @@
border-bottom: 1px solid $table-border-gray; border-bottom: 1px solid $table-border-gray;
border-top: 1px solid $table-border-gray; border-top: 1px solid $table-border-gray;
td, th { td,
th {
line-height: 21px; line-height: 21px;
} }
...@@ -74,7 +75,8 @@ ...@@ -74,7 +75,8 @@
max-width: 320px; max-width: 320px;
vertical-align: middle; vertical-align: middle;
i, a { i,
a {
color: $gl-dark-link-color; color: $gl-dark-link-color;
} }
......
.wiki h1, .wiki h2, .wiki h3, .wiki h4, .wiki h5, .wiki h6 {margin-top: 17px; } .wiki h1,
.wiki h1 {font-size: 30px;} .wiki h2,
.wiki h2 {font-size: 22px;} .wiki h3,
.wiki h3 {font-size: 18px; font-weight: bold; } .wiki h4,
.wiki h5,
.wiki h6 {
margin-top: 17px;
}
.wiki h1 {
font-size: 30px;
}
.wiki h2 {
font-size: 22px;
}
.wiki h3 {
font-size: 18px;
font-weight: bold;
}
header, header,
nav, nav,
......
...@@ -21,6 +21,10 @@ class Groups::GroupMembersController < Groups::ApplicationController ...@@ -21,6 +21,10 @@ class Groups::GroupMembersController < Groups::ApplicationController
end end
def create def create
if params[:user_ids].blank?
return redirect_to(group_group_members_path(@group), alert: 'No users specified.')
end
@group.add_users( @group.add_users(
params[:user_ids].split(','), params[:user_ids].split(','),
params[:access_level], params[:access_level],
......
...@@ -2,8 +2,8 @@ class Import::GitlabProjectsController < Import::BaseController ...@@ -2,8 +2,8 @@ class Import::GitlabProjectsController < Import::BaseController
before_action :verify_gitlab_project_import_enabled before_action :verify_gitlab_project_import_enabled
def new def new
@namespace_id = project_params[:namespace_id] @namespace = Namespace.find(project_params[:namespace_id])
@namespace_name = Namespace.find(project_params[:namespace_id]).name return render_404 unless current_user.can?(:create_projects, @namespace)
@path = project_params[:path] @path = project_params[:path]
end end
......
...@@ -25,6 +25,10 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -25,6 +25,10 @@ class Projects::ProjectMembersController < Projects::ApplicationController
end end
def create def create
if params[:user_ids].blank?
return redirect_to(namespace_project_project_members_path(@project.namespace, @project), alert: 'No users or groups specified.')
end
@project.team.add_users( @project.team.add_users(
params[:user_ids].split(','), params[:user_ids].split(','),
params[:access_level], params[:access_level],
...@@ -32,7 +36,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController ...@@ -32,7 +36,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
current_user: current_user current_user: current_user
) )
redirect_to namespace_project_project_members_path(@project.namespace, @project) redirect_to namespace_project_project_members_path(@project.namespace, @project), notice: 'Users were successfully added.'
end end
def update def update
......
...@@ -35,8 +35,10 @@ class LabelsFinder < UnionFinder ...@@ -35,8 +35,10 @@ class LabelsFinder < UnionFinder
end end
def with_title(items) def with_title(items)
items = items.where(title: title) if title return items if title.nil?
items return items.none if title.blank?
items.where(title: title)
end end
def group_id def group_id
...@@ -52,7 +54,7 @@ class LabelsFinder < UnionFinder ...@@ -52,7 +54,7 @@ class LabelsFinder < UnionFinder
end end
def title def title
params[:title].presence || params[:name].presence params[:title] || params[:name]
end end
def project def project
......
...@@ -5,7 +5,7 @@ module BoardsHelper ...@@ -5,7 +5,7 @@ module BoardsHelper
{ {
endpoint: namespace_project_boards_path(@project.namespace, @project), endpoint: namespace_project_boards_path(@project.namespace, @project),
board_id: board.id, board_id: board.id,
disabled: !can?(current_user, :admin_list, @project), disabled: "#{!can?(current_user, :admin_list, @project)}",
issue_link_base: namespace_project_issues_path(@project.namespace, @project) issue_link_base: namespace_project_issues_path(@project.namespace, @project)
} }
end end
......
...@@ -3,8 +3,8 @@ module Ci ...@@ -3,8 +3,8 @@ module Ci
include TokenAuthenticatable include TokenAuthenticatable
include AfterCommitQueue include AfterCommitQueue
belongs_to :runner, class_name: 'Ci::Runner' belongs_to :runner
belongs_to :trigger_request, class_name: 'Ci::TriggerRequest' belongs_to :trigger_request
belongs_to :erased_by, class_name: 'User' belongs_to :erased_by, class_name: 'User'
serialize :options serialize :options
......
...@@ -7,12 +7,12 @@ module Ci ...@@ -7,12 +7,12 @@ module Ci
self.table_name = 'ci_commits' self.table_name = 'ci_commits'
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, foreign_key: :gl_project_id
belongs_to :user belongs_to :user
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
has_many :builds, class_name: 'Ci::Build', foreign_key: :commit_id has_many :builds, foreign_key: :commit_id
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest', foreign_key: :commit_id has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id
validates_presence_of :sha, unless: :importing? validates_presence_of :sha, unless: :importing?
validates_presence_of :ref, unless: :importing? validates_presence_of :ref, unless: :importing?
......
...@@ -6,9 +6,9 @@ module Ci ...@@ -6,9 +6,9 @@ module Ci
AVAILABLE_SCOPES = %w[specific shared active paused online] AVAILABLE_SCOPES = %w[specific shared active paused online]
FORM_EDITABLE = %i[description tag_list active run_untagged locked] FORM_EDITABLE = %i[description tag_list active run_untagged locked]
has_many :builds, class_name: 'Ci::Build' has_many :builds
has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject' has_many :runner_projects, dependent: :destroy
has_many :projects, through: :runner_projects, class_name: '::Project', foreign_key: :gl_project_id has_many :projects, through: :runner_projects, foreign_key: :gl_project_id
has_one :last_build, ->() { order('id DESC') }, class_name: 'Ci::Build' has_one :last_build, ->() { order('id DESC') }, class_name: 'Ci::Build'
......
...@@ -2,8 +2,8 @@ module Ci ...@@ -2,8 +2,8 @@ module Ci
class RunnerProject < ActiveRecord::Base class RunnerProject < ActiveRecord::Base
extend Ci::Model extend Ci::Model
belongs_to :runner, class_name: 'Ci::Runner' belongs_to :runner
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, foreign_key: :gl_project_id
validates_uniqueness_of :runner_id, scope: :gl_project_id validates_uniqueness_of :runner_id, scope: :gl_project_id
end end
......
...@@ -4,8 +4,8 @@ module Ci ...@@ -4,8 +4,8 @@ module Ci
acts_as_paranoid acts_as_paranoid
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, foreign_key: :gl_project_id
has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest' has_many :trigger_requests, dependent: :destroy
validates_presence_of :token validates_presence_of :token
validates_uniqueness_of :token validates_uniqueness_of :token
......
...@@ -2,9 +2,9 @@ module Ci ...@@ -2,9 +2,9 @@ module Ci
class TriggerRequest < ActiveRecord::Base class TriggerRequest < ActiveRecord::Base
extend Ci::Model extend Ci::Model
belongs_to :trigger, class_name: 'Ci::Trigger' belongs_to :trigger
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id belongs_to :pipeline, foreign_key: :commit_id
has_many :builds, class_name: 'Ci::Build' has_many :builds
serialize :variables serialize :variables
......
...@@ -2,7 +2,7 @@ module Ci ...@@ -2,7 +2,7 @@ module Ci
class Variable < ActiveRecord::Base class Variable < ActiveRecord::Base
extend Ci::Model extend Ci::Model
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, foreign_key: :gl_project_id
validates_uniqueness_of :key, scope: :gl_project_id validates_uniqueness_of :key, scope: :gl_project_id
validates :key, validates :key,
......
...@@ -5,7 +5,7 @@ class CommitStatus < ActiveRecord::Base ...@@ -5,7 +5,7 @@ class CommitStatus < ActiveRecord::Base
self.table_name = 'ci_builds' self.table_name = 'ci_builds'
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id belongs_to :project, foreign_key: :gl_project_id
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
belongs_to :user belongs_to :user
......
module ProtectedBranchAccess module ProtectedBranchAccess
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do
scope :master, -> { where(access_level: Gitlab::Access::MASTER) }
scope :developer, -> { where(access_level: Gitlab::Access::DEVELOPER) }
end
def humanize def humanize
self.class.human_access_levels[self.access_level] self.class.human_access_levels[self.access_level]
end end
......
...@@ -6,7 +6,7 @@ class Group < Namespace ...@@ -6,7 +6,7 @@ class Group < Namespace
include AccessRequestable include AccessRequestable
include Referable include Referable
has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember' has_many :group_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source
alias_method :members, :group_members alias_method :members, :group_members
has_many :users, through: :group_members has_many :users, through: :group_members
has_many :owners, has_many :owners,
...@@ -68,7 +68,7 @@ class Group < Namespace ...@@ -68,7 +68,7 @@ class Group < Namespace
end end
def web_url def web_url
Gitlab::Routing.url_helpers.group_canonical_url(self) Gitlab::Routing.url_helpers.group_url(self)
end end
def human_name def human_name
......
class GroupMember < Member class GroupMember < Member
SOURCE_TYPE = 'Namespace' SOURCE_TYPE = 'Namespace'
belongs_to :group, class_name: 'Group', foreign_key: 'source_id' belongs_to :group, foreign_key: 'source_id'
# Make sure group member points only to group as it source # Make sure group member points only to group as it source
default_value_for :source_type, SOURCE_TYPE default_value_for :source_type, SOURCE_TYPE
......
...@@ -3,7 +3,7 @@ class ProjectMember < Member ...@@ -3,7 +3,7 @@ class ProjectMember < Member
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
belongs_to :project, class_name: 'Project', foreign_key: 'source_id' belongs_to :project, foreign_key: 'source_id'
# Make sure project member points only to project as it source # Make sure project member points only to project as it source
default_value_for :source_type, SOURCE_TYPE default_value_for :source_type, SOURCE_TYPE
......
...@@ -6,8 +6,8 @@ class MergeRequest < ActiveRecord::Base ...@@ -6,8 +6,8 @@ class MergeRequest < ActiveRecord::Base
include Taskable include Taskable
include Importable include Importable
belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project" belongs_to :target_project, class_name: "Project"
belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project" belongs_to :source_project, class_name: "Project"
belongs_to :merge_user, class_name: "User" belongs_to :merge_user, class_name: "User"
has_many :merge_request_diffs, dependent: :destroy has_many :merge_request_diffs, dependent: :destroy
......
...@@ -299,8 +299,10 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -299,8 +299,10 @@ class MergeRequestDiff < ActiveRecord::Base
end end
def keep_around_commits def keep_around_commits
repository.keep_around(start_commit_sha) [repository, merge_request.source_project.repository].each do |repo|
repository.keep_around(head_commit_sha) repo.keep_around(start_commit_sha)
repository.keep_around(base_commit_sha) repo.keep_around(head_commit_sha)
repo.keep_around(base_commit_sha)
end
end end
end end
...@@ -63,11 +63,11 @@ class Project < ActiveRecord::Base ...@@ -63,11 +63,11 @@ class Project < ActiveRecord::Base
alias_attribute :title, :name alias_attribute :title, :name
# Relations # Relations
belongs_to :creator, foreign_key: 'creator_id', class_name: 'User' belongs_to :creator, class_name: 'User'
belongs_to :group, -> { where(type: 'Group') }, foreign_key: 'namespace_id' belongs_to :group, -> { where(type: 'Group') }, foreign_key: 'namespace_id'
belongs_to :namespace belongs_to :namespace
has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id' has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event'
has_many :boards, before_add: :validate_board_limit, dependent: :destroy has_many :boards, before_add: :validate_board_limit, dependent: :destroy
# Project services # Project services
...@@ -116,7 +116,7 @@ class Project < ActiveRecord::Base ...@@ -116,7 +116,7 @@ class Project < ActiveRecord::Base
has_many :hooks, dependent: :destroy, class_name: 'ProjectHook' has_many :hooks, dependent: :destroy, class_name: 'ProjectHook'
has_many :protected_branches, dependent: :destroy has_many :protected_branches, dependent: :destroy
has_many :project_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'ProjectMember' has_many :project_members, -> { where(requested_at: nil) }, dependent: :destroy, as: :source
alias_method :members, :project_members alias_method :members, :project_members
has_many :users, through: :project_members has_many :users, through: :project_members
...@@ -137,7 +137,7 @@ class Project < ActiveRecord::Base ...@@ -137,7 +137,7 @@ class Project < ActiveRecord::Base
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData" has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"
has_one :project_feature, dependent: :destroy has_one :project_feature, dependent: :destroy
has_many :commit_statuses, dependent: :destroy, class_name: 'CommitStatus', foreign_key: :gl_project_id has_many :commit_statuses, dependent: :destroy, foreign_key: :gl_project_id
has_many :pipelines, dependent: :destroy, class_name: 'Ci::Pipeline', foreign_key: :gl_project_id has_many :pipelines, dependent: :destroy, class_name: 'Ci::Pipeline', foreign_key: :gl_project_id
has_many :builds, class_name: 'Ci::Build', foreign_key: :gl_project_id # the builds are created from the commit_statuses has_many :builds, class_name: 'Ci::Build', foreign_key: :gl_project_id # the builds are created from the commit_statuses
has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject', foreign_key: :gl_project_id has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject', foreign_key: :gl_project_id
......
...@@ -47,7 +47,7 @@ class User < ActiveRecord::Base ...@@ -47,7 +47,7 @@ class User < ActiveRecord::Base
# #
# Namespace for personal projects # Namespace for personal projects
has_one :namespace, -> { where type: nil }, dependent: :destroy, foreign_key: :owner_id, class_name: "Namespace" has_one :namespace, -> { where type: nil }, dependent: :destroy, foreign_key: :owner_id
# Profile # Profile
has_many :keys, dependent: :destroy has_many :keys, dependent: :destroy
...@@ -66,17 +66,17 @@ class User < ActiveRecord::Base ...@@ -66,17 +66,17 @@ class User < ActiveRecord::Base
# Projects # Projects
has_many :groups_projects, through: :groups, source: :projects has_many :groups_projects, through: :groups, source: :projects
has_many :personal_projects, through: :namespace, source: :projects has_many :personal_projects, through: :namespace, source: :projects
has_many :project_members, -> { where(requested_at: nil) }, dependent: :destroy, class_name: 'ProjectMember' has_many :project_members, -> { where(requested_at: nil) }, dependent: :destroy
has_many :projects, through: :project_members has_many :projects, through: :project_members
has_many :created_projects, foreign_key: :creator_id, class_name: 'Project' has_many :created_projects, foreign_key: :creator_id, class_name: 'Project'
has_many :users_star_projects, dependent: :destroy has_many :users_star_projects, dependent: :destroy
has_many :starred_projects, through: :users_star_projects, source: :project has_many :starred_projects, through: :users_star_projects, source: :project
has_many :snippets, dependent: :destroy, foreign_key: :author_id, class_name: "Snippet" has_many :snippets, dependent: :destroy, foreign_key: :author_id
has_many :issues, dependent: :destroy, foreign_key: :author_id has_many :issues, dependent: :destroy, foreign_key: :author_id
has_many :notes, dependent: :destroy, foreign_key: :author_id has_many :notes, dependent: :destroy, foreign_key: :author_id
has_many :merge_requests, dependent: :destroy, foreign_key: :author_id has_many :merge_requests, dependent: :destroy, foreign_key: :author_id
has_many :events, dependent: :destroy, foreign_key: :author_id, class_name: "Event" has_many :events, dependent: :destroy, foreign_key: :author_id
has_many :subscriptions, dependent: :destroy has_many :subscriptions, dependent: :destroy
has_many :recent_events, -> { order "id DESC" }, foreign_key: :author_id, class_name: "Event" has_many :recent_events, -> { order "id DESC" }, foreign_key: :author_id, class_name: "Event"
has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue" has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue"
...@@ -309,7 +309,7 @@ class User < ActiveRecord::Base ...@@ -309,7 +309,7 @@ class User < ActiveRecord::Base
username username
end end
def to_reference(_from_project = nil) def to_reference(_from_project = nil, _target_project = nil)
"#{self.class.reference_prefix}#{username}" "#{self.class.reference_prefix}#{username}"
end end
......
...@@ -7,9 +7,11 @@ module Notes ...@@ -7,9 +7,11 @@ module Notes
if note.award_emoji? if note.award_emoji?
noteable = note.noteable noteable = note.noteable
if noteable.user_can_award?(current_user, note.award_emoji_name)
todo_service.new_award_emoji(noteable, current_user) todo_service.new_award_emoji(noteable, current_user)
return noteable.create_award_emoji(note.award_emoji_name, current_user) return noteable.create_award_emoji(note.award_emoji_name, current_user)
end end
end
# We execute commands (extracted from `params[:note]`) on the noteable # We execute commands (extracted from `params[:note]`) on the noteable
# **before** we save the note because if the note consists of commands # **before** we save the note because if the note consists of commands
......
# The protected branches API still uses the `developers_can_push` and `developers_can_merge`
# flags for backward compatibility, and so performs translation between that format and the
# internal data model (separate access levels). The translation code is non-trivial, and so
# lives in this service.
module ProtectedBranches
class ApiCreateService < BaseService
def execute
push_access_level =
if params.delete(:developers_can_push)
Gitlab::Access::DEVELOPER
else
Gitlab::Access::MASTER
end
merge_access_level =
if params.delete(:developers_can_merge)
Gitlab::Access::DEVELOPER
else
Gitlab::Access::MASTER
end
@params.merge!(push_access_levels_attributes: [{ access_level: push_access_level }],
merge_access_levels_attributes: [{ access_level: merge_access_level }])
service = ProtectedBranches::CreateService.new(@project, @current_user, @params)
service.execute
end
end
end
# The protected branches API still uses the `developers_can_push` and `developers_can_merge`
# flags for backward compatibility, and so performs translation between that format and the
# internal data model (separate access levels). The translation code is non-trivial, and so
# lives in this service.
module ProtectedBranches
class ApiUpdateService < BaseService
def execute(protected_branch)
@developers_can_push = params.delete(:developers_can_push)
@developers_can_merge = params.delete(:developers_can_merge)
@protected_branch = protected_branch
protected_branch.transaction do
delete_redundant_access_levels
case @developers_can_push
when true
params.merge!(push_access_levels_attributes: [{ access_level: Gitlab::Access::DEVELOPER }])
when false
params.merge!(push_access_levels_attributes: [{ access_level: Gitlab::Access::MASTER }])
end
case @developers_can_merge
when true
params.merge!(merge_access_levels_attributes: [{ access_level: Gitlab::Access::DEVELOPER }])
when false
params.merge!(merge_access_levels_attributes: [{ access_level: Gitlab::Access::MASTER }])
end
service = ProtectedBranches::UpdateService.new(@project, @current_user, @params)
service.execute(protected_branch)
end
end
private
def delete_redundant_access_levels
unless @developers_can_merge.nil?
@protected_branch.merge_access_levels.destroy_all
end
unless @developers_can_push.nil?
@protected_branch.push_access_levels.destroy_all
end
end
end
end
...@@ -12,5 +12,5 @@ ...@@ -12,5 +12,5 @@
%label{for: "user_remember_me"} %label{for: "user_remember_me"}
= f.check_box :remember_me = f.check_box :remember_me
%span Remember me %span Remember me
.pull-right .pull-right.forgot-password
= link_to "Forgot your password?", new_password_path(resource_name) = link_to "Forgot your password?", new_password_path(resource_name)
%ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist'} %ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist'}
%li.active{ role: 'presentation' } %li.active{ role: 'presentation' }
%a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab'} Sign in %a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab'} Sign in
- if signin_enabled? && signup_enabled?
%li{ role: 'presentation'} %li{ role: 'presentation'}
%a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab'} Register %a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab'} Register
...@@ -9,12 +9,12 @@ ...@@ -9,12 +9,12 @@
%p %p
Project will be imported as Project will be imported as
%strong %strong
#{@namespace_name}/#{@path} #{@namespace.name}/#{@path}
%p %p
To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here. To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here.
.form-group .form-group
= hidden_field_tag :namespace_id, @namespace_id = hidden_field_tag :namespace_id, @namespace.id
= hidden_field_tag :path, @path = hidden_field_tag :path, @path
= label_tag :file, class: 'control-label' do = label_tag :file, class: 'control-label' do
%span GitLab project export %span GitLab project export
......
...@@ -101,7 +101,7 @@ ...@@ -101,7 +101,7 @@
Git Large File Storage Git Large File Storage
= link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs') = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
- if Gitlab.config.lfs.enabled && current_user.admin? - if Gitlab.config.registry.enabled
.form-group .form-group
.checkbox .checkbox
= f.label :container_registry_enabled do = f.label :container_registry_enabled do
......
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
Most recent commits displayed first Most recent commits displayed first
%ol#commits-list.list-unstyled %ol#commits-list.list-unstyled
= render "projects/commits/commits", project: @merge_request.project, ref: @merge_request.source_branch = render "projects/commits/commits", project: @merge_request.source_project, ref: @merge_request.source_branch
...@@ -12,8 +12,7 @@ constraints(GroupUrlConstrainer.new) do ...@@ -12,8 +12,7 @@ constraints(GroupUrlConstrainer.new) do
end end
end end
scope constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ } do resources :groups, constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ } do
resources :groups, except: [:show] do
member do member do
get :issues get :issues
get :merge_requests get :merge_requests
...@@ -32,6 +31,4 @@ scope constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ } do ...@@ -32,6 +31,4 @@ scope constraints: { id: /[a-zA-Z.0-9_\-]+(?<!\.atom)/ } do
resources :labels, except: [:show], constraints: { id: /\d+/ } resources :labels, except: [:show], constraints: { id: /\d+/ }
end end
end
get 'groups/:id' => 'groups#show', as: :group_canonical
end end
...@@ -61,6 +61,7 @@ executing commands in the following snippet. ...@@ -61,6 +61,7 @@ executing commands in the following snippet.
```bash ```bash
git clone https://github.com/koding/koding.git git clone https://github.com/koding/koding.git
cd koding cd koding
docker-compose -f docker-compose-init.yml run init
docker-compose up docker-compose up
``` ```
......
...@@ -37,7 +37,7 @@ graphs/dashboards. ...@@ -37,7 +37,7 @@ graphs/dashboards.
GitLab provides built-in tools to aid the process of improving performance: GitLab provides built-in tools to aid the process of improving performance:
* [Sherlock](profiling.md#sherlock) * [Sherlock](profiling.md#sherlock)
* [GitLab Performance Monitoring](../monitoring/performance/monitoring.md) * [GitLab Performance Monitoring](../administration/monitoring/performance/monitoring.md)
* [Request Profiling](../administration/monitoring/performance/request_profiling.md) * [Request Profiling](../administration/monitoring/performance/request_profiling.md)
GitLab employees can use GitLab.com's performance monitoring systems located at GitLab employees can use GitLab.com's performance monitoring systems located at
......
This document was moved to [administration/monitoring/performance/gitlab_configuration](../administration/monitoring/performance/gitlab_configuration.md). This document was moved to [administration/monitoring/performance/gitlab_configuration](../../administration/monitoring/performance/gitlab_configuration.md).
This document was moved to [administration/monitoring/performance/influxdb_configuration](../administration/monitoring/performance/influxdb_configuration.md). This document was moved to [administration/monitoring/performance/influxdb_configuration](../../administration/monitoring/performance/influxdb_configuration.md).
This document was moved to [administration/monitoring/performance/influxdb_schema](../administration/monitoring/performance/influxdb_schema.md). This document was moved to [administration/monitoring/performance/influxdb_schema](../../administration/monitoring/performance/influxdb_schema.md).
This document was moved to [administration/monitoring/performance/introduction](../administration/monitoring/performance/introduction.md). This document was moved to [administration/monitoring/performance/introduction](../../administration/monitoring/performance/introduction.md).
...@@ -30,6 +30,10 @@ Use this if you've installed GitLab from source: ...@@ -30,6 +30,10 @@ Use this if you've installed GitLab from source:
``` ```
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
``` ```
If you are running GitLab within a Docker container, you can run the backup from the host:
```
docker -t exec <container name> gitlab-rake gitlab:backup:create
```
You can specify that portions of the application data be skipped using the You can specify that portions of the application data be skipped using the
environment variable `SKIP`. You can skip: environment variable `SKIP`. You can skip:
......
...@@ -254,6 +254,12 @@ test: ...@@ -254,6 +254,12 @@ test:
This will make GitLab CI initialize (fetch) and update (checkout) all your This will make GitLab CI initialize (fetch) and update (checkout) all your
submodules recursively. submodules recursively.
If Git does not use the newly added relative URLs but still uses your old URLs,
you might need to add `git submodule sync --recursive` to your `.gitlab-ci.yml`,
prior to running `git submodule update --init --recursive`. This transfers the
changes from your `.gitmodules` file into the `.git` folder, which is kept by
runners between runs.
In case your environment or your Docker image doesn't have Git installed, In case your environment or your Docker image doesn't have Git installed,
you have to either ask your Administrator or install the missing dependency you have to either ask your Administrator or install the missing dependency
yourself: yourself:
......
...@@ -54,43 +54,25 @@ module API ...@@ -54,43 +54,25 @@ module API
not_found!('Branch') unless @branch not_found!('Branch') unless @branch
protected_branch = user_project.protected_branches.find_by(name: @branch.name) protected_branch = user_project.protected_branches.find_by(name: @branch.name)
developers_can_merge = to_boolean(params[:developers_can_merge])
developers_can_push = to_boolean(params[:developers_can_push])
protected_branch_params = { protected_branch_params = {
name: @branch.name name: @branch.name,
developers_can_push: to_boolean(params[:developers_can_push]),
developers_can_merge: to_boolean(params[:developers_can_merge])
} }
# If `developers_can_merge` is switched off, _all_ `DEVELOPER` service_args = [user_project, current_user, protected_branch_params]
# merge_access_levels need to be deleted.
if developers_can_merge == false
protected_branch.merge_access_levels.where(access_level: Gitlab::Access::DEVELOPER).destroy_all
end
# If `developers_can_push` is switched off, _all_ `DEVELOPER`
# push_access_levels need to be deleted.
if developers_can_push == false
protected_branch.push_access_levels.where(access_level: Gitlab::Access::DEVELOPER).destroy_all
end
protected_branch_params.merge!( protected_branch = if protected_branch
merge_access_levels_attributes: [{ ProtectedBranches::ApiUpdateService.new(*service_args).execute(protected_branch)
access_level: developers_can_merge ? Gitlab::Access::DEVELOPER : Gitlab::Access::MASTER
}],
push_access_levels_attributes: [{
access_level: developers_can_push ? Gitlab::Access::DEVELOPER : Gitlab::Access::MASTER
}]
)
if protected_branch
service = ProtectedBranches::UpdateService.new(user_project, current_user, protected_branch_params)
service.execute(protected_branch)
else else
service = ProtectedBranches::CreateService.new(user_project, current_user, protected_branch_params) ProtectedBranches::ApiCreateService.new(*service_args).execute
service.execute
end end
if protected_branch.valid?
present @branch, with: Entities::RepoBranch, project: user_project present @branch, with: Entities::RepoBranch, project: user_project
else
render_api_error!(protected_branch.errors.full_messages, 422)
end
end end
# Unprotect a single branch # Unprotect a single branch
......
...@@ -3,15 +3,32 @@ module API ...@@ -3,15 +3,32 @@ module API
class Builds < Grape::API class Builds < Grape::API
before { authenticate! } before { authenticate! }
params do
requires :id, type: String, desc: 'The ID of a project'
end
resource :projects do resource :projects do
# Get a project builds helpers do
# params :optional_scope do
# Parameters: optional :scope, types: [String, Array[String]], desc: 'The scope of builds to show',
# id (required) - The ID of a project values: ['pending', 'running', 'failed', 'success', 'canceled'],
# scope (optional) - The scope of builds to show (one or array of: created, pending, running, failed, success, canceled, skipped; coerce_with: ->(scope) {
# if none provided showing all builds) if scope.is_a?(String)
# Example Request: [scope]
# GET /projects/:id/builds elsif scope.is_a?(Hashie::Mash)
scope.values
else
['unknown']
end
}
end
end
desc 'Get a project builds' do
success Entities::Build
end
params do
use :optional_scope
end
get ':id/builds' do get ':id/builds' do
builds = user_project.builds.order('id DESC') builds = user_project.builds.order('id DESC')
builds = filter_builds(builds, params[:scope]) builds = filter_builds(builds, params[:scope])
...@@ -20,15 +37,13 @@ module API ...@@ -20,15 +37,13 @@ module API
user_can_download_artifacts: can?(current_user, :read_build, user_project) user_can_download_artifacts: can?(current_user, :read_build, user_project)
end end
# Get builds for a specific commit of a project desc 'Get builds for a specific commit of a project' do
# success Entities::Build
# Parameters: end
# id (required) - The ID of a project params do
# sha (required) - The SHA id of a commit requires :sha, type: String, desc: 'The SHA id of a commit'
# scope (optional) - The scope of builds to show (one or array of: created, pending, running, failed, success, canceled, skipped; use :optional_scope
# if none provided showing all builds) end
# Example Request:
# GET /projects/:id/repository/commits/:sha/builds
get ':id/repository/commits/:sha/builds' do get ':id/repository/commits/:sha/builds' do
authorize_read_builds! authorize_read_builds!
...@@ -42,13 +57,12 @@ module API ...@@ -42,13 +57,12 @@ module API
user_can_download_artifacts: can?(current_user, :read_build, user_project) user_can_download_artifacts: can?(current_user, :read_build, user_project)
end end
# Get a specific build of a project desc 'Get a specific build of a project' do
# success Entities::Build
# Parameters: end
# id (required) - The ID of a project params do
# build_id (required) - The ID of a build requires :build_id, type: Integer, desc: 'The ID of a build'
# Example Request: end
# GET /projects/:id/builds/:build_id
get ':id/builds/:build_id' do get ':id/builds/:build_id' do
authorize_read_builds! authorize_read_builds!
...@@ -58,13 +72,12 @@ module API ...@@ -58,13 +72,12 @@ module API
user_can_download_artifacts: can?(current_user, :read_build, user_project) user_can_download_artifacts: can?(current_user, :read_build, user_project)
end end
# Download the artifacts file from build desc 'Download the artifacts file from build' do
# detail 'This feature was introduced in GitLab 8.5'
# Parameters: end
# id (required) - The ID of a build params do
# token (required) - The build authorization token requires :build_id, type: Integer, desc: 'The ID of a build'
# Example Request: end
# GET /projects/:id/builds/:build_id/artifacts
get ':id/builds/:build_id/artifacts' do get ':id/builds/:build_id/artifacts' do
authorize_read_builds! authorize_read_builds!
...@@ -73,14 +86,13 @@ module API ...@@ -73,14 +86,13 @@ module API
present_artifacts!(build.artifacts_file) present_artifacts!(build.artifacts_file)
end end
# Download the artifacts file from ref_name and job desc 'Download the artifacts file from build' do
# detail 'This feature was introduced in GitLab 8.10'
# Parameters: end
# id (required) - The ID of a project params do
# ref_name (required) - The ref from repository requires :ref_name, type: String, desc: 'The ref from repository'
# job (required) - The name for the build requires :job, type: String, desc: 'The name for the build'
# Example Request: end
# GET /projects/:id/builds/artifacts/:ref_name/download?job=name
get ':id/builds/artifacts/:ref_name/download', get ':id/builds/artifacts/:ref_name/download',
requirements: { ref_name: /.+/ } do requirements: { ref_name: /.+/ } do
authorize_read_builds! authorize_read_builds!
...@@ -91,17 +103,13 @@ module API ...@@ -91,17 +103,13 @@ module API
present_artifacts!(latest_build.artifacts_file) present_artifacts!(latest_build.artifacts_file)
end end
# Get a trace of a specific build of a project
#
# Parameters:
# id (required) - The ID of a project
# build_id (required) - The ID of a build
# Example Request:
# GET /projects/:id/build/:build_id/trace
#
# TODO: We should use `present_file!` and leave this implementation for backward compatibility (when build trace # TODO: We should use `present_file!` and leave this implementation for backward compatibility (when build trace
# is saved in the DB instead of file). But before that, we need to consider how to replace the value of # is saved in the DB instead of file). But before that, we need to consider how to replace the value of
# `runners_token` with some mask (like `xxxxxx`) when sending trace file directly by workhorse. # `runners_token` with some mask (like `xxxxxx`) when sending trace file directly by workhorse.
desc 'Get a trace of a specific build of a project'
params do
requires :build_id, type: Integer, desc: 'The ID of a build'
end
get ':id/builds/:build_id/trace' do get ':id/builds/:build_id/trace' do
authorize_read_builds! authorize_read_builds!
...@@ -115,13 +123,12 @@ module API ...@@ -115,13 +123,12 @@ module API
body trace body trace
end end
# Cancel a specific build of a project desc 'Cancel a specific build of a project' do
# success Entities::Build
# parameters: end
# id (required) - the id of a project params do
# build_id (required) - the id of a build requires :build_id, type: Integer, desc: 'The ID of a build'
# example request: end
# post /projects/:id/build/:build_id/cancel
post ':id/builds/:build_id/cancel' do post ':id/builds/:build_id/cancel' do
authorize_update_builds! authorize_update_builds!
...@@ -133,13 +140,12 @@ module API ...@@ -133,13 +140,12 @@ module API
user_can_download_artifacts: can?(current_user, :read_build, user_project) user_can_download_artifacts: can?(current_user, :read_build, user_project)
end end
# Retry a specific build of a project desc 'Retry a specific build of a project' do
# success Entities::Build
# parameters: end
# id (required) - the id of a project params do
# build_id (required) - the id of a build requires :build_id, type: Integer, desc: 'The ID of a build'
# example request: end
# post /projects/:id/build/:build_id/retry
post ':id/builds/:build_id/retry' do post ':id/builds/:build_id/retry' do
authorize_update_builds! authorize_update_builds!
...@@ -152,13 +158,12 @@ module API ...@@ -152,13 +158,12 @@ module API
user_can_download_artifacts: can?(current_user, :read_build, user_project) user_can_download_artifacts: can?(current_user, :read_build, user_project)
end end
# Erase build (remove artifacts and build trace) desc 'Erase build (remove artifacts and build trace)' do
# success Entities::Build
# Parameters: end
# id (required) - the id of a project params do
# build_id (required) - the id of a build requires :build_id, type: Integer, desc: 'The ID of a build'
# example Request: end
# post /projects/:id/build/:build_id/erase
post ':id/builds/:build_id/erase' do post ':id/builds/:build_id/erase' do
authorize_update_builds! authorize_update_builds!
...@@ -170,13 +175,12 @@ module API ...@@ -170,13 +175,12 @@ module API
user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project) user_can_download_artifacts: can?(current_user, :download_build_artifacts, user_project)
end end
# Keep the artifacts to prevent them from being deleted desc 'Keep the artifacts to prevent them from being deleted' do
# success Entities::Build
# Parameters: end
# id (required) - the id of a project params do
# build_id (required) - The ID of a build requires :build_id, type: Integer, desc: 'The ID of a build'
# Example Request: end
# POST /projects/:id/builds/:build_id/artifacts/keep
post ':id/builds/:build_id/artifacts/keep' do post ':id/builds/:build_id/artifacts/keep' do
authorize_update_builds! authorize_update_builds!
...@@ -235,14 +239,6 @@ module API ...@@ -235,14 +239,6 @@ module API
return builds if scope.nil? || scope.empty? return builds if scope.nil? || scope.empty?
available_statuses = ::CommitStatus::AVAILABLE_STATUSES available_statuses = ::CommitStatus::AVAILABLE_STATUSES
scope =
if scope.is_a?(String)
[scope]
elsif scope.is_a?(Hashie::Mash)
scope.values
else
['unknown']
end
unknown = scope - available_statuses unknown = scope - available_statuses
render_api_error!('Scope contains invalid value(s)', 400) unless unknown.empty? render_api_error!('Scope contains invalid value(s)', 400) unless unknown.empty?
......
...@@ -19,6 +19,7 @@ module API ...@@ -19,6 +19,7 @@ module API
optional :until, type: String, desc: 'Only commits before or in this date will be returned' optional :until, type: String, desc: 'Only commits before or in this date will be returned'
optional :page, type: Integer, default: 0, desc: 'The page for pagination' optional :page, type: Integer, default: 0, desc: 'The page for pagination'
optional :per_page, type: Integer, default: 20, desc: 'The number of results per page' optional :per_page, type: Integer, default: 20, desc: 'The number of results per page'
optional :path, type: String, desc: 'The file path'
end end
get ":id/repository/commits" do get ":id/repository/commits" do
# TODO remove the next line for 9.0, use DateTime type in the params block # TODO remove the next line for 9.0, use DateTime type in the params block
...@@ -28,6 +29,7 @@ module API ...@@ -28,6 +29,7 @@ module API
offset = params[:page] * params[:per_page] offset = params[:page] * params[:per_page]
commits = user_project.repository.commits(ref, commits = user_project.repository.commits(ref,
path: params[:path],
limit: params[:per_page], limit: params[:per_page],
offset: offset, offset: offset,
after: params[:since], after: params[:since],
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment