Commit 13e2ca52 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'ce-to-ee-2018-07-11' into 'master'

CE upstream - 2018-07-11 09:25 UTC

See merge request gitlab-org/gitlab-ee!6457
parents 3c7cd2f9 ebeaf2df
...@@ -3,7 +3,7 @@ module PipelineSchedulesHelper ...@@ -3,7 +3,7 @@ module PipelineSchedulesHelper
ActiveSupport::TimeZone.all.map do |timezone| ActiveSupport::TimeZone.all.map do |timezone|
{ {
name: timezone.name, name: timezone.name,
offset: timezone.utc_offset, offset: timezone.now.utc_offset,
identifier: timezone.tzinfo.identifier identifier: timezone.tzinfo.identifier
} }
end end
......
...@@ -65,10 +65,10 @@ class GitGarbageCollectWorker ...@@ -65,10 +65,10 @@ class GitGarbageCollectWorker
client.repack_incremental client.repack_incremental
end end
rescue GRPC::NotFound => e rescue GRPC::NotFound => e
Gitlab::GitLogger.error("#{method} failed:\nRepository not found") Gitlab::GitLogger.error("#{__method__} failed:\nRepository not found")
raise Gitlab::Git::Repository::NoRepository.new(e) raise Gitlab::Git::Repository::NoRepository.new(e)
rescue GRPC::BadStatus => e rescue GRPC::BadStatus => e
Gitlab::GitLogger.error("#{method} failed:\n#{e}") Gitlab::GitLogger.error("#{__method__} failed:\n#{e}")
raise Gitlab::Git::CommandError.new(e) raise Gitlab::Git::CommandError.new(e)
end end
......
---
title: Add support for daylight savings time to pipleline schedules
merge_request: 20145
author:
type: fixed
---
title: Add missing maximum_timeout parameter
merge_request: 20355
author: gfyoung
type: fixed
---
title: Properly handle colons in URL passwords
merge_request:
author:
type: fixed
...@@ -198,14 +198,14 @@ And that's it, we're done! ...@@ -198,14 +198,14 @@ And that's it, we're done!
## Changing The Schema For Large Tables ## Changing The Schema For Large Tables
While `change_column_type_concurrently` and `rename_column_concurrently` can be While `change_column_type_concurrently` and `rename_column_concurrently` can be
used for changing the schema of a table without downtime it doesn't work very used for changing the schema of a table without downtime, it doesn't work very
well for large tables. Because all of the work happens in sequence the migration well for large tables. Because all of the work happens in sequence the migration
can take a very long time to complete, preventing a deployment from proceeding. can take a very long time to complete, preventing a deployment from proceeding.
They can also produce a lot of pressure on the database due to it rapidly They can also produce a lot of pressure on the database due to it rapidly
updating many rows in sequence. updating many rows in sequence.
To reduce database pressure you should instead use To reduce database pressure you should instead use
`change_column_type_using_background_migration` or `rename_column_concurrently` `change_column_type_using_background_migration` or `rename_column_using_background_migration`
when migrating a column in a large table (e.g. `issues`). These methods work when migrating a column in a large table (e.g. `issues`). These methods work
similarly to the concurrent counterparts but uses background migration to spread similarly to the concurrent counterparts but uses background migration to spread
the work / load over a longer time period, without slowing down deployments. the work / load over a longer time period, without slowing down deployments.
......
...@@ -58,7 +58,7 @@ module API ...@@ -58,7 +58,7 @@ module API
optional :access_level, type: String, values: Ci::Runner.access_levels.keys, optional :access_level, type: String, values: Ci::Runner.access_levels.keys,
desc: 'The access_level of the runner' desc: 'The access_level of the runner'
optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this Runner will handle the job' optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this Runner will handle the job'
at_least_one_of :description, :active, :tag_list, :run_untagged, :locked, :access_level at_least_one_of :description, :active, :tag_list, :run_untagged, :locked, :access_level, :maximum_timeout
end end
put ':id' do put ':id' do
runner = get_runner(params.delete(:id)) runner = get_runner(params.delete(:id))
......
...@@ -21,7 +21,17 @@ module DeclarativePolicy ...@@ -21,7 +21,17 @@ module DeclarativePolicy
cache = opts[:cache] || {} cache = opts[:cache] || {}
key = Cache.policy_key(user, subject) key = Cache.policy_key(user, subject)
cache[key] ||= class_for(subject).new(user, subject, opts) cache[key] ||=
if Gitlab.rails5?
# to avoid deadlocks in multi-threaded environment when
# autoloading is enabled, we allow concurrent loads,
# https://gitlab.com/gitlab-org/gitlab-ce/issues/48263
ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
class_for(subject).new(user, subject, opts)
end
else
class_for(subject).new(user, subject, opts)
end
end end
def class_for(subject) def class_for(subject)
......
...@@ -58,7 +58,7 @@ module Gitlab ...@@ -58,7 +58,7 @@ module Gitlab
if raw_credentials.present? if raw_credentials.present?
url.sub!("#{raw_credentials}@", '') url.sub!("#{raw_credentials}@", '')
user, password = raw_credentials.split(':') user, _, password = raw_credentials.partition(':')
@credentials ||= { user: user.presence, password: password.presence } @credentials ||= { user: user.presence, password: password.presence }
end end
......
...@@ -20,16 +20,22 @@ namespace :gettext do ...@@ -20,16 +20,22 @@ namespace :gettext do
end end
task :regenerate do task :regenerate do
pot_file = 'locale/gitlab.pot'
# Remove all translated files, this speeds up finding # Remove all translated files, this speeds up finding
FileUtils.rm Dir['locale/**/gitlab.*'] FileUtils.rm Dir['locale/**/gitlab.*']
# remove the `pot` file to ensure it's completely regenerated # remove the `pot` file to ensure it's completely regenerated
FileUtils.rm_f 'locale/gitlab.pot' FileUtils.rm_f pot_file
Rake::Task['gettext:find'].invoke Rake::Task['gettext:find'].invoke
# leave only the required changes. # leave only the required changes.
`git checkout -- locale/*/gitlab.po` `git checkout -- locale/*/gitlab.po`
# Remove timestamps from the pot file
pot_content = File.read pot_file
pot_content.gsub!(/^"POT?\-(?:Creation|Revision)\-Date\:.*\n/, '')
File.write pot_file, pot_content
puts <<~MSG puts <<~MSG
All done. Please commit the changes to `locale/gitlab.pot`. All done. Please commit the changes to `locale/gitlab.pot`.
......
...@@ -8,8 +8,6 @@ msgid "" ...@@ -8,8 +8,6 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gitlab 1.0.0\n" "Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-07-10 13:57-0500\n"
"PO-Revision-Date: 2018-07-10 13:57-0500\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n" "Language: \n"
......
export default () => new Promise(resolve => requestAnimationFrame(resolve));
...@@ -5,6 +5,7 @@ import { numberToHumanSize } from '~/lib/utils/number_utils'; ...@@ -5,6 +5,7 @@ import { numberToHumanSize } from '~/lib/utils/number_utils';
import '~/lib/utils/datetime_utility'; import '~/lib/utils/datetime_utility';
import Job from '~/job'; import Job from '~/job';
import '~/breakpoints'; import '~/breakpoints';
import waitForPromises from 'spec/helpers/wait_for_promises';
describe('Job', () => { describe('Job', () => {
const JOB_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1`; const JOB_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1`;
...@@ -12,10 +13,6 @@ describe('Job', () => { ...@@ -12,10 +13,6 @@ describe('Job', () => {
let response; let response;
let job; let job;
function waitForPromise() {
return new Promise(resolve => requestAnimationFrame(resolve));
}
preloadFixtures('builds/build-with-artifacts.html.raw'); preloadFixtures('builds/build-with-artifacts.html.raw');
beforeEach(() => { beforeEach(() => {
...@@ -49,7 +46,7 @@ describe('Job', () => { ...@@ -49,7 +46,7 @@ describe('Job', () => {
beforeEach(function (done) { beforeEach(function (done) {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
}); });
...@@ -93,7 +90,7 @@ describe('Job', () => { ...@@ -93,7 +90,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect($('#build-trace .js-build-output').text()).toMatch(/Update/); expect($('#build-trace .js-build-output').text()).toMatch(/Update/);
expect(job.state).toBe('newstate'); expect(job.state).toBe('newstate');
...@@ -107,7 +104,7 @@ describe('Job', () => { ...@@ -107,7 +104,7 @@ describe('Job', () => {
}; };
}) })
.then(() => jasmine.clock().tick(4001)) .then(() => jasmine.clock().tick(4001))
.then(waitForPromise) .then(waitForPromises)
.then(() => { .then(() => {
expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/); expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/);
expect(job.state).toBe('finalstate'); expect(job.state).toBe('finalstate');
...@@ -126,7 +123,7 @@ describe('Job', () => { ...@@ -126,7 +123,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect($('#build-trace .js-build-output').text()).toMatch(/Update/); expect($('#build-trace .js-build-output').text()).toMatch(/Update/);
...@@ -137,7 +134,7 @@ describe('Job', () => { ...@@ -137,7 +134,7 @@ describe('Job', () => {
}; };
}) })
.then(() => jasmine.clock().tick(4001)) .then(() => jasmine.clock().tick(4001))
.then(waitForPromise) .then(waitForPromises)
.then(() => { .then(() => {
expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/); expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/);
expect($('#build-trace .js-build-output').text()).toMatch(/Different/); expect($('#build-trace .js-build-output').text()).toMatch(/Different/);
...@@ -160,7 +157,7 @@ describe('Job', () => { ...@@ -160,7 +157,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect(document.querySelector('.js-truncated-info').classList).not.toContain('hidden'); expect(document.querySelector('.js-truncated-info').classList).not.toContain('hidden');
}) })
...@@ -181,7 +178,7 @@ describe('Job', () => { ...@@ -181,7 +178,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect( expect(
document.querySelector('.js-truncated-info-size').textContent.trim(), document.querySelector('.js-truncated-info-size').textContent.trim(),
...@@ -203,7 +200,7 @@ describe('Job', () => { ...@@ -203,7 +200,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect( expect(
document.querySelector('.js-truncated-info-size').textContent.trim(), document.querySelector('.js-truncated-info-size').textContent.trim(),
...@@ -219,7 +216,7 @@ describe('Job', () => { ...@@ -219,7 +216,7 @@ describe('Job', () => {
}; };
}) })
.then(() => jasmine.clock().tick(4001)) .then(() => jasmine.clock().tick(4001))
.then(waitForPromise) .then(waitForPromises)
.then(() => { .then(() => {
expect( expect(
document.querySelector('.js-truncated-info-size').textContent.trim(), document.querySelector('.js-truncated-info-size').textContent.trim(),
...@@ -258,7 +255,7 @@ describe('Job', () => { ...@@ -258,7 +255,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(() => { .then(() => {
expect(document.querySelector('.js-truncated-info').classList).toContain('hidden'); expect(document.querySelector('.js-truncated-info').classList).toContain('hidden');
}) })
...@@ -280,7 +277,7 @@ describe('Job', () => { ...@@ -280,7 +277,7 @@ describe('Job', () => {
job = new Job(); job = new Job();
waitForPromise() waitForPromises()
.then(done) .then(done)
.catch(done.fail); .catch(done.fail);
}); });
......
This diff is collapsed.
...@@ -92,6 +92,7 @@ describe Gitlab::UrlSanitizer do ...@@ -92,6 +92,7 @@ describe Gitlab::UrlSanitizer do
context 'credentials in URL' do context 'credentials in URL' do
where(:url, :credentials) do where(:url, :credentials) do
'http://foo:bar@example.com' | { user: 'foo', password: 'bar' } 'http://foo:bar@example.com' | { user: 'foo', password: 'bar' }
'http://foo:bar:baz@example.com' | { user: 'foo', password: 'bar:baz' }
'http://:bar@example.com' | { user: nil, password: 'bar' } 'http://:bar@example.com' | { user: nil, password: 'bar' }
'http://foo:@example.com' | { user: 'foo', password: nil } 'http://foo:@example.com' | { user: 'foo', password: nil }
'http://foo@example.com' | { user: 'foo', password: nil } 'http://foo@example.com' | { user: 'foo', password: nil }
......
...@@ -211,6 +211,69 @@ describe API::Runners do ...@@ -211,6 +211,69 @@ describe API::Runners do
describe 'PUT /runners/:id' do describe 'PUT /runners/:id' do
context 'admin user' do context 'admin user' do
# see https://gitlab.com/gitlab-org/gitlab-ce/issues/48625
context 'single parameter update' do
it 'runner description' do
description = shared_runner.description
update_runner(shared_runner.id, admin, description: "#{description}_updated")
expect(response).to have_gitlab_http_status(200)
expect(shared_runner.reload.description).to eq("#{description}_updated")
end
it 'runner active state' do
active = shared_runner.active
update_runner(shared_runner.id, admin, active: !active)
expect(response).to have_gitlab_http_status(200)
expect(shared_runner.reload.active).to eq(!active)
end
it 'runner tag list' do
update_runner(shared_runner.id, admin, tag_list: ['ruby2.1', 'pgsql', 'mysql'])
expect(response).to have_gitlab_http_status(200)
expect(shared_runner.reload.tag_list).to include('ruby2.1', 'pgsql', 'mysql')
end
it 'runner untagged flag' do
# Ensure tag list is non-empty before setting untagged to false.
update_runner(shared_runner.id, admin, tag_list: ['ruby2.1', 'pgsql', 'mysql'])
update_runner(shared_runner.id, admin, run_untagged: 'false')
expect(response).to have_gitlab_http_status(200)
expect(shared_runner.reload.run_untagged?).to be(false)
end
it 'runner unlocked flag' do
update_runner(shared_runner.id, admin, locked: 'true')
expect(response).to have_gitlab_http_status(200)
expect(shared_runner.reload.locked?).to be(true)
end
it 'runner access level' do
update_runner(shared_runner.id, admin, access_level: 'ref_protected')
expect(response).to have_gitlab_http_status(200)
expect(shared_runner.reload.ref_protected?).to be_truthy
end
it 'runner maximum timeout' do
update_runner(shared_runner.id, admin, maximum_timeout: 1234)
expect(response).to have_gitlab_http_status(200)
expect(shared_runner.reload.maximum_timeout).to eq(1234)
end
it 'fails with no parameters' do
put api("/runners/#{shared_runner.id}", admin)
shared_runner.reload
expect(response).to have_gitlab_http_status(400)
end
end
context 'when runner is shared' do context 'when runner is shared' do
it 'updates runner' do it 'updates runner' do
description = shared_runner.description description = shared_runner.description
......
...@@ -27,6 +27,12 @@ describe GitGarbageCollectWorker do ...@@ -27,6 +27,12 @@ describe GitGarbageCollectWorker do
subject.perform(project.id, :gc, lease_key, lease_uuid) subject.perform(project.id, :gc, lease_key, lease_uuid)
end end
it 'handles gRPC errors' do
expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:garbage_collect).and_raise(GRPC::NotFound)
expect { subject.perform(project.id, :gc, lease_key, lease_uuid) }.to raise_exception(Gitlab::Git::Repository::NoRepository)
end
end end
context 'with different lease than the active one' do context 'with different lease than the active one' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment