Skip to content
Snippets Groups Projects
Commit 67f6d73c authored by John Jarvis's avatar John Jarvis
Browse files

Merge branch '11-10-stable-prepare-rc5' into '11-10-stable'

Prepare 11.10.0-rc5 release

See merge request gitlab-org/gitlab-ce!27199
parents c259867e 05655f3b
No related branches found
No related tags found
No related merge requests found
Showing
with 121 additions and 119 deletions
Loading
Loading
@@ -18,5 +18,3 @@ export const timeWindows = {
threeDays: __('3 days'),
oneWeek: __('1 week'),
};
export const msPerMinute = 60000;
import { timeWindows, msPerMinute } from './constants';
import { timeWindows } from './constants';
 
/**
* method that converts a predetermined time window to minutes
Loading
Loading
@@ -6,27 +6,26 @@ import { timeWindows, msPerMinute } from './constants';
* @param {String} timeWindow - The time window to convert to minutes
* @returns {number} The time window in minutes
*/
const getTimeDifferenceMinutes = timeWindow => {
const getTimeDifferenceSeconds = timeWindow => {
switch (timeWindow) {
case timeWindows.thirtyMinutes:
return 30;
return 60 * 30;
case timeWindows.threeHours:
return 60 * 3;
return 60 * 60 * 3;
case timeWindows.oneDay:
return 60 * 24 * 1;
return 60 * 60 * 24 * 1;
case timeWindows.threeDays:
return 60 * 24 * 3;
return 60 * 60 * 24 * 3;
case timeWindows.oneWeek:
return 60 * 24 * 7 * 1;
return 60 * 60 * 24 * 7 * 1;
default:
return 60 * 8;
return 60 * 60 * 8;
}
};
 
export const getTimeDiff = selectedTimeWindow => {
const end = Date.now();
const timeDifferenceMinutes = getTimeDifferenceMinutes(selectedTimeWindow);
const start = new Date(end - timeDifferenceMinutes * msPerMinute).getTime();
const end = Date.now() / 1000; // convert milliseconds to seconds
const start = end - getTimeDifferenceSeconds(selectedTimeWindow);
 
return { start, end };
};
Loading
Loading
Loading
Loading
@@ -25,6 +25,18 @@ $item-weight-max-width: 48px;
flex-grow: 1;
}
 
.issue-token-state-icon-open {
color: $green-500;
}
.issue-token-state-icon-closed {
color: $blue-500;
}
.merge-request-status.closed {
color: $red-500;
}
.issue-token-state-icon-open,
.issue-token-state-icon-closed,
.confidential-icon,
Loading
Loading
Loading
Loading
@@ -193,7 +193,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
return unless Feature.enabled?(:metrics_time_window, project)
return unless params[:start].present? || params[:end].present?
 
params.require([:start, :end]).values_at(:start, :end)
params.require([:start, :end])
end
 
def search_environment_names
Loading
Loading
Loading
Loading
@@ -81,7 +81,7 @@ class ProjectsFinder < UnionFinder
if private_only?
current_user.authorized_projects
else
Project.public_or_visible_to_user(current_user, params[:visibility_level])
Project.public_or_visible_to_user(current_user)
end
end
end
Loading
Loading
Loading
Loading
@@ -459,41 +459,14 @@ class Project < ApplicationRecord
 
# Returns a collection of projects that is either public or visible to the
# logged in user.
#
# requested_visiblity_levels: Normally all projects that are visible
# to the user (e.g. internal and public) are queried, but this
# parameter allows the caller to narrow the search space to optimize
# database queries. For instance, a caller may only want to see
# internal projects. Instead of querying for internal and public
# projects and throwing away public projects, this parameter allows
# the query to be targeted for only internal projects.
def self.public_or_visible_to_user(user = nil, requested_visibility_levels = [])
return public_to_user unless user
visible_levels = Gitlab::VisibilityLevel.levels_for_user(user)
include_private = true
requested_visibility_levels = Array(requested_visibility_levels)
if requested_visibility_levels.present?
visible_levels &= requested_visibility_levels
include_private = requested_visibility_levels.include?(Gitlab::VisibilityLevel::PRIVATE)
end
public_or_internal_rel =
if visible_levels.present?
where('projects.visibility_level IN (?)', visible_levels)
else
Project.none
end
private_rel =
if include_private
where('EXISTS (?)', user.authorizations_for_projects)
else
Project.none
end
public_or_internal_rel.or(private_rel)
def self.public_or_visible_to_user(user = nil)
if user
where('EXISTS (?) OR projects.visibility_level IN (?)',
user.authorizations_for_projects,
Gitlab::VisibilityLevel.levels_for_user(user))
else
public_to_user
end
end
 
# project features may be "disabled", "internal", "enabled" or "public". If "internal",
Loading
Loading
Loading
Loading
@@ -21,6 +21,7 @@ module MergeRequests
post_merge_manually_merged
reload_merge_requests
outdate_suggestions
refresh_pipelines_on_merge_requests
reset_merge_when_pipeline_succeeds
mark_pending_todos_done
cache_merge_requests_closing_issues
Loading
Loading
@@ -107,8 +108,6 @@ module MergeRequests
end
 
