diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml index 64586362273..f9c3a40a17e 100644 --- a/.gitlab/ci/frontend.gitlab-ci.yml +++ b/.gitlab/ci/frontend.gitlab-ci.yml @@ -286,16 +286,18 @@ jest-build-cache: NODE_OPTIONS: --max-old-space-size=7680 allow_failure: true -.with-jest-build-cache-vue3-needs: +.with-jest-build-cache-vue3-ensure-compilable-sfcs-needs: needs: - - job: jest-build-cache-vue3 + - job: jest-build-cache-vue3-ensure-compilable-sfcs optional: true -jest-build-cache-vue3: +jest-build-cache-vue3-ensure-compilable-sfcs: extends: + - .vue3 + # Make sure allow_failure is set by jest-build-cache rather than .vue3. + # Failures should not be allowed in merge requests. - jest-build-cache - .frontend:rules:jest - - .vue3 jest: extends: @@ -338,7 +340,7 @@ jest vue3: - .frontend:rules:jest-vue3-nightly - .vue3 needs: - - !reference [.with-jest-build-cache-vue3-needs, needs] + - !reference [.with-jest-build-cache-vue3-ensure-compilable-sfcs-needs, needs] jest-with-fixtures vue3: extends: @@ -357,7 +359,7 @@ jest vue3 mr: - .frontend:rules:jest - .vue3 needs: - - !reference [.with-jest-build-cache-vue3-needs, needs] + - !reference [.with-jest-build-cache-vue3-ensure-compilable-sfcs-needs, needs] artifacts: name: vue3-mr-junit expire_in: 31d @@ -374,7 +376,7 @@ jest-with-fixtures vue3 mr: - jest vue3 mr - .repo-from-artifacts needs: - - !reference [.with-jest-build-cache-vue3-needs, needs] + - !reference [.with-jest-build-cache-vue3-ensure-compilable-sfcs-needs, needs] # it's ok to wait for the repo artifact as we're waiting for the fixtures (which wait for the repo artifact) anyway - !reference [.repo-from-artifacts, needs] - !reference [.with-fixtures-needs, needs] @@ -418,6 +420,7 @@ jest vue3 predictive: - "detect-tests" script: - if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then run_timed_command "yarn jest:ci:vue3-mr:predictive-without-fixtures"; fi + allow_failure: false jest-with-fixtures vue3 predictive: extends: @@ -428,6 +431,7 @@ jest-with-fixtures vue3 predictive: - "detect-tests" script: - if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then run_timed_command "yarn jest:ci:vue3-mr:predictive-with-fixtures"; fi + allow_failure: false jest-integration: extends: diff --git a/app/assets/javascripts/boards/components/board_content.vue b/app/assets/javascripts/boards/components/board_content.vue index c867137d427..9e1a75498d1 100644 --- a/app/assets/javascripts/boards/components/board_content.vue +++ b/app/assets/javascripts/boards/components/board_content.vue @@ -283,6 +283,9 @@ export default { @setAddColumnFormVisibility="$emit('setAddColumnFormVisibility', $event)" /> + + + `name` | [`String`](#string) | Entire name or part of the name. | - ### `Query.containerRepository` Find a container repository. @@ -23531,6 +23515,22 @@ four standard [pagination arguments](#pagination-arguments): | `ids` | [`[ComplianceManagementFrameworkID!]`](#compliancemanagementframeworkid) | List of Global IDs of compliance frameworks to return. | | `search` | [`String`](#string) | Search framework with most similar names. | +##### `Group.components` + +Find software dependencies by name. + +DETAILS: +**Introduced** in GitLab 17.5. +**Status**: Experiment. + +Returns [`[Component!]`](#component). + +###### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `name` | [`String`](#string) | Entire name or part of the name. | + ##### `Group.contactStateCounts` Counts of contacts by state for the group. diff --git a/doc/development/uploads/index.md b/doc/development/uploads/index.md index 39b8beec8e1..bdde8db2d05 100644 --- a/doc/development/uploads/index.md +++ b/doc/development/uploads/index.md @@ -118,6 +118,57 @@ This strategy is a different form of [Workhorse assistance](#workhorse-assisted- Of all existing upload strategies, direct upload is best able to handle large (gigabyte) uploads. +### Disk buffered uploads + +Direct upload falls back to _disk buffered upload_ when `direct_upload` is disabled inside the [object storage setting](../../administration/uploads.md#object-storage-settings). The answer to the `/authorize` call contains only a file system path. + +```mermaid +sequenceDiagram + participant c as Client + participant w as Workhorse + participant r as Rails + participant os as Object Storage + + activate c + c ->>+w: POST /some/url/upload + + w ->>+r: POST /some/url/upload/authorize + Note over w,r: this request has an empty body + r-->>-w: presigned OS URL + + w->>+os: PUT file + Note over w,os: file is stored on a temporary location. Rails select the destination + os-->>-w: request result + + w->>+r: POST /some/url/upload + Note over w,r: file was replaced with its location
and other metadata + + r->>+os: move object to final destination + os-->>-r: request result + + opt requires async processing + r->>+redis: schedule a job + redis-->>-r: job is scheduled + end + + r-->>-c: request result + deactivate c + w->>-w: cleanup + + opt requires async processing + activate sidekiq + sidekiq->>+redis: fetch a job + redis-->>-sidekiq: job + + sidekiq->>+os: get object + os-->>-sidekiq: file + + sidekiq->>sidekiq: process file + + deactivate sidekiq + end +``` + ## Workhorse assisted uploads Most uploads receive assistance from Workhorse in some way. diff --git a/doc/user/project/repository/code_suggestions/repository_xray.md b/doc/user/project/repository/code_suggestions/repository_xray.md index 148b1915658..f159394b603 100644 --- a/doc/user/project/repository/code_suggestions/repository_xray.md +++ b/doc/user/project/repository/code_suggestions/repository_xray.md @@ -37,20 +37,20 @@ The Repository X-Ray service is automatically enabled if: The Repository X-Ray searches a maximum of two directory levels from the repository's root. For example, it supports `Gemfile.lock`, `api/Gemfile.lock`, or `api/client/Gemfile.lock`, but not `api/v1/client/Gemfile.lock`. For each language, only the first matching configuration file is processed. Where available, lock files take precedence over their non-lock file counterparts. -| Language | Package manager | Configuration file | GitLab version | -| ---------- |-----------------| -------------------- | -------------- | -| C/C++ | Conan | `conanfile.py` | 17.5 or later | -| C/C++ | Conan | `conanfile.txt` | 17.5 or later | -| C/C++ | vcpkg | `vcpkg.json` | 17.5 or later | -| C# | NuGet | `*.csproj` | 17.5 or later | -| Go | Go Modules | `go.mod` | 17.4 or later | -| Java | Gradle | `build.gradle` | 17.4 or later | -| Java | Maven | `pom.xml` | 17.4 or later | -| Kotlin | Gradle | `build.gradle.kts` | 17.5 or later | -| Python | Conda | `environment.yml` | 17.5 or later | -| Python | Pip | `requirements.txt` | 17.5 or later | -| Python | Poetry | `pyproject.toml` | 17.5 or later | -| Ruby | RubyGems | `Gemfile.lock` | 17.4 or later | +| Language | Package manager | Configuration file | GitLab version | +| ---------- |-----------------| -------------------------------- | -------------- | +| C/C++ | Conan | `conanfile.py` | 17.5 or later | +| C/C++ | Conan | `conanfile.txt` | 17.5 or later | +| C/C++ | vcpkg | `vcpkg.json` | 17.5 or later | +| C# | NuGet | `*.csproj` | 17.5 or later | +| Go | Go Modules | `go.mod` | 17.4 or later | +| Java | Gradle | `build.gradle` | 17.4 or later | +| Java | Maven | `pom.xml` | 17.4 or later | +| Kotlin | Gradle | `build.gradle.kts` | 17.5 or later | +| Python | Conda | `environment.yml` | 17.5 or later | +| Python | Pip | `requirements.txt` | 17.5 or later | +| Python | Poetry | `poetry.lock`, `pyproject.toml` | 17.5 or later | +| Ruby | RubyGems | `Gemfile.lock` | 17.4 or later | ## Enable Repository X-Ray in your CI pipeline (deprecated) diff --git a/lib/api/entities/environment.rb b/lib/api/entities/environment.rb index fb93850fc75..b87cf13782d 100644 --- a/lib/api/entities/environment.rb +++ b/lib/api/entities/environment.rb @@ -13,6 +13,7 @@ module API expose :cluster_agent, using: Entities::Clusters::Agent, if: ->(_, _) { can_read_cluster_agent? } expose :kubernetes_namespace, if: ->(_, _) { can_read_cluster_agent? } expose :flux_resource_path, if: ->(_, _) { can_read_cluster_agent? } + expose :description, documentation: { type: 'string', example: 'description' } private diff --git a/lib/api/environments.rb b/lib/api/environments.rb index aa300a2b81f..a991cfe6c03 100644 --- a/lib/api/environments.rb +++ b/lib/api/environments.rb @@ -69,6 +69,7 @@ module API optional :cluster_agent_id, type: Integer, desc: 'The ID of the Cluster Agent to associate with this environment' optional :kubernetes_namespace, type: String, desc: 'The Kubernetes namespace to associate with this environment' optional :flux_resource_path, type: String, desc: 'The Flux resource path to associate with this environment' + optional :description, type: String, desc: 'The description of the environment' end route_setting :authentication, job_token_allowed: true post ':id/environments' do @@ -109,6 +110,7 @@ module API optional :cluster_agent_id, type: Integer, desc: 'The ID of the Cluster Agent to associate with this environment' optional :kubernetes_namespace, type: String, desc: 'The Kubernetes namespace to associate with this environment' optional :flux_resource_path, type: String, desc: 'The Flux resource path to associate with this environment' + optional :description, type: String, desc: 'The description of the environment' end route_setting :authentication, job_token_allowed: true put ':id/environments/:environment_id' do @@ -116,7 +118,7 @@ module API environment = user_project.environments.find(params[:environment_id]) - update_params = declared_params(include_missing: false).extract!(:external_url, :tier, :cluster_agent_id, :kubernetes_namespace, :flux_resource_path) + update_params = declared_params(include_missing: false).extract!(:external_url, :tier, :cluster_agent_id, :kubernetes_namespace, :flux_resource_path, :description) if update_params[:cluster_agent_id] agent = ::Clusters::AgentsFinder.new(user_project, current_user).execute.find_by_id(params[:cluster_agent_id]) diff --git a/lib/gitlab/usage_data_counters/hll_redis_key_overrides.yml b/lib/gitlab/usage_data_counters/hll_redis_key_overrides.yml index a4e2bcc5e8b..ca5dd625388 100644 --- a/lib/gitlab/usage_data_counters/hll_redis_key_overrides.yml +++ b/lib/gitlab/usage_data_counters/hll_redis_key_overrides.yml @@ -174,3 +174,4 @@ user_visited_dashboard-user: user_visited_dashboard visit_ci_cd_failure_rate_tab-user: p_analytics_ci_cd_change_failure_rate visit_ci_cd_time_to_restore_service_tab-user: p_analytics_ci_cd_time_to_restore_service visit_compliance_credential_inventory-user: i_compliance_credential_inventory +commit_change_to_ciconfigfile-user: o_pipeline_authoring_unique_users_committing_ciconfigfile diff --git a/lib/gitlab/usage_data_counters/hll_redis_legacy_events.yml b/lib/gitlab/usage_data_counters/hll_redis_legacy_events.yml index 4480670311c..04ae0d60579 100644 --- a/lib/gitlab/usage_data_counters/hll_redis_legacy_events.yml +++ b/lib/gitlab/usage_data_counters/hll_redis_legacy_events.yml @@ -353,7 +353,6 @@ - k8s_api_proxy_requests_unique_agents_via_pat_access - k8s_api_proxy_requests_unique_agents_via_user_access - merge_request_action -- o_pipeline_authoring_unique_users_committing_ciconfigfile - o_pipeline_authoring_unique_users_pushing_mr_ciconfigfile - p_analytics_code_reviews - p_analytics_insights diff --git a/locale/gitlab.pot b/locale/gitlab.pot index bab15632dc4..a922d2d80e5 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -3895,6 +3895,9 @@ msgstr "" msgid "AdminSelfHostedModels|An API key is set" msgstr "" +msgid "AdminSelfHostedModels|An error occurred while deleting your self-hosted model. Please try again." +msgstr "" + msgid "AdminSelfHostedModels|An error occurred while loading self-hosted models. Please try again." msgstr "" @@ -3982,6 +3985,9 @@ msgstr "" msgid "AdminSelfHostedModels|There was an error saving the self-hosted model. Please try again." msgstr "" +msgid "AdminSelfHostedModels|Your self-hosted model was successfully deleted." +msgstr "" + msgid "AdminSettings|%{generate_manually_link_start}Generate%{generate_manually_link_end} Service Ping to preview and download service usage data payload." msgstr "" @@ -38325,6 +38331,9 @@ msgstr "" msgid "Orphaned member" msgstr "" +msgid "Orphaned request" +msgstr "" + msgid "Other" msgstr "" diff --git a/qa/gdk/Dockerfile.gdk b/qa/gdk/Dockerfile.gdk index 08cfc549328..58636d2c1f7 100644 --- a/qa/gdk/Dockerfile.gdk +++ b/qa/gdk/Dockerfile.gdk @@ -1,4 +1,4 @@ -ARG GDK_SHA=59f9233de457781829a606c11e775b4809677dc3 +ARG GDK_SHA=25dd408d7727657811bf9fb59b1cbc15d4f1d160 # Use tag prefix when running on 'stable' branch to make sure 'protected' image is used which is not deleted by registry cleanup ARG GDK_BASE_TAG_PREFIX diff --git a/spec/controllers/concerns/onboarding/status_spec.rb b/spec/controllers/concerns/onboarding/status_spec.rb index 6fcbd059947..11b4b85afe3 100644 --- a/spec/controllers/concerns/onboarding/status_spec.rb +++ b/spec/controllers/concerns/onboarding/status_spec.rb @@ -7,6 +7,21 @@ RSpec.describe Onboarding::Status, feature_category: :onboarding do let_it_be(:user) { member.user } let_it_be(:source) { member.group } + describe '.registration_path_params' do + let(:params) { { some: 'thing' } } + let(:extra_params) { { another_extra: 'param' } } + + subject { described_class.registration_path_params(params: params) } + + it { is_expected.to eq({}) } + + context 'when extra params are passed' do + subject { described_class.registration_path_params(params: params, extra_params: extra_params) } + + it { is_expected.to eq({}) } + end + end + describe '#single_invite?' do subject { described_class.new(nil, nil, user).single_invite? } diff --git a/spec/fixtures/api/schemas/public_api/v4/environment.json b/spec/fixtures/api/schemas/public_api/v4/environment.json index 46fc27cb251..523083dbdb3 100644 --- a/spec/fixtures/api/schemas/public_api/v4/environment.json +++ b/spec/fixtures/api/schemas/public_api/v4/environment.json @@ -23,6 +23,9 @@ "tier": { "type": "string" }, + "description": { + "$ref": "../../types/nullable_string.json" + }, "external_url": { "$ref": "../../types/nullable_string.json" }, diff --git a/spec/frontend/__helpers__/vue_test_utils_helper.js b/spec/frontend/__helpers__/vue_test_utils_helper.js index 20a79fc4d2f..6b712b6592b 100644 --- a/spec/frontend/__helpers__/vue_test_utils_helper.js +++ b/spec/frontend/__helpers__/vue_test_utils_helper.js @@ -9,10 +9,6 @@ import { } from '@vue/test-utils'; import { compose } from 'lodash/fp'; -const vNodeContainsText = (vnode, text) => - (vnode.text && vnode.text.includes(text)) || - (vnode.children && vnode.children.filter((child) => vNodeContainsText(child, text)).length); - /** * Create a VTU wrapper from an element. * @@ -27,38 +23,6 @@ const createWrapperFromElement = (element, options) => // eslint-disable-next-line no-underscore-dangle createWrapper(element.__vue__ || element, options || {}); -/** - * Determines whether a `shallowMount` Wrapper contains text - * within one of it's slots. This will also work on Wrappers - * acquired with `find()`, but only if it's parent Wrapper - * was shallowMounted. - * NOTE: Prefer checking the rendered output of a component - * wherever possible using something like `text()` instead. - * @param {Wrapper} shallowWrapper - Vue test utils wrapper (shallowMounted) - * @param {String} slotName - * @param {String} text - */ -export const shallowWrapperContainsSlotText = (shallowWrapper, slotName, text) => - Boolean( - shallowWrapper.vm.$slots[slotName].filter((vnode) => vNodeContainsText(vnode, text)).length, - ); - -/** - * Returns a promise that waits for a mutation to be fired before resolving - * NOTE: There's no reject action here so it will hang if it waits for a mutation that won't happen. - * @param {Object} store - The Vue store that contains the mutations - * @param {String} expectedMutationType - The Mutation to wait for - */ -export const waitForMutation = (store, expectedMutationType) => - new Promise((resolve) => { - const unsubscribe = store.subscribe((mutation) => { - if (mutation.type === expectedMutationType) { - unsubscribe(); - resolve(); - } - }); - }); - /** * Query function type * @callback FindFunction diff --git a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js index c137561154d..dada937d3bf 100644 --- a/spec/frontend/__helpers__/vue_test_utils_helper_spec.js +++ b/spec/frontend/__helpers__/vue_test_utils_helper_spec.js @@ -7,12 +7,7 @@ import { ErrorWrapper as VTUErrorWrapper, } from '@vue/test-utils'; import Vue from 'vue'; -import { - extendedWrapper, - shallowMountExtended, - mountExtended, - shallowWrapperContainsSlotText, -} from './vue_test_utils_helper'; +import { extendedWrapper, shallowMountExtended, mountExtended } from './vue_test_utils_helper'; jest.mock('@testing-library/dom', () => ({ __esModule: true, @@ -24,50 +19,6 @@ describe('Vue test utils helpers', () => { jest.unmock('@testing-library/dom'); }); - describe('shallowWrapperContainsSlotText', () => { - const mockText = 'text'; - const mockSlot = `
${mockText}
`; - let mockComponent; - - beforeEach(() => { - mockComponent = shallowMount( - { - render(h) { - h(`
mockedComponent
`); - }, - }, - { - slots: { - default: mockText, - namedSlot: mockSlot, - }, - }, - ); - }); - - it('finds text within shallowWrapper default slot', () => { - expect(shallowWrapperContainsSlotText(mockComponent, 'default', mockText)).toBe(true); - }); - - it('finds text within shallowWrapper named slot', () => { - expect(shallowWrapperContainsSlotText(mockComponent, 'namedSlot', mockText)).toBe(true); - }); - - it('returns false when text is not present', () => { - const searchText = 'absent'; - - expect(shallowWrapperContainsSlotText(mockComponent, 'default', searchText)).toBe(false); - expect(shallowWrapperContainsSlotText(mockComponent, 'namedSlot', searchText)).toBe(false); - }); - - it('searches with case-sensitivity', () => { - const searchText = mockText.toUpperCase(); - - expect(shallowWrapperContainsSlotText(mockComponent, 'default', searchText)).toBe(false); - expect(shallowWrapperContainsSlotText(mockComponent, 'namedSlot', searchText)).toBe(false); - }); - }); - describe('extendedWrapper', () => { describe('when an invalid wrapper is provided', () => { beforeEach(() => { diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js index 99c4a11541b..e28fe2f7343 100644 --- a/spec/frontend/environment.js +++ b/spec/frontend/environment.js @@ -26,6 +26,9 @@ class CustomEnvironment extends TestEnvironment { // https://gitlab.com/gitlab-org/gitlab/-/issues/396779#note_1788506238 /^\[Vue warn\]: Missing required prop/, /^\[Vue warn\]: Invalid prop/, + // TODO: Implement robust vue-demi switching logic. + // https://gitlab.com/groups/gitlab-org/-/epics/15340 + /^\[Vue warn\]: \(deprecation GLOBAL_PRIVATE_UTIL\)/, ], // TODO: Remove this and replace with localized calls to `useConsoleWatcherThrowsImmediately` // https://gitlab.com/gitlab-org/gitlab/-/issues/396779#note_1788506238 diff --git a/spec/helpers/registrations_helper_spec.rb b/spec/helpers/registrations_helper_spec.rb index 74d46245cc2..fb7f6d14dd7 100644 --- a/spec/helpers/registrations_helper_spec.rb +++ b/spec/helpers/registrations_helper_spec.rb @@ -8,12 +8,4 @@ RSpec.describe RegistrationsHelper, feature_category: :user_management do expect(helper.signup_username_data_attributes.keys).to include(:min_length, :min_length_message, :max_length, :max_length_message, :testid) end end - - describe '#register_omniauth_params' do - it 'adds intent to register' do - allow(helper).to receive(:glm_tracking_params).and_return({}) - - expect(helper.register_omniauth_params({})).to eq({}) - end - end end diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb index b2b8fb453c2..df592eb153b 100644 --- a/spec/requests/api/environments_spec.rb +++ b/spec/requests/api/environments_spec.rb @@ -8,7 +8,7 @@ RSpec.describe API::Environments, feature_category: :continuous_delivery do let_it_be(:non_member) { create(:user) } let_it_be(:reporter) { create(:user) } let_it_be(:project) { create(:project, :private, :repository, namespace: user.namespace, maintainers: user, developers: developer, reporters: reporter) } - let_it_be_with_reload(:environment) { create(:environment, project: project) } + let_it_be_with_reload(:environment) { create(:environment, project: project, description: 'description') } describe 'GET /projects/:id/environments', :aggregate_failures do context 'as member of the project' do @@ -22,6 +22,7 @@ RSpec.describe API::Environments, feature_category: :continuous_delivery do expect(json_response.size).to eq(1) expect(json_response.first['name']).to eq(environment.name) expect(json_response.first['tier']).to eq(environment.tier) + expect(json_response.first['description']).to eq(environment.description) expect(json_response.first['external_url']).to eq(environment.external_url) expect(json_response.first['project']).to match_schema('public_api/v4/project') expect(json_response.first).not_to have_key('last_deployment') @@ -126,11 +127,12 @@ RSpec.describe API::Environments, feature_category: :continuous_delivery do describe 'POST /projects/:id/environments' do context 'as a member' do it 'creates an environment with valid params' do - post api("/projects/#{project.id}/environments", user), params: { name: "mepmep", tier: 'staging' } + post api("/projects/#{project.id}/environments", user), params: { name: "mepmep", tier: 'staging', description: 'description' } expect(response).to have_gitlab_http_status(:created) expect(response).to match_response_schema('public_api/v4/environment') expect(json_response['name']).to eq('mepmep') + expect(json_response['description']).to eq('description') expect(json_response['slug']).to eq('mepmep') expect(json_response['tier']).to eq('staging') expect(json_response['external']).to be nil @@ -316,6 +318,15 @@ RSpec.describe API::Environments, feature_category: :continuous_delivery do expect(json_response['external_url']).to eq(url) end + it 'returns a 200 if description is changed' do + put api("/projects/#{project.id}/environments/#{environment.id}", user), + params: { description: 'new description' } + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to match_response_schema('public_api/v4/environment') + expect(json_response['description']).to eq('new description') + end + it 'returns a 200 if tier is changed' do put api("/projects/#{project.id}/environments/#{environment.id}", user), params: { tier: 'production' } diff --git a/spec/services/git/branch_hooks_service_spec.rb b/spec/services/git/branch_hooks_service_spec.rb index 86ec885cdf8..23bad33f50a 100644 --- a/spec/services/git/branch_hooks_service_spec.rb +++ b/spec/services/git/branch_hooks_service_spec.rb @@ -121,26 +121,24 @@ RSpec.describe Git::BranchHooksService, :clean_gitlab_redis_shared_state, featur let!(:commit_author) { create(:user, email: sample_commit.author_email) } - let(:tracking_params) do - ['o_pipeline_authoring_unique_users_committing_ciconfigfile', { values: commit_author.id }] - end - it 'tracks the event' do - time = Time.zone.now - - execute_service - - expect(Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'o_pipeline_authoring_unique_users_committing_ciconfigfile', start_date: time, end_date: time + 7.days)).to eq(1) + expect { subject } + .to trigger_internal_events('commit_change_to_ciconfigfile') + .with(category: 'Git::BranchHooksService', user: commit_author, project: project) + .and increment_usage_metrics( + 'redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_committing_ciconfigfile_weekly', + 'redis_hll_counters.pipeline_authoring.o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly', + 'redis_hll_counters.pipeline_authoring.pipeline_authoring_total_unique_counts_weekly', + 'redis_hll_counters.pipeline_authoring.pipeline_authoring_total_unique_counts_monthly' + ) end context 'when the branch is not the main branch' do let(:branch) { 'feature' } it 'does not track the event' do - expect(Gitlab::UsageDataCounters::HLLRedisCounter) - .not_to receive(:track_event).with(*tracking_params) - - execute_service + expect { subject } + .not_to trigger_internal_events('commit_change_to_ciconfigfile') end end @@ -150,10 +148,8 @@ RSpec.describe Git::BranchHooksService, :clean_gitlab_redis_shared_state, featur end it 'does not track the event' do - expect(Gitlab::UsageDataCounters::HLLRedisCounter) - .not_to receive(:track_event).with(*tracking_params) - - execute_service + expect { subject } + .not_to trigger_internal_events('commit_change_to_ciconfigfile') end end end diff --git a/spec/views/devise/registrations/new.html.haml_spec.rb b/spec/views/devise/registrations/new.html.haml_spec.rb index 0961da8d1cd..85ebf626e7b 100644 --- a/spec/views/devise/registrations/new.html.haml_spec.rb +++ b/spec/views/devise/registrations/new.html.haml_spec.rb @@ -11,12 +11,14 @@ RSpec.describe 'devise/registrations/new', feature_category: :system_access do before do allow(view).to receive(:resource).and_return(resource) allow(view).to receive(:resource_name).and_return(:user) - allow(view).to receive(:glm_tracking_params).and_return({}) - allow(view).to receive(:registration_path_params).and_return({}) allow(view).to receive(:preregistration_tracking_label).and_return(tracking_label) allow(view).to receive(:arkose_labs_enabled?) end + context 'for password form' do + it { is_expected.to have_css('form[action="/users"]') } + end + context 'for omniauth provider buttons' do let(:provider_label) { :github } let(:tracking_action) { "#{provider_label}_sso" }