diff --git a/app/controllers/concerns/integrations/params.rb b/app/controllers/concerns/integrations/params.rb index e344e0dcd8cb5cb6f675420847060091c787de68..d71ab98c3fde9c709ccf3c1c4776fa30a1755966 100644 --- a/app/controllers/concerns/integrations/params.rb +++ b/app/controllers/concerns/integrations/params.rb @@ -38,6 +38,9 @@ module Params :default_irc_uri, :device, :disable_diffs, + :diffblue_access_token_name, + :diffblue_access_token_secret, + :diffblue_license_key, :drone_url, :enable_ssl_verification, :external_wiki_url, diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 2318554855414c515cdb712ba6e9aa85ee3750e2..a96a4f8d76d06f97b876f771d543ff6e412ccc28 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -100,6 +100,7 @@ class Build < Ci::Processable delegate :harbor_integration, to: :project delegate :apple_app_store_integration, to: :project delegate :google_play_integration, to: :project + delegate :diffblue_cover_integration, to: :project delegate :trigger_short_token, to: :trigger_request, allow_nil: true delegate :ensure_persistent_ref, to: :pipeline delegate :enable_debug_trace!, to: :metadata @@ -518,6 +519,7 @@ def persisted_variables .concat(harbor_variables) .concat(apple_app_store_variables) .concat(google_play_variables) + .concat(diffblue_cover_variables) end end @@ -570,6 +572,12 @@ def google_play_variables Gitlab::Ci::Variables::Collection.new(google_play_integration.ci_variables(protected_ref: pipeline.protected_ref?)) end + def diffblue_cover_variables + return [] unless diffblue_cover_integration.try(:activated?) + + Gitlab::Ci::Variables::Collection.new(diffblue_cover_integration.ci_variables) + end + def features { trace_sections: true, diff --git a/app/models/integration.rb b/app/models/integration.rb index cd7350b2549c274b57d8d8482c2c5f5cb656bc3c..8ebf24b1663b579fab69d3916d94964efa5ac981 100644 --- a/app/models/integration.rb +++ b/app/models/integration.rb @@ -19,8 +19,8 @@ class Integration < ApplicationRecord self.inheritance_column = :type_new INTEGRATION_NAMES = %w[ - asana assembla bamboo bugzilla buildkite campfire clickup confluence custom_issue_tracker datadog discord - drone_ci emails_on_push ewm external_wiki hangouts_chat harbor irker jira + asana assembla bamboo bugzilla buildkite campfire clickup confluence custom_issue_tracker + datadog diffblue_cover discord drone_ci emails_on_push ewm external_wiki hangouts_chat harbor irker jira mattermost mattermost_slash_commands microsoft_teams packagist pipelines_email pivotaltracker prometheus pumble pushover redmine slack slack_slash_commands squash_tm teamcity telegram unify_circuit webex_teams youtrack zentao diff --git a/app/models/integrations/diffblue_cover.rb b/app/models/integrations/diffblue_cover.rb new file mode 100644 index 0000000000000000000000000000000000000000..888aa9a5ffdc42a09fd7fb0cf5a698c8f74d2883 --- /dev/null +++ b/app/models/integrations/diffblue_cover.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true + +module Integrations + class DiffblueCover < Integration + field :diffblue_license_key, + section: SECTION_TYPE_CONNECTION, + type: :password, + title: -> { s_('DiffblueCover|License key') }, + description: -> { s_('DiffblueCover|Diffblue Cover license key') }, + non_empty_password_title: -> { s_('DiffblueCover|License key') }, + non_empty_password_help: -> { + s_( + 'DiffblueCover|Leave blank to use your current license key.' + ) + }, + exposes_secrets: true, + required: true, + is_secret: true, + placeholder: 'XXXX-XXXX-XXXX-XXXX', + help: -> { + format( + s_( + 'DiffblueCover|Enter your Diffblue Cover license key or ' \ + 'visit %{diffblue_link} to obtain a free trial license.' + ), + diffblue_link: diffblue_link + ) + } + + field :diffblue_access_token_name, + section: SECTION_TYPE_CONFIGURATION, + title: -> { s_('DiffblueCover|Name') }, + description: -> { s_('DiffblueCover|Access token name used by Diffblue Cover in pipelines') }, + required: true, + placeholder: -> { s_('DiffblueCover|My token name') } + + field :diffblue_access_token_secret, + section: SECTION_TYPE_CONFIGURATION, + type: :password, + title: -> { s_('DiffblueCover|Secret') }, + description: -> { s_('DiffblueCover|Access token secret used by Diffblue Cover in pipelines') }, + non_empty_password_title: -> { s_('DiffblueCover|Secret') }, + non_empty_password_help: -> { s_('DiffblueCover|Leave blank to use your current secret value.') }, + required: true, + is_secret: true, + placeholder: 'glpat-XXXXXXXXXXXXXXXXXXXX' # gitleaks:allow + + with_options if: :activated? do + validates :diffblue_license_key, presence: true + validates :diffblue_access_token_name, presence: true + validates :diffblue_access_token_secret, presence: true + end + + def self.title + 'Diffblue Cover' + end + + def self.description + s_('DiffblueCover|Automatically write comprehensive, human-like Java unit tests.') + end + + def self.to_param + 'diffblue_cover' + end + + def self.help + s_('DiffblueCover|Automatically write comprehensive, human-like Java unit tests.') + end + + def avatar_url + ActionController::Base.helpers.image_path('illustrations/third-party-logos/integrations-logos/diffblue.svg') + end + + def self.supported_events + [] + end + + def sections + [ + { + type: SECTION_TYPE_CONNECTION, + title: s_('DiffblueCover|Integration details'), + description: + s_( + 'DiffblueCover|Diffblue Cover is a reinforcement learning AI platform that automatically ' \ + 'writes comprehensive, human-like Java unit tests. Integrate the power of Diffblue ' \ + 'Cover into your CI/CD workflow for fully autonomous operation.' + ) + }, + { + type: SECTION_TYPE_CONFIGURATION, + title: s_('DiffblueCover|Access token'), + description: + 'A GitLab access token is required in allow Diffblue Cover to access your project. ' \ + 'Use a GitLab access token with a <code>Developer</code> role, plus ' \ + '<code>api</code> and <code>write_repository</code> scopes.' + } + ] + end + + def execute(_data) end + + def ci_variables + return [] unless activated? + + [ + { key: 'DIFFBLUE_LICENSE_KEY', value: diffblue_license_key, public: false, masked: true }, + { key: 'DIFFBLUE_ACCESS_TOKEN_NAME', value: diffblue_access_token_name, public: false, masked: true }, + { key: 'DIFFBLUE_ACCESS_TOKEN', value: diffblue_access_token_secret, public: false, masked: true } + ] + end + + def testable? + false + end + + def self.diffblue_link + ActionController::Base.helpers.link_to( + s_('DiffblueCover|Try Diffblue Cover'), + 'https://www.diffblue.com/try-cover/gitlab/', + target: '_blank', + rel: 'noopener noreferrer' + ) + end + end +end diff --git a/app/models/project.rb b/app/models/project.rb index 35a664f080ac20caba985ebc4d0388111b016d38..ea5eff7e6a62cc5b8861f625718349403c6472f4 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -208,6 +208,7 @@ def self.integration_association_name(name) has_one :custom_issue_tracker_integration, class_name: 'Integrations::CustomIssueTracker' has_one :datadog_integration, class_name: 'Integrations::Datadog' has_one :container_registry_data_repair_detail, class_name: 'ContainerRegistry::DataRepairDetail' + has_one :diffblue_cover_integration, class_name: 'Integrations::DiffblueCover' has_one :discord_integration, class_name: 'Integrations::Discord' has_one :drone_ci_integration, class_name: 'Integrations::DroneCi' has_one :emails_on_push_integration, class_name: 'Integrations::EmailsOnPush' diff --git a/config/metrics/counts_all/20231205140200_groups_diffblue_cover_active.yml b/config/metrics/counts_all/20231205140200_groups_diffblue_cover_active.yml new file mode 100644 index 0000000000000000000000000000000000000000..90662895b464715d24435ea9feea82477c5a0aa0 --- /dev/null +++ b/config/metrics/counts_all/20231205140200_groups_diffblue_cover_active.yml @@ -0,0 +1,20 @@ +--- +data_category: optional +key_path: counts.groups_diffblue_cover_active +description: Count of groups with active integrations for Diffblue Cover +product_section: dev +product_stage: manage +product_group: integrations +value_type: number +status: active +time_frame: all +data_source: database +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +performance_indicator_type: [] +milestone: "16.8" diff --git a/config/metrics/counts_all/20231205140200_groups_inheriting_diffblue_cover_active.yml b/config/metrics/counts_all/20231205140200_groups_inheriting_diffblue_cover_active.yml new file mode 100644 index 0000000000000000000000000000000000000000..c8d5ceb83937242f9aca70088d8e06adfeb06125 --- /dev/null +++ b/config/metrics/counts_all/20231205140200_groups_inheriting_diffblue_cover_active.yml @@ -0,0 +1,20 @@ +--- +data_category: optional +key_path: counts.groups_inheriting_diffblue_cover_active +description: Count of active groups inheriting integrations for Diffblue Cover +product_section: dev +product_stage: manage +product_group: integrations +value_type: number +status: active +time_frame: all +data_source: database +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +performance_indicator_type: [] +milestone: "16.8" diff --git a/config/metrics/counts_all/20231205140200_instances_diffblue_cover_active.yml b/config/metrics/counts_all/20231205140200_instances_diffblue_cover_active.yml new file mode 100644 index 0000000000000000000000000000000000000000..a75573277b6c65f82da4bd3d1cce555f173bca3d --- /dev/null +++ b/config/metrics/counts_all/20231205140200_instances_diffblue_cover_active.yml @@ -0,0 +1,20 @@ +--- +data_category: optional +key_path: counts.instances_diffblue_cover_active +description: Count of active instance-level integrations for Diffblue Cover +product_section: dev +product_stage: manage +product_group: integrations +value_type: number +status: active +time_frame: all +data_source: database +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +performance_indicator_type: [] +milestone: "16.8" diff --git a/config/metrics/counts_all/20231205140200_projects_diffblue_cover_active.yml b/config/metrics/counts_all/20231205140200_projects_diffblue_cover_active.yml new file mode 100644 index 0000000000000000000000000000000000000000..b421aef816b8e23b4e6e75a9b9eeadd0e1e243d3 --- /dev/null +++ b/config/metrics/counts_all/20231205140200_projects_diffblue_cover_active.yml @@ -0,0 +1,20 @@ +--- +data_category: optional +key_path: counts.projects_diffblue_cover_active +description: Count of projects with active integrations for Diffblue Cover +product_section: dev +product_stage: manage +product_group: integrations +value_type: number +status: active +time_frame: all +data_source: database +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +performance_indicator_type: [] +milestone: "16.8" diff --git a/config/metrics/counts_all/20231205140200_projects_inheriting_diffblue_cover_active.yml b/config/metrics/counts_all/20231205140200_projects_inheriting_diffblue_cover_active.yml new file mode 100644 index 0000000000000000000000000000000000000000..84e155bc8bc787c6c32dd1601262e0f4abcae931 --- /dev/null +++ b/config/metrics/counts_all/20231205140200_projects_inheriting_diffblue_cover_active.yml @@ -0,0 +1,20 @@ +--- +data_category: optional +key_path: counts.projects_inheriting_diffblue_cover_active +description: Count of active projects inheriting integrations for Diffblue Cover +product_section: dev +product_stage: manage +product_group: integrations +value_type: number +status: active +time_frame: all +data_source: database +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate +performance_indicator_type: [] +milestone: "16.8" diff --git a/db/docs/integrations.yml b/db/docs/integrations.yml index c087d49968a02eba24dba76970d052da56891f42..037dea949d0acfc648c33079497180a04eadac27 100644 --- a/db/docs/integrations.yml +++ b/db/docs/integrations.yml @@ -20,6 +20,7 @@ classes: - Integrations::Confluence - Integrations::CustomIssueTracker - Integrations::Datadog +- Integrations::DiffblueCover - Integrations::Discord - Integrations::DroneCi - Integrations::EmailsOnPush diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt index cc02821b6d607107b845646e8859453747df6d77..b8cc7d4d89081548921b85f24a3a17dfda39d49a 100644 --- a/doc/.vale/gitlab/spelling-exceptions.txt +++ b/doc/.vale/gitlab/spelling-exceptions.txt @@ -284,6 +284,7 @@ devfiles DevOps Dhall dialogs +Diffblue disambiguates discoverability dismissable diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index aaa1a7c559b4ef0b470b2c6253e7f20806cdcbcb..e2403dbca858cf377cb2ddeaaaeeb813646f9f6f 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -31570,6 +31570,7 @@ State of a Sentry error. | <a id="servicetypeconfluence_service"></a>`CONFLUENCE_SERVICE` | ConfluenceService type. | | <a id="servicetypecustom_issue_tracker_service"></a>`CUSTOM_ISSUE_TRACKER_SERVICE` | CustomIssueTrackerService type. | | <a id="servicetypedatadog_service"></a>`DATADOG_SERVICE` | DatadogService type. | +| <a id="servicetypediffblue_cover_service"></a>`DIFFBLUE_COVER_SERVICE` | DiffblueCoverService type. | | <a id="servicetypediscord_service"></a>`DISCORD_SERVICE` | DiscordService type. | | <a id="servicetypedrone_ci_service"></a>`DRONE_CI_SERVICE` | DroneCiService type. | | <a id="servicetypeemails_on_push_service"></a>`EMAILS_ON_PUSH_SERVICE` | EmailsOnPushService type. | diff --git a/doc/integration/diffblue-cover.md b/doc/integration/diffblue-cover.md new file mode 100644 index 0000000000000000000000000000000000000000..bd1d026b5ef1a547ec55bce65b8b7c1d93081612 --- /dev/null +++ b/doc/integration/diffblue-cover.md @@ -0,0 +1,89 @@ +--- +stage: Verify +group: Pipeline Execution +info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments" +description: >- + How to configure the Diffblue Cover GitLab integration - Cover Pipeline for + GitLab +--- + +# Diffblue Cover **(FREE ALL)** + +You can integrate the [Diffblue Cover](https://www.diffblue.com/) reinforcement learning AI tool into your CI/CD pipelines, to automatically write and maintain Java unit tests for your GitLab projects. +The Diffblue Cover Pipeline for GitLab integration allows you to automatically: + +- Write a baseline unit test suite for your projects. +- Write new unit tests for new code. +- Update existing unit tests in your code. +- Remove existing unit tests in your code when they're no longer required. + + + +## Configure the integration + +To integrate Diffblue Cover into your pipeline: + +1. Find and configure the Diffblue Cover integration. +1. Configure a pipeline for a sample project using the GitLab pipeline editor and the Diffblue Cover pipeline template. +1. Create a full baseline unit test suite for the project. + +### Configure Diffblue Cover + +1. On the left sidebar, select **Search or go to** and find your project. + - If you want to test the integration with a sample project, you can [import](../user/project/import/repo_by_url.md) + the Diffblue [Spring PetClinic sample project](https://github.com/diffblue/demo-spring-petclinic). +1. Select **Settings > Integrations**. +1. Find **Diffblue Cover** and select **Configure**. +1. Complete the fields: + + - Select the **Active** checkbox. + - Enter your Diffblue Cover **License key** provided in your welcome email or by your organization. + If needed, select the [**Try Diffblue Cover**](https://www.diffblue.com/try-cover/gitlab) link to sign up for a free trial. + - Enter details of your GitLab access token (**Name** and **Secret**) to allow Diffblue Cover to access your project. + In general, use a GitLab [project access token](../user/project/settings/project_access_tokens.md) with the `Developer` role, plus `api` and `write_repository` scopes. + If necessary you can use a [group access token](../user/group/settings/group_access_tokens.md) or a [personal access token](../user/profile/personal_access_tokens.md), again with the `Developer` role, plus `api` and `write_repository` scopes. + + NOTE: + Using an access token with excessive permissions is a security risk. + If you use a Personal access token, consider creating a dedicated user with access limited to just the project, minimizing the impact of the token being leaked. + +1. Select **Save changes**. + Your Diffblue Cover integration is now <mark style="color:green;">**Active**</mark> and ready for use in your project. + +### Configure a pipeline + +Here we'll create a merge request pipeline for the project that will download the latest version of Diffblue Cover, build the project, write Java unit tests for the project, and commit the changes to the branch. + +1. On the left sidebar, select **Search or go to** and find your project. +1. Select **Build > Pipeline editor**. +1. Select **Configure pipeline** to create the `.gitlab-ci.yml` file. +1. Select **Browse templates** and find the `Diffblue-Cover.gitlab-ci.yml` template file. +1. Select the file and copy the contents to your project's `.gitlab-ci.yml` file. + + NOTE: + When using the Diffblue Cover pipeline template with your own project and existing pipeline file, add the Diffblue template content to your file and modify as needed. + For more information, see [Cover Pipeline for GitLab](https://docs.diffblue.com/features/cover-pipeline/cover-pipeline-for-gitlab) in the Diffblue documentation. + +1. Enter a commit message. +1. Enter a new **Branch** name. For example, `add-diffblue-cover-pipeline`. +1. Select **Start a new merge request with these changes**. +1. Select **Commit changes**. + +### Create a baseline unit test suite + +1. In the **New merge request** form, enter a **Title** (for example, "Add Cover pipeline and create baseline unit test suite") and fill out the other fields. +1. Select **Create merge request**. The merge request pipeline runs Diffblue Cover to create the baseline unit test suite for the project. +1. Once the pipeline completes, the changes can be reviewed from the **Changes** tab. When you're happy, merge the updates to your repo. Go to the `src/test` folders in the project repository to see the unit tests created by Diffblue Cover (suffixed with `*DiffblueTest.java`). + +## Subsequent code changes + +When performing subsequent code changes to a project, the merge request pipeline will run Diffblue Cover but will only update the associated tests. +The resulting diff can then be analyzed to check the new behavior, catch regressions, and spot any unplanned behavioral changes to the code. + + + +## Next steps + +This topic demonstrates some of the key features of Cover Pipeline for GitLab and how to use the integration in a pipeline. +The wider and deeper functionality, provided through `dcover` commands in the pipeline template, can be implemented to expand your unit test capabilities even further. +For more information, see [Cover Pipeline for GitLab](https://docs.diffblue.com/features/cover-pipeline/cover-pipeline-for-gitlab) in the Diffblue documentation. diff --git a/doc/integration/img/diffblue_cover_diff_v16_8.png b/doc/integration/img/diffblue_cover_diff_v16_8.png new file mode 100644 index 0000000000000000000000000000000000000000..1ee4dd954af2a9fa2289879f53bc2d8e57ec2fbc Binary files /dev/null and b/doc/integration/img/diffblue_cover_diff_v16_8.png differ diff --git a/doc/integration/img/diffblue_cover_workflow_after_v16_8.png b/doc/integration/img/diffblue_cover_workflow_after_v16_8.png new file mode 100644 index 0000000000000000000000000000000000000000..213456001253076b3684ce96114cac2d2692efb4 Binary files /dev/null and b/doc/integration/img/diffblue_cover_workflow_after_v16_8.png differ diff --git a/lib/api/helpers/integrations_helpers.rb b/lib/api/helpers/integrations_helpers.rb index cb8e3697e6d7372bbae5d6d7240a2573e0b652c2..bdec33373a4e94d790360cda23176d71553a7f77 100644 --- a/lib/api/helpers/integrations_helpers.rb +++ b/lib/api/helpers/integrations_helpers.rb @@ -217,6 +217,7 @@ def self.integrations desc: 'Custom tags in Datadog. Specify one tag per line in the format: "key:value\nkey2:value2"' } ], + 'diffblue-cover' => ::Integrations::DiffblueCover.api_fields, 'discord' => [ ::Integrations::Discord.api_fields, chat_notification_flags, @@ -695,6 +696,7 @@ def self.integration_classes ::Integrations::Confluence, ::Integrations::CustomIssueTracker, ::Integrations::Datadog, + ::Integrations::DiffblueCover, ::Integrations::Discord, ::Integrations::DroneCi, ::Integrations::EmailsOnPush, diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 121d87af164678512c5a54cf53b0e26791d525a1..10c04c0f7d0d2c5639addbcee34dcbfb18fc8176 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -17710,6 +17710,51 @@ msgstr "" msgid "Diff notes" msgstr "" +msgid "DiffblueCover|Access token" +msgstr "" + +msgid "DiffblueCover|Access token name used by Diffblue Cover in pipelines" +msgstr "" + +msgid "DiffblueCover|Access token secret used by Diffblue Cover in pipelines" +msgstr "" + +msgid "DiffblueCover|Automatically write comprehensive, human-like Java unit tests." +msgstr "" + +msgid "DiffblueCover|Diffblue Cover is a reinforcement learning AI platform that automatically writes comprehensive, human-like Java unit tests. Integrate the power of Diffblue Cover into your CI/CD workflow for fully autonomous operation." +msgstr "" + +msgid "DiffblueCover|Diffblue Cover license key" +msgstr "" + +msgid "DiffblueCover|Enter your Diffblue Cover license key or visit %{diffblue_link} to obtain a free trial license." +msgstr "" + +msgid "DiffblueCover|Integration details" +msgstr "" + +msgid "DiffblueCover|Leave blank to use your current license key." +msgstr "" + +msgid "DiffblueCover|Leave blank to use your current secret value." +msgstr "" + +msgid "DiffblueCover|License key" +msgstr "" + +msgid "DiffblueCover|My token name" +msgstr "" + +msgid "DiffblueCover|Name" +msgstr "" + +msgid "DiffblueCover|Secret" +msgstr "" + +msgid "DiffblueCover|Try Diffblue Cover" +msgstr "" + msgid "Difference between start date and now" msgstr "" diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb index 74dfea585f26d0dc36c017da6b827b95feba8485..1d698e1b4d85534122fe3db6ce0dcf09b8e80b0d 100644 --- a/spec/factories/integrations.rb +++ b/spec/factories/integrations.rb @@ -30,6 +30,14 @@ api_key { 'secret' } end + factory :diffblue_cover_integration, class: 'Integrations::DiffblueCover' do + project + active { true } + diffblue_license_key { '1234-ABCD-DCBA-4321' } + diffblue_access_token_name { 'Diffblue CI' } + diffblue_access_token_secret { 'glpat-00112233445566778899' } # gitleaks:allow + end + factory :emails_on_push_integration, class: 'Integrations::EmailsOnPush' do project type { 'Integrations::EmailsOnPush' } diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 688487df778749980dade6ceabdd2f89ff27ed89..60c035f8387ffea273472addfdfb7ffece171491 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -588,6 +588,7 @@ project: - hangouts_chat_integration - unify_circuit_integration - buildkite_integration +- diffblue_cover_integration - bamboo_integration - teamcity_integration - pushover_integration diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index af3f54c5f0abf0ca01362a32ae87009b61878ac5..535cd9c3b903815197a85b43d2f111c0e7d364d6 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -3262,6 +3262,34 @@ def insert_expected_predefined_variables(variables, after:) end end + context 'for the diffblue_cover integration' do + context 'when active' do + let_it_be(:diffblue_cover_integration) { create(:diffblue_cover_integration, active: true) } + + let(:diffblue_cover_variables) do + [ + { key: 'DIFFBLUE_LICENSE_KEY', value: diffblue_cover_integration.diffblue_license_key, masked: true, public: false }, + { key: 'DIFFBLUE_ACCESS_TOKEN_NAME', value: diffblue_cover_integration.diffblue_access_token_name, masked: true, public: false }, + { key: 'DIFFBLUE_ACCESS_TOKEN', value: diffblue_cover_integration.diffblue_access_token_secret, masked: true, public: false } + ] + end + + it 'includes diffblue_cover variables' do + is_expected.to include(*diffblue_cover_variables) + end + end + + context 'when inactive' do + let_it_be(:diffblue_cover_integration) { create(:diffblue_cover_integration, active: false) } + + it 'does not include diffblue_cover variables' do + expect(subject.find { |v| v[:key] == 'DIFFBLUE_LICENSE_KEY' }).to be_nil + expect(subject.find { |v| v[:key] == 'DIFFBLUE_ACCESS_TOKEN_NAME' }).to be_nil + expect(subject.find { |v| v[:key] == 'DIFFBLUE_ACCESS_TOKEN' }).to be_nil + end + end + end + context 'for the google_play integration' do before do allow(build.pipeline).to receive(:protected_ref?).and_return(pipeline_protected_ref) diff --git a/spec/models/integrations/diffblue_cover_spec.rb b/spec/models/integrations/diffblue_cover_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..c1a98cc2fbddd728e41b98b3306f4b90001d80a4 --- /dev/null +++ b/spec/models/integrations/diffblue_cover_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Integrations::DiffblueCover, feature_category: :integrations do + let_it_be(:project) { build(:project) } + + subject(:integration) { build(:diffblue_cover_integration, project: project) } + + describe 'Validations' do + context 'when active' do + before do + integration.active = true + end + + it { is_expected.to validate_presence_of(:diffblue_license_key) } + it { is_expected.to validate_presence_of(:diffblue_access_token_name) } + it { is_expected.to validate_presence_of(:diffblue_access_token_secret) } + end + + context 'when inactive' do + before do + integration.active = false + end + + it { is_expected.not_to validate_presence_of(:diffblue_license_key) } + it { is_expected.not_to validate_presence_of(:diffblue_access_token_name) } + it { is_expected.not_to validate_presence_of(:diffblue_access_token_secret) } + end + end + + describe '#avatar_url' do + it 'returns the avatar image path' do + expect(integration.avatar_url).to eq(ActionController::Base.helpers.image_path( + 'illustrations/third-party-logos/integrations-logos/diffblue.svg' + )) + end + end + + describe '#ci-vars' do + let(:ci_vars) do + [ + { key: 'DIFFBLUE_LICENSE_KEY', value: '1234-ABCD-DCBA-4321', public: false, masked: true }, + { key: 'DIFFBLUE_ACCESS_TOKEN_NAME', value: 'Diffblue CI', public: false, masked: true }, + { key: 'DIFFBLUE_ACCESS_TOKEN', + value: 'glpat-00112233445566778899', public: false, masked: true } # gitleaks:allow + ] + end + + context 'when active' do + before do + integration.active = true + end + + it 'returns the required pipeline vars' do + expect(integration.ci_variables).to match_array(ci_vars) + end + end + + context 'when inactive' do + before do + integration.active = false + end + + it 'does not return the required pipeline vars' do + expect(integration.ci_variables).to be_empty + end + end + end + + describe '#diffblue_link' do + it { expect(described_class.diffblue_link).to include("https://www.diffblue.com/try-cover/gitlab/") } + end +end