Merge branch 'master' into fix/gb/improve-updating-column-in-batches-helper
* master: (56 commits)
File view buttons
Don't reset the session when the example failed, because we need capybara-screenshot to have access to it
Resolve "MR comment + system note highlight don't have the same width"
Add feature spec for dashboard state filter tabs
Wording of Mysql support.
a new feature checklist and more elaborate documentation requirements
Filter archived project in API v3 only if param present
Revert to using links instead of buttons in Issuable Index tabs.
Do not run the codeclimate job on docs-only changes
Only show gray footer space if environment actions exist
Migrate Gitlab::Git::Blob.find to Gitaly
Backport filtered search lazy token consistent state fix
Add a comment explaining how the branch clean up happens
Fix Github::Representation::PullRequest#source_branch_exists?
Add CHANGELOG
Fix GitHub importer performance on branch existence check
Rebuild the dynamic path before validating it
Rename stage ref migration specs to match a class name
Enable Style/DotPosition Rubocop 👮
Revert "Merge branch 'winh-merge-request-related-issues' into 'master'"
...
Conflicts:
db/post_migrate/20170526185921_migrate_build_stage_reference.rb
This commit is contained in:
commit
5331a49d0b
439 changed files with 4600 additions and 3581 deletions
|
@ -461,6 +461,7 @@ karma:
|
|||
- coverage-javascript/
|
||||
|
||||
codeclimate:
|
||||
<<: *except-docs
|
||||
before_script: []
|
||||
image: docker:latest
|
||||
stage: test
|
||||
|
|
|
@ -27,12 +27,24 @@ Please remove this notice if you're confident your issue isn't a duplicate.
|
|||
|
||||
### Documentation blurb
|
||||
|
||||
(Write the start of the documentation of this feature here, include:
|
||||
#### Overview
|
||||
|
||||
1. Why should someone use it; what's the underlying problem.
|
||||
2. What is the solution.
|
||||
3. How does someone use this
|
||||
What is it?
|
||||
Why should someone use this feature?
|
||||
What is the underlying (business) problem?
|
||||
How do you use this feature?
|
||||
|
||||
During implementation, this can then be copied and used as a starter for the documentation.)
|
||||
#### Use cases
|
||||
|
||||
/label ~"feature proposal"
|
||||
Who is this for? Provide one or more use cases.
|
||||
|
||||
### Feature checklist
|
||||
|
||||
Make sure these are completed before closing the issue,
|
||||
with a link to the relevant commit.
|
||||
|
||||
- [ ] [Feature assurance](https://about.gitlab.com/handbook/product/#feature-assurance)
|
||||
- [ ] Documentation
|
||||
- [ ] Added to [features.yml](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/features.yml)
|
||||
|
||||
/label ~"feature proposal"
|
|
@ -164,6 +164,11 @@ Style/DefWithParentheses:
|
|||
Style/Documentation:
|
||||
Enabled: false
|
||||
|
||||
# Multi-line method chaining should be done with leading dots.
|
||||
Style/DotPosition:
|
||||
Enabled: true
|
||||
EnforcedStyle: leading
|
||||
|
||||
# This cop checks for uses of double negation (!!) to convert something
|
||||
# to a boolean value. As this is both cryptic and usually redundant, it
|
||||
# should be avoided.
|
||||
|
|
|
@ -88,13 +88,6 @@ Security/YAMLLoad:
|
|||
Style/BarePercentLiterals:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 1403
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: leading, trailing
|
||||
Style/DotPosition:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 5
|
||||
# Cop supports --auto-correct.
|
||||
Style/EachWithObject:
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.11.2
|
||||
0.12.0
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -384,7 +384,7 @@ gem 'vmstat', '~> 2.3.0'
|
|||
gem 'sys-filesystem', '~> 1.1.6'
|
||||
|
||||
# Gitaly GRPC client
|
||||
gem 'gitaly', '~> 0.8.0'
|
||||
gem 'gitaly', '~> 0.9.0'
|
||||
|
||||
gem 'toml-rb', '~> 0.3.15', require: false
|
||||
|
||||
|
|
|
@ -277,7 +277,7 @@ GEM
|
|||
po_to_json (>= 1.0.0)
|
||||
rails (>= 3.2.0)
|
||||
gherkin-ruby (0.3.2)
|
||||
gitaly (0.8.0)
|
||||
gitaly (0.9.0)
|
||||
google-protobuf (~> 3.1)
|
||||
grpc (~> 1.0)
|
||||
github-linguist (4.7.6)
|
||||
|
@ -977,7 +977,7 @@ DEPENDENCIES
|
|||
gettext (~> 3.2.2)
|
||||
gettext_i18n_rails (~> 1.8.0)
|
||||
gettext_i18n_rails_js (~> 1.2.0)
|
||||
gitaly (~> 0.8.0)
|
||||
gitaly (~> 0.9.0)
|
||||
github-linguist (~> 4.7.0)
|
||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||
gitlab-markup (~> 1.5.1)
|
||||
|
|
|
@ -403,6 +403,14 @@ export default {
|
|||
return '';
|
||||
},
|
||||
|
||||
displayEnvironmentActions() {
|
||||
return this.hasManualActions ||
|
||||
this.externalURL ||
|
||||
this.monitoringUrl ||
|
||||
this.hasStopAction ||
|
||||
this.canRetry;
|
||||
},
|
||||
|
||||
/**
|
||||
* Constructs folder URL based on the current location and the folder id.
|
||||
*
|
||||
|
@ -535,9 +543,12 @@ export default {
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<div class="table-section section-30 table-button-footer" role="gridcell">
|
||||
<div
|
||||
v-if="!model.isFolder && displayEnvironmentActions"
|
||||
class="table-section section-30 table-button-footer"
|
||||
role="gridcell">
|
||||
|
||||
<div
|
||||
v-if="!model.isFolder"
|
||||
class="btn-group table-action-buttons"
|
||||
role="group">
|
||||
|
||||
|
|
|
@ -487,6 +487,7 @@ class FilteredSearchManager {
|
|||
}
|
||||
|
||||
searchState(e) {
|
||||
e.preventDefault();
|
||||
const target = e.currentTarget;
|
||||
// remove focus outline after click
|
||||
target.blur();
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,63 +1,42 @@
|
|||
export default {
|
||||
name: 'MRWidgetRelatedLinks',
|
||||
props: {
|
||||
isMerged: { type: Boolean, required: true },
|
||||
relatedLinks: { type: Object, required: true },
|
||||
},
|
||||
computed: {
|
||||
// TODO: the following should be handled by i18n
|
||||
closingText() {
|
||||
if (this.isMerged) {
|
||||
return `Closed ${this.issueLabel('closing')}`;
|
||||
}
|
||||
|
||||
return `Closes ${this.issueLabel('closing')}`;
|
||||
},
|
||||
hasLinks() {
|
||||
const { closing, mentioned, assignToMe } = this.relatedLinks;
|
||||
return closing || mentioned || assignToMe;
|
||||
},
|
||||
// TODO: the following should be handled by i18n
|
||||
mentionedText() {
|
||||
if (this.isMerged) {
|
||||
if (this.hasMultipleIssues(this.relatedLinks.mentioned)) {
|
||||
return 'are mentioned but were not closed';
|
||||
}
|
||||
|
||||
return 'is mentioned but was not closed';
|
||||
}
|
||||
|
||||
if (this.hasMultipleIssues(this.relatedLinks.mentioned)) {
|
||||
return 'are mentioned but will not be closed';
|
||||
}
|
||||
|
||||
return 'is mentioned but will not be closed';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hasMultipleIssues(text) {
|
||||
return /<\/a>,? and <a/.test(text);
|
||||
return !text ? false : text.match(/<\/a> and <a/);
|
||||
},
|
||||
// TODO: the following should be handled by i18n
|
||||
issueLabel(field) {
|
||||
return this.hasMultipleIssues(this.relatedLinks[field]) ? 'issues' : 'issue';
|
||||
},
|
||||
verbLabel(field) {
|
||||
return this.hasMultipleIssues(this.relatedLinks[field]) ? 'are' : 'is';
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<div v-if="hasLinks">
|
||||
<section
|
||||
v-if="hasLinks"
|
||||
class="mr-info-list mr-links">
|
||||
<div class="legend"></div>
|
||||
<p v-if="relatedLinks.closing">
|
||||
{{closingText}}
|
||||
Closes {{issueLabel('closing')}}
|
||||
<span v-html="relatedLinks.closing"></span>.
|
||||
</p>
|
||||
<p v-if="relatedLinks.mentioned">
|
||||
<span class="capitalize">{{issueLabel('mentioned')}}</span>
|
||||
<span v-html="relatedLinks.mentioned"></span>
|
||||
{{mentionedText}}
|
||||
{{verbLabel('mentioned')}} mentioned but will not be closed.
|
||||
</p>
|
||||
<p v-if="relatedLinks.assignToMe">
|
||||
<span v-html="relatedLinks.assignToMe"></span>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
`,
|
||||
};
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
/* global Flash */
|
||||
|
||||
import mrWidgetAuthorTime from '../../components/mr_widget_author_time';
|
||||
import mrWidgetRelatedLinks from '../../components/mr_widget_related_links';
|
||||
import eventHub from '../../event_hub';
|
||||
import '../../../flash';
|
||||
|
||||
export default {
|
||||
name: 'MRWidgetMerged',
|
||||
|
@ -13,7 +11,6 @@ export default {
|
|||
},
|
||||
components: {
|
||||
'mr-widget-author-and-time': mrWidgetAuthorTime,
|
||||
'mr-widget-related-links': mrWidgetRelatedLinks,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -21,9 +18,6 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
shouldRenderRelatedLinks() {
|
||||
return this.mr.relatedLinks && this.mr.isMerged;
|
||||
},
|
||||
shouldShowRemoveSourceBranch() {
|
||||
const { sourceBranchRemoved, isRemovingSourceBranch, canRemoveSourceBranch } = this.mr;
|
||||
|
||||
|
@ -92,10 +86,6 @@ export default {
|
|||
aria-hidden="true" />
|
||||
The source branch is being removed.
|
||||
</p>
|
||||
<mr-widget-related-links
|
||||
v-if="shouldRenderRelatedLinks"
|
||||
:is-merged="mr.isMerged()"
|
||||
:related-links="mr.relatedLinks" />
|
||||
</section>
|
||||
<div
|
||||
v-if="shouldShowMergedButtons"
|
||||
|
|
|
@ -48,7 +48,7 @@ export default {
|
|||
return stateMaps.stateToComponentMap[this.mr.state];
|
||||
},
|
||||
shouldRenderMergeHelp() {
|
||||
return !this.mr.isMerged;
|
||||
return stateMaps.statesToShowHelpWidget.indexOf(this.mr.state) > -1;
|
||||
},
|
||||
shouldRenderPipelines() {
|
||||
return Object.keys(this.mr.pipeline).length || this.mr.hasCI;
|
||||
|
@ -238,14 +238,9 @@ export default {
|
|||
:is="componentName"
|
||||
:mr="mr"
|
||||
:service="service" />
|
||||
<section
|
||||
<mr-widget-related-links
|
||||
v-if="shouldRenderRelatedLinks"
|
||||
class="mr-info-list mr-links">
|
||||
<div class="legend"></div>
|
||||
<mr-widget-related-links
|
||||
:is-merged="mr.isMerged"
|
||||
:related-links="mr.relatedLinks" />
|
||||
</section>
|
||||
:related-links="mr.relatedLinks" />
|
||||
<mr-widget-merge-help v-if="shouldRenderMergeHelp" />
|
||||
</div>
|
||||
`,
|
||||
|
|
|
@ -1,18 +1,6 @@
|
|||
import Timeago from 'timeago.js';
|
||||
import { getStateKey } from '../dependencies';
|
||||
|
||||
const unmergedStates = [
|
||||
'locked',
|
||||
'conflicts',
|
||||
'workInProgress',
|
||||
'readyToMerge',
|
||||
'checking',
|
||||
'unresolvedDiscussions',
|
||||
'pipelineFailed',
|
||||
'pipelineBlocked',
|
||||
'autoMergeFailed',
|
||||
];
|
||||
|
||||
export default class MergeRequestStore {
|
||||
|
||||
constructor(data) {
|
||||
|
@ -77,7 +65,6 @@ export default class MergeRequestStore {
|
|||
this.mergeActionsContentPath = data.commit_change_content_path;
|
||||
this.isRemovingSourceBranch = this.isRemovingSourceBranch || false;
|
||||
this.isOpen = data.state === 'opened' || data.state === 'reopened' || false;
|
||||
this.isMerged = unmergedStates.indexOf(data.state) === -1;
|
||||
this.hasMergeableDiscussionsState = data.mergeable_discussions_state === false;
|
||||
this.canRemoveSourceBranch = currentUser.can_remove_source_branch || false;
|
||||
this.canMerge = !!data.merge_path;
|
||||
|
|
|
@ -19,6 +19,19 @@ const stateToComponentMap = {
|
|||
shaMismatch: 'mr-widget-sha-mismatch',
|
||||
};
|
||||
|
||||
const statesToShowHelpWidget = [
|
||||
'locked',
|
||||
'conflicts',
|
||||
'workInProgress',
|
||||
'readyToMerge',
|
||||
'checking',
|
||||
'unresolvedDiscussions',
|
||||
'pipelineFailed',
|
||||
'pipelineBlocked',
|
||||
'autoMergeFailed',
|
||||
];
|
||||
|
||||
export default {
|
||||
stateToComponentMap,
|
||||
statesToShowHelpWidget,
|
||||
};
|
||||
|
|
|
@ -45,8 +45,7 @@
|
|||
li {
|
||||
display: flex;
|
||||
|
||||
a,
|
||||
.btn-link {
|
||||
a {
|
||||
padding: $gl-btn-padding;
|
||||
padding-bottom: 11px;
|
||||
font-size: 14px;
|
||||
|
@ -68,29 +67,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
padding-top: 16px;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-top: none;
|
||||
border-radius: 0;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:active {
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.active a,
|
||||
&.active .btn-link {
|
||||
&.active a {
|
||||
border-bottom: 2px solid $link-underline-blue;
|
||||
color: $black;
|
||||
font-weight: 600;
|
||||
|
|
|
@ -44,6 +44,10 @@
|
|||
&:target,
|
||||
&.target {
|
||||
background: $line-target-blue;
|
||||
|
||||
&.system-note .note-body .note-text.system-note-commit-list::after {
|
||||
background: linear-gradient(rgba($line-target-blue, 0.1) -100px, $line-target-blue 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
|
|
|
@ -323,6 +323,7 @@ $note-disabled-comment-color: #b2b2b2;
|
|||
$note-targe3-outside: #fffff0;
|
||||
$note-targe3-inside: #ffffd3;
|
||||
$note-line2-border: #ddd;
|
||||
$note-icon-gutter-width: 55px;
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -372,10 +372,6 @@
|
|||
margin-left: 12px;
|
||||
}
|
||||
|
||||
&.mr-state-locked + .mr-info-list.mr-links {
|
||||
margin-top: -16px;
|
||||
}
|
||||
|
||||
&.empty-state {
|
||||
.artwork {
|
||||
margin-bottom: $gl-padding;
|
||||
|
|
|
@ -148,8 +148,20 @@
|
|||
padding: 6px 0;
|
||||
}
|
||||
|
||||
.notes-form > li {
|
||||
border: 0;
|
||||
.notes.notes-form > li.timeline-entry {
|
||||
@include notes-media('max', $screen-sm-max) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
@include notes-media('max', $screen-sm-max) {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-entry-inner {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.note-edit-form {
|
||||
|
|
|
@ -14,16 +14,6 @@ ul.notes {
|
|||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
.timeline-content {
|
||||
margin-left: 55px;
|
||||
|
||||
&.timeline-content-form {
|
||||
@include notes-media('max', $screen-sm-max) {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.note-created-ago,
|
||||
.note-updated-at {
|
||||
white-space: nowrap;
|
||||
|
@ -46,17 +36,49 @@ ul.notes {
|
|||
}
|
||||
}
|
||||
|
||||
> li {
|
||||
padding: $gl-padding $gl-btn-padding;
|
||||
> li { // .timeline-entry
|
||||
padding: 0;
|
||||
display: block;
|
||||
position: relative;
|
||||
border-bottom: 1px solid $white-normal;
|
||||
border-bottom: 0;
|
||||
|
||||
&:last-child {
|
||||
// Override `.timeline > li:last-child { border-bottom: none; }`
|
||||
@include notes-media('min', $screen-sm-min) {
|
||||
padding-left: $note-icon-gutter-width;
|
||||
}
|
||||
|
||||
.timeline-entry-inner {
|
||||
padding: $gl-padding $gl-btn-padding;
|
||||
border-bottom: 1px solid $white-normal;
|
||||
}
|
||||
|
||||
&:target,
|
||||
&.target {
|
||||
border-bottom: 1px solid $white-normal;
|
||||
|
||||
&:not(:first-child) {
|
||||
border-top: 1px solid $white-normal;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.timeline-entry-inner {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-icon {
|
||||
@include notes-media('min', $screen-sm-min) {
|
||||
margin-left: -$note-icon-gutter-width;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-content {
|
||||
margin-left: $note-icon-gutter-width;
|
||||
|
||||
@include notes-media('min', $screen-sm-min) {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.being-posted {
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
|
@ -73,7 +95,7 @@ ul.notes {
|
|||
}
|
||||
|
||||
&.note-discussion {
|
||||
&.timeline-entry {
|
||||
.timeline-entry-inner {
|
||||
padding: $gl-padding 10px;
|
||||
}
|
||||
}
|
||||
|
@ -152,13 +174,8 @@ ul.notes {
|
|||
|
||||
.system-note {
|
||||
font-size: 14px;
|
||||
padding-left: 0;
|
||||
clear: both;
|
||||
|
||||
@include notes-media('min', $screen-sm-min) {
|
||||
margin-left: 65px;
|
||||
}
|
||||
|
||||
.note-header-info {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
@ -192,13 +209,16 @@ ul.notes {
|
|||
.timeline-icon {
|
||||
float: left;
|
||||
|
||||
@include notes-media('min', $screen-sm-min) {
|
||||
margin-left: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: $gray-darkest;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,7 +270,7 @@ ul.notes {
|
|||
&::after {
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 67px;
|
||||
height: 70px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
|
@ -639,15 +659,12 @@ ul.notes {
|
|||
.discussion-body,
|
||||
.diff-file {
|
||||
.notes .note {
|
||||
padding-left: $gl-padding;
|
||||
padding-right: $gl-padding;
|
||||
border-bottom: 1px solid $white-normal;
|
||||
|
||||
&.system-note {
|
||||
padding-left: 0;
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
margin-left: 70px;
|
||||
}
|
||||
.timeline-entry-inner {
|
||||
padding-left: $gl-padding;
|
||||
padding-right: $gl-padding;
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -380,7 +380,7 @@ a.deploy-project-label {
|
|||
padding: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
line-height: 36px;
|
||||
line-height: 34px;
|
||||
margin: 0;
|
||||
|
||||
> li + li::before {
|
||||
|
|
|
@ -1,6 +1,72 @@
|
|||
.tree-holder {
|
||||
> .nav-block {
|
||||
margin: 11px 0;
|
||||
.nav-block {
|
||||
margin: 10px 0;
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
display: flex;
|
||||
|
||||
.tree-ref-container {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tree-controls {
|
||||
text-align: right;
|
||||
|
||||
.btn-group {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.tree-ref-holder {
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.repo-breadcrumb {
|
||||
li:last-of-type {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.add-to-tree-dropdown {
|
||||
position: absolute;
|
||||
left: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
.repo-breadcrumb {
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
|
||||
.dropdown-menu {
|
||||
min-width: 100%;
|
||||
width: 100%;
|
||||
left: inherit;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.add-to-tree-dropdown {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.tree-controls {
|
||||
margin-bottom: 10px;
|
||||
|
||||
.btn,
|
||||
.dropdown,
|
||||
.btn-group {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin: 10px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-finder {
|
||||
|
@ -131,11 +197,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.tree-ref-holder {
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.blob-commit-info {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
|
@ -159,16 +220,6 @@
|
|||
color: $md-link-color;
|
||||
}
|
||||
|
||||
.tree-controls {
|
||||
float: right;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.project-action-button {
|
||||
margin-left: $btn-side-margin;
|
||||
}
|
||||
}
|
||||
|
||||
.repo-charts {
|
||||
.sub-header {
|
||||
margin: 20px 0;
|
||||
|
|
|
@ -97,8 +97,8 @@ module CreatesCommit
|
|||
def merge_request_exists?
|
||||
return @merge_request if defined?(@merge_request)
|
||||
|
||||
@merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.
|
||||
find_by(source_project_id: @project_to_commit_into, source_branch: @branch_name, target_branch: @start_branch)
|
||||
@merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened
|
||||
.find_by(source_project_id: @project_to_commit_into, source_branch: @branch_name, target_branch: @start_branch)
|
||||
end
|
||||
|
||||
def different_project?
|
||||
|
|
|
@ -15,8 +15,8 @@ module MembershipActions
|
|||
end
|
||||
|
||||
def destroy
|
||||
Members::DestroyService.new(membershipable, current_user, params).
|
||||
execute(:all)
|
||||
Members::DestroyService.new(membershipable, current_user, params)
|
||||
.execute(:all)
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
|
@ -42,8 +42,8 @@ module MembershipActions
|
|||
end
|
||||
|
||||
def leave
|
||||
member = Members::DestroyService.new(membershipable, current_user, user_id: current_user.id).
|
||||
execute(:all)
|
||||
member = Members::DestroyService.new(membershipable, current_user, user_id: current_user.id)
|
||||
.execute(:all)
|
||||
|
||||
notice =
|
||||
if member.request?
|
||||
|
|
|
@ -22,8 +22,8 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
|||
end
|
||||
|
||||
def starred
|
||||
@projects = load_projects(params.merge(starred: true)).
|
||||
includes(:forked_from_project, :tags).page(params[:page])
|
||||
@projects = load_projects(params.merge(starred: true))
|
||||
.includes(:forked_from_project, :tags).page(params[:page])
|
||||
|
||||
@groups = []
|
||||
|
||||
|
@ -45,8 +45,8 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
|||
end
|
||||
|
||||
def load_projects(finder_params)
|
||||
ProjectsFinder.new(params: finder_params, current_user: current_user).
|
||||
execute.includes(:route, namespace: :route)
|
||||
ProjectsFinder.new(params: finder_params, current_user: current_user)
|
||||
.execute.includes(:route, namespace: :route)
|
||||
end
|
||||
|
||||
def load_events
|
||||
|
|
|
@ -49,7 +49,7 @@ class Explore::ProjectsController < Explore::ApplicationController
|
|||
private
|
||||
|
||||
def load_projects
|
||||
ProjectsFinder.new(current_user: current_user, params: params).
|
||||
execute.includes(:route, namespace: :route)
|
||||
ProjectsFinder.new(current_user: current_user, params: params)
|
||||
.execute.includes(:route, namespace: :route)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,8 +11,8 @@ class JwtController < ApplicationController
|
|||
service = SERVICES[params[:service]]
|
||||
return head :not_found unless service
|
||||
|
||||
result = service.new(@authentication_result.project, @authentication_result.actor, auth_params).
|
||||
execute(authentication_abilities: @authentication_result.authentication_abilities)
|
||||
result = service.new(@authentication_result.project, @authentication_result.actor, auth_params)
|
||||
.execute(authentication_abilities: @authentication_result.authentication_abilities)
|
||||
|
||||
render json: result, status: result[:http_status]
|
||||
end
|
||||
|
|
|
@ -144,7 +144,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
|||
end
|
||||
|
||||
def log_audit_event(user, options = {})
|
||||
AuditEventService.new(user, user, options).
|
||||
for_authentication.security_event
|
||||
AuditEventService.new(user, user, options)
|
||||
.for_authentication.security_event
|
||||
end
|
||||
end
|
||||
|
|
|
@ -49,9 +49,9 @@ class ProfilesController < Profiles::ApplicationController
|
|||
end
|
||||
|
||||
def audit_log
|
||||
@events = AuditEvent.where(entity_type: "User", entity_id: current_user.id).
|
||||
order("created_at DESC").
|
||||
page(params[:page])
|
||||
@events = AuditEvent.where(entity_type: "User", entity_id: current_user.id)
|
||||
.order("created_at DESC")
|
||||
.page(params[:page])
|
||||
end
|
||||
|
||||
def update_username
|
||||
|
|
|
@ -53,9 +53,21 @@ class Projects::ApplicationController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def check_project_feature_available!(feature)
|
||||
render_404 unless project.feature_available?(feature, current_user)
|
||||
end
|
||||
|
||||
def check_issuables_available!
|
||||
render_404 unless project.feature_available?(:issues, current_user) ||
|
||||
project.feature_available?(:merge_requests, current_user)
|
||||
end
|
||||
|
||||
def method_missing(method_sym, *arguments, &block)
|
||||
if method_sym.to_s =~ /\Aauthorize_(.*)!\z/
|
||||
case method_sym.to_s
|
||||
when /\Aauthorize_(.*)!\z/
|
||||
authorize_action!($1.to_sym)
|
||||
when /\Acheck_(.*)_available!\z/
|
||||
check_project_feature_available!($1.to_sym)
|
||||
else
|
||||
super
|
||||
end
|
||||
|
|
|
@ -187,7 +187,7 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def set_last_commit_sha
|
||||
@last_commit_sha = Gitlab::Git::Commit.
|
||||
last_for_path(@repository, @ref, @path).sha
|
||||
@last_commit_sha = Gitlab::Git::Commit
|
||||
.last_for_path(@repository, @ref, @path).sha
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,8 +37,8 @@ class Projects::BranchesController < Projects::ApplicationController
|
|||
|
||||
redirect_to_autodeploy = project.empty_repo? && project.deployment_services.present?
|
||||
|
||||
result = CreateBranchService.new(project, current_user).
|
||||
execute(branch_name, ref)
|
||||
result = CreateBranchService.new(project, current_user)
|
||||
.execute(branch_name, ref)
|
||||
|
||||
if params[:issue_iid]
|
||||
issue = IssuesFinder.new(current_user, project_id: @project.id).find_by(iid: params[:issue_iid])
|
||||
|
|
|
@ -18,11 +18,11 @@ class Projects::CommitsController < Projects::ApplicationController
|
|||
@repository.commits(@ref, path: @path, limit: @limit, offset: @offset)
|
||||
end
|
||||
|
||||
@note_counts = project.notes.where(commit_id: @commits.map(&:id)).
|
||||
group(:commit_id).count
|
||||
@note_counts = project.notes.where(commit_id: @commits.map(&:id))
|
||||
.group(:commit_id).count
|
||||
|
||||
@merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.
|
||||
find_by(source_project: @project, source_branch: @ref, target_branch: @repository.root_ref)
|
||||
@merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened
|
||||
.find_by(source_project: @project, source_branch: @ref, target_branch: @repository.root_ref)
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
|
|
@ -61,7 +61,7 @@ class Projects::CompareController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def merge_request
|
||||
@merge_request ||= MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.
|
||||
find_by(source_project: @project, source_branch: @head_ref, target_branch: @start_ref)
|
||||
@merge_request ||= MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened
|
||||
.find_by(source_project: @project, source_branch: @head_ref, target_branch: @start_ref)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class Projects::DiscussionsController < Projects::ApplicationController
|
||||
before_action :module_enabled
|
||||
before_action :check_merge_requests_available!
|
||||
before_action :merge_request
|
||||
before_action :discussion
|
||||
before_action :authorize_resolve_discussion!
|
||||
|
@ -34,8 +34,4 @@ class Projects::DiscussionsController < Projects::ApplicationController
|
|||
def authorize_resolve_discussion!
|
||||
access_denied! unless discussion.can_resolve?(current_user)
|
||||
end
|
||||
|
||||
def module_enabled
|
||||
render_404 unless @project.feature_available?(:merge_requests, current_user)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,8 +15,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController
|
|||
respond_to do |format|
|
||||
format.html
|
||||
format.json do
|
||||
Gitlab::PollingInterval.set_header(response, interval: 3_000)
|
||||
|
||||
render json: {
|
||||
environments: EnvironmentSerializer
|
||||
.new(project: @project, current_user: @current_user)
|
||||
|
|
|
@ -9,7 +9,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
prepend_before_action :authenticate_user!, only: [:new]
|
||||
|
||||
before_action :redirect_to_external_issue_tracker, only: [:index, :new]
|
||||
before_action :module_enabled
|
||||
before_action :check_issues_available!
|
||||
before_action :issue, except: [:index, :new, :create, :bulk_update]
|
||||
|
||||
# Allow write(create) issue
|
||||
|
@ -250,7 +250,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
return render_404 unless can?(current_user, :push_code, @project) && @issue.can_be_worked_on?(current_user)
|
||||
end
|
||||
|
||||
def module_enabled
|
||||
def check_issues_available!
|
||||
return render_404 unless @project.feature_available?(:issues, current_user) && @project.default_issues_tracker?
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
class Projects::LabelsController < Projects::ApplicationController
|
||||
include ToggleSubscriptionAction
|
||||
|
||||
before_action :module_enabled
|
||||
before_action :check_issuables_available!
|
||||
before_action :label, only: [:edit, :update, :destroy, :promote]
|
||||
before_action :find_labels, only: [:index, :set_priorities, :remove_priority, :toggle_subscription]
|
||||
before_action :authorize_read_label!
|
||||
|
@ -135,12 +135,6 @@ class Projects::LabelsController < Projects::ApplicationController
|
|||
|
||||
protected
|
||||
|
||||
def module_enabled
|
||||
unless @project.feature_available?(:issues, current_user) || @project.feature_available?(:merge_requests, current_user)
|
||||
return render_404
|
||||
end
|
||||
end
|
||||
|
||||
def label_params
|
||||
params.require(:label).permit(:title, :description, :color)
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
include ToggleAwardEmoji
|
||||
include IssuableCollections
|
||||
|
||||
before_action :module_enabled
|
||||
before_action :check_merge_requests_available!
|
||||
before_action :merge_request, only: [
|
||||
:edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :pipelines, :merge,
|
||||
:pipeline_status, :ci_environments_status, :toggle_subscription, :cancel_merge_when_pipeline_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues, :commit_change_content
|
||||
|
@ -143,8 +143,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
# Get commits from repository
|
||||
# or from cache if already merged
|
||||
@commits = @merge_request.commits
|
||||
@note_counts = Note.where(commit_id: @commits.map(&:id)).
|
||||
group(:commit_id).count
|
||||
@note_counts = Note.where(commit_id: @commits.map(&:id))
|
||||
.group(:commit_id).count
|
||||
|
||||
render json: { html: view_to_html_string('projects/merge_requests/show/_commits') }
|
||||
end
|
||||
|
@ -192,9 +192,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
begin
|
||||
MergeRequests::Conflicts::ResolveService.
|
||||
new(merge_request).
|
||||
execute(current_user, params)
|
||||
MergeRequests::Conflicts::ResolveService
|
||||
.new(merge_request)
|
||||
.execute(current_user, params)
|
||||
|
||||
flash[:notice] = 'All merge conflicts were resolved. The merge request can now be merged.'
|
||||
|
||||
|
@ -461,10 +461,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
return render_404 unless @conflicts_list.can_be_resolved_by?(current_user)
|
||||
end
|
||||
|
||||
def module_enabled
|
||||
return render_404 unless @project.feature_available?(:merge_requests, current_user)
|
||||
end
|
||||
|
||||
def validates_merge_request
|
||||
# Show git not found page
|
||||
# if there is no saved commits between source & target branch
|
||||
|
@ -562,8 +558,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
@commits = @merge_request.compare_commits.reverse
|
||||
@commit = @merge_request.diff_head_commit
|
||||
|
||||
@note_counts = Note.where(commit_id: @commits.map(&:id)).
|
||||
group(:commit_id).count
|
||||
@note_counts = Note.where(commit_id: @commits.map(&:id))
|
||||
.group(:commit_id).count
|
||||
|
||||
@labels = LabelsFinder.new(current_user, project_id: @project.id).execute
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
class Projects::MilestonesController < Projects::ApplicationController
|
||||
include MilestoneActions
|
||||
|
||||
before_action :module_enabled
|
||||
before_action :check_issuables_available!
|
||||
before_action :milestone, only: [:edit, :update, :destroy, :show, :merge_requests, :participants, :labels]
|
||||
|
||||
# Allow read any milestone
|
||||
|
@ -95,12 +95,6 @@ class Projects::MilestonesController < Projects::ApplicationController
|
|||
return render_404 unless can?(current_user, :admin_milestone, @project)
|
||||
end
|
||||
|
||||
def module_enabled
|
||||
unless @project.feature_available?(:issues, current_user) || @project.feature_available?(:merge_requests, current_user)
|
||||
return render_404
|
||||
end
|
||||
end
|
||||
|
||||
def milestone_params
|
||||
params.require(:milestone).permit(:title, :description, :start_date, :due_date, :state_event)
|
||||
end
|
||||
|
|
|
@ -14,8 +14,8 @@ module Projects
|
|||
|
||||
def define_runners_variables
|
||||
@project_runners = @project.runners.ordered
|
||||
@assignable_runners = current_user.ci_authorized_runners.
|
||||
assignable_for(project).ordered.page(params[:page]).per(20)
|
||||
@assignable_runners = current_user.ci_authorized_runners
|
||||
.assignable_for(project).ordered.page(params[:page]).per(20)
|
||||
@shared_runners = Ci::Runner.shared.active
|
||||
@shared_runners_count = @shared_runners.count(:all)
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ class Projects::SnippetsController < Projects::ApplicationController
|
|||
include SnippetsActions
|
||||
include RendersBlob
|
||||
|
||||
before_action :module_enabled
|
||||
before_action :check_snippets_available!
|
||||
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :toggle_award_emoji, :mark_as_spam]
|
||||
|
||||
# Allow read any snippet
|
||||
|
@ -102,10 +102,6 @@ class Projects::SnippetsController < Projects::ApplicationController
|
|||
return render_404 unless can?(current_user, :admin_project_snippet, @snippet)
|
||||
end
|
||||
|
||||
def module_enabled
|
||||
return render_404 unless @project.feature_available?(:snippets, current_user)
|
||||
end
|
||||
|
||||
def snippet_params
|
||||
params.require(:project_snippet).permit(:title, :content, :file_name, :private, :visibility_level, :description)
|
||||
end
|
||||
|
|
|
@ -29,8 +29,8 @@ class Projects::TagsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def create
|
||||
result = Tags::CreateService.new(@project, current_user).
|
||||
execute(params[:tag_name], params[:ref], params[:message], params[:release_description])
|
||||
result = Tags::CreateService.new(@project, current_user)
|
||||
.execute(params[:tag_name], params[:ref], params[:message], params[:release_description])
|
||||
|
||||
if result[:status] == :success
|
||||
@tag = result[:tag]
|
||||
|
|
|
@ -128,8 +128,8 @@ class SessionsController < Devise::SessionsController
|
|||
end
|
||||
|
||||
def log_audit_event(user, options = {})
|
||||
AuditEventService.new(user, user, options).
|
||||
for_authentication.security_event
|
||||
AuditEventService.new(user, user, options)
|
||||
.for_authentication.security_event
|
||||
end
|
||||
|
||||
def log_user_activity(user)
|
||||
|
|
|
@ -4,8 +4,8 @@ module Sherlock
|
|||
|
||||
def find_transaction
|
||||
if params[:transaction_id]
|
||||
@transaction = Gitlab::Sherlock.collection.
|
||||
find_transaction(params[:transaction_id])
|
||||
@transaction = Gitlab::Sherlock.collection
|
||||
.find_transaction(params[:transaction_id])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -106,11 +106,11 @@ class UsersController < ApplicationController
|
|||
|
||||
def load_events
|
||||
# Get user activity feed for projects common for both users
|
||||
@events = user.recent_events.
|
||||
merge(projects_for_current_user).
|
||||
references(:project).
|
||||
with_associations.
|
||||
limit_recent(20, params[:offset])
|
||||
@events = user.recent_events
|
||||
.merge(projects_for_current_user)
|
||||
.references(:project)
|
||||
.with_associations
|
||||
.limit_recent(20, params[:offset])
|
||||
end
|
||||
|
||||
def load_projects
|
||||
|
|
|
@ -33,8 +33,8 @@ class EventsFinder
|
|||
private
|
||||
|
||||
def by_current_user_access(events)
|
||||
events.merge(ProjectsFinder.new(current_user: current_user).execute).
|
||||
joins(:project)
|
||||
events.merge(ProjectsFinder.new(current_user: current_user).execute)
|
||||
.joins(:project)
|
||||
end
|
||||
|
||||
def by_action(events)
|
||||
|
|
|
@ -8,9 +8,9 @@ class GroupMembersFinder
|
|||
|
||||
return group_members unless @group.parent
|
||||
|
||||
parents_members = GroupMember.non_request.
|
||||
where(source_id: @group.ancestors.select(:id)).
|
||||
where.not(user_id: @group.users.select(:id))
|
||||
parents_members = GroupMember.non_request
|
||||
.where(source_id: @group.ancestors.select(:id))
|
||||
.where.not(user_id: @group.users.select(:id))
|
||||
|
||||
wheres = ["members.id IN (#{group_members.select(:id).to_sql})"]
|
||||
wheres << "members.id IN (#{parents_members.select(:id).to_sql})"
|
||||
|
|
|
@ -8,10 +8,10 @@ module FormHelper
|
|||
content_tag(:div, class: 'alert alert-danger', id: 'error_explanation') do
|
||||
content_tag(:h4, headline) <<
|
||||
content_tag(:ul) do
|
||||
model.errors.full_messages.
|
||||
map { |msg| content_tag(:li, msg) }.
|
||||
join.
|
||||
html_safe
|
||||
model.errors.full_messages
|
||||
.map { |msg| content_tag(:li, msg) }
|
||||
.join
|
||||
.html_safe
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -194,8 +194,8 @@ module ProjectsHelper
|
|||
end
|
||||
|
||||
def load_pipeline_status(projects)
|
||||
Gitlab::Cache::Ci::ProjectPipelineStatus.
|
||||
load_in_batch_for_projects(projects)
|
||||
Gitlab::Cache::Ci::ProjectPipelineStatus
|
||||
.load_in_batch_for_projects(projects)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -97,8 +97,8 @@ module SearchHelper
|
|||
|
||||
# Autocomplete results for the current user's projects
|
||||
def projects_autocomplete(term, limit = 5)
|
||||
current_user.authorized_projects.search_by_title(term).
|
||||
sorted_by_stars.non_archived.limit(limit).map do |p|
|
||||
current_user.authorized_projects.search_by_title(term)
|
||||
.sorted_by_stars.non_archived.limit(limit).map do |p|
|
||||
{
|
||||
category: "Projects",
|
||||
id: p.id,
|
||||
|
|
|
@ -6,8 +6,8 @@ module WikiHelper
|
|||
# Returns a String composed of the capitalized name of each directory and the
|
||||
# capitalized name of the page itself.
|
||||
def breadcrumb(page_slug)
|
||||
page_slug.split('/').
|
||||
map { |dir_or_page| WikiPage.unhyphenize(dir_or_page).capitalize }.
|
||||
join(' / ')
|
||||
page_slug.split('/')
|
||||
.map { |dir_or_page| WikiPage.unhyphenize(dir_or_page).capitalize }
|
||||
.join(' / ')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,9 +19,9 @@ class AwardEmoji < ActiveRecord::Base
|
|||
|
||||
class << self
|
||||
def votes_for_collection(ids, type)
|
||||
select('name', 'awardable_id', 'COUNT(*) as count').
|
||||
where('name IN (?) AND awardable_type = ? AND awardable_id IN (?)', [DOWNVOTE_NAME, UPVOTE_NAME], type, ids).
|
||||
group('name', 'awardable_id')
|
||||
select('name', 'awardable_id', 'COUNT(*) as count')
|
||||
.where('name IN (?) AND awardable_type = ? AND awardable_id IN (?)', [DOWNVOTE_NAME, UPVOTE_NAME], type, ids)
|
||||
.group('name', 'awardable_id')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -138,17 +138,6 @@ module Ci
|
|||
ExpandVariables.expand(environment, simple_variables) if environment
|
||||
end
|
||||
|
||||
def environment_url
|
||||
return @environment_url if defined?(@environment_url)
|
||||
|
||||
@environment_url =
|
||||
if unexpanded_url = options&.dig(:environment, :url)
|
||||
ExpandVariables.expand(unexpanded_url, simple_variables)
|
||||
else
|
||||
persisted_environment&.external_url
|
||||
end
|
||||
end
|
||||
|
||||
def has_environment?
|
||||
environment.present?
|
||||
end
|
||||
|
@ -192,7 +181,7 @@ module Ci
|
|||
slugified.gsub(/[^a-z0-9]/, '-')[0..62]
|
||||
end
|
||||
|
||||
# Variables whose value does not depend on other variables
|
||||
# Variables whose value does not depend on environment
|
||||
def simple_variables
|
||||
variables = predefined_variables
|
||||
variables += project.predefined_variables
|
||||
|
@ -207,7 +196,8 @@ module Ci
|
|||
variables
|
||||
end
|
||||
|
||||
# All variables, including those dependent on other variables
|
||||
# All variables, including those dependent on environment, which could
|
||||
# contain unexpanded variables.
|
||||
def variables
|
||||
simple_variables.concat(persisted_environment_variables)
|
||||
end
|
||||
|
@ -481,9 +471,10 @@ module Ci
|
|||
|
||||
variables = persisted_environment.predefined_variables
|
||||
|
||||
if url = environment_url
|
||||
variables << { key: 'CI_ENVIRONMENT_URL', value: url, public: true }
|
||||
end
|
||||
# Here we're passing unexpanded environment_url for runner to expand,
|
||||
# and we need to make sure that CI_ENVIRONMENT_NAME and
|
||||
# CI_ENVIRONMENT_SLUG so on are available for the URL be expanded.
|
||||
variables << { key: 'CI_ENVIRONMENT_URL', value: environment_url, public: true } if environment_url
|
||||
|
||||
variables
|
||||
end
|
||||
|
@ -506,6 +497,10 @@ module Ci
|
|||
variables
|
||||
end
|
||||
|
||||
def environment_url
|
||||
options&.dig(:environment, :url) || persisted_environment&.external_url
|
||||
end
|
||||
|
||||
def build_attributes_from_config
|
||||
return {} unless pipeline.config_processor
|
||||
|
||||
|
|
|
@ -168,8 +168,8 @@ module Ci
|
|||
end
|
||||
|
||||
def stages_names
|
||||
statuses.order(:stage_idx).distinct.
|
||||
pluck(:stage, :stage_idx).map(&:first)
|
||||
statuses.order(:stage_idx).distinct
|
||||
.pluck(:stage, :stage_idx).map(&:first)
|
||||
end
|
||||
|
||||
def legacy_stage(name)
|
||||
|
|
|
@ -30,8 +30,8 @@ module Ci
|
|||
scope :assignable_for, ->(project) do
|
||||
# FIXME: That `to_sql` is needed to workaround a weird Rails bug.
|
||||
# Without that, placeholders would miss one and couldn't match.
|
||||
where(locked: false).
|
||||
where.not("id IN (#{project.runners.select(:id).to_sql})").specific
|
||||
where(locked: false)
|
||||
.where.not("id IN (#{project.runners.select(:id).to_sql})").specific
|
||||
end
|
||||
|
||||
validate :tag_constraints
|
||||
|
|
|
@ -161,9 +161,9 @@ module Issuable
|
|||
#
|
||||
milestones_due_date = 'MIN(milestones.due_date)'
|
||||
|
||||
order_milestone_due_asc.
|
||||
order_labels_priority(excluded_labels: excluded_labels, extra_select_columns: [milestones_due_date]).
|
||||
reorder(Gitlab::Database.nulls_last_order(milestones_due_date, 'ASC'),
|
||||
order_milestone_due_asc
|
||||
.order_labels_priority(excluded_labels: excluded_labels, extra_select_columns: [milestones_due_date])
|
||||
.reorder(Gitlab::Database.nulls_last_order(milestones_due_date, 'ASC'),
|
||||
Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
|
||||
end
|
||||
|
||||
|
@ -182,9 +182,9 @@ module Issuable
|
|||
"(#{highest_priority}) AS highest_priority"
|
||||
] + extra_select_columns
|
||||
|
||||
select(select_columns.join(', ')).
|
||||
group(arel_table[:id]).
|
||||
reorder(Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
|
||||
select(select_columns.join(', '))
|
||||
.group(arel_table[:id])
|
||||
.reorder(Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
|
||||
end
|
||||
|
||||
def with_label(title, sort = nil)
|
||||
|
|
|
@ -18,10 +18,10 @@ module RelativePositioning
|
|||
prev_pos = nil
|
||||
|
||||
if self.relative_position
|
||||
prev_pos = self.class.
|
||||
in_projects(project.id).
|
||||
where('relative_position < ?', self.relative_position).
|
||||
maximum(:relative_position)
|
||||
prev_pos = self.class
|
||||
.in_projects(project.id)
|
||||
.where('relative_position < ?', self.relative_position)
|
||||
.maximum(:relative_position)
|
||||
end
|
||||
|
||||
prev_pos
|
||||
|
@ -31,10 +31,10 @@ module RelativePositioning
|
|||
next_pos = nil
|
||||
|
||||
if self.relative_position
|
||||
next_pos = self.class.
|
||||
in_projects(project.id).
|
||||
where('relative_position > ?', self.relative_position).
|
||||
minimum(:relative_position)
|
||||
next_pos = self.class
|
||||
.in_projects(project.id)
|
||||
.where('relative_position > ?', self.relative_position)
|
||||
.minimum(:relative_position)
|
||||
end
|
||||
|
||||
next_pos
|
||||
|
|
|
@ -107,6 +107,14 @@ module Routable
|
|||
RequestStore[key] ||= uncached_full_path
|
||||
end
|
||||
|
||||
def build_full_path
|
||||
if parent && path
|
||||
parent.full_path + '/' + path
|
||||
else
|
||||
path
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def uncached_full_path
|
||||
|
@ -135,14 +143,6 @@ module Routable
|
|||
end
|
||||
end
|
||||
|
||||
def build_full_path
|
||||
if parent && path
|
||||
parent.full_path + '/' + path
|
||||
else
|
||||
path
|
||||
end
|
||||
end
|
||||
|
||||
def update_route
|
||||
prepare_route
|
||||
route.save
|
||||
|
|
|
@ -39,12 +39,12 @@ module Sortable
|
|||
private
|
||||
|
||||
def highest_label_priority(target_type_column: nil, target_type: nil, target_column:, project_column:, excluded_labels: [])
|
||||
query = Label.select(LabelPriority.arel_table[:priority].minimum).
|
||||
left_join_priorities.
|
||||
joins(:label_links).
|
||||
where("label_priorities.project_id = #{project_column}").
|
||||
where("label_links.target_id = #{target_column}").
|
||||
reorder(nil)
|
||||
query = Label.select(LabelPriority.arel_table[:priority].minimum)
|
||||
.left_join_priorities
|
||||
.joins(:label_links)
|
||||
.where("label_priorities.project_id = #{project_column}")
|
||||
.where("label_links.target_id = #{target_column}")
|
||||
.reorder(nil)
|
||||
|
||||
query =
|
||||
if target_type_column
|
||||
|
|
|
@ -27,16 +27,16 @@ module Subscribable
|
|||
end
|
||||
|
||||
def subscribers(project)
|
||||
subscriptions_available(project).
|
||||
where(subscribed: true).
|
||||
map(&:user)
|
||||
subscriptions_available(project)
|
||||
.where(subscribed: true)
|
||||
.map(&:user)
|
||||
end
|
||||
|
||||
def toggle_subscription(user, project = nil)
|
||||
unsubscribe_from_other_levels(user, project)
|
||||
|
||||
find_or_initialize_subscription(user, project).
|
||||
update(subscribed: !subscribed?(user, project))
|
||||
find_or_initialize_subscription(user, project)
|
||||
.update(subscribed: !subscribed?(user, project))
|
||||
end
|
||||
|
||||
def subscribe(user, project = nil)
|
||||
|
@ -69,14 +69,14 @@ module Subscribable
|
|||
end
|
||||
|
||||
def find_or_initialize_subscription(user, project)
|
||||
subscriptions.
|
||||
find_or_initialize_by(user_id: user.id, project_id: project.try(:id))
|
||||
subscriptions
|
||||
.find_or_initialize_by(user_id: user.id, project_id: project.try(:id))
|
||||
end
|
||||
|
||||
def subscriptions_available(project)
|
||||
t = Subscription.arel_table
|
||||
|
||||
subscriptions.
|
||||
where(t[:project_id].eq(nil).or(t[:project_id].eq(project.try(:id))))
|
||||
subscriptions
|
||||
.where(t[:project_id].eq(nil).or(t[:project_id].eq(project.try(:id))))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -58,10 +58,10 @@ class Deployment < ActiveRecord::Base
|
|||
def update_merge_request_metrics!
|
||||
return unless environment.update_merge_request_metrics?
|
||||
|
||||
merge_requests = project.merge_requests.
|
||||
joins(:metrics).
|
||||
where(target_branch: self.ref, merge_request_metrics: { first_deployed_to_production_at: nil }).
|
||||
where("merge_request_metrics.merged_at <= ?", self.created_at)
|
||||
merge_requests = project.merge_requests
|
||||
.joins(:metrics)
|
||||
.where(target_branch: self.ref, merge_request_metrics: { first_deployed_to_production_at: nil })
|
||||
.where("merge_request_metrics.merged_at <= ?", self.created_at)
|
||||
|
||||
if previous_deployment
|
||||
merge_requests = merge_requests.where("merge_request_metrics.merged_at >= ?", previous_deployment.created_at)
|
||||
|
@ -76,17 +76,17 @@ class Deployment < ActiveRecord::Base
|
|||
merge_requests.map(&:id)
|
||||
end
|
||||
|
||||
MergeRequest::Metrics.
|
||||
where(merge_request_id: merge_request_ids, first_deployed_to_production_at: nil).
|
||||
update_all(first_deployed_to_production_at: self.created_at)
|
||||
MergeRequest::Metrics
|
||||
.where(merge_request_id: merge_request_ids, first_deployed_to_production_at: nil)
|
||||
.update_all(first_deployed_to_production_at: self.created_at)
|
||||
end
|
||||
|
||||
def previous_deployment
|
||||
@previous_deployment ||=
|
||||
project.deployments.joins(:environment).
|
||||
where(environments: { name: self.environment.name }, ref: self.ref).
|
||||
where.not(id: self.id).
|
||||
take
|
||||
project.deployments.joins(:environment)
|
||||
.where(environments: { name: self.environment.name }, ref: self.ref)
|
||||
.where.not(id: self.id)
|
||||
.take
|
||||
end
|
||||
|
||||
def stop_action
|
||||
|
|
|
@ -40,9 +40,9 @@ class Environment < ActiveRecord::Base
|
|||
scope :stopped, -> { with_state(:stopped) }
|
||||
scope :order_by_last_deployed_at, -> do
|
||||
max_deployment_id_sql =
|
||||
Deployment.select(Deployment.arel_table[:id].maximum).
|
||||
where(Deployment.arel_table[:environment_id].eq(arel_table[:id])).
|
||||
to_sql
|
||||
Deployment.select(Deployment.arel_table[:id].maximum)
|
||||
.where(Deployment.arel_table[:environment_id].eq(arel_table[:id]))
|
||||
.to_sql
|
||||
order(Gitlab::Database.nulls_first_order("(#{max_deployment_id_sql})", 'ASC'))
|
||||
end
|
||||
|
||||
|
|
|
@ -376,9 +376,9 @@ class Event < ActiveRecord::Base
|
|||
# At this point it's possible for multiple threads/processes to try to
|
||||
# update the project. Only one query should actually perform the update,
|
||||
# hence we add the extra WHERE clause for last_activity_at.
|
||||
Project.unscoped.where(id: project_id).
|
||||
where('last_activity_at <= ?', RESET_PROJECT_ACTIVITY_INTERVAL.ago).
|
||||
update_all(last_activity_at: created_at)
|
||||
Project.unscoped.where(id: project_id)
|
||||
.where('last_activity_at <= ?', RESET_PROJECT_ACTIVITY_INTERVAL.ago)
|
||||
.update_all(last_activity_at: created_at)
|
||||
end
|
||||
|
||||
def authored_by?(user)
|
||||
|
@ -392,7 +392,7 @@ class Event < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def set_last_repository_updated_at
|
||||
Project.unscoped.where(id: project_id).
|
||||
update_all(last_repository_updated_at: created_at)
|
||||
Project.unscoped.where(id: project_id)
|
||||
.update_all(last_repository_updated_at: created_at)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -206,8 +206,8 @@ class Group < Namespace
|
|||
end
|
||||
|
||||
def refresh_members_authorized_projects
|
||||
UserProjectAccessChangedService.new(user_ids_for_project_authorizations).
|
||||
execute
|
||||
UserProjectAccessChangedService.new(user_ids_for_project_authorizations)
|
||||
.execute
|
||||
end
|
||||
|
||||
def user_ids_for_project_authorizations
|
||||
|
@ -225,10 +225,10 @@ class Group < Namespace
|
|||
def max_member_access_for_user(user)
|
||||
return GroupMember::OWNER if user.admin?
|
||||
|
||||
members_with_parents.
|
||||
where(user_id: user).
|
||||
reorder(access_level: :desc).
|
||||
first&.
|
||||
members_with_parents
|
||||
.where(user_id: user)
|
||||
.reorder(access_level: :desc)
|
||||
.first&.
|
||||
access_level || GroupMember::NO_ACCESS
|
||||
end
|
||||
|
||||
|
|
|
@ -124,8 +124,8 @@ class Issue < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def self.order_by_position_and_priority
|
||||
order_labels_priority.
|
||||
reorder(Gitlab::Database.nulls_last_order('relative_position', 'ASC'),
|
||||
order_labels_priority
|
||||
.reorder(Gitlab::Database.nulls_last_order('relative_position', 'ASC'),
|
||||
Gitlab::Database.nulls_last_order('highest_priority', 'ASC'),
|
||||
"id DESC")
|
||||
end
|
||||
|
|
|
@ -17,9 +17,9 @@ class IssueCollection
|
|||
|
||||
# Given all the issue projects we get a list of projects that the current
|
||||
# user has at least reporter access to.
|
||||
projects_with_reporter_access = user.
|
||||
projects_with_reporter_access_limited_to(project_ids).
|
||||
pluck(:id)
|
||||
projects_with_reporter_access = user
|
||||
.projects_with_reporter_access_limited_to(project_ids)
|
||||
.pluck(:id)
|
||||
|
||||
collection.select do |issue|
|
||||
if projects_with_reporter_access.include?(issue.project_id)
|
||||
|
|
|
@ -46,9 +46,9 @@ class Label < ActiveRecord::Base
|
|||
labels = Label.arel_table
|
||||
priorities = LabelPriority.arel_table
|
||||
|
||||
label_priorities = labels.join(priorities, Arel::Nodes::OuterJoin).
|
||||
on(labels[:id].eq(priorities[:label_id]).and(priorities[:project_id].eq(project.id))).
|
||||
join_sources
|
||||
label_priorities = labels.join(priorities, Arel::Nodes::OuterJoin)
|
||||
.on(labels[:id].eq(priorities[:label_id]).and(priorities[:project_id].eq(project.id)))
|
||||
.join_sources
|
||||
|
||||
joins(label_priorities).where(priorities[:priority].eq(nil))
|
||||
end
|
||||
|
@ -57,9 +57,9 @@ class Label < ActiveRecord::Base
|
|||
labels = Label.arel_table
|
||||
priorities = LabelPriority.arel_table
|
||||
|
||||
label_priorities = labels.join(priorities, Arel::Nodes::OuterJoin).
|
||||
on(labels[:id].eq(priorities[:label_id])).
|
||||
join_sources
|
||||
label_priorities = labels.join(priorities, Arel::Nodes::OuterJoin)
|
||||
.on(labels[:id].eq(priorities[:label_id]))
|
||||
.join_sources
|
||||
|
||||
joins(label_priorities)
|
||||
end
|
||||
|
|
|
@ -99,9 +99,9 @@ class Member < ActiveRecord::Base
|
|||
users = User.arel_table
|
||||
members = Member.arel_table
|
||||
|
||||
member_users = members.join(users, Arel::Nodes::OuterJoin).
|
||||
on(members[:user_id].eq(users[:id])).
|
||||
join_sources
|
||||
member_users = members.join(users, Arel::Nodes::OuterJoin)
|
||||
.on(members[:user_id].eq(users[:id]))
|
||||
.join_sources
|
||||
|
||||
joins(member_users)
|
||||
end
|
||||
|
|
|
@ -577,8 +577,8 @@ class MergeRequest < ActiveRecord::Base
|
|||
messages = [title, description]
|
||||
messages.concat(commits.map(&:safe_message)) if merge_request_diff
|
||||
|
||||
Gitlab::ClosingIssueExtractor.new(project, current_user).
|
||||
closed_by_message(messages.join("\n"))
|
||||
Gitlab::ClosingIssueExtractor.new(project, current_user)
|
||||
.closed_by_message(messages.join("\n"))
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
|
|
@ -7,9 +7,9 @@ class MergeRequestsClosingIssues < ActiveRecord::Base
|
|||
|
||||
class << self
|
||||
def count_for_collection(ids)
|
||||
group(:issue_id).
|
||||
where(issue_id: ids).
|
||||
pluck('issue_id', 'COUNT(*) as count')
|
||||
group(:issue_id)
|
||||
.where(issue_id: ids)
|
||||
.pluck('issue_id', 'COUNT(*) as count')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -98,11 +98,11 @@ class Milestone < ActiveRecord::Base
|
|||
if Gitlab::Database.postgresql?
|
||||
rel.order(:project_id, :due_date).select('DISTINCT ON (project_id) id')
|
||||
else
|
||||
rel.
|
||||
group(:project_id).
|
||||
having('due_date = MIN(due_date)').
|
||||
pluck(:id, :project_id, :due_date).
|
||||
map(&:first)
|
||||
rel
|
||||
.group(:project_id)
|
||||
.having('due_date = MIN(due_date)')
|
||||
.pluck(:id, :project_id, :due_date)
|
||||
.map(&:first)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -181,16 +181,16 @@ class Namespace < ActiveRecord::Base
|
|||
def ancestors
|
||||
return self.class.none unless parent_id
|
||||
|
||||
Gitlab::GroupHierarchy.
|
||||
new(self.class.where(id: parent_id)).
|
||||
base_and_ancestors
|
||||
Gitlab::GroupHierarchy
|
||||
.new(self.class.where(id: parent_id))
|
||||
.base_and_ancestors
|
||||
end
|
||||
|
||||
# Returns all the descendants of the current namespace.
|
||||
def descendants
|
||||
Gitlab::GroupHierarchy.
|
||||
new(self.class.where(parent_id: id)).
|
||||
base_and_descendants
|
||||
Gitlab::GroupHierarchy
|
||||
.new(self.class.where(parent_id: id))
|
||||
.base_and_descendants
|
||||
end
|
||||
|
||||
def user_ids_for_project_authorizations
|
||||
|
@ -253,10 +253,10 @@ class Namespace < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def refresh_access_of_projects_invited_groups
|
||||
Group.
|
||||
joins(project_group_links: :project).
|
||||
where(projects: { namespace_id: id }).
|
||||
find_each(&:refresh_members_authorized_projects)
|
||||
Group
|
||||
.joins(project_group_links: :project)
|
||||
.where(projects: { namespace_id: id })
|
||||
.find_each(&:refresh_members_authorized_projects)
|
||||
end
|
||||
|
||||
def remove_exports!
|
||||
|
|
|
@ -137,9 +137,9 @@ class Note < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def count_for_collection(ids, type)
|
||||
user.select('noteable_id', 'COUNT(*) as count').
|
||||
group(:noteable_id).
|
||||
where(noteable_type: type, noteable_id: ids)
|
||||
user.select('noteable_id', 'COUNT(*) as count')
|
||||
.group(:noteable_id)
|
||||
.where(noteable_type: type, noteable_id: ids)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -244,8 +244,8 @@ class Project < ActiveRecord::Base
|
|||
scope :inside_path, ->(path) do
|
||||
# We need routes alias rs for JOIN so it does not conflict with
|
||||
# includes(:route) which we use in ProjectsFinder.
|
||||
joins("INNER JOIN routes rs ON rs.source_id = projects.id AND rs.source_type = 'Project'").
|
||||
where('rs.path LIKE ?', "#{sanitize_sql_like(path)}/%")
|
||||
joins("INNER JOIN routes rs ON rs.source_id = projects.id AND rs.source_type = 'Project'")
|
||||
.where('rs.path LIKE ?', "#{sanitize_sql_like(path)}/%")
|
||||
end
|
||||
|
||||
# "enabled" here means "not disabled". It includes private features!
|
||||
|
@ -270,10 +270,10 @@ class Project < ActiveRecord::Base
|
|||
# logged in user.
|
||||
def self.public_or_visible_to_user(user = nil)
|
||||
if user
|
||||
authorized = user.
|
||||
project_authorizations.
|
||||
select(1).
|
||||
where('project_authorizations.project_id = projects.id')
|
||||
authorized = user
|
||||
.project_authorizations
|
||||
.select(1)
|
||||
.where('project_authorizations.project_id = projects.id')
|
||||
|
||||
levels = Gitlab::VisibilityLevel.levels_for_user(user)
|
||||
|
||||
|
@ -298,11 +298,11 @@ class Project < ActiveRecord::Base
|
|||
elsif user
|
||||
column = ProjectFeature.quoted_access_level_column(feature)
|
||||
|
||||
authorized = user.project_authorizations.select(1).
|
||||
where('project_authorizations.project_id = projects.id')
|
||||
authorized = user.project_authorizations.select(1)
|
||||
.where('project_authorizations.project_id = projects.id')
|
||||
|
||||
with_project_feature.
|
||||
where("#{column} IN (?) OR (#{column} = ? AND EXISTS (?))",
|
||||
with_project_feature
|
||||
.where("#{column} IN (?) OR (#{column} = ? AND EXISTS (?))",
|
||||
visible,
|
||||
ProjectFeature::PRIVATE,
|
||||
authorized)
|
||||
|
@ -369,14 +369,14 @@ class Project < ActiveRecord::Base
|
|||
# unscoping unnecessary conditions that'll be applied
|
||||
# when executing `where("projects.id IN (#{union.to_sql})")`
|
||||
projects = unscoped.select(:id).where(
|
||||
ptable[:path].matches(pattern).
|
||||
or(ptable[:name].matches(pattern)).
|
||||
or(ptable[:description].matches(pattern))
|
||||
ptable[:path].matches(pattern)
|
||||
.or(ptable[:name].matches(pattern))
|
||||
.or(ptable[:description].matches(pattern))
|
||||
)
|
||||
|
||||
namespaces = unscoped.select(:id).
|
||||
joins(:namespace).
|
||||
where(ntable[:name].matches(pattern))
|
||||
namespaces = unscoped.select(:id)
|
||||
.joins(:namespace)
|
||||
.where(ntable[:name].matches(pattern))
|
||||
|
||||
union = Gitlab::SQL::Union.new([projects, namespaces])
|
||||
|
||||
|
@ -417,8 +417,8 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def trending
|
||||
joins('INNER JOIN trending_projects ON projects.id = trending_projects.project_id').
|
||||
reorder('trending_projects.id ASC')
|
||||
joins('INNER JOIN trending_projects ON projects.id = trending_projects.project_id')
|
||||
.reorder('trending_projects.id ASC')
|
||||
end
|
||||
|
||||
def cached_count
|
||||
|
|
|
@ -7,9 +7,9 @@ class ProjectAuthorization < ActiveRecord::Base
|
|||
validates :user, uniqueness: { scope: [:project, :access_level] }, presence: true
|
||||
|
||||
def self.select_from_union(union)
|
||||
select(['project_id', 'MAX(access_level) AS access_level']).
|
||||
from("(#{union.to_sql}) #{ProjectAuthorization.table_name}").
|
||||
group(:project_id)
|
||||
select(['project_id', 'MAX(access_level) AS access_level'])
|
||||
.from("(#{union.to_sql}) #{ProjectAuthorization.table_name}")
|
||||
.group(:project_id)
|
||||
end
|
||||
|
||||
def self.insert_authorizations(rows, per_batch = 1000)
|
||||
|
|
|
@ -20,8 +20,8 @@ class MattermostSlashCommandsService < SlashCommandsService
|
|||
end
|
||||
|
||||
def configure(user, params)
|
||||
token = Mattermost::Command.new(user).
|
||||
create(command(params))
|
||||
token = Mattermost::Command.new(user)
|
||||
.create(command(params))
|
||||
|
||||
update(active: true, token: token) if token
|
||||
rescue Mattermost::Error => e
|
||||
|
|
|
@ -172,10 +172,10 @@ class ProjectTeam
|
|||
|
||||
return access if user_ids.empty?
|
||||
|
||||
users_access = project.project_authorizations.
|
||||
where(user: user_ids).
|
||||
group(:user_id).
|
||||
maximum(:access_level)
|
||||
users_access = project.project_authorizations
|
||||
.where(user: user_ids)
|
||||
.group(:user_id)
|
||||
.maximum(:access_level)
|
||||
|
||||
access.merge!(users_access)
|
||||
|
||||
|
|
|
@ -241,11 +241,11 @@ class Repository
|
|||
cache.fetch(:"diverging_commit_counts_#{branch.name}") do
|
||||
# Rugged seems to throw a `ReferenceError` when given branch_names rather
|
||||
# than SHA-1 hashes
|
||||
number_commits_behind = raw_repository.
|
||||
count_commits_between(branch.dereferenced_target.sha, root_ref_hash)
|
||||
number_commits_behind = raw_repository
|
||||
.count_commits_between(branch.dereferenced_target.sha, root_ref_hash)
|
||||
|
||||
number_commits_ahead = raw_repository.
|
||||
count_commits_between(root_ref_hash, branch.dereferenced_target.sha)
|
||||
number_commits_ahead = raw_repository
|
||||
.count_commits_between(root_ref_hash, branch.dereferenced_target.sha)
|
||||
|
||||
{ behind: number_commits_behind, ahead: number_commits_ahead }
|
||||
end
|
||||
|
|
|
@ -70,9 +70,9 @@ class Todo < ActiveRecord::Base
|
|||
|
||||
highest_priority = highest_label_priority(params).to_sql
|
||||
|
||||
select("#{table_name}.*, (#{highest_priority}) AS highest_priority").
|
||||
order(Gitlab::Database.nulls_last_order('highest_priority', 'ASC')).
|
||||
order('todos.created_at')
|
||||
select("#{table_name}.*, (#{highest_priority}) AS highest_priority")
|
||||
.order(Gitlab::Database.nulls_last_order('highest_priority', 'ASC'))
|
||||
.order('todos.created_at')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -223,13 +223,13 @@ class User < ActiveRecord::Base
|
|||
scope :order_oldest_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('last_sign_in_at', 'ASC')) }
|
||||
|
||||
def self.with_two_factor
|
||||
joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id").
|
||||
where("u2f.id IS NOT NULL OR otp_required_for_login = ?", true).distinct(arel_table[:id])
|
||||
joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id")
|
||||
.where("u2f.id IS NOT NULL OR otp_required_for_login = ?", true).distinct(arel_table[:id])
|
||||
end
|
||||
|
||||
def self.without_two_factor
|
||||
joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id").
|
||||
where("u2f.id IS NULL AND otp_required_for_login = ?", false)
|
||||
joins("LEFT OUTER JOIN u2f_registrations AS u2f ON u2f.user_id = users.id")
|
||||
.where("u2f.id IS NULL AND otp_required_for_login = ?", false)
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -300,9 +300,9 @@ class User < ActiveRecord::Base
|
|||
pattern = "%#{query}%"
|
||||
|
||||
where(
|
||||
table[:name].matches(pattern).
|
||||
or(table[:email].matches(pattern)).
|
||||
or(table[:username].matches(pattern))
|
||||
table[:name].matches(pattern)
|
||||
.or(table[:email].matches(pattern))
|
||||
.or(table[:username].matches(pattern))
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -317,10 +317,10 @@ class User < ActiveRecord::Base
|
|||
matched_by_emails_user_ids = email_table.project(email_table[:user_id]).where(email_table[:email].matches(pattern))
|
||||
|
||||
where(
|
||||
table[:name].matches(pattern).
|
||||
or(table[:email].matches(pattern)).
|
||||
or(table[:username].matches(pattern)).
|
||||
or(table[:id].in(matched_by_emails_user_ids))
|
||||
table[:name].matches(pattern)
|
||||
.or(table[:email].matches(pattern))
|
||||
.or(table[:username].matches(pattern))
|
||||
.or(table[:id].in(matched_by_emails_user_ids))
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -503,8 +503,8 @@ class User < ActiveRecord::Base
|
|||
|
||||
# Returns the groups a user has access to
|
||||
def authorized_groups
|
||||
union = Gitlab::SQL::Union.
|
||||
new([groups.select(:id), authorized_projects.select(:namespace_id)])
|
||||
union = Gitlab::SQL::Union
|
||||
.new([groups.select(:id), authorized_projects.select(:namespace_id)])
|
||||
|
||||
Group.where("namespaces.id IN (#{union.to_sql})")
|
||||
end
|
||||
|
@ -533,8 +533,8 @@ class User < ActiveRecord::Base
|
|||
projects = super()
|
||||
|
||||
if min_access_level
|
||||
projects = projects.
|
||||
where('project_authorizations.access_level >= ?', min_access_level)
|
||||
projects = projects
|
||||
.where('project_authorizations.access_level >= ?', min_access_level)
|
||||
end
|
||||
|
||||
projects
|
||||
|
@ -619,9 +619,9 @@ class User < ActiveRecord::Base
|
|||
next unless project
|
||||
|
||||
if project.repository.branch_exists?(event.branch_name)
|
||||
merge_requests = MergeRequest.where("created_at >= ?", event.created_at).
|
||||
where(source_project_id: project.id,
|
||||
source_branch: event.branch_name)
|
||||
merge_requests = MergeRequest.where("created_at >= ?", event.created_at)
|
||||
.where(source_project_id: project.id,
|
||||
source_branch: event.branch_name)
|
||||
merge_requests.empty?
|
||||
end
|
||||
end
|
||||
|
@ -832,8 +832,8 @@ class User < ActiveRecord::Base
|
|||
|
||||
def toggle_star(project)
|
||||
UsersStarProject.transaction do
|
||||
user_star_project = users_star_projects.
|
||||
where(project: project, user: self).lock(true).first
|
||||
user_star_project = users_star_projects
|
||||
.where(project: project, user: self).lock(true).first
|
||||
|
||||
if user_star_project
|
||||
user_star_project.destroy
|
||||
|
@ -869,11 +869,11 @@ class User < ActiveRecord::Base
|
|||
# ms on a database with a similar size to GitLab.com's database. On the other
|
||||
# hand, using a subquery means we can get the exact same data in about 40 ms.
|
||||
def contributed_projects
|
||||
events = Event.select(:project_id).
|
||||
contributions.where(author_id: self).
|
||||
where("created_at > ?", Time.now - 1.year).
|
||||
uniq.
|
||||
reorder(nil)
|
||||
events = Event.select(:project_id)
|
||||
.contributions.where(author_id: self)
|
||||
.where("created_at > ?", Time.now - 1.year)
|
||||
.uniq
|
||||
.reorder(nil)
|
||||
|
||||
Project.where(id: events)
|
||||
end
|
||||
|
@ -884,9 +884,9 @@ class User < ActiveRecord::Base
|
|||
|
||||
def ci_authorized_runners
|
||||
@ci_authorized_runners ||= begin
|
||||
runner_ids = Ci::RunnerProject.
|
||||
where("ci_runner_projects.project_id IN (#{ci_projects_union.to_sql})").
|
||||
select(:runner_id)
|
||||
runner_ids = Ci::RunnerProject
|
||||
.where("ci_runner_projects.project_id IN (#{ci_projects_union.to_sql})")
|
||||
.select(:runner_id)
|
||||
Ci::Runner.specific.where(id: runner_ids)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,16 +22,16 @@ class WikiPage
|
|||
def self.group_by_directory(pages)
|
||||
return [] if pages.blank?
|
||||
|
||||
pages.sort_by { |page| [page.directory, page.slug] }.
|
||||
group_by(&:directory).
|
||||
map do |dir, pages|
|
||||
pages.sort_by { |page| [page.directory, page.slug] }
|
||||
.group_by(&:directory)
|
||||
.map do |dir, pages|
|
||||
if dir.present?
|
||||
WikiDirectory.new(dir, pages)
|
||||
else
|
||||
pages
|
||||
end
|
||||
end.
|
||||
flatten
|
||||
end
|
||||
.flatten
|
||||
end
|
||||
|
||||
def self.unhyphenize(name)
|
||||
|
|
|
@ -67,8 +67,8 @@ module Ci
|
|||
def update_merge_requests_head_pipeline
|
||||
return unless pipeline.latest?
|
||||
|
||||
MergeRequest.where(source_project: @pipeline.project, source_branch: @pipeline.ref).
|
||||
update_all(head_pipeline_id: @pipeline.id)
|
||||
MergeRequest.where(source_project: @pipeline.project, source_branch: @pipeline.ref)
|
||||
.update_all(head_pipeline_id: @pipeline.id)
|
||||
end
|
||||
|
||||
def skip_ci?
|
||||
|
|
|
@ -3,8 +3,8 @@ module Ci
|
|||
def execute(project, trigger, ref, variables = nil)
|
||||
trigger_request = trigger.trigger_requests.create(variables: variables)
|
||||
|
||||
pipeline = Ci::CreatePipelineService.new(project, trigger.owner, ref: ref).
|
||||
execute(:trigger, ignore_skip_ci: true, trigger_request: trigger_request)
|
||||
pipeline = Ci::CreatePipelineService.new(project, trigger.owner, ref: ref)
|
||||
.execute(:trigger, ignore_skip_ci: true, trigger_request: trigger_request)
|
||||
|
||||
trigger_request if pipeline.persisted?
|
||||
end
|
||||
|
|
|
@ -54,15 +54,15 @@ module Ci
|
|||
def builds_for_shared_runner
|
||||
new_builds.
|
||||
# don't run projects which have not enabled shared runners and builds
|
||||
joins(:project).where(projects: { shared_runners_enabled: true }).
|
||||
joins('LEFT JOIN project_features ON ci_builds.project_id = project_features.project_id').
|
||||
where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0').
|
||||
joins(:project).where(projects: { shared_runners_enabled: true })
|
||||
.joins('LEFT JOIN project_features ON ci_builds.project_id = project_features.project_id')
|
||||
.where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0').
|
||||
|
||||
# Implement fair scheduling
|
||||
# this returns builds that are ordered by number of running builds
|
||||
# we prefer projects that don't use shared runners at all
|
||||
joins("LEFT JOIN (#{running_builds_for_shared_runners.to_sql}) AS project_builds ON ci_builds.project_id=project_builds.project_id").
|
||||
order('COALESCE(project_builds.running_builds, 0) ASC', 'ci_builds.id ASC')
|
||||
joins("LEFT JOIN (#{running_builds_for_shared_runners.to_sql}) AS project_builds ON ci_builds.project_id=project_builds.project_id")
|
||||
.order('COALESCE(project_builds.running_builds, 0) ASC', 'ci_builds.id ASC')
|
||||
end
|
||||
|
||||
def builds_for_specific_runner
|
||||
|
@ -70,8 +70,8 @@ module Ci
|
|||
end
|
||||
|
||||
def running_builds_for_shared_runners
|
||||
Ci::Build.running.where(runner: Ci::Runner.shared).
|
||||
group(:project_id).select(:project_id, 'count(*) AS running_builds')
|
||||
Ci::Build.running.where(runner: Ci::Runner.shared)
|
||||
.group(:project_id).select(:project_id, 'count(*) AS running_builds')
|
||||
end
|
||||
|
||||
def new_builds
|
||||
|
|
|
@ -10,9 +10,9 @@ module Issues
|
|||
def merge_request_to_resolve_discussions_of
|
||||
return @merge_request_to_resolve_discussions_of if defined?(@merge_request_to_resolve_discussions_of)
|
||||
|
||||
@merge_request_to_resolve_discussions_of = MergeRequestsFinder.new(current_user, project_id: project.id).
|
||||
execute.
|
||||
find_by(iid: merge_request_to_resolve_discussions_of_iid)
|
||||
@merge_request_to_resolve_discussions_of = MergeRequestsFinder.new(current_user, project_id: project.id)
|
||||
.execute
|
||||
.find_by(iid: merge_request_to_resolve_discussions_of_iid)
|
||||
end
|
||||
|
||||
def discussions_to_resolve
|
||||
|
|
|
@ -2,7 +2,7 @@ class CreateDeploymentService
|
|||
attr_reader :job
|
||||
|
||||
delegate :expanded_environment_name,
|
||||
:environment_url,
|
||||
:variables,
|
||||
:project,
|
||||
to: :job
|
||||
|
||||
|
@ -14,7 +14,8 @@ class CreateDeploymentService
|
|||
return unless executable?
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
environment.external_url = environment_url if environment_url
|
||||
environment.external_url = expanded_environment_url if
|
||||
expanded_environment_url
|
||||
environment.fire_state_event(action)
|
||||
|
||||
return unless environment.save
|
||||
|
@ -49,6 +50,17 @@ class CreateDeploymentService
|
|||
@environment_options ||= job.options&.dig(:environment) || {}
|
||||
end
|
||||
|
||||
def expanded_environment_url
|
||||
return @expanded_environment_url if defined?(@expanded_environment_url)
|
||||
|
||||
@expanded_environment_url =
|
||||
ExpandVariables.expand(environment_url, variables) if environment_url
|
||||
end
|
||||
|
||||
def environment_url
|
||||
environment_options[:url]
|
||||
end
|
||||
|
||||
def on_stop
|
||||
environment_options[:on_stop]
|
||||
end
|
||||
|
|
|
@ -28,8 +28,8 @@ module Files
|
|||
end
|
||||
|
||||
def last_commit
|
||||
@last_commit ||= Gitlab::Git::Commit.
|
||||
last_for_path(@start_project.repository, @start_branch, @file_path)
|
||||
@last_commit ||= Gitlab::Git::Commit
|
||||
.last_for_path(@start_project.repository, @start_branch, @file_path)
|
||||
end
|
||||
|
||||
def validate!
|
||||
|
|
|
@ -86,8 +86,8 @@ class GitPushService < BaseService
|
|||
|
||||
push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit|
|
||||
if commit.matches_cross_reference_regex?
|
||||
ProcessCommitWorker.
|
||||
perform_async(project.id, current_user.id, commit.to_hash, default)
|
||||
ProcessCommitWorker
|
||||
.perform_async(project.id, current_user.id, commit.to_hash, default)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -144,8 +144,8 @@ class IssuableBaseService < BaseService
|
|||
|
||||
def merge_quick_actions_into_params!(issuable)
|
||||
description, command_params =
|
||||
QuickActions::InterpretService.new(project, current_user).
|
||||
execute(params[:description], issuable)
|
||||
QuickActions::InterpretService.new(project, current_user)
|
||||
.execute(params[:description], issuable)
|
||||
|
||||
# Avoid a description already set on an issuable to be overwritten by a nil
|
||||
params[:description] = description if params.key?(:description)
|
||||
|
|
|
@ -30,8 +30,8 @@ module Issues
|
|||
|
||||
Discussions::ResolveService.new(project, current_user,
|
||||
merge_request: merge_request_to_resolve_discussions_of,
|
||||
follow_up_issue: issue).
|
||||
execute(discussions_to_resolve)
|
||||
follow_up_issue: issue)
|
||||
.execute(discussions_to_resolve)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -26,29 +26,29 @@ module Labels
|
|||
private
|
||||
|
||||
def label_ids_for_merge(new_label)
|
||||
LabelsFinder.
|
||||
new(current_user, title: new_label.title, group_id: project.group.id).
|
||||
execute(skip_authorization: true).
|
||||
where.not(id: new_label).
|
||||
select(:id) # Can't use pluck() to avoid object-creation because of the batching
|
||||
LabelsFinder
|
||||
.new(current_user, title: new_label.title, group_id: project.group.id)
|
||||
.execute(skip_authorization: true)
|
||||
.where.not(id: new_label)
|
||||
.select(:id) # Can't use pluck() to avoid object-creation because of the batching
|
||||
end
|
||||
|
||||
def update_issuables(new_label, label_ids)
|
||||
LabelLink.
|
||||
where(label: label_ids).
|
||||
update_all(label_id: new_label)
|
||||
LabelLink
|
||||
.where(label: label_ids)
|
||||
.update_all(label_id: new_label)
|
||||
end
|
||||
|
||||
def update_issue_board_lists(new_label, label_ids)
|
||||
List.
|
||||
where(label: label_ids).
|
||||
update_all(label_id: new_label)
|
||||
List
|
||||
.where(label: label_ids)
|
||||
.update_all(label_id: new_label)
|
||||
end
|
||||
|
||||
def update_priorities(new_label, label_ids)
|
||||
LabelPriority.
|
||||
where(label: label_ids).
|
||||
update_all(label_id: new_label)
|
||||
LabelPriority
|
||||
.where(label: label_ids)
|
||||
.update_all(label_id: new_label)
|
||||
end
|
||||
|
||||
def update_project_labels(label_ids)
|
||||
|
|
|
@ -41,16 +41,16 @@ module Labels
|
|||
end
|
||||
|
||||
def group_labels_applied_to_issues
|
||||
Label.joins(:issues).
|
||||
where(
|
||||
Label.joins(:issues)
|
||||
.where(
|
||||
issues: { project_id: project.id },
|
||||
labels: { type: 'GroupLabel', group_id: old_group.id }
|
||||
)
|
||||
end
|
||||
|
||||
def group_labels_applied_to_merge_requests
|
||||
Label.joins(:merge_requests).
|
||||
where(
|
||||
Label.joins(:merge_requests)
|
||||
.where(
|
||||
merge_requests: { target_project_id: project.id },
|
||||
labels: { type: 'GroupLabel', group_id: old_group.id }
|
||||
)
|
||||
|
@ -64,15 +64,15 @@ module Labels
|
|||
end
|
||||
|
||||
def update_label_links(labels, old_label_id:, new_label_id:)
|
||||
LabelLink.joins(:label).
|
||||
merge(labels).
|
||||
where(label_id: old_label_id).
|
||||
update_all(label_id: new_label_id)
|
||||
LabelLink.joins(:label)
|
||||
.merge(labels)
|
||||
.where(label_id: old_label_id)
|
||||
.update_all(label_id: new_label_id)
|
||||
end
|
||||
|
||||
def update_label_priorities(old_label_id:, new_label_id:)
|
||||
LabelPriority.where(project_id: project.id, label_id: old_label_id).
|
||||
update_all(label_id: new_label_id)
|
||||
LabelPriority.where(project_id: project.id, label_id: old_label_id)
|
||||
.update_all(label_id: new_label_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,30 +26,30 @@ module Members
|
|||
|
||||
def unassign_issues_and_merge_requests(member)
|
||||
if member.is_a?(GroupMember)
|
||||
issues = Issue.unscoped.select(1).
|
||||
joins(:project).
|
||||
where('issues.id = issue_assignees.issue_id AND projects.namespace_id = ?', member.source_id)
|
||||
issues = Issue.unscoped.select(1)
|
||||
.joins(:project)
|
||||
.where('issues.id = issue_assignees.issue_id AND projects.namespace_id = ?', member.source_id)
|
||||
|
||||
# DELETE FROM issue_assignees WHERE user_id = X AND EXISTS (...)
|
||||
IssueAssignee.unscoped.
|
||||
where('user_id = :user_id AND EXISTS (:sub)', user_id: member.user_id, sub: issues).
|
||||
delete_all
|
||||
IssueAssignee.unscoped
|
||||
.where('user_id = :user_id AND EXISTS (:sub)', user_id: member.user_id, sub: issues)
|
||||
.delete_all
|
||||
|
||||
MergeRequestsFinder.new(user, group_id: member.source_id, assignee_id: member.user_id).
|
||||
execute.
|
||||
update_all(assignee_id: nil)
|
||||
MergeRequestsFinder.new(user, group_id: member.source_id, assignee_id: member.user_id)
|
||||
.execute
|
||||
.update_all(assignee_id: nil)
|
||||
else
|
||||
project = member.source
|
||||
|
||||
# SELECT 1 FROM issues WHERE issues.id = issue_assignees.issue_id AND issues.project_id = X
|
||||
issues = Issue.unscoped.select(1).
|
||||
where('issues.id = issue_assignees.issue_id').
|
||||
where(project_id: project.id)
|
||||
issues = Issue.unscoped.select(1)
|
||||
.where('issues.id = issue_assignees.issue_id')
|
||||
.where(project_id: project.id)
|
||||
|
||||
# DELETE FROM issue_assignees WHERE user_id = X AND EXISTS (...)
|
||||
IssueAssignee.unscoped.
|
||||
where('user_id = :user_id AND EXISTS (:sub)', user_id: member.user_id, sub: issues).
|
||||
delete_all
|
||||
IssueAssignee.unscoped
|
||||
.where('user_id = :user_id AND EXISTS (:sub)', user_id: member.user_id, sub: issues)
|
||||
.delete_all
|
||||
|
||||
project.merge_requests.opened.assigned_to(member.user).update_all(assignee_id: nil)
|
||||
end
|
||||
|
|
|
@ -27,10 +27,10 @@ module MergeRequests
|
|||
tree: merge_index.write_tree(rugged)
|
||||
}
|
||||
|
||||
conflicts_for_resolution.
|
||||
project.
|
||||
repository.
|
||||
resolve_conflicts(current_user, merge_request.source_branch, commit_params)
|
||||
conflicts_for_resolution
|
||||
.project
|
||||
.repository
|
||||
.resolve_conflicts(current_user, merge_request.source_branch, commit_params)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -61,8 +61,8 @@ module MergeRequests
|
|||
MergeRequests::PostMergeService.new(project, current_user).execute(merge_request)
|
||||
|
||||
if params[:should_remove_source_branch].present? || @merge_request.force_remove_source_branch?
|
||||
DeleteBranchService.new(@merge_request.source_project, branch_deletion_user).
|
||||
execute(merge_request.source_branch)
|
||||
DeleteBranchService.new(@merge_request.source_project, branch_deletion_user)
|
||||
.execute(merge_request.source_branch)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -43,9 +43,9 @@ module MergeRequests
|
|||
end
|
||||
|
||||
filter_merge_requests(merge_requests).each do |merge_request|
|
||||
MergeRequests::PostMergeService.
|
||||
new(merge_request.target_project, @current_user).
|
||||
execute(merge_request)
|
||||
MergeRequests::PostMergeService
|
||||
.new(merge_request.target_project, @current_user)
|
||||
.execute(merge_request)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -56,8 +56,8 @@ module MergeRequests
|
|||
# Refresh merge request diff if we push to source or target branch of merge request
|
||||
# Note: we should update merge requests from forks too
|
||||
def reload_merge_requests
|
||||
merge_requests = @project.merge_requests.opened.
|
||||
by_source_or_target_branch(@branch_name).to_a
|
||||
merge_requests = @project.merge_requests.opened
|
||||
.by_source_or_target_branch(@branch_name).to_a
|
||||
|
||||
# Fork merge requests
|
||||
merge_requests += MergeRequest.opened
|
||||
|
|
|
@ -22,8 +22,8 @@ module Notes
|
|||
def extract_commands(note, options = {})
|
||||
return [note.note, {}] unless supported?(note)
|
||||
|
||||
QuickActions::InterpretService.new(project, current_user, options).
|
||||
execute(note.note, note.noteable)
|
||||
QuickActions::InterpretService.new(project, current_user, options)
|
||||
.execute(note.note, note.noteable)
|
||||
end
|
||||
|
||||
def execute(command_params, note)
|
||||
|
|
|
@ -19,8 +19,8 @@ module Tags
|
|||
|
||||
if new_tag
|
||||
if release_description
|
||||
CreateReleaseService.new(@project, @current_user).
|
||||
execute(tag_name, release_description)
|
||||
CreateReleaseService.new(@project, @current_user)
|
||||
.execute(tag_name, release_description)
|
||||
end
|
||||
|
||||
success.merge(tag: new_tag)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue