diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-10 09:17:26 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-10 09:17:26 +0300 |
commit | 4dfcbb2696bce1a94c0b0fbd7f9e0cef1015f3d2 (patch) | |
tree | 50071c95706017018bed80ac5053a03e3695839f | |
parent | fea86fb8bf2339727de5e91ccf17ab105e993dca (diff) |
Add latest changes from gitlab-org/gitlab@master
32 files changed, 326 insertions, 79 deletions
diff --git a/app/assets/javascripts/tracking/constants.js b/app/assets/javascripts/tracking/constants.js index bc416b20e80..06d324a970f 100644 --- a/app/assets/javascripts/tracking/constants.js +++ b/app/assets/javascripts/tracking/constants.js @@ -31,8 +31,6 @@ export const REFERRER_TTL = 24 * 60 * 60 * 1000; export const GOOGLE_ANALYTICS_ID_COOKIE_NAME = '_ga'; -export const GITLAB_INTERNAL_EVENT_CATEGORY = 'InternalEventTracking'; - export const SERVICE_PING_SCHEMA = 'iglu:com.gitlab/gitlab_service_ping/jsonschema/1-0-1'; export const SERVICE_PING_SECURITY_CONFIGURATION_THREAT_MANAGEMENT_VISIT = diff --git a/app/assets/javascripts/tracking/internal_events.js b/app/assets/javascripts/tracking/internal_events.js index a6d14bfbfd8..7da6da16d6f 100644 --- a/app/assets/javascripts/tracking/internal_events.js +++ b/app/assets/javascripts/tracking/internal_events.js @@ -1,11 +1,7 @@ import API from '~/api'; import Tracking from './tracking'; -import { - GITLAB_INTERNAL_EVENT_CATEGORY, - LOAD_INTERNAL_EVENTS_SELECTOR, - SERVICE_PING_SCHEMA, -} from './constants'; +import { LOAD_INTERNAL_EVENTS_SELECTOR, SERVICE_PING_SCHEMA } from './constants'; import { Tracker } from './tracker'; import { InternalEventHandler, createInternalEventPayload } from './utils'; @@ -16,7 +12,7 @@ const InternalEvents = { */ trackEvent(event) { API.trackInternalEvent(event); - Tracking.event(GITLAB_INTERNAL_EVENT_CATEGORY, event, { + Tracking.event(undefined, event, { context: { schema: SERVICE_PING_SCHEMA, data: { diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index e93f95beb4f..7dccaa6cd73 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -3,13 +3,6 @@ module SessionsHelper include Gitlab::Utils::StrongMemoize - def recently_confirmed_com? - strong_memoize(:recently_confirmed_com) do - ::Gitlab.com? && - !!flash[:notice]&.include?(t(:confirmed, scope: [:devise, :confirmations])) - end - end - def unconfirmed_email? flash[:alert] == t(:unconfirmed, scope: [:devise, :failure]) end diff --git a/app/models/deployment.rb b/app/models/deployment.rb index 36f4a0ef426..66456413a98 100644 --- a/app/models/deployment.rb +++ b/app/models/deployment.rb @@ -9,6 +9,7 @@ class Deployment < ApplicationRecord include Gitlab::Utils::StrongMemoize include FastDestroyAll include IgnorableColumns + include EachBatch StatusUpdateError = Class.new(StandardError) StatusSyncError = Class.new(StandardError) diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index 7ba5b6119b9..033d90abc7a 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -159,6 +159,7 @@ module Projects destroy_web_hooks! destroy_project_bots! destroy_ci_records! + destroy_deployments! destroy_mr_diff_relations! destroy_merge_request_diffs! @@ -253,6 +254,12 @@ module Projects ) end + def destroy_deployments! + project.deployments.each_batch(of: BATCH_SIZE) do |deployments| + deployments.fast_destroy_all + end + end + # The project can have multiple webhooks with hundreds of thousands of web_hook_logs. # By default, they are removed with "DELETE CASCADE" option defined via foreign_key. # But such queries can exceed the statement_timeout limit and fail to delete the project. diff --git a/db/migrate/20240103200822_replace_fk_on_approval_merge_request_rules_scan_result_policy_id.rb b/db/migrate/20240103200822_replace_fk_on_approval_merge_request_rules_scan_result_policy_id.rb new file mode 100644 index 00000000000..431183e7212 --- /dev/null +++ b/db/migrate/20240103200822_replace_fk_on_approval_merge_request_rules_scan_result_policy_id.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +class ReplaceFkOnApprovalMergeRequestRulesScanResultPolicyId < Gitlab::Database::Migration[2.2] + disable_ddl_transaction! + milestone '16.8' + + NEW_CONSTRAINT_NAME = 'fk_approval_merge_request_rules_on_scan_result_policy_id' + + def up + add_concurrent_foreign_key( + :approval_merge_request_rules, + :scan_result_policies, + column: :scan_result_policy_id, + on_delete: :nullify, + validate: false, + name: NEW_CONSTRAINT_NAME) + end + + def down + with_lock_retries do + remove_foreign_key_if_exists(:approval_merge_request_rules, + column: :scan_result_policy_id, + on_delete: :nullify, + name: NEW_CONSTRAINT_NAME) + end + end +end diff --git a/db/migrate/20240103202629_validate_fk_on_approval_merge_request_rules_scan_result_policy_id.rb b/db/migrate/20240103202629_validate_fk_on_approval_merge_request_rules_scan_result_policy_id.rb new file mode 100644 index 00000000000..fee02ce91de --- /dev/null +++ b/db/migrate/20240103202629_validate_fk_on_approval_merge_request_rules_scan_result_policy_id.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class ValidateFkOnApprovalMergeRequestRulesScanResultPolicyId < Gitlab::Database::Migration[2.2] + milestone '16.8' + + NEW_CONSTRAINT_NAME = 'fk_approval_merge_request_rules_on_scan_result_policy_id' + + # foreign key added in db/migrate/20240103200822_replace_fk_on_approval_merge_request_rules_scan_result_policy_id.rb + def up + validate_foreign_key(:approval_merge_request_rules, :scan_result_policy_id, name: NEW_CONSTRAINT_NAME) + end + + def down + # no-op + end +end diff --git a/db/migrate/20240103203314_remove_old_fk_on_approval_merge_request_rules_scan_result_policy_id.rb b/db/migrate/20240103203314_remove_old_fk_on_approval_merge_request_rules_scan_result_policy_id.rb new file mode 100644 index 00000000000..7758b230242 --- /dev/null +++ b/db/migrate/20240103203314_remove_old_fk_on_approval_merge_request_rules_scan_result_policy_id.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +class RemoveOldFkOnApprovalMergeRequestRulesScanResultPolicyId < Gitlab::Database::Migration[2.2] + disable_ddl_transaction! + milestone '16.8' + + OLD_CONSTRAINT_NAME = 'fk_f726c79756' + + # new foreign key added in + # db/migrate/20240103200822_replace_fk_on_approval_merge_request_rules_scan_result_policy_id.rb + # and validated in db/migrate/20240103202629_validate_fk_on_approval_merge_request_rules_scan_result_policy_id.rb + def up + remove_foreign_key_if_exists( + :approval_merge_request_rules, + column: :scan_result_policy_id, + on_delete: :cascade, + name: OLD_CONSTRAINT_NAME) + end + + def down + add_concurrent_foreign_key( + :approval_merge_request_rules, + :scan_result_policies, + column: :scan_result_policy_id, + on_delete: :cascade, + validate: false, + name: OLD_CONSTRAINT_NAME) + end +end diff --git a/db/schema_migrations/20240103200822 b/db/schema_migrations/20240103200822 new file mode 100644 index 00000000000..896e75a009b --- /dev/null +++ b/db/schema_migrations/20240103200822 @@ -0,0 +1 @@ +7b4f74933360df0a49d44f0738922b0929b62f23aa60a36a5ae24c88a2857638
\ No newline at end of file diff --git a/db/schema_migrations/20240103202629 b/db/schema_migrations/20240103202629 new file mode 100644 index 00000000000..c2151c9fcd5 --- /dev/null +++ b/db/schema_migrations/20240103202629 @@ -0,0 +1 @@ +f5c40748ac911a2ee151a36b1a15d8080c4948e0439d25b791db2bb0ae57f7d9
\ No newline at end of file diff --git a/db/schema_migrations/20240103203314 b/db/schema_migrations/20240103203314 new file mode 100644 index 00000000000..ebb3382d1a9 --- /dev/null +++ b/db/schema_migrations/20240103203314 @@ -0,0 +1 @@ +9a638b98580e144b7a3e7ad6fc0833531ff63fbd94476310604f1581c8625200
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 0a048082a93..8c77da4afc5 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -38723,6 +38723,9 @@ ALTER TABLE ONLY dast_profile_schedules ALTER TABLE ONLY analytics_cycle_analytics_group_stages ADD CONSTRAINT fk_analytics_cycle_analytics_group_stages_group_value_stream_id FOREIGN KEY (group_value_stream_id) REFERENCES analytics_cycle_analytics_group_value_streams(id) ON DELETE CASCADE; +ALTER TABLE ONLY approval_merge_request_rules + ADD CONSTRAINT fk_approval_merge_request_rules_on_scan_result_policy_id FOREIGN KEY (scan_result_policy_id) REFERENCES scan_result_policies(id) ON DELETE SET NULL; + ALTER TABLE ONLY fork_network_members ADD CONSTRAINT fk_b01280dae4 FOREIGN KEY (forked_from_project_id) REFERENCES projects(id) ON DELETE SET NULL; @@ -39098,9 +39101,6 @@ ALTER TABLE ONLY boards_epic_list_user_preferences ALTER TABLE ONLY user_project_callouts ADD CONSTRAINT fk_f62dd11a33 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; -ALTER TABLE ONLY approval_merge_request_rules - ADD CONSTRAINT fk_f726c79756 FOREIGN KEY (scan_result_policy_id) REFERENCES scan_result_policies(id) ON DELETE CASCADE; - ALTER TABLE ONLY workspaces ADD CONSTRAINT fk_f78aeddc77 FOREIGN KEY (cluster_agent_id) REFERENCES cluster_agents(id) ON DELETE CASCADE; diff --git a/doc/administration/job_artifacts_troubleshooting.md b/doc/administration/job_artifacts_troubleshooting.md index 138803a2675..b8605ff94bf 100644 --- a/doc/administration/job_artifacts_troubleshooting.md +++ b/doc/administration/job_artifacts_troubleshooting.md @@ -24,7 +24,7 @@ reasons are: [Rake task for _orphaned_ artifact files](../raketasks/cleanup.md#remove-orphan-artifact-files) to remove these. This script should always find work to do, as it also removes empty directories (see above). - [Artifact housekeeping was changed significantly](#housekeeping-disabled-in-gitlab-146-to-152), - and you might need to enable a feature flag to used the updated system. + and you might need to enable a feature flag to use the updated system. - The [keep latest artifacts from most recent success jobs](../ci/jobs/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs) feature is enabled. @@ -220,7 +220,7 @@ end ### List projects by total size of job artifacts stored List the top 20 projects, sorted by the total size of job artifacts stored, by -running the following code in the Rails console (`sudo gitlab-rails console`): +running the following code in the [Rails console](operations/rails_console.md): ```ruby include ActionView::Helpers::NumberHelper @@ -235,7 +235,7 @@ number you want. ### List largest artifacts in a single project List the 50 largest job artifacts in a single project by running the following -code in the Rails console (`sudo gitlab-rails console`): +code in the [Rails console](operations/rails_console.md): ```ruby include ActionView::Helpers::NumberHelper @@ -273,7 +273,7 @@ WARNING: These commands remove data permanently from database and storage. Before running them, we highly recommend seeking guidance from a Support Engineer, or running them in a test environment with a backup of the instance ready to be restored, just in case. If you need to manually remove job artifacts associated with multiple jobs while -**retaining their job logs**, this can be done from the Rails console (`sudo gitlab-rails console`): +**retaining their job logs**, this can be done from the [Rails console](operations/rails_console.md): 1. Select jobs to be deleted: @@ -297,7 +297,7 @@ If you need to manually remove job artifacts associated with multiple jobs while ["keep"](../ci/jobs/job_artifacts.md#download-job-artifacts). ```ruby - builds_to_clear = builds_with_artifacts.where("finished_at < ?", 1.week.ago) + builds_to_clear = builds_with_artifacts.where("finished_at < ?", 1.year.ago) builds_to_clear.find_each do |build| Ci::JobArtifacts::DeleteService.new(build).execute build.update!(artifacts_expire_at: Time.now) @@ -307,19 +307,16 @@ If you need to manually remove job artifacts associated with multiple jobs while In [GitLab 15.3 and earlier](https://gitlab.com/gitlab-org/gitlab/-/issues/372537), use the following instead: ```ruby - builds_to_clear = builds_with_artifacts.where("finished_at < ?", 1.week.ago) + builds_to_clear = builds_with_artifacts.where("finished_at < ?", 1.year.ago) builds_to_clear.find_each do |build| build.artifacts_expire_at = Time.now build.erase_erasable_artifacts! end ``` - `1.week.ago` is a Rails `ActiveSupport::Duration` method which calculates a new - date or time in the past. Other valid examples are: - - - `7.days.ago` - - `3.months.ago` - - `1.year.ago` + `1.year.ago` is a Rails [`ActiveSupport::Duration`](https://api.rubyonrails.org/classes/ActiveSupport/Duration.html) method. + Start with a long duration to reduce the risk of accidentally deleting artifacts that are still in use. + Rerun the deletion with shorter durations as needed, for example `3.months.ago`, `2.weeks.ago`, or `7.days.ago`. `erase_erasable_artifacts!` is a synchronous method, and upon execution the artifacts are immediately removed; they are not scheduled by a background queue. @@ -330,7 +327,7 @@ WARNING: These commands remove data permanently from both the database and from disk. Before running them, we highly recommend seeking guidance from a Support Engineer, or running them in a test environment with a backup of the instance ready to be restored, just in case. If you need to manually remove **all** job artifacts associated with multiple jobs, -**including job logs**, this can be done from the Rails console (`sudo gitlab-rails console`): +**including job logs**, this can be done from the [Rails console](operations/rails_console.md): 1. Select the jobs to be deleted: @@ -371,7 +368,7 @@ If you need to manually remove **all** job artifacts associated with multiple jo 1. Erase the job artifacts and logs older than a specific date: ```ruby - builds_to_clear = builds_with_artifacts.where("finished_at < ?", 1.week.ago) + builds_to_clear = builds_with_artifacts.where("finished_at < ?", 1.year.ago) builds_to_clear.find_each do |build| print "Ci::Build ID #{build.id}... " @@ -387,12 +384,9 @@ If you need to manually remove **all** job artifacts associated with multiple jo In [GitLab 15.3 and earlier](https://gitlab.com/gitlab-org/gitlab/-/issues/369132), replace `Ci::BuildEraseService.new(build, admin_user).execute` with `build.erase(erased_by: admin_user)`. - `1.week.ago` is a Rails `ActiveSupport::Duration` method which calculates a new - date or time in the past. Other valid examples are: - - - `7.days.ago` - - `3.months.ago` - - `1.year.ago` + `1.year.ago` is a Rails [`ActiveSupport::Duration`](https://api.rubyonrails.org/classes/ActiveSupport/Duration.html) method. + Start with a long duration to reduce the risk of accidentally deleting artifacts that are still in use. + Rerun the deletion with shorter durations as needed, for example `3.months.ago`, `2.weeks.ago`, or `7.days.ago`. ## Job artifact upload fails with error 500 diff --git a/doc/ci/secrets/gcp_secret_manager.md b/doc/ci/secrets/gcp_secret_manager.md new file mode 100644 index 00000000000..ad2a2a269eb --- /dev/null +++ b/doc/ci/secrets/gcp_secret_manager.md @@ -0,0 +1,92 @@ +--- +stage: Verify +group: Pipeline Security +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 +--- + +# Use GCP Secret Manager secrets in GitLab CI/CD **(PREMIUM ALL)** + +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/11739) in GitLab and GitLab Runner 16.8. + +You can use secrets stored in the [Google Cloud (GCP) Secret Manager](https://cloud.google.com/security/products/secret-manager) +in your GitLab CI/CD pipelines. + +The flow for using GitLab with GCP Secret Manager +is summarized by this diagram: + +1. GitLab issues ID token to CI/CD job. +1. The runner authenticates to GCP using an ID token. +1. GCP verifies the ID token with GitLab. +1. GCP issues a short-lived access token. +1. The runner accesses the secret data using the access token. +1. GCP checks IAM permission on the access token's principal. +1. GCP returns the secret data to Runner. + +To use GitLab with GCP Secret Manager, you must: + +- Have secrets stored in [GCP Secret Manager](https://cloud.google.com/security/products/secret-manager). +- Configure [GCP Workload Identity Federation](#configure-gcp-iam-workload-identify-federation-wif) to include GitLab as an identity provider. +- Configure [GCP IAM](#grant-access-to-gcp-iam-principal) permissions to grant access to GCP Secret Manager. +- Configure [GitLab CI/CD with GCP Secret Manager](#configure-gitlab-cicd-to-use-gcp-secret-manager-secrets). + +## Configure GCP IAM Workload Identify Federation (WIF) + +GCP IAM WIF must be configured to recognize ID tokens issued by GitLab and assign an appropriate principal to them. +The principal is used to authorize access to the Secret Manager resources: + +1. In GCP Console, go to **IAM & Admin > Workload Identity Federation**. +1. Select **CREATE POOL** and create a new identity pool with a unique name, for example `gitlab-pool`. +1. Select **ADD PROVIDER** to add a new OIDC Provider to the Identity Pool with a unique name, for example `gitlab-provider`. + 1. Set **Issuer (URL)** to the GitLab URL, for example `https://gitlab.com`. + 1. Select **Default audience**, or select **Allowed audiences** for a custom audience, which is used in the `aud` for the GitLab CI/CD ID token. +1. Under **Attribute Mapping**, configure provider attributes, which are mappings between the [OIDC claims](id_token_authentication.md#token-payload) + (referred to as "assertion") and Google attributes. These mappings can be used to set fine grained access control. + For example, to grant a GitLab project access to Secret Manager secrets, select **ADD MAPPING** and create a mapping of + `attribute.gitlab_project_id` to `assertion.project_id`. + +## Grant access to GCP IAM principal + +After setting up WIF, you must grant the WIF principal access to the secrets in Secret Manager. + +1. In GCP Console, go to **IAM & Admin > IAM**. +1. Select **GRANT ACCESS** to grant access to the principal set created through the WIF provider. For example, + to grant IAM access to the principal matching the project with ID `123`, add + a new principal like: `principalSet://iam.googleapis.com/projects/[PROJECT_NUMBER]/locations/global/workloadIdentityPools/[POOL_ID]/attribute.gitlab_project_id/[PROJECT_ID]`. +1. Assign the role **Secret Manager Secret Accessor**. +1. (Optional) Select **IAM condition (Optional)** to add an IAM condition. + Under **Condition Builder**, you can add conditions. For example, you could add two `AND` conditions: + - First condition: + - **Condition type**: `Type` + - **Operator**: `is` + - **Resource type**: `secretmanager.googleapis.com/SecretVersion` + - Second condition: + - **Condition type**: `Name` + - **Operator**: `Starts with` + - **Value**: The pattern of secrets that you want to grant access to. + +You can add additional IAM conditions for fine-grained access controls, including +accessing secrets with names starting with the project name. + +## Configure GitLab CI/CD to use GCP Secret Manager secrets + +You can use secrets stored in GCP Secret Manager in CI/CD jobs by defining them with the `gcp_secret_manager` keyword: + +```yaml +job_using_gcp_sm: + id_tokens: + GCP_ID_TOKEN: + # `aud` must match the audience defined in the WIF Identity Pool. + aud: https://iam.googleapis.com/projects/1234/locations/global/workloadIdentityPools/gitlab-pool/providers/gitlab-provider + secrets: + DATABASE_PASSWORD: + gcp_secret_manager: + name: my-project-secret # This is the name of the secret defined in GCP Secret Manager + version: 1 # optional: default to `latest`. + token: $GCP_ID_TOKEN +``` + +You must also [add these CI/CD variables](../variables/index.md#for-a-project) to provide details about your GCP Secret Manager: + +- `GCP_PROJECT_NUMBER`: The GCP [Project Number](https://cloud.google.com/resource-manager/docs/creating-managing-projects) +- `GCP_WORKLOAD_IDENTITY_FEDERATION_POOL_ID`: The WIF Pool ID (e.g `gitlab-pool`) +- `GCP_WORKLOAD_IDENTITY_FEDERATION_PROVIDER_ID`: The WIF Provider ID (e.g `gitlab-provider`) diff --git a/doc/ci/secrets/index.md b/doc/ci/secrets/index.md index e452b26d8a9..96b9709bdef 100644 --- a/doc/ci/secrets/index.md +++ b/doc/ci/secrets/index.md @@ -18,6 +18,12 @@ Unlike CI/CD variables, which are always presented to a job, secrets must be exp required by a job. Read [GitLab CI/CD pipeline configuration reference](../yaml/index.md#secrets) for more information about the syntax. +GitLab provides support for the following secret management providers: + +1. [Vault by HashiCorp](#use-vault-secrets-in-a-ci-job) +1. [Google Cloud Secret Manager](gcp_secret_manager.md) +1. [Azure Key Vault](azure_key_vault.md) + GitLab has selected [Vault by HashiCorp](https://www.vaultproject.io) as the first supported provider, and [KV-V2](https://developer.hashicorp.com/vault/docs/secrets/kv/kv-v2) as the first supported secrets engine. diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md index 35b35567d8f..27f6113345f 100644 --- a/doc/ci/yaml/index.md +++ b/doc/ci/yaml/index.md @@ -4253,6 +4253,34 @@ job: vault: production/db/password@ops # Translates to secret: `ops/data/production/db`, field: `password` ``` +#### `secrets:gcp_secret_manager` + +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/11739) in GitLab 16.8 and GitLab Runner 16.8. + +Use `secrets:gcp_secret_manager` to specify secrets provided by [GCP Secret Manager](https://cloud.google.com/security/products/secret-manager). + +**Keyword type**: Job keyword. You can use it only as part of a job. + +**Possible inputs**: + +- `name`: Name of the secret. +- `version`: Version of the secret. + +**Example of `secrets:gcp_secret_manager`**: + +```yaml +job: + secrets: + DATABASE_PASSWORD: + gcp_secret_manager: + name: 'test' + version: 2 +``` + +**Related topics**: + +- [Use GCP Secret Manager secrets in GitLab CI/CD](../secrets/gcp_secret_manager.md). + #### `secrets:azure_key_vault` > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/271271) in GitLab 16.3 and GitLab Runner 16.3. diff --git a/doc/development/internal_analytics/index.md b/doc/development/internal_analytics/index.md index b5403f56600..0875ea7afad 100644 --- a/doc/development/internal_analytics/index.md +++ b/doc/development/internal_analytics/index.md @@ -95,7 +95,6 @@ SELECT COUNT(*) as event_occurences FROM common_mart.mart_behavior_structured_event WHERE event_action = 'feature_used' -AND event_category = 'InternalEventTracking' AND behavior_date > '2023-08-01' --restricted minimum date for performance AND app_id='gitlab' -- use gitlab for production events and gitlab-staging for events from staging GROUP BY 1 ORDER BY 1 desc diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 55739eae24b..c2da2cf6deb 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1934,6 +1934,12 @@ msgstr "" msgid "AIAgents|Create agent" msgstr "" +msgid "AIAgents|New AI Agent" +msgstr "" + +msgid "AIAgents|New agent" +msgstr "" + msgid "AIPoweredSM|AI-powered features" msgstr "" diff --git a/spec/features/search/user_searches_for_code_spec.rb b/spec/features/search/user_searches_for_code_spec.rb index 9329b1f2a5e..f893bf9b608 100644 --- a/spec/features/search/user_searches_for_code_spec.rb +++ b/spec/features/search/user_searches_for_code_spec.rb @@ -74,6 +74,20 @@ RSpec.describe 'User searches for code', :js, :disable_rate_limiter, feature_cat it_behaves_like 'code highlight' do subject { page } end + + context 'no search term' do + before do + submit_dashboard_search('dashboard_search') + # fill_in('dashboard_search', with: '') + # find('.gl-search-box-by-click-search-button').click + end + + it 'shows scopes' do + page.within('[data-testid="search-filter"]') do + expect(page).to have_selector('[data-testid="nav-item"]', minimum: 5) + end + end + end end it 'search multiple words with refs switching' do diff --git a/spec/features/search/user_searches_for_comments_spec.rb b/spec/features/search/user_searches_for_comments_spec.rb index f7af1797c71..92e9174295b 100644 --- a/spec/features/search/user_searches_for_comments_spec.rb +++ b/spec/features/search/user_searches_for_comments_spec.rb @@ -33,6 +33,14 @@ RSpec.describe 'User searches for comments', :js, :disable_rate_limiter, feature end end + it 'shows scopes when there is no search term' do + submit_dashboard_search('') + + within_testid('search-filter') do + expect(page).to have_selector('[data-testid="nav-item"]', minimum: 5) + end + end + context 'when a comment is in a snippet' do let(:snippet) { create(:project_snippet, :private, project: project, author: user, title: 'Some title') } let(:comment) { create(:note, noteable: snippet, author: user, note: 'Supercalifragilisticexpialidocious', project: project) } diff --git a/spec/features/search/user_searches_for_commits_spec.rb b/spec/features/search/user_searches_for_commits_spec.rb index 724daf9277d..2510a7f9b20 100644 --- a/spec/features/search/user_searches_for_commits_spec.rb +++ b/spec/features/search/user_searches_for_commits_spec.rb @@ -19,6 +19,14 @@ RSpec.describe 'User searches for commits', :js, :clean_gitlab_redis_rate_limiti let(:additional_params) { { project_id: project.id } } end + it 'shows scopes when there is no search term' do + submit_dashboard_search('') + + within_testid('search-filter') do + expect(page).to have_selector('[data-testid="nav-item"]', minimum: 5) + end + end + context 'when searching by SHA' do it 'finds a commit and redirects to its page' do submit_search(sha) diff --git a/spec/features/search/user_searches_for_issues_spec.rb b/spec/features/search/user_searches_for_issues_spec.rb index caddf8b698e..610b9e2f09d 100644 --- a/spec/features/search/user_searches_for_issues_spec.rb +++ b/spec/features/search/user_searches_for_issues_spec.rb @@ -103,6 +103,14 @@ RSpec.describe 'User searches for issues', :js, :clean_gitlab_redis_rate_limitin end end end + + it 'shows scopes when there is no search term' do + search_for_issue('') + + page.within('[data-testid="search-filter"]') do + expect(page).to have_selector('[data-testid="nav-item"]', minimum: 5) + end + end end context 'when signed out' do diff --git a/spec/features/search/user_searches_for_merge_requests_spec.rb b/spec/features/search/user_searches_for_merge_requests_spec.rb index 7819e036f21..faefa55586d 100644 --- a/spec/features/search/user_searches_for_merge_requests_spec.rb +++ b/spec/features/search/user_searches_for_merge_requests_spec.rb @@ -23,6 +23,14 @@ RSpec.describe 'User searches for merge requests', :js, :clean_gitlab_redis_rate include_examples 'top right search form' include_examples 'search timeouts', 'merge_requests' + it 'shows scopes when there is no search term' do + submit_dashboard_search('') + + page.within('[data-testid="search-filter"]') do + expect(page).to have_selector('[data-testid="nav-item"]', minimum: 5) + end + end + it 'finds a merge request' do search_for_mr(merge_request1.title) diff --git a/spec/features/search/user_searches_for_milestones_spec.rb b/spec/features/search/user_searches_for_milestones_spec.rb index 334fe6f0170..2700785ac1a 100644 --- a/spec/features/search/user_searches_for_milestones_spec.rb +++ b/spec/features/search/user_searches_for_milestones_spec.rb @@ -20,6 +20,14 @@ RSpec.describe 'User searches for milestones', :js, :clean_gitlab_redis_rate_lim include_examples 'top right search form' include_examples 'search timeouts', 'milestones' + it 'shows scopes when there is no search term' do + submit_dashboard_search('') + + page.within('[data-testid="search-filter"]') do + expect(page).to have_selector('[data-testid="nav-item"]', minimum: 5) + end + end + it 'finds a milestone' do submit_dashboard_search(milestone1.title) select_search_scope('Milestones') diff --git a/spec/features/search/user_searches_for_projects_spec.rb b/spec/features/search/user_searches_for_projects_spec.rb index ee5a3ec9806..8d94ed2a08e 100644 --- a/spec/features/search/user_searches_for_projects_spec.rb +++ b/spec/features/search/user_searches_for_projects_spec.rb @@ -14,6 +14,14 @@ RSpec.describe 'User searches for projects', :js, :disable_rate_limiter, feature include_examples 'top right search form' include_examples 'search timeouts', 'projects' + it 'shows scopes when there is no search term' do + submit_dashboard_search('') + + within_testid('search-filter') do + expect(page).to have_selector('[data-testid="nav-item"]', minimum: 5) + end + end + it 'finds a project' do visit(search_path) submit_dashboard_search(project.name[0..3]) diff --git a/spec/features/search/user_searches_for_users_spec.rb b/spec/features/search/user_searches_for_users_spec.rb index e0a07c5103d..2628b329d96 100644 --- a/spec/features/search/user_searches_for_users_spec.rb +++ b/spec/features/search/user_searches_for_users_spec.rb @@ -17,6 +17,14 @@ RSpec.describe 'User searches for users', :js, :clean_gitlab_redis_rate_limiting end end + it 'shows scopes when there is no search term' do + submit_dashboard_search('') + + within_testid('search-filter') do + expect(page).to have_selector('[data-testid="nav-item"]', minimum: 5) + end + end + context 'when on the dashboard' do it 'finds the user' do visit dashboard_projects_path diff --git a/spec/features/search/user_searches_for_wiki_pages_spec.rb b/spec/features/search/user_searches_for_wiki_pages_spec.rb index 4de28a99c21..85cc3900fad 100644 --- a/spec/features/search/user_searches_for_wiki_pages_spec.rb +++ b/spec/features/search/user_searches_for_wiki_pages_spec.rb @@ -23,6 +23,14 @@ RSpec.describe 'User searches for wiki pages', :js, :clean_gitlab_redis_rate_lim let(:additional_params) { { project_id: project.id } } end + it 'shows scopes when there is no search term' do + submit_dashboard_search('') + + page.within('[data-testid="search-filter"]') do + expect(page).to have_selector('[data-testid="nav-item"]', minimum: 5) + end + end + shared_examples 'search wiki blobs' do it 'finds a page' do find('[data-testid="project-filter"]').click diff --git a/spec/frontend/comment_templates/components/form_spec.js b/spec/frontend/comment_templates/components/form_spec.js index b48feba5290..05ddf94b72b 100644 --- a/spec/frontend/comment_templates/components/form_spec.js +++ b/spec/frontend/comment_templates/components/form_spec.js @@ -74,7 +74,7 @@ describe('Comment templates form component', () => { name: 'Test', }); expect(trackingSpy).toHaveBeenCalledWith( - expect.any(String), + undefined, 'i_code_review_saved_replies_create', expect.any(Object), ); diff --git a/spec/frontend/vue_shared/components/markdown/comment_templates_dropdown_spec.js b/spec/frontend/vue_shared/components/markdown/comment_templates_dropdown_spec.js index 11c57fc5768..01122fe1103 100644 --- a/spec/frontend/vue_shared/components/markdown/comment_templates_dropdown_spec.js +++ b/spec/frontend/vue_shared/components/markdown/comment_templates_dropdown_spec.js @@ -98,7 +98,7 @@ describe('Comment templates dropdown', () => { await selectSavedReply(); expect(trackingSpy).toHaveBeenCalledWith( - expect.any(String), + undefined, TRACKING_SAVED_REPLIES_USE, expect.any(Object), ); @@ -111,7 +111,7 @@ describe('Comment templates dropdown', () => { await selectSavedReply(); expect(trackingSpy).toHaveBeenCalledWith( - expect.any(String), + undefined, TRACKING_SAVED_REPLIES_USE_IN_MR, expect.any(Object), ); @@ -137,7 +137,7 @@ describe('Comment templates dropdown', () => { await selectSavedReply(); expect(trackingSpy).toHaveBeenCalledWith( - expect.any(String), + undefined, TRACKING_SAVED_REPLIES_USE_IN_OTHER, expect.any(Object), ); diff --git a/spec/helpers/sessions_helper_spec.rb b/spec/helpers/sessions_helper_spec.rb index 366032100de..adf7b92127e 100644 --- a/spec/helpers/sessions_helper_spec.rb +++ b/spec/helpers/sessions_helper_spec.rb @@ -3,42 +3,6 @@ require 'spec_helper' RSpec.describe SessionsHelper, feature_category: :system_access do - describe '#recently_confirmed_com?' do - subject { helper.recently_confirmed_com? } - - context 'when on .com' do - before do - allow(Gitlab).to receive(:com?).and_return(true) - end - - it 'when flash notice is empty it is false' do - flash[:notice] = nil - expect(subject).to be false - end - - it 'when flash notice is anything it is false' do - flash[:notice] = 'hooray!' - expect(subject).to be false - end - - it 'when flash notice is devise confirmed message it is true' do - flash[:notice] = t(:confirmed, scope: [:devise, :confirmations]) - expect(subject).to be true - end - end - - context 'when not on .com' do - before do - allow(Gitlab).to receive(:com?).and_return(false) - end - - it 'when flash notice is devise confirmed message it is false' do - flash[:notice] = t(:confirmed, scope: [:devise, :confirmations]) - expect(subject).to be false - end - end - end - describe '#unconfirmed_email?' do it 'returns true when the flash alert contains a devise failure unconfirmed message' do flash[:alert] = t(:unconfirmed, scope: [:devise, :failure]) diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb index b8217ffd2c9..2beab48fb73 100644 --- a/spec/models/deployment_spec.rb +++ b/spec/models/deployment_spec.rb @@ -56,6 +56,8 @@ RSpec.describe Deployment, feature_category: :continuous_delivery do let(:scope_attrs) { { project: project } } let(:usage) { :deployments } end + + it { is_expected.to include_module(EachBatch) } end describe '.stoppable' do diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb index 3aea329a45f..e5dd17a3c7c 100644 --- a/spec/services/projects/destroy_service_spec.rb +++ b/spec/services/projects/destroy_service_spec.rb @@ -166,6 +166,14 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi end end + context 'deleting a project with deployments' do + let!(:deployment) { create(:deployment, project: project) } + + it 'deletes deployments' do + expect { destroy_project(project, user, {}) }.to change(Deployment, :count).by(-1) + end + end + it_behaves_like 'deleting the project' context 'personal projects count cache' do |