Commit 634bd522 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 5cf2def4 6c1626e0
d12fb69a841d91d843f392a124865f6d47d3bc22 747d61c17a51f361cc883c9d4700e174219088a5
...@@ -93,12 +93,12 @@ export default { ...@@ -93,12 +93,12 @@ export default {
return { return {
name, name,
list, list,
title: this.getAwardListTitle(list), title: this.getAwardListTitle(list, name),
classes: this.getAwardClassBindings(list), classes: this.getAwardClassBindings(list),
html: glEmojiTag(name), html: glEmojiTag(name),
}; };
}, },
getAwardListTitle(awardsList) { getAwardListTitle(awardsList, name) {
if (!awardsList.length) { if (!awardsList.length) {
return ''; return '';
} }
...@@ -128,7 +128,7 @@ export default { ...@@ -128,7 +128,7 @@ export default {
// We have 10+ awarded user, join them with comma and add `and x more`. // We have 10+ awarded user, join them with comma and add `and x more`.
if (remainingAwardList.length) { if (remainingAwardList.length) {
title = sprintf( title = sprintf(
__(`%{listToShow}, and %{awardsListLength} more.`), __(`%{listToShow}, and %{awardsListLength} more`),
{ {
listToShow: namesToShow.join(', '), listToShow: namesToShow.join(', '),
awardsListLength: remainingAwardList.length, awardsListLength: remainingAwardList.length,
...@@ -146,7 +146,7 @@ export default { ...@@ -146,7 +146,7 @@ export default {
title = namesToShow.join(__(' and ')); title = namesToShow.join(__(' and '));
} }
return title; return title + sprintf(__(' reacted with :%{name}:'), { name });
}, },
handleAward(awardName) { handleAward(awardName) {
if (!this.canAwardEmoji) { if (!this.canAwardEmoji) {
......
...@@ -16,6 +16,7 @@ module Environments ...@@ -16,6 +16,7 @@ module Environments
environments = project.environments environments = project.environments
environments = by_name(environments) environments = by_name(environments)
environments = by_search(environments) environments = by_search(environments)
environments = by_ids(environments)
# Raises InvalidStatesError if params[:states] contains invalid states. # Raises InvalidStatesError if params[:states] contains invalid states.
by_states(environments) by_states(environments)
...@@ -47,6 +48,14 @@ module Environments ...@@ -47,6 +48,14 @@ module Environments
end end
end end
def by_ids(environments)
if params[:environment_ids].present?
environments.for_id(params[:environment_ids])
else
environments
end
end
def environments_with_states(environments) def environments_with_states(environments)
# Convert to array of strings # Convert to array of strings
states = Array(params[:states]).map(&:to_s) states = Array(params[:states]).map(&:to_s)
......
...@@ -9,6 +9,8 @@ class FinalizePushEventPayloadsBigintConversion < ActiveRecord::Migration[6.1] ...@@ -9,6 +9,8 @@ class FinalizePushEventPayloadsBigintConversion < ActiveRecord::Migration[6.1]
INDEX_NAME = 'index_push_event_payloads_on_event_id_convert_to_bigint' INDEX_NAME = 'index_push_event_payloads_on_event_id_convert_to_bigint'
def up def up
return unless should_run?
ensure_batched_background_migration_is_finished( ensure_batched_background_migration_is_finished(
job_class_name: 'CopyColumnUsingBackgroundMigrationJob', job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
table_name: TABLE_NAME, table_name: TABLE_NAME,
...@@ -20,11 +22,17 @@ class FinalizePushEventPayloadsBigintConversion < ActiveRecord::Migration[6.1] ...@@ -20,11 +22,17 @@ class FinalizePushEventPayloadsBigintConversion < ActiveRecord::Migration[6.1]
end end
def down def down
return unless should_run?
swap_columns swap_columns
end end
private private
def should_run?
Gitlab.dev_or_test_env? || Gitlab.com?
end
def swap_columns def swap_columns
add_concurrent_index TABLE_NAME, :event_id_convert_to_bigint, unique: true, name: INDEX_NAME add_concurrent_index TABLE_NAME, :event_id_convert_to_bigint, unique: true, name: INDEX_NAME
......
# frozen_string_literal: true
require Rails.root.join('db', 'post_migrate', '20210622041846_finalize_push_event_payloads_bigint_conversion')
class MigratePushEventPayloadsEventIdBackToIntegerForGitlabCom < ActiveRecord::Migration[6.1]
disable_ddl_transaction!
def up
FinalizePushEventPayloadsBigintConversion.new.down
end
def down
FinalizePushEventPayloadsBigintConversion.new.up
end
end
71ad8c8f2419721f8fdf6c6bbd1265c4a7ca277972c59319e155bc6dfc46aa48
\ No newline at end of file
...@@ -17376,7 +17376,7 @@ ALTER SEQUENCE protected_tags_id_seq OWNED BY protected_tags.id; ...@@ -17376,7 +17376,7 @@ ALTER SEQUENCE protected_tags_id_seq OWNED BY protected_tags.id;
CREATE TABLE push_event_payloads ( CREATE TABLE push_event_payloads (
commit_count bigint NOT NULL, commit_count bigint NOT NULL,
event_id_convert_to_bigint integer DEFAULT 0 NOT NULL, event_id integer NOT NULL,
action smallint NOT NULL, action smallint NOT NULL,
ref_type smallint NOT NULL, ref_type smallint NOT NULL,
commit_from bytea, commit_from bytea,
...@@ -17384,7 +17384,7 @@ CREATE TABLE push_event_payloads ( ...@@ -17384,7 +17384,7 @@ CREATE TABLE push_event_payloads (
ref text, ref text,
commit_title character varying(70), commit_title character varying(70),
ref_count integer, ref_count integer,
event_id bigint NOT NULL event_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
); );
CREATE TABLE push_rules ( CREATE TABLE push_rules (
...@@ -10949,6 +10949,7 @@ Represents the network policy. ...@@ -10949,6 +10949,7 @@ Represents the network policy.
| Name | Type | Description | | Name | Type | Description |
| ---- | ---- | ----------- | | ---- | ---- | ----------- |
| <a id="networkpolicyenabled"></a>`enabled` | [`Boolean!`](#boolean) | Indicates whether this policy is enabled. | | <a id="networkpolicyenabled"></a>`enabled` | [`Boolean!`](#boolean) | Indicates whether this policy is enabled. |
| <a id="networkpolicyenvironments"></a>`environments` | [`EnvironmentConnection`](#environmentconnection) | Environments where this policy is applied. (see [Connections](#connections)) |
| <a id="networkpolicyfromautodevops"></a>`fromAutoDevops` | [`Boolean!`](#boolean) | Indicates whether this policy is created from AutoDevops. | | <a id="networkpolicyfromautodevops"></a>`fromAutoDevops` | [`Boolean!`](#boolean) | Indicates whether this policy is created from AutoDevops. |
| <a id="networkpolicyname"></a>`name` | [`String!`](#string) | Name of the policy. | | <a id="networkpolicyname"></a>`name` | [`String!`](#string) | Name of the policy. |
| <a id="networkpolicynamespace"></a>`namespace` | [`String!`](#string) | Namespace of the policy. | | <a id="networkpolicynamespace"></a>`namespace` | [`String!`](#string) | Namespace of the policy. |
......
...@@ -29,7 +29,9 @@ module Resolvers ...@@ -29,7 +29,9 @@ module Resolvers
updated_at: Time.iso8601(policy_json[:creation_timestamp]), updated_at: Time.iso8601(policy_json[:creation_timestamp]),
yaml: policy_json[:manifest], yaml: policy_json[:manifest],
from_auto_devops: policy_json[:is_autodevops], from_auto_devops: policy_json[:is_autodevops],
enabled: policy_json[:is_enabled] enabled: policy_json[:is_enabled],
environment_ids: policy_json[:environment_ids],
project: project
} }
end end
end end
......
...@@ -35,5 +35,21 @@ module Types ...@@ -35,5 +35,21 @@ module Types
Types::TimeType, Types::TimeType,
null: false, null: false,
description: 'Timestamp of when the policy YAML was last updated.' description: 'Timestamp of when the policy YAML was last updated.'
field :environments,
Types::EnvironmentType.connection_type,
null: true,
description: 'Environments where this policy is applied.'
def environments
BatchLoader::GraphQL.for(object[:environment_ids]).batch do |policy_environment_ids, loader|
finder = ::Environments::EnvironmentsFinder.new(object[:project], context[:current_user], environment_ids: policy_environment_ids.flatten.uniq)
environments_by_id = finder.execute.index_by(&:id)
policy_environment_ids.each do |ids|
loader.call(ids, environments_by_id.values_at(*ids))
end
end
end
end end
end end
...@@ -17,8 +17,8 @@ module NetworkPolicies ...@@ -17,8 +17,8 @@ module NetworkPolicies
policies = [] policies = []
errors = [] errors = []
@kubeclient_info.each do |platform, namespace| @kubeclient_info.each do |platform, (namespace, environment_ids)|
policies_per_environment, error_per_environment = execute_per_environment(platform, namespace) policies_per_environment, error_per_environment = execute_per_environment(platform, namespace, environment_ids)
policies += policies_per_environment if policies_per_environment policies += policies_per_environment if policies_per_environment
errors << error_per_environment if error_per_environment errors << error_per_environment if error_per_environment
end end
...@@ -33,13 +33,13 @@ module NetworkPolicies ...@@ -33,13 +33,13 @@ module NetworkPolicies
track_usage_event(:clusters_using_network_policies_ui, platform.cluster_id) track_usage_event(:clusters_using_network_policies_ui, platform.cluster_id)
end end
def execute_per_environment(platform, namespace) def execute_per_environment(platform, namespace, environment_ids)
policies = platform.kubeclient policies = platform.kubeclient
.get_network_policies(namespace: namespace) .get_network_policies(namespace: namespace)
.map { |resource| Gitlab::Kubernetes::NetworkPolicy.from_resource(resource) } .map { |resource| Gitlab::Kubernetes::NetworkPolicy.from_resource(resource, environment_ids) }
policies += platform.kubeclient policies += platform.kubeclient
.get_cilium_network_policies(namespace: namespace) .get_cilium_network_policies(namespace: namespace)
.map { |resource| Gitlab::Kubernetes::CiliumNetworkPolicy.from_resource(resource) } .map { |resource| Gitlab::Kubernetes::CiliumNetworkPolicy.from_resource(resource, environment_ids) }
track_usage_data_for_cluster(platform, policies) track_usage_data_for_cluster(platform, policies)
[policies, nil] [policies, nil]
rescue Kubeclient::HttpError => e rescue Kubeclient::HttpError => e
...@@ -47,7 +47,7 @@ module NetworkPolicies ...@@ -47,7 +47,7 @@ module NetworkPolicies
end end
def has_deployment_platform?(kubeclient_info) def has_deployment_platform?(kubeclient_info)
kubeclient_info.any? { |platform, namespace| platform.present? } kubeclient_info.any? { |platform, _| platform.present? }
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
...@@ -63,7 +63,7 @@ module NetworkPolicies ...@@ -63,7 +63,7 @@ module NetworkPolicies
.order(updated_at: :desc) .order(updated_at: :desc)
.preload(:platform_kubernetes) .preload(:platform_kubernetes)
.group_by(&:namespace) .group_by(&:namespace)
.map { |namespace, kubernetes_namespaces| [kubernetes_namespaces.first.platform_kubernetes, namespace] } .map { |namespace, kubernetes_namespaces| [kubernetes_namespaces.first.platform_kubernetes, [namespace, kubernetes_namespaces.map(&:environment_id)]] }
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
end end
......
...@@ -16,7 +16,8 @@ RSpec.describe Resolvers::NetworkPolicyResolver do ...@@ -16,7 +16,8 @@ RSpec.describe Resolvers::NetworkPolicyResolver do
namespace: 'another', namespace: 'another',
creation_timestamp: time_now.iso8601, creation_timestamp: time_now.iso8601,
selector: { matchLabels: { role: 'db' } }, selector: { matchLabels: { role: 'db' } },
ingress: [{ from: [{ namespaceSelector: { matchLabels: { project: 'myproject' } } }] }] ingress: [{ from: [{ namespaceSelector: { matchLabels: { project: 'myproject' } } }] }],
environment_ids: [1, 2]
) )
end end
...@@ -27,7 +28,8 @@ RSpec.describe Resolvers::NetworkPolicyResolver do ...@@ -27,7 +28,8 @@ RSpec.describe Resolvers::NetworkPolicyResolver do
creation_timestamp: time_now.iso8601, creation_timestamp: time_now.iso8601,
resource_version: '102', resource_version: '102',
selector: { matchLabels: { role: 'db' } }, selector: { matchLabels: { role: 'db' } },
ingress: [{ endpointFrom: [{ matchLabels: { project: 'myproject' } }] }] ingress: [{ endpointFrom: [{ matchLabels: { project: 'myproject' } }] }],
environment_ids: [3, 4]
) )
end end
...@@ -97,7 +99,9 @@ RSpec.describe Resolvers::NetworkPolicyResolver do ...@@ -97,7 +99,9 @@ RSpec.describe Resolvers::NetworkPolicyResolver do
enabled: true, enabled: true,
yaml: policy.as_json[:manifest], yaml: policy.as_json[:manifest],
updated_at: time_now, updated_at: time_now,
from_auto_devops: false from_auto_devops: false,
environment_ids: [1, 2],
project: project
}, },
{ {
name: 'cilium_policy', name: 'cilium_policy',
...@@ -105,7 +109,9 @@ RSpec.describe Resolvers::NetworkPolicyResolver do ...@@ -105,7 +109,9 @@ RSpec.describe Resolvers::NetworkPolicyResolver do
enabled: true, enabled: true,
yaml: cilium_policy.as_json[:manifest], yaml: cilium_policy.as_json[:manifest],
updated_at: time_now, updated_at: time_now,
from_auto_devops: false from_auto_devops: false,
environment_ids: [3, 4],
project: project
} }
] ]
expect(resolve_network_policies).to eq(expected_resolved) expect(resolve_network_policies).to eq(expected_resolved)
......
...@@ -12,7 +12,54 @@ RSpec.describe GitlabSchema.types['NetworkPolicy'] do ...@@ -12,7 +12,54 @@ RSpec.describe GitlabSchema.types['NetworkPolicy'] do
:enabled, :enabled,
:from_auto_devops, :from_auto_devops,
:yaml, :yaml,
:updated_at :updated_at,
:environments
) )
end end
describe '#environments' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, namespace: user.namespace) }
let_it_be(:environment_1) { create(:environment, project: project) }
let_it_be(:environment_2) { create(:environment, project: project) }
let_it_be(:environment_3) { create(:environment, project: project) }
let(:policy_1) { double(as_json: { creation_timestamp: Time.current.iso8601, project: project, environment_ids: [environment_1.id] }) }
let(:policy_2) { double(as_json: { creation_timestamp: Time.current.iso8601, project: project, environment_ids: [environment_1.id, environment_2.id] }) }
let(:service_response_single_environment) { double(success?: true, payload: [policy_1]) }
let(:service_response_multiple_environments) { double(success?: true, payload: [policy_1, policy_2]) }
let(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
networkPolicies {
nodes {
environments {
nodes {
id
name
}
}
}
}
}
}
)
end
it 'avoids N+1 database queries' do
allow_next_instance_of(NetworkPolicies::ResourcesService) do |service|
allow(service).to receive(:execute).and_return(service_response_single_environment)
end
control_count = ActiveRecord::QueryRecorder.new { GitlabSchema.execute(query, context: { current_user: user }) }.count
allow_next_instance_of(NetworkPolicies::ResourcesService) do |service|
allow(service).to receive(:execute).and_return(service_response_multiple_environments)
end
expect { GitlabSchema.execute(query, context: { current_user: user }) }.not_to exceed_query_limit(control_count)
end
end
end end
...@@ -16,7 +16,8 @@ RSpec.describe NetworkPolicies::ResourcesService do ...@@ -16,7 +16,8 @@ RSpec.describe NetworkPolicies::ResourcesService do
name: 'policy', name: 'policy',
namespace: 'another', namespace: 'another',
selector: { matchLabels: { role: 'db' } }, selector: { matchLabels: { role: 'db' } },
ingress: [{ from: [{ namespaceSelector: { matchLabels: { project: 'myproject' } } }] }] ingress: [{ from: [{ namespaceSelector: { matchLabels: { project: 'myproject' } } }] }],
environment_ids: [environment.id]
) )
end end
...@@ -26,7 +27,8 @@ RSpec.describe NetworkPolicies::ResourcesService do ...@@ -26,7 +27,8 @@ RSpec.describe NetworkPolicies::ResourcesService do
namespace: 'another', namespace: 'another',
resource_version: '102', resource_version: '102',
selector: { matchLabels: { role: 'db' } }, selector: { matchLabels: { role: 'db' } },
ingress: [{ endpointFrom: [{ matchLabels: { project: 'myproject' } }] }] ingress: [{ endpointFrom: [{ matchLabels: { project: 'myproject' } }] }],
environment_ids: [environment.id]
) )
end end
...@@ -109,7 +111,8 @@ RSpec.describe NetworkPolicies::ResourcesService do ...@@ -109,7 +111,8 @@ RSpec.describe NetworkPolicies::ResourcesService do
name: 'policy_2', name: 'policy_2',
namespace: 'another_2', namespace: 'another_2',
selector: { matchLabels: { role: 'db' } }, selector: { matchLabels: { role: 'db' } },
ingress: [{ from: [{ namespaceSelector: { matchLabels: { project: 'myproject' } } }] }] ingress: [{ from: [{ namespaceSelector: { matchLabels: { project: 'myproject' } } }] }],
environment_ids: [environment.id]
) )
end end
......
...@@ -12,7 +12,7 @@ module Gitlab ...@@ -12,7 +12,7 @@ module Gitlab
# We are modeling existing kubernetes resource and don't have # We are modeling existing kubernetes resource and don't have
# control over amount of parameters. # control over amount of parameters.
# rubocop:disable Metrics/ParameterLists # rubocop:disable Metrics/ParameterLists
def initialize(name:, namespace:, selector:, ingress:, resource_version: nil, description: nil, labels: nil, creation_timestamp: nil, egress: nil, annotations: nil) def initialize(name:, namespace:, selector:, ingress:, resource_version: nil, description: nil, labels: nil, creation_timestamp: nil, egress: nil, annotations: nil, environment_ids: [])
@name = name @name = name
@description = description @description = description
@namespace = namespace @namespace = namespace
...@@ -23,6 +23,7 @@ module Gitlab ...@@ -23,6 +23,7 @@ module Gitlab
@ingress = ingress @ingress = ingress
@egress = egress @egress = egress
@annotations = annotations @annotations = annotations
@environment_ids = environment_ids
end end
# rubocop:enable Metrics/ParameterLists # rubocop:enable Metrics/ParameterLists
...@@ -49,7 +50,7 @@ module Gitlab ...@@ -49,7 +50,7 @@ module Gitlab
nil nil
end end
def self.from_resource(resource) def self.from_resource(resource, environment_ids = [])
return unless resource return unless resource
return if !resource[:metadata] || !resource[:spec] return if !resource[:metadata] || !resource[:spec]
...@@ -65,7 +66,8 @@ module Gitlab ...@@ -65,7 +66,8 @@ module Gitlab
creation_timestamp: metadata[:creationTimestamp], creation_timestamp: metadata[:creationTimestamp],
selector: spec[:endpointSelector], selector: spec[:endpointSelector],
ingress: spec[:ingress], ingress: spec[:ingress],
egress: spec[:egress] egress: spec[:egress],
environment_ids: environment_ids
) )
end end
...@@ -83,7 +85,7 @@ module Gitlab ...@@ -83,7 +85,7 @@ module Gitlab
private private
attr_reader :name, :description, :namespace, :labels, :creation_timestamp, :resource_version, :ingress, :egress, :annotations attr_reader :name, :description, :namespace, :labels, :creation_timestamp, :resource_version, :ingress, :egress, :annotations, :environment_ids
def selector def selector
@selector ||= {} @selector ||= {}
......
...@@ -8,7 +8,8 @@ module Gitlab ...@@ -8,7 +8,8 @@ module Gitlab
KIND = 'NetworkPolicy' KIND = 'NetworkPolicy'
def initialize(name:, namespace:, selector:, ingress:, labels: nil, creation_timestamp: nil, policy_types: ["Ingress"], egress: nil) # rubocop:disable Metrics/ParameterLists
def initialize(name:, namespace:, selector:, ingress:, labels: nil, creation_timestamp: nil, policy_types: ["Ingress"], egress: nil, environment_ids: [])
@name = name @name = name
@namespace = namespace @namespace = namespace
@labels = labels @labels = labels
...@@ -17,7 +18,9 @@ module Gitlab ...@@ -17,7 +18,9 @@ module Gitlab
@policy_types = policy_types @policy_types = policy_types
@ingress = ingress @ingress = ingress
@egress = egress @egress = egress
@environment_ids = environment_ids
end end
# rubocop:enable Metrics/ParameterLists
def self.from_yaml(manifest) def self.from_yaml(manifest)
return unless manifest return unless manifest
...@@ -40,7 +43,7 @@ module Gitlab ...@@ -40,7 +43,7 @@ module Gitlab
nil nil
end end
def self.from_resource(resource) def self.from_resource(resource, environment_ids = [])
return unless resource return unless resource
return if !resource[:metadata] || !resource[:spec] return if !resource[:metadata] || !resource[:spec]
...@@ -54,7 +57,8 @@ module Gitlab ...@@ -54,7 +57,8 @@ module Gitlab
selector: spec[:podSelector], selector: spec[:podSelector],
policy_types: spec[:policyTypes], policy_types: spec[:policyTypes],
ingress: spec[:ingress], ingress: spec[:ingress],
egress: spec[:egress] egress: spec[:egress],
environment_ids: environment_ids
) )
end end
...@@ -69,7 +73,7 @@ module Gitlab ...@@ -69,7 +73,7 @@ module Gitlab
private private
attr_reader :name, :namespace, :labels, :creation_timestamp, :policy_types, :ingress, :egress attr_reader :name, :namespace, :labels, :creation_timestamp, :policy_types, :ingress, :egress, :environment_ids
def selector def selector
@selector ||= {} @selector ||= {}
......
...@@ -16,7 +16,8 @@ module Gitlab ...@@ -16,7 +16,8 @@ module Gitlab
creation_timestamp: creation_timestamp, creation_timestamp: creation_timestamp,
manifest: manifest, manifest: manifest,
is_autodevops: autodevops?, is_autodevops: autodevops?,
is_enabled: enabled? is_enabled: enabled?,
environment_ids: environment_ids
} }
end end
......
...@@ -177,7 +177,7 @@ module Gitlab ...@@ -177,7 +177,7 @@ module Gitlab
end end
def repository_route_regex def repository_route_regex
@repository_route_regex ||= /#{full_namespace_route_regex}|#{personal_snippet_repository_path_regex}/.freeze @repository_route_regex ||= /(#{full_namespace_route_regex}|#{personal_snippet_repository_path_regex})\.*/.freeze
end end
def repository_git_route_regex def repository_git_route_regex
...@@ -185,7 +185,7 @@ module Gitlab ...@@ -185,7 +185,7 @@ module Gitlab
end end
def repository_wiki_git_route_regex def repository_wiki_git_route_regex
@repository_wiki_git_route_regex ||= /#{full_namespace_route_regex}\.wiki\.git/.freeze @repository_wiki_git_route_regex ||= /#{full_namespace_route_regex}\.*\.wiki\.git/.freeze
end end
def full_namespace_path_regex def full_namespace_path_regex
......
...@@ -77,6 +77,9 @@ msgstr "" ...@@ -77,6 +77,9 @@ msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)" msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr "" msgstr ""
msgid " reacted with :%{name}:"
msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\"" msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "" msgstr ""
...@@ -687,7 +690,7 @@ msgstr "" ...@@ -687,7 +690,7 @@ msgstr ""
msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready." msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
msgstr "" msgstr ""
msgid "%{listToShow}, and %{awardsListLength} more." msgid "%{listToShow}, and %{awardsListLength} more"
msgstr "" msgstr ""
msgid "%{location} is missing required keys: %{keys}" msgid "%{location} is missing required keys: %{keys}"
......
...@@ -63,7 +63,7 @@ RSpec.describe 'User interacts with awards' do ...@@ -63,7 +63,7 @@ RSpec.describe 'User interacts with awards' do
page.within('.awards') do page.within('.awards') do
expect(page).to have_selector('[data-testid="award-button"]') expect(page).to have_selector('[data-testid="award-button"]')
expect(page.find('[data-testid="award-button"].selected .js-counter')).to have_content('1') expect(page.find('[data-testid="award-button"].selected .js-counter')).to have_content('1')
expect(page).to have_css('[data-testid="award-button"].selected[title="You"]') expect(page).to have_css('[data-testid="award-button"].selected[title="You reacted with :8ball:"]')
expect do expect do
page.find('[data-testid="award-button"].selected').click page.find('[data-testid="award-button"].selected').click
......
...@@ -3,9 +3,11 @@ ...@@ -3,9 +3,11 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Environments::EnvironmentsFinder do RSpec.describe Environments::EnvironmentsFinder do
let(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
let(:user) { project.creator } let_it_be(:user) { project.creator }
let(:environment) { create(:environment, :available, project: project) } let_it_be(:environment) { create(:environment, :available, project: project) }
let_it_be(:environment_stopped) { create(:environment, :stopped, name: 'test2', project: project) }
let_it_be(:environment_available) { create(:environment, :available, name: 'test3', project: project) }
before do before do
project.add_maintainer(user) project.add_maintainer(user)
...@@ -13,18 +15,18 @@ RSpec.describe Environments::EnvironmentsFinder do ...@@ -13,18 +15,18 @@ RSpec.describe Environments::EnvironmentsFinder do
describe '#execute' do describe '#execute' do
context 'with states parameter' do context 'with states parameter' do
let(:stopped_environment) { create(:environment, :stopped, project: project) } let_it_be(:stopped_environment) { create(:environment, :stopped, project: project) }
it 'returns environments with the requested state' do it 'returns environments with the requested state' do
result = described_class.new(project, user, states: 'available').execute result = described_class.new(project, user, states: 'available').execute
expect(result).to contain_exactly(environment) expect(result).to contain_exactly(environment, environment_available)
end end
it 'returns environments with any of the requested states' do it 'returns environments with any of the requested states' do
result = described_class.new(project, user, states: %w(available stopped)).execute result = described_class.new(project, user, states: %w(available stopped)).execute
expect(result).to contain_exactly(environment, stopped_environment) expect(result).to contain_exactly(environment, environment_stopped, environment_available, stopped_environment)
end end
it 'raises exception when requested state is invalid' do it 'raises exception when requested state is invalid' do
...@@ -37,25 +39,30 @@ RSpec.describe Environments::EnvironmentsFinder do ...@@ -37,25 +39,30 @@ RSpec.describe Environments::EnvironmentsFinder do
it 'returns environments with the requested state' do it 'returns environments with the requested state' do
result = described_class.new(project, user, states: :available).execute result = described_class.new(project, user, states: :available).execute
expect(result).to contain_exactly(environment) expect(result).to contain_exactly(environment, environment_available)
end end
it 'returns environments with any of the requested states' do it 'returns environments with any of the requested states' do
result = described_class.new(project, user, states: [:available, :stopped]).execute result = described_class.new(project, user, states: [:available, :stopped]).execute
expect(result).to contain_exactly(environment, stopped_environment) expect(result).to contain_exactly(environment, environment_stopped, environment_available, stopped_environment)
end end
end end
end end
context 'with search and states' do context 'with search and states' do
let(:environment2) { create(:environment, :stopped, name: 'test2', project: project) }
let(:environment3) { create(:environment, :available, name: 'test3', project: project) }
it 'searches environments by name and state' do it 'searches environments by name and state' do
result = described_class.new(project, user, search: 'test', states: :available).execute result = described_class.new(project, user, search: 'test', states: :available).execute
expect(result).to contain_exactly(environment3) expect(result).to contain_exactly(environment_available)
end
end
context 'with id' do
it 'searches environments by name and state' do
result = described_class.new(project, user, search: 'test', environment_ids: [environment_available.id]).execute
expect(result).to contain_exactly(environment_available)
end end
end end
end end
......
...@@ -7,7 +7,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = ` ...@@ -7,7 +7,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button <button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button" class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button"
data-testid="award-button" data-testid="award-button"
title="Ada, Leonardo, and Marie" title="Ada, Leonardo, and Marie reacted with :thumbsup:"
type="button" type="button"
> >
<!----> <!---->
...@@ -37,7 +37,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = ` ...@@ -37,7 +37,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button <button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected" class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button" data-testid="award-button"
title="You, Ada, and Marie" title="You, Ada, and Marie reacted with :thumbsdown:"
type="button" type="button"
> >
<!----> <!---->
...@@ -67,7 +67,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = ` ...@@ -67,7 +67,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button <button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button" class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button"
data-testid="award-button" data-testid="award-button"
title="Ada and Jane" title="Ada and Jane reacted with :smile:"
type="button" type="button"
> >
<!----> <!---->
...@@ -97,7 +97,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = ` ...@@ -97,7 +97,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button <button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected" class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button" data-testid="award-button"
title="You, Ada, Jane, and Leonardo" title="You, Ada, Jane, and Leonardo reacted with :ok_hand:"
type="button" type="button"
> >
<!----> <!---->
...@@ -127,7 +127,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = ` ...@@ -127,7 +127,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button <button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected" class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button" data-testid="award-button"
title="You" title="You reacted with :cactus:"
type="button" type="button"
> >
<!----> <!---->
...@@ -157,7 +157,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = ` ...@@ -157,7 +157,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button <button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button" class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button"
data-testid="award-button" data-testid="award-button"
title="Marie" title="Marie reacted with :a:"
type="button" type="button"
> >
<!----> <!---->
...@@ -187,7 +187,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = ` ...@@ -187,7 +187,7 @@ exports[`vue_shared/components/awards_list default matches snapshot 1`] = `
<button <button
class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected" class="btn gl-mr-3 gl-my-2 btn-default btn-md gl-button selected"
data-testid="award-button" data-testid="award-button"
title="You" title="You reacted with :b:"
type="button" type="button"
> >
<!----> <!---->
......
...@@ -98,43 +98,43 @@ describe('vue_shared/components/awards_list', () => { ...@@ -98,43 +98,43 @@ describe('vue_shared/components/awards_list', () => {
classes: REACTION_CONTROL_CLASSES, classes: REACTION_CONTROL_CLASSES,
count: 3, count: 3,
html: matchingEmojiTag(EMOJI_THUMBSUP), html: matchingEmojiTag(EMOJI_THUMBSUP),
title: 'Ada, Leonardo, and Marie', title: `Ada, Leonardo, and Marie reacted with :${EMOJI_THUMBSUP}:`,
}, },
{ {
classes: [...REACTION_CONTROL_CLASSES, 'selected'], classes: [...REACTION_CONTROL_CLASSES, 'selected'],
count: 3, count: 3,
html: matchingEmojiTag(EMOJI_THUMBSDOWN), html: matchingEmojiTag(EMOJI_THUMBSDOWN),
title: 'You, Ada, and Marie', title: `You, Ada, and Marie reacted with :${EMOJI_THUMBSDOWN}:`,
}, },
{ {
classes: REACTION_CONTROL_CLASSES, classes: REACTION_CONTROL_CLASSES,
count: 2, count: 2,
html: matchingEmojiTag(EMOJI_SMILE), html: matchingEmojiTag(EMOJI_SMILE),
title: 'Ada and Jane', title: `Ada and Jane reacted with :${EMOJI_SMILE}:`,
}, },
{ {
classes: [...REACTION_CONTROL_CLASSES, 'selected'], classes: [...REACTION_CONTROL_CLASSES, 'selected'],
count: 4, count: 4,
html: matchingEmojiTag(EMOJI_OK), html: matchingEmojiTag(EMOJI_OK),
title: 'You, Ada, Jane, and Leonardo', title: `You, Ada, Jane, and Leonardo reacted with :${EMOJI_OK}:`,
}, },
{ {
classes: [...REACTION_CONTROL_CLASSES, 'selected'], classes: [...REACTION_CONTROL_CLASSES, 'selected'],
count: 1, count: 1,
html: matchingEmojiTag(EMOJI_CACTUS), html: matchingEmojiTag(EMOJI_CACTUS),
title: 'You', title: `You reacted with :${EMOJI_CACTUS}:`,
}, },
{ {
classes: REACTION_CONTROL_CLASSES, classes: REACTION_CONTROL_CLASSES,
count: 1, count: 1,
html: matchingEmojiTag(EMOJI_A), html: matchingEmojiTag(EMOJI_A),
title: 'Marie', title: `Marie reacted with :${EMOJI_A}:`,
}, },
{ {
classes: [...REACTION_CONTROL_CLASSES, 'selected'], classes: [...REACTION_CONTROL_CLASSES, 'selected'],
count: 1, count: 1,
html: matchingEmojiTag(EMOJI_B), html: matchingEmojiTag(EMOJI_B),
title: 'You', title: `You reacted with :${EMOJI_B}:`,
}, },
]); ]);
}); });
...@@ -246,13 +246,13 @@ describe('vue_shared/components/awards_list', () => { ...@@ -246,13 +246,13 @@ describe('vue_shared/components/awards_list', () => {
classes: REACTION_CONTROL_CLASSES, classes: REACTION_CONTROL_CLASSES,
count: 1, count: 1,
html: matchingEmojiTag(EMOJI_100), html: matchingEmojiTag(EMOJI_100),
title: 'Marie', title: `Marie reacted with :${EMOJI_100}:`,
}, },
{ {
classes: REACTION_CONTROL_CLASSES, classes: REACTION_CONTROL_CLASSES,
count: 1, count: 1,
html: matchingEmojiTag(EMOJI_SMILE), html: matchingEmojiTag(EMOJI_SMILE),
title: 'Marie', title: `Marie reacted with :${EMOJI_SMILE}:`,
}, },
]); ]);
}); });
......
...@@ -206,6 +206,14 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do ...@@ -206,6 +206,14 @@ RSpec.describe Gitlab::Kubernetes::CiliumNetworkPolicy do
it { is_expected.to be_nil } it { is_expected.to be_nil }
end end
context 'with environment_ids' do
subject { Gitlab::Kubernetes::CiliumNetworkPolicy.from_resource(resource, [1, 2, 3]) }
it 'includes environment_ids in as_json result' do
expect(subject.as_json).to include(environment_ids: [1, 2, 3])
end
end
end end
describe '#resource' do describe '#resource' do
......
...@@ -196,6 +196,14 @@ RSpec.describe Gitlab::Kubernetes::NetworkPolicy do ...@@ -196,6 +196,14 @@ RSpec.describe Gitlab::Kubernetes::NetworkPolicy do
it { is_expected.to be_nil } it { is_expected.to be_nil }
end end
context 'with environment_ids' do
subject { Gitlab::Kubernetes::NetworkPolicy.from_resource(resource, [1, 2, 3]) }
it 'includes environment_ids in as_json result' do
expect(subject.as_json).to include(environment_ids: [1, 2, 3])
end
end
end end
describe '#resource' do describe '#resource' do
......
...@@ -445,6 +445,8 @@ RSpec.describe Gitlab::PathRegex do ...@@ -445,6 +445,8 @@ RSpec.describe Gitlab::PathRegex do
[ [
'gitlab-org', 'gitlab-org',
'gitlab-org/gitlab-test', 'gitlab-org/gitlab-test',
'gitlab-org/foo.',
'gitlab-org/bar..',
'gitlab-org/gitlab-test/snippets/1', 'gitlab-org/gitlab-test/snippets/1',
'gitlab-org/gitlab-test/snippets/foo', # ambiguous, we allow creating a sub-group called 'snippets' 'gitlab-org/gitlab-test/snippets/foo', # ambiguous, we allow creating a sub-group called 'snippets'
'snippets/1' 'snippets/1'
......
This diff is collapsed.
...@@ -19,7 +19,8 @@ RSpec.shared_examples 'network policy common specs' do ...@@ -19,7 +19,8 @@ RSpec.shared_examples 'network policy common specs' do
creation_timestamp: nil, creation_timestamp: nil,
manifest: YAML.dump(policy.resource.deep_stringify_keys), manifest: YAML.dump(policy.resource.deep_stringify_keys),
is_autodevops: false, is_autodevops: false,
is_enabled: true is_enabled: true,
environment_ids: []
} }
end end
......
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