...
 
Commits (311)
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-9.6-graphicsmagick-1.3.29"
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-9.6-graphicsmagick-1.3.33"
variables:
RAILS_ENV: "test"
......
......@@ -15,7 +15,7 @@
.gitlab:assets:compile-metadata:
<<: *assets-compile-cache
extends: .dedicated-no-docs-pull-cache-job
image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-git-2.22-chrome-73.0-node-12.x-yarn-1.16-graphicsmagick-1.3.29-docker-18.06.1
image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-git-2.22-chrome-73.0-node-12.x-yarn-1.16-graphicsmagick-1.3.33-docker-18.06.1
dependencies:
- setup-test-env
services:
......
......@@ -90,7 +90,7 @@
.rspec-metadata-pg-10: &rspec-metadata-pg-10
<<: *rspec-metadata
<<: *use-pg-10
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-10-graphicsmagick-1.3.29"
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-10-graphicsmagick-1.3.33"
# DB migration, rollback, and seed jobs
.db-migrate-reset: &db-migrate-reset
......
......@@ -26,7 +26,7 @@ Add all known Documentation Requirements here, per https://docs.gitlab.com/ee/de
### Testing
<!-- What risks does this change pose? How might it affect the quality of the product? What additional test coverage or changes to tests will be needed? Will it require cross-browser testing? See the test engineering process for further guidelines: https://about.gitlab.com/handbook/engineering/quality/guidelines/test-engineering/ -->
<!-- What risks does this change pose? How might it affect the quality of the product? What additional test coverage or changes to tests will be needed? Will it require cross-browser testing? See the test engineering process for further help: https://about.gitlab.com/handbook/engineering/quality/test-engineering/ -->
### What does success look like, and how can we measure that?
......
......@@ -89,7 +89,7 @@ New end-to-end and integration tests (Selenium and API) should be added to the
Please note if automated tests already exist.
When adding new automated tests, please keep [testing levels](https://docs.gitlab.com/ce/development/testing_guide/testing_levels.html)
When adding new automated tests, please keep [testing levels](https://docs.gitlab.com/ee/development/testing_guide/testing_levels.html)
in mind.
-->
......
Please view this file on the master branch, on stable branches it's out of date.
## 12.1.5
- No changes.
## 12.1.4
### Fixed (3 changes)
......@@ -48,6 +52,10 @@ Please view this file on the master branch, on stable branches it's out of date.
- Don't send CI usage email notifications for self-hosted instances. !14809
## 12.0.6
- No changes.
## 12.0.2 (2019-06-25)
### Fixed (1 change)
......@@ -191,6 +199,10 @@ Please view this file on the master branch, on stable branches it's out of date.
- Remove commit count from storage quotass.
## 11.11.8
- No changes.
## 11.11.7
### Security (5 changes)
......
......@@ -2,6 +2,14 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 12.1.5
### Security (2 changes)
- Upgrade Gitaly to 1.53.2 to prevent revision flag injection exploits.
- Upgrade pages to 1.7.1 to prevent gitlab api token recovery from cookie.
## 12.1.4
### Fixed (3 changes, 1 of them is from the community)
......@@ -330,6 +338,10 @@ entry.
- Removes EE differences for app/views/admin/users/show.html.haml.
## 12.0.6
- No changes.
## 12.0.3 (2019-06-27)
- No changes.
......@@ -677,6 +689,14 @@ entry.
- Moves the table pagination shared component.
## 11.11.8
### Security (2 changes)
- Upgrade Gitaly to 1.42.7 to prevent revision flag injection exploits.
- Upgrade pages to 1.5.1 to prevent gitlab api token recovery from cookie.
## 11.11.7
### Security (9 changes)
......
1.58.0
\ No newline at end of file
1.59.0
The GitLab Enterprise Edition (EE) license (the “EE License”)
Copyright (c) 2011-present GitLab B.V.
With regard to the GitLab Software:
Portions of this software are licensed as follows:
This software and associated documentation files (the "Software") may only be
used in production, if you (and any entity that you represent) have agreed to,
and are in compliance with, the GitLab Subscription Terms of Service, available
at https://about.gitlab.com/terms/#subscription (the “EE Terms”), or other
agreement governing the use of the Software, as agreed by you and GitLab,
and otherwise have a valid GitLab Enterprise Edition subscription for the
correct number of user seats. Subject to the foregoing sentence, you are free to
modify this Software and publish patches to the Software. You agree that GitLab
and/or its licensors (as applicable) retain all right, title and interest in and
to all such modifications and/or patches, and all such modifications and/or
patches may only be used, copied, modified, displayed, distributed, or otherwise
exploited with a valid GitLab Enterprise Edition subscription for the correct
number of user seats. Notwithstanding the foregoing, you may copy and modify
the Software for development and testing purposes, without requiring a
subscription. You agree that GitLab and/or its licensors (as applicable) retain
all right, title and interest in and to all such modifications. You are not
granted any other rights beyond what is expressly stated herein. Subject to the
foregoing, it is forbidden to copy, merge, publish, distribute, sublicense,
and/or sell the Software.
* All content residing under the "doc/" directory of this repository is licensed under "Creative Commons: CC BY-SA 4.0 license".
* All content that resides under the "ee/" directory of this repository, if that directory exists, is licensed under the license defined in "ee/LICENSE".
* All client-side JavaScript (when served directly or after being compiled, arranged, augmented, or combined), is licensed under the "MIT Expat" license.
* All third party components incorporated into the GitLab Software are licensed under the original license provided by the owner of the applicable component.
* Content outside of the above mentioned directories or restrictions above is available under the "MIT Expat" license as defined below.
This EE License applies only to the part of this Software that is not
distributed as part of GitLab Community Edition (CE), and that is not a file
that produces client-side JavaScript, in whole or in part. Any part of this
Software distributed as part of GitLab CE or that is a file that produces
client-side JavaScript, in whole or in part, is copyrighted under the MIT Expat
license. The full text of this EE License shall be included in all copies or
substantial portions of the Software.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
......@@ -38,7 +25,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
For all third party components incorporated into the GitLab Software, those
components are licensed under the original license provided by the owner of the
applicable component.
# GitLab
![logo](https://about.gitlab.com/images/logo.png)
## Test coverage
- [![Ruby coverage](https://gitlab.com/gitlab-org/gitlab-ee/badges/master/coverage.svg?job=coverage)](https://gitlab-org.gitlab.io/gitlab-ee/coverage-ruby) Ruby
......@@ -11,8 +13,6 @@ The canonical source of GitLab Community Edition is [hosted on GitLab.com](https
The source of GitLab Enterprise Edition is [hosted on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ee).
# ![logo](https://about.gitlab.com/images/logo.png) GitLab
## Free trial
You can request a free trial of GitLab Ultimate [on our website](https://about.gitlab.com/free-trial/).
......@@ -28,10 +28,6 @@ To see how GitLab looks please see the [features page on our website](https://ab
- Used by more than 100,000 organizations, GitLab is the most popular solution to manage Git repositories on-premises
- Completely free and open source (MIT Expat license)
## Hiring
We're hiring developers, support people, and production engineers all the time, please see our [jobs page](https://about.gitlab.com/jobs/).
## Editions
There are two editions of GitLab:
......@@ -39,6 +35,15 @@ There are two editions of GitLab:
- GitLab Community Edition (CE) is available freely under the MIT Expat license.
- GitLab Enterprise Edition (EE) includes [extra features](https://about.gitlab.com/pricing/#compare-options) that are more useful for organizations with more than 100 users. To use EE and get official support please [become a subscriber](https://about.gitlab.com/pricing/).
## Licensing
See the [LICENSE](LICENSE) file for licensing information as it pertains to
files in this repository.
## Hiring
We're hiring developers, support people, and production engineers all the time, please see our [jobs page](https://about.gitlab.com/jobs/).
## Website
On [about.gitlab.com](https://about.gitlab.com/) you can find more information about:
......@@ -66,14 +71,6 @@ There are various other options to install GitLab, please refer to the [installa
GitLab is an open source project and we are very happy to accept community contributions. Please refer to [Contributing to GitLab page](https://about.gitlab.com/contributing/) for more details.
## Licensing
GitLab Community Edition (CE) is available freely under the MIT Expat license.
All third party components incorporated into the GitLab Software are licensed under the original license provided by the owner of the applicable component.
All Documentation content that resides under the `doc/` directory of this repository is licensed under Creative Commons: CC BY-SA 4.0.
## Install a development environment
To work on GitLab itself, we recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
......
......@@ -6,6 +6,8 @@ export default class ShortcutsWiki extends ShortcutsNavigation {
constructor() {
super();
Mousetrap.bind('e', ShortcutsWiki.editWiki);
this.enabledHelp.push('.hidden-shortcut.wiki');
}
static editWiki() {
......
import axios from '~/lib/utils/axios_utils';
function showCount(el, count) {
el.textContent = count;
el.classList.remove('hidden');
}
function refreshCount(el) {
const { url } = el.dataset;
return axios
.get(url)
.then(({ data }) => showCount(el, data.count))
.catch(e => {
// eslint-disable-next-line no-console
console.error(`Failed to fetch search count from '${url}'.`, e);
});
}
export default function refreshCounts() {
const elements = Array.from(document.querySelectorAll('.js-search-count'));
return Promise.all(elements.map(refreshCount));
}
......@@ -3,6 +3,7 @@ import Flash from '~/flash';
import Api from '~/api';
import { __ } from '~/locale';
import Project from '~/pages/projects/project';
import refreshCounts from './refresh_counts';
export default class Search {
constructor() {
......@@ -14,6 +15,7 @@ export default class Search {
this.groupId = $groupDropdown.data('groupId');
this.eventListeners();
refreshCounts();
$groupDropdown.glDropdown({
selectable: true,
......
......@@ -94,9 +94,6 @@ export default {
return __('Merge');
},
shouldShowMergeOptionsDropdown() {
return this.isAutoMergeAvailable && !this.mr.onlyAllowMergeIfPipelineSucceeds;
},
isRemoveSourceBranchButtonDisabled() {
return this.isMergeButtonDisabled;
},
......@@ -246,7 +243,7 @@ export default {
{{ mergeButtonText }}
</button>
<button
v-if="isAutoMergeAvailable"
v-if="shouldShowMergeImmediatelyDropdown"
:disabled="isMergeButtonDisabled"
type="button"
class="btn btn-sm btn-info dropdown-toggle js-merge-moment"
......@@ -256,7 +253,7 @@ export default {
<i class="fa fa-chevron-down qa-merge-moment-dropdown" aria-hidden="true"></i>
</button>
<ul
v-if="shouldShowMergeOptionsDropdown"
v-if="shouldShowMergeImmediatelyDropdown"
class="dropdown-menu dropdown-menu-right"
role="menu"
>
......
......@@ -15,5 +15,8 @@ export default {
// MWPS is currently the only auto merge strategy available in CE
return __('Merge when pipeline succeeds');
},
shouldShowMergeImmediatelyDropdown() {
return this.mr.isPipelineActive && !this.mr.onlyAllowMergeIfPipelineSucceeds;
},
},
};
......@@ -603,6 +603,7 @@ $blame-blue: #254e77;
* Builds
*/
$builds-trace-bg: #111;
$job-log-highlight-height: 18px;
/*
* Commit Page
......
......@@ -124,6 +124,26 @@
float: left;
padding-left: $gl-padding-8;
}
.section-start {
display: inline;
}
.section-start,
.section-header {
&:hover {
cursor: pointer;
&::after {
content: '';
background-color: rgba($white-light, 0.2);
left: 0;
right: 0;
position: absolute;
height: $job-log-highlight-height;
}
}
}
}
.build-header {
......
......@@ -4,7 +4,7 @@
*/
.todos-list > .todo {
// workaround because we cannot use border-colapse
// workaround because we cannot use border-collapse
border-top: 1px solid transparent;
display: flex;
flex-direction: row;
......
.new-wiki-page {
.new-wiki-page-slug-tip {
display: inline-block;
max-width: 100%;
margin-top: 5px;
}
}
.wiki-form {
.edit-wiki-page-slug-tip {
display: inline-block;
max-width: 100%;
margin-top: 5px;
}
}
.title .edit-wiki-header {
width: 780px;
margin-left: auto;
......@@ -22,7 +6,6 @@
}
.wiki-page-header {
@extend .top-area;
position: relative;
.wiki-breadcrumb {
......
......@@ -14,8 +14,14 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
@cycle_analytics_no_data = @cycle_analytics.no_stats?
respond_to do |format|
format.html
format.json { render json: cycle_analytics_json }
format.html do
Gitlab::UsageDataCounters::CycleAnalyticsCounter.count(:views)
render :show
end
format.json do
render json: cycle_analytics_json
end
end
end
......
......@@ -26,7 +26,7 @@ class Projects::RawController < Projects::ApplicationController
limiter.log_request(request, :raw_blob_request_limit, current_user)
flash[:alert] = _('You cannot access the raw file. Please wait a minute.')
redirect_to project_blob_path(@project, File.join(@ref, @path))
redirect_to project_blob_path(@project, File.join(@ref, @path)), status: :too_many_requests
end
def raw_blob_request_limit
......
......@@ -36,6 +36,15 @@ class SearchController < ApplicationController
check_single_commit_result
end
def count
params.require([:search, :scope])
scope = search_service.scope
count = search_service.search_results.formatted_count(scope)
render json: { count: count }
end
# rubocop: disable CodeReuse/ActiveRecord
def autocomplete
term = params[:term]
......
# frozen_string_literal: true
class RemoteMirrorFinder
attr_accessor :params
def initialize(params)
@params = params
end
# rubocop: disable CodeReuse/ActiveRecord
def execute
RemoteMirror.find_by(id: params[:id])
end
# rubocop: enable CodeReuse/ActiveRecord
end
......@@ -145,17 +145,27 @@ module SearchHelper
Sanitize.clean(str)
end
def search_filter_path(options = {})
exist_opts = {
search: params[:search],
project_id: params[:project_id],
group_id: params[:group_id],
scope: params[:scope],
repository_ref: params[:repository_ref]
}
def search_filter_link(scope, label, data: {}, search: {})
search_params = params
.merge(search)
.merge({ scope: scope })
.permit(:search, :scope, :project_id, :group_id, :repository_ref, :snippets)
if @scope == scope
li_class = 'active'
count = @search_results.formatted_count(scope)
else
badge_class = 'js-search-count hidden'
badge_data = { url: search_count_path(search_params) }
end
options = exist_opts.merge(options)
search_path(options)
content_tag :li, class: li_class, data: data do
link_to search_path(search_params) do
concat label
concat ' '
concat content_tag(:span, count, class: ['badge badge-pill', badge_class], data: badge_data)
end
end
end
def search_filter_input_options(type)
......@@ -212,10 +222,6 @@ module SearchHelper
sanitize(html, tags: %w(a p ol ul li pre code))
end
def limited_count(count, limit = 1000)
count > limit ? "#{limit}+" : count
end
def search_tabs?(tab)
return false if Feature.disabled?(:users_search, default_enabled: true)
......
......@@ -3,7 +3,7 @@
module Emails
module RemoteMirrors
def remote_mirror_update_failed_email(remote_mirror_id, recipient_id)
@remote_mirror = RemoteMirrorFinder.new(id: remote_mirror_id).execute
@remote_mirror = RemoteMirror.find_by_id(remote_mirror_id)
@project = @remote_mirror.project
mail(to: recipient(recipient_id, @project.group), subject: subject('Remote mirror update failed'))
......
......@@ -384,7 +384,7 @@ module Ci
return unless has_environment?
strong_memoize(:expanded_environment_name) do
ExpandVariables.expand(environment, simple_variables)
ExpandVariables.expand(environment, -> { simple_variables })
end
end
......
......@@ -41,7 +41,7 @@ module Clusters
extra_apps = Clusters::Applications::Helm.where('EXISTS (?)', klass.select(1).where(cluster_id: cluster_id))
applications = applications.present? ? applications.or(extra_apps) : extra_apps
applications = applications ? applications.or(extra_apps) : extra_apps
end
!applications.exists?
......
......@@ -42,8 +42,11 @@ class CommitStatus < ApplicationRecord
scope :ordered, -> { order(:name) }
scope :latest_ordered, -> { latest.ordered.includes(project: :namespace) }
scope :retried_ordered, -> { retried.ordered.includes(project: :namespace) }
scope :before_stage, -> (index) { where('stage_idx < ?', index) }
scope :for_stage, -> (index) { where(stage_idx: index) }
scope :after_stage, -> (index) { where('stage_idx > ?', index) }
scope :processables, -> { where(type: %w[Ci::Build Ci::Bridge]) }
scope :for_ids, -> (ids) { where(id: ids) }
scope :with_needs, -> (names = nil) do
needs = Ci::BuildNeed.scoped_build.select(1)
......@@ -51,8 +54,10 @@ class CommitStatus < ApplicationRecord
where('EXISTS (?)', needs).preload(:needs)
end
scope :without_needs, -> do
where('NOT EXISTS (?)', Ci::BuildNeed.scoped_build.select(1))
scope :without_needs, -> (names = nil) do
needs = Ci::BuildNeed.scoped_build.select(1)
needs = needs.where(name: names) if names
where('NOT EXISTS (?)', needs)
end
# We use `CommitStatusEnums.failure_reasons` here so that EE can more easily
......@@ -151,6 +156,18 @@ class CommitStatus < ApplicationRecord
end
end
def self.names
select(:name)
end
def self.status_for_prior_stages(index)
before_stage(index).latest.status || 'success'
end
def self.status_for_names(names)
where(name: names).latest.status || 'success'
end
def locking_enabled?
will_save_change_to_status?
end
......
......@@ -106,10 +106,15 @@ module HasStatus
scope :running_or_pending, -> { with_status(:running, :pending) }
scope :finished, -> { with_status(:success, :failed, :canceled) }
scope :failed_or_canceled, -> { with_status(:failed, :canceled) }
scope :incomplete, -> { without_statuses(completed_statuses) }
scope :cancelable, -> do
where(status: [:running, :preparing, :pending, :created, :scheduled])
end
scope :without_statuses, -> (names) do
with_status(all_state_names - names.to_a)
end
end
def started?
......
......@@ -138,6 +138,8 @@ class Label < ApplicationRecord
end
def self.on_project_board?(project_id, label_id)
return false if label_id.blank?
on_project_boards(project_id).where(id: label_id).exists?
end
......
......@@ -3,5 +3,3 @@
class PersonalSnippet < Snippet
include WithUploads
end
PersonalSnippet.prepend_if_ee('EE::PersonalSnippet')
......@@ -1230,6 +1230,14 @@ class Project < ApplicationRecord
end
end
def has_active_hooks?(hooks_scope = :push_hooks)
hooks.hooks_for(hooks_scope).any? || SystemHook.hooks_for(hooks_scope).any?
end
def has_active_services?(hooks_scope = :push_hooks)
services.public_send(hooks_scope).any? # rubocop:disable GitlabSecurity/PublicSend
end
def valid_repo?
repository.exists?
rescue
......
......@@ -68,7 +68,7 @@ module ChatMessage
title_link: pipeline_url,
fields: attachments_fields,
footer: project.name,
footer_icon: project.avatar_url,
footer_icon: project.avatar_url(only_path: false),
ts: finished_at
}]
end
......
......@@ -12,5 +12,3 @@ class ProjectSnippet < Snippet
participant :author
participant :notes_with_associations
end
ProjectSnippet.prepend_if_ee('EE::ProjectSnippet')
......@@ -4,6 +4,8 @@ class RemoteMirror < ApplicationRecord
include AfterCommitQueue
include MirrorAuthentication
MAX_FIRST_RUNTIME = 3.hours
MAX_INCREMENTAL_RUNTIME = 1.hour
PROTECTED_BACKOFF_DELAY = 1.minute
UNPROTECTED_BACKOFF_DELAY = 5.minutes
......@@ -31,11 +33,18 @@ class RemoteMirror < ApplicationRecord
scope :enabled, -> { where(enabled: true) }
scope :started, -> { with_update_status(:started) }
scope :stuck, -> { started.where('last_update_at < ? OR (last_update_at IS NULL AND updated_at < ?)', 1.hour.ago, 3.hours.ago) }
scope :stuck, -> do
started
.where('(last_update_started_at < ? AND last_update_at IS NOT NULL)',
MAX_INCREMENTAL_RUNTIME.ago)
.or(where('(last_update_started_at < ? AND last_update_at IS NULL)',
MAX_FIRST_RUNTIME.ago))
end
state_machine :update_status, initial: :none do
event :update_start do
transition [:none, :finished, :failed] => :started
transition any => :started
end
event :update_finish do
......@@ -46,9 +55,14 @@ class RemoteMirror < ApplicationRecord
transition started: :failed
end
event :update_retry do
transition started: :to_retry
end
state :started
state :finished
state :failed
state :to_retry
after_transition any => :started do |remote_mirror, _|
Gitlab::Metrics.add_event(:remote_mirrors_running)
......@@ -138,16 +152,27 @@ class RemoteMirror < ApplicationRecord
end
def updated_since?(timestamp)
last_update_started_at && last_update_started_at > timestamp && !update_failed?
return false if failed?
last_update_started_at && last_update_started_at > timestamp
end
def mark_for_delete_if_blank_url
mark_for_destruction if url.blank?
end
def mark_as_failed(error_message)
update_column(:last_error, Gitlab::UrlSanitizer.sanitize(error_message))
update_fail
def update_error_message(error_message)
self.last_error = Gitlab::UrlSanitizer.sanitize(error_message)
end
def mark_for_retry!(error_message)
update_error_message(error_message)
update_retry!
end
def mark_as_failed!(error_message)
update_error_message(error_message)
update_fail!
end
def url=(value)
......@@ -190,6 +215,18 @@ class RemoteMirror < ApplicationRecord
update_column(:error_notification_sent, true)
end
def backoff_delay
if self.only_protected_branches
PROTECTED_BACKOFF_DELAY
else
UNPROTECTED_BACKOFF_DELAY
end
end
def max_runtime
last_update_at.present? ? MAX_INCREMENTAL_RUNTIME : MAX_FIRST_RUNTIME
end
private
def store_credentials
......@@ -219,14 +256,6 @@ class RemoteMirror < ApplicationRecord
self.last_update_started_at >= Time.now - backoff_delay
end
def backoff_delay
if self.only_protected_branches
PROTECTED_BACKOFF_DELAY
else
UNPROTECTED_BACKOFF_DELAY
end
end
def reset_fields
update_columns(
last_error: nil,
......
......@@ -418,25 +418,29 @@ class Repository
end
# Runs code before pushing (= creating or removing) a tag.
#
# Note that this doesn't expire the tags. You may need to call
# expire_caches_for_tags or expire_tags_cache.
def before_push_tag
repository_event(:push_tag)
end
def expire_caches_for_tags
expire_statistics_caches
expire_emptiness_caches
expire_tags_cache
repository_event(:push_tag)
end
# Runs code before removing a tag.
def before_remove_tag
expire_tags_cache
expire_statistics_caches
expire_caches_for_tags
repository_event(:remove_tag)
end
# Runs code after removing a tag.
def after_remove_tag
expire_tags_cache
expire_caches_for_tags
end
# Runs code after the HEAD of a repository is changed.
......@@ -460,8 +464,8 @@ class Repository
end
# Runs code after a new branch has been created.
def after_create_branch
expire_branches_cache
def after_create_branch(expire_cache: true)
expire_branches_cache if expire_cache
repository_event(:push_branch)
end
......@@ -474,8 +478,8 @@ class Repository
end
# Runs code after an existing branch has been removed.
def after_remove_branch
expire_branches_cache
def after_remove_branch(expire_cache: true)
expire_branches_cache if expire_cache
end
def method_missing(msg, *args, &block)
......
......@@ -438,18 +438,20 @@ class User < ApplicationRecord
order = <<~SQL
CASE
WHEN users.name = %{query} THEN 0
WHEN users.username = %{query} THEN 1
WHEN users.email = %{query} THEN 2
WHEN users.name = :query THEN 0
WHEN users.username = :query THEN 1
WHEN users.email = :query THEN 2
ELSE 3
END
SQL
sanitized_order_sql = Arel.sql(sanitize_sql_array([order, query: query]))
where(
fuzzy_arel_match(:name, query, lower_exact_match: true)
.or(fuzzy_arel_match(:username, query, lower_exact_match: true))
.or(arel_table[:email].eq(query))
).reorder(order % { query: ApplicationRecord.connection.quote(query) }, :name)
).reorder(sanitized_order_sql, :name)
end
# Limits the result set to users _not_ in the given query/list of IDs.
......
......@@ -42,14 +42,19 @@ module Ci
return false unless trigger_build_ids.present?
return false unless Feature.enabled?(:ci_dag_support, project)
# rubocop: disable CodeReuse/ActiveRecord
trigger_build_names = pipeline.statuses
.where(id: trigger_build_ids)
.select(:name)
# rubocop: enable CodeReuse/ActiveRecord
# we find processables that are dependent:
# 1. because of current dependency,
trigger_build_names = pipeline.processables.latest
.for_ids(trigger_build_ids).names
# 2. does not have builds that not yet complete
incomplete_build_names = pipeline.processables.latest
.incomplete.names
# Each found processable is guaranteed here to have completed status
created_processables
.with_needs(trigger_build_names)
.without_needs(incomplete_build_names)
.find_each
.map(&method(:process_build_with_needs))
.any?
......@@ -70,17 +75,13 @@ module Ci
end
end
# rubocop: disable CodeReuse/ActiveRecord
def status_for_prior_stages(index)
pipeline.builds.where('stage_idx < ?', index).latest.status || 'success'
pipeline.processables.status_for_prior_stages(index)
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def status_for_build_needs(needs)
pipeline.builds.where(name: needs).latest.status || 'success'
pipeline.processables.status_for_names(needs)
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def stage_indexes_of_created_processables_without_needs
......@@ -89,12 +90,10 @@ module Ci
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def created_processables_in_stage_without_needs(index)
created_processables_without_needs
.where(stage_idx: index)
.for_stage(index)
end
# rubocop: enable CodeReuse/ActiveRecord
def created_processables_without_needs
if Feature.enabled?(:ci_dag_support, project)
......
......@@ -19,7 +19,7 @@ module Git
update_remote_mirrors
push_data
success
end
private
......@@ -33,7 +33,7 @@ module Git
end
def limited_commits
commits.last(PROCESS_COMMIT_LIMIT)
@limited_commits ||= commits.last(PROCESS_COMMIT_LIMIT)
end
def commits_count
......@@ -48,21 +48,25 @@ module Git
[]
end
# Push events in the activity feed only show information for the
# last commit.
def create_events
EventCreateService.new.push(project, current_user, push_data)
EventCreateService.new.push(project, current_user, event_push_data)
end
def create_pipelines
return unless params.fetch(:create_pipelines, true)
Ci::CreatePipelineService
.new(project, current_user, push_data)
.new(project, current_user, base_params)
.execute(:push, pipeline_options)
end
def execute_project_hooks
project.execute_hooks(push_data, hook_name)
project.execute_services(push_data, hook_name)
# Creating push_data invokes one CommitDelta RPC per commit. Only
# build this data if we actually need it.
project.execute_hooks(push_data, hook_name) if project.has_active_hooks?(hook_name)
project.execute_services(push_data, hook_name) if project.has_active_services?(hook_name)
end
def enqueue_invalidate_cache
......@@ -73,18 +77,35 @@ module Git
)
end
def push_data
@push_data ||= Gitlab::DataBuilder::Push.build(
project: project,
user: current_user,
def base_params
{
oldrev: params[:oldrev],
newrev: params[:newrev],
ref: params[:ref],
commits: limited_commits,
push_options: params[:push_options] || {}
}
end
def push_data_params(commits:, with_changed_files: true)
base_params.merge(
project: project,
user: current_user,
commits: commits,
message: event_message,
commits_count: commits_count,
push_options: params[:push_options] || {}
with_changed_files: with_changed_files
)
end
def event_push_data
# We only need the last commit for the event push, and we don't
# need the full deltas either.
@event_push_data ||= Gitlab::DataBuilder::Push.build(
push_data_params(commits: commits.last, with_changed_files: false))
end
def push_data
@push_data ||= Gitlab::DataBuilder::Push.build(push_data_params(commits: limited_commits))
# Dependent code may modify the push data, so return a duplicate each time
@push_data.dup
......
......@@ -63,7 +63,7 @@ module Git
end
def branch_create_hooks
project.repository.after_create_branch
project.repository.after_create_branch(expire_cache: false)
project.after_create_default_branch if default_branch?
end
......@@ -78,7 +78,7 @@ module Git
end
def branch_remove_hooks
project.repository.after_remove_branch
project.repository.after_remove_branch(expire_cache: false)
end
# Schedules processing of commit messages
......
......@@ -53,7 +53,7 @@ module Notes
# We must add the error after we call #save because errors are reset
# when #save is called
if only_commands
note.errors.add(:commands_only, message.presence || _('Commands did not apply'))
note.errors.add(:commands_only, message.presence || _('Failed to apply commands.'))
end
end
......
......@@ -2,31 +2,52 @@
module Projects
class UpdateRemoteMirrorService < BaseService
attr_reader :errors
MAX_TRIES = 3
def execute(remote_mirror)
def execute(remote_mirror, tries)
return success unless remote_mirror.enabled?
errors = []
update_mirror(remote_mirror)
begin
remote_mirror.ensure_remote!
repository.fetch_remote(remote_mirror.remote_name, ssh_auth: remote_mirror, no_tags: true)
success
rescue Gitlab::Git::CommandError => e
# This happens if one of the gitaly calls above fail, for example when
# branches have diverged, or the pre-receive hook fails.
retry_or_fail(remote_mirror, e.message, tries)
opts = {}
if remote_mirror.only_protected_branches?
opts[:only_branches_matching] = project.protected_branches.select(:name).map(&:name)
end
error(e.message)
rescue => e
remote_mirror.mark_as_failed!(e.message)
raise e
end
private
def update_mirror(remote_mirror)
remote_mirror.update_start!
remote_mirror.ensure_remote!
repository.fetch_remote(remote_mirror.remote_name, ssh_auth: remote_mirror, no_tags: true)
remote_mirror.update_repository(opts)
rescue => e
errors << e.message.strip
opts = {}
if remote_mirror.only_protected_branches?
opts[:only_branches_matching] = project.protected_branches.select(:name).map(&:name)
end
if errors.present?
error(errors.join("\n\n"))
remote_mirror.update_repository(opts)
remote_mirror.update_finish!
end
def retry_or_fail(mirror, message, tries)
if tries < MAX_TRIES
mirror.mark_for_retry!(message)
else
success
# It's not likely we'll be able to recover from this ourselves, so we'll
# notify the users of the problem, and don't trigger any sidekiq retries
# Instead, we'll wait for the next change to try the push again, or until
# a user manually retries.
mirror.mark_as_failed!(message)
end
end
end
......
......@@ -42,7 +42,7 @@ class UpdateDeploymentService
return unless environment_url
@expanded_environment_url =