Commit 747646b7 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'ce-to-ee' into 'master'

CE Upstream - Monday

Closes gitlab-ce#39776, gitlab-ce#39771 et #3544

See merge request gitlab-org/gitlab-ee!3277
parents b1e572b3 2f8a25d2
......@@ -479,7 +479,7 @@ db:migrate:reset-mysql:
variables:
SETUP_DB: "false"
script:
- git fetch origin v9.3.0-ee
- git fetch https://gitlab.com/gitlab-org/gitlab-ee.git v9.3.0-ee
- git checkout -f FETCH_HEAD
- bundle install $BUNDLE_INSTALL_FLAGS
- cp config/gitlab.yml.example config/gitlab.yml
......
......@@ -112,7 +112,7 @@ linters:
# Reports when you define the same selector twice in a single sheet.
MergeableSelector:
enabled: false
enabled: true
# Functions, mixins, variables, and placeholders should be declared
# with all lowercase letters and hyphens instead of underscores.
......
......@@ -4,7 +4,6 @@ entry.
## 10.1.1 (2017-10-31)
- No changes.
- [FIXED] Auto Devops kubernetes default namespace is now correctly built out of gitlab project group-name. !14642 (Mircea Danila Dumitrescu)
- [FIXED] Forbid the usage of `Redis#keys`. !14889
- [FIXED] Make the circuitbreaker more robust by adding higher thresholds, and multiple access attempts. !14933
......
/* globals Flash */
import Visibility from 'visibilityjs';
import axios from 'axios';
import setAxiosCsrfToken from './lib/utils/axios_utils';
import Poll from './lib/utils/poll';
import { s__ } from './locale';
import initSettingsPanels from './settings_panels';
......@@ -17,6 +18,7 @@ import Flash from './flash';
class ClusterService {
constructor(options = {}) {
this.options = options;
setAxiosCsrfToken();
}
fetchData() {
return axios.get(this.options.endpoint);
......
import axios from 'axios';
import csrf from './csrf';
export default function setAxiosCsrfToken() {
axios.defaults.headers.common[csrf.headerKey] = csrf.token;
}
......@@ -40,6 +40,10 @@
&.top-block {
border-top: 0;
.container-fluid {
background-color: inherit;
}
}
&.middle-block {
......@@ -98,10 +102,6 @@
background-color: $white-light;
border-top: 0;
}
&.top-block .container-fluid {
background-color: inherit;
}
}
.sub-header-block {
......
......@@ -12,15 +12,15 @@
border-left: 3px solid $border-color;
color: $text-color;
background: $gray-light;
}
.bs-callout h4 {
h4 {
margin-top: 0;
margin-bottom: 5px;
}
}
.bs-callout p:last-child {
p:last-child {
margin-bottom: 0;
}
}
/* Variations */
......
......@@ -56,6 +56,14 @@ hr {
.str-truncated {
@include str-truncated;
&-60 {
@include str-truncated(60%);
}
&-100 {
@include str-truncated(100%);
}
}
.block-truncated {
......@@ -85,10 +93,17 @@ hr {
font-size: 14px;
}
table a code {
table {
a code {
position: relative;
top: -2px;
margin-right: 3px;
}
td.permission-x {
background: $table-permission-x-bg !important;
text-align: center;
}
}
.loading {
......@@ -277,13 +292,6 @@ img.emoji {
margin: 5px 0;
}
table {
td.permission-x {
background: $table-permission-x-bg !important;
text-align: center;
}
}
.btn-sign-in {
text-shadow: none;
......@@ -349,10 +357,11 @@ table {
.dropzone .dz-preview .dz-progress {
border-color: $border-color !important;
}
.dropzone .dz-preview .dz-progress .dz-upload {
.dz-upload {
background: $gl-success !important;
}
}
.dz-message {
......@@ -413,16 +422,6 @@ table {
border-radius: $border-radius-default;
}
.str-truncated {
&-60 {
@include str-truncated(60%);
}
&-100 {
@include str-truncated(100%);
}
}
.tooltip {
.tooltip-inner {
word-wrap: break-word;
......
......@@ -141,17 +141,17 @@
svg {
fill: $gl-text-color-secondary;
}
}
.nav-item-name {
flex: 1;
}
li.active {
&.active {
> a {
font-weight: $gl-font-weight-bold;
}
}
}
@media (max-width: $screen-xs-max) {
left: (-$contextual-sidebar-width);
......
......@@ -728,11 +728,11 @@
.pika-single.animate-picker.is-bound {
@include set-visible;
}
.pika-single.animate-picker.is-bound.is-hidden {
&.is-hidden {
@include set-invisible;
overflow: hidden;
}
}
@mixin dropdown-item-hover {
......@@ -939,9 +939,7 @@ header.header-content .dropdown-menu.projects-dropdown-menu {
border-right: 0;
}
}
}
.projects-dropdown-container {
.projects-list-frequent-container,
.projects-list-search-container, {
padding: 8px 0;
......@@ -952,11 +950,6 @@ header.header-content .dropdown-menu.projects-dropdown-menu {
.projects-list-frequent-container li.section-empty,
.projects-list-search-container li.section-empty {
padding: 0 15px;
}
.section-header,
.projects-list-frequent-container li.section-empty,
.projects-list-search-container li.section-empty {
color: $gl-text-color-secondary;
font-size: $gl-font-size;
}
......
......@@ -165,9 +165,8 @@
&:last-child {
border-right: 0;
}
}
td.blame-commit {
&.blame-commit {
padding: 5px 10px;
min-width: 400px;
max-width: 400px;
......@@ -184,19 +183,7 @@
}
}
@for $i from 0 through 5 {
td.blame-commit-age-#{$i} {
border-left-color: mix($blame-cyan, $blame-blue, $i / 5.0 * 100%);
}
}
@for $i from 1 through 4 {
td.blame-commit-age-#{$i + 5} {
border-left-color: mix($blame-gray, $blame-cyan, $i / 4.0 * 100%);
}
}
td.line-numbers {
&.line-numbers {
float: none;
border-left: 1px solid $blame-line-numbers-border;
......@@ -206,11 +193,24 @@
}
}
td.lines {
&.lines {
padding: 0;
}
}
@for $i from 0 through 5 {
td.blame-commit-age-#{$i} {
border-left-color: mix($blame-cyan, $blame-blue, $i / 5.0 * 100%);
}
}
@for $i from 1 through 4 {
td.blame-commit-age-#{$i + 5} {
border-left-color: mix($blame-gray, $blame-cyan, $i / 4.0 * 100%);
}
}
}
&.logs {
background: $logs-bg;
max-height: 700px;
......
......@@ -463,10 +463,10 @@
word-break: break-all;
}
}
}
.filter-dropdown-item.droplab-item-active .btn {
&.droplab-item-active .btn {
@extend %filter-dropdown-item-btn-hover;
}
}
.filter-dropdown-loading {
......
......@@ -352,7 +352,77 @@
.header-user .dropdown-menu-nav,
.header-new .dropdown-menu-nav {
margin-top: $dropdown-vertical-offset;
margin-top: 4px;
}
.search {
margin: 4px 8px 0;
form {
height: 32px;
border: 0;
border-radius: $border-radius-default;
transition: border-color ease-in-out 0.15s, background-color ease-in-out 0.15s;
&:hover {
box-shadow: none;
}
}
.search-input {
color: $white-light;
background: none;
transition: color ease-in-out 0.15s;
}
.search-input::placeholder {
transition: color ease-in-out 0.15s;
}
.location-badge {
font-size: 12px;
margin: -4px 4px -4px -4px;
line-height: 25px;
padding: 4px 8px;
border-radius: 2px 0 0 2px;
height: 32px;
transition: border-color ease-in-out 0.15s;
}
&.search-active {
form {
background-color: rgba($indigo-200, .3);
box-shadow: none;
.search-input {
color: $gl-text-color;
transition: color ease-in-out 0.15s;
}
.search-input::placeholder {
color: $gl-text-color-tertiary;
}
.search-input-wrap {
.search-icon,
.clear-icon {
color: $gl-text-color-tertiary;
transition: color ease-in-out 0.15s;
}
}
}
.location-badge {
background-color: $nav-badge-bg;
border-color: $border-color;
}
.search-input-wrap {
.clear-icon {
color: $white-light;
}
}
}
}
.breadcrumbs {
......
......@@ -30,10 +30,10 @@ body {
.container {
padding-top: 0;
z-index: 5;
}
.container .content {
.content {
margin: 0;
}
}
.navless-container {
......@@ -82,26 +82,26 @@ body {
transition: background-color 0.15s, border-color 0.15s;
background-color: $orange-500;
border-color: $orange-500;
&:only-of-type {
background-color: $orange-500;
border-color: $orange-500;
}
.alert-warning + .alert-warning {
+ .alert-warning {
background-color: $orange-600;
border-color: $orange-600;
}
.alert-warning + .alert-warning + .alert-warning {
+ .alert-warning {
background-color: $orange-700;
border-color: $orange-700;
}
.alert-warning + .alert-warning + .alert-warning + .alert-warning {
+ .alert-warning {
background-color: $orange-800;
border-color: $orange-800;
}
.alert-warning:only-of-type {
background-color: $orange-500;
border-color: $orange-500;
}
}
}
}
......
......@@ -305,7 +305,8 @@ ul.indent-list {
}
}
.group-list-tree .avatar-container.content-loading {
.group-list-tree {
.avatar-container.content-loading {
position: relative;
> a,
......@@ -316,15 +317,15 @@ ul.indent-list {
> a {
padding: 2px;
}
> a .avatar {
.avatar {
border: 2px solid $white-normal;
&.identicon {
line-height: 30px;
}
}
}
&::after {
content: "";
......@@ -336,9 +337,8 @@ ul.indent-list {
border-radius: 50%;
animation: spin-avatar 3s infinite linear;
}
}
}
.group-list-tree {
.folder-toggle-wrap {
float: left;
line-height: $list-text-height;
......
......@@ -173,21 +173,8 @@
ul > li {
white-space: nowrap;
}
}
@media(max-width: $screen-xs-max) {
.atwho-view-ul {
width: 350px;
}
.atwho-view ul li {
overflow: hidden;
text-overflow: ellipsis;
}
}
// TODO: fallback to global style
.atwho-view {
// TODO: fallback to global style
.atwho-view-ul {
padding: 8px 1px;
......@@ -220,3 +207,14 @@
}
}
}
@media(max-width: $screen-xs-max) {
.atwho-view-ul {
width: 350px;
}
.atwho-view ul li {
overflow: hidden;
text-overflow: ellipsis;
}
}
......@@ -9,6 +9,7 @@
.modal-body {
position: relative;
padding: #{3 * $grid-size} #{2 * $grid-size};
background-color: $modal-body-bg;
.form-actions {
margin: #{2 * $grid-size} #{-2 * $grid-size} #{-2 * $grid-size};
......@@ -46,7 +47,3 @@ body.modal-open {
.modal.popup-dialog {
display: block;
}
.modal-body {
background-color: $modal-body-bg;
}
......@@ -367,11 +367,64 @@
}
}
.project-item-select-holder.btn-group {
.page-with-layout-nav {
.right-sidebar {
top: ($header-height + 1) * 2;
}
&.page-with-sub-nav {
.right-sidebar {
top: ($header-height + 1) * 3;
&.affix {
top: $header-height;
}
}
}
}
.with-performance-bar .page-with-layout-nav {
.right-sidebar {
top: ($header-height + 1) * 2 + $performance-bar-height;
}
&.page-with-sub-nav {
.right-sidebar {
top: ($header-height + 1) * 3 + $performance-bar-height;
&.affix {
top: $header-height + $performance-bar-height;
}
}
}
}
@media (max-width: $screen-xs-max) {
.top-area {
flex-flow: row wrap;
.nav-controls {
$controls-margin: $btn-xs-side-margin - 2px;
flex: 0 0 100%;
&.controls-flex {
display: flex;
max-width: 350px;
overflow: hidden;
float: right;
flex-flow: row wrap;
align-items: center;
justify-content: center;
padding: 0 0 $gl-padding-top;
}
.controls-item,
.controls-item-full,
.controls-item:last-child {
flex: 1 1 35%;
display: block;
width: 100%;
margin: $controls-margin;
}
}
}
.new-project-item-link {
white-space: nowrap;
......
......@@ -60,22 +60,12 @@
border-radius: $border-radius-base;
border: 1px solid $dropdown-border-color;
min-width: 175px;
color: $gl-text-color;
z-index: 999;
}
.select2-drop-mask {
z-index: 998;
color: $gl-grayish-blue;
}
.select2-drop.select2-drop-above.select2-drop-active {
border-top: 1px solid $dropdown-border-color;
margin-top: -6px;
}
.select2-results li.select2-result-with-children > .select2-result-label {
font-weight: $gl-font-weight-bold;
color: $gl-text-color;
.select2-results .select2-result-label,
.select2-more-results {
padding: 10px 15px;
}
.select2-container-active {
......@@ -144,9 +134,8 @@
.select2-drop-auto-width & {
padding: 15px 15px 5px;
}
}
.select2-search input {
input {
padding: 2px 25px 2px 5px;
background: $white-light image-url('select2.png');
background-repeat: no-repeat;
......@@ -158,44 +147,33 @@
&:focus {
border-color: $input-border-focus;
}
}
.select2-search input.select2-active {
&.select2-active {
background-color: $white-light;
background-image: image-url('select2-spinner.gif') !important;
background-repeat: no-repeat;
background-position: right 5px center !important;
background-size: 16px 16px !important;
}
}
}
.select2-results .select2-no-results,
.select2-results .select2-searching,
.select2-results .select2-ajax-error,
.select2-results .select2-selection-limit {
background: $gray-light;
display: list-item;
padding: 10px 15px;
}
.select2-results {
margin: 0;
padding: #{$gl-padding / 2} 0;
.select2-no-results,
.select2-searching,
.select2-ajax-error,
.select2-selection-limit {
background: transparent;
padding: #{$gl-padding / 2} $gl-padding;
}
padding: 10px 0;
.select2-result-label,
.select2-more-results {
padding: #{$gl-padding / 2} $gl-padding;
}
.select2-highlighted {
background: transparent;
li.select2-result-with-children > .select2-result-label {
font-weight: $gl-font-weight-bold;
color: $gl-text-color;
.select2-result-label {
background: $dropdown-item-hover-bg;
}
}
.select2-result {
padding: 0 1px;
}
}
......@@ -212,6 +190,8 @@
}
.select2-highlighted {
background: $gl-link-color !important;
.group-result {
.group-path {
color: $white-light;
......
......@@ -217,13 +217,31 @@ $white-gc-bg: #eaf2f5;
.cp { color: $white-cp; font-weight: $gl-font-weight-bold; }
.c1 { color: $white-c1; font-style: italic; }
.cs { color: $white-cs; font-weight: $gl-font-weight-bold; font-style: italic; }
.gd { color: $white-gd; background-color: $white-gd-bg; }
.gd .x { color: $white-gd-x; background-color: $white-gd-x-bg; }
.gd {
color: $white-gd;
background-color: $white-gd-bg;
.x {
color: $white-gd-x;
background-color: $white-gd-x-bg;
}
}
.ge { font-style: italic; }
.gr { color: $white-gr; }
.gh { color: $white-gh; }
.gi { color: $white-gi; background-color: $white-gi-bg; }
.gi .x { color: $white-gi-x; background-color: $white-gi-x-bg; }
.gi {
color: $white-gi;
background-color: $white-gi-bg;
.x {
color: $white-gi-x;
background-color: $white-gi-x-bg;
}
}
.go { color: $white-go; }
.gp { color: $white-gp; }
.gs { font-weight: $gl-font-weight-bold; }
......
......@@ -158,13 +158,31 @@ span.highlight_word {
.cp { color: $highlighted-cp; font-weight: $gl-font-weight-bold; }
.c1 { color: $highlighted-c1; font-style: italic; }
.cs { color: $highlighted-cs; font-weight: $gl-font-weight-bold; font-style: italic; }
.gd { color: $highlighted-gd; background-color: $highlighted-gd-bg; }
.gd .x { color: $highlighted-gd; background-color: $highlighted-gd-x-bg; }
.gd {
color: $highlighted-gd;
background-color: $highlighted-gd-bg;
.x {
color: $highlighted-gd;
background-color: $highlighted-gd-x-bg;
}
}
.ge { font-style: italic; }
.gr { color: $highlighted-gr; }
.gh { color: $highlighted-gh; }
.gi { color: $highlighted-gi; background-color: $highlighted-gi-bg; }
.gi .x { color: $highlighted-gi; background-color: $highlighted-gi-x-bg; }
.gi {
color: $highlighted-gi;
background-color: $highlighted-gi-bg;
.x {
color: $highlighted-gi;
background-color: $highlighted-gi-x-bg;
}
}
.go { color: $highlighted-go; }
.gp { color: $highlighted-gp; }
.gs { font-weight: $gl-font-weight-bold; }
......
......@@ -107,7 +107,7 @@
}
.boards-list {
height: calc(100vh - 152px);
height: calc(100vh - 105px);
width: 100%;
padding-top: 25px;
padding-bottom: 25px;
......@@ -116,8 +116,12 @@
overflow-x: scroll;
white-space: nowrap;
@media (min-width: $screen-sm-min) {
height: calc(100vh - 222px);
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
height: calc(100vh - 90px);
}
@media (min-width: $screen-md-min) {
height: calc(100vh - 160px);
min-height: 475px;
}
}
......
......@@ -68,19 +68,19 @@
&.affix {
top: $header-height;
}
// with sidebar
&.affix.sidebar-expanded {
&.sidebar-expanded {
right: 306px;
left: 16px;
}
// without sidebar
&.affix.sidebar-collapsed {
&.sidebar-collapsed {
right: 16px;
left: 16px;
}
}
&.affix-top {
position: absolute;
......
......@@ -22,6 +22,11 @@
}
}
}
svg {
width: 136px;
height: 136px;
}
}
.col-headers {
......@@ -155,11 +160,6 @@
}
}
.landing svg {
width: 136px;
height: 136px;
}
.fa-spinner {
font-size: 28px;
position: relative;
......
......@@ -380,6 +380,10 @@
}
}
}
.line_content {
white-space: pre-wrap;
}
}
.file-content .diff-file {
......@@ -387,10 +391,6 @@
border: 0;
}
.diff-file .line_content {
white-space: pre-wrap;
}
.diff-wrap-lines .line_content {
white-space: pre-wrap;
}
......
......@@ -415,23 +415,6 @@
width: 100%;
padding: 0;
padding-bottom: 100%;
}
.prometheus-svg-container > svg {
position: absolute;
height: 100%;
width: 100%;
left: 0;
top: 0;
text {
fill: $gl-text-color;
stroke-width: 0;
}
.text-metric-bold {
font-weight: $gl-font-weight-bold;
}
.label-axis-text {
fill: $black;
......@@ -446,19 +429,27 @@
font-size: 12px;
}
.legend-axis-text {
> svg {
position: absolute;
height: 100%;
width: 100%;
left: 0;
top: 0;
.label-axis-text,
.text-metric-usage {
fill: $black;
font-weight: $gl-font-weight-normal;
font-size: 12px;
}
.tick {
> line {
stroke: $gray-darker;
.legend-axis-text {
fill: $black;
}
> text {
.tick > text {
font-size: 12px;
}
}
.text-metric-title {
font-size: 12px;
......@@ -484,4 +475,5 @@
font-size: 8px;
}
}
}
}
......@@ -127,7 +127,16 @@
}
.right-sidebar {
a:not(.btn-retry),
position: absolute;
top: $header-height;
bottom: 0;
right: 0;
transition: width .3s;
background: $gray-light;
z-index: 200;
overflow: hidden;
a,
.btn-link {
color: inherit;
}
......@@ -228,17 +237,6 @@
.btn-clipboard:hover {
color: $gl-text-color;
}
}
.right-sidebar {
position: absolute;
top: $header-height;
bottom: 0;
right: 0;
transition: width $right-sidebar-transition-duration;
background: $gray-light;
z-index: 200;
overflow: hidden;
.issuable-sidebar {
width: calc(100% + 100px);
......
......@@ -109,6 +109,30 @@
border-top-right-radius: $border-radius-default;
border-top-left-radius: $border-radius-default;
// Ldap configurations may need more tabs & the tab labels are user generated (arbitrarily long).
// These styles prevent this from breaking the layout, and only applied when providers are configured.
&.custom-provider-tabs {
flex-wrap: wrap;
li {
min-width: 85px;
flex-basis: auto;
// This styles tab elements that have wrapped to a second line. We cannot easily predict when this will happen.
// We are making somewhat of an assumption about the configuration here: that users do not have more than
// 3 LDAP servers configured (in addition to standard login) and they are not using especially long names for any
// of them. If either condition is false, this will work as expected. If both are true, there may be a missing border
// above one of the bottom row elements. If you know a better way, please implement it!
&:nth-child(n+5) {
border-top: 1px solid $border-color;
}
}
a {
font-size: 16px;
}
}
li {
flex: 1;
text-align: center;
......@@ -154,32 +178,6 @@
}
}
// Ldap configurations may need more tabs & the tab labels are user generated (arbitrarily long).
// These styles prevent this from breaking the layout, and only applied when providers are configured.
.new-session-tabs.custom-provider-tabs {
flex-wrap: wrap;
li {
min-width: 85px;
flex-basis: auto;
// This styles tab elements that have wrapped to a second line. We cannot easily predict when this will happen.
// We are making somewhat of an assumption about the configuration here: that users do not have more than
// 3 LDAP servers configured (in addition to standard login) and they are not using especially long names for any
// of them. If either condition is false, this will work as expected. If both are true, there may be a missing border
// above one of the bottom row elements. If you know a better way, please implement it!
&:nth-child(n+5) {
border-top: 1px solid $border-color;
}
}
a {
font-size: 16px;
}
}
.form-control {
&:active,
&:focus {
......@@ -231,10 +229,9 @@
margin: 0;
padding: 0;
height: 100%;
}
// Fixes footer container to bottom of viewport
.devise-layout-html body {
// Fixes footer container to bottom of viewport
body {
// offset height of fixed header + 1 to avoid scroll
height: calc(100% - 51px);
margin: 0;
......@@ -262,4 +259,5 @@
padding: 0 15px 65px;
}
}
}
}
......@@ -55,9 +55,17 @@
width: auto;
}
}
&.existing-title {
@media (min-width: $screen-sm-min) {
float: left;
}
}
}
.member-form-control {
@include new-style-dropdown;
@media (max-width: $screen-xs-max) {
padding-bottom: 5px;
margin-left: 0;
......@@ -70,12 +78,6 @@
line-height: 43px;
}
.member.existing-title {
@media (min-width: $screen-sm-min) {
float: left;
}
}
.member-search-form {
@include new-style-dropdown;
......@@ -331,7 +333,3 @@
}
}
}
.member-form-control {
@include new-style-dropdown;
}
......@@ -155,6 +155,10 @@
&.media > *:first-child {
margin-right: 10px;
}
.approve-btn {
margin-right: 5px;
}
}
.mr-widget-pipeline-graph {
......@@ -190,6 +194,10 @@
overflow: hidden;
word-break: break-all;
&.media > *:first-child {
margin-right: 10px;
}
&.label-truncated {
position: relative;
display: inline-block;
......@@ -207,14 +215,7 @@
background-color: $gray-light;
}
}
}
.mr-widget-help {
padding: 10px 16px 10px 48px;
font-style: italic;
}
.mr-widget-body {
h4 {
float: left;
font-weight: $gl-font-weight-bold;
......@@ -237,6 +238,10 @@
margin-right: 7px;
}
.approve-btn {
margin-right: 5px;
}
label {
font-weight: $gl-font-weight-normal;
}
......@@ -329,6 +334,22 @@
}
}
.mini-pipeline-graph-dropdown-menu .mini-pipeline-graph-dropdown-item {
display: flex;
align-items: center;
.ci-status-text,
.ci-status-icon {
top: 0;
margin-right: 10px;
}
}
.mr-widget-help {
padding: 10px 16px 10px 48px;
font-style: italic;
}
.ci-coverage {
float: right;
}
......@@ -347,10 +368,6 @@
flex-wrap: wrap;
}
.mr-widget-body-controls {
flex-wrap: wrap;
}
.mr_source_commit,
.mr_target_commit {
margin-bottom: 0;
......@@ -460,9 +477,8 @@
padding-bottom: 0;
}
}
}
.mr-info-list.mr-memory-usage {
&.mr-memory-usage {
p {
float: left;
}
......@@ -471,6 +487,7 @@
float: left;
margin-left: 5px;
}
}
}
.mr-source-target {
......
......@@ -66,6 +66,15 @@
height: 6px;
margin: 0;
}
.sidebar-collapsed-icon {
clear: both;
padding: 15px 5px 5px;
.progress {
margin: 5px 0;
}
}
}
.collapsed-milestone-date {
......@@ -93,17 +102,6 @@
margin-right: 0;
}
.milestone-progress {
.sidebar-collapsed-icon {
clear: both;
padding: 15px 5px 5px;
.progress {
margin: 5px 0;
}
}
}
.right-sidebar-collapsed & {
.reference {
border-top: 1px solid $border-gray-normal;
......@@ -156,18 +154,16 @@
.status-box {
margin-top: 0;
order: 1;
}
.milestone-buttons {
margin-left: auto;
}
order: 2;
.status-box {
order: 1;
.verbose {
display: none;
}
.milestone-buttons {
order: 2;
}
.header-text-content {
......@@ -175,10 +171,6 @@
width: 100%;
}
.milestone-buttons .verbose {
display: none;
}
@media (min-width: $screen-xs-min) {
.milestone-buttons .verbose {
display: inline;
......
......@@ -111,24 +111,9 @@
margin: auto;
align-items: center;
.icon {
margin-right: $issuable-warning-icon-margin;
}
}
.disabled-comment .issuable-note-warning {
border: 0;
border-radius: $label-border-radius;
padding-top: $gl-vert-padding;
padding-bottom: $gl-vert-padding;
.icon svg {
position: relative;
top: 2px;
margin-right: $btn-xs-side-margin;
width: $gl-font-size;
height: $gl-font-size;
fill: $orange-600;
.md-area {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
......@@ -155,11 +140,6 @@
}
}
.issuable-note-warning + .md-area {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.discussion-form {
background-color: $white-light;
}
......
......@@ -312,7 +312,21 @@ ul.notes {
}
}
.diff-file .notes_holder {
.diff-file {
.is-over {
.add-diff-note {
display: inline-block;
}
}
// Merge request notes in diffs
// Diff is inline
.notes_content .note-header .note-headline-light {
display: inline-block;
position: relative;
}
.notes_holder {
font-family: $regular_font;
td {
......@@ -366,6 +380,7 @@ ul.notes {
}
}
}
}
}
.discussion-header,
......@@ -457,8 +472,9 @@ ul.notes {
margin-left: 10px;
color: $gray-darkest;
.btn-group > .discussion-next-btn {
margin-left: -1px;
@include notes-media('max', $screen-md-max) {
float: none;
margin-left: 0;
}
}
......@@ -499,13 +515,6 @@ ul.notes {
min-width: 180px;
}
.discussion-actions {
@include notes-media('max', $screen-md-max) {
float: none;
margin-left: 0;
}
}
.note-actions-item {
margin-left: 12px;
display: flex;
......@@ -662,14 +671,6 @@ ul.notes {
}
}
.diff-file {
.is-over {
.add-diff-note {
display: inline-block;
}
}
}
.disabled-comment {
background-color: $gray-light;
border-radius: $border-radius-base;
......@@ -711,9 +712,8 @@ ul.notes {
svg path {
fill: $gray-darkest;
}
}
.btn.discussion-create-issue-btn {
&.discussion-create-issue-btn {
margin-left: -4px;
border-radius: 0;
border-right: 0;
......@@ -728,6 +728,7 @@ ul.notes {
}
}
}
}
}
.line-resolve-all {
......@@ -798,12 +799,3 @@ ul.notes {
.line-resolve-text {
vertical-align: middle;
}
// Merge request notes in diffs
.diff-file {
// Diff is inline
.notes_content .note-header .note-headline-light {
display: inline-block;
position: relative;
}
}
......@@ -202,6 +202,25 @@
}
}
/**
* Play button with icon in dropdowns
*/
.no-btn {
border: 0;
background: none;
outline: none;
width: 100%;
text-align: left;
.icon-play {
position: relative;
top: 2px;
margin-right: 5px;
height: 13px;
width: 12px;
}
}
.duration,
.finished-at {
color: $gl-text-color-secondary;
......@@ -481,6 +500,9 @@
// Action Icons in big pipeline-graph nodes
.ci-action-icon-container.ci-action-icon-wrapper {
position: absolute;
right: 5px;
top: 5px;
height: 30px;
width: 30px;
background: $white-light;
......@@ -491,6 +513,10 @@
&:hover {
background-color: $stage-hover-bg;
border: 1px solid $dropdown-toggle-active-border-color;
svg {
fill: $gl-text-color;
}
}
svg {
......@@ -509,16 +535,6 @@
left: 8px;
}
}
&:hover svg {
fill: $gl-text-color;
}
}
.ci-action-icon-container {
position: absolute;
right: 5px;
top: 5px;
}
.ci-status-icon svg {
......@@ -765,43 +781,44 @@ a.linked-pipeline-mini-item {
left: -3px;
position: relative;
top: -2px;
}
&:hover svg,
&:focus svg {
fill: $gl-text-color;
}
&.icon-action-retry,
&.icon-action-play {
svg {
width: #{$ci-action-icon-size - 6};
height: #{$ci-action-icon-size - 6};
left: 8px;
}
}
svg.icon-action-stop,
svg.icon-action-cancel {
&.icon-action-stop,
&.icon-action-cancel {
width: 12px;
height: 12px;
top: 1px;
left: -1px;
}
svg.icon-action-play {
&.icon-action-play {
width: 11px;
height: 11px;
top: 1px;
left: 1px;
}
svg.icon-action-retry {
&.icon-action-retry {
width: 16px;
height: 16px;
top: 0;
left: -3px;
}
}
&:hover svg,
&:focus svg {
fill: $gl-text-color;
}
&.icon-action-retry,
&.icon-action-play {
svg {
width: #{$ci-action-icon-size - 6};
height: #{$ci-action-icon-size - 6};
left: 8px;
}
}
}
......@@ -870,13 +887,10 @@ a.linked-pipeline-mini-item {
left: 100%;
top: -10px;
box-shadow: 0 1px 5px $black-transparent;
}
/**
/**
* Top arrow in the dropdown in the big pipeline graph
*/
.big-pipeline-graph-dropdown-menu {
&::before,
&::after {
content: '';
......@@ -938,12 +952,11 @@ a.linked-pipeline-mini-item {
margin-top: 1px;
border-bottom-color: $white-light;
}
}
/**
/**
* Center dropdown menu in mini graph
*/
.mini-pipeline-graph-dropdown-menu.dropdown-menu {
&.dropdown-menu {
transform: translate(-80%, 0);
min-width: 150px;
......@@ -953,7 +966,9 @@ a.linked-pipeline-mini-item {
left: 50%;
min-width: 240px;
}
}
}
/**
* Terminal
*/
......@@ -977,25 +992,6 @@ a.linked-pipeline-mini-item {
}
}
/**
* Play button with icon in dropdowns
*/
.ci-table .no-btn {
border: 0;
background: none;
outline: none;
width: 100%;
text-align: left;
.icon-play {
position: relative;
top: 2px;
margin-right: 5px;
height: 13px;
width: 12px;
}
}
.linked-pipeline-mini-list {
display: inline-block;
......
......@@ -96,7 +96,8 @@
transition: background 2s ease-out;
&:disabled {
opacity: 0.75;
opacity: 0.5;
pointer-events: none;
}
.highlight-changes & {
......@@ -785,9 +786,8 @@ a.deploy-project-label {
.nav {
padding-top: 12px;
padding-bottom: 12px;
}
.nav > li {
> li {
display: inline-block;
&:not(:last-child) {
......@@ -802,9 +802,8 @@ a.deploy-project-label {
float: right;
}
}
}
.nav > li > a {
> a {
padding: 0;
background-color: transparent;
font-size: 14px;
......@@ -816,6 +815,8 @@ a.deploy-project-label {
color: $gl-text-color;
}
}
}
}
li.missing {
border: 1px dashed $border-gray-normal-dashed;
......@@ -1202,13 +1203,6 @@ a.allowed-to-push {
}
}
.project-repo-select {
&.disabled {
opacity: 0.5;
pointer-events: none;
}
}
.variables-table {
table-layout: fixed;
......
......@@ -78,6 +78,10 @@ input[type="checkbox"]:hover {
}
.search-input-wrap {
// Fallback if flexbox is not supported
display: inline-block;
width: 100%;
.search-icon,
.clear-icon {
position: absolute;
......
......@@ -266,11 +266,11 @@
margin-left: 5px;
background: $badge-bg;
}
}
/* Ensure we don't add border if there's only single li */
li + li {
+ li {
border-top: 1px solid $border-color;
}
}
}
}
......@@ -5,11 +5,11 @@ table .sherlock-code {
.sherlock-code {
pre {
word-wrap: normal;
}
pre code {
code {
white-space: pre;
}
}
}
.sherlock-line-samples-table {
......@@ -21,13 +21,13 @@ table .sherlock-code {
text-align: right;
padding: 0 10px !important;
}
.slow {
color: $red-500;
font-weight: $gl-font-weight-bold;
}
}
.sherlock-file-sample pre {
padding-top: 28px !important;
}
.sherlock-line-samples-table .slow {
color: $red-500;
font-weight: $gl-font-weight-bold;
}
......@@ -40,17 +40,17 @@
@media (max-width: $screen-xs-max) {
width: 100%;
}
}
.person .spark {
.spark {
display: block;
background: $stat-graph-common-bg;
width: 100%;
}
.person .area-contributor {
.area-contributor {
fill: $stat-graph-orange-fill;
}
}
}
.selection rect {
......
......@@ -161,11 +161,11 @@ ul.wiki-pages-list.content-list {
list-style: none;
margin-left: 0;
padding-left: 15px;
}
ul li {
li {
padding: 5px 0;
}
}
}
.wiki {
......
......@@ -95,10 +95,9 @@ module LfsRequest
@storage_project ||= begin
result = project
loop do
break unless result.forked?
result = result.forked_from_project
end
# TODO: Make this go to the fork_network root immeadiatly
# dependant on the discussion in: https://gitlab.com/gitlab-org/gitlab-ce/issues/39769
result = result.fork_source while result.forked?
result
end
......
......@@ -4,6 +4,7 @@ module NotesActions
included do
before_action :set_polling_interval_header, only: [:index]
before_action :noteable, only: :index
before_action :authorize_admin_note!, only: [:update, :destroy]
before_action :note_project, only: [:create]
end
......@@ -188,7 +189,7 @@ module NotesActions
end
def noteable
@noteable ||= notes_finder.target
@noteable ||= notes_finder.target || render_404
end
def last_fetched_at
......
......@@ -112,7 +112,15 @@ module ProjectsHelper
def remove_fork_project_message(project)
_("You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?") %
{ forked_from_project: @project.forked_from_project.name_with_namespace }
{ forked_from_project: fork_source_name(project) }
end
def fork_source_name(project)
if @project.fork_source
@project.fork_source.full_name
else
@project.fork_network&.deleted_root_project_name
end
end
def project_nav_tabs
......@@ -142,8 +150,8 @@ module ProjectsHelper
def can_change_visibility_level?(project, current_user)
return false unless can?(current_user, :change_visibility_level, project)
if project.forked?
project.forked_from_project.visibility_level > Gitlab::VisibilityLevel::PRIVATE
if project.fork_source
project.fork_source.visibility_level > Gitlab::VisibilityLevel::PRIVATE
else
true
end
......
......@@ -110,7 +110,7 @@ class Environment < ActiveRecord::Base
end
def ref_path
"refs/#{Repository::REF_ENVIRONMENTS}/#{generate_slug}"
"refs/#{Repository::REF_ENVIRONMENTS}/#{slug}"
end
def formatted_external_url
......@@ -168,6 +168,10 @@ class Environment < ActiveRecord::Base
end
end
def slug
super.presence || generate_slug
end
# An environment name is not necessarily suitable for use in URLs, DNS
# or other third-party contexts, so provide a slugified version. A slug has
# the following properties:
......
......@@ -12,4 +12,8 @@ class ForkNetwork < ActiveRecord::Base
def find_forks_in(other_projects)
projects.where(id: other_projects)
end
def merge_requests
MergeRequest.where(target_project: projects)
end
end
......@@ -1039,6 +1039,10 @@ class Project < ActiveRecord::Base
!(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
end
def fork_source
forked_from_project || fork_network&.root_project
end
def personal?
!group
end
......@@ -1488,7 +1492,8 @@ class Project < ActiveRecord::Base
{ key: 'CI_PROJECT_PATH', value: full_path, public: true },
{ key: 'CI_PROJECT_PATH_SLUG', value: full_path_slug, public: true },
{ key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path, public: true },
{ key: 'CI_PROJECT_URL', value: web_url, public: true }
{ key: 'CI_PROJECT_URL', value: web_url, public: true },
{ key: 'CI_PROJECT_VISIBILITY', value: Gitlab::VisibilityLevel.string_level(visibility_level), public: true }
]
end
......
......@@ -3,18 +3,24 @@ module Projects
def execute
return unless @project.forked?
@project.forked_from_project.lfs_objects.find_each do |lfs_object|
if fork_source = @project.fork_source
fork_source.lfs_objects.find_each do |lfs_object|
lfs_object.projects << @project
end
merge_requests = @project.forked_from_project.merge_requests.opened.from_project(@project)
refresh_forks_count(fork_source)
end
merge_requests = @project.fork_network
.merge_requests
.opened
.where.not(target_project: @project)
.from_project(@project)
merge_requests.each do |mr|
::MergeRequests::CloseService.new(@project, @current_user).execute(mr)
end
refresh_forks_count(@project.forked_from_project)
@project.fork_network_member.destroy
@project.forked_project_link.destroy
end
......
- empty_repo = @project.empty_repo?
- fork_network = @project.fork_network
- forked_from_project = @project.forked_from_project || fork_network&.root_project
.project-home-panel.text-center{ class: ("empty-project" if empty_repo) }
.limit-container-width{ class: container_class }
.avatar-container.s70.project-avatar
......@@ -16,13 +15,13 @@
- if @project.forked?
%p
- if forked_from_project
- if @project.fork_source
#{ s_('ForkedFromProjectPath|Forked from') }
= link_to project_path(forked_from_project) do
= forked_from_project.full_name
= link_to project_path(@project.fork_source) do
= fork_source_name(@project)
- else
- deleted_message = s_('ForkedFromProjectPath|Forked from %{project_name} (deleted)')
= deleted_message % { project_name: fork_network.deleted_root_project_name }
= deleted_message % { project_name: fork_source_name(@project) }
- if @project.mirror?
- import_url = @project.safe_import_url
......
......@@ -185,7 +185,10 @@
%p
This will remove the fork relationship to source project
= succeed "." do
= link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project)
- if @project.fork_source
= link_to(fork_source_name(@project), project_path(@project.fork_source))
- else
= fork_source_name(@project)
= form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' }) do |f|
%p
%strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source.
......
---
title: Expose project visibility as CI variable - CI_PROJECT_VISIBILITY
merge_request: 15193
author:
type: added
---
title: Stop merge requests with thousands of commits from timing out
merge_request: 15063
author:
type: performance
---
title: Fix issues with forked projects of which the source was deleted
merge_request: 15150
author:
type: fixed
---
title: Enable MergeableSelector in scss-lint
merge_request: 12810
author: Takuya Noguchi
---
title: Fix widget of locked merge requests not being presented
title: Fix a migration that adds merge_requests_ff_only_enabled column to MR table
merge_request:
author:
type: fixed
---
title: Adds callback functions for initial request in clusters page
title: Render 404 when polling commit notes without having permissions
merge_request:
author:
type: fixed
---
title: Normalize LDAP DN when looking up identity
title: Avoid regenerating the ref path for the environment
merge_request:
author:
type: fixed
......@@ -615,7 +615,7 @@ production: &base
# Gitaly settings
gitaly:
# Path to the directory containing Gitaly client executables.
client_path: /home/git/gitaly
client_path: /home/git/gitaly/bin
# Default Gitaly authentication token. Can be overriden per storage. Can
# be left blank when Gitaly is running locally on a Unix socket, which
# is the normal way to deploy Gitaly.
......
......@@ -8,8 +8,12 @@ class AddFastForwardOptionToProject < ActiveRecord::Migration
disable_ddl_transaction!
def up
# We put condition here because of a mistake we made a couple of years ago
# see https://gitlab.com/gitlab-org/gitlab-ce/issues/39382#note_45716103
unless column_exists?(:projects, :merge_requests_ff_only_enabled)
add_column_with_default(:projects, :merge_requests_ff_only_enabled, :boolean, default: false)
end
end
def down
if column_exists?(:projects, :merge_requests_ff_only_enabled)
......
......@@ -67,6 +67,7 @@ future GitLab releases.**
| **CI_PROJECT_PATH** | 8.10 | 0.5 | The namespace with project name |
| **CI_PROJECT_PATH_SLUG** | 9.3 | all | `$CI_PROJECT_PATH` lowercased and with everything except `0-9` and `a-z` replaced with `-`. Use in URLs and domain names. |
| **CI_PROJECT_URL** | 8.10 | 0.5 | The HTTP address to access project |
| **CI_PROJECT_VISIBILITY** | 10.3 | all | The project visibility (internal, private, public) |
| **CI_REGISTRY** | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of GitLab's Container Registry |
| **CI_REGISTRY_IMAGE** | 8.10 | 0.5 | If the Container Registry is enabled for the project it returns the address of the registry tied to the specific project |
| **CI_REGISTRY_PASSWORD** | 9.0 | all | The password to use to push containers to the GitLab Container Registry |
......
......@@ -144,6 +144,12 @@ has a `.gitlab-ci.yml` or not:
All you need to do is remove your existing `.gitlab-ci.yml`, and you can even
do that in a branch to test Auto DevOps before committing to `master`.
NOTE: **Note:**
If you are a GitLab Administrator, you can enable Auto DevOps instance wide
in **Admin Area > Settings > Continuous Integration and Deployment**. Doing that,
all the projects that haven't explicitly set an option will have Auto DevOps
enabled by default.
## Stages of Auto DevOps
The following sections describe the stages of Auto DevOps. Read them carefully
......
......@@ -46,14 +46,14 @@ module Gitlab
# Returns the current real time in a given precision.
#
# Returns the time as a Float.
# Returns the time as a Fixnum.
def self.real_time(precision = :millisecond)
Process.clock_gettime(Process::CLOCK_REALTIME, precision)
end
# Returns the current monotonic clock time in a given precision.
#
# Returns the time as a Float.
# Returns the time as a Fixnum.
def self.monotonic_time(precision = :millisecond)
Process.clock_gettime(Process::CLOCK_MONOTONIC, precision)
end
......
......@@ -36,7 +36,7 @@ module Gitlab
end
def track_query(raw_query, bindings, start, finish)
duration = finish - start
duration = (finish - start) * 1000.0
query_info = { duration: duration.round(3), sql: raw_query }
PEEK_DB_CLIENT.query_details << query_info
......
......@@ -89,9 +89,11 @@ module Gitlab
ActiveSupport::Notifications.subscribe('sql.active_record') do |_, start, finish, _, data|
next unless same_thread?
unless data.fetch(:cached, data[:name] == 'CACHE')
track_query(data[:sql].strip, data[:binds], start, finish)
end
end
end
def subscribe_to_action_view
regex = /render_(template|partial)\.action_view/
......
require 'spec_helper'
describe LfsRequest do
include ProjectForksHelper
controller(Projects::GitHttpClientController) do
# `described_class` is not available in this context
include LfsRequest # rubocop:disable RSpec/DescribedClass
def show
storage_project
render nothing: true
end
def project
@project ||= Project.find(params[:id])
end
def download_request?
true
end
def ci?
false
end
end
let(:project) { create(:project, :public) }
before do
stub_lfs_setting(enabled: true)
end
describe '#storage_project' do
it 'assigns the project as storage project' do
get :show, id: project.id
expect(assigns(:storage_project)).to eq(project)
end
it 'assigns the source of a forked project' do
forked_project = fork_project(project)
get :show, id: forked_project.id
expect(assigns(:storage_project)).to eq(project)
end
end
end
......@@ -105,6 +105,19 @@ describe Projects::NotesController do
expect(note_json[:discussion_html]).to be_nil
expect(note_json[:diff_discussion_html]).to be_nil
end
context 'when user cannot read commit' do
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?).with(user, :download_code, project).and_return(false)
end
it 'renders 404' do
get :index, params
expect(response).to have_gitlab_http_status(404)
end
end
end
end
......
require 'spec_helper'
feature 'Settings for a forked project', :js do
include ProjectForksHelper
let(:user) { create(:user) }
let(:original_project) { create(:project) }
let(:forked_project) { fork_project(original_project, user) }
before do
original_project.add_master(user)
forked_project.add_master(user)
sign_in(user)
end
shared_examples 'project settings for a forked projects' do
it 'allows deleting the link to the forked project' do
visit edit_project_path(forked_project)
click_button 'Remove fork relationship'
wait_for_requests
fill_in('confirm_name_input', with: forked_project.name)
click_button('Confirm')
expect(page).to have_content('The fork relationship has been removed.')
expect(forked_project.reload.forked?).to be_falsy
end
end
it_behaves_like 'project settings for a forked projects'
context 'when the original project is deleted' do
before do
original_project.destroy!
end
it_behaves_like 'project settings for a forked projects'
end
end
......@@ -77,12 +77,24 @@ describe Gitlab::Ci::CronParser do
it_behaves_like "returns time in the future"
context 'when PST (Pacific Standard Time)' do
it 'converts time in server time zone' do
Timecop.freeze(Time.utc(2017, 1, 1)) do
expect(subject.hour).to eq(hour_in_utc)
end
end
end
context 'when PDT (Pacific Daylight Time)' do
it 'converts time in server time zone' do
Timecop.freeze(Time.utc(2017, 6, 1)) do
expect(subject.hour).to eq(hour_in_utc)
end
end
end
end
end
context 'when cron_timezone is ActiveSupport::TimeZone format' do
before do
allow(Time).to receive(:zone)
......@@ -100,10 +112,22 @@ describe Gitlab::Ci::CronParser do
it_behaves_like "returns time in the future"
context 'when CET (Central European Time)' do
it 'converts time in server time zone' do
Timecop.freeze(Time.utc(2017, 1, 1)) do
expect(subject.hour).to eq(hour_in_utc)
end
end
end
context 'when CEST (Central European Summer Time)' do
it 'converts time in server time zone' do
Timecop.freeze(Time.utc(2017, 6, 1)) do
expect(subject.hour).to eq(hour_in_utc)
end
end
end
end
context 'when cron_timezone is Eastern Time (US & Canada)' do
let(:cron) { '* 0 * * *' }
......@@ -111,12 +135,24 @@ describe Gitlab::Ci::CronParser do
it_behaves_like "returns time in the future"
context 'when EST (Eastern Standard Time)' do
it 'converts time in server time zone' do
Timecop.freeze(Time.utc(2017, 1, 1)) do
expect(subject.hour).to eq(hour_in_utc)
end
end
end
context 'when EDT (Eastern Daylight Time)' do
it 'converts time in server time zone' do
Timecop.freeze(Time.utc(2017, 6, 1)) do
expect(subject.hour).to eq(hour_in_utc)
end
end
end
end
end
end
context 'when cron and cron_timezone are invalid' do
let(:cron) { 'invalid_cron' }
......
......@@ -1290,6 +1290,7 @@ describe Ci::Build do
{ key: 'CI_PROJECT_PATH_SLUG', value: project.full_path_slug, public: true },
{ key: 'CI_PROJECT_NAMESPACE', value: project.namespace.full_path, public: true },
{ key: 'CI_PROJECT_URL', value: project.web_url, public: true },
{ key: 'CI_PROJECT_VISIBILITY', value: 'private', public: true },
{ key: 'CI_PIPELINE_ID', value: pipeline.id.to_s, public: true },
{ key: 'CI_CONFIG_PATH', value: pipeline.ci_yaml_file_path, public: true },
{ key: 'CI_REGISTRY_USER', value: 'gitlab-ci-token', public: true },
......
......@@ -635,6 +635,15 @@ describe Environment do
expect(environment.slug).to eq(original_slug)
end
it "regenerates the slug if nil" do
environment = build(:environment, slug: nil)
new_slug = environment.slug
expect(new_slug).not_to be_nil
expect(environment.slug).to eq(new_slug)
end
end
describe '#generate_slug' do
......@@ -671,6 +680,12 @@ describe Environment do
it 'returns a path that uses the slug and does not have spaces' do
expect(environment.ref_path).to start_with('refs/environments/staging-review-1-')
end
it "doesn't change when the slug is nil initially" do
environment.slug = nil
expect(environment.ref_path).to eq(environment.ref_path)
end
end
describe '#external_url_for' do
......
......@@ -24,6 +24,16 @@ describe ForkNetwork do
end
end
describe '#merge_requests' do
it 'finds merge requests within the fork network' do
project = create(:project)
forked_project = fork_project(project)
merge_request = create(:merge_request, source_project: forked_project, target_project: project)
expect(project.fork_network.merge_requests).to include(merge_request)
end
end
context 'for a deleted project' do
it 'keeps the fork network' do
project = create(:project, :public)
......
......@@ -2256,6 +2256,20 @@ describe Project do
expect(forked_project.in_fork_network_of?(other_project)).to be_falsy
end
end
describe '#fork_source' do
let!(:second_fork) { fork_project(forked_project) }
it 'returns the direct source if it exists' do
expect(second_fork.fork_source).to eq(forked_project)
end
it 'returns the root of the fork network when the directs source was deleted' do
forked_project.destroy
expect(second_fork.fork_source).to eq(project)
end
end
end
describe '#pushes_since_gc' do
......
......@@ -12,6 +12,9 @@ describe Projects::UnlinkForkService do
context 'with opened merge request on the source project' do
let(:merge_request) { create(:merge_request, source_project: forked_project, target_project: fork_link.forked_from_project) }
let(:merge_request2) { create(:merge_request, source_project: forked_project, target_project: fork_project(project)) }
let(:merge_request_in_fork) { create(:merge_request, source_project: forked_project, target_project: forked_project) }
let(:mr_close_service) { MergeRequests::CloseService.new(forked_project, user) }
before do
......@@ -22,9 +25,14 @@ describe Projects::UnlinkForkService do
it 'close all pending merge requests' do
expect(mr_close_service).to receive(:execute).with(merge_request)
expect(mr_close_service).to receive(:execute).with(merge_request2)
subject.execute
end
it 'does not close merge requests for the project being unlinked' do
expect(mr_close_service).not_to receive(:execute).with(merge_request_in_fork)
end
end
it 'remove fork relation' do
......@@ -53,4 +61,14 @@ describe Projects::UnlinkForkService do
expect(source.forks_count).to be_zero
end
context 'when the original project was deleted' do
it 'does not fail when the original project is deleted' do
source = forked_project.forked_from_project
source.destroy
forked_project.reload
expect { subject.execute }.not_to raise_error
end
end
end
......@@ -48,6 +48,10 @@ module StubConfiguration
allow(Gitlab.config.backup).to receive_messages(to_settings(messages))
end
def stub_lfs_setting(messages)
allow(Gitlab.config.lfs).to receive_messages(to_settings(messages))
end
def stub_storage_settings(messages)
# Default storage is always required
messages['default'] ||= Gitlab.config.repositories.storages.default
......
/*
* This is a modified version of https://github.com/peek/peek/blob/master/app/assets/javascripts/peek.js
*
* - Removed the dependency on jquery.tipsy
* - Removed the initializeTipsy and toggleBar functions
* - Customized updatePerformanceBar to handle SQL queries report specificities
* - Changed /peek/results to /-/peek/results
* - Removed the keypress, pjax:end, page:change, and turbolinks:load handlers
*/
(function($) {
var fetchRequestResults, getRequestId, peekEnabled, toggleBar, updatePerformanceBar;
var fetchRequestResults, getRequestId, peekEnabled, updatePerformanceBar;
getRequestId = function() {
return $('#peek').data('request-id');
};
......@@ -41,22 +50,6 @@
});
return $(document).trigger('peek:render', [getRequestId(), results]);
};
toggleBar = function(event) {
var wrapper;
if ($(event.target).is(':input')) {
return;
}
if (event.which === 96 && !event.metaKey) {
wrapper = $('#peek');
if (wrapper.hasClass('disabled')) {
wrapper.removeClass('disabled');
return document.cookie = "peek=true; path=/";
} else {
wrapper.addClass('disabled');
return document.cookie = "peek=false; path=/";
}
}
};
fetchRequestResults = function() {
return $.ajax('/-/peek/results', {
data: {
......@@ -68,7 +61,6 @@
error: function(xhr, textStatus, error) {}
});
};
$(document).on('keypress', toggleBar);
$(document).on('peek:update', fetchRequestResults);
return $(function() {
if (peekEnabled()) {
......
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