Commit 2a65a97e authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 2d96e61c
...@@ -42,7 +42,6 @@ export default { ...@@ -42,7 +42,6 @@ export default {
<template> <template>
<li class="linked-pipeline build"> <li class="linked-pipeline build">
<div class="curve"></div>
<gl-button <gl-button
:id="buttonId" :id="buttonId"
v-gl-tooltip v-gl-tooltip
......
...@@ -9,11 +9,11 @@ module ClustersHelper ...@@ -9,11 +9,11 @@ module ClustersHelper
def create_new_cluster_label(provider: nil) def create_new_cluster_label(provider: nil)
case provider case provider
when 'aws' when 'aws'
s_('ClusterIntegration|Create new Cluster on EKS') s_('ClusterIntegration|Create new cluster on EKS')
when 'gcp' when 'gcp'
s_('ClusterIntegration|Create new Cluster on GKE') s_('ClusterIntegration|Create new cluster on GKE')
else else
s_('ClusterIntegration|Create new Cluster') s_('ClusterIntegration|Create new cluster')
end end
end end
......
...@@ -205,4 +205,4 @@ module TodosHelper ...@@ -205,4 +205,4 @@ module TodosHelper
end end
end end
TodosHelper.prepend_if_ee('EE::NotesHelper'); TodosHelper.prepend_if_ee('EE::TodosHelper') # rubocop: disable Style/Semicolon TodosHelper.prepend_if_ee('EE::TodosHelper')
...@@ -762,6 +762,10 @@ module Ci ...@@ -762,6 +762,10 @@ module Ci
Gitlab::Ci::Build::Credentials::Factory.new(self).create! Gitlab::Ci::Build::Credentials::Factory.new(self).create!
end end
def all_dependencies
(dependencies + cross_dependencies).uniq
end
def dependencies def dependencies
return [] if empty_dependencies? return [] if empty_dependencies?
...@@ -782,6 +786,10 @@ module Ci ...@@ -782,6 +786,10 @@ module Ci
depended_jobs depended_jobs
end end
def cross_dependencies
[]
end
def empty_dependencies? def empty_dependencies?
options[:dependencies]&.empty? options[:dependencies]&.empty?
end end
......
...@@ -47,6 +47,12 @@ class CommitStatus < ApplicationRecord ...@@ -47,6 +47,12 @@ class CommitStatus < ApplicationRecord
scope :after_stage, -> (index) { where('stage_idx > ?', index) } scope :after_stage, -> (index) { where('stage_idx > ?', index) }
scope :processables, -> { where(type: %w[Ci::Build Ci::Bridge]) } scope :processables, -> { where(type: %w[Ci::Build Ci::Bridge]) }
scope :for_ids, -> (ids) { where(id: ids) } scope :for_ids, -> (ids) { where(id: ids) }
scope :for_ref, -> (ref) { where(ref: ref) }
scope :by_name, -> (name) { where(name: name) }
scope :for_project_paths, -> (paths) do
where(project: Project.where_full_path_in(Array(paths)))
end
scope :with_preloads, -> do scope :with_preloads, -> do
preload(:project, :user) preload(:project, :user)
......
---
title: Harmonize capitalization on cluster UI
merge_request: 21878
author: Evan Read
type: other
---
title: Strong validate import export references
merge_request: 19682
author:
type: added
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
# #
# rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/AbcSize
def instrument_classes(instrumentation) def instrument_classes(instrumentation)
return if ENV['STATIC_VERIFICATION']
instrumentation.instrument_instance_methods(Gitlab::Shell) instrumentation.instrument_instance_methods(Gitlab::Shell)
instrumentation.instrument_methods(Gitlab::Git) instrumentation.instrument_methods(Gitlab::Git)
......
# frozen_string_literal: true
class AddIndexForCrossProjectsDependenciesToCiBuilds < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :ci_builds, [:project_id, :name, :ref],
where: "type = 'Ci::Build' AND status = 'success' AND (retried = FALSE OR retried IS NULL)"
end
def down
remove_concurrent_index :ci_builds, [:project_id, :name, :ref],
where: "type = 'Ci::Build' AND status = 'success' AND (retried = FALSE OR retried IS NULL)"
end
end
...@@ -693,6 +693,7 @@ ActiveRecord::Schema.define(version: 2019_12_16_183532) do ...@@ -693,6 +693,7 @@ ActiveRecord::Schema.define(version: 2019_12_16_183532) do
t.index ["commit_id", "type", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_ref" t.index ["commit_id", "type", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_ref"
t.index ["name"], name: "index_ci_builds_on_name_for_security_products_values", where: "((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text]))" t.index ["name"], name: "index_ci_builds_on_name_for_security_products_values", where: "((name)::text = ANY (ARRAY[('container_scanning'::character varying)::text, ('dast'::character varying)::text, ('dependency_scanning'::character varying)::text, ('license_management'::character varying)::text, ('sast'::character varying)::text]))"
t.index ["project_id", "id"], name: "index_ci_builds_on_project_id_and_id" t.index ["project_id", "id"], name: "index_ci_builds_on_project_id_and_id"
t.index ["project_id", "name", "ref"], name: "index_ci_builds_on_project_id_and_name_and_ref", where: "(((type)::text = 'Ci::Build'::text) AND ((status)::text = 'success'::text) AND ((retried = false) OR (retried IS NULL)))"
t.index ["project_id", "status"], name: "index_ci_builds_project_id_and_status_for_live_jobs_partial2", where: "(((type)::text = 'Ci::Build'::text) AND ((status)::text = ANY (ARRAY[('running'::character varying)::text, ('pending'::character varying)::text, ('created'::character varying)::text])))" t.index ["project_id", "status"], name: "index_ci_builds_project_id_and_status_for_live_jobs_partial2", where: "(((type)::text = 'Ci::Build'::text) AND ((status)::text = ANY (ARRAY[('running'::character varying)::text, ('pending'::character varying)::text, ('created'::character varying)::text])))"
t.index ["project_id"], name: "index_ci_builds_on_project_id_for_successfull_pages_deploy", where: "(((type)::text = 'GenericCommitStatus'::text) AND ((stage)::text = 'deploy'::text) AND ((name)::text = 'pages:deploy'::text) AND ((status)::text = 'success'::text))" t.index ["project_id"], name: "index_ci_builds_on_project_id_for_successfull_pages_deploy", where: "(((type)::text = 'GenericCommitStatus'::text) AND ((stage)::text = 'deploy'::text) AND ((name)::text = 'pages:deploy'::text) AND ((status)::text = 'success'::text))"
t.index ["protected"], name: "index_ci_builds_on_protected" t.index ["protected"], name: "index_ci_builds_on_protected"
......
...@@ -53,7 +53,7 @@ Refer to <https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/over ...@@ -53,7 +53,7 @@ Refer to <https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/over
- This utility can help you check if one method would override - This utility can help you check if one method would override
another or not. It is the same concept as Java's `@Override` annotation another or not. It is the same concept as Java's `@Override` annotation
or Scala's `override` keyword. However, you should only do this check when or Scala's `override` keyword. However, we only run this check when
`ENV['STATIC_VERIFICATION']` is set to avoid production runtime overhead. `ENV['STATIC_VERIFICATION']` is set to avoid production runtime overhead.
This is useful for checking: This is useful for checking:
...@@ -94,6 +94,15 @@ Refer to <https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/over ...@@ -94,6 +94,15 @@ Refer to <https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/over
end end
``` ```
Note that the check will only happen when either:
- The overriding method is defined in a class, or:
- The overriding method is defined in a module, and it's prepended to
a class or a module.
Because only a class or prepended module can actually override a method.
Including or extending a module into another cannot override anything.
## `StrongMemoize` ## `StrongMemoize`
Refer to <https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/strong_memoize.rb>: Refer to <https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/utils/strong_memoize.rb>:
......
...@@ -1672,7 +1672,7 @@ module API ...@@ -1672,7 +1672,7 @@ module API
expose :artifacts, using: Artifacts expose :artifacts, using: Artifacts
expose :cache, using: Cache expose :cache, using: Cache
expose :credentials, using: Credentials expose :credentials, using: Credentials
expose :dependencies, using: Dependency expose :all_dependencies, as: :dependencies, using: Dependency
expose :features expose :features
end end
end end
......
...@@ -134,7 +134,7 @@ module Gitlab ...@@ -134,7 +134,7 @@ module Gitlab
entry :needs, Entry::Needs, entry :needs, Entry::Needs,
description: 'Needs configuration for this job.', description: 'Needs configuration for this job.',
metadata: { allowed_needs: %i[job] }, metadata: { allowed_needs: %i[job cross_dependency] },
inherit: false inherit: false
entry :variables, Entry::Variables, entry :variables, Entry::Variables,
......
...@@ -6,7 +6,9 @@ module Gitlab ...@@ -6,7 +6,9 @@ module Gitlab
module Entry module Entry
class Need < ::Gitlab::Config::Entry::Simplifiable class Need < ::Gitlab::Config::Entry::Simplifiable
strategy :JobString, if: -> (config) { config.is_a?(String) } strategy :JobString, if: -> (config) { config.is_a?(String) }
strategy :JobHash, if: -> (config) { config.is_a?(Hash) && config.key?(:job) }
strategy :JobHash,
if: -> (config) { config.is_a?(Hash) && config.key?(:job) && !(config.key?(:project) || config.key?(:ref)) }
class JobString < ::Gitlab::Config::Entry::Node class JobString < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Validatable include ::Gitlab::Config::Entry::Validatable
......
...@@ -53,3 +53,5 @@ module Gitlab ...@@ -53,3 +53,5 @@ module Gitlab
end end
end end
end end
::Gitlab::Ci::Config::Entry::Needs.prepend_if_ee('::EE::Gitlab::Ci::Config::Entry::Needs')
...@@ -69,6 +69,7 @@ module Gitlab ...@@ -69,6 +69,7 @@ module Gitlab
services: job[:services], services: job[:services],
artifacts: job[:artifacts], artifacts: job[:artifacts],
dependencies: job[:dependencies], dependencies: job[:dependencies],
cross_dependencies: job.dig(:needs, :cross_dependency),
job_timeout: job[:timeout], job_timeout: job[:timeout],
before_script: job[:before_script], before_script: job[:before_script],
script: job[:script], script: job[:script],
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module Gitlab module Gitlab
module ImportExport module ImportExport
class AttributeCleaner class AttributeCleaner
ALLOWED_REFERENCES = RelationFactory::PROJECT_REFERENCES + RelationFactory::USER_REFERENCES + %w[group_id commit_id] ALLOWED_REFERENCES = RelationFactory::PROJECT_REFERENCES + RelationFactory::USER_REFERENCES + %w[group_id commit_id discussion_id]
PROHIBITED_REFERENCES = Regexp.union(/\Acached_markdown_version\Z/, /_id\Z/, /_ids\Z/, /_html\Z/).freeze PROHIBITED_REFERENCES = Regexp.union(/\Acached_markdown_version\Z/, /_id\Z/, /_ids\Z/, /_html\Z/).freeze
def self.clean(*args) def self.clean(*args)
......
...@@ -172,24 +172,36 @@ excluded_attributes: ...@@ -172,24 +172,36 @@ excluded_attributes:
- :external_diff - :external_diff
- :stored_externally - :stored_externally
- :external_diff_store - :external_diff_store
- :merge_request_id
merge_request_diff_commits:
- :merge_request_diff_id
merge_request_diff_files: merge_request_diff_files:
- :diff - :diff
- :external_diff_offset - :external_diff_offset
- :external_diff_size - :external_diff_size
- :merge_request_diff_id
issues: issues:
- :milestone_id - :milestone_id
- :moved_to_id
- :state_id
- :duplicated_to_id
- :promoted_to_epic_id
merge_request: merge_request:
- :milestone_id - :milestone_id
- :ref_fetched - :ref_fetched
- :merge_jid - :merge_jid
- :rebase_jid - :rebase_jid
- :latest_merge_request_diff_id - :latest_merge_request_diff_id
- :head_pipeline_id
- :state_id
merge_requests: merge_requests:
- :milestone_id - :milestone_id
- :ref_fetched - :ref_fetched
- :merge_jid - :merge_jid
- :rebase_jid - :rebase_jid
- :latest_merge_request_diff_id - :latest_merge_request_diff_id
- :head_pipeline_id
- :state_id
award_emoji: award_emoji:
- :awardable_id - :awardable_id
statuses: statuses:
...@@ -203,6 +215,16 @@ excluded_attributes: ...@@ -203,6 +215,16 @@ excluded_attributes:
- :artifacts_metadata_store - :artifacts_metadata_store
- :artifacts_size - :artifacts_size
- :commands - :commands
- :runner_id
- :trigger_request_id
- :erased_by_id
- :auto_canceled_by_id
- :stage_id
- :upstream_pipeline_id
- :resource_group_id
- :waiting_for_resource_at
sentry_issue:
- :issue_id
push_event_payload: push_event_payload:
- :event_id - :event_id
project_badges: project_badges:
...@@ -211,6 +233,9 @@ excluded_attributes: ...@@ -211,6 +233,9 @@ excluded_attributes:
- :reference - :reference
- :reference_html - :reference_html
- :epic_id - :epic_id
- :issue_id
- :merge_request_id
- :label_id
runners: runners:
- :token - :token
- :token_encrypted - :token_encrypted
...@@ -222,7 +247,64 @@ excluded_attributes: ...@@ -222,7 +247,64 @@ excluded_attributes:
- :enabled - :enabled
service_desk_setting: service_desk_setting:
- :outgoing_name - :outgoing_name
priorities:
- :label_id
events:
- :target_id
timelogs:
- :issue_id
- :merge_request_id
notes:
- :noteable_id
- :review_id
label_links:
- :label_id
- :target_id
issue_assignees:
- :issue_id
zoom_meetings:
- :issue_id
design:
- :issue_id
designs:
- :issue_id
design_versions:
- :issue_id
actions:
- :design_id
- :version_id
links:
- :release_id
project_members:
- :source_id
metrics:
- :merge_request_id
- :pipeline_id
suggestions:
- :note_id
ci_pipelines:
- :auto_canceled_by_id
- :pipeline_schedule_id
- :merge_request_id
- :external_pull_request_id
stages:
- :pipeline_id
merge_access_levels:
- :protected_branch_id
push_access_levels:
- :protected_branch_id
unprotect_access_levels:
- :protected_branch_id
create_access_levels:
- :protected_tag_id
deploy_access_levels:
- :protected_environment_id
boards:
- :milestone_id
lists:
- :board_id
- :label_id
- :milestone_id
methods: methods:
notes: notes:
- :type - :type
......
...@@ -146,7 +146,8 @@ module Gitlab ...@@ -146,7 +146,8 @@ module Gitlab
def prepended(base = nil) def prepended(base = nil)
super super
queue_verification(base) if base # prepend can override methods, thus we need to verify it like classes
queue_verification(base, verify: true) if base
end end
def extended(mod = nil) def extended(mod = nil)
...@@ -155,11 +156,15 @@ module Gitlab ...@@ -155,11 +156,15 @@ module Gitlab
queue_verification(mod.singleton_class) if mod queue_verification(mod.singleton_class) if mod
end end
def queue_verification(base) def queue_verification(base, verify: false)
return unless ENV['STATIC_VERIFICATION'] return unless ENV['STATIC_VERIFICATION']
if base.is_a?(Class) # We could check for Class in `override` # We could check for Class in `override`
# This could be `nil` if `override` was never called # This could be `nil` if `override` was never called.
# We also force verification for prepend because it can also override
# a method like a class, but not the cases for include or extend.
# This includes Rails helpers but not limited to.
if base.is_a?(Class) || verify
Override.extensions[self]&.add_class(base) Override.extensions[self]&.add_class(base)
end end
end end
......
...@@ -3790,13 +3790,13 @@ msgstr "" ...@@ -3790,13 +3790,13 @@ msgstr ""
msgid "ClusterIntegration|Create cluster on" msgid "ClusterIntegration|Create cluster on"
msgstr "" msgstr ""
msgid "ClusterIntegration|Create new Cluster" msgid "ClusterIntegration|Create new cluster"
msgstr "" msgstr ""
msgid "ClusterIntegration|Create new Cluster on EKS" msgid "ClusterIntegration|Create new cluster on EKS"
msgstr "" msgstr ""
msgid "ClusterIntegration|Create new Cluster on GKE" msgid "ClusterIntegration|Create new cluster on GKE"
msgstr "" msgstr ""
msgid "ClusterIntegration|Creating Kubernetes cluster" msgid "ClusterIntegration|Creating Kubernetes cluster"
......
...@@ -8,17 +8,9 @@ module QA ...@@ -8,17 +8,9 @@ module QA
before do before do
Flow::Login.sign_in Flow::Login.sign_in
project = Resource::Project.fabricate_via_api! do |resource|
resource.name = 'project-for-issue-suggestions'
resource.description = 'project for issue suggestions'
end
Resource::Issue.fabricate_via_api! do |issue| Resource::Issue.fabricate_via_api! do |issue|
issue.title = issue_title issue.title = issue_title
issue.project = project end.project.visit!
end
project.visit!
end end
it 'user sees issue suggestions when creating a new issue' do it 'user sees issue suggestions when creating a new issue' do
......
...@@ -22,7 +22,7 @@ describe 'Instance-level AWS EKS Cluster', :js do ...@@ -22,7 +22,7 @@ describe 'Instance-level AWS EKS Cluster', :js do
end end
it 'user sees a form to create an EKS cluster' do it 'user sees a form to create an EKS cluster' do
expect(page).to have_content('Create new Cluster on EKS') expect(page).to have_content('Create new cluster on EKS')
end end
end end
end end
......
...@@ -28,7 +28,7 @@ describe 'Group AWS EKS Cluster', :js do ...@@ -28,7 +28,7 @@ describe 'Group AWS EKS Cluster', :js do
end end
it 'user sees a form to create an EKS cluster' do it 'user sees a form to create an EKS cluster' do
expect(page).to have_content('Create new Cluster on EKS') expect(page).to have_content('Create new cluster on EKS')
end end
end end
end end
......
...@@ -28,7 +28,7 @@ describe 'AWS EKS Cluster', :js do ...@@ -28,7 +28,7 @@ describe 'AWS EKS Cluster', :js do
end end
it 'user sees a form to create an EKS cluster' do it 'user sees a form to create an EKS cluster' do
expect(page).to have_content('Create new Cluster on EKS') expect(page).to have_content('Create new cluster on EKS')
end end
end end
end end
......
...@@ -29,7 +29,7 @@ describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do ...@@ -29,7 +29,7 @@ describe 'Gcp Cluster', :js, :do_not_mock_admin_mode do
visit project_clusters_path(project) visit project_clusters_path(project)
click_link 'Add Kubernetes cluster' click_link 'Add Kubernetes cluster'
click_link 'Create new Cluster' click_link 'Create new cluster'
click_link 'Google GKE' click_link 'Google GKE'
end end
......
...@@ -54,7 +54,7 @@ describe 'Clusters', :js do ...@@ -54,7 +54,7 @@ describe 'Clusters', :js do
visit project_clusters_path(project) visit project_clusters_path(project)
click_link 'Add Kubernetes cluster' click_link 'Add Kubernetes cluster'
click_link 'Create new Cluster' click_link 'Create new cluster'
end end
it 'user sees a link to create a GKE cluster' do it 'user sees a link to create a GKE cluster' do
......
...@@ -12,8 +12,6 @@ describe 'Import/Export - project export integration test', :js do ...@@ -12,8 +12,6 @@ describe 'Import/Export - project export integration test', :js do
let(:user) { create(:admin) } let(:user) { create(:admin) }
let(:export_path) { "#{Dir.tmpdir}/import_file_spec" } let(:export_path) { "#{Dir.tmpdir}/import_file_spec" }
let(:config_hash) { Gitlab::ImportExport::Config.new.to_h.deep_stringify_keys }
let(:sensitive_words) { %w[pass secret token key encrypted html] } let(:sensitive_words) { %w[pass secret token key encrypted html] }
let(:safe_list) do let(:safe_list) do
{ {
......
...@@ -37,25 +37,25 @@ describe ClustersHelper do ...@@ -37,25 +37,25 @@ describe ClustersHelper do
context 'GCP provider' do context 'GCP provider' do
let(:provider) { 'gcp' } let(:provider) { 'gcp' }
it { is_expected.to eq('Create new Cluster on GKE') } it { is_expected.to eq('Create new cluster on GKE') }
end end
context 'AWS provider' do context 'AWS provider' do
let(:provider) { 'aws' } let(:provider) { 'aws' }
it { is_expected.to eq('Create new Cluster on EKS') } it { is_expected.to eq('Create new cluster on EKS') }
end end
context 'other provider' do context 'other provider' do
let(:provider) { 'other' } let(:provider) { 'other' }
it { is_expected.to eq('Create new Cluster') } it { is_expected.to eq('Create new cluster') }
end end
context 'no provider' do context 'no provider' do
let(:provider) { nil } let(:provider) { nil }
it { is_expected.to eq('Create new Cluster') } it { is_expected.to eq('Create new cluster') }
end end
end end
......
...@@ -12,21 +12,11 @@ require 'spec_helper' ...@@ -12,21 +12,11 @@ require 'spec_helper'
describe 'Import/Export attribute configuration' do describe 'Import/Export attribute configuration' do
include ConfigurationHelper include ConfigurationHelper
let(:config_hash) { Gitlab::ImportExport::Config.new.to_h.deep_stringify_keys }
let(:relation_names) do
names = names_from_tree(config_hash.dig('tree', 'project'))
# Remove duplicated or add missing models
# - project is not part of the tree, so it has to be added manually.
# - milestone, labels have both singular and plural versions in the tree, so remove the duplicates.
names.flatten.uniq - %w(milestones labels) + ['project']
end
let(:safe_attributes_file) { 'spec/lib/gitlab/import_export/safe_model_attributes.yml' } let(:safe_attributes_file) { 'spec/lib/gitlab/import_export/safe_model_attributes.yml' }
let(:safe_model_attributes) { YAML.load_file(safe_attributes_file) } let(:safe_model_attributes) { YAML.load_file(safe_attributes_file) }
it 'has no new columns' do it 'has no new columns' do
relation_names.each do |relation_name| relation_names_for(:project).each do |relation_name|
relation_class = relation_class_for_name(relation_name) relation_class = relation_class_for_name(relation_name)
relation_attributes = relation_class.new.attributes.keys - relation_class.encrypted_attributes.keys.map(&:to_s) relation_attributes = relation_class.new.attributes.keys - relation_class.encrypted_attributes.keys.map(&:to_s)
......
...@@ -8,19 +8,10 @@ require 'spec_helper' ...@@ -8,19 +8,10 @@ require 'spec_helper'
describe 'Import/Export model configuration' do describe 'Import/Export model configuration' do
include ConfigurationHelper include ConfigurationHelper
let(:config_hash) { Gitlab::ImportExport::Config.new.to_h.deep_stringify_keys }
let(:model_names) do
names = names_from_tree(config_hash.dig('tree', 'project'))
# Remove duplicated or add missing models
# - project is not part of the tree, so it has to be added manually.
# - milestone, labels, merge_request have both singular and plural versions in the tree, so remove the duplicates.
# - User, Author... Models we do not care about for checking models
names.flatten.uniq - %w(milestones labels user author merge_request) + ['project']
end
let(:all_models_yml) { 'spec/lib/gitlab/import_export/all_models.yml' } let(:all_models_yml) { 'spec/lib/gitlab/import_export/all_models.yml' }
let(:all_models_hash) { YAML.load_file(all_models_yml) } let(:all_models_hash) { YAML.load_file(all_models_yml) }
let(:current_models) { setup_models } let(:current_models) { setup_models }
let(:model_names) { relation_names_for(:project) }
it 'has no new models' do it 'has no new models' do
model_names.each do |model_name| model_names.each do |model_name|
......
# frozen_string_literal: true
require 'spec_helper'
# Part of the test security suite for the Import/Export feature
# Checks whether there are new reference attributes ending with _id in models that are currently being exported as part of the
# project Import/Export feature.
# If there are new references (foreign keys), these will have to either be replaced with actual relation
# or to be blacklisted by using the import_export.yml configuration file.
# Likewise, new models added to import_export.yml, will need to be added with their correspondent relations
# to this spec.
describe 'Import/Export Project configuration' do
include ConfigurationHelper
where(:relation_path, :relation_name) do
relation_paths_for(:project).map do |relation_names|
next if relation_names.last == :author
[relation_names.join("."), relation_names.last]
end.compact
end
with_them do
context "where relation #{params[:relation_path]}" do
it 'does not have prohibited keys' do
relation_class = relation_class_for_name(relation_name)
relation_attributes = relation_class.new.attributes.keys - relation_class.encrypted_attributes.keys.map(&:to_s)
current_attributes = parsed_attributes(relation_name, relation_attributes)
prohibited_keys = current_attributes.select do |attribute|
prohibited_key?(attribute) || !relation_class.attribute_method?(attribute)
end
expect(prohibited_keys).to be_empty, failure_message(relation_class.to_s, prohibited_keys)
end
end
end
def failure_message(relation_class, prohibited_keys)
<<-MSG
It looks like #{relation_class}, which is exported using the project Import/Export, has references: #{prohibited_keys.join(',')}
Please replace it with actual relation in IMPORT_EXPORT_CONFIG if you consider this can be exported.
Please blacklist the attribute(s) in IMPORT_EXPORT_CONFIG by adding it to its correspondent
model in the +excluded_attributes+ section.
IMPORT_EXPORT_CONFIG: #{Gitlab::ImportExport.config_file}
MSG
end
end
...@@ -33,7 +33,6 @@ Issue: ...@@ -33,7 +33,6 @@ Issue:
Event: Event:
- id - id
- target_type - target_type
- target_id
- project_id - project_id
- group_id - group_id
- created_at - created_at
...@@ -60,7 +59,6 @@ Note: ...@@ -60,7 +59,6 @@ Note:
- attachment - attachment
- line_code - line_code
- commit_id - commit_id
- noteable_id
- system - system
- st_diff - st_diff
- updated_by_id - updated_by_id
...@@ -73,11 +71,8 @@ Note: ...@@ -73,11 +71,8 @@ Note:
- resolved_by_push - resolved_by_push
- discussion_id - discussion_id
- original_discussion_id - original_discussion_id
- review_id
LabelLink: LabelLink:
- id - id
- label_id
- target_id
- target_type - target_type
- created_at - created_at
- updated_at - updated_at
...@@ -130,13 +125,11 @@ Release: ...@@ -130,13 +125,11 @@ Release:
- released_at - released_at
Evidence: Evidence:
- id - id
- release_id
- summary - summary
- created_at - created_at
- updated_at - updated_at
Releases::Link: Releases::Link:
- id - id
- release_id
- url - url
- name - name
- created_at - created_at
...@@ -144,7 +137,6 @@ Releases::Link: ...@@ -144,7 +137,6 @@ Releases::Link:
ProjectMember: ProjectMember:
- id - id
- access_level - access_level
- source_id
- source_type - source_type
- user_id - user_id
- notification_level - notification_level
...@@ -600,7 +592,6 @@ AwardEmoji: ...@@ -600,7 +592,6 @@ AwardEmoji:
LabelPriority: LabelPriority:
- id - id
- project_id - project_id
- label_id
- priority - priority
- created_at - created_at
- updated_at - updated_at
...@@ -608,7 +599,6 @@ Timelog: ...@@ -608,7 +599,6 @@ Timelog:
- id - id
- time_spent - time_spent
- merge_request_id - merge_request_id
- issue_id
- user_id - user_id
- spent_at - spent_at
- created_at - created_at
...@@ -623,7 +613,6 @@ ProjectAutoDevops: ...@@ -623,7 +613,6 @@ ProjectAutoDevops:
- updated_at - updated_at
IssueAssignee: IssueAssignee:
- user_id - user_id
- issue_id
ProjectCustomAttribute: ProjectCustomAttribute:
- id - id
- created_at - created_at
...@@ -679,7 +668,6 @@ ProtectedEnvironment::DeployAccessLevel: ...@@ -679,7 +668,6 @@ ProtectedEnvironment::DeployAccessLevel:
ResourceLabelEvent: ResourceLabelEvent:
- id - id
- action - action
- issue_id
- merge_request_id - merge_request_id
- label_id - label_id
- user_id - user_id
...@@ -691,11 +679,9 @@ ErrorTracking::ProjectErrorTrackingSetting: ...@@ -691,11 +679,9 @@ ErrorTracking::ProjectErrorTrackingSetting:
- organization_name - organization_name
SentryIssue: SentryIssue:
- id - id
- issue_id
- sentry_issue_identifier - sentry_issue_identifier
Suggestion: Suggestion:
- id - id
- note_id
- relative_order - relative_order
- applied - applied
- commit_id - commit_id
...@@ -750,21 +736,16 @@ ExternalPullRequest: ...@@ -750,21 +736,16 @@ ExternalPullRequest:
DesignManagement::Design: DesignManagement::Design:
- id - id
- project_id - project_id
- issue_id
- filename - filename
DesignManagement::Action: DesignManagement::Action:
- design_id
- event - event
- version_id
DesignManagement::Version: DesignManagement::Version:
- id - id
- created_at - created_at
- sha - sha
- issue_id
- author_id - author_id
ZoomMeeting: ZoomMeeting:
- id - id
- issue_id
- project_id - project_id
- issue_status - issue_status
- url - url
......
...@@ -815,6 +815,27 @@ describe Ci::Build do ...@@ -815,6 +815,27 @@ describe Ci::Build do
it { is_expected.to contain_exactly(build, rspec_test, rubocop_test, staging) } it { is_expected.to contain_exactly(build, rspec_test, rubocop_test, staging) }
end end
end end
describe '#all_dependencies' do
let!(:final_build) do
create(:ci_build,
pipeline: pipeline, name: 'deploy',
stage_idx: 3, stage: 'deploy'
)
end
subject { final_build.all_dependencies }
it 'returns dependencies and cross_dependencies' do
dependencies = [1, 2, 3]
cross_dependencies = [3, 4]
allow(final_build).to receive(:dependencies).and_return(dependencies)
allow(final_build).to receive(:cross_dependencies).and_return(cross_dependencies)
is_expected.to match(a_collection_containing_exactly(1, 2, 3, 4))
end
end
end end
describe '#triggered_by?' do describe '#triggered_by?' do
......
...@@ -312,6 +312,72 @@ describe CommitStatus do ...@@ -312,6 +312,72 @@ describe CommitStatus do
end end
end end
describe '.for_ref' do
subject { described_class.for_ref('bb').order(:id) }
let(:statuses) do
[create_status(ref: 'aa'),
create_status(ref: 'bb'),
create_status(ref: 'cc')]
end
it 'returns statuses with the specified ref' do
is_expected.to eq(statuses.values_at(1))
end
end
describe '.by_name' do
subject { described_class.by_name('bb').order(:id) }
let(:statuses) do
[create_status(name: 'aa'),
create_status(name: 'bb'),
create_status(name: 'cc')]
end
it 'returns statuses with the specified name' do
is_expected.to eq(statuses.values_at(1))
end
end
describe '.for_project_paths' do
subject do
described_class
.for_project_paths(paths)
.order(:id)
end
context 'with a single path' do
let(:other_project) { create(:project, :repository) }
let(:paths) { other_project.full_path }
let(:other_pipeline) do
create(:ci_pipeline, project: other_project, sha: other_project.commit.id)
end
let(:statuses) do
[create_status(pipeline: pipeline),
create_status(pipeline: other_pipeline)]
end
it 'returns statuses for other_project' do
is_expected.to eq(statuses.values_at(1))
end
end
context 'with array of paths' do
let(:paths) { [project.full_path] }
let(:statuses) do
[create_status(pipeline: pipeline)]
end
it 'returns statuses for project' do
is_expected.to eq(statuses.values_at(0))
end
end
end
describe '.status' do describe '.status' do
context 'when there are multiple statuses present' do context 'when there are multiple statuses present' do
before do before do
......
...@@ -10,21 +10,54 @@ module ConfigurationHelper ...@@ -10,21 +10,54 @@ module ConfigurationHelper
end end
end end
def all_relations(tree, tree_path = [])
tree.flat_map do |relation_name, relations|
relation_path = tree_path + [relation_name]
[relation_path] + all_relations(relations, relation_path)
end
end
def config_hash(config = Gitlab::ImportExport.config_file)
Gitlab::ImportExport::Config.new(config: config).to_h
end
def relation_paths_for(key, config: Gitlab::ImportExport.config_file)
# - project is not part of the tree, so it has to be added manually.
all_relations({ project: config_hash(config).dig(:tree, key) })
end
def relation_names_for(key, config: Gitlab::ImportExport.config_file)
names = names_from_tree(config_hash(config).dig(:tree, key))
# Remove duplicated or add missing models
# - project is not part of the tree, so it has to be added manually.
# - milestone, labels, merge_request have both singular and plural versions in the tree, so remove the duplicates.
# - User, Author... Models we do not care about for checking models
names.flatten.uniq - %w(milestones labels user author merge_request design) + [key.to_s]
end
def relation_class_for_name(relation_name) def relation_class_for_name(relation_name)
relation_name = Gitlab::ImportExport::RelationFactory.overrides[relation_name.to_sym] || relation_name relation_name = Gitlab::ImportExport::RelationFactory.overrides[relation_name.to_sym] || relation_name
Gitlab::ImportExport::RelationFactory.relation_class(relation_name) Gitlab::ImportExport::RelationFactory.relation_class(relation_name)
end end
def parsed_attributes(relation_name, attributes) def parsed_attributes(relation_name, attributes, config: Gitlab::ImportExport.config_file)
excluded_attributes = config_hash['excluded_attributes'][relation_name] import_export_config = config_hash(config)
included_attributes = config_hash['included_attributes'][relation_name] excluded_attributes = import_export_config[:excluded_attributes][relation_name.to_sym]
included_attributes = import_export_config[:included_attributes][relation_name.to_sym]
attributes = attributes - JSON[excluded_attributes.to_json] if excluded_attributes attributes = attributes - JSON[excluded_attributes.to_json] if excluded_attributes
attributes = attributes & JSON[included_attributes.to_json] if included_attributes attributes = attributes & JSON[included_attributes.to_json] if included_attributes
attributes attributes
end end
def prohibited_key?(key)
key =~ Gitlab::ImportExport::AttributeCleaner::PROHIBITED_REFERENCES && !permitted_key?(key)
end
def permitted_key?(key)
Gitlab::ImportExport::AttributeCleaner::ALLOWED_REFERENCES.include?(key)
end
def associations_for(safe_model) def associations_for(safe_model)
safe_model.reflect_on_all_associations.map { |assoc| assoc.name.to_s } safe_model.reflect_on_all_associations.map { |assoc| assoc.name.to_s }
end end
......
...@@ -732,15 +732,15 @@ ...@@ -732,15 +732,15 @@
dependencies: dependencies:
vue-eslint-parser "^6.0.4" vue-eslint-parser "^6.0.4"
"@gitlab/svgs@^1.85.0": "@gitlab/svgs@^1.88.0":
version "1.85.0" version "1.88.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.85.0.tgz#c80247ec4764824385df2837136a0d4a84f881dc" resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.88.0.tgz#0a9b72e9591264fcac592ebf9944665c70f48de2"
integrity sha512-yzvKut0MPJEbSx/LExopCLpF5KEZsckF+d/Blbji1VqODVanH85oIVuJNmdECUlc7qxye9Or3evpFjW9Pkshmg== integrity sha512-ZgepCvZoB/lFdgttHtu8+9YlRZlVc9MnHDbbqcQCFBvrfOjY1wq12ikxnNbwKj8QNA47TRJvSS0TkHgMWYnbsA==
"@gitlab/ui@8.2.0": "@gitlab/ui@8.8.0":
version "8.2.0" version "8.8.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-8.2.0.tgz#82cf512407f8a774878969c72c4227d08ce49aa6" resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-8.8.0.tgz#c22b4dece89d224c525b3510970f3c61321a6765"
integrity sha512-ZzxA3XwmwZpol6QJjqBf3Oblb1wSFbDJ4QENvPiE9lAUHvhbe8wfKBK++RtgOtd6aXtLvoY1o1Du9qill07Jvg== integrity sha512-fjAGSgfau28iq+Uhivc5OPwu3ZLUL25gFuW1rKeQFgnkVEaQ9IRvdM8RD9+kgXWUsccsrafQkz/nOUmp85o8yQ==
dependencies: dependencies:
"@babel/standalone" "^7.0.0" "@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0" "@gitlab/vue-toasted" "^1.3.0"
...@@ -755,10 +755,10 @@ ...@@ -755,10 +755,10 @@
vue "^2.6.10" vue "^2.6.10"
vue-loader "^15.4.2" vue-loader "^15.4.2"
"@gitlab/visual-review-tools@1.2.0": "@gitlab/visual-review-tools@1.5.1":
version "1.2.0" version "1.5.1"
resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.2.0.tgz#8d6757917193c1023012bb4a316dc1a97309a27a" resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.5.1.tgz#2552927cd7a376f1f06ef3293a69fe2ffcdddb52"
integrity sha512-GaV/lYLmOF0hWtv8K8MLWGaCZ7PL1LF4D0/gargXYf9HO0Cw4wtz4oWyaLS15wFposJIYdPIHSNfrLVk4Dk9sQ== integrity sha512-8d6xgK4TsLA5gucd78jzaMyginAMJ8cbu/6ghUGws84zzAEsyJsMTstyt/fA5l4toQXVxtOh90BvDzwxSjZ6hQ==
"@gitlab/vue-toasted@^1.3.0": "@gitlab/vue-toasted@^1.3.0":
version "1.3.0" version "1.3.0"
......
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