Commit ebe14437 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'master' into refactor/ci-config-add-global-entry

* master: (59 commits)
  Improved SVG sanitizer specs to include smoke tests for clean.
  Refactored SVG sanitizer
  Added SVG sanitizer fix to the changelog
  Refactor SVG sanitizer and prevent `xlink:href` to refer to external resources
  Fix SVG whitelisting to allow namespaced attributes
  Fix Error 500 when using closes_issues API with an external issue tracker
  Center layout navigation and remove icons
  Fix preferences_spec test
  Add back sidebar counters and username
  Only create the backup directory if it is local
  Fix safari logo loading animation safari bug
  Revert side nav to full width; remove border under nav; remove tooltips on nav links; stop page content shifting with side nav; put project nav in container
  Update media queries
  Fix profile test
  Fix logo at all screen widths, update sidebar text
  Move tanuki icon to center of nav bar; keep nav closed by default; remove collapsed nav cookie
  Remove unused MergeRequest#gitlab_merge_status method
  Add CHANGELOG item for labels/milestones navigation change
  Render issues link on issues subnav unless you visit merge request controller
  Render only issues/mr in subnav depends on context
  ...
parents 11c0d022 06a99cf7
We’re closing our issue tracker on GitHub so we can focus on the GitLab.com project and respond to issues more quickly.
We encourage you to open an issue on the [GitLab.com issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues). You can log into GitLab.com using your GitHub account.
Thank you for taking the time to contribute back to GitLab!
Please open a merge request [on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests), we look forward to reviewing your contribution! You can log into GitLab.com using your GitHub account.
...@@ -13,7 +13,8 @@ AllCops: ...@@ -13,7 +13,8 @@ AllCops:
# Exclude some GitLab files # Exclude some GitLab files
Exclude: Exclude:
- 'vendor/**/*' - 'vendor/**/*'
- 'db/**/*' - 'db/*'
- 'db/fixtures/**/*'
- 'tmp/**/*' - 'tmp/**/*'
- 'bin/**/*' - 'bin/**/*'
- 'lib/backup/**/*' - 'lib/backup/**/*'
......
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.9.0 (unreleased) v 8.9.0 (unreleased)
- Fix Error 500 when using closes_issues API with an external issue tracker
- Bulk assign/unassign labels to issues. - Bulk assign/unassign labels to issues.
- Ability to prioritize labels !4009 / !3205 (Thijs Wouters) - Ability to prioritize labels !4009 / !3205 (Thijs Wouters)
- Fix endless redirections when accessing user OAuth applications when they are disabled - Fix endless redirections when accessing user OAuth applications when they are disabled
- Allow enabling wiki page events from Webhook management UI - Allow enabling wiki page events from Webhook management UI
- Bump rouge to 1.11.0 - Bump rouge to 1.11.0
- Fix issue with arrow keys not working in search autocomplete dropdown
- Make EmailsOnPushWorker use Sidekiq mailers queue - Make EmailsOnPushWorker use Sidekiq mailers queue
- Fix wiki page events' webhook to point to the wiki repository - Fix wiki page events' webhook to point to the wiki repository
- Fix issue todo not remove when leave project !4150 (Long Nguyen) - Fix issue todo not remove when leave project !4150 (Long Nguyen)
- Allow customisable text on the 'nearly there' page after a user signs up - Allow customisable text on the 'nearly there' page after a user signs up
- Bump recaptcha gem to 3.0.0 to remove deprecated stoken support - Bump recaptcha gem to 3.0.0 to remove deprecated stoken support
- Fix SVG sanitizer to allow more elements
- Allow forking projects with restricted visibility level - Allow forking projects with restricted visibility level
- Added descriptions to notification settings dropdown - Added descriptions to notification settings dropdown
- Improve note validation to prevent errors when creating invalid note via API - Improve note validation to prevent errors when creating invalid note via API
...@@ -31,6 +34,7 @@ v 8.9.0 (unreleased) ...@@ -31,6 +34,7 @@ v 8.9.0 (unreleased)
- Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database - Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database
- Changed the Slack build message to use the singular duration if necessary (Aran Koning) - Changed the Slack build message to use the singular duration if necessary (Aran Koning)
- Links from a wiki page to other wiki pages should be rewritten as expected - Links from a wiki page to other wiki pages should be rewritten as expected
- Add option to project to only allow merge requests to be merged if the build succeeds (Rui Santos)
- Fix issues filter when ordering by milestone - Fix issues filter when ordering by milestone
- Todos will display target state if issuable target is 'Closed' or 'Merged' - Todos will display target state if issuable target is 'Closed' or 'Merged'
- Fix bug when sorting issues by milestone due date and filtering by two or more labels - Fix bug when sorting issues by milestone due date and filtering by two or more labels
...@@ -54,6 +58,7 @@ v 8.9.0 (unreleased) ...@@ -54,6 +58,7 @@ v 8.9.0 (unreleased)
- Remove duplicated notification settings - Remove duplicated notification settings
- Put project Files and Commits tabs under Code tab - Put project Files and Commits tabs under Code tab
- Replace Colorize with Rainbow for coloring console output in Rake tasks. - Replace Colorize with Rainbow for coloring console output in Rake tasks.
- Add workhorse controller and API helpers
- An indicator is now displayed at the top of the comment field for confidential issues. - An indicator is now displayed at the top of the comment field for confidential issues.
- RepositoryCheck::SingleRepositoryWorker public and private methods are now instrumented - RepositoryCheck::SingleRepositoryWorker public and private methods are now instrumented
- Improve issuables APIs performance when accessing notes !4471 - Improve issuables APIs performance when accessing notes !4471
...@@ -61,15 +66,17 @@ v 8.9.0 (unreleased) ...@@ -61,15 +66,17 @@ v 8.9.0 (unreleased)
- Markdown editor now correctly resets the input value on edit cancellation !4175 - Markdown editor now correctly resets the input value on edit cancellation !4175
- Toggling a task list item in a issue/mr description does not creates a Todo for mentions - Toggling a task list item in a issue/mr description does not creates a Todo for mentions
- Improved UX of date pickers on issue & milestone forms - Improved UX of date pickers on issue & milestone forms
- Cache on the database if a project has an active external issue tracker.
- Put project Labels and Milestones pages links under Issues and Merge Requests tabs as subnav
v 8.8.5 (unreleased) v 8.8.5 (unreleased)
- Ensure branch cleanup regardless of whether the GitHub import process succeeds - Ensure branch cleanup regardless of whether the GitHub import process succeeds
- Fix issue with arrow keys not working in search autocomplete dropdown
- Fix todos page throwing errors when you have a project pending deletion - Fix todos page throwing errors when you have a project pending deletion
- Reduce number of SQL queries when rendering user references - Reduce number of SQL queries when rendering user references
- Import GitHub repositories respecting the API rate limit - Import GitHub repositories respecting the API rate limit
- Fix importer for GitHub comments on diff - Fix importer for GitHub comments on diff
- Disable Webhooks before proceeding with the GitHub import - Disable Webhooks before proceeding with the GitHub import
- Fix incremental trace upload API when using multi-byte UTF-8 chars in trace
v 8.8.4 v 8.8.4
- Fix LDAP-based login for users with 2FA enabled. !4493 - Fix LDAP-based login for users with 2FA enabled. !4493
......
...@@ -162,19 +162,6 @@ $ -> ...@@ -162,19 +162,6 @@ $ ->
$el.data('placement') || 'bottom' $el.data('placement') || 'bottom'
) )
$('.header-logo .home').tooltip(
placement: (_, el) ->
$el = $(el)
if $('.page-with-sidebar').hasClass('page-sidebar-collapsed') then 'right' else 'bottom'
container: 'body'
)
$('.page-with-sidebar').tooltip(
selector: '.sidebar-collapsed .nav-sidebar a, .sidebar-collapsed a.sidebar-user'
placement: 'right'
container: 'body'
)
# Form submitter # Form submitter
$('.trigger-submit').on 'change', -> $('.trigger-submit').on 'change', ->
$(@).parents('form').submit() $(@).parents('form').submit()
...@@ -207,6 +194,7 @@ $ -> ...@@ -207,6 +194,7 @@ $ ->
$('.navbar-toggle').on 'click', -> $('.navbar-toggle').on 'click', ->
$('.header-content .title').toggle() $('.header-content .title').toggle()
$('.header-content .header-logo').toggle()
$('.header-content .navbar-collapse').toggle() $('.header-content .navbar-collapse').toggle()
$('.navbar-toggle').toggleClass('active') $('.navbar-toggle').toggleClass('active')
$('.navbar-toggle i').toggleClass("fa-angle-right fa-angle-left") $('.navbar-toggle i').toggleClass("fa-angle-right fa-angle-left")
...@@ -241,7 +229,6 @@ $ -> ...@@ -241,7 +229,6 @@ $ ->
$this.attr 'value', $this.val() $this.attr 'value', $this.val()
$sidebarGutterToggle = $('.js-sidebar-toggle') $sidebarGutterToggle = $('.js-sidebar-toggle')
$navIconToggle = $('.toggle-nav-collapse')
$(document) $(document)
.off 'breakpoint:change' .off 'breakpoint:change'
...@@ -251,10 +238,6 @@ $ -> ...@@ -251,10 +238,6 @@ $ ->
if $gutterIcon.hasClass('fa-angle-double-right') if $gutterIcon.hasClass('fa-angle-double-right')
$sidebarGutterToggle.trigger('click') $sidebarGutterToggle.trigger('click')
$navIcon = $navIconToggle.find('.fa')
if $navIcon.hasClass('fa-angle-left')
$navIconToggle.trigger('click')
fitSidebarForSize = -> fitSidebarForSize = ->
oldBootstrapBreakpoint = bootstrapBreakpoint oldBootstrapBreakpoint = bootstrapBreakpoint
bootstrapBreakpoint = bp.getBreakpointSize() bootstrapBreakpoint = bp.getBreakpointSize()
...@@ -267,8 +250,8 @@ $ -> ...@@ -267,8 +250,8 @@ $ ->
$(document).trigger('breakpoint:change', [bootstrapBreakpoint]) $(document).trigger('breakpoint:change', [bootstrapBreakpoint])
$(window) $(window)
.off "resize" .off "resize.app"
.on "resize", (e) -> .on "resize.app", (e) ->
fitSidebarForSize() fitSidebarForSize()
gl.awardsHandler = new AwardsHandler() gl.awardsHandler = new AwardsHandler()
......
class CiBuild class @CiBuild
@interval: null @interval: null
@state: null @state: null
constructor: (build_url, build_status, build_state) -> constructor: (@build_url, @build_status, @state) ->
clearInterval(CiBuild.interval) clearInterval(CiBuild.interval)
@state = build_state # Init breakpoint checker
@bp = Breakpoints.get()
@hideSidebar()
$('.js-build-sidebar').niceScroll()
$(document)
.off 'click', '.js-sidebar-build-toggle'
.on 'click', '.js-sidebar-build-toggle', @toggleSidebar
$(window)
.off 'resize.build'
.on 'resize.build', @hideSidebar
if $('#build-trace').length
@getInitialBuildTrace()
@initScrollButtonAffix() @initScrollButtonAffix()
if build_status == "running" || build_status == "pending" if @build_status is "running" or @build_status is "pending"
# #
# Bind autoscroll button to follow build output # Bind autoscroll button to follow build output
# #
$("#autoscroll-button").bind "click", -> $('#autoscroll-button').on 'click', ->
state = $(this).data("state") state = $(this).data("state")
if "enabled" is state if "enabled" is state
$(this).data "state", "disabled" $(this).data "state", "disabled"
...@@ -27,25 +39,36 @@ class CiBuild ...@@ -27,25 +39,36 @@ class CiBuild
# Only valid for runnig build when output changes during time # Only valid for runnig build when output changes during time
# #
CiBuild.interval = setInterval => CiBuild.interval = setInterval =>
if window.location.href.split("#").first() is build_url if window.location.href.split("#").first() is @build_url
last_state = @state @getBuildTrace()
, 4000
getInitialBuildTrace: ->
$.ajax $.ajax
url: build_url + "/trace.json?state=" + encodeURIComponent(@state) url: @build_url
dataType: 'json'
success: (build_data) ->
$('.js-build-output').html build_data.trace_html
if build_data.status is 'success' or build_data.status is 'failed'
$('.js-build-refresh').remove()
getBuildTrace: ->
$.ajax
url: "#{@build_url}/trace.json?state=#{encodeURIComponent(@state)}"
dataType: "json" dataType: "json"
success: (log) => success: (log) =>
return unless last_state is @state if log.state
if log.state and log.status is "running"
@state = log.state @state = log.state
if log.status is "running"
if log.append if log.append
$('.fa-refresh').before log.html $('.js-build-output').append log.html
else else
$('#build-trace code').html log.html $('.js-build-output').html log.html
$('#build-trace code').append '<i class="fa fa-refresh fa-spin"/>'
@checkAutoscroll() @checkAutoscroll()
else if log.status isnt build_status else if log.status isnt @build_status
Turbolinks.visit build_url Turbolinks.visit @build_url
, 4000
checkAutoscroll: -> checkAutoscroll: ->
$("html,body").scrollTop $("#build-trace").height() if "enabled" is $("#autoscroll-button").data("state") $("html,body").scrollTop $("#build-trace").height() if "enabled" is $("#autoscroll-button").data("state")
...@@ -61,4 +84,22 @@ class CiBuild ...@@ -61,4 +84,22 @@ class CiBuild
$body.outerHeight() - ($buildTrace.outerHeight() + $buildTrace.offset().top) $body.outerHeight() - ($buildTrace.outerHeight() + $buildTrace.offset().top)
) )
@CiBuild = CiBuild shouldHideSidebar: ->
bootstrapBreakpoint = @bp.getBreakpointSize()
bootstrapBreakpoint is 'xs' or bootstrapBreakpoint is 'sm'
toggleSidebar: =>
if @shouldHideSidebar()
$('.js-build-sidebar')
.toggleClass 'right-sidebar-expanded right-sidebar-collapsed'
hideSidebar: =>
if @shouldHideSidebar()
$('.js-build-sidebar')
.removeClass 'right-sidebar-expanded'
.addClass 'right-sidebar-collapsed'
else
$('.js-build-sidebar')
.removeClass 'right-sidebar-collapsed'
.addClass 'right-sidebar-expanded'
...@@ -95,8 +95,11 @@ class @LabelsSelect ...@@ -95,8 +95,11 @@ class @LabelsSelect
$newLabelCreateButton.enable() $newLabelCreateButton.enable()
if label.message? if label.message?
errors = _.map label.message, (value, key) ->
"#{key} #{value[0]}"
$newLabelError $newLabelError
.text label.message .html errors.join("<br/>")
.show() .show()
else else
$('.dropdown-menu-back', $dropdown.parent()).trigger 'click' $('.dropdown-menu-back', $dropdown.parent()).trigger 'click'
...@@ -254,7 +257,7 @@ class @LabelsSelect ...@@ -254,7 +257,7 @@ class @LabelsSelect
search: search:
fields: ['title'] fields: ['title']
selectable: true selectable: true
filterable: true
toggleLabel: (selected, el) -> toggleLabel: (selected, el) ->
selected_labels = $('.js-label-select').siblings('.dropdown-menu-labels').find('.is-active') selected_labels = $('.js-label-select').siblings('.dropdown-menu-labels').find('.is-active')
......
...@@ -47,4 +47,4 @@ $ -> ...@@ -47,4 +47,4 @@ $ ->
# Make logo clickable as part of a workaround for Safari visited # Make logo clickable as part of a workaround for Safari visited
# link behaviour (See !2690). # link behaviour (See !2690).
$('#logo').on 'click', -> $('#logo').on 'click', ->
$('#js-shortcuts-home').get(0).click() Turbolinks.visit('/')
...@@ -7,12 +7,17 @@ class @ProjectNew ...@@ -7,12 +7,17 @@ class @ProjectNew
@toggleSettingsOnclick() @toggleSettingsOnclick()
toggleSettings: -> toggleSettings: =>
checked = $("#project_builds_enabled").prop("checked") @_showOrHide('#project_builds_enabled', '.builds-feature')
if checked @_showOrHide('#project_merge_requests_enabled', '.merge-requests-feature')
$('.builds-feature').show()
else
$('.builds-feature').hide()
toggleSettingsOnclick: -> toggleSettingsOnclick: ->
$("#project_builds_enabled").on 'click', @toggleSettings $('#project_builds_enabled, #project_merge_requests_enabled').on 'click', @toggleSettings
_showOrHide: (checkElement, container) ->
$container = $(container)
if $(checkElement).prop('checked')
$container.show()
else
$container.hide()
...@@ -4,8 +4,6 @@ expanded = 'page-sidebar-expanded' ...@@ -4,8 +4,6 @@ expanded = 'page-sidebar-expanded'
toggleSidebar = -> toggleSidebar = ->
$('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}") $('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}")
$('header').toggleClass("header-collapsed header-expanded") $('header').toggleClass("header-collapsed header-expanded")
$('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
$.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
setTimeout ( -> setTimeout ( ->
niceScrollBars = $('.nicescroll').niceScroll(); niceScrollBars = $('.nicescroll').niceScroll();
...@@ -17,10 +15,3 @@ $(document).on("click", '.toggle-nav-collapse, .side-nav-toggle', (e) -> ...@@ -17,10 +15,3 @@ $(document).on("click", '.toggle-nav-collapse, .side-nav-toggle', (e) ->
toggleSidebar() toggleSidebar()
) )
$ ->
size = bp.getBreakpointSize()
if size is "xs" or size is "sm"
if $('.page-with-sidebar').hasClass(expanded)
toggleSidebar()
...@@ -95,7 +95,7 @@ class @UsersSelect ...@@ -95,7 +95,7 @@ class @UsersSelect
data: (term, callback) => data: (term, callback) =>
isAuthorFilter = $('.js-author-search') isAuthorFilter = $('.js-author-search')
@users term, term is '' and isAuthorFilter, (users) => @users term, (users) =>
if term.length is 0 if term.length is 0
showDivider = 0 showDivider = 0
...@@ -221,7 +221,7 @@ class @UsersSelect ...@@ -221,7 +221,7 @@ class @UsersSelect
multiple: $(select).hasClass('multiselect') multiple: $(select).hasClass('multiselect')
minimumInputLength: 0 minimumInputLength: 0
query: (query) => query: (query) =>
@users query.term, @projectId?, (users) => @users query.term, (users) =>
data = { results: users } data = { results: users }
if query.term.length == 0 if query.term.length == 0
...@@ -304,7 +304,7 @@ class @UsersSelect ...@@ -304,7 +304,7 @@ class @UsersSelect
# Return users list. Filtered by query # Return users list. Filtered by query
# Only active users retrieved # Only active users retrieved
users: (query, fromProject, callback) => users: (query, callback) =>
url = @buildUrl(@usersPath) url = @buildUrl(@usersPath)
$.ajax( $.ajax(
...@@ -313,7 +313,7 @@ class @UsersSelect ...@@ -313,7 +313,7 @@ class @UsersSelect
search: query search: query
per_page: 20 per_page: 20
active: true active: true
project_id: @projectId if fromProject project_id: @projectId
group_id: @groupId group_id: @groupId
current_user: @showCurrentUser current_user: @showCurrentUser
author_id: @authorId author_id: @authorId
......
...@@ -8,32 +8,14 @@ ...@@ -8,32 +8,14 @@
*/ */
@mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) { @mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) {
.page-with-sidebar { .page-with-sidebar {
.header-logo {
background: $color-darker;
a { .collapse-nav a {
color: $color-light;
h3 {
color: $color-light; color: $color-light;
} background: $color;
}
&:hover { &:hover {
background-color: $color-dark;
a {
color: $white-light; color: $white-light;
h3 {
color: $white-light;
}
}
}
} }
.collapse-nav a {
color: $white-light;
background: $color;
} }
.sidebar-wrapper { .sidebar-wrapper {
......
...@@ -109,10 +109,8 @@ header { ...@@ -109,10 +109,8 @@ header {
position: relative; position: relative;
height: $header-height; height: $header-height;
padding-right: 40px; padding-right: 40px;
padding-left: 30px;
@media (max-width: $screen-xs-min) { transition-duration: .3s;
padding-left: 40px;
}
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
padding-right: 0; padding-right: 0;
...@@ -122,9 +120,29 @@ header { ...@@ -122,9 +120,29 @@ header {
margin-top: -5px; margin-top: -5px;
} }
.header-logo {
position: absolute;
left: 50%;
margin-left: -18px;
top: 7px;
transition-duration: .3s;
z-index: 999;
&:hover {
cursor: pointer;
}
@media (max-width: $screen-xs-max) {
right: 25px;
left: auto;
}
}
.title { .title {
margin: 0; margin: 0;
font-size: 19px; font-size: 19px;
max-width: 400px;
display: inline-block;
line-height: $header-height; line-height: $header-height;
font-weight: normal; font-weight: normal;
color: $gl-text-color; color: $gl-text-color;
...@@ -133,6 +151,10 @@ header { ...@@ -133,6 +151,10 @@ header {
vertical-align: top; vertical-align: top;
white-space: nowrap; white-space: nowrap;
@media (max-width: $screen-sm-max) {
max-width: 190px;
}
a { a {
color: $gl-text-color; color: $gl-text-color;
&:hover { &:hover {
...@@ -160,6 +182,10 @@ header { ...@@ -160,6 +182,10 @@ header {
.navbar-collapse { .navbar-collapse {
float: right; float: right;
border-top: none; border-top: none;
@media (max-width: $screen-xs-max) {
float: none;
}
} }
} }
...@@ -176,17 +202,20 @@ header { ...@@ -176,17 +202,20 @@ header {
margin-left: 0; margin-left: 0;
.header-content { .header-content {
@media (min-width: $screen-sm-max) {
padding-left: 30px; padding-left: 30px;
transition-duration: .3s; transition-duration: .3s;
} }
}
} }
.header-expanded { .tanuki-shape {
margin-left: 0; transition: all 0.8s;
.header-content { &:hover, &.highlight {
padding-left: $sidebar_width; fill: rgb(255, 255, 255);
transition-duration: .3s; transition: all 0.1s;
} }
} }
......
@mixin fade($gradient-direction, $rgba, $gradient-color) { @mixin fade($gradient-direction, $rgba, $gradient-color) {
visibility: visible; visibility: visible;
opacity: 1; opacity: 1;
z-index: 2;
position: absolute; position: absolute;
bottom: 12px; bottom: 12px;
width: 43px; width: 43px;
...@@ -68,6 +69,7 @@ ...@@ -68,6 +69,7 @@
} }
&.sub-nav { &.sub-nav {
text-align: center;
background-color: $background-color; background-color: $background-color;
.container-fluid { .container-fluid {
...@@ -171,7 +173,6 @@ ...@@ -171,7 +173,6 @@
> form { > form {
display: inline-block; display: inline-block;
margin-top: -1px; margin-top: -1px;
margin-bottom: 12px;
} }
.icon-label { .icon-label {
...@@ -250,6 +251,7 @@ ...@@ -250,6 +251,7 @@
background: $background-color; background: $background-color;
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
transition-duration: .3s; transition-duration: .3s;
text-align: center;
.container-fluid { .container-fluid {
position: relative; position: relative;
...@@ -352,7 +354,7 @@ ...@@ -352,7 +354,7 @@
.fade-right { .fade-right {
@media (min-width: $screen-xs-max) { @media (min-width: $screen-xs-max) {
right: 67px; right: 68px;
} }
@media (max-width: $screen-xs-min) { @media (max-width: $screen-xs-min) {
right: 0; right: 0;
......
...@@ -35,24 +35,11 @@ ...@@ -35,24 +35,11 @@
} }
.sidebar-wrapper { .sidebar-wrapper {
.header-logo {
height: $header-height;
padding: 8px 26px;
width: $sidebar_width;
position: fixed;
z-index: 999;
overflow: hidden;
transition-duration: .3s;
&:hover {
background-color: #eee;
}
}
.sidebar-user { .sidebar-user {
padding: 15px 22px; padding: 15px 22px;
position: fixed; position: fixed;
bottom: 40px; bottom: 0;
width: $sidebar_width; width: $sidebar_width;
overflow: hidden; overflow: hidden;
transition-duration: .3s; transition-duration: .3s;
...@@ -97,10 +84,10 @@ ...@@ -97,10 +84,10 @@
} }
a { a {
text-align: center; width: $sidebar_width;
padding: 8px; padding: 7px 15px 7px 23px;
font-size: $gl-font-size; font-size: $gl-font-size;
color: $gray; line-height: 24px;
display: block; display: block;
text-decoration: none; text-decoration: none;
font-weight: normal; font-weight: normal;
...@@ -118,10 +105,9 @@ ...@@ -118,10 +105,9 @@
font-size: 16px; font-size: 16px;
} }
.nav-link-text { i,
margin-top: 3px; svg {
font-size: 13px; margin-right: 13px;
line-height: 18px;
} }
&.back-link i { &.back-link i {
...@@ -129,6 +115,12 @@ ...@@ -129,6 +115,12 @@
} }
} }
} }
.count {
float: right;
padding: 0 8px;
@include border-radius(6px);
}
} }
.sidebar-subnav { .sidebar-subnav {
...@@ -143,11 +135,12 @@ ...@@ -143,11 +135,12 @@
.collapse-nav a { .collapse-nav a {
width: $sidebar_width; width: $sidebar_width;
position: fixed; position: fixed;
bottom: 0; top: 0;
left: 0; left: 0;
font-size: 13px; padding: 5px 0;
font-size: 18px;
background: transparent; background: transparent;
height: 40px; height: 50px;
text-align: center; text-align: center;
line-height: 40px; line-height: 40px;
transition-duration: .3s; transition-duration: .3s;
...@@ -170,25 +163,8 @@ ...@@ -170,25 +163,8 @@
.sidebar-wrapper { .sidebar-wrapper {
width: 0; width: 0;
.header-logo {
width: 0;
padding: 8px 0;
a {
padding-left: ($sidebar_collapsed_width - 36) / 2;
.gitlab-text-container {
display: none;
}
}
}
#logo {
display: none;
}
.nav-sidebar { .nav-sidebar {
width: $sidebar_collapsed_width; width: 0;
li { li {
width: auto; width: auto;
...@@ -203,6 +179,10 @@ ...@@ -203,6 +179,10 @@
.collapse-nav a { .collapse-nav a {
width: 0; width: 0;
i {
display: none;
}
} }
.sidebar-user { .sidebar-user {
...@@ -218,9 +198,8 @@ ...@@ -218,9 +198,8 @@
} }
.page-sidebar-expanded { .page-sidebar-expanded {
padding-left: $sidebar_width;
@media (max-width: $screen-xs-min) { @media (max-width: $screen-sm-max) {
padding-left: 0; padding-left: 0;
} }
...@@ -241,20 +220,6 @@ ...@@ -241,20 +220,6 @@
} }
} }
} }
.layout-nav {
@media (max-width: $screen-xs-min) {
padding-right: 0;
}
@media (min-width: $screen-xs-min) and (max-width: $screen-md-min) {
padding-right: 90px;
}
@media (min-width: $screen-md-min) {
padding-right: $sidebar_width;
}
}
} }
.right-sidebar-collapsed { .right-sidebar-collapsed {
...@@ -273,8 +238,10 @@ ...@@ -273,8 +238,10 @@
padding-right: 0; padding-right: 0;
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) { @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
&:not(.build-sidebar) {
padding-right: $sidebar_collapsed_width; padding-right: $sidebar_collapsed_width;
} }
}
@media (min-width: $screen-md-min) { @media (min-width: $screen-md-min) {
padding-right: $gutter_width; padding-right: $gutter_width;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Layout * Layout
*/ */
$sidebar_collapsed_width: 62px; $sidebar_collapsed_width: 62px;
$sidebar_width: 90px; $sidebar_width: 220px;
$gutter_collapsed_width: 62px; $gutter_collapsed_width: 62px;
$gutter_width: 290px; $gutter_width: 290px;
$gutter_inner_width: 258px; $gutter_inner_width: 258px;
...@@ -260,3 +260,6 @@ $calendar-header-color: #b8b8b8; ...@@ -260,3 +260,6 @@ $calendar-header-color: #b8b8b8;
$calendar-hover-bg: #ecf3fe; $calendar-hover-bg: #ecf3fe;
$calendar-border-color: rgba(#000, .1); $calendar-border-color: rgba(#000, .1);
$calendar-unselectable-bg: #faf9f9; $calendar-unselectable-bg: #faf9f9;
$ci-output-bg: #1d1f21;
$ci-text-color: #c5c8c6;
...@@ -101,13 +101,21 @@ ...@@ -101,13 +101,21 @@
line-height: 20px; line-height: 20px;
outline: 0; outline: 0;
&:hover,
&.active, &.active,
&:active { &:active {
background-color: $white-dark; background-color: $row-hover;
border-color: $row-hover-border;
box-shadow: none; box-shadow: none;
outline: 0; outline: 0;
} }
&.btn {
&:focus {
outline: 0;
}
}
&.is-loading { &.is-loading {
.award-control-icon-normal, .award-control-icon-normal,
.emoji-icon { .emoji-icon {
......
...@@ -53,37 +53,92 @@ ...@@ -53,37 +53,92 @@
left: 70px; left: 70px;
} }
} }
}
.build-widget { .build-header {
padding: 10px; position: relative;
background: $background-color; padding-right: 40px;
margin-bottom: 20px;
border-radius: 4px;
.title { @media (min-width: $screen-sm-min) {
margin-top: 0; padding-right: 0;
color: #666;
line-height: 1.5;
} }
.attr-name {
color: #777; a {
color: $gl-gray;
&:hover {
color: $gl-link-color;
text-decoration: none;
} }
} }
.alert-disabled { code {
background: $background-color; color: $code-color;
a {
color: #3084bb !important;
} }
.avatar {
float: none;
margin-right: 2px;
margin-left: 2px;
} }
} }
table.builds { table.builds {
.build-link { .build-link {
a { a {
color: $gl-dark-link-color; color: $gl-dark-link-color;
} }
} }
} }
.build-trace {
background: $ci-output-bg;
color: $ci-text-color;
white-space: pre;
overflow-x: auto;
font-size: 12px;
.fa-refresh {
font-size: 24px;
}
.bash {
display: block;
}
}
.right-sidebar.build-sidebar {
padding-top: $gl-padding;
padding-bottom: $gl-padding;
&.right-sidebar-collapsed {
display: none;
}
.block {
width: 100%;
}
.build-sidebar-header {
padding-top: 0;
.gutter-toggle {
margin-top: 0;
}
}
}
.build-detail-row {
margin-bottom: 5px;
}
.build-light-text {
color: $gl-placeholder-color;
}
.build-gutter-toggle {
position: absolute;
top: 50%;
right: 0;
margin-top: -17px;
}
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
} }
} }
.issuable-sidebar { .right-sidebar {
a { a {
color: inherit; color: inherit;
} }
...@@ -74,6 +74,10 @@ ...@@ -74,6 +74,10 @@
} }
} }
.block-first {
padding-top: 0;
}
.title { .title {
color: $gl-text-color; color: $gl-text-color;
margin-bottom: 10px; margin-bottom: 10px;
......
...@@ -11,18 +11,15 @@ ...@@ -11,18 +11,15 @@
$magenta: #cd00cd; $magenta: #cd00cd;
$cyan: #00cdcd; $cyan: #00cdcd;
$white: #e5e5e5; $white: #e5e5e5;
$l-black: #7f7f7f; $l-black: #373b41;
$l-red: #f00; $l-red: #c66;
$l-green: #0f0; $l-green: #b5bd68;
$l-yellow: #ff0; $l-yellow: #f0c674;
$l-blue: #5c5cff; $l-blue: #81a2be;
$l-magenta: #f0f; $l-magenta: #b294bb;
$l-cyan: #0ff; $l-cyan: #8abeb7;
$l-white: #fff; $l-white: $ci-text-color;
.term-bold {
font-weight: bold;
}
.term-italic { .term-italic {
font-style: italic; font-style: italic;
} }
......
...@@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base ...@@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base
include Gitlab::GonHelper include Gitlab::GonHelper
include GitlabRoutingHelper include GitlabRoutingHelper
include PageLayoutHelper include PageLayoutHelper
include WorkhorseHelper
before_action :authenticate_user_from_token! before_action :authenticate_user_from_token!
before_action :authenticate_user! before_action :authenticate_user!
......
...@@ -10,10 +10,7 @@ class Projects::AvatarsController < Projects::ApplicationController ...@@ -10,10 +10,7 @@ class Projects::AvatarsController < Projects::ApplicationController
return if cached_blob? return if cached_blob?
headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) send_git_blob @repository, @blob
headers['Content-Disposition'] = 'inline'
headers['Content-Type'] = safe_content_type(@blob)
head :ok # 'render nothing: true' messes up the Content-Type
else else
render_404 render_404
end end
......
...@@ -41,7 +41,7 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -41,7 +41,7 @@ class Projects::BuildsController < Projects::ApplicationController
def trace def trace
respond_to do |format| respond_to do |format|
format.json do format.json do
render json: @build.trace_with_state(params[:state]).merge!(id: @build.id, status: @build.status) render json: @build.trace_with_state(params[:state].presence).merge!(id: @build.id, status: @build.status)
end end
end end
end end
......
...@@ -61,12 +61,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -61,12 +61,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
format.json { render json: @merge_request } format.json { render json: @merge_request }
format.patch { render text: @merge_request.to_patch } format.patch { render text: @merge_request.to_patch }
format.diff do format.diff do
headers.store(*Gitlab::Workhorse.send_git_diff(@project.repository, return render_404 unless @merge_request.diff_refs
@merge_request.diff_base_commit.id,
@merge_request.last_commit.id))
headers['Content-Disposition'] = 'inline'
head :ok send_git_diff @project.repository, @merge_request.diff_refs
end end
end end
end end
......
...@@ -18,10 +18,7 @@ class Projects::RawController < Projects::ApplicationController ...@@ -18,10 +18,7 @@ class Projects::RawController < Projects::ApplicationController
if @blob.lfs_pointer? if @blob.lfs_pointer?
send_lfs_object send_lfs_object
else else
headers.store(*Gitlab::Workhorse.send_git_blob(@repository, @blob)) send_git_blob @repository, @blob
headers['Content-Disposition'] = 'inline'
headers['Content-Type'] = safe_content_type(@blob)
head :ok # 'render nothing: true' messes up the Content-Type
end end
else else
render_404 render_404
......
...@@ -11,8 +11,7 @@ class Projects::RepositoriesController < Projects::ApplicationController ...@@ -11,8 +11,7 @@ class Projects::RepositoriesController < Projects::ApplicationController
end end
def archive def archive
headers.store(*Gitlab::Workhorse.send_git_archive(@project, params[:ref], params[:format])) send_git_archive @repository, ref: params[:ref], format: params[:format]
head :ok
rescue => ex rescue => ex
logger.error("#{self.class.name}: #{ex}") logger.error("#{self.class.name}: #{ex}")
return git_not_found! return git_not_found!
......
...@@ -234,7 +234,7 @@ class ProjectsController < Projects::ApplicationController ...@@ -234,7 +234,7 @@ class ProjectsController < Projects::ApplicationController
:issues_tracker_id, :default_branch, :issues_tracker_id, :default_branch,
:wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar,
:builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, :builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex,
:public_builds, :public_builds, :only_allow_merge_if_build_succeeds
) )
end end
......
...@@ -67,9 +67,9 @@ module DropdownsHelper ...@@ -67,9 +67,9 @@ module DropdownsHelper
end end
end end
def dropdown_filter(placeholder) def dropdown_filter(placeholder, search_id: nil)
content_tag :div, class: "dropdown-input" do content_tag :div, class: "dropdown-input" do
filter_output = search_field_tag nil, nil, class: "dropdown-input-field", placeholder: placeholder filter_output = search_field_tag search_id, nil, class: "dropdown-input-field", placeholder: placeholder
filter_output << icon('search', class: "dropdown-input-search") filter_output << icon('search', class: "dropdown-input-search")
filter_output << icon('times', class: "dropdown-input-clear js-dropdown-input-clear", role: "button") filter_output << icon('times', class: "dropdown-input-clear js-dropdown-input-clear", role: "button")
......
...@@ -30,17 +30,13 @@ module NavHelper ...@@ -30,17 +30,13 @@ module NavHelper
else else
"page-gutter right-sidebar-expanded" "page-gutter right-sidebar-expanded"
end end
elsif current_path?('builds#show')
"page-gutter build-sidebar right-sidebar-expanded"
end end
end end
def nav_header_class def nav_header_class
class_name = class_name = " with-horizontal-nav" if defined?(nav) && nav
if nav_menu_collapsed?
"header-collapsed"
else
"header-expanded"
end
class_name += " with-horizontal-nav" if defined?(nav) && nav
class_name class_name
end end
......
# Helpers to send Git blobs, diffs or archives through Workhorse.
# Workhorse will also serve files when using `send_file`.
module WorkhorseHelper
# Send a Git blob through Workhorse
def send_git_blob(repository, blob)
headers.store(*Gitlab::Workhorse.send_git_blob(repository, blob))
headers['Content-Disposition'] = 'inline'
headers['Content-Type'] = safe_content_type(blob)
head :ok # 'render nothing: true' messes up the Content-Type
end
# Send a Git diff through Workhorse
def send_git_diff(repository, diff_refs)
headers.store(*Gitlab::Workhorse.send_git_diff(repository, diff_refs))
headers['Content-Disposition'] = 'inline'
head :ok
end
# Archive a Git repository and send it through Workhorse
def send_git_archive(repository, ref:, format:)
headers.store(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format))
head :ok
end
end
...@@ -194,7 +194,7 @@ module Ci ...@@ -194,7 +194,7 @@ module Ci
def trace_length def trace_length
if raw_trace if raw_trace
raw_trace.length raw_trace.bytesize
else else
0 0
end end
...@@ -216,7 +216,7 @@ module Ci ...@@ -216,7 +216,7 @@ module Ci
recreate_trace_dir recreate_trace_dir
File.truncate(path_to_trace, offset) if File.exist?(path_to_trace) File.truncate(path_to_trace, offset) if File.exist?(path_to_trace)
File.open(path_to_trace, 'a') do |f| File.open(path_to_trace, 'ab') do |f|
f.write(trace_part) f.write(trace_part)
end end
end end
......
...@@ -3,7 +3,7 @@ module Ci ...@@ -3,7 +3,7 @@ module Ci
extend Ci::Model extend Ci::Model
belongs_to :trigger, class_name: 'Ci::Trigger' belongs_to :trigger, class_name: 'Ci::Trigger'
belongs_to :commit, class_name: 'Ci::Pipeline', foreign_key: :commit_id belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
has_many :builds, class_name: 'Ci::Build' has_many :builds, class_name: 'Ci::Build'
serialize :variables serialize :variables
......
...@@ -260,19 +260,20 @@ class MergeRequest < ActiveRecord::Base ...@@ -260,19 +260,20 @@ class MergeRequest < ActiveRecord::Base
end end
def mergeable? def mergeable?
return false unless open? && !work_in_progress? && !broken? return false unless mergeable_state?
check_if_can_be_merged check_if_can_be_merged
can_be_merged? can_be_merged?
end end
def gitlab_merge_status def mergeable_state?
if work_in_progress? return false unless open?
"work_in_progress" return false if work_in_progress?
else return false if broken?
merge_status_name return false unless mergeable_ci_state?
end
true
end end
def can_cancel_merge_when_build_succeeds?(current_user) def can_cancel_merge_when_build_succeeds?(current_user)
...@@ -481,6 +482,12 @@ class MergeRequest < ActiveRecord::Base ...@@ -481,6 +482,12 @@ class MergeRequest < ActiveRecord::Base
::Gitlab::GitAccess.new(user, project).can_push_to_branch?(target_branch) ::Gitlab::GitAccess.new(user, project).can_push_to_branch?(target_branch)
end end
def mergeable_ci_state?
return true unless project.only_allow_merge_if_build_succeeds?
!pipeline || pipeline.success?
end
def state_human_name def state_human_name
if merged? if merged?
"Merged" "Merged"
......
...@@ -253,20 +253,69 @@ class Project < ActiveRecord::Base ...@@ -253,20 +253,69 @@ class Project < ActiveRecord::Base
non_archived.where(table[:name].matches(pattern)) non_archived.where(table[:name].matches(pattern))
end end
def find_with_namespace(id) # Finds a single project for the given path.
namespace_path, project_path = id.split('/', 2) #
# path - The full project path (including namespace path).
#
# Returns a Project, or nil if no project could be found.
def find_with_namespace(path)
where_paths_in([path]).reorder(nil).take
end
return nil if !namespace_path || !project_path # Builds a relation to find multiple projects by their full paths.
#
# Each path must be in the following format:
#
# namespace_path/project_path
#
# For example:
#
# gitlab-org/gitlab-ce
#
# Usage:
#
# Project.where_paths_in(%w{gitlab-org/gitlab-ce gitlab-org/gitlab-ee})
#
# This would return the projects with the full paths matching the values
# given.
#
# paths - An Array of full paths (namespace path + project path) for which
# to find the projects.
#
# Returns an ActiveRecord::Relation.
def where_paths_in(paths)
wheres = []
cast_lower = Gitlab::Database.postgresql?
# Use of unscoped ensures we're not secretly adding any ORDER BYs, which paths.each do |path|
# have a negative impact on performance (and aren't needed for this namespace_path, project_path = path.split('/', 2)
# query).
projects = unscoped. next unless namespace_path && project_path
joins(:namespace).
iwhere('namespaces.path' => namespace_path) namespace_path = connection.quote(namespace_path)
project_path = connection.quote(project_path)
projects.find_by('projects.path' => project_path) || where = "(namespaces.path = #{namespace_path}
projects.iwhere('projects.path' => project_path).take AND projects.path = #{project_path})"
if cast_lower
where = "(
#{where}
OR (
LOWER(namespaces.path) = LOWER(#{namespace_path})
AND LOWER(projects.path) = LOWER(#{project_path})
)
)"
end
wheres << where
end
if wheres.empty?
none
else
joins(:namespace).where(wheres.join(' OR '))
end
end end
def visibility_levels def visibility_levels
...@@ -523,9 +572,21 @@ class Project < ActiveRecord::Base ...@@ -523,9 +572,21 @@ class Project < ActiveRecord::Base
end end
def external_issue_tracker def external_issue_tracker
if has_external_issue_tracker.nil? # To populate existing projects
cache_has_external_issue_tracker
end
if has_external_issue_tracker?
return @external_issue_tracker if defined?(@external_issue_tracker) return @external_issue_tracker if defined?(@external_issue_tracker)
@external_issue_tracker ||=
services.issue_trackers.active.without_defaults.first @external_issue_tracker = services.external_issue_trackers.first
else
nil
end
end
def cache_has_external_issue_tracker
update_column(:has_external_issue_tracker, services.external_issue_trackers.any?)
end end
def can_have_issues_tracker_id? def can_have_issues_tracker_id?
......
...@@ -16,6 +16,7 @@ class Service < ActiveRecord::Base ...@@ -16,6 +16,7 @@ class Service < ActiveRecord::Base
after_initialize :initialize_properties after_initialize :initialize_properties
after_commit :reset_updated_properties after_commit :reset_updated_properties
after_commit :cache_project_has_external_issue_tracker
belongs_to :project belongs_to :project
has_one :service_hook has_one :service_hook
...@@ -34,6 +35,7 @@ class Service < ActiveRecord::Base ...@@ -34,6 +35,7 @@ class Service < ActiveRecord::Base
scope :note_hooks, -> { where(note_events: true, active: true) } scope :note_hooks, -> { where(note_events: true, active: true) }
scope :build_hooks, -> { where(build_events: true, active: true) } scope :build_hooks, -> { where(build_events: true, active: true) }
scope :wiki_page_hooks, -> { where(wiki_page_events: true, active: true) } scope :wiki_page_hooks, -> { where(wiki_page_events: true, active: true) }
scope :external_issue_trackers, -> { issue_trackers.active.without_defaults }
default_value_for :category, 'common' default_value_for :category, 'common'
...@@ -192,4 +194,12 @@ class Service < ActiveRecord::Base ...@@ -192,4 +194,12 @@ class Service < ActiveRecord::Base
service.project_id = project_id service.project_id = project_id
service if service.save service if service.save
end end
private
def cache_project_has_external_issue_tracker
if project && !project.destroyed?
project.cache_has_external_issue_tracker
end
end
end end
...@@ -11,7 +11,7 @@ module Ci ...@@ -11,7 +11,7 @@ module Ci
trigger_request = trigger.trigger_requests.create!( trigger_request = trigger.trigger_requests.create!(
variables: variables, variables: variables,
commit: pipeline, pipeline: pipeline,
) )
if pipeline.create_builds(nil, trigger_request) if pipeline.create_builds(nil, trigger_request)
......
- if nav_menu_collapsed? = link_to icon('bars'), '#', class: 'toggle-nav-collapse', title: "Open/Close"
= link_to icon('angle-right'), '#', class: 'toggle-nav-collapse', title: "Open/Close"
- else
= link_to icon('angle-left'), '#', class: 'toggle-nav-collapse', title: "Open/Close"
.page-with-sidebar{ class: "#{page_sidebar_class} #{page_gutter_class}" } .page-with-sidebar.page-sidebar-collapsed{ class: "#{page_gutter_class}" }
.sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .sidebar-wrapper.nicescroll{ class: nav_sidebar_class }
= link_to root_path, class: 'gitlab-text-container-link', title: 'Dashboard', id: 'js-shortcuts-home' do
.header-logo
#logo
= brand_header_logo
- if defined?(sidebar) && sidebar - if defined?(sidebar) && sidebar
= render "layouts/nav/#{sidebar}" = render "layouts/nav/#{sidebar}"
...@@ -16,7 +12,9 @@ ...@@ -16,7 +12,9 @@
= render partial: 'layouts/collapse_button' = render partial: 'layouts/collapse_button'
- if current_user - if current_user
= link_to current_user, class: 'sidebar-user', title: "Profile", data: {user: current_user.username} do = link_to current_user, class: 'sidebar-user', title: "Profile", data: {user: current_user.username} do
= image_tag avatar_icon(current_user, 60), alt: 'Profile', class: 'avatar avatar s46' = image_tag avatar_icon(current_user, 60), alt: 'Profile', class: 'avatar avatar s36'
.username
= current_user.username
- if defined?(nav) && nav - if defined?(nav) && nav
.layout-nav .layout-nav
.container-fluid .container-fluid
......
.page-with-sidebar{ class: page_sidebar_class } .page-with-sidebar{ class: page_sidebar_class }
= render "layouts/broadcast" = render "layouts/broadcast"
.sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .sidebar-wrapper.nicescroll{ class: nav_sidebar_class }
.header-logo
%a#logo
= brand_header_logo
= link_to root_path, class: 'gitlab-text-container-link', title: 'Dashboard', id: 'js-shortcuts-home' do
.gitlab-text-container
%h3 GitLab
- if defined?(sidebar) && sidebar - if defined?(sidebar) && sidebar
= render "layouts/ci/#{sidebar}" = render "layouts/ci/#{sidebar}"
......
%header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class } %header.navbar.navbar-fixed-top.navbar-gitlab.header-collapsed{ class: nav_header_class }
%div{ class: fluid_layout ? "container-fluid" : "container-fluid" } %div{ class: fluid_layout ? "container-fluid" : "container-fluid" }
.header-content .header-content
%button.side-nav-toggle{type: 'button'} %button.side-nav-toggle{type: 'button'}
...@@ -50,6 +50,10 @@ ...@@ -50,6 +50,10 @@
%h1.title= title %h1.title= title
.header-logo
#logo
= brand_header_logo
= yield :header_content = yield :header_content
= render 'shared/outdated_browser' = render 'shared/outdated_browser'
......
...@@ -2,102 +2,106 @@ ...@@ -2,102 +2,106 @@
= nav_link(controller: :dashboard, html_options: {class: 'home'}) do = nav_link(controller: :dashboard, html_options: {class: 'home'}) do
= link_to admin_root_path, title: 'Overview' do = link_to admin_root_path, title: 'Overview' do
= icon('dashboard fw') = icon('dashboard fw')
.nav-link-text %span
Overview Overview
= nav_link(controller: [:admin, :projects]) do = nav_link(controller: [:admin, :projects]) do
= link_to admin_namespaces_projects_path, title: 'Projects' do = link_to admin_namespaces_projects_path, title: 'Projects' do
= icon('cube fw') = icon('cube fw')
.nav-link-text %span
Projects Projects
= nav_link(controller: :users) do = nav_link(controller: :users) do
= link_to admin_users_path, title: 'Users' do = link_to admin_users_path, title: 'Users' do
= icon('user fw') = icon('user fw')
.nav-link-text %span
Users Users
= nav_link(controller: :groups) do = nav_link(controller: :groups) do
= link_to admin_groups_path, title: 'Groups' do = link_to admin_groups_path, title: 'Groups' do
= icon('group fw') = icon('group fw')
.nav-link-text %span
Groups Groups
= nav_link(controller: :deploy_keys) do = nav_link(controller: :deploy_keys) do
= link_to admin_deploy_keys_path, title: 'Deploy Keys' do = link_to admin_deploy_keys_path, title: 'Deploy Keys' do
= icon('key fw') = icon('key fw')
.nav-link-text %span
Deploy Keys Deploy Keys
= nav_link path: ['runners#index', 'runners#show'] do = nav_link path: ['runners#index', 'runners#show'] do
= link_to admin_runners_path, title: 'Runners' do = link_to admin_runners_path, title: 'Runners' do
= icon('cog fw') = icon('cog fw')
.nav-link-text %span
Runners Runners
%span.count= number_with_delimiter(Ci::Runner.count(:all))
= nav_link path: 'builds#index' do = nav_link path: 'builds#index' do
= link_to admin_builds_path, title: 'Builds' do = link_to admin_builds_path, title: 'Builds' do
= icon('link fw') = icon('link fw')
.nav-link-text %span
Builds Builds
%span.count= number_with_delimiter(Ci::Build.count(:all))
= nav_link(controller: :logs) do = nav_link(controller: :logs) do
= link_to admin_logs_path, title: 'Logs' do = link_to admin_logs_path, title: 'Logs' do
= icon('file-text fw') = icon('file-text fw')
.nav-link-text %span
Logs Logs
= nav_link(controller: :health_check) do = nav_link(controller: :health_check) do
= link_to admin_health_check_path, title: 'Health Check' do = link_to admin_health_check_path, title: 'Health Check' do
= icon('medkit fw') = icon('medkit fw')
.nav-link-text %span
Health Check Health Check
= nav_link(controller: :broadcast_messages) do = nav_link(controller: :broadcast_messages) do
= link_to admin_broadcast_messages_path, title: 'Messages' do = link_to admin_broadcast_messages_path, title: 'Messages' do
= icon('bullhorn fw') = icon('bullhorn fw')
.nav-link-text %span
Messages Messages
= nav_link(controller: :hooks) do = nav_link(controller: :hooks) do
= link_to admin_hooks_path, title: 'Hooks' do = link_to admin_hooks_path, title: 'Hooks' do
= icon('external-link fw') = icon('external-link fw')
.nav-link-text %span
Hooks Hooks
= nav_link(controller: :background_jobs) do = nav_link(controller: :background_jobs) do
= link_to admin_background_jobs_path, title: 'Background Jobs' do = link_to admin_background_jobs_path, title: 'Background Jobs' do
= icon('cog fw') = icon('cog fw')
.nav-link-text %span
Background Jobs Background Jobs
= nav_link(controller: :appearances) do = nav_link(controller: :appearances) do
= link_to admin_appearances_path, title: 'Appearances' do = link_to admin_appearances_path, title: 'Appearances' do
= icon('image') = icon('image')
.nav-link-text %span
Appearance Appearance
= nav_link(controller: :applications) do = nav_link(controller: :applications) do
= link_to admin_applications_path, title: 'Applications' do = link_to admin_applications_path, title: 'Applications' do
= icon('cloud fw') = icon('cloud fw')
.nav-link-text %span
Applications Applications
= nav_link(controller: :services) do = nav_link(controller: :services) do
= link_to admin_application_settings_services_path, title: 'Service Templates' do = link_to admin_application_settings_services_path, title: 'Service Templates' do
= icon('copy fw') = icon('copy fw')
.nav-link-text %span
Service Templates Service Templates
= nav_link(controller: :labels) do = nav_link(controller: :labels) do
= link_to admin_labels_path, title: 'Labels' do = link_to admin_labels_path, title: 'Labels' do
= icon('tags fw') = icon('tags fw')
.nav-link-text %span
Labels Labels
= nav_link(controller: :abuse_reports) do = nav_link(controller: :abuse_reports) do
= link_to admin_abuse_reports_path, title: "Abuse Reports" do = link_to admin_abuse_reports_path, title: "Abuse Reports" do
= icon('exclamation-circle fw') = icon('exclamation-circle fw')
.nav-link-text %span
Abuse Reports Abuse Reports
%span.count= number_with_delimiter(AbuseReport.count(:all))
- if askimet_enabled? - if askimet_enabled?
= nav_link(controller: :spam_logs) do = nav_link(controller: :spam_logs) do
= link_to admin_spam_logs_path, title: "Spam Logs" do = link_to admin_spam_logs_path, title: "Spam Logs" do
= icon('exclamation-triangle fw') = icon('exclamation-triangle fw')
.nav-link-text %span
Spam Logs Spam Logs
%span.count= number_with_delimiter(SpamLog.count(:all))
= nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do
= link_to admin_application_settings_path, title: 'Settings' do = link_to admin_application_settings_path, title: 'Settings' do
= icon('cogs fw') = icon('cogs fw')
.nav-link-text %span
Settings Settings
...@@ -2,50 +2,53 @@ ...@@ -2,50 +2,53 @@
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "#{project_tab_class} home"}) do = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "#{project_tab_class} home"}) do
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do = link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
= navbar_icon('project') = navbar_icon('project')
.nav-link-text %span
Projects Projects
= nav_link(controller: :todos) do = nav_link(controller: :todos) do
= link_to dashboard_todos_path, title: 'Todos' do = link_to dashboard_todos_path, title: 'Todos' do
= icon('bell fw') = icon('bell fw')
.nav-link-text %span
Todos Todos
%span.count= number_with_delimiter(todos_pending_count)
= nav_link(path: 'dashboard#activity') do = nav_link(path: 'dashboard#activity') do
= link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
= navbar_icon('activity') = navbar_icon('activity')
.nav-link-text %span
Activity Activity
= nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
= link_to dashboard_groups_path, title: 'Groups' do = link_to dashboard_groups_path, title: 'Groups' do
= navbar_icon('group') = navbar_icon('group')
.nav-link-text %span
Groups Groups
= nav_link(controller: 'dashboard/milestones') do = nav_link(controller: 'dashboard/milestones') do
= link_to dashboard_milestones_path, title: 'Milestones' do = link_to dashboard_milestones_path, title: 'Milestones' do
= navbar_icon('milestones') = navbar_icon('milestones')
.nav-link-text %span
Milestones Milestones
= nav_link(path: 'dashboard#issues') do = nav_link(path: 'dashboard#issues') do
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues' do = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues' do
= navbar_icon('issues') = navbar_icon('issues')
.nav-link-text %span
Issues Issues
%span.count= number_with_delimiter(current_user.assigned_issues.opened.count)
= nav_link(path: 'dashboard#merge_requests') do = nav_link(path: 'dashboard#merge_requests') do
= link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'dashboard-shortcuts-merge_requests' do = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'dashboard-shortcuts-merge_requests' do
= navbar_icon('mr') = navbar_icon('mr')
.nav-link-text %span
Merge Requests Merge Requests
%span.count= number_with_delimiter(current_user.assigned_merge_requests.opened.count)
= nav_link(controller: :snippets) do = nav_link(controller: :snippets) do
= link_to dashboard_snippets_path, title: 'Snippets' do = link_to dashboard_snippets_path, title: 'Snippets' do
= icon('clipboard fw') = icon('clipboard fw')
.nav-link-text %span
Snippets Snippets
= nav_link(controller: :help) do = nav_link(controller: :help) do
= link_to help_path, title: 'Help' do = link_to help_path, title: 'Help' do
= icon('question-circle fw') = icon('question-circle fw')
.nav-link-text %span
Help Help
= nav_link(html_options: {class: profile_tab_class}) do = nav_link(html_options: {class: profile_tab_class}) do
= link_to profile_path, title: 'Profile Settings', data: {placement: 'bottom'} do = link_to profile_path, title: 'Profile Settings', data: {placement: 'bottom'} do
= icon('user fw') = icon('user fw')
.nav-link-text %span
Profile Settings Profile Settings
...@@ -2,20 +2,20 @@ ...@@ -2,20 +2,20 @@
= nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do = nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do
= link_to explore_root_path, title: 'Projects' do = link_to explore_root_path, title: 'Projects' do
= icon('bookmark fw') = icon('bookmark fw')
.nav-link-text %span
Projects Projects
= nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
= link_to explore_groups_path, title: 'Groups' do = link_to explore_groups_path, title: 'Groups' do
= icon('group fw') = icon('group fw')
.nav-link-text %span
Groups Groups
= nav_link(controller: :snippets) do = nav_link(controller: :snippets) do
= link_to explore_snippets_path, title: 'Snippets' do = link_to explore_snippets_path, title: 'Snippets' do
= icon('clipboard fw') = icon('clipboard fw')
.nav-link-text %span
Snippets Snippets
= nav_link(controller: :help) do = nav_link(controller: :help) do
= link_to help_path, title: 'Help' do = link_to help_path, title: 'Help' do
= icon('question-circle fw') = icon('question-circle fw')
.nav-link-text %span
Help Help
...@@ -5,36 +5,30 @@ ...@@ -5,36 +5,30 @@
.fade-left .fade-left
= nav_link(path: 'groups#show', html_options: {class: 'home'}) do = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
= link_to group_path(@group), title: 'Home' do = link_to group_path(@group), title: 'Home' do
= navbar_icon('group')
%span %span
Group Group
= nav_link(path: 'groups#activity') do = nav_link(path: 'groups#activity') do
= link_to activity_group_path(@group), title: 'Activity' do = link_to activity_group_path(@group), title: 'Activity' do
= navbar_icon('activity')
%span %span
Activity Activity
= nav_link(controller: [:group, :milestones]) do = nav_link(controller: [:group, :milestones]) do
= link_to group_milestones_path(@group), title: 'Milestones' do = link_to group_milestones_path(@group), title: 'Milestones' do
= navbar_icon('milestones')
%span %span
Milestones Milestones
= nav_link(path: 'groups#issues') do = nav_link(path: 'groups#issues') do
= link_to issues_group_path(@group), title: 'Issues' do = link_to issues_group_path(@group), title: 'Issues' do
= navbar_icon('issues')
%span %span
Issues Issues
- issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
%span.badge.count= number_with_delimiter(issues.count) %span.badge.count= number_with_delimiter(issues.count)
= nav_link(path: 'groups#merge_requests') do = nav_link(path: 'groups#merge_requests') do
= link_to merge_requests_group_path(@group), title: 'Merge Requests' do = link_to merge_requests_group_path(@group), title: 'Merge Requests' do
= navbar_icon('mr')
%span %span
Merge Requests Merge Requests
- merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute
%span.badge.count= number_with_delimiter(merge_requests.count) %span.badge.count= number_with_delimiter(merge_requests.count)
= nav_link(controller: [:group_members]) do = nav_link(controller: [:group_members]) do
= link_to group_group_members_path(@group), title: 'Members' do = link_to group_group_members_path(@group), title: 'Members' do
= navbar_icon('members')
%span %span
Members Members
.fade-right .fade-right
...@@ -2,51 +2,41 @@ ...@@ -2,51 +2,41 @@
.fade-left .fade-left
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path, title: 'Profile Settings' do = link_to profile_path, title: 'Profile Settings' do
= icon('user fw')
%span %span
Profile Profile
= nav_link(controller: [:accounts, :two_factor_auths]) do = nav_link(controller: [:accounts, :two_factor_auths]) do
= link_to profile_account_path, title: 'Account' do = link_to profile_account_path, title: 'Account' do
= icon('gear fw')
%span %span
Account Account
- if current_application_settings.user_oauth_applications? - if current_application_settings.user_oauth_applications?
= nav_link(controller: 'oauth/applications') do = nav_link(controller: 'oauth/applications') do
= link_to applications_profile_path, title: 'Applications' do = link_to applications_profile_path, title: 'Applications' do
= icon('cloud fw')
%span %span
Applications Applications
= nav_link(controller: :emails) do = nav_link(controller: :emails) do
= link_to profile_emails_path, title: 'Emails' do = link_to profile_emails_path, title: 'Emails' do
= icon('envelope-o fw')
%span %span
Emails Emails
- unless current_user.ldap_user? - unless current_user.ldap_user?
= nav_link(controller: :passwords) do = nav_link(controller: :passwords) do
= link_to edit_profile_password_path, title: 'Password' do = link_to edit_profile_password_path, title: 'Password' do
= icon('lock fw')
%span %span
Password Password
= nav_link(controller: :notifications) do = nav_link(controller: :notifications) do
= link_to profile_notifications_path, title: 'Notifications' do = link_to profile_notifications_path, title: 'Notifications' do
= icon('inbox fw')
%span %span
Notifications Notifications
= nav_link(controller: :keys) do = nav_link(controller: :keys) do
= link_to profile_keys_path, title: 'SSH Keys' do = link_to profile_keys_path, title: 'SSH Keys' do
= icon('key fw')
%span %span
SSH Keys SSH Keys
= nav_link(controller: :preferences) do = nav_link(controller: :preferences) do
= link_to profile_preferences_path, title: 'Preferences' do = link_to profile_preferences_path, title: 'Preferences' do
-# TODO (rspeicher): Better icon?
= icon('image fw')
%span %span
Preferences Preferences
= nav_link(path: 'profiles#audit_log') do = nav_link(path: 'profiles#audit_log') do
= link_to audit_log_profile_path, title: 'Audit Log' do = link_to audit_log_profile_path, title: 'Audit Log' do
= icon('history fw')
%span %span
Audit Log Audit Log
.fade-right .fade-right
...@@ -24,55 +24,41 @@ ...@@ -24,55 +24,41 @@
.fade-left .fade-left
= nav_link(path: 'projects#show', html_options: {class: 'home'}) do = nav_link(path: 'projects#show', html_options: {class: 'home'}) do
= link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do
= navbar_icon('project')
%span %span
Project Project
= nav_link(path: 'projects#activity') do = nav_link(path: 'projects#activity') do
= link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do
= navbar_icon('activity')
%span %span
Activity Activity
- if project_nav_tab? :files - if project_nav_tab? :files
= nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare repositories tags branches releases network)) do = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare repositories tags branches releases network)) do
= link_to project_files_path(@project), title: 'Code', class: 'shortcuts-tree' do = link_to project_files_path(@project), title: 'Code', class: 'shortcuts-tree' do
= icon('code fw')
%span %span
Code Code
- if project_nav_tab? :pipelines - if project_nav_tab? :pipelines
= nav_link(controller: :pipelines) do = nav_link(controller: :pipelines) do
= link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do
= navbar_icon('pipelines')
%span %span
Pipelines Pipelines
- if project_nav_tab? :container_registry - if project_nav_tab? :container_registry
= nav_link(controller: %w(container_registry)) do = nav_link(controller: %w(container_registry)) do
= link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do = link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do
= icon('hdd-o fw')
%span %span
Registry Registry
- if project_nav_tab? :graphs - if project_nav_tab? :graphs
= nav_link(controller: %w(graphs)) do = nav_link(controller: %w(graphs)) do
= link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do
= icon('area-chart fw')
%span %span
Graphs Graphs
- if project_nav_tab? :milestones
= nav_link(controller: :milestones) do
= link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do
= navbar_icon('milestones')
%span
Milestones
- if project_nav_tab? :issues - if project_nav_tab? :issues
= nav_link(controller: :issues) do = nav_link(controller: [:issues, :labels, :milestones]) do
= link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do
= navbar_icon('issues')
%span %span
Issues Issues
- if @project.default_issues_tracker? - if @project.default_issues_tracker?
...@@ -81,29 +67,19 @@ ...@@ -81,29 +67,19 @@
- if project_nav_tab? :merge_requests - if project_nav_tab? :merge_requests
= nav_link(controller: :merge_requests) do = nav_link(controller: :merge_requests) do
= link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
= navbar_icon('mr')
%span %span
Merge Requests Merge Requests
%span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count) %span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count)
- if project_nav_tab? :labels
= nav_link(controller: :labels) do
= link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do
= icon('tags fw')
%span
Labels
- if project_nav_tab? :wiki - if project_nav_tab? :wiki
= nav_link(controller: :wikis) do = nav_link(controller: :wikis) do
= link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do
= navbar_icon('wiki')
%span %span
Wiki Wiki
- if project_nav_tab? :snippets - if project_nav_tab? :snippets
= nav_link(controller: :snippets) do = nav_link(controller: :snippets) do
= link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do
= icon('clipboard fw')
%span %span
Snippets Snippets
...@@ -129,5 +105,4 @@ ...@@ -129,5 +105,4 @@
%li.hidden %li.hidden
= link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do
Commits Commits
.fade-right .fade-right
%fieldset.builds-feature
%h5.prepend-top-0
Merge Requests
.form-group
.checkbox
= f.label :only_allow_merge_if_build_succeeds do
= f.check_box :only_allow_merge_if_build_succeeds
%strong Only allow merge requests to be merged if the build succeeds
.help-block
Builds need to be configured to enable this feature.
= link_to icon('question-circle'), help_page_path('workflow', 'merge_requests#only-allow-merge-requests-to-be-merged-if-the-build-succeeds')
- page_title 'Artifacts', "#{@build.name} (##{@build.id})", 'Builds' - page_title 'Artifacts', "#{@build.name} (##{@build.id})", 'Builds'
- header_title project_title(@project, "Builds", project_builds_path(@project))
.top-block.row-content-block.clearfix .top-block.row-content-block.clearfix
.pull-right .pull-right
......
.content-block.build-header
= ci_status_with_icon(@build.status)
Build
%strong ##{@build.id}
for commit
= link_to ci_status_path(@build.pipeline) do
%strong= @build.pipeline.short_sha
from
= link_to namespace_project_commits_path(@project.namespace, @project, @build.ref) do
%code
= @build.ref
- if @build.user
= render "user"
= time_ago_with_tooltip(@build.created_at)
%button.btn.btn-default.pull-right.visible-xs-block.visible-sm-block.build-gutter-toggle.js-sidebar-build-toggle{ role: "button", type: "button" }
= icon('angle-double-left')
%aside.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar
.block.build-sidebar-header.visible-xs-block.visible-sm-block.append-bottom-default
Build
%strong ##{@build.id}
%a.gutter-toggle.pull-right.js-sidebar-build-toggle{ href: "#" }
= icon('angle-double-right')
- if @build.coverage
.block.block-first
.title
Test coverage
%p.build-detail-row
#{@build.coverage}%
- if can?(current_user, :read_build, @project) && @build.artifacts?
.block{ class: ("block-first" if !@build.coverage) }
.title
Build artifacts
.btn-group.btn-group-justified{ role: :group }
= link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' do
Download
- if @build.artifacts_metadata?
= link_to browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' do
Browse
.block{ class: ("block-first" if !@build.coverage && !(can?(current_user, :read_build, @project) && @build.artifacts?)) }
.title
Build details
- if @build.retryable?
= link_to "Retry", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'pull-right', method: :post
- if @build.merge_request
%p.build-detail-row
%span.build-light-text Merge Request:
= link_to "#{@build.merge_request.to_reference}", merge_request_path(@build.merge_request)
- if @build.duration
%p.build-detail-row
%span.build-light-text Duration:
#{duration_in_words(@build.finished_at, @build.started_at)}
- if @build.finished_at
%p.build-detail-row
%span.build-light-text Finished:
#{time_ago_with_tooltip(@build.finished_at)}
- if @build.erased_at
%p.build-detail-row
%span.build-light-text Erased:
#{time_ago_with_tooltip(@build.erased_at)}
%p.build-detail-row
%span.build-light-text Runner:
- if @build.runner && current_user && current_user.admin
= link_to "##{@build.runner.id}", admin_runner_path(@build.runner.id)
- elsif @build.runner
\##{@build.runner.id}
.btn-group.btn-group-justified{ role: :group }
- if @build.has_trace?
= link_to 'Raw', raw_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default'
- if @build.active?
= link_to "Cancel", cancel_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post
- if can?(current_user, :update_build, @project) && @build.erasable?
= link_to erase_namespace_project_build_path(@project.namespace, @project, @build),
class: "btn btn-sm btn-default", method: :post,
data: { confirm: "Are you sure you want to erase this build?" } do
Erase
- if @build.trigger_request
.build-widget
%h4.title
Trigger
%p
%span.build-light-text Token:
#{@build.trigger_request.trigger.short_token}
- if @build.trigger_request.variables
%p
%span.build-light-text Variables:
%code
- @build.trigger_request.variables.each do |key, value|
#{key}=#{value}
.block
.title
Commit message
%p.build-light-text.append-bottom-0
#{@build.pipeline.git_commit_message}
- if @build.tags.any?
.block
.title
Tags
- @build.tag_list.each do |tag|
%span.label.label-primary
= tag
by
%a{ href: user_path(@build.user) }
= image_tag avatar_icon(@build.user, 24), class: "avatar s24"
%strong= @build.user.to_reference
- page_title "#{@build.name} (##{@build.id})", "Builds" - page_title "#{@build.name} (##{@build.id})", "Builds"
- trace_with_state = @build.trace_with_state - trace_with_state = @build.trace_with_state
- header_title project_title(@project, "Builds", project_builds_path(@project))
.build-page .build-page
.row-content-block.top-block = render "header"
Build ##{@build.id} for commit
%strong.monospace= link_to @build.pipeline.short_sha, ci_status_path(@build.pipeline)
from
= link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref)
- merge_request = @build.merge_request
- if merge_request
via
= link_to "merge request #{merge_request.to_reference}", merge_request_path(merge_request)
#up-build-trace
- builds = @build.pipeline.builds.latest.to_a - builds = @build.pipeline.builds.latest.to_a
- if builds.size > 1 - if builds.size > 1
%ul.nav-links.no-top.no-bottom %ul.nav-links.no-top.no-bottom
...@@ -33,18 +25,6 @@ ...@@ -33,18 +25,6 @@
&middot; &middot;
%i.fa.fa-warning %i.fa.fa-warning
This build was retried. This build was retried.
.row-content-block.middle-block
.build-head
.clearfix
= ci_status_with_icon(@build.status)
- if @build.duration
%span
%i.fa.fa-time
#{duration_in_words(@build.finished_at, @build.started_at)}
.pull-right
#{time_ago_with_tooltip(@build.finished_at) if @build.finished_at}
- if @build.stuck? - if @build.stuck?
- unless @build.any_runners_online? - unless @build.any_runners_online?
.bs-callout.bs-callout-warning .bs-callout.bs-callout-warning
...@@ -64,158 +44,27 @@ ...@@ -64,158 +44,27 @@
= link_to namespace_project_runners_path(@build.project.namespace, @build.project) do = link_to namespace_project_runners_path(@build.project.namespace, @build.project) do
Runners page Runners page
.row.prepend-top-default .prepend-top-default
.col-md-9
.clearfix
- if @build.active? - if @build.active?
.autoscroll-container .autoscroll-container
%button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll
.clearfix
#js-build-scroll.scroll-controls #js-build-scroll.scroll-controls
= link_to '#up-build-trace', class: 'btn' do = link_to '#build-trace', class: 'btn' do
%i.fa.fa-angle-up %i.fa.fa-angle-up
= link_to '#down-build-trace', class: 'btn' do = link_to '#down-build-trace', class: 'btn' do
%i.fa.fa-angle-down %i.fa.fa-angle-down
- if @build.erased? - if @build.erased?
.erased.alert.alert-warning .erased.alert.alert-warning
- erased_by = "by #{link_to @build.erased_by.name, user_path(@build.erased_by)}" if @build.erased_by - erased_by = "by #{link_to @build.erased_by.name, user_path(@build.erased_by)}" if @build.erased_by
Build has been erased #{erased_by.html_safe} #{time_ago_with_tooltip(@build.erased_at)} Build has been erased #{erased_by.html_safe} #{time_ago_with_tooltip(@build.erased_at)}
- else - else
%pre.trace#build-trace %pre.build-trace#build-trace
%code.bash %code.bash.js-build-output
= preserve do = icon("refresh spin", class: "js-build-refresh")
= raw trace_with_state[:html]
- if @build.active?
%i{:class => "fa fa-refresh fa-spin"}
%div#down-build-trace
.col-md-3
- if @build.coverage
.build-widget
%h4.title
Test coverage
%h1 #{@build.coverage}%
- if can?(current_user, :read_build, @project) && @build.artifacts?
.build-widget.artifacts
%h4.title Build artifacts
.center
.btn-group{ role: :group }
= link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-primary' do
= icon('download')
Download
- if @build.artifacts_metadata?
= link_to browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-primary' do
= icon('folder-open')
Browse
.build-widget.build-controls
%h4.title
Build ##{@build.id}
- if can?(current_user, :update_build, @project)
.center
.btn-group{ role: :group }
- if @build.active?
= link_to "Cancel", cancel_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-danger', method: :post
- elsif @build.retryable?
= link_to "Retry", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-primary', method: :post
- if @build.erasable?
= link_to erase_namespace_project_build_path(@project.namespace, @project, @build),
class: 'btn btn-sm btn-warning', method: :post,
data: { confirm: 'Are you sure you want to erase this build?' } do
= icon('eraser')
Erase
- if @build.has_trace?
= link_to 'Raw', raw_namespace_project_build_path(@project.namespace, @project, @build),
class: 'btn btn-sm btn-success', target: '_blank'
.clearfix
- if @build.duration
%p
%span.attr-name Duration:
#{duration_in_words(@build.finished_at, @build.started_at)}
%p
%span.attr-name Created:
#{time_ago_with_tooltip(@build.created_at)}
- if @build.finished_at
%p
%span.attr-name Finished:
#{time_ago_with_tooltip(@build.finished_at)}
- if @build.erased_at
%p
%span.attr-name Erased:
#{time_ago_with_tooltip(@build.erased_at)}
%p
%span.attr-name Runner:
- if @build.runner && current_user && current_user.admin
= link_to "##{@build.runner.id}", admin_runner_path(@build.runner.id)
- elsif @build.runner
\##{@build.runner.id}
- if @build.trigger_request
.build-widget
%h4.title
Trigger
%p
%span.attr-name Token:
#{@build.trigger_request.trigger.short_token}
- if @build.trigger_request.variables
%p
%span.attr-name Variables:
%code
- @build.trigger_request.variables.each do |key, value|
#{key}=#{value}
.build-widget
%h4.title
Commit
.pull-right
%small
= link_to @build.pipeline.short_sha, ci_status_path(@build.pipeline), class: "monospace"
%p
%span.attr-name Branch:
= link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref)
%p
%span.attr-name Author:
#{@build.pipeline.git_author_name}
%p
%span.attr-name Message:
#{@build.pipeline.git_commit_message}
- if @build.tags.any?
.build-widget
%h4.title
Tags
- @build.tag_list.each do |tag|
%span.label.label-primary
= tag
- if @builds.present?
.build-widget
%h4.title #{pluralize(@builds.count(:id), "other build")} for
= succeed ":" do
= link_to @build.pipeline.short_sha, ci_status_path(@build.pipeline), class: "monospace"
%table.table.builds
- @builds.each_with_index do |build, i|
%tr.build
%td
= ci_icon_for_status(build.status)
%td
= link_to namespace_project_build_path(@project.namespace, @project, build) do
- if build.name
= build.name
- else
%span ##{build.id}
%td.status= build.status #down-build-trace
= render "sidebar"
:javascript :javascript
new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}", "#{trace_with_state[:state]}") new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}", "#{trace_with_state[:state]}")
...@@ -84,6 +84,8 @@ ...@@ -84,6 +84,8 @@
%br %br
%span.descr Enable Container Registry for this repository %span.descr Enable Container Registry for this repository
%hr %hr
= render 'merge_request_settings', f: f
%hr
= render 'builds_settings', f: f = render 'builds_settings', f: f
%hr %hr
%fieldset.features.append-bottom-default %fieldset.features.append-bottom-default
......
%ul.nav-links.sub-nav
%div{ class: (container_class) }
- if project_nav_tab?(:issues) && !current_controller?(:merge_requests)
= nav_link(controller: :issues) do
= link_to url_for_project_issues(@project, only_path: true), title: 'Issues' do
%span
Issues
- if project_nav_tab?(:merge_requests) && current_controller?(:merge_requests)
= nav_link(controller: :merge_requests) do
= link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests' do
%span
Merge Requests
- 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
- @no_container = true
- page_title "Issues" - page_title "Issues"
= render "projects/issues/head"
= content_for :meta_tags do = content_for :meta_tags do
- if current_user - if current_user
= auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") = auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues")
.top-area %div{ class: (container_class) }
.top-area
= render 'shared/issuable/nav', type: :issues = render 'shared/issuable/nav', type: :issues
.nav-controls .nav-controls
- if current_user - if current_user
...@@ -17,7 +20,7 @@ ...@@ -17,7 +20,7 @@
= link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do
New Issue New Issue
= render 'shared/issuable/filter', type: :issues = render 'shared/issuable/filter', type: :issues
.issues-holder .issues-holder
= render "issues" = render "issues"
- @no_container = true
- page_title "Labels" - page_title "Labels"
- hide_class = '' - hide_class = ''
= render "projects/issues/head"
.top-area %div{ class: (container_class) }
.top-area
.nav-text .nav-text
Labels can be applied to issues and merge requests. Labels can be applied to issues and merge requests.
.nav-controls .nav-controls
...@@ -9,7 +12,7 @@ ...@@ -9,7 +12,7 @@
= link_to new_namespace_project_label_path(@project.namespace, @project), class: "btn btn-new" do = link_to new_namespace_project_label_path(@project.namespace, @project), class: "btn btn-new" do
New label New label
.labels .labels
- if can?(current_user, :admin_label, @project) - if can?(current_user, :admin_label, @project)
-# Only show it in the first page -# Only show it in the first page
- hide = @project.labels.empty? || (params[:page].present? && params[:page] != '1') - hide = @project.labels.empty? || (params[:page].present? && params[:page] != '1')
......
.top-tabs
= link_to namespace_project_merge_requests_path(@project.namespace, @project), class: "tab #{'active' if current_page?(namespace_project_merge_requests_path(@project.namespace, @project)) }" do
%span
Merge Requests
- @no_container = true
- page_title "Merge Requests" - page_title "Merge Requests"
= render "projects/issues/head"
= render 'projects/last_push' = render 'projects/last_push'
.top-area %div{ class: (container_class) }
.top-area
= render 'shared/issuable/nav', type: :merge_requests = render 'shared/issuable/nav', type: :merge_requests
.nav-controls .nav-controls
= render 'shared/issuable/search_form', path: namespace_project_merge_requests_path(@project.namespace, @project) = render 'shared/issuable/search_form', path: namespace_project_merge_requests_path(@project.namespace, @project)
...@@ -12,7 +14,7 @@ ...@@ -12,7 +14,7 @@
= link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New Merge Request" do = link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New Merge Request" do
New Merge Request New Merge Request
= render 'shared/issuable/filter', type: :merge_requests = render 'shared/issuable/filter', type: :merge_requests
.merge-requests-holder .merge-requests-holder
= render 'merge_requests' = render 'merge_requests'
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
= render 'projects/merge_requests/widget/open/merge_when_build_succeeds' = render 'projects/merge_requests/widget/open/merge_when_build_succeeds'
- elsif !@merge_request.can_be_merged_by?(current_user) - elsif !@merge_request.can_be_merged_by?(current_user)
= render 'projects/merge_requests/widget/open/not_allowed' = render 'projects/merge_requests/widget/open/not_allowed'
- elsif !@merge_request.mergeable_ci_state? && @pipeline && @pipeline.failed?
= render 'projects/merge_requests/widget/open/build_failed'
- elsif @merge_request.can_be_merged? - elsif @merge_request.can_be_merged?
= render 'projects/merge_requests/widget/open/accept' = render 'projects/merge_requests/widget/open/accept'
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
%span.btn-group %span.btn-group
= button_tag class: "btn btn-create js-merge-button merge_when_build_succeeds" do = button_tag class: "btn btn-create js-merge-button merge_when_build_succeeds" do
Merge When Build Succeeds Merge When Build Succeeds
- unless @project.only_allow_merge_if_build_succeeds?
= button_tag class: "btn btn-success dropdown-toggle", 'data-toggle' => 'dropdown' do = button_tag class: "btn btn-success dropdown-toggle", 'data-toggle' => 'dropdown' do
%span.caret %span.caret
%span.sr-only %span.sr-only
......
%h4
= icon('exclamation-triangle')
The build for this merge request failed
%p
Please retry the build or push a new commit to fix the failure.
- @no_container = true
- page_title "Milestones" - page_title "Milestones"
= render "projects/issues/head"
.top-area %div{ class: (container_class) }
.top-area
= render 'shared/milestones_filter' = render 'shared/milestones_filter'
.nav-controls .nav-controls
...@@ -8,7 +11,7 @@ ...@@ -8,7 +11,7 @@
= link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "btn btn-new", title: "New Milestone" do = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "btn btn-new", title: "New Milestone" do
New Milestone New Milestone
.milestones .milestones
%ul.content-list %ul.content-list
= render @milestones = render @milestones
......
...@@ -3,13 +3,14 @@ ...@@ -3,13 +3,14 @@
<!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch --> <!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
<title>path-1</title> <title>path-1</title>
<desc>Created with Sketch.</desc> <desc>Created with Sketch.</desc>
<defs> <defs></defs>
<path d="M5,0 C4.448,0 4,0.448 4,1 L4,3 L1,3 C0.448,3 0,3.448 0,4 L0,9 C0,9.552 0.448,10 1,10 L5,10 L5,8 L11,8 L11,10 L15,10 C15.552,10 16,9.552 16,9 L16,4 C16,3.448 15.552,3 15,3 L12,3 L12,1 C12,0.448 11.552,0 11,0 L5,0 L5,0 L5,0 Z M6,2.5 C6,2.224 6.224,2 6.5,2 L9.5,2 C9.776,2 10,2.224 10,2.5 C10,2.776 9.776,3 9.5,3 L6.5,3 C6.224,3 6,2.776 6,2.5 L6,2.5 L6,2.5 Z M6,11 L10.001,11 L10.001,9 L6,9 L6,11 L6,11 L6,11 Z M11,11 L11,12 L5,12 L5,11 L1,11 C0.448,11 0,11.448 0,12 L0,15 C0,15.552 0.448,16 1,16 L15,16 C15.552,16 16,15.552 16,15 L16,12 C16,11.448 15.552,11 15,11 L11,11 L11,11 L11,11 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<mask id="mask-2" fill="white"> <g id="_activity" fill="#7E7D7D">
<use xlink:href="#path-1"></use> <g id="Page-1">
</mask> <g id="path-1">
<use id="path-1" fill="#D8D8D8" xlink:href="#path-1"></use> <path d="M5,0 C4.448,0 4,0.448 4,1 L4,3 L1,3 C0.448,3 0,3.448 0,4 L0,9 C0,9.552 0.448,10 1,10 L5,10 L5,8 L11,8 L11,10 L15,10 C15.552,10 16,9.552 16,9 L16,4 C16,3.448 15.552,3 15,3 L12,3 L12,1 C12,0.448 11.552,0 11,0 L5,0 L5,0 L5,0 L5,0 Z M6,2.5 C6,2.224 6.224,2 6.5,2 L9.5,2 C9.776,2 10,2.224 10,2.5 C10,2.776 9.776,3 9.5,3 L6.5,3 C6.224,3 6,2.776 6,2.5 L6,2.5 L6,2.5 L6,2.5 Z M6,11 L10.001,11 L10.001,9 L6,9 L6,11 L6,11 L6,11 L6,11 Z M11,11 L11,12 L5,12 L5,11 L1,11 C0.448,11 0,11.448 0,12 L0,15 C0,15.552 0.448,16 1,16 L15,16 C15.552,16 16,15.552 16,15 L16,12 C16,11.448 15.552,11 15,11 L11,11 L11,11 L11,11 L11,11 Z"></path>
</g>
</g>
</g>
</g> </g>
</svg> </svg>
\ No newline at end of file
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
- filter_placeholder = local_assigns.fetch(:filter_placeholder, 'Search labels') - filter_placeholder = local_assigns.fetch(:filter_placeholder, 'Search labels')
.dropdown-page-one .dropdown-page-one
= dropdown_title(title) = dropdown_title(title)
= dropdown_filter(filter_placeholder) = dropdown_filter(filter_placeholder, search_id: "label-name")
= dropdown_content = dropdown_content
- if @project && show_footer - if @project && show_footer
= dropdown_footer do = dropdown_footer do
......
...@@ -181,7 +181,7 @@ production: &base ...@@ -181,7 +181,7 @@ production: &base
# host: registry.example.com # host: registry.example.com
# port: 5005 # port: 5005
# api_url: http://localhost:5000/ # internal address to the registry, will be used by GitLab to directly communicate with API # api_url: http://localhost:5000/ # internal address to the registry, will be used by GitLab to directly communicate with API
# key_path: config/registry.key # key: config/registry.key
# path: shared/registry # path: shared/registry
# issuer: gitlab-issuer # issuer: gitlab-issuer
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<% <%
require "yaml" require "yaml"
require "json" require "json"
require_relative "lib/gitlab/redis" require_relative "lib/gitlab/redis" unless defined?(Gitlab::Redis)
rails_env = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development" rails_env = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
......
# rubocop:disable all
class InitSchema < ActiveRecord::Migration class InitSchema < ActiveRecord::Migration
def up def up
......
# rubocop:disable all
class RenameOwnerToCreatorForProject < ActiveRecord::Migration class RenameOwnerToCreatorForProject < ActiveRecord::Migration
def change def change
rename_column :projects, :owner_id, :creator_id rename_column :projects, :owner_id, :creator_id
......
# rubocop:disable all
class AddPublicToProject < ActiveRecord::Migration class AddPublicToProject < ActiveRecord::Migration
def change def change
add_column :projects, :public, :boolean, default: false, null: false add_column :projects, :public, :boolean, default: false, null: false
......
# rubocop:disable all
class AddIssuesTrackerToProject < ActiveRecord::Migration class AddIssuesTrackerToProject < ActiveRecord::Migration
def change def change
add_column :projects, :issues_tracker, :string, default: :gitlab, null: false add_column :projects, :issues_tracker, :string, default: :gitlab, null: false
......
# rubocop:disable all
class AddUserPermissions < ActiveRecord::Migration class AddUserPermissions < ActiveRecord::Migration
def up def up
add_column :users, :can_create_group, :boolean, default: true, null: false add_column :users, :can_create_group, :boolean, default: true, null: false
......
# rubocop:disable all
class RemovePrivateFlagFromProject < ActiveRecord::Migration class RemovePrivateFlagFromProject < ActiveRecord::Migration
def up def up
remove_column :projects, :private_flag remove_column :projects, :private_flag
......
# rubocop:disable all
class AddDescriptionToNamsespace < ActiveRecord::Migration class AddDescriptionToNamsespace < ActiveRecord::Migration
def change def change
add_column :namespaces, :description, :string, default: '', null: false add_column :namespaces, :description, :string, default: '', null: false
......
# rubocop:disable all
class AddDescriptionToTeams < ActiveRecord::Migration class AddDescriptionToTeams < ActiveRecord::Migration
def change def change
add_column :user_teams, :description, :string, default: '', null: false add_column :user_teams, :description, :string, default: '', null: false
......
# rubocop:disable all
class AddIssuesTrackerIdToProject < ActiveRecord::Migration class AddIssuesTrackerIdToProject < ActiveRecord::Migration
def change def change
add_column :projects, :issues_tracker_id, :string add_column :projects, :issues_tracker_id, :string
......
# rubocop:disable all
class RenameStateToMergeStatusInMilestone < ActiveRecord::Migration class RenameStateToMergeStatusInMilestone < ActiveRecord::Migration
def change def change
rename_column :merge_requests, :state, :merge_status rename_column :merge_requests, :state, :merge_status
......
# rubocop:disable all
class AddStateToIssue < ActiveRecord::Migration class AddStateToIssue < ActiveRecord::Migration
def change def change
add_column :issues, :state, :string add_column :issues, :state, :string
......
# rubocop:disable all
class AddStateToMergeRequest < ActiveRecord::Migration class AddStateToMergeRequest < ActiveRecord::Migration
def change def change
add_column :merge_requests, :state, :string add_column :merge_requests, :state, :string
......
# rubocop:disable all
class AddStateToMilestone < ActiveRecord::Migration class AddStateToMilestone < ActiveRecord::Migration
def change def change
add_column :milestones, :state, :string add_column :milestones, :state, :string
......
# rubocop:disable all
class ConvertClosedToStateInIssue < ActiveRecord::Migration class ConvertClosedToStateInIssue < ActiveRecord::Migration
include Gitlab::Database include Gitlab::Database
......
# rubocop:disable all
class ConvertClosedToStateInMergeRequest < ActiveRecord::Migration class ConvertClosedToStateInMergeRequest < ActiveRecord::Migration
include Gitlab::Database include Gitlab::Database
......
# rubocop:disable all
class ConvertClosedToStateInMilestone < ActiveRecord::Migration class ConvertClosedToStateInMilestone < ActiveRecord::Migration
include Gitlab::Database include Gitlab::Database
......
# rubocop:disable all
class RemoveMergedFromMergeRequest < ActiveRecord::Migration class RemoveMergedFromMergeRequest < ActiveRecord::Migration
def up def up
remove_column :merge_requests, :merged remove_column :merge_requests, :merged
......
# rubocop:disable all
class RemoveClosedFromIssue < ActiveRecord::Migration class RemoveClosedFromIssue < ActiveRecord::Migration
def up def up
remove_column :issues, :closed remove_column :issues, :closed
......
# rubocop:disable all
class RemoveClosedFromMergeRequest < ActiveRecord::Migration class RemoveClosedFromMergeRequest < ActiveRecord::Migration
def up def up
remove_column :merge_requests, :closed remove_column :merge_requests, :closed
......
# rubocop:disable all
class RemoveClosedFromMilestone < ActiveRecord::Migration class RemoveClosedFromMilestone < ActiveRecord::Migration
def up def up
remove_column :milestones, :closed remove_column :milestones, :closed
......
# rubocop:disable all
class AddNewMergeStatusToMergeRequest < ActiveRecord::Migration class AddNewMergeStatusToMergeRequest < ActiveRecord::Migration
def change def change
add_column :merge_requests, :new_merge_status, :string add_column :merge_requests, :new_merge_status, :string
......
# rubocop:disable all
class ConvertMergeStatusInMergeRequest < ActiveRecord::Migration class ConvertMergeStatusInMergeRequest < ActiveRecord::Migration
def up def up
execute "UPDATE #{table_name} SET new_merge_status = 'unchecked' WHERE merge_status = 1" execute "UPDATE #{table_name} SET new_merge_status = 'unchecked' WHERE merge_status = 1"
......
# rubocop:disable all
class RemoveMergeStatusFromMergeRequest < ActiveRecord::Migration class RemoveMergeStatusFromMergeRequest < ActiveRecord::Migration
def up def up
remove_column :merge_requests, :merge_status remove_column :merge_requests, :merge_status
......
# rubocop:disable all
class RenameNewMergeStatusToMergeStatusInMilestone < ActiveRecord::Migration class RenameNewMergeStatusToMergeStatusInMilestone < ActiveRecord::Migration
def change def change
rename_column :merge_requests, :new_merge_status, :merge_status rename_column :merge_requests, :new_merge_status, :merge_status
......
# rubocop:disable all
class AddStateToUser < ActiveRecord::Migration class AddStateToUser < ActiveRecord::Migration
def change def change
add_column :users, :state, :string add_column :users, :state, :string
......
# rubocop:disable all
class ConvertBlockedToState < ActiveRecord::Migration class ConvertBlockedToState < ActiveRecord::Migration
def up def up
User.transaction do User.transaction do
......
# rubocop:disable all
class RemoveBlockedFromUser < ActiveRecord::Migration class RemoveBlockedFromUser < ActiveRecord::Migration
def up def up
remove_column :users, :blocked remove_column :users, :blocked
......
# rubocop:disable all
class UserColorScheme < ActiveRecord::Migration class UserColorScheme < ActiveRecord::Migration
include Gitlab::Database include Gitlab::Database
......
# rubocop:disable all
class AddSnippetsToFeatures < ActiveRecord::Migration class AddSnippetsToFeatures < ActiveRecord::Migration
def change def change
add_column :projects, :snippets_enabled, :boolean, null: false, default: true add_column :projects, :snippets_enabled, :boolean, null: false, default: true
......
# rubocop:disable all
class CreateForkedProjectLinks < ActiveRecord::Migration class CreateForkedProjectLinks < ActiveRecord::Migration
def change def change
create_table :forked_project_links do |t| create_table :forked_project_links do |t|
......
# rubocop:disable all
class AddPrivateToSnippets < ActiveRecord::Migration class AddPrivateToSnippets < ActiveRecord::Migration
def change def change
add_column :snippets, :private, :boolean, null: false, default: true add_column :snippets, :private, :boolean, null: false, default: true
......
# rubocop:disable all
class AddTypeToSnippets < ActiveRecord::Migration class AddTypeToSnippets < ActiveRecord::Migration
def change def change
add_column :snippets, :type, :string add_column :snippets, :type, :string
......
# rubocop:disable all
class ChangeProjectIdToNullInSnipepts < ActiveRecord::Migration class ChangeProjectIdToNullInSnipepts < ActiveRecord::Migration
def up def up
change_column :snippets, :project_id, :integer, :null => true change_column :snippets, :project_id, :integer, :null => true
......
# rubocop:disable all
class AddTypeValueForSnippets < ActiveRecord::Migration class AddTypeValueForSnippets < ActiveRecord::Migration
def up def up
Snippet.where("project_id IS NOT NULL").update_all(type: 'ProjectSnippet') Snippet.where("project_id IS NOT NULL").update_all(type: 'ProjectSnippet')
......
# rubocop:disable all
class AddNotificationLevelToUser < ActiveRecord::Migration class AddNotificationLevelToUser < ActiveRecord::Migration
def change def change
add_column :users, :notification_level, :integer, null: false, default: 1 add_column :users, :notification_level, :integer, null: false, default: 1
......
# rubocop:disable all
class AddIndexToUsersAuthenticationToken < ActiveRecord::Migration class AddIndexToUsersAuthenticationToken < ActiveRecord::Migration
def change def change
add_index :users, :authentication_token, unique: true add_index :users, :authentication_token, unique: true
......
# rubocop:disable all
class AddLastActivityColumnIntoProject < ActiveRecord::Migration class AddLastActivityColumnIntoProject < ActiveRecord::Migration
def up def up
add_column :projects, :last_activity_at, :datetime add_column :projects, :last_activity_at, :datetime
......
# rubocop:disable all
class AddNotificationLevelToUserProject < ActiveRecord::Migration class AddNotificationLevelToUserProject < ActiveRecord::Migration
def change def change
add_column :users_projects, :notification_level, :integer, null: false, default: 3 add_column :users_projects, :notification_level, :integer, null: false, default: 3
......
# rubocop:disable all
class RemoveWikiTable < ActiveRecord::Migration class RemoveWikiTable < ActiveRecord::Migration
def up def up
drop_table :wikis drop_table :wikis
......
# rubocop:disable all
class AllowMergesForForks < ActiveRecord::Migration class AllowMergesForForks < ActiveRecord::Migration
def self.up def self.up
add_column :merge_requests, :target_project_id, :integer, :null => true add_column :merge_requests, :target_project_id, :integer, :null => true
......
# rubocop:disable all
class AddTypeToKey < ActiveRecord::Migration class AddTypeToKey < ActiveRecord::Migration
def change def change
add_column :keys, :type, :string add_column :keys, :type, :string
......
# rubocop:disable all
class CreateDeployKeysProjects < ActiveRecord::Migration class CreateDeployKeysProjects < ActiveRecord::Migration
def change def change
create_table :deploy_keys_projects do |t| create_table :deploy_keys_projects do |t|
......
# rubocop:disable all
class RemoveProjectIdFromKey < ActiveRecord::Migration class RemoveProjectIdFromKey < ActiveRecord::Migration
def up def up
puts 'Migrate deploy keys: ' puts 'Migrate deploy keys: '
......
# rubocop:disable all
class AddMoreFieldsToService < ActiveRecord::Migration class AddMoreFieldsToService < ActiveRecord::Migration
def change def change
add_column :services, :subdomain, :string add_column :services, :subdomain, :string
......
# rubocop:disable all
class AddSystemToNotes < ActiveRecord::Migration class AddSystemToNotes < ActiveRecord::Migration
class Note < ActiveRecord::Base class Note < ActiveRecord::Base
end end
......
# rubocop:disable all
class IncreaseSnippetTextColumnSize < ActiveRecord::Migration class IncreaseSnippetTextColumnSize < ActiveRecord::Migration
def up def up
# MYSQL LARGETEXT for snippet # MYSQL LARGETEXT for snippet
......
# rubocop:disable all
class AddPasswordExpiresAtToUsers < ActiveRecord::Migration class AddPasswordExpiresAtToUsers < ActiveRecord::Migration
def change def change
add_column :users, :password_expires_at, :datetime add_column :users, :password_expires_at, :datetime
......
# rubocop:disable all
class AddCreatedByIdToUser < ActiveRecord::Migration class AddCreatedByIdToUser < ActiveRecord::Migration
def change def change
add_column :users, :created_by_id, :integer add_column :users, :created_by_id, :integer
......
# rubocop:disable all
class AddImprotedToProject < ActiveRecord::Migration class AddImprotedToProject < ActiveRecord::Migration
def change def change
add_column :projects, :imported, :boolean, default: false, null: false add_column :projects, :imported, :boolean, default: false, null: false
......
# rubocop:disable all
class CreateUsersGroups < ActiveRecord::Migration class CreateUsersGroups < ActiveRecord::Migration
def change def change
create_table :users_groups do |t| create_table :users_groups do |t|
......
# rubocop:disable all
class AddNotificationLevelToUserGroup < ActiveRecord::Migration class AddNotificationLevelToUserGroup < ActiveRecord::Migration
def change def change
add_column :users_groups, :notification_level, :integer, null: false, default: 3 add_column :users_groups, :notification_level, :integer, null: false, default: 3
......
# rubocop:disable all
class AddMoreDbIndex < ActiveRecord::Migration class AddMoreDbIndex < ActiveRecord::Migration
def change def change
add_index :deploy_keys_projects, :project_id add_index :deploy_keys_projects, :project_id
......
# rubocop:disable all
class AddFingerprintToKey < ActiveRecord::Migration class AddFingerprintToKey < ActiveRecord::Migration
def change def change
add_column :keys, :fingerprint, :string add_column :keys, :fingerprint, :string
......
# rubocop:disable all
class CreateProjectGroupLinks < ActiveRecord::Migration class CreateProjectGroupLinks < ActiveRecord::Migration
def change def change
create_table :project_group_links do |t| create_table :project_group_links do |t|
......
# rubocop:disable all
class AddStDiffToNote < ActiveRecord::Migration class AddStDiffToNote < ActiveRecord::Migration
def change def change
add_column :notes, :st_diff, :text, :null => true add_column :notes, :st_diff, :text, :null => true
......
# rubocop:disable all
class AddPermissionCheckToUser < ActiveRecord::Migration class AddPermissionCheckToUser < ActiveRecord::Migration
def change def change
add_column :users, :last_credential_check_at, :datetime add_column :users, :last_credential_check_at, :datetime
......
# rubocop:disable all
class AddImportUrlToProject < ActiveRecord::Migration class AddImportUrlToProject < ActiveRecord::Migration
def change def change
add_column :projects, :import_url, :string add_column :projects, :import_url, :string
......
# rubocop:disable all
class AddInternalIdsToIssuesAndMr < ActiveRecord::Migration class AddInternalIdsToIssuesAndMr < ActiveRecord::Migration
def change def change
add_column :issues, :iid, :integer add_column :issues, :iid, :integer
......
# rubocop:disable all
class AddAccessToProjectGroupLink < ActiveRecord::Migration class AddAccessToProjectGroupLink < ActiveRecord::Migration
def change def change
add_column :project_group_links, :group_access, :integer, null: false, default: ProjectGroupLink.default_access add_column :project_group_links, :group_access, :integer, null: false, default: ProjectGroupLink.default_access
......
# rubocop:disable all
class RemoveDeprecatedTables < ActiveRecord::Migration class RemoveDeprecatedTables < ActiveRecord::Migration
def up def up
drop_table :user_teams drop_table :user_teams
......
# rubocop:disable all
class AddInternalIdsToMilestones < ActiveRecord::Migration class AddInternalIdsToMilestones < ActiveRecord::Migration
def change def change
add_column :milestones, :iid, :integer add_column :milestones, :iid, :integer
......
# rubocop:disable all
class AddDescriptionToMergeRequest < ActiveRecord::Migration class AddDescriptionToMergeRequest < ActiveRecord::Migration
def change def change
add_column :merge_requests, :description, :text, null: true add_column :merge_requests, :description, :text, null: true
......
# rubocop:disable all
class ChangeOwnerIdForGroup < ActiveRecord::Migration class ChangeOwnerIdForGroup < ActiveRecord::Migration
def up def up
change_column :namespaces, :owner_id, :integer, null: true change_column :namespaces, :owner_id, :integer, null: true
......
# rubocop:disable all
class AddAvatarToUsers < ActiveRecord::Migration class AddAvatarToUsers < ActiveRecord::Migration
def change def change
add_column :users, :avatar, :string add_column :users, :avatar, :string
......
# rubocop:disable all
class AddConfirmableToUsers < ActiveRecord::Migration class AddConfirmableToUsers < ActiveRecord::Migration
def self.up def self.up
add_column :users, :confirmation_token, :string add_column :users, :confirmation_token, :string
......
# rubocop:disable all
class RemoveDefaultBranch < ActiveRecord::Migration class RemoveDefaultBranch < ActiveRecord::Migration
def up def up
remove_column :projects, :default_branch remove_column :projects, :default_branch
......
# rubocop:disable all
class CreateBroadcastMessages < ActiveRecord::Migration class CreateBroadcastMessages < ActiveRecord::Migration
def change def change
create_table :broadcast_messages do |t| create_table :broadcast_messages do |t|
......
# rubocop:disable all
class AddVisibilityLevelToProjects < ActiveRecord::Migration class AddVisibilityLevelToProjects < ActiveRecord::Migration
include Gitlab::Database include Gitlab::Database
......
# rubocop:disable all
class AddArchivedToProjects < ActiveRecord::Migration class AddArchivedToProjects < ActiveRecord::Migration
def change def change
add_column :projects, :archived, :boolean, default: false, null: false add_column :projects, :archived, :boolean, default: false, null: false
......
# rubocop:disable all
class AddColorAndFontToBroadcastMessages < ActiveRecord::Migration class AddColorAndFontToBroadcastMessages < ActiveRecord::Migration
def change def change
add_column :broadcast_messages, :color, :string add_column :broadcast_messages, :color, :string
......
# rubocop:disable all
class AddEventFieldsForWebHook < ActiveRecord::Migration class AddEventFieldsForWebHook < ActiveRecord::Migration
def change def change
add_column :web_hooks, :push_events, :boolean, default: true, null: false add_column :web_hooks, :push_events, :boolean, default: true, null: false
......
# rubocop:disable all
class AddHideNoSshKeyToUsers < ActiveRecord::Migration class AddHideNoSshKeyToUsers < ActiveRecord::Migration
def change def change
add_column :users, :hide_no_ssh_key, :boolean, :default => false add_column :users, :hide_no_ssh_key, :boolean, :default => false
......
# rubocop:disable all
class AddRecipientsToService < ActiveRecord::Migration class AddRecipientsToService < ActiveRecord::Migration
def change def change
add_column :services, :recipients, :text add_column :services, :recipients, :text
......
# rubocop:disable all
class AddWebsiteUrlToUsers < ActiveRecord::Migration class AddWebsiteUrlToUsers < ActiveRecord::Migration
def change def change
add_column :users, :website_url, :string, {:null => false, :default => ''} add_column :users, :website_url, :string, {:null => false, :default => ''}
......
# rubocop:disable all
class CreateMergeRequestDiffs < ActiveRecord::Migration class CreateMergeRequestDiffs < ActiveRecord::Migration
def up def up
create_table :merge_request_diffs do |t| create_table :merge_request_diffs do |t|
......
# rubocop:disable all
class MigrateMrDiffs < ActiveRecord::Migration class MigrateMrDiffs < ActiveRecord::Migration
def self.up def self.up
execute "INSERT INTO merge_request_diffs ( merge_request_id, st_commits, st_diffs ) SELECT id, st_commits, st_diffs FROM merge_requests" execute "INSERT INTO merge_request_diffs ( merge_request_id, st_commits, st_diffs ) SELECT id, st_commits, st_diffs FROM merge_requests"
......
# rubocop:disable all
class RemoveMRdiffFields < ActiveRecord::Migration class RemoveMRdiffFields < ActiveRecord::Migration
def up def up
remove_column :merge_requests, :st_commits remove_column :merge_requests, :st_commits
......
# rubocop:disable all
class AddAvatarToProjects < ActiveRecord::Migration class AddAvatarToProjects < ActiveRecord::Migration
def change def change
add_column :projects, :avatar, :string add_column :projects, :avatar, :string
......
# rubocop:disable all
class AddGroupAvatars < ActiveRecord::Migration class AddGroupAvatars < ActiveRecord::Migration
def change def change
add_column :namespaces, :avatar, :string add_column :namespaces, :avatar, :string
......
# rubocop:disable all
class CreateEmails < ActiveRecord::Migration class CreateEmails < ActiveRecord::Migration
def change def change
create_table :emails do |t| create_table :emails do |t|
......
# rubocop:disable all
class AddApiKeyToServices < ActiveRecord::Migration class AddApiKeyToServices < ActiveRecord::Migration
def change def change
add_column :services, :api_key, :string add_column :services, :api_key, :string
......
# rubocop:disable all
class AddIndexMergeRequestDiffsOnMergeRequestId < ActiveRecord::Migration class AddIndexMergeRequestDiffsOnMergeRequestId < ActiveRecord::Migration
def change def change
add_index :merge_request_diffs, :merge_request_id, unique: true add_index :merge_request_diffs, :merge_request_id, unique: true
......
# rubocop:disable all
class AddTagPushHooksToProjectHook < ActiveRecord::Migration class AddTagPushHooksToProjectHook < ActiveRecord::Migration
def change def change
add_column :web_hooks, :tag_push_events, :boolean, default: false add_column :web_hooks, :tag_push_events, :boolean, default: false
......
# rubocop:disable all
class AddImportStatusToProject < ActiveRecord::Migration class AddImportStatusToProject < ActiveRecord::Migration
def change def change
add_column :projects, :import_status, :string add_column :projects, :import_status, :string
......
# rubocop:disable all
class MigrateAlreadyImportedProjects < ActiveRecord::Migration class MigrateAlreadyImportedProjects < ActiveRecord::Migration
include Gitlab::Database include Gitlab::Database
......
# rubocop:disable all
class FixNamespaces < ActiveRecord::Migration class FixNamespaces < ActiveRecord::Migration
def up def up
Namespace.where('name <> path and type is null').each do |namespace| Namespace.where('name <> path and type is null').each do |namespace|
......
# rubocop:disable all
class ChangeStateToAllowEmptyMergeRequestDiffs < ActiveRecord::Migration class ChangeStateToAllowEmptyMergeRequestDiffs < ActiveRecord::Migration
def up def up
change_column :merge_request_diffs, :state, :string, null: true, change_column :merge_request_diffs, :state, :string, null: true,
......
# rubocop:disable all
require_relative 'limits_to_mysql' require_relative 'limits_to_mysql'
# rubocop:disable all
class AddIndexOnIid < ActiveRecord::Migration class AddIndexOnIid < ActiveRecord::Migration
def change def change
RemoveDuplicateIid.clean(Issue) RemoveDuplicateIid.clean(Issue)
......
# rubocop:disable all
class IndexOnCurrentSignInAt < ActiveRecord::Migration class IndexOnCurrentSignInAt < ActiveRecord::Migration
def change def change
add_index :users, :current_sign_in_at add_index :users, :current_sign_in_at
......
# rubocop:disable all
class AddNotesIndexUpdatedAt < ActiveRecord::Migration class AddNotesIndexUpdatedAt < ActiveRecord::Migration
def change def change
add_index :notes, :updated_at add_index :notes, :updated_at
......
# rubocop:disable all
class AddRepoSizeToDb < ActiveRecord::Migration class AddRepoSizeToDb < ActiveRecord::Migration
def change def change
add_column :projects, :repository_size, :float, default: 0 add_column :projects, :repository_size, :float, default: 0
......
# rubocop:disable all
class MigrateRepoSize < ActiveRecord::Migration class MigrateRepoSize < ActiveRecord::Migration
def up def up
project_data = execute('SELECT projects.id, namespaces.path AS namespace_path, projects.path AS project_path FROM projects LEFT JOIN namespaces ON projects.namespace_id = namespaces.id') project_data = execute('SELECT projects.id, namespaces.path AS namespace_path, projects.path AS project_path FROM projects LEFT JOIN namespaces ON projects.namespace_id = namespaces.id')
......
# rubocop:disable all
class AddPositionToMergeRequest < ActiveRecord::Migration class AddPositionToMergeRequest < ActiveRecord::Migration
def change def change
add_column :merge_requests, :position, :integer, default: 0 add_column :merge_requests, :position, :integer, default: 0
......
# rubocop:disable all
class CreateUsersStarProjects < ActiveRecord::Migration class CreateUsersStarProjects < ActiveRecord::Migration
def change def change
create_table :users_star_projects do |t| create_table :users_star_projects do |t|
......
# rubocop:disable all
class CreateLabels < ActiveRecord::Migration class CreateLabels < ActiveRecord::Migration
def change def change
create_table :labels do |t| create_table :labels do |t|
......
# rubocop:disable all
class CreateLabelLinks < ActiveRecord::Migration class CreateLabelLinks < ActiveRecord::Migration
def change def change
create_table :label_links do |t| create_table :label_links do |t|
......
# rubocop:disable all
class MigrateProjectTags < ActiveRecord::Migration class MigrateProjectTags < ActiveRecord::Migration
def up def up
ActsAsTaggableOn::Tagging.where(taggable_type: 'Project', context: 'labels').update_all(context: 'tags') ActsAsTaggableOn::Tagging.where(taggable_type: 'Project', context: 'labels').update_all(context: 'tags')
......
# rubocop:disable all
class MigrateTaggableLabels < ActiveRecord::Migration class MigrateTaggableLabels < ActiveRecord::Migration
def up def up
taggings = ActsAsTaggableOn::Tagging.where(taggable_type: ['Issue', 'MergeRequest'], context: 'labels') taggings = ActsAsTaggableOn::Tagging.where(taggable_type: ['Issue', 'MergeRequest'], context: 'labels')
......
# rubocop:disable all
class AddIndexToLabels < ActiveRecord::Migration class AddIndexToLabels < ActiveRecord::Migration
def change def change
add_index "labels", :project_id add_index "labels", :project_id
......
# rubocop:disable all
class MigrateToNewShell < ActiveRecord::Migration class MigrateToNewShell < ActiveRecord::Migration
def change def change
return if Rails.env.test? return if Rails.env.test?
......
# rubocop:disable all
class SerializeServiceProperties < ActiveRecord::Migration class SerializeServiceProperties < ActiveRecord::Migration
def change def change
unless column_exists?(:services, :properties) unless column_exists?(:services, :properties)
......
# rubocop:disable all
class AddMembersTable < ActiveRecord::Migration class AddMembersTable < ActiveRecord::Migration
def change def change
create_table :members do |t| create_table :members do |t|
......
# rubocop:disable all
class MigrateToNewMembersModel < ActiveRecord::Migration class MigrateToNewMembersModel < ActiveRecord::Migration
def up def up
execute "INSERT INTO members ( user_id, source_id, source_type, access_level, notification_level, type ) SELECT user_id, group_id, 'Namespace', group_access, notification_level, 'GroupMember' FROM users_groups" execute "INSERT INTO members ( user_id, source_id, source_type, access_level, notification_level, type ) SELECT user_id, group_id, 'Namespace', group_access, notification_level, 'GroupMember' FROM users_groups"
......
# rubocop:disable all
class RemoveOldMemberTables < ActiveRecord::Migration class RemoveOldMemberTables < ActiveRecord::Migration
def up def up
drop_table :users_groups drop_table :users_groups
......
# rubocop:disable all
class MoveSlackServiceToWebhook < ActiveRecord::Migration class MoveSlackServiceToWebhook < ActiveRecord::Migration
def change def change
SlackService.all.each do |slack_service| SlackService.all.each do |slack_service|
......
# rubocop:disable all
class AddVisibilityLevelToSnippet < ActiveRecord::Migration class AddVisibilityLevelToSnippet < ActiveRecord::Migration
include Gitlab::Database include Gitlab::Database
......
# rubocop:disable all
class AddAuditEvent < ActiveRecord::Migration class AddAuditEvent < ActiveRecord::Migration
def change def change
create_table :audit_events do |t| create_table :audit_events do |t|
......
# rubocop:disable all
# In 20140914145549_migrate_to_new_members_model.rb we forgot to set the # In 20140914145549_migrate_to_new_members_model.rb we forgot to set the
# created_at and updated_at times for new records in the 'members' table. This # created_at and updated_at times for new records in the 'members' table. This
# became a problem after commit c8e78d972a5a628870eefca0f2ccea0199c55bda which # became a problem after commit c8e78d972a5a628870eefca0f2ccea0199c55bda which
......
# rubocop:disable all
class AddIdentityTable < ActiveRecord::Migration class AddIdentityTable < ActiveRecord::Migration
def up def up
create_table :identities do |t| create_table :identities do |t|
......
# rubocop:disable all
class AddLockedAtToMergeRequest < ActiveRecord::Migration class AddLockedAtToMergeRequest < ActiveRecord::Migration
def change def change
add_column :merge_requests, :locked_at, :datetime add_column :merge_requests, :locked_at, :datetime
......
# rubocop:disable all
class CreateDoorkeeperTables < ActiveRecord::Migration class CreateDoorkeeperTables < ActiveRecord::Migration
def change def change
create_table :oauth_applications do |t| create_table :oauth_applications do |t|
......
# rubocop:disable all
class AddOwnerToApplication < ActiveRecord::Migration class AddOwnerToApplication < ActiveRecord::Migration
def change def change
add_column :oauth_applications, :owner_id, :integer, null: true add_column :oauth_applications, :owner_id, :integer, null: true
......
# rubocop:disable all
class AddImportDataToProjectTable < ActiveRecord::Migration class AddImportDataToProjectTable < ActiveRecord::Migration
def change def change
add_column :projects, :import_type, :string add_column :projects, :import_type, :string
......
# rubocop:disable all
class AddDevelopersCanPushToProtectedBranches < ActiveRecord::Migration class AddDevelopersCanPushToProtectedBranches < ActiveRecord::Migration
def change def change
add_column :protected_branches, :developers_can_push, :boolean, default: false, null: false add_column :protected_branches, :developers_can_push, :boolean, default: false, null: false
......
# rubocop:disable all
class CreateApplicationSettings < ActiveRecord::Migration class CreateApplicationSettings < ActiveRecord::Migration
def change def change
create_table :application_settings do |t| create_table :application_settings do |t|
......
# rubocop:disable all
class AddHomePageUrlForApplicationSettings < ActiveRecord::Migration class AddHomePageUrlForApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :home_page_url, :string add_column :application_settings, :home_page_url, :string
......
# rubocop:disable all
class AddGitlabAccessTokenToUser < ActiveRecord::Migration class AddGitlabAccessTokenToUser < ActiveRecord::Migration
def change def change
add_column :users, :gitlab_access_token, :string add_column :users, :gitlab_access_token, :string
......
# rubocop:disable all
class AddDefaultBranchProtectionSetting < ActiveRecord::Migration class AddDefaultBranchProtectionSetting < ActiveRecord::Migration
def change def change
add_column :application_settings, :default_branch_protection, :integer, :default => 2 add_column :application_settings, :default_branch_protection, :integer, :default => 2
......
# rubocop:disable all
class AddTimestampsToIdentities < ActiveRecord::Migration class AddTimestampsToIdentities < ActiveRecord::Migration
def change def change
add_timestamps(:identities) add_timestamps(:identities)
......
# rubocop:disable all
class AddIndexToCreatedAt < ActiveRecord::Migration class AddIndexToCreatedAt < ActiveRecord::Migration
def change def change
add_index "users", [:created_at, :id] add_index "users", [:created_at, :id]
......
# rubocop:disable all
class AddNotificationEmailToUser < ActiveRecord::Migration class AddNotificationEmailToUser < ActiveRecord::Migration
def up def up
add_column :users, :notification_email, :string add_column :users, :notification_email, :string
......
# rubocop:disable all
class AddMissingIndex < ActiveRecord::Migration class AddMissingIndex < ActiveRecord::Migration
def change def change
add_index "services", [:created_at, :id] add_index "services", [:created_at, :id]
......
# rubocop:disable all
class AddTemplateToService < ActiveRecord::Migration class AddTemplateToService < ActiveRecord::Migration
def change def change
add_column :services, :template, :boolean, default: false add_column :services, :template, :boolean, default: false
......
# rubocop:disable all
class AllowNullInServicesProjectId < ActiveRecord::Migration class AllowNullInServicesProjectId < ActiveRecord::Migration
def change def change
change_column :services, :project_id, :integer, null: true change_column :services, :project_id, :integer, null: true
......
# rubocop:disable all
class AddTwitterSharingEnabledToApplicationSettings < ActiveRecord::Migration class AddTwitterSharingEnabledToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :twitter_sharing_enabled, :boolean, default: true add_column :application_settings, :twitter_sharing_enabled, :boolean, default: true
......
# rubocop:disable all
class AddHideNoPasswordToUser < ActiveRecord::Migration class AddHideNoPasswordToUser < ActiveRecord::Migration
def change def change
add_column :users, :hide_no_password, :boolean, default: false add_column :users, :hide_no_password, :boolean, default: false
......
# rubocop:disable all
class AddPasswordAutomaticallySetToUser < ActiveRecord::Migration class AddPasswordAutomaticallySetToUser < ActiveRecord::Migration
def change def change
add_column :users, :password_automatically_set, :boolean, default: false add_column :users, :password_automatically_set, :boolean, default: false
......
# rubocop:disable all
class AddBitbucketAccessTokenAndSecretToUser < ActiveRecord::Migration class AddBitbucketAccessTokenAndSecretToUser < ActiveRecord::Migration
def change def change
add_column :users, :bitbucket_access_token, :string add_column :users, :bitbucket_access_token, :string
......
# rubocop:disable all
class AddEventsToServices < ActiveRecord::Migration class AddEventsToServices < ActiveRecord::Migration
def change def change
add_column :services, :push_events, :boolean, :default => true add_column :services, :push_events, :boolean, :default => true
......
# rubocop:disable all
class SetMissingLastActivityAt < ActiveRecord::Migration class SetMissingLastActivityAt < ActiveRecord::Migration
def up def up
execute "UPDATE projects SET last_activity_at = updated_at WHERE last_activity_at IS NULL" execute "UPDATE projects SET last_activity_at = updated_at WHERE last_activity_at IS NULL"
......
# rubocop:disable all
class AddNoteEventsToServices < ActiveRecord::Migration class AddNoteEventsToServices < ActiveRecord::Migration
def change def change
add_column :services, :note_events, :boolean, default: true, null: false add_column :services, :note_events, :boolean, default: true, null: false
......
# rubocop:disable all
class AddRestrictedVisibilityLevelsToApplicationSettings < ActiveRecord::Migration class AddRestrictedVisibilityLevelsToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :restricted_visibility_levels, :text add_column :application_settings, :restricted_visibility_levels, :text
......
# rubocop:disable all
class FixNamespaceDuplication < ActiveRecord::Migration class FixNamespaceDuplication < ActiveRecord::Migration
def up def up
#fixes path duplication #fixes path duplication
......
# rubocop:disable all
class AddUniqueIndexToNamespace < ActiveRecord::Migration class AddUniqueIndexToNamespace < ActiveRecord::Migration
def change def change
remove_index :namespaces, column: :name if index_exists?(:namespaces, :name) remove_index :namespaces, column: :name if index_exists?(:namespaces, :name)
......
# rubocop:disable all
class AddVersionCheckToApplicationSettings < ActiveRecord::Migration class AddVersionCheckToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :version_check_enabled, :boolean, default: true add_column :application_settings, :version_check_enabled, :boolean, default: true
......
# rubocop:disable all
class CreateSubscriptionsTable < ActiveRecord::Migration class CreateSubscriptionsTable < ActiveRecord::Migration
def change def change
create_table :subscriptions do |t| create_table :subscriptions do |t|
......
# rubocop:disable all
class AddLocationToUser < ActiveRecord::Migration class AddLocationToUser < ActiveRecord::Migration
def change def change
add_column :users, :location, :string add_column :users, :location, :string
......
# rubocop:disable all
class SetIncorrectAssigneeIdToNull < ActiveRecord::Migration class SetIncorrectAssigneeIdToNull < ActiveRecord::Migration
def up def up
execute "UPDATE issues SET assignee_id = NULL WHERE assignee_id = -1" execute "UPDATE issues SET assignee_id = NULL WHERE assignee_id = -1"
......
# rubocop:disable all
class AddPublicToKey < ActiveRecord::Migration class AddPublicToKey < ActiveRecord::Migration
def change def change
add_column :keys, :public, :boolean, default: false, null: false add_column :keys, :public, :boolean, default: false, null: false
......
# rubocop:disable all
class AddImportDataToProject < ActiveRecord::Migration class AddImportDataToProject < ActiveRecord::Migration
def change def change
add_column :projects, :import_data, :text add_column :projects, :import_data, :text
......
# rubocop:disable all
class AddDeviseTwoFactorToUsers < ActiveRecord::Migration class AddDeviseTwoFactorToUsers < ActiveRecord::Migration
def change def change
add_column :users, :encrypted_otp_secret, :string add_column :users, :encrypted_otp_secret, :string
......
# rubocop:disable all
class AddMaxAttachmentSizeToApplicationSettings < ActiveRecord::Migration class AddMaxAttachmentSizeToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :max_attachment_size, :integer, default: 10, null: false add_column :application_settings, :max_attachment_size, :integer, default: 10, null: false
......
# rubocop:disable all
class AddDeviseTwoFactorBackupableToUsers < ActiveRecord::Migration class AddDeviseTwoFactorBackupableToUsers < ActiveRecord::Migration
def change def change
add_column :users, :otp_backup_codes, :text add_column :users, :otp_backup_codes, :text
......
# rubocop:disable all
class AddInviteDataToMember < ActiveRecord::Migration class AddInviteDataToMember < ActiveRecord::Migration
def up def up
add_column :members, :created_by_id, :integer add_column :members, :created_by_id, :integer
......
# rubocop:disable all
class FixIdentities < ActiveRecord::Migration class FixIdentities < ActiveRecord::Migration
def up def up
# Up until now, legacy 'ldap' references in the database were charitably # Up until now, legacy 'ldap' references in the database were charitably
......
# rubocop:disable all
class RenameBuildboxService < ActiveRecord::Migration class RenameBuildboxService < ActiveRecord::Migration
def up def up
execute "UPDATE services SET type = 'BuildkiteService' WHERE type = 'BuildboxService';" execute "UPDATE services SET type = 'BuildkiteService' WHERE type = 'BuildboxService';"
......
# rubocop:disable all
class AddPublicEmailToUsers < ActiveRecord::Migration class AddPublicEmailToUsers < ActiveRecord::Migration
def change def change
add_column :users, :public_email, :string, default: "", null: false add_column :users, :public_email, :string, default: "", null: false
......
# rubocop:disable all
class CreateProjectImportData < ActiveRecord::Migration class CreateProjectImportData < ActiveRecord::Migration
def change def change
create_table :project_import_data do |t| create_table :project_import_data do |t|
......
# rubocop:disable all
class RemoveImportDataFromProject < ActiveRecord::Migration class RemoveImportDataFromProject < ActiveRecord::Migration
def up def up
remove_column :projects, :import_data remove_column :projects, :import_data
......
# rubocop:disable all
class RemovePeriodsAtEndsOfUsernames < ActiveRecord::Migration class RemovePeriodsAtEndsOfUsernames < ActiveRecord::Migration
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
......
# rubocop:disable all
class AddDefaultProjectVisibililtyToApplicationSettings < ActiveRecord::Migration class AddDefaultProjectVisibililtyToApplicationSettings < ActiveRecord::Migration
def up def up
add_column :application_settings, :default_project_visibility, :integer add_column :application_settings, :default_project_visibility, :integer
......
# rubocop:disable all
# This migration is a duplicate of 20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb # This migration is a duplicate of 20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
# It shold be applied before the index additions to ensure that `name` is case sensitive. # It shold be applied before the index additions to ensure that `name` is case sensitive.
......
# rubocop:disable all
class RemoveDuplicateTags < ActiveRecord::Migration class RemoveDuplicateTags < ActiveRecord::Migration
def up def up
select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(id) > 1").each do |tag| select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(id) > 1").each do |tag|
......
# rubocop:disable all
# This migration comes from acts_as_taggable_on_engine (originally 2) # This migration comes from acts_as_taggable_on_engine (originally 2)
class AddMissingUniqueIndices < ActiveRecord::Migration class AddMissingUniqueIndices < ActiveRecord::Migration
def self.up def self.up
......
# rubocop:disable all
# This migration comes from acts_as_taggable_on_engine (originally 3) # This migration comes from acts_as_taggable_on_engine (originally 3)
class AddTaggingsCounterCacheToTags < ActiveRecord::Migration class AddTaggingsCounterCacheToTags < ActiveRecord::Migration
def self.up def self.up
......
# rubocop:disable all
# This migration comes from acts_as_taggable_on_engine (originally 4) # This migration comes from acts_as_taggable_on_engine (originally 4)
class AddMissingTaggableIndex < ActiveRecord::Migration class AddMissingTaggableIndex < ActiveRecord::Migration
def self.up def self.up
......
# rubocop:disable all
# This migration comes from acts_as_taggable_on_engine (originally 5) # This migration comes from acts_as_taggable_on_engine (originally 5)
# This migration is added to circumvent issue #623 and have special characters # This migration is added to circumvent issue #623 and have special characters
# work properly # work properly
......
# rubocop:disable all
class AddDefaultSnippetVisibilityToAppSettings < ActiveRecord::Migration class AddDefaultSnippetVisibilityToAppSettings < ActiveRecord::Migration
def up def up
add_column :application_settings, :default_snippet_visibility, :integer add_column :application_settings, :default_snippet_visibility, :integer
......
# rubocop:disable all
class RemoveAbandonedGroupMembersRecords < ActiveRecord::Migration class RemoveAbandonedGroupMembersRecords < ActiveRecord::Migration
def up def up
execute("DELETE FROM members WHERE type = 'GroupMember' AND source_id NOT IN(\ execute("DELETE FROM members WHERE type = 'GroupMember' AND source_id NOT IN(\
......
# rubocop:disable all
class AddRestrictedSignupDomainsToApplicationSettings < ActiveRecord::Migration class AddRestrictedSignupDomainsToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :restricted_signup_domains, :text add_column :application_settings, :restricted_signup_domains, :text
......
# rubocop:disable all
# Convert legacy Markdown-emphasized notes to the current, non-emphasized format # Convert legacy Markdown-emphasized notes to the current, non-emphasized format
# #
# _mentioned in 54f7727c850972f0401c1312a7c4a6a380de5666_ # _mentioned in 54f7727c850972f0401c1312a7c4a6a380de5666_
......
# rubocop:disable all
class AddNoteEventsToWebHooks < ActiveRecord::Migration class AddNoteEventsToWebHooks < ActiveRecord::Migration
def up def up
add_column :web_hooks, :note_events, :boolean, default: false, null: false add_column :web_hooks, :note_events, :boolean, default: false, null: false
......
# rubocop:disable all
class AddUserOauthApplicationsToApplicationSettings < ActiveRecord::Migration class AddUserOauthApplicationsToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :user_oauth_applications, :bool, default: true add_column :application_settings, :user_oauth_applications, :bool, default: true
......
# rubocop:disable all
class AddAfterSignOutPathForApplicationSettings < ActiveRecord::Migration class AddAfterSignOutPathForApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :after_sign_out_path, :string add_column :application_settings, :after_sign_out_path, :string
......
# rubocop:disable all
class AddSessionExpireDelayForApplicationSettings < ActiveRecord::Migration class AddSessionExpireDelayForApplicationSettings < ActiveRecord::Migration
def change def change
unless column_exists?(:application_settings, :session_expire_delay) unless column_exists?(:application_settings, :session_expire_delay)
......
# rubocop:disable all
class AddDashboardToUsers < ActiveRecord::Migration class AddDashboardToUsers < ActiveRecord::Migration
def up def up
add_column :users, :dashboard, :integer, default: 0 add_column :users, :dashboard, :integer, default: 0
......
# rubocop:disable all
class AddDefaultOtpRequiredForLoginValue < ActiveRecord::Migration class AddDefaultOtpRequiredForLoginValue < ActiveRecord::Migration
def up def up
execute %q{UPDATE users SET otp_required_for_login = FALSE WHERE otp_required_for_login IS NULL} execute %q{UPDATE users SET otp_required_for_login = FALSE WHERE otp_required_for_login IS NULL}
......
# rubocop:disable all
class AddProjectViewToUsers < ActiveRecord::Migration class AddProjectViewToUsers < ActiveRecord::Migration
def change def change
add_column :users, :project_view, :integer, default: 0 add_column :users, :project_view, :integer, default: 0
......
# rubocop:disable all
class AddCommitsCountToProject < ActiveRecord::Migration class AddCommitsCountToProject < ActiveRecord::Migration
def change def change
add_column :projects, :commit_count, :integer, default: 0 add_column :projects, :commit_count, :integer, default: 0
......
# rubocop:disable all
class AddUpdatedByToIssuablesAndNotes < ActiveRecord::Migration class AddUpdatedByToIssuablesAndNotes < ActiveRecord::Migration
def change def change
add_column :notes, :updated_by_id, :integer add_column :notes, :updated_by_id, :integer
......
# rubocop:disable all
class CreateAbuseReports < ActiveRecord::Migration class CreateAbuseReports < ActiveRecord::Migration
def change def change
create_table :abuse_reports do |t| create_table :abuse_reports do |t|
......
# rubocop:disable all
require 'yaml' require 'yaml'
class AddSettingsImportSources < ActiveRecord::Migration class AddSettingsImportSources < ActiveRecord::Migration
......
# rubocop:disable all
class RemoveOauthTokensFromUsers < ActiveRecord::Migration class RemoveOauthTokensFromUsers < ActiveRecord::Migration
def change def change
remove_column :users, :github_access_token, :string remove_column :users, :github_access_token, :string
......
# rubocop:disable all
class DeduplicateUserIdentities < ActiveRecord::Migration class DeduplicateUserIdentities < ActiveRecord::Migration
def change def change
execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;' execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;'
......
# rubocop:disable all
class AddSentNotifications < ActiveRecord::Migration class AddSentNotifications < ActiveRecord::Migration
def change def change
create_table :sent_notifications do |t| create_table :sent_notifications do |t|
......
# rubocop:disable all
class AddEnableSslVerification < ActiveRecord::Migration class AddEnableSslVerification < ActiveRecord::Migration
def change def change
add_column :web_hooks, :enable_ssl_verification, :boolean, default: false add_column :web_hooks, :enable_ssl_verification, :boolean, default: false
......
# rubocop:disable all
class AddCiTables < ActiveRecord::Migration class AddCiTables < ActiveRecord::Migration
def change def change
create_table "ci_application_settings", force: true do |t| create_table "ci_application_settings", force: true do |t|
......
# rubocop:disable all
class AddTemplateToLabel < ActiveRecord::Migration class AddTemplateToLabel < ActiveRecord::Migration
def change def change
add_column :labels, :template, :boolean, default: false add_column :labels, :template, :boolean, default: false
......
# rubocop:disable all
class AddCiTags < ActiveRecord::Migration class AddCiTags < ActiveRecord::Migration
def change def change
create_table "ci_taggings", force: true do |t| create_table "ci_taggings", force: true do |t|
......
# rubocop:disable all
class EnableSslVerificationByDefault < ActiveRecord::Migration class EnableSslVerificationByDefault < ActiveRecord::Migration
def change def change
change_column :web_hooks, :enable_ssl_verification, :boolean, default: true change_column :web_hooks, :enable_ssl_verification, :boolean, default: true
......
# rubocop:disable all
class EnableSslVerificationForWebHooks < ActiveRecord::Migration class EnableSslVerificationForWebHooks < ActiveRecord::Migration
def up def up
execute("UPDATE web_hooks SET enable_ssl_verification = true") execute("UPDATE web_hooks SET enable_ssl_verification = true")
......
# rubocop:disable all
class AddHelpPageTextToApplicationSettings < ActiveRecord::Migration class AddHelpPageTextToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :help_page_text, :text add_column :application_settings, :help_page_text, :text
......
# rubocop:disable all
class AddIndexForCommittedAtAndId < ActiveRecord::Migration class AddIndexForCommittedAtAndId < ActiveRecord::Migration
def change def change
add_index :ci_commits, [:project_id, :committed_at, :id] add_index :ci_commits, [:project_id, :committed_at, :id]
......
# rubocop:disable all
class AddCiEnabledToApplicationSettings < ActiveRecord::Migration class AddCiEnabledToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :ci_enabled, :boolean, null: false, default: true add_column :application_settings, :ci_enabled, :boolean, null: false, default: true
......
# rubocop:disable all
class RemoveInvalidMilestonesFromMergeRequests < ActiveRecord::Migration class RemoveInvalidMilestonesFromMergeRequests < ActiveRecord::Migration
def up def up
execute("UPDATE merge_requests SET milestone_id = NULL where milestone_id NOT IN (SELECT id FROM milestones)") execute("UPDATE merge_requests SET milestone_id = NULL where milestone_id NOT IN (SELECT id FROM milestones)")
......
# rubocop:disable all
class AddConsumedTimestepToUsers < ActiveRecord::Migration class AddConsumedTimestepToUsers < ActiveRecord::Migration
def change def change
add_column :users, :consumed_timestep, :integer add_column :users, :consumed_timestep, :integer
......
# rubocop:disable all
class AddLineCodeToSentNotification < ActiveRecord::Migration class AddLineCodeToSentNotification < ActiveRecord::Migration
def change def change
add_column :sent_notifications, :line_code, :string add_column :sent_notifications, :line_code, :string
......
# rubocop:disable all
class AddProjectIdToCiCommit < ActiveRecord::Migration class AddProjectIdToCiCommit < ActiveRecord::Migration
def up def up
add_column :ci_commits, :gl_project_id, :integer add_column :ci_commits, :gl_project_id, :integer
......
# rubocop:disable all
class MigrateProjectIdForCiCommits < ActiveRecord::Migration class MigrateProjectIdForCiCommits < ActiveRecord::Migration
def up def up
subquery = 'SELECT gitlab_id FROM ci_projects WHERE ci_projects.id = ci_commits.project_id' subquery = 'SELECT gitlab_id FROM ci_projects WHERE ci_projects.id = ci_commits.project_id'
......
# rubocop:disable all
class MergeRequestErrorField < ActiveRecord::Migration class MergeRequestErrorField < ActiveRecord::Migration
def up def up
add_column :merge_requests, :merge_error, :string add_column :merge_requests, :merge_error, :string
......
# rubocop:disable all
class AddNullToNameForCiProjects < ActiveRecord::Migration class AddNullToNameForCiProjects < ActiveRecord::Migration
def up def up
change_column_null :ci_projects, :name, true change_column_null :ci_projects, :name, true
......
# rubocop:disable all
class AddGroupShareLock < ActiveRecord::Migration class AddGroupShareLock < ActiveRecord::Migration
def change def change
add_column :namespaces, :share_with_group_lock, :boolean, default: false add_column :namespaces, :share_with_group_lock, :boolean, default: false
......
# rubocop:disable all
class AddStageIdxToBuilds < ActiveRecord::Migration class AddStageIdxToBuilds < ActiveRecord::Migration
def change def change
add_column :ci_builds, :stage_idx, :integer add_column :ci_builds, :stage_idx, :integer
......
# rubocop:disable all
class AddIndexForBuilds < ActiveRecord::Migration class AddIndexForBuilds < ActiveRecord::Migration
def up def up
add_index :ci_builds, [:commit_id, :stage_idx, :created_at] add_index :ci_builds, [:commit_id, :stage_idx, :created_at]
......
# rubocop:disable all
class AddRefAndTagToBuilds < ActiveRecord::Migration class AddRefAndTagToBuilds < ActiveRecord::Migration
def change def change
add_column :ci_builds, :tag, :boolean add_column :ci_builds, :tag, :boolean
......
# rubocop:disable all
class MigrateRefAndTagToBuild < ActiveRecord::Migration class MigrateRefAndTagToBuild < ActiveRecord::Migration
def change def change
execute('UPDATE ci_builds SET ref=(SELECT ref FROM ci_commits WHERE ci_commits.id = ci_builds.commit_id) WHERE ref IS NULL') execute('UPDATE ci_builds SET ref=(SELECT ref FROM ci_commits WHERE ci_commits.id = ci_builds.commit_id) WHERE ref IS NULL')
......
# rubocop:disable all
class AddUserIdToBuild < ActiveRecord::Migration class AddUserIdToBuild < ActiveRecord::Migration
def change def change
add_column :ci_builds, :user_id, :integer add_column :ci_builds, :user_id, :integer
......
# rubocop:disable all
class AddLayoutOptionForUsers < ActiveRecord::Migration class AddLayoutOptionForUsers < ActiveRecord::Migration
def change def change
add_column :users, :layout, :integer, default: 0 add_column :users, :layout, :integer, default: 0
......
# rubocop:disable all
class RemoveCiEnabledFromApplicationSettings < ActiveRecord::Migration class RemoveCiEnabledFromApplicationSettings < ActiveRecord::Migration
def change def change
remove_column :application_settings, :ci_enabled, :boolean, null: false, default: true remove_column :application_settings, :ci_enabled, :boolean, null: false, default: true
......
# rubocop:disable all
class NamespacesProjectsPathLowerIndexes < ActiveRecord::Migration class NamespacesProjectsPathLowerIndexes < ActiveRecord::Migration
disable_ddl_transaction! disable_ddl_transaction!
......
# rubocop:disable all
class AddUsersLowerUsernameEmailIndexes < ActiveRecord::Migration class AddUsersLowerUsernameEmailIndexes < ActiveRecord::Migration
disable_ddl_transaction! disable_ddl_transaction!
......
# rubocop:disable all
class AddTypeAndDescriptionToBuilds < ActiveRecord::Migration class AddTypeAndDescriptionToBuilds < ActiveRecord::Migration
def change def change
add_column :ci_builds, :type, :string add_column :ci_builds, :type, :string
......
# rubocop:disable all
class MigrateNameToDescriptionForBuilds < ActiveRecord::Migration class MigrateNameToDescriptionForBuilds < ActiveRecord::Migration
def change def change
execute("UPDATE ci_builds SET type='Ci::Build' WHERE type IS NULL") execute("UPDATE ci_builds SET type='Ci::Build' WHERE type IS NULL")
......
# rubocop:disable all
class AddAdminNotificationEmailSetting < ActiveRecord::Migration class AddAdminNotificationEmailSetting < ActiveRecord::Migration
def change def change
add_column :application_settings, :admin_notification_email, :string add_column :application_settings, :admin_notification_email, :string
......
# rubocop:disable all
class SetJiraServiceApiUrl < ActiveRecord::Migration class SetJiraServiceApiUrl < ActiveRecord::Migration
# This migration can be performed online without errors, but some Jira API calls may be missed # This migration can be performed online without errors, but some Jira API calls may be missed
# when doing so because api_url is not yet available. # when doing so because api_url is not yet available.
......
# rubocop:disable all
class AddArtifactsFileToBuilds < ActiveRecord::Migration class AddArtifactsFileToBuilds < ActiveRecord::Migration
def change def change
add_column :ci_builds, :artifacts_file, :text add_column :ci_builds, :artifacts_file, :text
......
# rubocop:disable all
class AddCiProjectsGlProjectIdIndex < ActiveRecord::Migration class AddCiProjectsGlProjectIdIndex < ActiveRecord::Migration
def change def change
add_index :ci_commits, :gl_project_id add_index :ci_commits, :gl_project_id
......
# rubocop:disable all
class AddCiBuildsAndProjectsIndexes < ActiveRecord::Migration class AddCiBuildsAndProjectsIndexes < ActiveRecord::Migration
def change def change
add_index :ci_projects, :gitlab_id add_index :ci_projects, :gitlab_id
......
# rubocop:disable all
class AddNotesLineCodeIndex < ActiveRecord::Migration class AddNotesLineCodeIndex < ActiveRecord::Migration
def change def change
add_index :notes, :line_code add_index :notes, :line_code
......
# rubocop:disable all
class FixBuildTags < ActiveRecord::Migration class FixBuildTags < ActiveRecord::Migration
def up def up
execute("UPDATE taggings SET taggable_type='CommitStatus' WHERE taggable_type='Ci::Build'") execute("UPDATE taggings SET taggable_type='CommitStatus' WHERE taggable_type='Ci::Build'")
......
# rubocop:disable all
class FailBuildWithoutNames < ActiveRecord::Migration class FailBuildWithoutNames < ActiveRecord::Migration
def up def up
execute("UPDATE ci_builds SET status='failed' WHERE name IS NULL AND status='pending'") execute("UPDATE ci_builds SET status='failed' WHERE name IS NULL AND status='pending'")
......
# rubocop:disable all
class AddServicesTemplateIndex < ActiveRecord::Migration class AddServicesTemplateIndex < ActiveRecord::Migration
def change def change
add_index :services, :template add_index :services, :template
......
# rubocop:disable all
class CiLimitsToMysql < ActiveRecord::Migration class CiLimitsToMysql < ActiveRecord::Migration
def change def change
return unless ActiveRecord::Base.configurations[Rails.env]['adapter'] =~ /^mysql/ return unless ActiveRecord::Base.configurations[Rails.env]['adapter'] =~ /^mysql/
......
# rubocop:disable all
class AddCiBuildsIndexForStatus < ActiveRecord::Migration class AddCiBuildsIndexForStatus < ActiveRecord::Migration
def change def change
add_index :ci_builds, [:commit_id, :status, :type] add_index :ci_builds, [:commit_id, :status, :type]
......
# rubocop:disable all
class FailBuildWithEmptyName < ActiveRecord::Migration class FailBuildWithEmptyName < ActiveRecord::Migration
def up def up
execute("UPDATE ci_builds SET status='failed' WHERE (name IS NULL OR name='') AND status='pending'") execute("UPDATE ci_builds SET status='failed' WHERE (name IS NULL OR name='') AND status='pending'")
......
# rubocop:disable all
require 'fileutils' require 'fileutils'
class RemoveSatellites < ActiveRecord::Migration class RemoveSatellites < ActiveRecord::Migration
......
# rubocop:disable all
class AddProjectPathIndex < ActiveRecord::Migration class AddProjectPathIndex < ActiveRecord::Migration
def up def up
add_index :projects, :path add_index :projects, :path
......
# rubocop:disable all
class AddMergeWhenBuildSucceedsToMergeRequest < ActiveRecord::Migration class AddMergeWhenBuildSucceedsToMergeRequest < ActiveRecord::Migration
def change def change
add_column :merge_requests, :merge_params, :text add_column :merge_requests, :merge_params, :text
......
# rubocop:disable all
class AddPublicToGroup < ActiveRecord::Migration class AddPublicToGroup < ActiveRecord::Migration
def change def change
add_column :namespaces, :public, :boolean, default: false add_column :namespaces, :public, :boolean, default: false
......
# rubocop:disable all
class AddSharedRunnersSetting < ActiveRecord::Migration class AddSharedRunnersSetting < ActiveRecord::Migration
def up def up
add_column :application_settings, :shared_runners_enabled, :boolean, default: true, null: false add_column :application_settings, :shared_runners_enabled, :boolean, default: true, null: false
......
# rubocop:disable all
class CreateLfsObjects < ActiveRecord::Migration class CreateLfsObjects < ActiveRecord::Migration
def change def change
create_table :lfs_objects do |t| create_table :lfs_objects do |t|
......
# rubocop:disable all
class CreateLfsObjectsProjects < ActiveRecord::Migration class CreateLfsObjectsProjects < ActiveRecord::Migration
def change def change
create_table :lfs_objects_projects do |t| create_table :lfs_objects_projects do |t|
......
# rubocop:disable all
class AddFileToLfsObjects < ActiveRecord::Migration class AddFileToLfsObjects < ActiveRecord::Migration
def change def change
add_column :lfs_objects, :file, :string add_column :lfs_objects, :file, :string
......
# rubocop:disable all
class CreateReleases < ActiveRecord::Migration class CreateReleases < ActiveRecord::Migration
def change def change
create_table :releases do |t| create_table :releases do |t|
......
# rubocop:disable all
class AddIsAwardToNotes < ActiveRecord::Migration class AddIsAwardToNotes < ActiveRecord::Migration
def change def change
add_column :notes, :is_award, :boolean, default: false, null: false add_column :notes, :is_award, :boolean, default: false, null: false
......
# rubocop:disable all
class AddMaxArtifactsSizeToApplicationSettings < ActiveRecord::Migration class AddMaxArtifactsSizeToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :max_artifacts_size, :integer, default: 100, null: false add_column :application_settings, :max_artifacts_size, :integer, default: 100, null: false
......
# rubocop:disable all
class AddIssuesStateIndex < ActiveRecord::Migration class AddIssuesStateIndex < ActiveRecord::Migration
def change def change
add_index :issues, :state add_index :issues, :state
......
# rubocop:disable all
class AddProjectsVisibilityLevelIndex < ActiveRecord::Migration class AddProjectsVisibilityLevelIndex < ActiveRecord::Migration
def change def change
add_index :projects, :visibility_level add_index :projects, :visibility_level
......
# rubocop:disable all
class AddImportErrorToProject < ActiveRecord::Migration class AddImportErrorToProject < ActiveRecord::Migration
def change def change
add_column :projects, :import_error, :text add_column :projects, :import_error, :text
......
# rubocop:disable all
class AddIndexForLfsOidAndSize < ActiveRecord::Migration class AddIndexForLfsOidAndSize < ActiveRecord::Migration
def change def change
add_index :lfs_objects, :oid add_index :lfs_objects, :oid
......
# rubocop:disable all
class AddUniqueForLfsOidIndex < ActiveRecord::Migration class AddUniqueForLfsOidIndex < ActiveRecord::Migration
def change def change
remove_index :lfs_objects, :oid remove_index :lfs_objects, :oid
......
# rubocop:disable all
class AddProjectsPublicIndex < ActiveRecord::Migration class AddProjectsPublicIndex < ActiveRecord::Migration
def change def change
add_index :namespaces, :public add_index :namespaces, :public
......
# rubocop:disable all
class RaiseHookUrlLimit < ActiveRecord::Migration class RaiseHookUrlLimit < ActiveRecord::Migration
def change def change
change_column :web_hooks, :url, :string, limit: 2000 change_column :web_hooks, :url, :string, limit: 2000
......
# rubocop:disable all
class AddHideProjectLimitToUsers < ActiveRecord::Migration class AddHideProjectLimitToUsers < ActiveRecord::Migration
def change def change
add_column :users, :hide_project_limit, :boolean, default: false add_column :users, :hide_project_limit, :boolean, default: false
......
# rubocop:disable all
class AddBuildEventsToServices < ActiveRecord::Migration class AddBuildEventsToServices < ActiveRecord::Migration
def change def change
add_column :services, :build_events, :boolean, default: false, null: false add_column :services, :build_events, :boolean, default: false, null: false
......
# rubocop:disable all
class MigrateCiWebHooks < ActiveRecord::Migration class MigrateCiWebHooks < ActiveRecord::Migration
include Gitlab::Database include Gitlab::Database
......
# rubocop:disable all
class MigrateCiEmails < ActiveRecord::Migration class MigrateCiEmails < ActiveRecord::Migration
include Gitlab::Database include Gitlab::Database
......
# rubocop:disable all
class AddUnlockTokenToUser < ActiveRecord::Migration class AddUnlockTokenToUser < ActiveRecord::Migration
def change def change
add_column :users, :unlock_token, :string add_column :users, :unlock_token, :string
......
# rubocop:disable all
class AddRunnersRegistrationTokenToApplicationSettings < ActiveRecord::Migration class AddRunnersRegistrationTokenToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :runners_registration_token, :string add_column :application_settings, :runners_registration_token, :string
......
# rubocop:disable all
class MigrateCiSlackService < ActiveRecord::Migration class MigrateCiSlackService < ActiveRecord::Migration
include Gitlab::Database include Gitlab::Database
......
# rubocop:disable all
class MigrateCiHipChatService < ActiveRecord::Migration class MigrateCiHipChatService < ActiveRecord::Migration
include Gitlab::Database include Gitlab::Database
......
# rubocop:disable all
class AddCiToProject < ActiveRecord::Migration class AddCiToProject < ActiveRecord::Migration
def change def change
add_column :projects, :ci_id, :integer add_column :projects, :ci_id, :integer
......
# rubocop:disable all
class AddProjectIdToCi < ActiveRecord::Migration class AddProjectIdToCi < ActiveRecord::Migration
def change def change
add_column :ci_builds, :gl_project_id, :integer add_column :ci_builds, :gl_project_id, :integer
......
# rubocop:disable all
class MigrateCiToProject < ActiveRecord::Migration class MigrateCiToProject < ActiveRecord::Migration
def up def up
migrate_project_id_for_table('ci_runner_projects') migrate_project_id_for_table('ci_runner_projects')
......
# rubocop:disable all
class AddIndexToCiTables < ActiveRecord::Migration class AddIndexToCiTables < ActiveRecord::Migration
def change def change
add_index :ci_builds, :gl_project_id add_index :ci_builds, :gl_project_id
......
# rubocop:disable all
class DropNullForCiTables < ActiveRecord::Migration class DropNullForCiTables < ActiveRecord::Migration
def change def change
remove_index :ci_variables, :project_id remove_index :ci_variables, :project_id
......
# rubocop:disable all
class AddTfaToApplicationSettings < ActiveRecord::Migration class AddTfaToApplicationSettings < ActiveRecord::Migration
def change def change
change_table :application_settings do |t| change_table :application_settings do |t|
......
# rubocop:disable all
class AddTfaAdditionalFields < ActiveRecord::Migration class AddTfaAdditionalFields < ActiveRecord::Migration
def change def change
change_table :users do |t| change_table :users do |t|
......
# rubocop:disable all
# Migration type: online without errors (works on previous version and new one) # Migration type: online without errors (works on previous version and new one)
class RenameEmojis < ActiveRecord::Migration class RenameEmojis < ActiveRecord::Migration
def up def up
......
# rubocop:disable all
# Migration type: online # Migration type: online
class RemovePublicFromNamespace < ActiveRecord::Migration class RemovePublicFromNamespace < ActiveRecord::Migration
def change def change
......
# rubocop:disable all
class InfluxdbSettings < ActiveRecord::Migration class InfluxdbSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :metrics_enabled, :boolean, default: false add_column :application_settings, :metrics_enabled, :boolean, default: false
......
# rubocop:disable all
class AddRecaptchaToApplicationSettings < ActiveRecord::Migration class AddRecaptchaToApplicationSettings < ActiveRecord::Migration
def change def change
change_table :application_settings do |t| change_table :application_settings do |t|
......
# rubocop:disable all
class InfluxdbUdpPortSetting < ActiveRecord::Migration class InfluxdbUdpPortSetting < ActiveRecord::Migration
def change def change
add_column :application_settings, :metrics_port, :integer, default: 8089 add_column :application_settings, :metrics_port, :integer, default: 8089
......
# rubocop:disable all
class InfluxdbRemoteDatabaseSetting < ActiveRecord::Migration class InfluxdbRemoteDatabaseSetting < ActiveRecord::Migration
def change def change
remove_column :application_settings, :metrics_database remove_column :application_settings, :metrics_database
......
# rubocop:disable all
class AddArtifactsMetadataToCiBuild < ActiveRecord::Migration class AddArtifactsMetadataToCiBuild < ActiveRecord::Migration
def change def change
add_column :ci_builds, :artifacts_metadata, :text add_column :ci_builds, :artifacts_metadata, :text
......
# rubocop:disable all
class AddAkismetToApplicationSettings < ActiveRecord::Migration class AddAkismetToApplicationSettings < ActiveRecord::Migration
def change def change
change_table :application_settings do |t| change_table :application_settings do |t|
......
# rubocop:disable all
class RemoveAlertTypeFromBroadcastMessages < ActiveRecord::Migration class RemoveAlertTypeFromBroadcastMessages < ActiveRecord::Migration
def change def change
remove_column :broadcast_messages, :alert_type, :integer remove_column :broadcast_messages, :alert_type, :integer
......
# rubocop:disable all
class AddIndexMilestonesTitle < ActiveRecord::Migration class AddIndexMilestonesTitle < ActiveRecord::Migration
def change def change
add_index :milestones, :title add_index :milestones, :title
......
# rubocop:disable all
class RemoveInfluxdbCredentials < ActiveRecord::Migration class RemoveInfluxdbCredentials < ActiveRecord::Migration
def change def change
remove_column :application_settings, :metrics_username, :string remove_column :application_settings, :metrics_username, :string
......
# rubocop:disable all
class CreateSpamLogs < ActiveRecord::Migration class CreateSpamLogs < ActiveRecord::Migration
def change def change
create_table :spam_logs do |t| create_table :spam_logs do |t|
......
# rubocop:disable all
class AddMetricsSampleInterval < ActiveRecord::Migration class AddMetricsSampleInterval < ActiveRecord::Migration
def change def change
add_column :application_settings, :metrics_sample_interval, :integer, add_column :application_settings, :metrics_sample_interval, :integer,
......
# rubocop:disable all
class AddSentryToApplicationSettings < ActiveRecord::Migration class AddSentryToApplicationSettings < ActiveRecord::Migration
def change def change
change_table :application_settings do |t| change_table :application_settings do |t|
......
# rubocop:disable all
class AddIpBlockingSettingsToApplicationSettings < ActiveRecord::Migration class AddIpBlockingSettingsToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :ip_blocking_enabled, :boolean, default: false add_column :application_settings, :ip_blocking_enabled, :boolean, default: false
......
# rubocop:disable all
class AddServicesCategory < ActiveRecord::Migration class AddServicesCategory < ActiveRecord::Migration
def up def up
add_column :services, :category, :string, default: 'common', null: false add_column :services, :category, :string, default: 'common', null: false
......
# rubocop:disable all
class AddServicesDefault < ActiveRecord::Migration class AddServicesDefault < ActiveRecord::Migration
def up def up
add_column :services, :default, :boolean, default: false add_column :services, :default, :boolean, default: false
......
# rubocop:disable all
class AddLdapEmailToUsers < ActiveRecord::Migration class AddLdapEmailToUsers < ActiveRecord::Migration
def up def up
add_column :users, :ldap_email, :boolean, default: false, null: false add_column :users, :ldap_email, :boolean, default: false, null: false
......
# rubocop:disable all
class AddBaseCommitShaToMergeRequestDiffs < ActiveRecord::Migration class AddBaseCommitShaToMergeRequestDiffs < ActiveRecord::Migration
def change def change
add_column :merge_request_diffs, :base_commit_sha, :string add_column :merge_request_diffs, :base_commit_sha, :string
......
# rubocop:disable all
class AddEmailAuthorInBodyToApplicationSettings < ActiveRecord::Migration class AddEmailAuthorInBodyToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :email_author_in_body, :boolean, default: false add_column :application_settings, :email_author_in_body, :boolean, default: false
......
# rubocop:disable all
class AddPendingDeleteToProject < ActiveRecord::Migration class AddPendingDeleteToProject < ActiveRecord::Migration
def change def change
add_column :projects, :pending_delete, :boolean, default: false add_column :projects, :pending_delete, :boolean, default: false
......
# rubocop:disable all
class RemoveIpBlockingSettingsFromApplicationSettings < ActiveRecord::Migration class RemoveIpBlockingSettingsFromApplicationSettings < ActiveRecord::Migration
def change def change
remove_column :application_settings, :ip_blocking_enabled, :boolean, default: false remove_column :application_settings, :ip_blocking_enabled, :boolean, default: false
......
# rubocop:disable all
class ChangeLfsObjectsSizeColumn < ActiveRecord::Migration class ChangeLfsObjectsSizeColumn < ActiveRecord::Migration
def change def change
change_column :lfs_objects, :size, :integer, limit: 8 change_column :lfs_objects, :size, :integer, limit: 8
......
# rubocop:disable all
class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
......
# rubocop:disable all
class AddMergeCommitShaToMergeRequests < ActiveRecord::Migration class AddMergeCommitShaToMergeRequests < ActiveRecord::Migration
def change def change
add_column :merge_requests, :merge_commit_sha, :string add_column :merge_requests, :merge_commit_sha, :string
......
# rubocop:disable all
class AddErasableToCiBuild < ActiveRecord::Migration class AddErasableToCiBuild < ActiveRecord::Migration
def change def change
add_reference :ci_builds, :erased_by, references: :users, index: true add_reference :ci_builds, :erased_by, references: :users, index: true
......
# rubocop:disable all
class AddAllowGuestToAccessBuildsProject < ActiveRecord::Migration class AddAllowGuestToAccessBuildsProject < ActiveRecord::Migration
def change def change
add_column :projects, :public_builds, :boolean, default: true, null: false add_column :projects, :public_builds, :boolean, default: true, null: false
......
# rubocop:disable all
class AddRealSizeToMergeRequestDiffs < ActiveRecord::Migration class AddRealSizeToMergeRequestDiffs < ActiveRecord::Migration
def change def change
add_column :merge_request_diffs, :real_size, :string add_column :merge_request_diffs, :real_size, :string
......
# rubocop:disable all
class AddIndexToSnippet < ActiveRecord::Migration class AddIndexToSnippet < ActiveRecord::Migration
def change def change
add_index :snippets, :updated_at add_index :snippets, :updated_at
......
# rubocop:disable all
class CreateTasks < ActiveRecord::Migration class CreateTasks < ActiveRecord::Migration
def change def change
create_table :tasks do |t| create_table :tasks do |t|
......
# rubocop:disable all
class AddDescriptionToLabel < ActiveRecord::Migration class AddDescriptionToLabel < ActiveRecord::Migration
def change def change
add_column :labels, :description, :string add_column :labels, :description, :string
......
# rubocop:disable all
class AddNoteToTasks < ActiveRecord::Migration class AddNoteToTasks < ActiveRecord::Migration
def change def change
add_reference :tasks, :note, index: true add_reference :tasks, :note, index: true
......
# rubocop:disable all
class RenameTasksToTodos < ActiveRecord::Migration class RenameTasksToTodos < ActiveRecord::Migration
def change def change
rename_table :tasks, :todos rename_table :tasks, :todos
......
# rubocop:disable all
class CreateAppearancesCe < ActiveRecord::Migration class CreateAppearancesCe < ActiveRecord::Migration
def change def change
unless table_exists?(:appearances) unless table_exists?(:appearances)
......
# rubocop:disable all
class AddConfidentialToIssues < ActiveRecord::Migration class AddConfidentialToIssues < ActiveRecord::Migration
def change def change
add_column :issues, :confidential, :boolean, default: false add_column :issues, :confidential, :boolean, default: false
......
# rubocop:disable all
class AddDeleteAtToIssues < ActiveRecord::Migration class AddDeleteAtToIssues < ActiveRecord::Migration
def change def change
add_column :issues, :deleted_at, :datetime add_column :issues, :deleted_at, :datetime
......
# rubocop:disable all
class AddDeleteAtToMergeRequests < ActiveRecord::Migration class AddDeleteAtToMergeRequests < ActiveRecord::Migration
def change def change
add_column :merge_requests, :deleted_at, :datetime add_column :merge_requests, :deleted_at, :datetime
......
# rubocop:disable all
class AddTrigramIndexesForSearching < ActiveRecord::Migration class AddTrigramIndexesForSearching < ActiveRecord::Migration
disable_ddl_transaction! disable_ddl_transaction!
......
# rubocop:disable all
class AddEventFieldForWebHook < ActiveRecord::Migration class AddEventFieldForWebHook < ActiveRecord::Migration
def change def change
add_column :web_hooks, :wiki_page_events, :boolean, default: false, null: false add_column :web_hooks, :wiki_page_events, :boolean, default: false, null: false
......
# rubocop:disable all
class AddEventToServices < ActiveRecord::Migration class AddEventToServices < ActiveRecord::Migration
def change def change
add_column :services, :wiki_page_events, :boolean, default: true add_column :services, :wiki_page_events, :boolean, default: true
......
# rubocop:disable all
class AddMainLanguageToRepository < ActiveRecord::Migration class AddMainLanguageToRepository < ActiveRecord::Migration
def change def change
add_column :projects, :main_language, :string add_column :projects, :main_language, :string
......
# rubocop:disable all
class AddVisibilityLevelToGroups < ActiveRecord::Migration class AddVisibilityLevelToGroups < ActiveRecord::Migration
def up def up
add_column :namespaces, :visibility_level, :integer, null: false, default: Gitlab::VisibilityLevel::PUBLIC add_column :namespaces, :visibility_level, :integer, null: false, default: Gitlab::VisibilityLevel::PUBLIC
......
# rubocop:disable all
class AddImportCredentialsToProjectImportData < ActiveRecord::Migration class AddImportCredentialsToProjectImportData < ActiveRecord::Migration
def change def change
add_column :project_import_data, :encrypted_credentials, :text add_column :project_import_data, :encrypted_credentials, :text
......
# rubocop:disable all
# Loops through old importer projects that kept a token/password in the import URL # Loops through old importer projects that kept a token/password in the import URL
# and encrypts the credentials into a separate field in project#import_data # and encrypts the credentials into a separate field in project#import_data
# #down method not supported # #down method not supported
......
# rubocop:disable all
class RemoveExpiresAtFromSnippets < ActiveRecord::Migration class RemoveExpiresAtFromSnippets < ActiveRecord::Migration
def change def change
remove_column :snippets, :expires_at, :datetime remove_column :snippets, :expires_at, :datetime
......
# rubocop:disable all
class DisallowBlankLineCodeOnNote < ActiveRecord::Migration class DisallowBlankLineCodeOnNote < ActiveRecord::Migration
def up def up
execute("UPDATE notes SET line_code = NULL WHERE line_code = ''") execute("UPDATE notes SET line_code = NULL WHERE line_code = ''")
......
# rubocop:disable all
# Create visibility level field on DB # Create visibility level field on DB
# Sets default_visibility_level to value on settings if not restricted # Sets default_visibility_level to value on settings if not restricted
# If value is restricted takes higher visibility level allowed # If value is restricted takes higher visibility level allowed
......
# rubocop:disable all
class FixTodos < ActiveRecord::Migration class FixTodos < ActiveRecord::Migration
def up def up
execute <<-SQL execute <<-SQL
......
# rubocop:disable all
class AddDueDateToIssues < ActiveRecord::Migration class AddDueDateToIssues < ActiveRecord::Migration
def change def change
add_column :issues, :due_date, :date add_column :issues, :due_date, :date
......
# rubocop:disable all
class AddExternalFlagToUsers < ActiveRecord::Migration class AddExternalFlagToUsers < ActiveRecord::Migration
def change def change
add_column :users, :external, :boolean, default: false add_column :users, :external, :boolean, default: false
......
# rubocop:disable all
class AddPriorityToLabel < ActiveRecord::Migration class AddPriorityToLabel < ActiveRecord::Migration
def change def change
add_column :labels, :priority, :integer add_column :labels, :priority, :integer
......
# rubocop:disable all
class ProjectsAddPushesSinceGc < ActiveRecord::Migration class ProjectsAddPushesSinceGc < ActiveRecord::Migration
def change def change
add_column :projects, :pushes_since_gc, :integer, default: 0 add_column :projects, :pushes_since_gc, :integer, default: 0
......
# rubocop:disable all
class ProjectAddRepositoryCheck < ActiveRecord::Migration class ProjectAddRepositoryCheck < ActiveRecord::Migration
def change def change
add_column :projects, :last_repository_check_failed, :boolean add_column :projects, :last_repository_check_failed, :boolean
......
# rubocop:disable all
class CiRunnersTokenIndex < ActiveRecord::Migration class CiRunnersTokenIndex < ActiveRecord::Migration
disable_ddl_transaction! disable_ddl_transaction!
......
# rubocop:disable all
class ChangeTargetIdToNullOnTodos < ActiveRecord::Migration class ChangeTargetIdToNullOnTodos < ActiveRecord::Migration
def change def change
change_column_null :todos, :target_id, true change_column_null :todos, :target_id, true
......
# rubocop:disable all
class AddCommitIdToTodos < ActiveRecord::Migration class AddCommitIdToTodos < ActiveRecord::Migration
def change def change
add_column :todos, :commit_id, :string add_column :todos, :commit_id, :string
......
# rubocop:disable all
class AddMovedToToIssue < ActiveRecord::Migration class AddMovedToToIssue < ActiveRecord::Migration
def change def change
add_reference :issues, :moved_to, references: :issues add_reference :issues, :moved_to, references: :issues
......
# rubocop:disable all
class IndexNamespacesOnVisibilityLevel < ActiveRecord::Migration class IndexNamespacesOnVisibilityLevel < ActiveRecord::Migration
def change def change
unless index_exists?(:namespaces, :visibility_level) unless index_exists?(:namespaces, :visibility_level)
......
# rubocop:disable all
class RemoveTodosForDeletedIssues < ActiveRecord::Migration class RemoveTodosForDeletedIssues < ActiveRecord::Migration
def up def up
execute <<-SQL execute <<-SQL
......
# rubocop:disable all
class CreateNotificationSettings < ActiveRecord::Migration class CreateNotificationSettings < ActiveRecord::Migration
def change def change
create_table :notification_settings do |t| create_table :notification_settings do |t|
......
# rubocop:disable all
# This migration will create one row of NotificationSetting for each Member row # This migration will create one row of NotificationSetting for each Member row
# It can take long time on big instances. # It can take long time on big instances.
# #
......
# rubocop:disable all
class AddNotificationSettingIndex < ActiveRecord::Migration class AddNotificationSettingIndex < ActiveRecord::Migration
def change def change
add_index :notification_settings, :user_id add_index :notification_settings, :user_id
......
# rubocop:disable all
class AddIndexOnPendingDeleteProjects < ActiveRecord::Migration class AddIndexOnPendingDeleteProjects < ActiveRecord::Migration
def change def change
add_index :projects, :pending_delete add_index :projects, :pending_delete
......
# rubocop:disable all
class RemoveTodosForDeletedMergeRequests < ActiveRecord::Migration class RemoveTodosForDeletedMergeRequests < ActiveRecord::Migration
def up def up
execute <<-SQL execute <<-SQL
......
# rubocop:disable all
class RemoveTwitterSharingEnabledFromApplicationSettings < ActiveRecord::Migration class RemoveTwitterSharingEnabledFromApplicationSettings < ActiveRecord::Migration
def change def change
remove_column :application_settings, :twitter_sharing_enabled, :boolean remove_column :application_settings, :twitter_sharing_enabled, :boolean
......
# rubocop:disable all
class AddImagesEnabledForProject < ActiveRecord::Migration class AddImagesEnabledForProject < ActiveRecord::Migration
def change def change
add_column :projects, :container_registry_enabled, :boolean add_column :projects, :container_registry_enabled, :boolean
......
# rubocop:disable all
class AddRepositoryChecksEnabledSetting < ActiveRecord::Migration class AddRepositoryChecksEnabledSetting < ActiveRecord::Migration
def change def change
add_column :application_settings, :repository_checks_enabled, :boolean, default: true add_column :application_settings, :repository_checks_enabled, :boolean, default: true
......
# rubocop:disable all
class AddFieldsToCiCommit < ActiveRecord::Migration class AddFieldsToCiCommit < ActiveRecord::Migration
def change def change
add_column :ci_commits, :status, :string add_column :ci_commits, :status, :string
......
# rubocop:disable all
class UpdateCiCommit < ActiveRecord::Migration class UpdateCiCommit < ActiveRecord::Migration
# This migration can be run online, but needs to be executed for the second time after restarting Unicorn workers # This migration can be run online, but needs to be executed for the second time after restarting Unicorn workers
# Otherwise Offline migration should be used. # Otherwise Offline migration should be used.
......
# rubocop:disable all
class AddCiCommitIndexes < ActiveRecord::Migration class AddCiCommitIndexes < ActiveRecord::Migration
disable_ddl_transaction! disable_ddl_transaction!
......
# rubocop:disable all
class AddTokenToWebHooks < ActiveRecord::Migration class AddTokenToWebHooks < ActiveRecord::Migration
def change def change
add_column :web_hooks, :token, :string add_column :web_hooks, :token, :string
......
# rubocop:disable all
class AddSharedRunnersTextToApplicationSettings < ActiveRecord::Migration class AddSharedRunnersTextToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :shared_runners_text, :text add_column :application_settings, :shared_runners_text, :text
......
# rubocop:disable all
class AddAwardEmoji < ActiveRecord::Migration class AddAwardEmoji < ActiveRecord::Migration
def change def change
create_table :award_emoji do |t| create_table :award_emoji do |t|
......
# rubocop:disable all
class ConvertAwardNoteToEmojiAward < ActiveRecord::Migration class ConvertAwardNoteToEmojiAward < ActiveRecord::Migration
def change def change
def up def up
......
# rubocop:disable all
class RemoveNoteIsAward < ActiveRecord::Migration class RemoveNoteIsAward < ActiveRecord::Migration
def change def change
remove_column :notes, :is_award, :boolean remove_column :notes, :is_award, :boolean
......
# rubocop:disable all
class AddMetricsPacketSize < ActiveRecord::Migration class AddMetricsPacketSize < ActiveRecord::Migration
def change def change
add_column :application_settings, :metrics_packet_size, :integer, default: 1 add_column :application_settings, :metrics_packet_size, :integer, default: 1
......
class AddOnlyAllowMergeIfBuildSucceedsToProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def up
add_column_with_default(:projects,
:only_allow_merge_if_build_succeeds,
:boolean,
default: false)
end
def down
remove_column(:projects, :only_allow_merge_if_build_succeeds)
end
end
# rubocop:disable all
class DisableRepositoryChecks < ActiveRecord::Migration class DisableRepositoryChecks < ActiveRecord::Migration
def up def up
change_column_default :application_settings, :repository_checks_enabled, false change_column_default :application_settings, :repository_checks_enabled, false
......
# rubocop:disable all
class CreateU2fRegistrations < ActiveRecord::Migration class CreateU2fRegistrations < ActiveRecord::Migration
def change def change
create_table :u2f_registrations do |t| create_table :u2f_registrations do |t|
......
# rubocop:disable all
class AddDisabledOauthSignInSourcesToApplicationSettings < ActiveRecord::Migration class AddDisabledOauthSignInSourcesToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :disabled_oauth_sign_in_sources, :text add_column :application_settings, :disabled_oauth_sign_in_sources, :text
......
# rubocop:disable all
class AddRunUntaggedToCiRunner < ActiveRecord::Migration class AddRunUntaggedToCiRunner < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
disable_ddl_transaction! disable_ddl_transaction!
......
# rubocop:disable all
class RemoveWallEnabledFromProjects < ActiveRecord::Migration class RemoveWallEnabledFromProjects < ActiveRecord::Migration
def change def change
remove_column :projects, :wall_enabled, :boolean, default: true, null: false remove_column :projects, :wall_enabled, :boolean, default: true, null: false
......
# rubocop:disable all
class AddTypeToNotes < ActiveRecord::Migration class AddTypeToNotes < ActiveRecord::Migration
def change def change
add_column :notes, :type, :string add_column :notes, :type, :string
......
# rubocop:disable all
class SetTypeOnLegacyDiffNotes < ActiveRecord::Migration class SetTypeOnLegacyDiffNotes < ActiveRecord::Migration
def change def change
execute "UPDATE notes SET type = 'LegacyDiffNote' WHERE line_code IS NOT NULL" execute "UPDATE notes SET type = 'LegacyDiffNote' WHERE line_code IS NOT NULL"
......
# rubocop:disable all
class AddHealthCheckAccessTokenToApplicationSettings < ActiveRecord::Migration class AddHealthCheckAccessTokenToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :health_check_access_token, :string add_column :application_settings, :health_check_access_token, :string
......
# rubocop:disable all
class AddSendUserConfirmationEmailToApplicationSettings < ActiveRecord::Migration class AddSendUserConfirmationEmailToApplicationSettings < ActiveRecord::Migration
def up def up
add_column :application_settings, :send_user_confirmation_email, :boolean, default: false add_column :application_settings, :send_user_confirmation_email, :boolean, default: false
......
# rubocop:disable all
# See http://doc.gitlab.com/ce/development/migration_style_guide.html # See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab. # for more information on how to write migrations for GitLab.
......
# rubocop:disable all
class RemoveNotificationSettingsForDeletedProjects < ActiveRecord::Migration class RemoveNotificationSettingsForDeletedProjects < ActiveRecord::Migration
def up def up
execute <<-SQL execute <<-SQL
......
# rubocop:disable all
class AddUsersStateIndex < ActiveRecord::Migration class AddUsersStateIndex < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
......
# rubocop:disable all
# This is ONLINE migration # This is ONLINE migration
class AddContainerRegistryTokenExpireDelayToApplicationSettings < ActiveRecord::Migration class AddContainerRegistryTokenExpireDelayToApplicationSettings < ActiveRecord::Migration
......
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddHasExternalIssueTrackerToProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
def change
add_column(:projects, :has_external_issue_tracker, :boolean)
end
end
# rubocop:disable all
class RemoveDuplicatedNotificationSettings < ActiveRecord::Migration class RemoveDuplicatedNotificationSettings < ActiveRecord::Migration
def up def up
duplicates = exec_query(%Q{ duplicates = exec_query(%Q{
......
# rubocop:disable all
class AddIndexToNotificationSettings < ActiveRecord::Migration class AddIndexToNotificationSettings < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
......
# rubocop:disable all
class AddAfterSignUpTextToApplicationSettings < ActiveRecord::Migration class AddAfterSignUpTextToApplicationSettings < ActiveRecord::Migration
def change def change
add_column :application_settings, :after_sign_up_text, :text add_column :application_settings, :after_sign_up_text, :text
......
# rubocop:disable all
class LimitsToMysql < ActiveRecord::Migration class LimitsToMysql < ActiveRecord::Migration
def up def up
return unless ActiveRecord::Base.configurations[Rails.env]['adapter'] =~ /^mysql/ return unless ActiveRecord::Base.configurations[Rails.env]['adapter'] =~ /^mysql/
......
...@@ -779,6 +779,8 @@ ActiveRecord::Schema.define(version: 20160608155312) do ...@@ -779,6 +779,8 @@ ActiveRecord::Schema.define(version: 20160608155312) do
t.boolean "last_repository_check_failed" t.boolean "last_repository_check_failed"
t.datetime "last_repository_check_at" t.datetime "last_repository_check_at"
t.boolean "container_registry_enabled" t.boolean "container_registry_enabled"
t.boolean "only_allow_merge_if_build_succeeds", default: false, null: false
t.boolean "has_external_issue_tracker"
end end
add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree add_index "projects", ["builds_enabled", "shared_runners_enabled"], name: "index_projects_on_builds_enabled_and_shared_runners_enabled", using: :btree
......
...@@ -62,7 +62,7 @@ registry: ...@@ -62,7 +62,7 @@ registry:
host: registry.gitlab.example.com host: registry.gitlab.example.com
port: 5005 port: 5005
api_url: http://localhost:5000/ api_url: http://localhost:5000/
key_path: config/registry.key key: config/registry.key
path: shared/registry path: shared/registry
issuer: gitlab-issuer issuer: gitlab-issuer
``` ```
...@@ -75,7 +75,7 @@ where: ...@@ -75,7 +75,7 @@ where:
| `host` | The host URL under which the Registry will run and the users will be able to use. | | `host` | The host URL under which the Registry will run and the users will be able to use. |
| `port` | The port under which the external Registry domain will listen on. | | `port` | The port under which the external Registry domain will listen on. |
| `api_url` | The internal API URL under which the Registry is exposed to. It defaults to `http://localhost:5000`. | | `api_url` | The internal API URL under which the Registry is exposed to. It defaults to `http://localhost:5000`. |
| `key_path`| The private key location that is a pair of Registry's `rootcertbundle`. Read the [token auth configuration documentation][token-config]. | | `key` | The private key location that is a pair of Registry's `rootcertbundle`. Read the [token auth configuration documentation][token-config]. |
| `path` | This should be the same directory like specified in Registry's `rootdirectory`. Read the [storage configuration documentation][storage-config]. This path needs to be readable by the GitLab user, the web-server user and the Registry user. Read more in [#container-registry-storage-path](#container-registry-storage-path). | | `path` | This should be the same directory like specified in Registry's `rootdirectory`. Read the [storage configuration documentation][storage-config]. This path needs to be readable by the GitLab user, the web-server user and the Registry user. Read more in [#container-registry-storage-path](#container-registry-storage-path). |
| `issuer` | This should be the same value as configured in Registry's `issuer`. Read the [token auth configuration documentation][token-config]. | | `issuer` | This should be the same value as configured in Registry's `issuer`. Read the [token auth configuration documentation][token-config]. |
......
...@@ -572,7 +572,7 @@ GET /projects/:id/merge_requests/:merge_request_id/closes_issues ...@@ -572,7 +572,7 @@ GET /projects/:id/merge_requests/:merge_request_id/closes_issues
curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/76/merge_requests/1/closes_issues curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/76/merge_requests/1/closes_issues
``` ```
Example response: Example response when the GitLab issue tracker is used:
```json ```json
[ [
...@@ -618,6 +618,17 @@ Example response: ...@@ -618,6 +618,17 @@ Example response:
] ]
``` ```
Example response when an external issue tracker (e.g. JIRA) is used:
```json
[
{
"id" : "PROJECT-123",
"title" : "Title of this issue"
}
]
```
## Subscribe to a merge request ## Subscribe to a merge request
Subscribes the authenticated user to a merge request to receive notification. If Subscribes the authenticated user to a merge request to receive notification. If
......
...@@ -2,6 +2,17 @@ ...@@ -2,6 +2,17 @@
Merge requests allow you to exchange changes you made to source code Merge requests allow you to exchange changes you made to source code
## Only allow merge requests to be merged if the build succeeds
You can prevent merge requests from being merged if their build did not succeed
in the project settings page.
![only_allow_merge_if_build_succeeds](merge_requests/only_allow_merge_if_build_succeeds.png)
Navigate to project settings page and select the `Only allow merge requests to be merged if the build succeeds` check box.
Please note that you need to have builds configured to enable this feature.
## Checkout merge requests locally ## Checkout merge requests locally
Locate the section for your GitLab remote in the `.git/config` file. It looks like this: Locate the section for your GitLab remote in the `.git/config` file. It looks like this:
......
...@@ -107,12 +107,16 @@ Feature: Project Active Tab ...@@ -107,12 +107,16 @@ Feature: Project Active Tab
Scenario: On Project Issues/Milestones Scenario: On Project Issues/Milestones
Given I visit my project's issues page Given I visit my project's issues page
And I click the "Milestones" tab And I click the "Milestones" sub tab
Then the active main tab should be Milestones Then the active main tab should be Issues
Then the active sub tab should be Milestones
And no other main tabs should be active And no other main tabs should be active
And no other sub tabs should be active
Scenario: On Project Issues/Labels Scenario: On Project Issues/Labels
Given I visit my project's issues page Given I visit my project's issues page
And I click the "Labels" tab And I click the "Labels" sub tab
Then the active main tab should be Labels Then the active main tab should be Issues
Then the active sub tab should be Labels
And no other main tabs should be active And no other main tabs should be active
And no other sub tabs should be active
...@@ -155,6 +155,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps ...@@ -155,6 +155,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
end end
step 'I click on my profile picture' do step 'I click on my profile picture' do
find(:css, '.side-nav-toggle').click
find(:css, '.sidebar-user').click find(:css, '.sidebar-user').click
end end
......
...@@ -77,14 +77,14 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps ...@@ -77,14 +77,14 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
# Sub Tabs: Issues # Sub Tabs: Issues
step 'I click the "Milestones" tab' do step 'I click the "Milestones" sub tab' do
page.within('.layout-nav') do page.within('.sub-nav') do
click_link('Milestones') click_link('Milestones')
end end
end end
step 'I click the "Labels" tab' do step 'I click the "Labels" sub tab' do
page.within('.layout-nav') do page.within('.sub-nav') do
click_link('Labels') click_link('Labels')
end end
end end
...@@ -93,11 +93,11 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps ...@@ -93,11 +93,11 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
ensure_active_sub_tab('Issues') ensure_active_sub_tab('Issues')
end end
step 'the active main tab should be Milestones' do step 'the active sub tab should be Milestones' do
ensure_active_main_tab('Milestones') ensure_active_sub_tab('Milestones')
end end
step 'the active main tab should be Labels' do step 'the active sub tab should be Labels' do
ensure_active_main_tab('Labels') ensure_active_sub_tab('Labels')
end end
end end
...@@ -5,11 +5,11 @@ class Spinach::Features::ProjectBuildsArtifacts < Spinach::FeatureSteps ...@@ -5,11 +5,11 @@ class Spinach::Features::ProjectBuildsArtifacts < Spinach::FeatureSteps
include RepoHelpers include RepoHelpers
step 'I click artifacts download button' do step 'I click artifacts download button' do
page.within('.artifacts') { click_link 'Download' } click_link 'Download'
end end
step 'I click artifacts browse button' do step 'I click artifacts browse button' do
page.within('.artifacts') { click_link 'Browse' } click_link 'Browse'
end end
step 'I should see content of artifacts archive' do step 'I should see content of artifacts archive' do
......
...@@ -6,7 +6,7 @@ module SharedActiveTab ...@@ -6,7 +6,7 @@ module SharedActiveTab
end end
def ensure_active_sub_tab(content) def ensure_active_sub_tab(content)
expect(find('div.content ul.nav-links li.active')).to have_content(content) expect(find('.sub-nav li.active')).to have_content(content)
end end
def ensure_active_sub_nav(content) def ensure_active_sub_nav(content)
...@@ -18,7 +18,7 @@ module SharedActiveTab ...@@ -18,7 +18,7 @@ module SharedActiveTab
end end
step 'no other sub tabs should be active' do step 'no other sub tabs should be active' do
expect(page).to have_selector('div.content ul.nav-links li.active', count: 1) expect(page).to have_selector('.sub-nav li.active', count: 1)
end end
step 'no other sub navs should be active' do step 'no other sub navs should be active' do
......
...@@ -179,6 +179,11 @@ module API ...@@ -179,6 +179,11 @@ module API
expose :upvotes, :downvotes expose :upvotes, :downvotes
end end
class ExternalIssue < Grape::Entity
expose :title
expose :id
end
class MergeRequest < ProjectEntity class MergeRequest < ProjectEntity
expose :target_branch, :source_branch expose :target_branch, :source_branch
expose :upvotes, :downvotes expose :upvotes, :downvotes
......
...@@ -408,5 +408,23 @@ module API ...@@ -408,5 +408,23 @@ module API
error!(errors[:access_level], 422) if errors[:access_level].any? error!(errors[:access_level], 422) if errors[:access_level].any?
not_found!(errors) not_found!(errors)
end end
def send_git_blob(repository, blob)
env['api.format'] = :txt
content_type 'text/plain'
header(*Gitlab::Workhorse.send_git_blob(repository, blob))
end
def send_git_archive(repository, ref:, format:)
header(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format))
end
def issue_entity(project)
if project.has_external_issue_tracker?
Entities::ExternalIssue
else
Entities::Issue
end
end
end end
end end
...@@ -228,11 +228,10 @@ module API ...@@ -228,11 +228,10 @@ module API
# Merge request can not be merged # Merge request can not be merged
# because user dont have permissions to push into target branch # because user dont have permissions to push into target branch
unauthorized! unless merge_request.can_be_merged_by?(current_user) unauthorized! unless merge_request.can_be_merged_by?(current_user)
not_allowed! if !merge_request.open? || merge_request.work_in_progress?
merge_request.check_if_can_be_merged not_allowed! unless merge_request.mergeable_state?
render_api_error!('Branch cannot be merged', 406) unless merge_request.can_be_merged? render_api_error!('Branch cannot be merged', 406) unless merge_request.mergeable?
if params[:sha] && merge_request.source_sha != params[:sha] if params[:sha] && merge_request.source_sha != params[:sha]
render_api_error!("SHA does not match HEAD of source branch: #{merge_request.source_sha}", 409) render_api_error!("SHA does not match HEAD of source branch: #{merge_request.source_sha}", 409)
...@@ -330,7 +329,7 @@ module API ...@@ -330,7 +329,7 @@ module API
get "#{path}/closes_issues" do get "#{path}/closes_issues" do
merge_request = user_project.merge_requests.find(params[:merge_request_id]) merge_request = user_project.merge_requests.find(params[:merge_request_id])
issues = ::Kaminari.paginate_array(merge_request.closes_issues(current_user)) issues = ::Kaminari.paginate_array(merge_request.closes_issues(current_user))
present paginate(issues), with: Entities::Issue, current_user: current_user present paginate(issues), with: issue_entity(user_project), current_user: current_user
end end
end end
end end
......
...@@ -56,8 +56,7 @@ module API ...@@ -56,8 +56,7 @@ module API
blob = Gitlab::Git::Blob.find(repo, commit.id, params[:filepath]) blob = Gitlab::Git::Blob.find(repo, commit.id, params[:filepath])
not_found! "File" unless blob not_found! "File" unless blob
content_type 'text/plain' send_git_blob repo, blob
header(*Gitlab::Workhorse.send_git_blob(repo, blob))
end end
# Get a raw blob contents by blob sha # Get a raw blob contents by blob sha
...@@ -80,10 +79,7 @@ module API ...@@ -80,10 +79,7 @@ module API
not_found! 'Blob' unless blob not_found! 'Blob' unless blob
env['api.format'] = :txt send_git_blob repo, blob
content_type blob.mime_type
header(*Gitlab::Workhorse.send_git_blob(repo, blob))
end end
# Get a an archive of the repository # Get a an archive of the repository
...@@ -98,7 +94,7 @@ module API ...@@ -98,7 +94,7 @@ module API
authorize! :download_code, user_project authorize! :download_code, user_project
begin begin
header(*Gitlab::Workhorse.send_git_archive(user_project, params[:sha], params[:format])) send_git_archive user_project.repository, ref: params[:sha], format: params[:format]
rescue rescue
not_found!('File') not_found!('File')
end end
......
...@@ -38,7 +38,6 @@ module Backup ...@@ -38,7 +38,6 @@ module Backup
end end
def upload(tar_file) def upload(tar_file)
remote_directory = Gitlab.config.backup.upload.remote_directory
$progress.print "Uploading backup archive to remote storage #{remote_directory} ... " $progress.print "Uploading backup archive to remote storage #{remote_directory} ... "
connection_settings = Gitlab.config.backup.upload.connection connection_settings = Gitlab.config.backup.upload.connection
...@@ -47,8 +46,7 @@ module Backup ...@@ -47,8 +46,7 @@ module Backup
return return
end end
connection = ::Fog::Storage.new(connection_settings) directory = connect_to_remote_directory(connection_settings)
directory = connection.directories.create(key: remote_directory)
if directory.files.create(key: tar_file, body: File.open(tar_file), public: false, if directory.files.create(key: tar_file, body: File.open(tar_file), public: false,
multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size, multipart_chunk_size: Gitlab.config.backup.upload.multipart_chunk_size,
...@@ -155,6 +153,23 @@ module Backup ...@@ -155,6 +153,23 @@ module Backup
private private
def connect_to_remote_directory(connection_settings)
connection = ::Fog::Storage.new(connection_settings)
# We only attempt to create the directory for local backups. For AWS
# and other cloud providers, we cannot guarantee the user will have
# permission to create the bucket.
if connection.service == ::Fog::Storage::Local
connection.directories.create(key: remote_directory)
else
connection.directories.get(remote_directory)
end
end
def remote_directory
Gitlab.config.backup.upload.remote_directory
end
def backup_contents def backup_contents
folders_to_backup + archives_to_backup + ["backup_information.yml"] folders_to_backup + archives_to_backup + ["backup_information.yml"]
end end
......
...@@ -56,7 +56,7 @@ module Ci ...@@ -56,7 +56,7 @@ module Ci
class TriggerRequest < Grape::Entity class TriggerRequest < Grape::Entity
expose :id, :variables expose :id, :variables
expose :commit, using: Commit expose :pipeline, using: Commit, as: :commit
end end
end end
end end
......
module Gitlab module Gitlab
module GithubImport module GithubImport
class Client class Client
GITHUB_SAFE_REMAINING_REQUESTS = 100
GITHUB_SAFE_SLEEP_TIME = 500
attr_reader :client, :api attr_reader :client, :api
def initialize(access_token) def initialize(access_token)
...@@ -11,7 +14,7 @@ module Gitlab ...@@ -11,7 +14,7 @@ module Gitlab
) )
if access_token if access_token
::Octokit.auto_paginate = true ::Octokit.auto_paginate = false
@api = ::Octokit::Client.new( @api = ::Octokit::Client.new(
access_token: access_token, access_token: access_token,
...@@ -36,7 +39,7 @@ module Gitlab ...@@ -36,7 +39,7 @@ module Gitlab
def method_missing(method, *args, &block) def method_missing(method, *args, &block)
if api.respond_to?(method) if api.respond_to?(method)
api.send(method, *args, &block) request { api.send(method, *args, &block) }
else else
super(method, *args, &block) super(method, *args, &block)
end end
...@@ -55,6 +58,34 @@ module Gitlab ...@@ -55,6 +58,34 @@ module Gitlab
def github_options def github_options
config["args"]["client_options"].deep_symbolize_keys config["args"]["client_options"].deep_symbolize_keys
end end
def rate_limit
api.rate_limit!
end
def rate_limit_exceed?
rate_limit.remaining <= GITHUB_SAFE_REMAINING_REQUESTS
end
def rate_limit_sleep_time
rate_limit.resets_in + GITHUB_SAFE_SLEEP_TIME
end
def request
sleep rate_limit_sleep_time if rate_limit_exceed?
data = yield
last_response = api.last_response
while last_response.rels[:next]
sleep rate_limit_sleep_time if rate_limit_exceed?
last_response = last_response.rels[:next].get
data.concat(last_response.data) if last_response.data.is_a?(Array)
end
data
end
end end
end end
end end
...@@ -3,9 +3,6 @@ module Gitlab ...@@ -3,9 +3,6 @@ module Gitlab
class Importer class Importer
include Gitlab::ShellAdapter include Gitlab::ShellAdapter
GITHUB_SAFE_REMAINING_REQUESTS = 100
GITHUB_SAFE_SLEEP_TIME = 500
attr_reader :client, :project, :repo, :repo_url attr_reader :client, :project, :repo, :repo_url
def initialize(project) def initialize(project)
...@@ -28,52 +25,12 @@ module Gitlab ...@@ -28,52 +25,12 @@ module Gitlab
private private
def turn_auto_pagination_off!
client.auto_paginate = false
end
def turn_auto_pagination_on!
client.auto_paginate = true
end
def rate_limit
client.rate_limit!
end
def rate_limit_exceed?
rate_limit.remaining <= GITHUB_SAFE_REMAINING_REQUESTS
end
def rate_limit_sleep_time
rate_limit.resets_in + GITHUB_SAFE_SLEEP_TIME
end
def paginate
turn_auto_pagination_off!
sleep rate_limit_sleep_time if rate_limit_exceed?
data = yield
last_response = client.last_response
while last_response.rels[:next]
sleep rate_limit_sleep_time if rate_limit_exceed?
last_response = last_response.rels[:next].get
data.concat(last_response.data) if last_response.data.is_a?(Array)
end
turn_auto_pagination_on!
data
end
def credentials def credentials
@credentials ||= project.import_data.credentials if project.import_data @credentials ||= project.import_data.credentials if project.import_data
end end
def import_labels def import_labels
labels = paginate { client.labels(repo, per_page: 100) } labels = client.labels(repo, per_page: 100)
labels.each { |raw| LabelFormatter.new(project, raw).create! } labels.each { |raw| LabelFormatter.new(project, raw).create! }
true true
...@@ -82,7 +39,7 @@ module Gitlab ...@@ -82,7 +39,7 @@ module Gitlab
end end
def import_milestones def import_milestones
milestones = paginate { client.milestones(repo, state: :all, per_page: 100) } milestones = client.milestones(repo, state: :all, per_page: 100)
milestones.each { |raw| MilestoneFormatter.new(project, raw).create! } milestones.each { |raw| MilestoneFormatter.new(project, raw).create! }
true true
...@@ -91,9 +48,9 @@ module Gitlab ...@@ -91,9 +48,9 @@ module Gitlab
end end
def import_issues def import_issues
data = paginate { client.issues(repo, state: :all, sort: :created, direction: :asc, per_page: 100) } issues = client.issues(repo, state: :all, sort: :created, direction: :asc, per_page: 100)
data.each do |raw| issues.each do |raw|
gh_issue = IssueFormatter.new(project, raw) gh_issue = IssueFormatter.new(project, raw)
if gh_issue.valid? if gh_issue.valid?
...@@ -112,7 +69,7 @@ module Gitlab ...@@ -112,7 +69,7 @@ module Gitlab
hooks = client.hooks(repo).map { |raw| HookFormatter.new(raw) }.select(&:valid?) hooks = client.hooks(repo).map { |raw| HookFormatter.new(raw) }.select(&:valid?)
disable_webhooks(hooks) disable_webhooks(hooks)
pull_requests = paginate { client.pull_requests(repo, state: :all, sort: :created, direction: :asc, per_page: 100) } pull_requests = client.pull_requests(repo, state: :all, sort: :created, direction: :asc, per_page: 100)
pull_requests = pull_requests.map { |raw| PullRequestFormatter.new(project, raw) }.select(&:valid?) pull_requests = pull_requests.map { |raw| PullRequestFormatter.new(project, raw) }.select(&:valid?)
source_branches_removed = pull_requests.reject(&:source_branch_exists?).map { |pr| [pr.source_branch_name, pr.source_branch_sha] } source_branches_removed = pull_requests.reject(&:source_branch_exists?).map { |pr| [pr.source_branch_name, pr.source_branch_sha] }
...@@ -146,14 +103,12 @@ module Gitlab ...@@ -146,14 +103,12 @@ module Gitlab
def update_webhooks(hooks, options) def update_webhooks(hooks, options)
hooks.each do |hook| hooks.each do |hook|
sleep rate_limit_sleep_time if rate_limit_exceed?
client.edit_hook(repo, hook.id, hook.name, hook.config, options) client.edit_hook(repo, hook.id, hook.name, hook.config, options)
end end
end end
def restore_branches(branches) def restore_branches(branches)
branches.each do |name, sha| branches.each do |name, sha|
sleep rate_limit_sleep_time if rate_limit_exceed?
client.create_ref(repo, "refs/heads/#{name}", sha) client.create_ref(repo, "refs/heads/#{name}", sha)
end end
...@@ -162,15 +117,12 @@ module Gitlab ...@@ -162,15 +117,12 @@ module Gitlab
def clean_up_restored_branches(branches) def clean_up_restored_branches(branches)
branches.each do |name, _| branches.each do |name, _|
sleep rate_limit_sleep_time if rate_limit_exceed?
client.delete_ref(repo, "heads/#{name}") client.delete_ref(repo, "heads/#{name}")
project.repository.rm_branch(project.creator, name) project.repository.rm_branch(project.creator, name)
end end
end end
def apply_labels(issuable) def apply_labels(issuable)
sleep rate_limit_sleep_time if rate_limit_exceed?
issue = client.issue(repo, issuable.iid) issue = client.issue(repo, issuable.iid)
if issue.labels.count > 0 if issue.labels.count > 0
...@@ -183,12 +135,12 @@ module Gitlab ...@@ -183,12 +135,12 @@ module Gitlab
end end
def import_comments(issuable) def import_comments(issuable)
comments = paginate { client.issue_comments(repo, issuable.iid, per_page: 100) } comments = client.issue_comments(repo, issuable.iid, per_page: 100)
create_comments(issuable, comments) create_comments(issuable, comments)
end end
def import_comments_on_diff(merge_request) def import_comments_on_diff(merge_request)
comments = paginate { client.pull_request_comments(repo, merge_request.iid, per_page: 100) } comments = client.pull_request_comments(repo, merge_request.iid, per_page: 100)
create_comments(merge_request, comments) create_comments(merge_request, comments)
end end
......
...@@ -12,22 +12,44 @@ module Gitlab ...@@ -12,22 +12,44 @@ module Gitlab
def scrub(node) def scrub(node)
unless Whitelist::ALLOWED_ELEMENTS.include?(node.name) unless Whitelist::ALLOWED_ELEMENTS.include?(node.name)
node.unlink node.unlink
else return
node.attributes.each do |attr_name, attr| end
valid_attributes = Whitelist::ALLOWED_ATTRIBUTES[node.name] valid_attributes = Whitelist::ALLOWED_ATTRIBUTES[node.name]
return unless valid_attributes
node.attribute_nodes.each do |attr|
attr_name = attribute_name_with_namespace(attr)
unless valid_attributes && valid_attributes.include?(attr_name) if valid_attributes.include?(attr_name)
if Whitelist::ALLOWED_DATA_ATTRIBUTES_IN_ELEMENTS.include?(node.name) && attr.unlink if unsafe_href?(attr)
attr_name.start_with?('data-')
# Arbitrary data attributes are allowed. Verify that the attribute
# is a valid data attribute.
attr.unlink unless attr_name =~ DATA_ATTR_PATTERN
else else
# Arbitrary data attributes are allowed.
unless allows_data_attribute?(node) && data_attribute?(attr)
attr.unlink attr.unlink
end end
end end
end end
end end
def attribute_name_with_namespace(attr)
if attr.namespace
"#{attr.namespace.prefix}:#{attr.name}"
else
attr.name
end
end
def allows_data_attribute?(node)
Whitelist::ALLOWED_DATA_ATTRIBUTES_IN_ELEMENTS.include?(node.name)
end
def unsafe_href?(attr)
attribute_name_with_namespace(attr) == 'xlink:href' && !attr.value.start_with?('#')
end
def data_attribute?(attr)
attr.name.start_with?('data-') && attr.name =~ DATA_ATTR_PATTERN && attr.namespace.nil?
end end
end end
end end
......
...@@ -21,27 +21,29 @@ module Gitlab ...@@ -21,27 +21,29 @@ module Gitlab
[ [
SEND_DATA_HEADER, SEND_DATA_HEADER,
"git-blob:#{encode(params)}", "git-blob:#{encode(params)}"
] ]
end end
def send_git_archive(project, ref, format) def send_git_archive(repository, ref:, format:)
format ||= 'tar.gz' format ||= 'tar.gz'
format.downcase! format.downcase!
params = project.repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format) params = repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format)
raise "Repository or ref not found" if params.empty? raise "Repository or ref not found" if params.empty?
[ [
SEND_DATA_HEADER, SEND_DATA_HEADER,
"git-archive:#{encode(params)}", "git-archive:#{encode(params)}"
] ]
end end
def send_git_diff(repository, from, to) def send_git_diff(repository, diff_refs)
from, to = diff_refs
params = { params = {
'RepoPath' => repository.path_to_repo, 'RepoPath' => repository.path_to_repo,
'ShaFrom' => from, 'ShaFrom' => from.sha,
'ShaTo' => to 'ShaTo' => to.sha
} }
[ [
......
...@@ -91,7 +91,7 @@ describe Projects::MergeRequestsController do ...@@ -91,7 +91,7 @@ describe Projects::MergeRequestsController do
id: merge_request.iid, id: merge_request.iid,
format: :diff) format: :diff)
expect(response.headers['Gitlab-Workhorse-Send-Data']).to start_with("git-diff:") expect(response.headers[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-diff:")
end end
end end
......
...@@ -17,6 +17,7 @@ describe Projects::RawController do ...@@ -17,6 +17,7 @@ describe Projects::RawController do
expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8') expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8')
expect(response.header['Content-Disposition']). expect(response.header['Content-Disposition']).
to eq("inline") to eq("inline")
expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-blob:")
end end
end end
...@@ -31,6 +32,7 @@ describe Projects::RawController do ...@@ -31,6 +32,7 @@ describe Projects::RawController do
expect(response.status).to eq(200) expect(response.status).to eq(200)
expect(response.header['Content-Type']).to eq('image/jpeg') expect(response.header['Content-Type']).to eq('image/jpeg')
expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-blob:")
end end
end end
......
...@@ -20,10 +20,11 @@ describe Projects::RepositoriesController do ...@@ -20,10 +20,11 @@ describe Projects::RepositoriesController do
project.team << [user, :developer] project.team << [user, :developer]
sign_in(user) sign_in(user)
end end
it "uses Gitlab::Workhorse" do
expect(Gitlab::Workhorse).to receive(:send_git_archive).with(project, "master", "zip")
it "uses Gitlab::Workhorse" do
get :archive, namespace_id: project.namespace.path, project_id: project.path, ref: "master", format: "zip" get :archive, namespace_id: project.namespace.path, project_id: project.path, ref: "master", format: "zip"
expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("git-archive:")
end end
context "when the service raises an error" do context "when the service raises an error" do
......
...@@ -93,11 +93,9 @@ describe "Builds" do ...@@ -93,11 +93,9 @@ describe "Builds" do
end end
it 'has button to download artifacts' do it 'has button to download artifacts' do
page.within('.artifacts') do
expect(page).to have_content 'Download' expect(page).to have_content 'Download'
end end
end end
end
context 'Build raw trace' do context 'Build raw trace' do
before do before do
...@@ -107,12 +105,10 @@ describe "Builds" do ...@@ -107,12 +105,10 @@ describe "Builds" do
end end
it do it do
page.within('.build-controls') do
expect(page).to have_link 'Raw' expect(page).to have_link 'Raw'
end end
end end
end end
end
describe "POST /:project/builds/:id/cancel" do describe "POST /:project/builds/:id/cancel" do
context "Build from project" do context "Build from project" do
...@@ -165,15 +161,10 @@ describe "Builds" do ...@@ -165,15 +161,10 @@ describe "Builds" do
end end
describe "GET /:project/builds/:id/download" do describe "GET /:project/builds/:id/download" do
context "Build from project" do
before do before do
@build.update_attributes(artifacts_file: artifacts_file) @build.update_attributes(artifacts_file: artifacts_file)
visit namespace_project_build_path(@project.namespace, @project, @build) visit namespace_project_build_path(@project.namespace, @project, @build)
page.within('.artifacts') { click_link 'Download' } click_link 'Download'
end
it { expect(page.status_code).to eq(200) }
it { expect(page.response_headers['Content-Type']).to eq(artifacts_file.content_type) }
end end
context "Build from other project" do context "Build from other project" do
...@@ -193,7 +184,7 @@ describe "Builds" do ...@@ -193,7 +184,7 @@ describe "Builds" do
@build.run! @build.run!
@build.trace = 'BUILD TRACE' @build.trace = 'BUILD TRACE'
visit namespace_project_build_path(@project.namespace, @project, @build) visit namespace_project_build_path(@project.namespace, @project, @build)
page.within('.build-controls') { click_link 'Raw' } page.within('.js-build-sidebar') { click_link 'Raw' }
end end
it 'sends the right headers' do it 'sends the right headers' do
......
...@@ -199,4 +199,19 @@ feature 'Issue filtering by Labels', feature: true do ...@@ -199,4 +199,19 @@ feature 'Issue filtering by Labels', feature: true do
end end
end end
end end
context 'dropdown filtering', js: true do
it 'should filter by label name' do
page.within '.labels-filter' do
click_button 'Label'
wait_for_ajax
fill_in 'label-name', with: 'bug'
page.within '.dropdown-content' do
expect(page).not_to have_content 'enhancement'
expect(page).to have_content 'bug'
end
end
end
end
end end
...@@ -294,40 +294,4 @@ describe 'Filter issues', feature: true do ...@@ -294,40 +294,4 @@ describe 'Filter issues', feature: true do
end end
end end
end end
describe 'filter by any author', js: true do
before do
user2 = create(:user, name: "tester")
create(:issue, project: project, author: user)
create(:issue, project: project, author: user2)
visit namespace_project_issues_path(project.namespace, project)
end
it 'should show filter by any author link' do
click_button "Author"
fill_in "Search authors", with: "tester"
page.within ".dropdown-menu-author" do
expect(page).to have_content "tester"
end
end
it 'should show filter issues by any author' do
page.within '.issues-list' do
expect(page).to have_selector ".issue", count: 2
end
click_button "Author"
fill_in "Search authors", with: "tester"
page.within ".dropdown-menu-author" do
click_link "tester"
end
page.within '.issues-list' do
expect(page).to have_selector ".issue", count: 1
end
end
end
end end
require 'spec_helper'
feature 'Only allow merge requests to be merged if the build succeeds', feature: true do
let(:project) { create(:project, :public) }
let(:merge_request) { create(:merge_request_with_diffs, source_project: project) }
before do
login_as merge_request.author
project.team << [merge_request.author, :master]
end
context 'project does not have CI enabled' do
it 'allows MR to be merged' do
visit_merge_request(merge_request)
expect(page).to have_button 'Accept Merge Request'
end
end
context 'when project has CI enabled' do
let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: merge_request.last_commit.id, ref: merge_request.source_branch) }
context 'when merge requests can only be merged if the build succeeds' do
before do
project.update_attribute(:only_allow_merge_if_build_succeeds, true)
end
context 'when CI is running' do
before { pipeline.update_column(:status, :running) }
it 'does not allow to merge immediately' do
visit_merge_request(merge_request)
expect(page).to have_button 'Merge When Build Succeeds'
expect(page).not_to have_button 'Select Merge Moment'
end
end
context 'when CI failed' do
before { pipeline.update_column(:status, :failed) }
it 'does not allow MR to be merged' do
visit_merge_request(merge_request)
expect(page).not_to have_button 'Accept Merge Request'
expect(page).to have_content('Please retry the build or push a new commit to fix the failure.')
end
end
context 'when CI succeeded' do
before { pipeline.update_column(:status, :success) }
it 'allows MR to be merged' do
visit_merge_request(merge_request)
expect(page).to have_button 'Accept Merge Request'
end
end
end
context 'when merge requests can be merged when the build failed' do
before do
project.update_attribute(:only_allow_merge_if_build_succeeds, false)
end
context 'when CI is running' do
before { pipeline.update_column(:status, :running) }
it 'allows MR to be merged immediately', js: true do
visit_merge_request(merge_request)
expect(page).to have_button 'Merge When Build Succeeds'
click_button 'Select Merge Moment'
expect(page).to have_content 'Merge Immediately'
end
end
context 'when CI failed' do
before { pipeline.update_column(:status, :failed) }
it 'allows MR to be merged' do
visit_merge_request(merge_request)
expect(page).to have_button 'Accept Merge Request'
end
end
context 'when CI succeeded' do
before { pipeline.update_column(:status, :success) }
it 'allows MR to be merged' do
visit_merge_request(merge_request)
expect(page).to have_button 'Accept Merge Request'
end
end
end
end
def visit_merge_request(merge_request)
visit namespace_project_merge_request_path(merge_request.project.namespace, merge_request.project, merge_request)
end
end
...@@ -54,7 +54,7 @@ describe 'Profile > Preferences', feature: true do ...@@ -54,7 +54,7 @@ describe 'Profile > Preferences', feature: true do
end end
end end
describe 'User changes their default dashboard' do describe 'User changes their default dashboard', js: true do
it 'creates a flash message' do it 'creates a flash message' do
select 'Starred Projects', from: 'user_dashboard' select 'Starred Projects', from: 'user_dashboard'
click_button 'Save' click_button 'Save'
...@@ -66,8 +66,10 @@ describe 'Profile > Preferences', feature: true do ...@@ -66,8 +66,10 @@ describe 'Profile > Preferences', feature: true do
select 'Starred Projects', from: 'user_dashboard' select 'Starred Projects', from: 'user_dashboard'
click_button 'Save' click_button 'Save'
click_link 'Dashboard' allowing_for_delay do
find('#logo').click
expect(page.current_path).to eq starred_dashboard_projects_path expect(page.current_path).to eq starred_dashboard_projects_path
end
click_link 'Your Projects' click_link 'Your Projects'
expect(page.current_path).to eq dashboard_projects_path expect(page.current_path).to eq dashboard_projects_path
......
...@@ -52,8 +52,8 @@ describe Banzai::Pipeline::WikiPipeline do ...@@ -52,8 +52,8 @@ describe Banzai::Pipeline::WikiPipeline do
end end
describe "Links" do describe "Links" do
let(:namespace) { build_stubbed(:namespace, name: "wiki_link_ns") } let(:namespace) { create(:namespace, name: "wiki_link_ns") }
let(:project) { build_stubbed(:empty_project, :public, name: "wiki_link_project", namespace: namespace) } let(:project) { create(:empty_project, :public, name: "wiki_link_project", namespace: namespace) }
let(:project_wiki) { ProjectWiki.new(project, double(:user)) } let(:project_wiki) { ProjectWiki.new(project, double(:user)) }
let(:page) { build(:wiki_page, wiki: project_wiki, page: OpenStruct.new(url_path: 'nested/twice/start-page')) } let(:page) { build(:wiki_page, wiki: project_wiki, page: OpenStruct.new(url_path: 'nested/twice/start-page')) }
......
...@@ -2,7 +2,7 @@ require 'spec_helper' ...@@ -2,7 +2,7 @@ require 'spec_helper'
describe DisableEmailInterceptor, lib: true do describe DisableEmailInterceptor, lib: true do
before do before do
ActionMailer::Base.register_interceptor(DisableEmailInterceptor) Mail.register_interceptor(DisableEmailInterceptor)
end end
it 'should not send emails' do it 'should not send emails' do
...@@ -14,7 +14,7 @@ describe DisableEmailInterceptor, lib: true do ...@@ -14,7 +14,7 @@ describe DisableEmailInterceptor, lib: true do
# Removing interceptor from the list because unregister_interceptor is # Removing interceptor from the list because unregister_interceptor is
# implemented in later version of mail gem # implemented in later version of mail gem
# See: https://github.com/mikel/mail/pull/705 # See: https://github.com/mikel/mail/pull/705
Mail.class_variable_set(:@@delivery_interceptors, []) Mail.unregister_interceptor(DisableEmailInterceptor)
end end
def deliver_mail def deliver_mail
......
require 'spec_helper'
describe Gitlab::Sanitizers::SVG do
let(:scrubber) { Gitlab::Sanitizers::SVG::Scrubber.new }
let(:namespace) { double(Nokogiri::XML::Namespace, prefix: 'xlink', href: 'http://www.w3.org/1999/xlink') }
let(:namespaced_attr) { double(Nokogiri::XML::Attr, name: 'href', namespace: namespace, value: '#awesome_id') }
describe '.clean' do
let(:input_svg_path) { File.join(Rails.root, 'spec', 'fixtures', 'unsanitized.svg') }
let(:data) { open(input_svg_path).read }
let(:sanitized_svg_path) { File.join(Rails.root, 'spec', 'fixtures', 'sanitized.svg') }
let(:sanitized) { open(sanitized_svg_path).read }
it 'delegates sanitization to scrubber' do
expect_any_instance_of(Gitlab::Sanitizers::SVG::Scrubber).to receive(:scrub).at_least(:once)
described_class.clean(data)
end
it 'returns sanitized data' do
expect(described_class.clean(data)).to eq(sanitized)
end
end
context 'scrubber' do
describe '#scrub' do
let(:invalid_element) { double(Nokogiri::XML::Node, name: 'invalid', value: 'invalid') }
let(:invalid_attribute) { double(Nokogiri::XML::Attr, name: 'invalid', namespace: nil) }
let(:valid_element) { double(Nokogiri::XML::Node, name: 'use') }
it 'removes an invalid element' do
expect(invalid_element).to receive(:unlink)
scrubber.scrub(invalid_element)
end
it 'removes an invalid attribute' do
allow(valid_element).to receive(:attribute_nodes) { [invalid_attribute] }
expect(invalid_attribute).to receive(:unlink)
scrubber.scrub(valid_element)
end
it 'accepts valid element' do
allow(valid_element).to receive(:attribute_nodes) { [namespaced_attr] }
expect(valid_element).not_to receive(:unlink)
scrubber.scrub(valid_element)
end
it 'accepts valid namespaced attributes' do
allow(valid_element).to receive(:attribute_nodes) { [namespaced_attr] }
expect(namespaced_attr).not_to receive(:unlink)
scrubber.scrub(valid_element)
end
end
describe '#attribute_name_with_namespace' do
it 'returns name with prefix when attribute is namespaced' do
expect(scrubber.attribute_name_with_namespace(namespaced_attr)).to eq('xlink:href')
end
end
describe '#unsafe_href?' do
let(:unsafe_attr) { double(Nokogiri::XML::Attr, name: 'href', namespace: namespace, value: 'http://evilsite.example.com/random.svg') }
it 'returns true if href attribute is an external url' do
expect(scrubber.unsafe_href?(unsafe_attr)).to be_truthy
end
it 'returns false if href atttribute is an internal reference' do
expect(scrubber.unsafe_href?(namespaced_attr)).to be_falsey
end
end
describe '#data_attribute?' do
let(:data_attr) { double(Nokogiri::XML::Attr, name: 'data-gitlab', namespace: nil, value: 'gitlab is awesome') }
let(:namespaced_attr) { double(Nokogiri::XML::Attr, name: 'data-gitlab', namespace: namespace, value: 'gitlab is awesome') }
let(:other_attr) { double(Nokogiri::XML::Attr, name: 'something', namespace: nil, value: 'content') }
it 'returns true if is a valid data attribute' do
expect(scrubber.data_attribute?(data_attr)).to be_truthy
end
it 'returns false if attribute is namespaced' do
expect(scrubber.data_attribute?(namespaced_attr)).to be_falsey
end
it 'returns false if not a data attribute' do
expect(scrubber.data_attribute?(other_attr)).to be_falsey
end
end
end
end
...@@ -11,7 +11,7 @@ describe Gitlab::Workhorse, lib: true do ...@@ -11,7 +11,7 @@ describe Gitlab::Workhorse, lib: true do
end end
it "raises an error" do it "raises an error" do
expect { subject.send_git_archive(project, "master", "zip") }.to raise_error(RuntimeError) expect { subject.send_git_archive(project.repository, ref: "master", format: "zip") }.to raise_error(RuntimeError)
end end
end end
end end
......
...@@ -219,7 +219,7 @@ describe Ci::Build, models: true do ...@@ -219,7 +219,7 @@ describe Ci::Build, models: true do
context 'and trigger variables' do context 'and trigger variables' do
let(:trigger) { create(:ci_trigger, project: project) } let(:trigger) { create(:ci_trigger, project: project) }
let(:trigger_request) { create(:ci_trigger_request_with_variables, commit: pipeline, trigger: trigger) } let(:trigger_request) { create(:ci_trigger_request_with_variables, pipeline: pipeline, trigger: trigger) }
let(:trigger_variables) do let(:trigger_variables) do
[ [
{ key: :TRIGGER_KEY, value: 'TRIGGER_VALUE', public: false } { key: :TRIGGER_KEY, value: 'TRIGGER_VALUE', public: false }
......
...@@ -455,4 +455,157 @@ describe MergeRequest, models: true do ...@@ -455,4 +455,157 @@ describe MergeRequest, models: true do
expect(user2.assigned_open_merge_request_count).to eq(1) expect(user2.assigned_open_merge_request_count).to eq(1)
end end
end end
describe '#check_if_can_be_merged' do
let(:project) { create(:project, only_allow_merge_if_build_succeeds: true) }
subject { create(:merge_request, source_project: project, merge_status: :unchecked) }
context 'when it is not broken and has no conflicts' do
it 'is marked as mergeable' do
allow(subject).to receive(:broken?) { false }
allow(project).to receive_message_chain(:repository, :can_be_merged?) { true }
expect { subject.check_if_can_be_merged }.to change { subject.merge_status }.to('can_be_merged')
end
end
context 'when broken' do
before { allow(subject).to receive(:broken?) { true } }
it 'becomes unmergeable' do
expect { subject.check_if_can_be_merged }.to change { subject.merge_status }.to('cannot_be_merged')
end
end
context 'when it has conflicts' do
before do
allow(subject).to receive(:broken?) { false }
allow(project).to receive_message_chain(:repository, :can_be_merged?) { false }
end
it 'becomes unmergeable' do
expect { subject.check_if_can_be_merged }.to change { subject.merge_status }.to('cannot_be_merged')
end
end
end
describe '#mergeable?' do
let(:project) { create(:project) }
subject { create(:merge_request, source_project: project) }
it 'returns false if #mergeable_state? is false' do
expect(subject).to receive(:mergeable_state?) { false }
expect(subject.mergeable?).to be_falsey
end
it 'return true if #mergeable_state? is true and the MR #can_be_merged? is true' do
allow(subject).to receive(:mergeable_state?) { true }
expect(subject).to receive(:check_if_can_be_merged)
expect(subject).to receive(:can_be_merged?) { true }
expect(subject.mergeable?).to be_truthy
end
end
describe '#mergeable_state?' do
let(:project) { create(:project) }
subject { create(:merge_request, source_project: project) }
it 'checks if merge request can be merged' do
allow(subject).to receive(:mergeable_ci_state?) { true }
expect(subject).to receive(:check_if_can_be_merged)
subject.mergeable?
end
context 'when not open' do
before { subject.close }
it 'returns false' do
expect(subject.mergeable_state?).to be_falsey
end
end
context 'when working in progress' do
before { subject.title = 'WIP MR' }
it 'returns false' do
expect(subject.mergeable_state?).to be_falsey
end
end
context 'when broken' do
before { allow(subject).to receive(:broken?) { true } }
it 'returns false' do
expect(subject.mergeable_state?).to be_falsey
end
end
context 'when failed' do
before { allow(subject).to receive(:broken?) { false } }
context 'when project settings restrict to merge only if build succeeds and build failed' do
before do
project.only_allow_merge_if_build_succeeds = true
allow(subject).to receive(:mergeable_ci_state?) { false }
end
it 'returns false' do
expect(subject.mergeable_state?).to be_falsey
end
end
end
end
describe '#mergeable_ci_state?' do
let(:project) { create(:empty_project, only_allow_merge_if_build_succeeds: true) }
let(:pipeline) { create(:ci_empty_pipeline) }
subject { build(:merge_request, target_project: project) }
context 'when it is only allowed to merge when build is green' do
context 'and a failed pipeline is associated' do
before do
pipeline.statuses << create(:commit_status, status: 'failed', project: project)
allow(subject).to receive(:pipeline) { pipeline }
end
it { expect(subject.mergeable_ci_state?).to be_falsey }
end
context 'when no pipeline is associated' do
before do
allow(subject).to receive(:pipeline) { nil }
end
it { expect(subject.mergeable_ci_state?).to be_truthy }
end
end
context 'when merges are not restricted to green builds' do
subject { build(:merge_request, target_project: build(:empty_project, only_allow_merge_if_build_succeeds: false)) }
context 'and a failed pipeline is associated' do
before do
pipeline.statuses << create(:commit_status, status: 'failed', project: project)
allow(subject).to receive(:pipeline) { pipeline }
end
it { expect(subject.mergeable_ci_state?).to be_truthy }
end
context 'when no pipeline is associated' do
before do
allow(subject).to receive(:pipeline) { nil }
end
it { expect(subject.mergeable_ci_state?).to be_truthy }
end
end
end
end end
...@@ -194,7 +194,7 @@ describe BambooService, models: true do ...@@ -194,7 +194,7 @@ describe BambooService, models: true do
def service(bamboo_url: 'http://gitlab.com') def service(bamboo_url: 'http://gitlab.com')
described_class.create( described_class.create(
project: build_stubbed(:empty_project), project: create(:empty_project),
properties: { properties: {
bamboo_url: bamboo_url, bamboo_url: bamboo_url,
username: 'mic', username: 'mic',
......
...@@ -182,7 +182,7 @@ describe TeamcityService, models: true do ...@@ -182,7 +182,7 @@ describe TeamcityService, models: true do
def service(teamcity_url: 'http://gitlab.com') def service(teamcity_url: 'http://gitlab.com')
described_class.create( described_class.create(
project: build_stubbed(:empty_project), project: create(:empty_project),
properties: { properties: {
teamcity_url: teamcity_url, teamcity_url: teamcity_url,
username: 'mic', username: 'mic',
......
...@@ -258,6 +258,69 @@ describe Project, models: true do ...@@ -258,6 +258,69 @@ describe Project, models: true do
end end
end end
describe :external_issue_tracker do
let(:project) { create(:project) }
let(:ext_project) { create(:redmine_project) }
context 'on existing projects with no value for has_external_issue_tracker' do
before(:each) do
project.update_column(:has_external_issue_tracker, nil)
ext_project.update_column(:has_external_issue_tracker, nil)
end
it 'updates the has_external_issue_tracker boolean' do
expect do
project.external_issue_tracker
end.to change { project.reload.has_external_issue_tracker }.to(false)
expect do
ext_project.external_issue_tracker
end.to change { ext_project.reload.has_external_issue_tracker }.to(true)
end
end
it 'returns nil and does not query services when there is no external issue tracker' do
project.build_missing_services
project.reload
expect(project).not_to receive(:services)
expect(project.external_issue_tracker).to eq(nil)
end
it 'retrieves external_issue_tracker querying services and cache it when there is external issue tracker' do
ext_project.reload # Factory returns a project with changed attributes
ext_project.build_missing_services
ext_project.reload
expect(ext_project).to receive(:services).once.and_call_original
2.times { expect(ext_project.external_issue_tracker).to be_a_kind_of(RedmineService) }
end
end
describe :cache_has_external_issue_tracker do
let(:project) { create(:project) }
it 'stores true if there is any external_issue_tracker' do
services = double(:service, external_issue_trackers: [RedmineService.new])
expect(project).to receive(:services).and_return(services)
expect do
project.cache_has_external_issue_tracker
end.to change { project.has_external_issue_tracker}.to(true)
end
it 'stores false if there is no external_issue_tracker' do
services = double(:service, external_issue_trackers: [])
expect(project).to receive(:services).and_return(services)
expect do
project.cache_has_external_issue_tracker
end.to change { project.has_external_issue_tracker}.to(false)
end
end
describe :can_have_issues_tracker_id? do describe :can_have_issues_tracker_id? do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:ext_project) { create(:redmine_project) } let(:ext_project) { create(:redmine_project) }
...@@ -859,4 +922,37 @@ describe Project, models: true do ...@@ -859,4 +922,37 @@ describe Project, models: true do
it { is_expected.to be_falsey } it { is_expected.to be_falsey }
end end
end end
describe '.where_paths_in' do
context 'without any paths' do
it 'returns an empty relation' do
expect(Project.where_paths_in([])).to eq([])
end
end
context 'without any valid paths' do
it 'returns an empty relation' do
expect(Project.where_paths_in(%w[foo])).to eq([])
end
end
context 'with valid paths' do
let!(:project1) { create(:project) }
let!(:project2) { create(:project) }
it 'returns the projects matching the paths' do
projects = Project.where_paths_in([project1.path_with_namespace,
project2.path_with_namespace])
expect(projects).to contain_exactly(project1, project2)
end
it 'returns projects regardless of the casing of paths' do
projects = Project.where_paths_in([project1.path_with_namespace.upcase,
project2.path_with_namespace.upcase])
expect(projects).to contain_exactly(project1, project2)
end
end
end
end end
...@@ -204,4 +204,37 @@ describe Service, models: true do ...@@ -204,4 +204,37 @@ describe Service, models: true do
expect(service.bamboo_url_was).to be_nil expect(service.bamboo_url_was).to be_nil
end end
end end
describe "callbacks" do
let(:project) { create(:project) }
let!(:service) do
RedmineService.new(
project: project,
active: true,
properties: {
project_url: 'http://redmine/projects/project_name_in_redmine',
issues_url: "http://redmine/#{project.id}/project_name_in_redmine/:id",
new_issue_url: 'http://redmine/projects/project_name_in_redmine/issues/new'
}
)
end
describe "on create" do
it "updates the has_external_issue_tracker boolean" do
expect do
service.save!
end.to change { service.project.has_external_issue_tracker }.from(nil).to(true)
end
end
describe "on update" do
it "updates the has_external_issue_tracker boolean" do
service.save!
expect do
service.update_attributes(active: false)
end.to change { service.project.has_external_issue_tracker }.from(true).to(false)
end
end
end
end end
...@@ -419,6 +419,15 @@ describe API::API, api: true do ...@@ -419,6 +419,15 @@ describe API::API, api: true do
expect(json_response['message']).to eq('405 Method Not Allowed') expect(json_response['message']).to eq('405 Method Not Allowed')
end end
it 'returns 405 if the build failed for a merge request that requires success' do
allow_any_instance_of(MergeRequest).to receive(:mergeable_ci_state?).and_return(false)
put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
expect(response.status).to eq(405)
expect(json_response['message']).to eq('405 Method Not Allowed')
end
it "should return 401 if user has no permissions to merge" do it "should return 401 if user has no permissions to merge" do
user2 = create(:user) user2 = create(:user)
project.team << [user2, :reporter] project.team << [user2, :reporter]
...@@ -554,6 +563,21 @@ describe API::API, api: true do ...@@ -554,6 +563,21 @@ describe API::API, api: true do
expect(json_response).to be_an Array expect(json_response).to be_an Array
expect(json_response.length).to eq(0) expect(json_response.length).to eq(0)
end end
it 'handles external issues' do
jira_project = create(:jira_project, :public, name: 'JIR_EXT1')
issue = ExternalIssue.new("#{jira_project.name}-123", jira_project)
merge_request = create(:merge_request, :simple, author: user, assignee: user, source_project: jira_project)
merge_request.update_attribute(:description, "Closes #{issue.to_reference(jira_project)}")
get api("/projects/#{jira_project.id}/merge_requests/#{merge_request.id}/closes_issues", user)
expect(response.status).to eq(200)
expect(json_response).to be_an Array
expect(json_response.length).to eq(1)
expect(json_response.first['title']).to eq(issue.title)
expect(json_response.first['id']).to eq(issue.id)
end
end end
describe 'POST :id/merge_requests/:merge_request_id/subscription' do describe 'POST :id/merge_requests/:merge_request_id/subscription' do
......
...@@ -85,7 +85,7 @@ describe Ci::API::API do ...@@ -85,7 +85,7 @@ describe Ci::API::API do
trigger = FactoryGirl.create(:ci_trigger, project: project) trigger = FactoryGirl.create(:ci_trigger, project: project)
pipeline = FactoryGirl.create(:ci_pipeline, project: project, ref: 'master') pipeline = FactoryGirl.create(:ci_pipeline, project: project, ref: 'master')
trigger_request = FactoryGirl.create(:ci_trigger_request_with_variables, commit: pipeline, trigger: trigger) trigger_request = FactoryGirl.create(:ci_trigger_request_with_variables, pipeline: pipeline, trigger: trigger)
pipeline.create_builds(nil, trigger_request) pipeline.create_builds(nil, trigger_request)
project.variables << Ci::Variable.new(key: "SECRET_KEY", value: "secret_value") project.variables << Ci::Variable.new(key: "SECRET_KEY", value: "secret_value")
......
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