merge_request.mark_as_unchecked
create_pipeline_for(merge_request, current_user)
UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
end
 
# Upcoming method calls need the refreshed version of
Loading
Loading
@@ -134,6 +133,13 @@ module MergeRequests
end
end
 
def refresh_pipelines_on_merge_requests
merge_requests_for_source_branch.each do |merge_request|
create_pipeline_for(merge_request, current_user)
UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
end
end
def reset_merge_when_pipeline_succeeds
merge_requests_for_source_branch.each(&:reset_merge_when_pipeline_succeeds)
end
Loading
Loading
---
title: Create pipelines for merge requests only when source branch is updated
merge_request: 26921
author:
type: fixed
---
title: Optimize /api/v4/projects endpoint for visibility level
merge_request: 26481
author:
type: performance
Loading
Loading
@@ -62,7 +62,7 @@ into more features:
| [ChatOps](chatops/README.md) | Trigger CI jobs from chat, with results sent back to the channel. |
| [Interactive web terminals](interactive_web_terminal/index.md) | Open an interactive web terminal to debug the running jobs. |
| [Review Apps](review_apps/index.md) | Configure GitLab CI/CD to preview code changes in a per-branch basis. |
| [Optimising GitLab for large repositories](large_repositories/index.md) | Useful tips on how to optimise GitLab and GitLab Runner for big repositories. |
| [Optimizing GitLab for large repositories](large_repositories/index.md) | Useful tips on how to optimize GitLab and GitLab Runner for big repositories. |
| [Deploy Boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html) **[PREMIUM]** | Check the current health and status of each CI/CD environment running on Kubernetes. |
| [GitLab CI/CD for external repositories](https://docs.gitlab.com/ee/ci/ci_cd_for_external_repos/index.html) **[PREMIUM]** | Get the benefits of GitLab CI/CD combined with repositories in GitHub and BitBucket Cloud. |
 
Loading
Loading
# Optimising GitLab for large repositories
# Optimizing GitLab for large repositories
 
Large repositories consisting of more than 50k files in a worktree
often require special consideration because of
the time required to clone and check out.
 
GitLab and GitLab Runner handle this scenario well
but require optimised configuration to efficiently perform its
but require optimized configuration to efficiently perform its
set of operations.
 
The general guidelines for handling big repositories are simple.
Loading
Loading
@@ -15,7 +15,7 @@ Each guideline is described in more detail in the sections below:
- Always use shallow clone to reduce data transfer. Be aware that this puts more burden
on GitLab instance due to higher CPU impact.
- Control the clone directory if you heavily use a fork-based workflow.
- Optimise `git clean` flags to ensure that you remove or keep data that might affect or speed-up your build.
- Optimize `git clean` flags to ensure that you remove or keep data that might affect or speed-up your build.
 
## Shallow cloning
 
Loading
Loading
@@ -76,7 +76,7 @@ done by GitLab, requiring you to do them.
This can have implications if you heavily use big repositories with fork workflow.
 
Fork workflow from GitLab Runner's perspective is stored as a separate repository
with separate worktree. That means that GitLab Runner cannot optimise the usage
with separate worktree. That means that GitLab Runner cannot optimize the usage
of worktrees and you might have to instruct GitLab Runner to use that.
 
In such cases, ideally you want to make the GitLab Runner executor be used only used only
Loading
Loading
@@ -113,7 +113,7 @@ available parameters are dependent on Git version.
 
Following the guidelines above, lets imagine that we want to:
 
- Optimise for a big project (more than 50k files in directory).
- Optimize for a big project (more than 50k files in directory).
- Use forks-based workflow for contributing.
- Reuse existing worktrees. Have preconfigured runners that are pre-cloned with repositories.
- Runner assigned only to project and all forks.
Loading
Loading
# frozen_string_literal: true
 
module QA
context 'Verify' do
# Failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/91
context 'Verify', :quarantine do
describe 'CI variable support' do
it 'user adds a CI variable' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Loading
Loading
Loading
Loading
@@ -419,6 +419,17 @@ describe Projects::EnvironmentsController do
expect(json_response['data']).to eq({})
expect(json_response['last_update']).to eq(42)
end
context 'when time params are provided' do
it 'returns a metrics JSON document' do
additional_metrics(start: '1554702993.5398998', end: '1554717396.996232')
expect(response).to be_ok
expect(json_response['success']).to be(true)
expect(json_response['data']).to eq({})
expect(json_response['last_update']).to eq(42)
end
end
end
 
context 'when only one time param is provided' do
Loading
Loading
import { getTimeDiff } from '~/monitoring/utils';
import { timeWindows } from '~/monitoring/constants';
describe('getTimeDiff', () => {
it('defaults to an 8 hour (28800s) difference', () => {
const params = getTimeDiff();
expect(params.end - params.start).toEqual(28800);
});
it('accepts time window as an argument', () => {
const params = getTimeDiff(timeWindows.thirtyMinutes);
expect(params.end - params.start).not.toEqual(28800);
});
it('returns a value for every defined time window', () => {
const nonDefaultWindows = Object.keys(timeWindows).filter(window => window !== 'eightHours');
nonDefaultWindows.forEach(window => {
const params = getTimeDiff(timeWindows[window]);
const diff = params.end - params.start;
// Ensure we're not returning the default, 28800 (the # of seconds in 8 hrs)
expect(diff).not.toEqual(28800);
expect(typeof diff).toEqual('number');
});
});
});
Loading
Loading
@@ -2721,7 +2721,7 @@ describe Project do
end
 
describe '#any_lfs_file_locks?', :request_store do
let!(:project) { create(:project) }
set(:project) { create(:project) }
 
it 'returns false when there are no LFS file locks' do
expect(project.any_lfs_file_locks?).to be_falsey
Loading
Loading
@@ -3159,53 +3159,6 @@ describe Project do
expect(projects).to eq([public_project])
end
end
context 'with requested visibility levels' do
set(:internal_project) { create(:project, :internal, :repository) }
set(:private_project_2) { create(:project, :private) }
context 'with admin user' do
set(:admin) { create(:admin) }
it 'returns all projects' do
projects = described_class.all.public_or_visible_to_user(admin, [])
expect(projects).to match_array([public_project, private_project, private_project_2, internal_project])
end
it 'returns all public and private projects' do
projects = described_class.all.public_or_visible_to_user(admin, [Gitlab::VisibilityLevel::PUBLIC, Gitlab::VisibilityLevel::PRIVATE])
expect(projects).to match_array([public_project, private_project, private_project_2])
end
it 'returns all private projects' do
projects = described_class.all.public_or_visible_to_user(admin, [Gitlab::VisibilityLevel::PRIVATE])
expect(projects).to match_array([private_project, private_project_2])
end
end
context 'with regular user' do
it 'returns authorized projects' do
projects = described_class.all.public_or_visible_to_user(user, [])
expect(projects).to match_array([public_project, private_project, internal_project])
end
it "returns user's public and private projects" do
projects = described_class.all.public_or_visible_to_user(user, [Gitlab::VisibilityLevel::PUBLIC, Gitlab::VisibilityLevel::PRIVATE])
expect(projects).to match_array([public_project, private_project])
end
it 'returns one private project' do
projects = described_class.all.public_or_visible_to_user(user, [Gitlab::VisibilityLevel::PRIVATE])
expect(projects).to eq([private_project])
end
end
end
end
 
describe '.with_feature_available_for_user' do
Loading
Loading
Loading
Loading
@@ -146,7 +146,10 @@ describe MergeRequests::RefreshService do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
 
subject { service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/master') }
subject { service.new(project, @user).execute(@oldrev, @newrev, ref) }
let(:ref) { 'refs/heads/master' }
let(:project) { @project }
 
context "when .gitlab-ci.yml has merge_requests keywords" do
let(:config) do
Loading
Loading
@@ -162,14 +165,17 @@ describe MergeRequests::RefreshService do
it 'create detached merge request pipeline with commits' do
expect { subject }
.to change { @merge_request.merge_request_pipelines.count }.by(1)
.and change { @fork_merge_request.merge_request_pipelines.count }.by(1)
.and change { @another_merge_request.merge_request_pipelines.count }.by(0)
 
expect(@merge_request.has_commits?).to be_truthy
expect(@fork_merge_request.has_commits?).to be_truthy
expect(@another_merge_request.has_commits?).to be_falsy
end
 
it 'does not create detached merge request pipeline for forked project' do
expect { subject }
.not_to change { @fork_merge_request.merge_request_pipelines.count }
end
it 'create detached merge request pipeline for non-fork merge request' do
subject
 
Loading
Loading
@@ -177,11 +183,25 @@ describe MergeRequests::RefreshService do
.to be_detached_merge_request_pipeline
end
 
it 'create legacy detached merge request pipeline for fork merge request' do
subject
context 'when service is hooked by target branch' do
let(:ref) { 'refs/heads/feature' }
 
expect(@fork_merge_request.merge_request_pipelines.first)
.to be_legacy_detached_merge_request_pipeline
it 'does not create detached merge request pipeline' do
expect { subject }
.not_to change { @merge_request.merge_request_pipelines.count }
end
end
context 'when service runs on forked project' do
let(:project) { @fork_project }
it 'creates legacy detached merge request pipeline for fork merge request' do
expect { subject }
.to change { @fork_merge_request.merge_request_pipelines.count }.by(1)
expect(@fork_merge_request.merge_request_pipelines.first)
.to be_legacy_detached_merge_request_pipeline
end
end
 
context 'when ci_use_merge_request_ref feature flag is false' do
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment