Skip to content
Snippets Groups Projects
Commit 538fff82 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 3692e9f8
No related branches found
No related tags found
No related merge requests found
Showing
with 355 additions and 159 deletions
---
title: Check permissions before showing head pipeline blocking merge requests
merge_request:
author:
type: security
# frozen_string_literal: true
class BackfillReleasesTableUpdatedAtAndAddNotNullConstraintsToTimestamps < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
change_column_null(:releases, :created_at, false, Time.zone.now)
update_column_in_batches(:releases, :updated_at, Arel.sql('created_at')) do |table, query|
query.where(table[:updated_at].eq(nil))
end
change_column_null(:releases, :updated_at, false, Time.zone.now)
end
def down
change_column_null(:releases, :updated_at, true)
change_column_null(:releases, :created_at, true)
end
end
Loading
Loading
@@ -3137,8 +3137,8 @@ ActiveRecord::Schema.define(version: 2019_09_27_074328) do
t.string "tag"
t.text "description"
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "description_html"
t.integer "cached_markdown_version"
t.integer "author_id"
Loading
Loading
Loading
Loading
@@ -74,7 +74,7 @@ The following options are available.
| Restrict by branch name | **Starter** 9.3 | Only branch names that match this regular expression are allowed to be pushed. Leave empty to allow any branch name. |
| Restrict by commit author's email | **Starter** 7.10 | Only commit author's email that match this regular expression are allowed to be pushed. Leave empty to allow any email. |
| Prohibited file names | **Starter** 7.10 | Any committed filenames that match this regular expression are not allowed to be pushed. Leave empty to allow any filenames. |
| Maximum file size | **Starter** 7.12 | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. |
| Maximum file size | **Starter** 7.12 | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. Files tracked by Git LFS are exempted. |
 
