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

Add latest changes from gitlab-org/gitlab@master

parent 74a2d57b
No related branches found
No related tags found
No related merge requests found
Showing
with 316 additions and 64 deletions
Loading
Loading
@@ -20696,6 +20696,54 @@
},
"defaultValue": null
},
{
"name": "title",
"description": "Title of the issue",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "description",
"description": "Description of the issue",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "dueDate",
"description": "Due date of the issue",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Time",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "confidential",
"description": "Indicates the issue is confidential",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "healthStatus",
"description": "The desired health status",
Loading
Loading
Loading
Loading
@@ -21,6 +21,7 @@ There are many places where file uploading is used, according to contexts:
- CI Artifacts (archive, metadata, trace)
- LFS Objects
- Merge request diffs
- Design Management design thumbnails (EE)
 
## Disk storage
 
Loading
Loading
@@ -37,6 +38,7 @@ they are still not 100% standardized. You can see them below:
| Project avatars | yes | uploads/-/system/project/avatar/:id/:filename | `AvatarUploader` | Project |
| Issues/MR/Notes Markdown attachments | yes | uploads/:project_path_with_namespace/:random_hex/:filename | `FileUploader` | Project |
| Issues/MR/Notes Legacy Markdown attachments | no | uploads/-/system/note/attachment/:id/:filename | `AttachmentUploader` | Note |
| Design Management design thumbnails (EE) | yes | uploads/-/system/design_management/action/image_v432x230/:id/:filename | `DesignManagement::DesignV432x230Uploader` | DesignManagement::Action |
| CI Artifacts (CE) | yes | `shared/artifacts/:disk_hash[0..1]/:disk_hash[2..3]/:disk_hash/:year_:month_:date/:job_id/:job_artifact_id` (:disk_hash is SHA256 digest of project_id) | `JobArtifactUploader` | Ci::JobArtifact |
| LFS Objects (CE) | yes | shared/lfs-objects/:hex/:hex/:object_hash | `LfsObjectUploader` | LfsObject |
| External merge request diffs | yes | shared/external-diffs/merge_request_diffs/mr-:parent_id/diff-:id | `ExternalDiffUploader` | MergeRequestDiff |
Loading
Loading
Loading
Loading
@@ -9,7 +9,6 @@ module Gitlab
@time_left = time_left
end
 
# rubocop: disable CodeReuse/ActiveRecord
def objects_missing?
return false unless @newrev && @project.lfs_enabled?
 
Loading
Loading
@@ -19,12 +18,11 @@ module Gitlab
return false unless new_lfs_pointers.present?
 
existing_count = @project.all_lfs_objects
.where(oid: new_lfs_pointers.map(&:lfs_oid))
.for_oids(new_lfs_pointers.map(&:lfs_oid))
.count
 
existing_count != new_lfs_pointers.count
end
# rubocop: enable CodeReuse/ActiveRecord
end
end
end
Loading
Loading
@@ -235,11 +235,17 @@ module Gitlab
# PostgreSQL constraint names have a limit of 63 bytes. The logic used
# here is based on Rails' foreign_key_name() method, which unfortunately
# is private so we can't rely on it directly.
def concurrent_foreign_key_name(table, column)
#
# prefix:
# - The default prefix is `fk_` for backward compatibility with the existing
# concurrent foreign key helpers.
# - For standard rails foreign keys the prefix is `fk_rails_`
#
def concurrent_foreign_key_name(table, column, prefix: 'fk_')
identifier = "#{table}_#{column}_fk"
hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
 
"fk_#{hashed_identifier}"
"#{prefix}#{hashed_identifier}"
end
 
# Long-running migrations may take more than the timeout allowed by
Loading
Loading
# frozen_string_literal: true
 
# The method `filename` must be defined in classes that use this module.
# The method `filename` must be defined in classes that mix in this module.
#
# This module is intended to be used as a helper and not a security gate
# to validate that a file is safe, as it identifies files only by the
Loading
Loading
@@ -35,6 +35,13 @@ module Gitlab
DANGEROUS_VIDEO_EXT = [].freeze # None, yet
DANGEROUS_AUDIO_EXT = [].freeze # None, yet
 
def self.extension_match?(filename, extensions)
return false unless filename.present?
extension = File.extname(filename).delete('.')
extensions.include?(extension.downcase)
end
def image?
extension_match?(SAFE_IMAGE_EXT)
end
Loading
Loading
@@ -74,10 +81,7 @@ module Gitlab
private
 
def extension_match?(extensions)
return false unless filename
extension = File.extname(filename).delete('.')
extensions.include?(extension.downcase)
::Gitlab::FileTypeDetection.extension_match?(filename, extensions)
end
end
end
Loading
Loading
@@ -43,12 +43,11 @@ module Gitlab
relation_name.to_s.constantize
end
 
def initialize(relation_sym:, relation_hash:, members_mapper:, object_builder:, merge_requests_mapping: nil, user:, importable:, excluded_keys: [])
def initialize(relation_sym:, relation_hash:, members_mapper:, object_builder:, user:, importable:, excluded_keys: [])
@relation_name = self.class.overrides[relation_sym]&.to_sym || relation_sym
@relation_hash = relation_hash.except('noteable_id')
@members_mapper = members_mapper
@object_builder = object_builder
@merge_requests_mapping = merge_requests_mapping
@user = user
@importable = importable
@imported_object_retries = 0
Loading
Loading
Loading
Loading
@@ -377,3 +377,6 @@ ee:
- protected_environments:
- :deploy_access_levels
- :service_desk_setting
excluded_attributes:
actions:
- image_v432x230
Loading
Loading
@@ -111,28 +111,6 @@ module Gitlab
@relation_hash['group_id'] = @importable.namespace_id
end
 
# This code is a workaround for broken project exports that don't
# export merge requests with CI pipelines (i.e. exports that were
# generated from
# https://gitlab.com/gitlab-org/gitlab/merge_requests/17844).
# This method can be removed in GitLab 12.6.
def update_merge_request_references
# If a merge request was properly created, we don't need to fix
# up this export.
return if @relation_hash['merge_request']
merge_request_id = @relation_hash['merge_request_id']
return unless merge_request_id
new_merge_request_id = @merge_requests_mapping[merge_request_id]
return unless new_merge_request_id
@relation_hash['merge_request_id'] = new_merge_request_id
parsed_relation_hash['merge_request_id'] = new_merge_request_id
end
def setup_build
@relation_hash.delete('trace') # old export files have trace
@relation_hash.delete('token')
Loading
Loading
@@ -147,8 +125,6 @@ module Gitlab
end
 
def setup_pipeline
update_merge_request_references
@relation_hash.fetch('stages', []).each do |stage|
stage.statuses.each do |status|
status.pipeline = imported_object
Loading
Loading
Loading
Loading
@@ -76,8 +76,6 @@ module Gitlab
import_failure_service.with_retry(action: 'relation_object.save!', relation_key: relation_key, relation_index: relation_index) do
relation_object.save!
end
save_id_mapping(relation_key, data_hash, relation_object)
rescue => e
import_failure_service.log_import_failure(
source: 'process_relation_item!',
Loading
Loading
@@ -90,17 +88,6 @@ module Gitlab
@import_failure_service ||= ImportFailureService.new(@importable)
end
 
# Older, serialized CI pipeline exports may only have a
# merge_request_id and not the full hash of the merge request. To
# import these pipelines, we need to preserve the mapping between
# the old and new the merge request ID.
def save_id_mapping(relation_key, data_hash, relation_object)
return unless importable_class == Project
return unless relation_key == 'merge_requests'
merge_requests_mapping[data_hash['id']] = relation_object.id
end
def relations
@relations ||=
@reader
Loading
Loading
@@ -219,13 +206,8 @@ module Gitlab
importable_class.to_s.downcase.to_sym
end
 
# A Hash of the imported merge request ID -> imported ID.
def merge_requests_mapping
@merge_requests_mapping ||= {}
end
def relation_factory_params(relation_key, data_hash)
base_params = {
{
relation_sym: relation_key.to_sym,
relation_hash: data_hash,
importable: @importable,
Loading
Loading
@@ -234,9 +216,6 @@ module Gitlab
user: @user,
excluded_keys: excluded_keys_for_relation(relation_key)
}
base_params[:merge_requests_mapping] = merge_requests_mapping if importable_class == Project
base_params
end
end
end
Loading
Loading
Loading
Loading
@@ -21,6 +21,10 @@ module Gitlab
prepare_variables(args, logger)
end
 
def self.categories
CATEGORIES
end
def migrate_to_remote_storage
@to_store = ObjectStorage::Store::REMOTE
 
Loading
Loading
@@ -70,3 +74,5 @@ module Gitlab
end
end
end
Gitlab::Uploads::MigrationHelper.prepend_if_ee('EE::Gitlab::Uploads::MigrationHelper')
Loading
Loading
@@ -3,7 +3,7 @@ namespace :gitlab do
namespace :migrate do
desc "GitLab | Uploads | Migrate all uploaded files to object storage"
task all: :environment do
Gitlab::Uploads::MigrationHelper::CATEGORIES.each do |args|
Gitlab::Uploads::MigrationHelper.categories.each do |args|
Rake::Task["gitlab:uploads:migrate"].invoke(*args)
Rake::Task["gitlab:uploads:migrate"].reenable
end
Loading
Loading
@@ -20,7 +20,7 @@ namespace :gitlab do
namespace :migrate_to_local do
desc "GitLab | Uploads | Migrate all uploaded files to local storage"
task all: :environment do
Gitlab::Uploads::MigrationHelper::CATEGORIES.each do |args|
Gitlab::Uploads::MigrationHelper.categories.each do |args|
Rake::Task["gitlab:uploads:migrate_to_local"].invoke(*args)
Rake::Task["gitlab:uploads:migrate_to_local"].reenable
end
Loading
Loading
Loading
Loading
@@ -14075,6 +14075,9 @@ msgstr ""
msgid "Please create a username with only alphanumeric characters."
msgstr ""
 
msgid "Please create an index before enabling indexing"
msgstr ""
msgid "Please enable and migrate to hashed storage to avoid security issues and ensure data integrity. %{migrate_link}"
msgstr ""
 
Loading
Loading
@@ -21876,9 +21879,15 @@ msgstr ""
msgid "Who will be able to see this group?"
msgstr ""
 
msgid "Who will be using GitLab?"
msgstr ""
msgid "Who will be using this GitLab subscription?"
msgstr ""
 
msgid "Who will be using this GitLab trial?"
msgstr ""
msgid "Wiki"
msgstr ""
 
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
describe 'User edits Release', :js do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:release) { create(:release, project: project, name: 'The first release' ) }
let_it_be(:user) { create(:user) }
before do
project.add_developer(user)
gitlab_sign_in(user)
visit edit_project_release_path(project, release)
end
def fill_out_form_and_click(button_to_click)
fill_in 'Release title', with: 'Updated Release title'
fill_in 'Release notes', with: 'Updated Release notes'
click_button button_to_click
wait_for_requests
end
it 'renders the breadcrumbs' do
within('.breadcrumbs') do
expect(page).to have_content("#{project.creator.name} #{project.name} Edit Release")
expect(page).to have_link(project.creator.name, href: user_path(project.creator))
expect(page).to have_link(project.name, href: project_path(project))
expect(page).to have_link('Edit Release', href: edit_project_release_path(project, release))
end
end
it 'renders the edit Release form' do
expect(page).to have_content('Releases are based on Git tags. We recommend naming tags that fit within semantic versioning, for example v1.0, v2.0-pre.')
expect(find_field('Tag name', { disabled: true }).value).to eq(release.tag)
expect(find_field('Release title').value).to eq(release.name)
expect(find_field('Release notes').value).to eq(release.description)
expect(page).to have_button('Save changes')
expect(page).to have_button('Cancel')
end
it 'redirects to the main Releases page without updating the Release when "Cancel" is clicked' do
original_name = release.name
original_description = release.description
fill_out_form_and_click 'Cancel'
expect(current_path).to eq(project_releases_path(project))
release.reload
expect(release.name).to eq(original_name)
expect(release.description).to eq(original_description)
end
it 'updates the Release and redirects to the main Releases page when "Save changes" is clicked' do
fill_out_form_and_click 'Save changes'
expect(current_path).to eq(project_releases_path(project))
release.reload
expect(release.name).to eq('Updated Release title')
expect(release.description).to eq('Updated Release notes')
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Mutations::Issues::Update do
let(:issue) { create(:issue) }
let(:user) { create(:user) }
let(:expected_attributes) do
{
title: 'new title',
description: 'new description',
confidential: true,
due_date: Date.tomorrow
}
end
let(:mutation) { described_class.new(object: nil, context: { current_user: user }) }
let(:mutated_issue) { subject[:issue] }
describe '#resolve' do
let(:mutation_params) do
{
project_path: issue.project.full_path,
iid: issue.iid
}.merge(expected_attributes)
end
subject { mutation.resolve(mutation_params) }
it 'raises an error if the resource is not accessible to the user' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
context 'when the user can update the issue' do
before do
issue.project.add_developer(user)
end
it 'updates issue with correct values' do
subject
expect(issue.reload).to have_attributes(expected_attributes)
end
context 'when iid does not exist' do
it 'raises resource not available error' do
mutation_params[:iid] = 99999
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
end
end
end
Loading
Loading
@@ -2,6 +2,35 @@
require 'spec_helper'
 
describe Gitlab::FileTypeDetection do
describe '.extension_match?' do
let(:extensions) { %w[foo bar] }
it 'returns false when filename is blank' do
expect(described_class.extension_match?(nil, extensions)).to eq(false)
expect(described_class.extension_match?('', extensions)).to eq(false)
end
it 'returns true when filename matches extensions' do
expect(described_class.extension_match?('file.foo', extensions)).to eq(true)
expect(described_class.extension_match?('file.bar', extensions)).to eq(true)
end
it 'returns false when filename does not match extensions' do
expect(described_class.extension_match?('file.baz', extensions)).to eq(false)
end
it 'can match case insensitive filenames' do
expect(described_class.extension_match?('file.FOO', extensions)).to eq(true)
end
it 'can match filenames with periods' do
expect(described_class.extension_match?('my.file.foo', extensions)).to eq(true)
end
it 'can match filenames with directories' do
expect(described_class.extension_match?('my/file.foo', extensions)).to eq(true)
end
end
context 'when class is an uploader' do
let(:uploader) do
example_uploader = Class.new(CarrierWave::Uploader::Base) do
Loading
Loading
Loading
Loading
@@ -567,6 +567,8 @@ designs: *design
actions:
- design
- version
- uploads
- file_uploads
versions: &version
- author
- issue
Loading
Loading
Loading
Loading
@@ -7,7 +7,6 @@ describe Gitlab::ImportExport::BaseRelationFactory do
let(:project) { create(:project) }
let(:members_mapper) { double('members_mapper').as_null_object }
let(:relation_sym) { :project_snippets }
let(:merge_requests_mapping) { {} }
let(:relation_hash) { {} }
let(:excluded_keys) { [] }
 
Loading
Loading
@@ -16,7 +15,6 @@ describe Gitlab::ImportExport::BaseRelationFactory do
relation_hash: relation_hash,
object_builder: Gitlab::ImportExport::GroupProjectObjectBuilder,
members_mapper: members_mapper,
merge_requests_mapping: merge_requests_mapping,
user: user,
importable: project,
excluded_keys: excluded_keys)
Loading
Loading
Loading
Loading
@@ -6,7 +6,6 @@ describe Gitlab::ImportExport::ProjectRelationFactory do
let(:group) { create(:group) }
let(:project) { create(:project, :repository, group: group) }
let(:members_mapper) { double('members_mapper').as_null_object }
let(:merge_requests_mapping) { {} }
let(:user) { create(:admin) }
let(:excluded_keys) { [] }
let(:created_object) do
Loading
Loading
@@ -14,7 +13,6 @@ describe Gitlab::ImportExport::ProjectRelationFactory do
relation_hash: relation_hash,
object_builder: Gitlab::ImportExport::GroupProjectObjectBuilder,
members_mapper: members_mapper,
merge_requests_mapping: merge_requests_mapping,
user: user,
importable: project,
excluded_keys: excluded_keys)
Loading
Loading
Loading
Loading
@@ -769,7 +769,9 @@ DesignManagement::Design:
- project_id
- filename
DesignManagement::Action:
- id
- event
- image_v432x230
DesignManagement::Version:
- id
- created_at
Loading
Loading
# frozen_string_literal: true
require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20200214214934_create_environment_for_self_monitoring_project')
describe CreateEnvironmentForSelfMonitoringProject, :migration do
let(:application_settings_table) { table(:application_settings) }
let(:environments) { table(:environments) }
let(:instance_administrators_group) do
table(:namespaces).create!(
id: 1,
name: 'GitLab Instance Administrators',
path: 'gitlab-instance-administrators-random',
type: 'Group'
)
end
let(:self_monitoring_project) do
table(:projects).create!(
id: 2,
name: 'Self Monitoring',
path: 'self_monitoring',
namespace_id: instance_administrators_group.id
)
end
context 'when the self monitoring project ID is not set' do
it 'does not make changes' do
expect(environments.find_by(project_id: self_monitoring_project.id)).to be_nil
migrate!
expect(environments.find_by(project_id: self_monitoring_project.id)).to be_nil
end
end
context 'when the self monitoring project ID is set' do
before do
application_settings_table.create!(instance_administration_project_id: self_monitoring_project.id)
end
context 'when the environment already exists' do
let!(:environment) do
environments.create!(project_id: self_monitoring_project.id, name: 'production', slug: 'production')
end
it 'does not make changes' do
expect(environments.find_by(project_id: self_monitoring_project.id)).to eq(environment)
migrate!
expect(environments.find_by(project_id: self_monitoring_project.id)).to eq(environment)
end
end
context 'when the environment does not exist' do
it 'creates the environment' do
expect(environments.find_by(project_id: self_monitoring_project.id)).to be_nil
migrate!
expect(environments.find_by(project_id: self_monitoring_project.id)).to be
end
end
end
end
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