diff options
| author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-22 03:14:19 +0000 |
|---|---|---|
| committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-22 03:14:19 +0000 |
| commit | e4011eb84527cb7fd46aa34e07a8cd33746c4a5a (patch) | |
| tree | 0d78b17efd2a759109abef0e8154a652f2f7f935 | |
| parent | 6fded6a0b7d595391245de4f0a81ce6724e3a893 (diff) | |
| download | gitlab-ce-e4011eb84527cb7fd46aa34e07a8cd33746c4a5a.tar.gz | |
Add latest changes from gitlab-org/gitlab@master
44 files changed, 256 insertions, 268 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index fb0a396446b..f83d8b11dce 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -1c364e717ce8fdc4a6603f7369756785c146c898 +ad76c4bd99833148140d5c08b7258363e5163b9c diff --git a/app/graphql/types/projects/service_type.rb b/app/graphql/types/projects/service_type.rb index 4a9e5dcbfe9..88b7b95aa57 100644 --- a/app/graphql/types/projects/service_type.rb +++ b/app/graphql/types/projects/service_type.rb @@ -10,9 +10,20 @@ module Types # https://gitlab.com/gitlab-org/gitlab/-/issues/213088 field :type, GraphQL::Types::String, null: true, description: 'Class name of the service.' + field :service_type, ::Types::Projects::ServiceTypeEnum, null: true, + description: 'Type of the service.' field :active, GraphQL::Types::Boolean, null: true, description: 'Indicates if the service is active.' + def type + enum = ::Types::Projects::ServiceTypeEnum.coerce_result(service_type, context) + enum.downcase.camelize + end + + def service_type + object.type + end + definition_methods do def resolve_type(object, context) if object.is_a?(::Integrations::Jira) diff --git a/app/graphql/types/projects/service_type_enum.rb b/app/graphql/types/projects/service_type_enum.rb index 84fd4fc6f4f..d0cecbfea49 100644 --- a/app/graphql/types/projects/service_type_enum.rb +++ b/app/graphql/types/projects/service_type_enum.rb @@ -8,7 +8,7 @@ module Types class << self private - def type_description(type) + def type_description(name, type) "#{type} type" end end @@ -16,8 +16,10 @@ module Types # This prepend must stay here because the dynamic block below depends on it. prepend_mod # rubocop: disable Cop/InjectEnterpriseEditionModule - ::Integration.available_integration_types(include_dev: false).each do |type| - value type.underscore.upcase, value: type, description: type_description(type) + ::Integration.available_integration_names(include_dev: false).each do |name| + type = "#{name.camelize}Service" + domain_value = Integration.integration_name_to_type(name) + value type.underscore.upcase, value: domain_value, description: type_description(name, type) end end end diff --git a/app/models/integration.rb b/app/models/integration.rb index 77b59446b8d..a5b5e238410 100644 --- a/app/models/integration.rb +++ b/app/models/integration.rb @@ -12,6 +12,11 @@ class Integration < ApplicationRecord include IgnorableColumns ignore_column :template, remove_with: '15.0', remove_after: '2022-04-22' + ignore_column :type, remove_with: '15.0', remove_after: '2022-04-22' + + UnknownType = Class.new(StandardError) + + self.inheritance_column = :type_new INTEGRATION_NAMES = %w[ asana assembla bamboo bugzilla buildkite campfire confluence custom_issue_tracker datadog discord @@ -44,7 +49,7 @@ class Integration < ApplicationRecord serialize :properties, JSON # rubocop:disable Cop/ActiveRecordSerialize - attribute :type, Gitlab::Integrations::StiType.new + alias_attribute :type, :type_new default_value_for :active, false default_value_for :alert_events, true @@ -79,9 +84,10 @@ class Integration < ApplicationRecord validate :validate_belongs_to_project_or_group scope :external_issue_trackers, -> { where(category: 'issue_tracker').active } - scope :external_wikis, -> { where(type: 'ExternalWikiService').active } + scope :by_name, ->(name) { by_type(integration_name_to_type(name)) } + scope :external_wikis, -> { by_name(:external_wiki).active } scope :active, -> { where(active: true) } - scope :by_type, -> (type) { where(type: type) } + scope :by_type, ->(type) { where(type: type) } # INTERNAL USE ONLY: use by_name instead scope :by_active_flag, -> (flag) { where(active: flag) } scope :inherit_from_id, -> (id) { where(inherit_from_id: id) } scope :with_default_settings, -> { where.not(inherit_from_id: nil) } @@ -231,7 +237,7 @@ class Integration < ApplicationRecord end # Returns a list of available integration types. - # Example: ["AsanaService", ...] + # Example: ["Integrations::Asana", ...] def self.available_integration_types(include_project_specific: true, include_dev: true) available_integration_names(include_project_specific: include_project_specific, include_dev: include_dev).map do integration_name_to_type(_1) @@ -239,22 +245,27 @@ class Integration < ApplicationRecord end # Returns the model for the given integration name. - # Example: "asana" => Integrations::Asana + # Example: :asana => Integrations::Asana def self.integration_name_to_model(name) type = integration_name_to_type(name) integration_type_to_model(type) end # Returns the STI type for the given integration name. - # Example: "asana" => "AsanaService" + # Example: "asana" => "Integrations::Asana" def self.integration_name_to_type(name) - "#{name}_service".camelize + name = name.to_s + if available_integration_names.exclude?(name) + Gitlab::ErrorTracking.track_and_raise_for_dev_exception(UnknownType.new(name.inspect)) + else + "Integrations::#{name.camelize}" + end end # Returns the model for the given STI type. - # Example: "AsanaService" => Integrations::Asana + # Example: "Integrations::Asana" => Integrations::Asana def self.integration_type_to_model(type) - Gitlab::Integrations::StiType.new.cast(type).constantize + type.constantize end private_class_method :integration_type_to_model @@ -303,7 +314,7 @@ class Integration < ApplicationRecord from_union([ active.where(instance: true), active.where(group_id: group_ids, inherit_from_id: nil) - ]).order(Arel.sql("type ASC, array_position(#{array}::bigint[], #{table_name}.group_id), instance DESC")).group_by(&:type).each do |type, records| + ]).order(Arel.sql("type_new ASC, array_position(#{array}::bigint[], #{table_name}.group_id), instance DESC")).group_by(&:type).each do |type, records| build_from_integration(records.first, association => scope.id).save end end @@ -380,8 +391,10 @@ class Integration < ApplicationRecord %w[active] end + # return a hash of columns => values suitable for passing to insert_all def to_integration_hash - as_json(methods: :type, except: %w[id instance project_id group_id]) + column = self.class.attribute_aliases.fetch('type', 'type') + as_json(except: %w[id instance project_id group_id]).merge(column => type) end def to_data_fields_hash diff --git a/config/feature_flags/development/roadmap_settings.yml b/config/feature_flags/development/roadmap_settings.yml deleted file mode 100644 index 78704a90d06..00000000000 --- a/config/feature_flags/development/roadmap_settings.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: roadmap_settings -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78626 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350830 -milestone: '14.8' -type: development -group: group::product planning -default_enabled: true diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 6758afc91c4..84acb220ac5 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -185,7 +185,7 @@ production: &base ## Reply by email # Allow users to comment on issues and merge requests by replying to notification emails. - # For documentation on how to set this up, see http://doc.gitlab.com/ce/administration/reply_by_email.html + # For documentation on how to set this up, see https://docs.gitlab.com/ee/administration/reply_by_email.html incoming_email: enabled: false diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 0adecbbafd9..97e3365bc47 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -8726,6 +8726,7 @@ An emoji awarded by a user. | Name | Type | Description | | ---- | ---- | ----------- | | <a id="baseserviceactive"></a>`active` | [`Boolean`](#boolean) | Indicates if the service is active. | +| <a id="baseserviceservicetype"></a>`serviceType` | [`ServiceType`](#servicetype) | Type of the service. | | <a id="baseservicetype"></a>`type` | [`String`](#string) | Class name of the service. | ### `Blob` @@ -12028,6 +12029,7 @@ Represents an iteration cadence. | Name | Type | Description | | ---- | ---- | ----------- | | <a id="jiraserviceactive"></a>`active` | [`Boolean`](#boolean) | Indicates if the service is active. | +| <a id="jiraserviceservicetype"></a>`serviceType` | [`ServiceType`](#servicetype) | Type of the service. | | <a id="jiraservicetype"></a>`type` | [`String`](#string) | Class name of the service. | #### Fields with arguments @@ -19284,6 +19286,7 @@ Implementations: | Name | Type | Description | | ---- | ---- | ----------- | | <a id="serviceactive"></a>`active` | [`Boolean`](#boolean) | Indicates if the service is active. | +| <a id="serviceservicetype"></a>`serviceType` | [`ServiceType`](#servicetype) | Type of the service. | | <a id="servicetype"></a>`type` | [`String`](#string) | Class name of the service. | #### `TimeboxReportInterface` diff --git a/doc/development/architecture.md b/doc/development/architecture.md index e8d04d68565..6ef81f04148 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -349,7 +349,7 @@ Component statuses are linked to configuration documentation for each component. | [GitLab Exporter](#gitlab-exporter) | Generates a variety of GitLab metrics | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | CE & EE | | [GitLab Geo Node](#gitlab-geo) | Geographically distributed GitLab nodes | ⚙ | ⚙ | ❌ | ❌ | ✅ | ❌ | ⚙ | EE Only | | [GitLab Pages](#gitlab-pages) | Hosts static websites | ⚙ | ⚙ | ❌ | ❌ | ✅ | ⚙ | ⚙ | CE & EE | -| [GitLab Agent](#gitlab-agent) | Integrate Kubernetes clusters in a cloud-native way | ⚙ | ⚙ | ⚙ | ❌ | ❌ | ⤓ | ⚙ | EE Only | +| [GitLab agent](#gitlab-agent) | Integrate Kubernetes clusters in a cloud-native way | ⚙ | ⚙ | ⚙ | ❌ | ❌ | ⤓ | ⚙ | EE Only | | [GitLab self-monitoring: Alertmanager](#alertmanager) | Deduplicates, groups, and routes alerts from Prometheus | ⚙ | ⚙ | ✅ | ⚙ | ✅ | ❌ | ❌ | CE & EE | | [GitLab self-monitoring: Grafana](#grafana) | Metrics dashboard | ✅ | ✅ | ⚙ | ⤓ | ✅ | ❌ | ⚙ | CE & EE | | [GitLab self-monitoring: Jaeger](#jaeger) | View traces generated by the GitLab instance | ❌ | ⚙ | ⚙ | ❌ | ❌ | ⤓ | ⚙ | CE & EE | @@ -499,14 +499,14 @@ Geo is a premium feature built to help speed up the development of distributed t GitLab Exporter is a process designed in house that allows us to export metrics about GitLab application internals to Prometheus. You can read more [in the project's README](https://gitlab.com/gitlab-org/gitlab-exporter). -#### GitLab Agent +#### GitLab agent - [Project page](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent) - Configuration: - [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) - [Charts](https://docs.gitlab.com/charts/charts/gitlab/kas/index.html) -The [GitLab Agent](../user/clusters/agent/index.md) is an active in-cluster +The [GitLab agent](../user/clusters/agent/index.md) is an active in-cluster component for solving GitLab and Kubernetes integration tasks in a secure and cloud-native way. diff --git a/doc/user/compliance/compliance_report/index.md b/doc/user/compliance/compliance_report/index.md index 215554769af..bd4bdb21f35 100644 --- a/doc/user/compliance/compliance_report/index.md +++ b/doc/user/compliance/compliance_report/index.md @@ -113,7 +113,7 @@ The remaining records are truncated when this limit is reached. FLAG: On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `compliance_violations_report`. -The feature is not ready for production use. +On GitLab.com, this feature is not available. This feature is not ready for production use. Merge request violations provide a view of all the [separation of duties](#approval-status-and-separation-of-duties) compliance violations that exist in projects in a specific group. For each separation of duties compliance violation, you can see: diff --git a/doc/user/group/index.md b/doc/user/group/index.md index 9d06314f295..86704f81c82 100644 --- a/doc/user/group/index.md +++ b/doc/user/group/index.md @@ -46,19 +46,16 @@ the immediate parent group. ### Namespaces -In GitLab, a namespace is a unique name and URL for a user, a group, or subgroup. - -- `http://gitlab.example.com/username` -- `http://gitlab.example.com/groupname` -- `http://gitlab.example.com/groupname/subgroup_name` +In GitLab, a namespace is a unique name for a user, a group, or subgroup under +which a project can be created. For example, consider a user named Alex: -1. Alex creates an account with the username `alex`: `https://gitlab.example.com/alex` -1. Alex creates a group for their team with the group name `alex-team`. - The group and its projects are available at: `https://gitlab.example.com/alex-team` -1. Alex creates a subgroup of `alex-team` with the subgroup name `marketing`. - The subgroup and its projects are available at: `https://gitlab.example.com/alex-team/marketing` +| GitLab URL | Namespace | +| ---------- | --------- | +| Alex creates an account with the username `alex`: `https://gitlab.example.com/alex`. | The namespace in this case is `alex`. | +| Alex creates a group for their team with the group name `alex-team`. The group and its projects are available at: `https://gitlab.example.com/alex-team`. | The namespace in this cases is `alex-team`. | +| Alex creates a subgroup of `alex-team` with the subgroup name `marketing`. The subgroup and its projects are available at: `https://gitlab.example.com/alex-team/marketing`. | The namespace in this case is `alex-team/marketing`. | ## Create a group diff --git a/doc/user/group/roadmap/img/epics_state_dropdown_v14_3.png b/doc/user/group/roadmap/img/epics_state_dropdown_v14_3.png Binary files differdeleted file mode 100644 index 171876e34a9..00000000000 --- a/doc/user/group/roadmap/img/epics_state_dropdown_v14_3.png +++ /dev/null diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md index 64cead7642f..89c5c6ed466 100644 --- a/doc/user/group/roadmap/index.md +++ b/doc/user/group/roadmap/index.md @@ -47,10 +47,6 @@ Filtering roadmaps by milestone might not be available to you. Check the **versi When you want to explore a roadmap, there are several ways to make it easier by sorting epics or filtering them by what's important for you. -A dropdown list lets you show only open or closed epics. By default, all epics are shown. - - - You can sort epics in the Roadmap view by: - Start date @@ -74,11 +70,8 @@ Roadmaps can also be [visualized inside an epic](../epics/index.md#roadmap-in-ep ### Roadmap settings -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345158) in GitLab 14.8 [with a flag](../../../administration/feature_flags.md) named `roadmap_settings`. Enabled by default. - -FLAG: -On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `roadmap_settings`. -On GitLab.com, this feature is available but can be configured by GitLab.com administrators only. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345158) in GitLab 14.8 [with a flag](../../../administration/feature_flags.md) named `roadmap_settings`. Enabled by default. +> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/350830) in GitLab 14.9. Feature flag `roadmap_settings`removed. When you enable the roadmap settings sidebar, you can use it to refine epics shown in the roadmap. diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md index 14c4447c5c6..d86bce3f8b6 100644 --- a/doc/user/group/saml_sso/index.md +++ b/doc/user/group/saml_sso/index.md @@ -214,6 +214,35 @@ we recommend the ["Use the OneLogin SAML Test Connector" documentation](https:// Recommended `NameID` value: `OneLogin ID`. +### Change the SAML app + +To change the SAML app used for sign in: + +- If the NameID is not identical in both the existing and new SAML apps, users must: + 1. [Unlink the current SAML identity](#unlinking-accounts). + 1. [Link their identity](#user-access-and-management) to the new SAML app. +- If the NameID is identical, no change is required. + +### Migrate to a different SAML provider + +You can migrate to a different SAML provider. During the migration process users will not be able to access any of the SAML groups. +To mitigate this, you can disable [SSO enforcement](#sso-enforcement). + +To migrate SAML providers: + +1. [Configure](#configure-your-identity-provider) the group with the new identity provider SAML app. +1. Ask users to [unlink their account from the group](#unlinking-accounts). +1. Ask users to [link their account to the new SAML app](#linking-saml-to-your-existing-gitlabcom-account). + +### Change email domains + +To migrate users to a new email domain, users must: + +1. Add their new email as the primary email to their accounts and verify it. +1. [Unlink their account from the group](#unlinking-accounts). +1. [Link their account to the group](#linking-saml-to-your-existing-gitlabcom-account). +1. (Optional) Remove their old email from the account. + ## User access and management > [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/268142) in GitLab 13.7. @@ -610,12 +639,6 @@ Alternatively, when users need to [link SAML to their existing GitLab.com accoun | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | As mentioned in the [NameID](#nameid) section, if the NameID changes for any user, the user can be locked out. This is a common problem when an email address is used as the identifier. | Follow the steps outlined in the ["SAML authentication failed: User has already been taken"](#message-saml-authentication-failed-user-has-already-been-taken) section. | -### I need to change my SAML app - -If the NameID is identical in both SAML apps, then no change is required. - -Otherwise, to change the SAML app used for sign in, users need to [unlink the current SAML identity](#unlinking-accounts) and then [link their identity](#user-access-and-management) to the new SAML app. - ### I need additional information to configure my identity provider Many SAML terms can vary between providers. It is possible that the information you are looking for is listed under another name. diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md index d1e9ba29378..546743e0174 100644 --- a/doc/user/group/saml_sso/scim_setup.md +++ b/doc/user/group/saml_sso/scim_setup.md @@ -244,7 +244,7 @@ It is important not to update these to incorrect values, since this causes users ### I need to change my SCIM app -Individual users can follow the instructions in the ["SAML authentication failed: User has already been taken"](index.md#i-need-to-change-my-saml-app) section. +Individual users can follow the instructions in the ["SAML authentication failed: User has already been taken"](index.md#change-the-saml-app) section. Alternatively, users can be removed from the SCIM app which de-links all removed users. Sync can then be turned on for the new SCIM app to [link existing users](#user-access-and-linking-setup). diff --git a/doc/user/infrastructure/clusters/connect/index.md b/doc/user/infrastructure/clusters/connect/index.md index 06d1307984d..004f4409919 100644 --- a/doc/user/infrastructure/clusters/connect/index.md +++ b/doc/user/infrastructure/clusters/connect/index.md @@ -8,10 +8,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w The [certificate-based Kubernetes integration with GitLab](../index.md) was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) -in GitLab 14.5. To connect your clusters, use the [GitLab Agent](../../../clusters/agent/index.md). +in GitLab 14.5. To connect your clusters, use the [GitLab agent](../../../clusters/agent/index.md). <!-- TBA: (We need to resolve https://gitlab.com/gitlab-org/gitlab/-/issues/343660 before adding this line) -If you don't have a cluster yet, create one and connect it to GitLab through the Agent. +If you don't have a cluster yet, create one and connect it to GitLab through the agent. You can also create a new cluster from GitLab using [Infrastructure as Code](../../iac/index.md#create-a-new-cluster-through-iac). --> diff --git a/doc/user/infrastructure/clusters/connect/new_eks_cluster.md b/doc/user/infrastructure/clusters/connect/new_eks_cluster.md index 9e613ed4f0d..87b8f510289 100644 --- a/doc/user/infrastructure/clusters/connect/new_eks_cluster.md +++ b/doc/user/infrastructure/clusters/connect/new_eks_cluster.md @@ -79,8 +79,8 @@ contains other variables that you can override according to your needs: - `TF_VAR_cluster_version`: Set the version of Kubernetes. - `TF_VAR_instance_type`: Set the instance type for the Kubernetes nodes. - `TF_VAR_instance_count`: Set the number of Kubernetes nodes. -- `TF_VAR_agent_version`: Set the version of the GitLab Agent. -- `TF_VAR_agent_namespace`: Set the Kubernetes namespace for the GitLab Agent. +- `TF_VAR_agent_version`: Set the version of the GitLab agent. +- `TF_VAR_agent_namespace`: Set the Kubernetes namespace for the GitLab agent. View the [AWS Terraform provider](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) and the [Kubernetes Terraform provider](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs) documentation for further resource options. diff --git a/doc/user/infrastructure/clusters/connect/new_gke_cluster.md b/doc/user/infrastructure/clusters/connect/new_gke_cluster.md index d1e3bd47b89..55fea5890b3 100644 --- a/doc/user/infrastructure/clusters/connect/new_gke_cluster.md +++ b/doc/user/infrastructure/clusters/connect/new_gke_cluster.md @@ -11,9 +11,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w WARNING: The process described on this page uses cluster certificates to connect the new cluster to GitLab, [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. -You can still create a cluster and then connect it to GitLab through the [Agent](../index.md). +You can still create a cluster and then connect it to GitLab through the [agent](../index.md). [An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/343660) -to migrate this functionality to the [Agent](../index.md). +to migrate this functionality to the [agent](../index.md). Learn how to create a new cluster on Google Kubernetes Engine (GKE) through [Infrastructure as Code (IaC)](../../index.md). diff --git a/doc/user/infrastructure/clusters/deploy/inventory_object.md b/doc/user/infrastructure/clusters/deploy/inventory_object.md index f23fae072f5..64955b2d2b6 100644 --- a/doc/user/infrastructure/clusters/deploy/inventory_object.md +++ b/doc/user/infrastructure/clusters/deploy/inventory_object.md @@ -9,10 +9,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332227) in GitLab 14.0. An inventory object is a `ConfigMap` object for keeping track of the set of objects applied to a cluster. -When you remove objects from a manifest repository, the Agent uses a corresponding inventory object to +When you remove objects from a manifest repository, the agent uses a corresponding inventory object to prune (delete) objects from the cluster. -The Agent creates an inventory object for each manifest project specified in the +The agent creates an inventory object for each manifest project specified in the `gitops.manifest_projects` configuration section. The inventory object has to be stored somewhere in the cluster. The default behavior is: @@ -20,10 +20,10 @@ The default behavior is: explicitly, the inventory object is stored in the `default` namespace. - The `name` is generated from the numeric project ID of the manifest project and the numeric agent ID. - This way, the Agent constructs the name and location where the inventory object is + This way, the agent constructs the name and location where the inventory object is stored in the cluster. -The Agent cannot locate the existing inventory object if you: +The agent cannot locate the existing inventory object if you: - Change `gitops.manifest_projects[].default_namespace` parameter. - Move manifests into another project. @@ -57,13 +57,13 @@ metadata: ## Using GitOps with pre-existing Kubernetes objects -The Agent treats manifest files in the manifest repository as the source of truth. When it applies +The agent treats manifest files in the manifest repository as the source of truth. When it applies objects from the files to the cluster, it tracks them in an inventory object. If an object already exists, -The Agent behaves differently based on the `gitops.manifest_projects[].inventory_policy` configuration. +The agent behaves differently based on the `gitops.manifest_projects[].inventory_policy` configuration. Check the table below with the available options and when to use them. `inventory_policy` value | Description | ------------------------ | ------------------------------------------------------------------------------------------- | `must_match` | This is the default policy. A live object must have the `config.k8s.io/owning-inventory` annotation set to the same value as the `cli-utils.sigs.k8s.io/inventory-id` label on the corresponding inventory object to be updated. Object is not updated and an error is reported if the values don't match or the object doesn't have the annotation. | `adopt_if_no_inventory` | This mode allows to "adopt" an object if it doesn't have the `config.k8s.io/owning-inventory` annotation. Use this mode if you want to start managing existing objects using the GitOps feature. Once all objects have been "adopted", we recommend you to put the setting back into the default `must_match` mode to avoid any unexpected adoptions. | -`adopt_all` | This mode allows to "adopt" an object even if it has the `config.k8s.io/owning-inventory` annotation set to a different value. This mode can be useful if you want to migrate a set of objects from one agent to another one or from some other tool to the Agent. Once all objects have been "adopted", we recommend you to put the setting back into the default `must_match` mode to avoid any unexpected adoptions. | +`adopt_all` | This mode allows to "adopt" an object even if it has the `config.k8s.io/owning-inventory` annotation set to a different value. This mode can be useful if you want to migrate a set of objects from one agent to another one or from some other tool to the agent. Once all objects have been "adopted", we recommend you to put the setting back into the default `must_match` mode to avoid any unexpected adoptions. | diff --git a/doc/user/instance/clusters/index.md b/doc/user/instance/clusters/index.md index a184f00f6f6..a5c1402b9ec 100644 --- a/doc/user/instance/clusters/index.md +++ b/doc/user/instance/clusters/index.md @@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w WARNING: This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. To connect clusters to GitLab, -use the [GitLab Agent](../../clusters/agent/index.md). +use the [GitLab agent](../../clusters/agent/index.md). Similar to [project-level](../../project/clusters/index.md) and [group-level](../../group/clusters/index.md) Kubernetes clusters, diff --git a/doc/user/project/clusters/add_eks_clusters.md b/doc/user/project/clusters/add_eks_clusters.md index 023ffed3d81..82106c9d1a9 100644 --- a/doc/user/project/clusters/add_eks_clusters.md +++ b/doc/user/project/clusters/add_eks_clusters.md @@ -19,7 +19,7 @@ Kubernetes Service (EKS). ## Connect an existing EKS cluster If you already have an EKS cluster and want to connect it to GitLab, -use the [GitLab Agent](../../clusters/agent/index.md). +use the [GitLab agent](../../clusters/agent/index.md). ## Create a new EKS cluster diff --git a/doc/user/project/clusters/add_existing_cluster.md b/doc/user/project/clusters/add_existing_cluster.md index 0c3827bcbb1..8e060bc98ad 100644 --- a/doc/user/project/clusters/add_existing_cluster.md +++ b/doc/user/project/clusters/add_existing_cluster.md @@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w WARNING: This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. -To connect your cluster to GitLab, use the [GitLab Agent](../../clusters/agent/index.md) +To connect your cluster to GitLab, use the [GitLab agent](../../clusters/agent/index.md) instead. If you have an existing Kubernetes cluster, you can add it to a project, group, diff --git a/doc/user/project/clusters/add_gke_clusters.md b/doc/user/project/clusters/add_gke_clusters.md index 99edddeb3e9..cb8d04e0e28 100644 --- a/doc/user/project/clusters/add_gke_clusters.md +++ b/doc/user/project/clusters/add_gke_clusters.md @@ -19,7 +19,7 @@ hosted on Google Kubernetes Engine (GKE). ## Connect an existing GKE cluster If you already have a GKE cluster and want to connect it to GitLab, -use the [GitLab Agent](../../clusters/agent/index.md). +use the [GitLab agent](../../clusters/agent/index.md). ## Create a new GKE cluster from GitLab diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md index 6c0f319de67..a4f6dc325c8 100644 --- a/doc/user/project/clusters/add_remove_clusters.md +++ b/doc/user/project/clusters/add_remove_clusters.md @@ -49,7 +49,7 @@ supports connecting existing clusters using the certificate-based connection met ## Add existing cluster -As of GitLab 14.0, use the [GitLab Agent](../../clusters/agent/index.md) +As of GitLab 14.0, use the [GitLab agent](../../clusters/agent/index.md) to connect your cluster to GitLab. Alternatively, you can [add an existing cluster](add_existing_cluster.md) @@ -57,7 +57,7 @@ through the certificate-based method, but we don't recommend using this method f ## Configure your cluster -As of GitLab 14.0, use the [GitLab Agent](../../clusters/agent/index.md) +As of GitLab 14.0, use the [GitLab agent](../../clusters/agent/index.md) to configure your cluster. ## Disable a cluster diff --git a/doc/user/project/clusters/cluster_access.md b/doc/user/project/clusters/cluster_access.md index 4e00ae0dd07..8ff0a275649 100644 --- a/doc/user/project/clusters/cluster_access.md +++ b/doc/user/project/clusters/cluster_access.md @@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w WARNING: This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. -To connect your cluster to GitLab, use the [GitLab Agent](../../clusters/agent/index.md) +To connect your cluster to GitLab, use the [GitLab agent](../../clusters/agent/index.md) instead. When creating a cluster in GitLab, you are asked if you would like to create either: diff --git a/doc/user/project/clusters/deploy_to_cluster.md b/doc/user/project/clusters/deploy_to_cluster.md index e89ce12b35e..07edaa927a5 100644 --- a/doc/user/project/clusters/deploy_to_cluster.md +++ b/doc/user/project/clusters/deploy_to_cluster.md @@ -10,8 +10,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w WARNING: This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. -To connect your cluster to GitLab, use the [GitLab Agent](../../clusters/agent/index.md). -To deploy with the Agent, use the [CI/CD Tunnel](../../clusters/agent/ci_cd_tunnel.md). +To connect your cluster to GitLab, use the [GitLab agent](../../clusters/agent/index.md). +To deploy with the agent, use the [CI/CD workflow](../../clusters/agent/ci_cd_tunnel.md). A Kubernetes cluster can be the destination for a deployment job. If diff --git a/doc/user/project/clusters/gitlab_managed_clusters.md b/doc/user/project/clusters/gitlab_managed_clusters.md index 686b3026b2c..9c5cc14f720 100644 --- a/doc/user/project/clusters/gitlab_managed_clusters.md +++ b/doc/user/project/clusters/gitlab_managed_clusters.md @@ -12,7 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w WARNING: This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. -To connect your cluster to GitLab, use the [GitLab Agent](../../../user/clusters/agent/index.md). +To connect your cluster to GitLab, use the [GitLab agent](../../../user/clusters/agent/index.md). To manage applications, use the [Cluster Project Management Template](../../../user/clusters/management_project_template.md). You can choose to allow GitLab to manage your cluster for you. If your cluster diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md index dc37060593c..f89d863e83b 100644 --- a/doc/user/project/clusters/index.md +++ b/doc/user/project/clusters/index.md @@ -12,7 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w WARNING: This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. To connect clusters to GitLab, use the -[GitLab Agent](../../clusters/agent/index.md). +[GitLab agent](../../clusters/agent/index.md). [Project-level](../../infrastructure/clusters/connect/index.md#cluster-levels-deprecated) Kubernetes clusters allow you to connect a Kubernetes cluster to a project in GitLab. diff --git a/doc/user/project/clusters/multiple_kubernetes_clusters.md b/doc/user/project/clusters/multiple_kubernetes_clusters.md index a56eaa9b953..149df5248c8 100644 --- a/doc/user/project/clusters/multiple_kubernetes_clusters.md +++ b/doc/user/project/clusters/multiple_kubernetes_clusters.md @@ -13,7 +13,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w WARNING: Using multiple Kubernetes clusters for a single project **with cluster certificates** was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. -To connect clusters to GitLab, use the [GitLab Agent](../../../user/clusters/agent/index.md). +To connect clusters to GitLab, use the [GitLab agent](../../../user/clusters/agent/index.md). You can associate more than one Kubernetes cluster to your project. That way you can have different clusters for different environments, diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md index 15490ab0b94..af03db14ee9 100644 --- a/doc/user/project/deploy_boards.md +++ b/doc/user/project/deploy_boards.md @@ -20,7 +20,7 @@ type: howto, reference WARNING: This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. [An epic exists](https://gitlab.com/groups/gitlab-org/-/epics/2493) -to add this functionality to the [Agent](../index.md). +to add this functionality to the [agent](../index.md). GitLab deploy boards offer a consolidated view of the current health and status of each CI [environment](../../ci/environments/index.md) running on [Kubernetes](https://kubernetes.io), displaying the status diff --git a/locale/gitlab.pot b/locale/gitlab.pot index e6295df5513..79632484c7f 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -3519,9 +3519,6 @@ msgstr "" msgid "All environments" msgstr "" -msgid "All epics" -msgstr "" - msgid "All groups and projects" msgstr "" @@ -7576,9 +7573,6 @@ msgstr "" msgid "Closed MRs" msgstr "" -msgid "Closed epics" -msgstr "" - msgid "Closed issues" msgstr "" @@ -25608,9 +25602,6 @@ msgstr "" msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command." msgstr "" -msgid "Open epics" -msgstr "" - msgid "Open errors" msgstr "" @@ -29885,9 +29876,6 @@ msgstr "" msgid "QualitySummary|Project quality" msgstr "" -msgid "Quarters" -msgstr "" - msgid "Query" msgstr "" diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb index 96e85139e78..a7d2fb4ad2a 100644 --- a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb @@ -2,7 +2,11 @@ module QA RSpec.describe 'Create' do - describe 'Open a fork in Web IDE' do + describe 'Open a fork in Web IDE', quarantine: { + only: { subdomain: %i[canary production] }, + issue: "https://gitlab.com/gitlab-org/gitlab/-/issues/347247", + type: :flaky + } do let(:parent_project) do Resource::Project.fabricate_via_api! do |project| project.name = 'parent-project' diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb index 6293c69de70..674c71935ec 100644 --- a/spec/factories/integrations.rb +++ b/spec/factories/integrations.rb @@ -12,6 +12,16 @@ FactoryBot.define do issue_tracker end + factory :jenkins_integration, class: 'Integrations::Jenkins' do + project + active { true } + type { 'Integrations::Jenkins' } + jenkins_url { 'http://jenkins.example.com/' } + project_name { 'my-project' } + username { 'jenkings-user' } + password { 'passw0rd' } + end + factory :datadog_integration, class: 'Integrations::Datadog' do project active { true } @@ -20,7 +30,7 @@ FactoryBot.define do factory :emails_on_push_integration, class: 'Integrations::EmailsOnPush' do project - type { 'EmailsOnPushService' } + type { 'Integrations::EmailsOnPush' } active { true } push_events { true } tag_push_events { true } @@ -54,7 +64,7 @@ FactoryBot.define do factory :jira_integration, class: 'Integrations::Jira' do project active { true } - type { 'JiraService' } + type { 'Integrations::Jira' } transient do create_data { true } @@ -88,7 +98,7 @@ FactoryBot.define do factory :zentao_integration, class: 'Integrations::Zentao' do project active { true } - type { 'ZentaoService' } + type { 'Integrations::Zentao' } transient do create_data { true } @@ -167,7 +177,7 @@ FactoryBot.define do factory :external_wiki_integration, class: 'Integrations::ExternalWiki' do project - type { 'ExternalWikiService' } + type { 'Integrations::ExternalWiki' } active { true } external_wiki_url { 'http://external-wiki-url.com' } end @@ -178,24 +188,39 @@ FactoryBot.define do password { 'my-secret-password' } end + trait :chat_notification do + webhook { 'https://example.com/webhook' } + end + + trait :inactive do + active { false } + end + + factory :mattermost_integration, class: 'Integrations::Mattermost' do + chat_notification + project + type { 'Integrations::Mattermost' } + active { true } + end + # avoids conflict with slack_integration factory factory :integrations_slack, class: 'Integrations::Slack' do + chat_notification project active { true } - webhook { 'https://slack.service.url' } - type { 'SlackService' } + type { 'Integrations::Slack' } end factory :slack_slash_commands_integration, class: 'Integrations::SlackSlashCommands' do project active { true } - type { 'SlackSlashCommandsService' } + type { 'Integrations::SlackSlashCommands' } end factory :pipelines_email_integration, class: 'Integrations::PipelinesEmail' do project active { true } - type { 'PipelinesEmailService' } + type { 'Integrations::PipelinesEmail' } recipients { 'test@example.com' } end diff --git a/spec/factories/usage_data.rb b/spec/factories/usage_data.rb index 86799af1719..316e0c2b8d6 100644 --- a/spec/factories/usage_data.rb +++ b/spec/factories/usage_data.rb @@ -5,8 +5,7 @@ FactoryBot.define do skip_create # non-model factories (i.e. without #save) initialize_with do - projects = create_list(:project, 3) - projects << create(:project, :repository) + projects = create_list(:project, 4, :repository) group = create(:group) create(:board, project: projects[0]) create(:jira_integration, project: projects[0]) @@ -19,16 +18,21 @@ FactoryBot.define do create(:jira_import_state, :finished, project: projects[1], label: jira_label, imported_issues_count: 3) create(:jira_import_state, :scheduled, project: projects[1], label: jira_label) create(:prometheus_integration, project: projects[1]) - create(:integration, project: projects[1], type: 'JenkinsService', active: true) - create(:integration, project: projects[0], type: 'SlackSlashCommandsService', active: true) - create(:integration, project: projects[1], type: 'SlackService', active: true) - create(:integration, project: projects[2], type: 'SlackService', active: true) - create(:integration, project: projects[2], type: 'MattermostService', active: false) - create(:integration, group: group, project: nil, type: 'MattermostService', active: true) - mattermost_instance = create(:integration, :instance, type: 'MattermostService', active: true) - create(:integration, project: projects[1], type: 'MattermostService', active: true, inherit_from_id: mattermost_instance.id) - create(:integration, group: group, project: nil, type: 'SlackService', active: true, inherit_from_id: mattermost_instance.id) - create(:integration, project: projects[2], type: 'CustomIssueTrackerService', active: true) + create(:jenkins_integration, project: projects[1]) + + # slack + create(:slack_slash_commands_integration, project: projects[0]) + create(:integrations_slack, project: projects[1]) + create(:integrations_slack, project: projects[2]) + + # mattermost + create(:mattermost_integration, project: projects[2], active: false) + create(:mattermost_integration, group: group, project: nil) + mattermost_instance = create(:mattermost_integration, :instance) + create(:mattermost_integration, project: projects[1], inherit_from_id: mattermost_instance.id) + create(:integrations_slack, group: group, project: nil, active: true, inherit_from_id: mattermost_instance.id) + + create(:custom_issue_tracker_integration, project: projects[2], active: true) create(:project_error_tracking_setting, project: projects[0]) create(:project_error_tracking_setting, project: projects[1], enabled: false) alert_bot_issues = create_list(:incident, 2, project: projects[0], author: User.alert_bot) diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index 872507c3b7a..27f7c699c50 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -96,10 +96,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do context 'view merge request with external CI service' do before do - create(:integration, project: project, - active: true, - type: 'DroneCiService', - category: 'ci') + create(:drone_ci_integration, project: project) visit project_merge_request_path(project, merge_request) end diff --git a/spec/graphql/types/projects/base_service_type_spec.rb b/spec/graphql/types/projects/base_service_type_spec.rb index 423cea860d7..43a680bc9c2 100644 --- a/spec/graphql/types/projects/base_service_type_spec.rb +++ b/spec/graphql/types/projects/base_service_type_spec.rb @@ -6,7 +6,7 @@ RSpec.describe GitlabSchema.types['BaseService'] do specify { expect(described_class.graphql_name).to eq('BaseService') } it 'has basic expected fields' do - expect(described_class).to have_graphql_fields(:type, :active) + expect(described_class).to have_graphql_fields(:type, :active, :service_type) end specify { expect(described_class).to require_graphql_authorizations(:admin_project) } diff --git a/spec/graphql/types/projects/jira_service_type_spec.rb b/spec/graphql/types/projects/jira_service_type_spec.rb index 9db580ac963..69cdcb0f46f 100644 --- a/spec/graphql/types/projects/jira_service_type_spec.rb +++ b/spec/graphql/types/projects/jira_service_type_spec.rb @@ -6,7 +6,7 @@ RSpec.describe GitlabSchema.types['JiraService'] do specify { expect(described_class.graphql_name).to eq('JiraService') } it 'has basic expected fields' do - expect(described_class).to have_graphql_fields(:type, :active, :projects) + expect(described_class).to have_graphql_fields(:type, :active, :projects, :service_type) end specify { expect(described_class).to require_graphql_authorizations(:admin_project) } diff --git a/spec/graphql/types/projects/service_type_enum_spec.rb b/spec/graphql/types/projects/service_type_enum_spec.rb index 00427e1d580..ead69e60f6c 100644 --- a/spec/graphql/types/projects/service_type_enum_spec.rb +++ b/spec/graphql/types/projects/service_type_enum_spec.rb @@ -4,10 +4,52 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['ServiceType'] do it 'exposes all the existing project services' do - expect(described_class.values.keys).to match_array(available_services_enum) + expect(described_class.values.keys).to include(*core_service_enums) end - def available_services_enum - ::Integration.available_integration_types(include_dev: false).map(&:underscore).map(&:upcase) + def core_service_enums + %w[ + ASANA_SERVICE + ASSEMBLA_SERVICE + BAMBOO_SERVICE + BUGZILLA_SERVICE + BUILDKITE_SERVICE + CAMPFIRE_SERVICE + CONFLUENCE_SERVICE + CUSTOM_ISSUE_TRACKER_SERVICE + DATADOG_SERVICE + DISCORD_SERVICE + DRONE_CI_SERVICE + EMAILS_ON_PUSH_SERVICE + EWM_SERVICE + EXTERNAL_WIKI_SERVICE + FLOWDOCK_SERVICE + HANGOUTS_CHAT_SERVICE + IRKER_SERVICE + JENKINS_SERVICE + JIRA_SERVICE + MATTERMOST_SERVICE + MATTERMOST_SLASH_COMMANDS_SERVICE + MICROSOFT_TEAMS_SERVICE + PACKAGIST_SERVICE + PIPELINES_EMAIL_SERVICE + PIVOTALTRACKER_SERVICE + PROMETHEUS_SERVICE + PUSHOVER_SERVICE + REDMINE_SERVICE + SHIMO_SERVICE + SLACK_SERVICE + SLACK_SLASH_COMMANDS_SERVICE + TEAMCITY_SERVICE + UNIFY_CIRCUIT_SERVICE + WEBEX_TEAMS_SERVICE + YOUTRACK_SERVICE + ZENTAO_SERVICE + ] + end + + it 'coerces values correctly' do + integration = build(:jenkins_integration) + expect(described_class.coerce_isolated_result(integration.type)).to eq 'JENKINS_SERVICE' end end diff --git a/spec/graphql/types/projects/service_type_spec.rb b/spec/graphql/types/projects/service_type_spec.rb index 0bffdfd629d..1a6a128544e 100644 --- a/spec/graphql/types/projects/service_type_spec.rb +++ b/spec/graphql/types/projects/service_type_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe Types::Projects::ServiceType do - specify { expect(described_class).to have_graphql_fields(:type, :active) } + specify { expect(described_class).to have_graphql_fields(:type, :service_type, :active) } describe ".resolve_type" do it 'resolves the corresponding type for objects' do diff --git a/spec/lib/gitlab/integrations/sti_type_spec.rb b/spec/lib/gitlab/integrations/sti_type_spec.rb deleted file mode 100644 index d3205fa8742..00000000000 --- a/spec/lib/gitlab/integrations/sti_type_spec.rb +++ /dev/null @@ -1,114 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::Integrations::StiType do - let(:types) { ['AsanaService', 'Integrations::Asana', Integrations::Asana] } - - describe '#serialize' do - context 'SQL SELECT' do - let(:expected_sql) do - <<~SQL.strip - FROM "integrations" WHERE "integrations"."type" = 'AsanaService' - SQL - end - - it 'forms SQL SELECT statements correctly' do - sql_statements = types.map do |type| - Integration.where(type: type).to_sql - end - - expect(sql_statements).to all(end_with(expected_sql)) - end - end - - context 'SQL CREATE' do - let(:expected_sql) do - <<~SQL.strip - INSERT INTO "integrations" ("type") VALUES ('AsanaService') - SQL - end - - it 'forms SQL CREATE statements correctly' do - sql_statements = types.map do |type| - record = ActiveRecord::QueryRecorder.new { Integration.insert({ type: type }) } - record.log.first - end - - expect(sql_statements).to all(include(expected_sql)) - end - end - - context 'SQL UPDATE' do - let(:expected_sql) do - <<~SQL.strip - UPDATE "integrations" SET "type" = 'AsanaService' - SQL - end - - let_it_be(:integration) { create(:integration) } - - it 'forms SQL UPDATE statements correctly' do - sql_statements = types.map do |type| - record = ActiveRecord::QueryRecorder.new { integration.update_column(:type, type) } - record.log.first - end - - expect(sql_statements).to all(include(expected_sql)) - end - end - - context 'SQL DELETE' do - let(:expected_sql) do - <<~SQL.strip - DELETE FROM "integrations" WHERE "integrations"."type" = 'AsanaService' - SQL - end - - it 'forms SQL DELETE statements correctly' do - sql_statements = types.map do |type| - record = ActiveRecord::QueryRecorder.new { Integration.delete_by(type: type) } - record.log.first - end - - expect(sql_statements).to all(match(expected_sql)) - end - end - end - - describe '#deserialize' do - specify 'it deserializes type correctly', :aggregate_failures do - types.each do |type| - service = create(:integration, type: type) - - expect(service.type).to eq('AsanaService') - end - end - end - - describe '#cast' do - it 'casts type as model correctly', :aggregate_failures do - create(:integration, type: 'AsanaService') - - types.each do |type| - expect(Integration.find_by(type: type)).to be_kind_of(Integrations::Asana) - end - end - end - - describe '#changed?' do - it 'detects changes correctly', :aggregate_failures do - service = create(:integration, type: 'AsanaService') - - types.each do |type| - service.type = type - - expect(service).not_to be_changed - end - - service.type = 'NewType' - - expect(service).to be_changed - end - end -end diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb index d34c0e46008..b8f75e8595e 100644 --- a/spec/models/integration_spec.rb +++ b/spec/models/integration_spec.rb @@ -85,14 +85,14 @@ RSpec.describe Integration do subject { described_class.by_type(type) } - context 'when type is "JiraService"' do - let(:type) { 'JiraService' } + context 'when type is "Integrations::JiraService"' do + let(:type) { 'Integrations::Jira' } it { is_expected.to match_array([integration1, integration2]) } end - context 'when type is "RedmineService"' do - let(:type) { 'RedmineService' } + context 'when type is "Integrations::Redmine"' do + let(:type) { 'Integrations::Redmine' } it { is_expected.to match_array([integration3]) } end @@ -103,7 +103,7 @@ RSpec.describe Integration do let!(:integration2) { create(:jira_integration) } it 'returns the right group integration' do - expect(described_class.for_group(group)).to match_array([integration1]) + expect(described_class.for_group(group)).to contain_exactly(integration1) end end @@ -376,22 +376,24 @@ RSpec.describe Integration do let_it_be(:instance_integration) { create(:jira_integration, :instance) } it 'returns the instance integration' do - expect(described_class.default_integration('JiraService', project)).to eq(instance_integration) + expect(described_class.default_integration('Integrations::Jira', project)).to eq(instance_integration) end it 'returns nil for nonexistent integration type' do - expect(described_class.default_integration('HipchatService', project)).to eq(nil) + expect(described_class.default_integration('Integrations::Hipchat', project)).to eq(nil) end context 'with a group integration' do + let(:integration_name) { 'Integrations::Jira' } + let_it_be(:group_integration) { create(:jira_integration, group_id: group.id, project_id: nil) } it 'returns the group integration for a project' do - expect(described_class.default_integration('JiraService', project)).to eq(group_integration) + expect(described_class.default_integration(integration_name, project)).to eq(group_integration) end it 'returns the instance integration for a group' do - expect(described_class.default_integration('JiraService', group)).to eq(instance_integration) + expect(described_class.default_integration(integration_name, group)).to eq(instance_integration) end context 'with a subgroup' do @@ -400,18 +402,18 @@ RSpec.describe Integration do let!(:project) { create(:project, group: subgroup) } it 'returns the closest group integration for a project' do - expect(described_class.default_integration('JiraService', project)).to eq(group_integration) + expect(described_class.default_integration(integration_name, project)).to eq(group_integration) end it 'returns the closest group integration for a subgroup' do - expect(described_class.default_integration('JiraService', subgroup)).to eq(group_integration) + expect(described_class.default_integration(integration_name, subgroup)).to eq(group_integration) end context 'having a integration with custom settings' do let!(:subgroup_integration) { create(:jira_integration, group_id: subgroup.id, project_id: nil) } it 'returns the closest group integration for a project' do - expect(described_class.default_integration('JiraService', project)).to eq(subgroup_integration) + expect(described_class.default_integration(integration_name, project)).to eq(subgroup_integration) end end @@ -419,7 +421,7 @@ RSpec.describe Integration do let!(:subgroup_integration) { create(:jira_integration, group_id: subgroup.id, project_id: nil, inherit_from_id: group_integration.id) } it 'returns the closest group integration which does not inherit from its parent for a project' do - expect(described_class.default_integration('JiraService', project)).to eq(group_integration) + expect(described_class.default_integration(integration_name, project)).to eq(group_integration) end end end @@ -556,19 +558,26 @@ RSpec.describe Integration do end end - describe '.integration_name_to_model' do - it 'returns the model for the given integration name' do - expect(described_class.integration_name_to_model('asana')).to eq(Integrations::Asana) + describe '.integration_name_to_type' do + it 'handles a simple case' do + expect(described_class.integration_name_to_type(:asana)).to eq 'Integrations::Asana' end - it 'raises an error if integration name is invalid' do - expect { described_class.integration_name_to_model('foo') }.to raise_exception(NameError, /uninitialized constant FooService/) + it 'raises an error if the name is unknown' do + expect { described_class.integration_name_to_type('foo') } + .to raise_exception(described_class::UnknownType, /foo/) + end + + it 'handles all available_integration_names' do + types = described_class.available_integration_names.map { described_class.integration_name_to_type(_1) } + + expect(types).to all(start_with('Integrations::')) end end - describe '.integration_name_to_type' do - it 'transforms the name to a type' do - expect(described_class.integration_name_to_type('asana')).to eq('AsanaService') + describe '.integration_name_to_model' do + it 'raises an error if integration name is invalid' do + expect { described_class.integration_name_to_model('foo') }.to raise_exception(described_class::UnknownType, /foo/) end end diff --git a/spec/models/integrations/slack_spec.rb b/spec/models/integrations/slack_spec.rb index 4661d9c8291..9f69f4f51f8 100644 --- a/spec/models/integrations/slack_spec.rb +++ b/spec/models/integrations/slack_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Integrations::Slack do describe '#execute' do before do - stub_request(:post, "https://slack.service.url/") + stub_request(:post, slack_integration.webhook) end let_it_be(:slack_integration) { create(:integrations_slack, branches_to_be_notified: 'all') } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 0248f55bd6e..f53bb4604e2 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1470,7 +1470,7 @@ RSpec.describe Project, factory_default: :keep do context 'when there is an active external issue tracker integration' do let!(:integration) do - create(:integration, project: project, type: 'JiraService', category: 'issue_tracker', active: true) + create(:jira_integration, project: project, category: 'issue_tracker') end specify { is_expected.to eq(true) } @@ -1489,7 +1489,7 @@ RSpec.describe Project, factory_default: :keep do context 'when there are two active external issue tracker integrations' do let_it_be(:second_integration) do - create(:integration, project: project, type: 'CustomIssueTracker', category: 'issue_tracker', active: true) + create(:custom_issue_tracker_integration, project: project, category: 'issue_tracker') end it 'does not become false when external issue tracker integration is destroyed' do diff --git a/spec/requests/api/graphql/project/jira_service_spec.rb b/spec/requests/api/graphql/project/jira_service_spec.rb index 64e9e04ae44..d6abe94b873 100644 --- a/spec/requests/api/graphql/project/jira_service_spec.rb +++ b/spec/requests/api/graphql/project/jira_service_spec.rb @@ -16,6 +16,7 @@ RSpec.describe 'query Jira service' do services(active: true, type: JIRA_SERVICE) { nodes { type + serviceType } } } @@ -23,7 +24,7 @@ RSpec.describe 'query Jira service' do ) end - let(:services) { graphql_data.dig('project', 'services', 'nodes')} + let(:services) { graphql_data.dig('project', 'services', 'nodes') } it_behaves_like 'unauthorized users cannot read services' @@ -35,10 +36,8 @@ RSpec.describe 'query Jira service' do it_behaves_like 'a working graphql query' - it 'retuns list of jira imports' do - service = services.first - - expect(service['type']).to eq('JiraService') + it 'returns list of jira integrations' do + expect(services).to contain_exactly({ 'type' => 'JiraService', 'serviceType' => 'JIRA_SERVICE' }) end end end diff --git a/spec/workers/deployments/hooks_worker_spec.rb b/spec/workers/deployments/hooks_worker_spec.rb index 50ead66cfbf..29b3e8d3ee4 100644 --- a/spec/workers/deployments/hooks_worker_spec.rb +++ b/spec/workers/deployments/hooks_worker_spec.rb @@ -13,7 +13,7 @@ RSpec.describe Deployments::HooksWorker do it 'executes project services for deployment_hooks' do deployment = create(:deployment, :running) project = deployment.project - service = create(:integration, type: 'SlackService', project: project, deployment_events: true, active: true) + service = create(:integrations_slack, project: project, deployment_events: true) expect(ProjectServiceWorker).to receive(:perform_async).with(service.id, an_instance_of(Hash)) @@ -23,7 +23,7 @@ RSpec.describe Deployments::HooksWorker do it 'does not execute an inactive service' do deployment = create(:deployment, :running) project = deployment.project - create(:integration, type: 'SlackService', project: project, deployment_events: true, active: false) + create(:integrations_slack, project: project, deployment_events: true, active: false) expect(ProjectServiceWorker).not_to receive(:perform_async) |