TIP: **Tip:**
GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in push rules, and you can test them at the [GoLang regex tester](https://regex-golang.appspot.com).
Loading
Loading
Loading
Loading
@@ -4,19 +4,19 @@ module Gitlab
class SnippetSearchResults < SearchResults
include SnippetsHelper
 
attr_reader :limit_snippets
attr_reader :current_user
 
def initialize(limit_snippets, query)
@limit_snippets = limit_snippets
def initialize(current_user, query)
@current_user = current_user
@query = query
end
 
def objects(scope, page = nil)
case scope
when 'snippet_titles'
snippet_titles.page(page).per(per_page)
paginated_objects(snippet_titles, page)
when 'snippet_blobs'
snippet_blobs.page(page).per(per_page)
paginated_objects(snippet_blobs, page)
else
super(scope, nil, false)
end
Loading
Loading
@@ -25,38 +25,47 @@ module Gitlab
def formatted_count(scope)
case scope
when 'snippet_titles'
snippet_titles_count.to_s
formatted_limited_count(limited_snippet_titles_count)
when 'snippet_blobs'
snippet_blobs_count.to_s
formatted_limited_count(limited_snippet_blobs_count)
else
super
end
end
 
def snippet_titles_count
@snippet_titles_count ||= snippet_titles.count
def limited_snippet_titles_count
@limited_snippet_titles_count ||= limited_count(snippet_titles)
end
 
def snippet_blobs_count
@snippet_blobs_count ||= snippet_blobs.count
def limited_snippet_blobs_count
@limited_snippet_blobs_count ||= limited_count(snippet_blobs)
end
 
private
 
# rubocop: disable CodeReuse/ActiveRecord
def snippet_titles
limit_snippets.search(query).order('updated_at DESC').includes(:author)
def snippets
SnippetsFinder.new(current_user)
.execute
.includes(:author)
.reorder(updated_at: :desc)
end
# rubocop: enable CodeReuse/ActiveRecord
 
# rubocop: disable CodeReuse/ActiveRecord
def snippet_titles
snippets.search(query)
end
def snippet_blobs
limit_snippets.search_code(query).order('updated_at DESC').includes(:author)
snippets.search_code(query)
end
# rubocop: enable CodeReuse/ActiveRecord
 
def default_scope
'snippet_blobs'
end
def paginated_objects(relation, page)
relation.page(page).per(per_page)
end
end
end
Loading
Loading
@@ -38,7 +38,7 @@
"@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/preset-env": "^7.6.2",
"@gitlab/svgs": "^1.75.0",
"@gitlab/ui": "5.26.1",
"@gitlab/ui": "5.26.2",
"@gitlab/visual-review-tools": "1.0.3",
"apollo-cache-inmemory": "^1.5.1",
"apollo-client": "^2.5.1",
Loading
Loading
Loading
Loading
@@ -3,7 +3,6 @@
require 'spec_helper'
 
describe 'Import/Export - project import integration test', :js do
include Select2Helper
include GitHelpers
 
let(:user) { create(:user) }
Loading
Loading
@@ -31,7 +30,6 @@ describe 'Import/Export - project import integration test', :js do
it 'user imports an exported project successfully' do
visit new_project_path
 
select2(namespace.id, from: '#project_namespace_id')
fill_in :project_name, with: project_name, visible: true
click_import_project_tab
click_link 'GitLab export'
Loading
Loading
@@ -78,7 +76,6 @@ describe 'Import/Export - project import integration test', :js do
 
visit new_project_path
 
select2(user.namespace.id, from: '#project_namespace_id')
fill_in :project_name, with: project.name, visible: true
click_import_project_tab
click_link 'GitLab export'
Loading
Loading
Loading
Loading
@@ -42,6 +42,7 @@ describe('Issue card component', () => {
assignees: [],
reference_path: '#1',
real_path: '/test/1',
weight: 1,
});
 
component = new Vue({
Loading
Loading
@@ -287,8 +288,17 @@ describe('Issue card component', () => {
});
 
describe('weights', () => {
it('not shows weight component', () => {
expect(component.$el.querySelector('.board-card-weight')).toBeNull();
it('shows weight component is greater than 0', () => {
expect(component.$el.querySelector('.board-card-weight')).not.toBeNull();
});
it('shows weight component when weight is 0', done => {
component.issue.weight = 0;
Vue.nextTick(() => {
expect(component.$el.querySelector('.board-card-weight')).not.toBeNull();
done();
});
});
});
});
Loading
Loading
@@ -6,18 +6,17 @@ describe Gitlab::SnippetSearchResults do
include SearchHelpers
 
let!(:snippet) { create(:snippet, content: 'foo', file_name: 'foo') }
let(:results) { described_class.new(Snippet.all, 'foo') }
let(:results) { described_class.new(snippet.author, 'foo') }
 
describe '#snippet_titles_count' do
it 'returns the amount of matched snippet titles' do
expect(results.snippet_titles_count).to eq(1)
expect(results.limited_snippet_titles_count).to eq(1)
end
end
 
describe '#snippet_blobs_count' do
it 'returns the amount of matched snippet blobs' do
expect(results.snippet_blobs_count).to eq(1)
expect(results.limited_snippet_blobs_count).to eq(1)
end
end
 
Loading
Loading
@@ -25,10 +24,10 @@ describe Gitlab::SnippetSearchResults do
using RSpec::Parameterized::TableSyntax
 
where(:scope, :count_method, :expected) do
'snippet_titles' | :snippet_titles_count | '1234'
'snippet_blobs' | :snippet_blobs_count | '1234'
'projects' | :limited_projects_count | max_limited_count
'unknown' | nil | nil
'snippet_titles' | :limited_snippet_titles_count | max_limited_count
'snippet_blobs' | :limited_snippet_blobs_count | max_limited_count
'projects' | :limited_projects_count | max_limited_count
'unknown' | nil | nil
end
 
with_them do
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20190920194925_backfill_releases_table_updated_at_and_add_not_null_constraints_to_timestamps.rb')
describe BackfillReleasesTableUpdatedAtAndAddNotNullConstraintsToTimestamps, :migration do
let(:releases) { table(:releases) }
let(:namespaces) { table(:namespaces) }
let(:projects) { table(:projects) }
subject(:migration) { described_class.new }
it 'fills null updated_at rows with the value of created_at' do
created_at_a = Time.zone.parse('2014-03-11T04:30:00Z')
created_at_b = Time.zone.parse('2019-09-10T12:00:00Z')
namespace = namespaces.create(name: 'foo', path: 'foo')
project = projects.create!(namespace_id: namespace.id)
release_a = releases.create!(project_id: project.id,
released_at: Time.zone.parse('2014-12-10T06:00:00Z'),
created_at: created_at_a)
release_b = releases.create!(project_id: project.id,
released_at: Time.zone.parse('2019-09-11T06:00:00Z'),
created_at: created_at_b)
release_a.update!(updated_at: nil)
release_b.update!(updated_at: nil)
disable_migrations_output { migrate! }
release_a.reload
release_b.reload
expect(release_a.updated_at).to eq(created_at_a)
expect(release_b.updated_at).to eq(created_at_b)
end
it 'does not change updated_at columns with a value' do
created_at_a = Time.zone.parse('2014-03-11T04:30:00Z')
updated_at_a = Time.zone.parse('2015-01-16T10:00:00Z')
created_at_b = Time.zone.parse('2019-09-10T12:00:00Z')
namespace = namespaces.create(name: 'foo', path: 'foo')
project = projects.create!(namespace_id: namespace.id)
release_a = releases.create!(project_id: project.id,
released_at: Time.zone.parse('2014-12-10T06:00:00Z'),
created_at: created_at_a,
updated_at: updated_at_a)
release_b = releases.create!(project_id: project.id,
released_at: Time.zone.parse('2019-09-11T06:00:00Z'),
created_at: created_at_b)
release_b.update!(updated_at: nil)
disable_migrations_output { migrate! }
release_a.reload
release_b.reload
expect(release_a.updated_at).to eq(updated_at_a)
expect(release_b.updated_at).to eq(created_at_b)
end
end
Loading
Loading
@@ -1966,40 +1966,57 @@ describe Ci::Pipeline, :mailer do
end
end
 
describe '.latest_status_per_commit' do
describe '.latest_pipeline_per_commit' do
let(:project) { create(:project) }
 
before do
pairs = [
%w[success ref1 123],
%w[manual master 123],
%w[failed ref 456]
]
pairs.each do |(status, ref, sha)|
create(
:ci_empty_pipeline,
status: status,
ref: ref,
sha: sha,
project: project
)
end
let!(:commit_123_ref_master) do
create(
:ci_empty_pipeline,
status: 'success',
ref: 'master',
sha: '123',
project: project
)
end
let!(:commit_123_ref_develop) do
create(
:ci_empty_pipeline,
status: 'success',
ref: 'develop',
sha: '123',
project: project
)
end
let!(:commit_456_ref_test) do
create(
:ci_empty_pipeline,
status: 'success',
ref: 'test',
sha: '456',
project: project
)
end
 
context 'without a ref' do
it 'returns a Hash containing the latest status per commit for all refs' do
expect(described_class.latest_status_per_commit(%w[123 456]))
.to eq({ '123' => 'manual', '456' => 'failed' })
it 'returns a Hash containing the latest pipeline per commit for all refs' do
result = described_class.latest_pipeline_per_commit(%w[123 456])
expect(result).to match(
'123' => commit_123_ref_develop,
'456' => commit_456_ref_test
)
end
 
it 'only includes the status of the given commit SHAs' do
expect(described_class.latest_status_per_commit(%w[123]))
.to eq({ '123' => 'manual' })
it 'only includes the latest pipeline of the given commit SHAs' do
result = described_class.latest_pipeline_per_commit(%w[123])
expect(result).to match(
'123' => commit_123_ref_develop
)
end
 
context 'when there are two pipelines for a ref and SHA' do
it 'returns the status of the latest pipeline' do
let!(:commit_123_ref_master_latest) do
create(
:ci_empty_pipeline,
status: 'failed',
Loading
Loading
@@ -2007,17 +2024,25 @@ describe Ci::Pipeline, :mailer do
sha: '123',
project: project
)
end
it 'returns the latest pipeline' do
result = described_class.latest_pipeline_per_commit(%w[123])
 
expect(described_class.latest_status_per_commit(%w[123]))
.to eq({ '123' => 'failed' })
expect(result).to match(
'123' => commit_123_ref_master_latest
)
end
end
end
 
context 'with a ref' do
it 'only includes the pipelines for the given ref' do
expect(described_class.latest_status_per_commit(%w[123 456], 'master'))
.to eq({ '123' => 'manual' })
result = described_class.latest_pipeline_per_commit(%w[123 456], 'master')
expect(result).to match(
'123' => commit_123_ref_master
)
end
end
end
Loading
Loading
Loading
Loading
@@ -51,6 +51,30 @@ describe CommitCollection do
end
end
 
describe '#with_latest_pipeline' do
let!(:pipeline) do
create(
:ci_empty_pipeline,
ref: 'master',
sha: commit.id,
status: 'success',
project: project
)
end
let(:collection) { described_class.new(project, [commit]) }
it 'sets the latest pipeline for every commit so no additional queries are necessary' do
commits = collection.with_latest_pipeline('master')
recorder = ActiveRecord::QueryRecorder.new do
expect(commits.map { |c| c.latest_pipeline('master') })
.to eq([pipeline])
end
expect(recorder.count).to be_zero
end
end
describe 'enrichment methods' do
let(:gitaly_commit) { commit }
let(:hash_commit) { Commit.from_hash(gitaly_commit.to_hash, project) }
Loading
Loading
@@ -128,27 +152,6 @@ describe CommitCollection do
end
end
 
describe '#with_pipeline_status' do
it 'sets the pipeline status for every commit so no additional queries are necessary' do
create(
:ci_empty_pipeline,
ref: 'master',
sha: commit.id,
status: 'success',
project: project
)
collection = described_class.new(project, [commit])
collection.with_pipeline_status
recorder = ActiveRecord::QueryRecorder.new do
expect(commit.status).to eq('success')
end
expect(recorder.count).to be_zero
end
end
describe '#respond_to_missing?' do
it 'returns true when the underlying Array responds to the message' do
collection = described_class.new(project, [])
Loading
Loading
Loading
Loading
@@ -462,78 +462,6 @@ eos
end
end
 
describe '#last_pipeline' do
let!(:first_pipeline) do
create(:ci_empty_pipeline,
project: project,
sha: commit.sha,
status: 'success')
end
let!(:second_pipeline) do
create(:ci_empty_pipeline,
project: project,
sha: commit.sha,
status: 'success')
end
it 'returns last pipeline' do
expect(commit.last_pipeline).to eq second_pipeline
end
end
describe '#status' do
context 'without ref argument' do
before do
%w[success failed created pending].each do |status|
create(:ci_empty_pipeline,
project: project,
sha: commit.sha,
status: status)
end
end
it 'gives compound status from latest pipelines' do
expect(commit.status).to eq(Ci::Pipeline.latest_status)
expect(commit.status).to eq('pending')
end
end
context 'when a particular ref is specified' do
let!(:pipeline_from_master) do
create(:ci_empty_pipeline,
project: project,
sha: commit.sha,
ref: 'master',
status: 'failed')
end
let!(:pipeline_from_fix) do
create(:ci_empty_pipeline,
project: project,
sha: commit.sha,
ref: 'fix',
status: 'success')
end
it 'gives pipelines from a particular branch' do
expect(commit.status('master')).to eq(pipeline_from_master.status)
expect(commit.status('fix')).to eq(pipeline_from_fix.status)
end
it 'gives compound status from latest pipelines if ref is nil' do
expect(commit.status(nil)).to eq(pipeline_from_fix.status)
end
end
end
describe '#set_status_for_ref' do
it 'sets the status for a given reference' do
commit.set_status_for_ref('master', 'failed')
expect(commit.status('master')).to eq('failed')
end
end
describe '#participants' do
let(:user1) { build(:user) }
let(:user2) { build(:user) }
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe CommitWithPipeline do
let(:project) { create(:project, :public, :repository) }
let(:commit) { described_class.new(project.commit) }
describe '#last_pipeline' do
let!(:first_pipeline) do
create(:ci_empty_pipeline,
project: project,
sha: commit.sha,
status: 'success')
end
let!(:second_pipeline) do
create(:ci_empty_pipeline,
project: project,
sha: commit.sha,
status: 'success')
end
it 'returns last pipeline' do
expect(commit.last_pipeline).to eq second_pipeline
end
end
describe '#latest_pipeline' do
let(:pipeline) { double }
shared_examples_for 'fetching latest pipeline' do |ref|
it 'returns the latest pipeline for the project' do
expect(commit)
.to receive(:latest_pipeline_for_project)
.with(ref, project)
.and_return(pipeline)
expect(result).to eq(pipeline)
end
it "returns the memoized pipeline for the key of #{ref}" do
commit.set_latest_pipeline_for_ref(ref, pipeline)
expect(commit)
.not_to receive(:latest_pipeline_for_project)
expect(result).to eq(pipeline)
end
end
context 'without ref argument' do
let(:result) { commit.latest_pipeline }
it_behaves_like 'fetching latest pipeline', nil
end
context 'when a particular ref is specified' do
let(:result) { commit.latest_pipeline('master') }
it_behaves_like 'fetching latest pipeline', 'master'
end
end
describe '#latest_pipeline_for_project' do
let(:project_pipelines) { double }
let(:pipeline_project) { double }
let(:pipeline) { double }
let(:ref) { 'master' }
let(:result) { commit.latest_pipeline_for_project(ref, pipeline_project) }
before do
allow(pipeline_project).to receive(:ci_pipelines).and_return(project_pipelines)
end
it 'returns the latest pipeline of the commit for the given ref and project' do
expect(project_pipelines)
.to receive(:latest_pipeline_per_commit)
.with(commit.id, ref)
.and_return(commit.id => pipeline)
expect(result).to eq(pipeline)
end
end
describe '#set_latest_pipeline_for_ref' do
let(:pipeline) { double }
it 'sets the latest pipeline for a given reference' do
commit.set_latest_pipeline_for_ref('master', pipeline)
expect(commit.latest_pipeline('master')).to eq(pipeline)
end
end
describe "#status" do
it 'returns the status of the latest pipeline for the given ref' do
expect(commit)
.to receive(:latest_pipeline)
.with('master')
.and_return(double(status: 'success'))
expect(commit.status('master')).to eq('success')
end
it 'returns nil when latest pipeline is not present for the given ref' do
expect(commit)
.to receive(:latest_pipeline)
.with('master')
.and_return(nil)
expect(commit.status('master')).to eq(nil)
end
it 'returns the status of the latest pipeline when no ref is given' do
expect(commit)
.to receive(:latest_pipeline)
.with(nil)
.and_return(double(status: 'success'))
expect(commit.status).to eq('success')
end
end
end
Loading
Loading
@@ -17,15 +17,19 @@ describe CommitPresenter do
end
 
it 'returns commit status for ref' do
expect(commit).to receive(:status).with('ref').and_return('test')
pipeline = double
status = double
 
expect(subject).to eq('test')
expect(commit).to receive(:latest_pipeline).with('ref').and_return(pipeline)
expect(pipeline).to receive(:detailed_status).with(user).and_return(status)
expect(subject).to eq(status)
end
end
 
context 'when user can not read_commit_status' do
it 'is false' do
is_expected.to eq(false)
it 'is nil' do
is_expected.to eq(nil)
end
end
end
Loading
Loading
Loading
Loading
@@ -24,7 +24,7 @@ module Select2Helper
 
selector = options.fetch(:from)
 
first(selector, visible: false)
ensure_select2_loaded(selector)
 
if options[:multiple]
execute_script("$('#{selector}').select2('val', ['#{value}']).trigger('change');")
Loading
Loading
@@ -34,14 +34,24 @@ module Select2Helper
end
 
def open_select2(selector)
ensure_select2_loaded(selector)
execute_script("$('#{selector}').select2('open');")
end
 
def close_select2(selector)
ensure_select2_loaded(selector)
execute_script("$('#{selector}').select2('close');")
end
 
def scroll_select2_to_bottom(selector)
evaluate_script "$('#{selector}').scrollTop($('#{selector}')[0].scrollHeight); $('#{selector}');"
end
private
def ensure_select2_loaded(selector)
first(selector, visible: :all).sibling('.select2-container')
end
end
# frozen_string_literal: true
module StrategyHelpers
include Rack::Test::Methods
include ActionDispatch::Assertions::ResponseAssertions
Loading
Loading
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
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