diff options
172 files changed, 1635 insertions, 765 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index 588a46df00c..02258c366c5 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -1419,3 +1419,7 @@ ee/lib/ee/api/entities/project.rb @gitlab-org/manage/manage-workspace/backend-ap /ee/app/assets/javascripts/usage_quotas/components/ @fulfillment-group/utilization-group/fe /ee/app/assets/javascripts/usage_quotas/seats/ @fulfillment-group/utilization-group/fe /ee/app/assets/javascripts/usage_quotas/storage/ @fulfillment-group/utilization-group/fe + +[Manage::Foundations] +/lib/sidebars/ @gitlab/ @gitlab-org/manage/foundations/engineering +/ee/lib/sidebars/ @gitlab-org/manage/foundations/engineering
\ No newline at end of file diff --git a/.gitlab/ci/build-images.gitlab-ci.yml b/.gitlab/ci/build-images.gitlab-ci.yml index 9177913de18..4ee15ccb311 100644 --- a/.gitlab/ci/build-images.gitlab-ci.yml +++ b/.gitlab/ci/build-images.gitlab-ci.yml @@ -29,6 +29,33 @@ build-qa-image as-if-foss: - .as-if-foss - .build-images:rules:build-qa-image-as-if-foss +# Prepares an image with GDK configured based on code in master. This saves some time in MRs because some installation +# and complilation will have already been performed. +build-qa-on-gdk-master-image: + extends: + - .base-image-build-buildx + - .build-images:rules:build-qa-on-gdk-master-image + tags: + - e2e + stage: build-images + needs: [] + variables: + QA_GDK_IMAGE: "${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-qa-gdk" + before_script: + - !reference [.use-buildx, before_script] + - sysctl -n -w fs.inotify.max_user_watches=524288 + script: + - | + docker buildx build \ + --cache-to=type=inline \ + --cache-from ${QA_GDK_IMAGE}:master \ + --platform=${ARCH:-amd64} \ + --add-host gdk.test:127.0.0.1 \ + --tag ${QA_GDK_IMAGE}:master \ + --file="qa/gdk/Dockerfile" \ + --push \ + ${CI_PROJECT_DIR} + build-assets-image: extends: - .base-image-build diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml index 0ca20e95c47..a72e6fc0137 100644 --- a/.gitlab/ci/qa.gitlab-ci.yml +++ b/.gitlab/ci/qa.gitlab-ci.yml @@ -97,3 +97,20 @@ e2e:package-and-test: include: - artifact: package-and-test-pipeline.yml job: e2e-test-pipeline-generate + +e2e:test-on-gdk: + extends: + - .qa:rules:e2e:test-on-gdk + stage: qa + needs: + # In scheduled master pipelines we wait for the image to be built. + # In MRs we assume the last scheduled master pipeline built the image already. + - job: build-qa-on-gdk-master-image + optional: true + allow_failure: true + trigger: + strategy: depend + forward: + yaml_variables: true + pipeline_variables: true + include: .gitlab/ci/test-on-gdk/main.gitlab-ci.yml diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 53adc2936f3..d1e29084a5a 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -742,6 +742,19 @@ rules: - !reference [".build-images:rules:build-qa-image-merge-requests", "rules"] +# We want to rebuild the master image when the full e2e test pipeline runs. Currently this happens on a 2 hour schedule. +.build-images:rules:build-qa-on-gdk-master-image: + rules: + - if: '$QA_RUN_TESTS_ON_GDK !~ /true|yes|1/i' + when: never + - <<: *if-not-canonical-namespace + when: never + - <<: *if-not-ee + when: never + - <<: *if-dot-com-gitlab-org-schedule + variables: + ARCH: amd64,arm64 + .build-images:rules:build-assets-image: rules: - <<: *if-not-canonical-namespace @@ -1144,7 +1157,7 @@ allow_failure: true - <<: *if-ruby2-branch -.qa:rules:package-and-test: +.qa:rules:package-and-test-mrs: rules: - <<: *if-not-canonical-namespace when: never @@ -1184,6 +1197,13 @@ changes: *code-patterns when: manual allow_failure: true + - <<: *if-force-ci + when: manual + allow_failure: true + +.qa:rules:package-and-test: + rules: + - !reference [".qa:rules:package-and-test-mrs", rules] - <<: *if-dot-com-gitlab-org-schedule allow_failure: true variables: @@ -1192,9 +1212,12 @@ KNAPSACK_GENERATE_REPORT: "true" QA_SAVE_TEST_METRICS: "true" QA_EXPORT_TEST_METRICS: "false" # on main runs, metrics are exported to separate bucket via rake task for better consistency - - <<: *if-force-ci - when: manual - allow_failure: true + +.qa:rules:e2e:test-on-gdk: + rules: + - if: '$QA_RUN_TESTS_ON_GDK !~ /true|yes|1/i' + when: never + - !reference [".qa:rules:package-and-test", rules] ############### # Rails rules # @@ -2218,6 +2241,7 @@ - <<: *if-not-ee when: never - <<: *if-dot-com-ee-schedule-default-branch-maintenance + when: always - <<: *if-default-branch-refs changes: - ".gitlab/ci/test-metadata.gitlab-ci.yml" diff --git a/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml new file mode 100644 index 00000000000..a04d81fb342 --- /dev/null +++ b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml @@ -0,0 +1,81 @@ +default: + interruptible: true + +include: + - local: .gitlab/ci/package-and-test/rules.gitlab-ci.yml + +dont-interrupt-me: + extends: .rules:dont-interrupt + stage: test + interruptible: false + script: + - echo "This jobs makes sure this pipeline won't be interrupted! See https://docs.gitlab.com/ee/ci/yaml/#interruptible." + +.run-tests: + stage: test + image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/debian-bullseye-ruby-${RUBY_VERSION}:bundler-2.3-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION} + services: + - docker:${DOCKER_VERSION}-dind + tags: + - e2e + before_script: + - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY + - sysctl -n -w fs.inotify.max_user_watches=524288 + variables: + DOCKER_DRIVER: overlay2 + DOCKER_HOST: tcp://docker:2375 + QA_GDK_IMAGE: "${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-qa-gdk:master" + QA_GENERATE_ALLURE_REPORT: "false" + QA_CAN_TEST_PRAEFECT: "false" + QA_INTERCEPT_REQUESTS: "false" + QA_RUN_TYPE: e2e-test-on-gdk + TEST_LICENSE_MODE: $QA_TEST_LICENSE_MODE + EE_LICENSE: $QA_EE_LICENSE + GITHUB_ACCESS_TOKEN: $QA_GITHUB_ACCESS_TOKEN + GITLAB_QA_ADMIN_ACCESS_TOKEN: $QA_ADMIN_ACCESS_TOKEN + QA_KNAPSACK_REPORTS: qa-smoke,ee-instance-parallel + timeout: 2 hours + artifacts: + when: always + paths: + - test_output + - logs + expire_in: 7 days + script: + - echo -e "\e[0Ksection_start:`date +%s`:pull_image\r\e[0KPull GDK QA image" + - docker pull ${QA_GDK_IMAGE} + - echo -e "\e[0Ksection_end:`date +%s`:pull_image\r\e[0K" + - echo -e "\e[0Ksection_start:`date +%s`:launch_gdk_and_tests\r\e[0KLaunch GDK and run QA tests" + - cd qa && bundle install --jobs=$(nproc) --retry=3 --quiet + - mkdir -p $CI_PROJECT_DIR/test_output $CI_PROJECT_DIR/logs/gdk $CI_PROJECT_DIR/logs/gitlab + # This command matches the permissions of the user that runs GDK inside the container. + - chown -R 1000:1000 $CI_PROJECT_DIR/test_output $CI_PROJECT_DIR/logs + - | + docker run --rm --name gdk --add-host gdk.test:127.0.0.1 --shm-size=2gb \ + --env-file <(bundle exec rake ci:env_var_name_list) \ + --volume /var/run/docker.sock:/var/run/docker.sock:z \ + --volume $CI_PROJECT_DIR/test_output:/home/gdk/gdk/gitlab/qa/tmp:z \ + --volume $CI_PROJECT_DIR/logs/gdk:/home/gdk/gdk/log \ + --volume $CI_PROJECT_DIR/logs/gitlab:/home/gdk/gdk/gitlab/log \ + ${QA_GDK_IMAGE} "${CI_COMMIT_REF_SLUG}" "$TEST_GDK_TAGS --tag ~requires_praefect" || true + - echo -e "\e[0Ksection_end:`date +%s`:launch_gdk_and_tests\r\e[0K" + allow_failure: true + +test-on-gdk-smoke: + extends: + - .run-tests + parallel: 2 + variables: + TEST_GDK_TAGS: "--tag smoke" + QA_KNAPSACK_REPORT_NAME: qa-smoke + rules: + - when: always + +test-on-gdk-full: + extends: + - .run-tests + parallel: 5 + variables: + QA_KNAPSACK_REPORT_NAME: ee-instance-parallel + rules: + - when: manual diff --git a/.rubocop_todo/rspec/missing_feature_category.yml b/.rubocop_todo/rspec/missing_feature_category.yml index d85dd24d803..fa24075c566 100644 --- a/.rubocop_todo/rspec/missing_feature_category.yml +++ b/.rubocop_todo/rspec/missing_feature_category.yml @@ -1,6 +1,5 @@ --- RSpec/MissingFeatureCategory: - Details: grace period Exclude: - 'ee/spec/components/billing/plan_component_spec.rb' - 'ee/spec/components/namespaces/free_user_cap/enforcement_alert_component_spec.rb' @@ -45,10 +44,8 @@ RSpec/MissingFeatureCategory: - 'ee/spec/elastic/migrate/20210910100000_redo_backfill_namespace_ancestry_ids_for_issues_spec.rb' - 'ee/spec/elastic/migrate/20220118150500_delete_orphaned_commits_spec.rb' - 'ee/spec/elastic/migrate/20220512150000_pause_indexing_for_unsupported_es_versions_spec.rb' - - 'ee/spec/elastic/migrate/20220613120500_migrate_commits_to_separate_index_spec.rb' - 'ee/spec/elastic/migrate/20220824123000_add_label_ids_and_schema_version_to_issues_mapping_spec.rb' - 'ee/spec/elastic/migrate/20221026082700_backfill_users_spec.rb' - - 'ee/spec/elastic_integration/global_search_spec.rb' - 'ee/spec/elastic_integration/repository_index_spec.rb' - 'ee/spec/features/admin/admin_emails_spec.rb' - 'ee/spec/features/admin/admin_settings_spec.rb' @@ -63,7 +60,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/finders/auth/provisioned_users_finder_spec.rb' - 'ee/spec/finders/autocomplete/group_subgroups_finder_spec.rb' - 'ee/spec/finders/autocomplete/project_invited_groups_finder_spec.rb' - - 'ee/spec/finders/autocomplete/vulnerabilities_autocomplete_finder_spec.rb' - 'ee/spec/finders/billed_users_finder_spec.rb' - 'ee/spec/finders/boards/boards_finder_spec.rb' - 'ee/spec/finders/boards/epic_boards_finder_spec.rb' @@ -125,7 +121,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/finders/iterations_finder_spec.rb' - 'ee/spec/finders/license_template_finder_spec.rb' - 'ee/spec/finders/licenses_finder_spec.rb' - - 'ee/spec/finders/merge_requests/by_approvers_finder_spec.rb' - 'ee/spec/finders/merge_requests_finder_spec.rb' - 'ee/spec/finders/merge_trains_finder_spec.rb' - 'ee/spec/finders/notes_finder_spec.rb' @@ -791,7 +786,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/lib/ee/gitlab/import_export/after_export_strategies/custom_template_export_import_strategy_spec.rb' - 'ee/spec/lib/ee/gitlab/import_export/group/tree_restorer_spec.rb' - 'ee/spec/lib/ee/gitlab/import_export/group/tree_saver_spec.rb' - - 'ee/spec/lib/ee/gitlab/import_export/project/tree_restorer_spec.rb' - 'ee/spec/lib/ee/gitlab/import_export/project/tree_saver_spec.rb' - 'ee/spec/lib/ee/gitlab/import_export/repo_restorer_spec.rb' - 'ee/spec/lib/ee/gitlab/import_export/wiki_repo_saver_spec.rb' @@ -876,10 +870,8 @@ RSpec/MissingFeatureCategory: - 'ee/spec/lib/gitlab/analytics/cycle_analytics/stage_events/merge_request_last_edited_spec.rb' - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/base_dora_summary_spec.rb' - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/change_failure_rate_spec.rb' - - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_summary_spec.rb' - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/lead_time_for_changes_spec.rb' - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/lead_time_spec.rb' - - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/stage_time_summary_spec.rb' - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/time_to_restore_service_spec.rb' - 'ee/spec/lib/gitlab/analytics/type_of_work/tasks_by_type_spec.rb' - 'ee/spec/lib/gitlab/audit/auditor_spec.rb' @@ -985,7 +977,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/lib/gitlab/contribution_analytics/data_collector_spec.rb' - 'ee/spec/lib/gitlab/custom_file_templates_spec.rb' - 'ee/spec/lib/gitlab/customers_dot/jwt_spec.rb' - - 'ee/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb' - 'ee/spec/lib/gitlab/data_builder/vulnerability_spec.rb' - 'ee/spec/lib/gitlab/elastic/bulk_indexer_spec.rb' - 'ee/spec/lib/gitlab/elastic/client_spec.rb' @@ -1204,7 +1195,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/models/alert_management/alert_payload_field_spec.rb' - 'ee/spec/models/allowed_email_domain_spec.rb' - 'ee/spec/models/analytics/cycle_analytics/aggregation_context_spec.rb' - - 'ee/spec/models/analytics/cycle_analytics/group_level_spec.rb' - 'ee/spec/models/analytics/cycle_analytics/runtime_limiter_spec.rb' - 'ee/spec/models/analytics/devops_adoption/enabled_namespace_spec.rb' - 'ee/spec/models/analytics/devops_adoption/snapshot_spec.rb' @@ -1232,7 +1222,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/models/boards/epic_list_user_preference_spec.rb' - 'ee/spec/models/boards/epic_user_preference_spec.rb' - 'ee/spec/models/broadcast_message_spec.rb' - - 'ee/spec/models/burndown_spec.rb' - 'ee/spec/models/ci/bridge_spec.rb' - 'ee/spec/models/ci/build_spec.rb' - 'ee/spec/models/ci/daily_build_group_report_result_spec.rb' @@ -1265,7 +1254,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/models/concerns/elastic/issue_spec.rb' - 'ee/spec/models/concerns/elastic/merge_request_spec.rb' - 'ee/spec/models/concerns/elastic/milestone_spec.rb' - - 'ee/spec/models/concerns/elastic/note_spec.rb' - 'ee/spec/models/concerns/elastic/project_wiki_spec.rb' - 'ee/spec/models/concerns/elastic/projects_search_spec.rb' - 'ee/spec/models/concerns/elastic/repository_spec.rb' @@ -1326,7 +1314,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/models/ee/incident_management/project_incident_management_setting_spec.rb' - 'ee/spec/models/ee/integration_spec.rb' - 'ee/spec/models/ee/integrations/jira_spec.rb' - - 'ee/spec/models/ee/iteration_spec.rb' - 'ee/spec/models/ee/iterations/cadence_spec.rb' - 'ee/spec/models/ee/key_spec.rb' - 'ee/spec/models/ee/label_spec.rb' @@ -1358,11 +1345,9 @@ RSpec/MissingFeatureCategory: - 'ee/spec/models/ee/resource_state_event_spec.rb' - 'ee/spec/models/ee/service_desk_setting_spec.rb' - 'ee/spec/models/ee/system_note_metadata_spec.rb' - - 'ee/spec/models/ee/terraform/state_version_spec.rb' - 'ee/spec/models/ee/user_highest_role_spec.rb' - 'ee/spec/models/ee/users/merge_request_interaction_spec.rb' - 'ee/spec/models/ee/users_statistics_spec.rb' - - 'ee/spec/models/ee/work_items/type_spec.rb' - 'ee/spec/models/elastic/index_setting_spec.rb' - 'ee/spec/models/elastic/migration_record_spec.rb' - 'ee/spec/models/elastic/reindexing_slice_spec.rb' @@ -1802,7 +1787,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/services/ci/minutes/reset_usage_service_spec.rb' - 'ee/spec/services/ci/minutes/track_live_consumption_service_spec.rb' - 'ee/spec/services/ci/minutes/update_build_minutes_service_spec.rb' - - 'ee/spec/services/ci/minutes/update_project_and_namespace_usage_service_spec.rb' - 'ee/spec/services/ci/pipeline_bridge_status_service_spec.rb' - 'ee/spec/services/ci/pipeline_creation/drop_not_runnable_builds_service_spec.rb' - 'ee/spec/services/ci/pipeline_creation/start_pipeline_service_spec.rb' @@ -1888,15 +1872,12 @@ RSpec/MissingFeatureCategory: - 'ee/spec/services/ee/merge_requests/base_service_spec.rb' - 'ee/spec/services/ee/merge_requests/create_approval_event_service_spec.rb' - 'ee/spec/services/ee/merge_requests/create_from_vulnerability_data_service_spec.rb' - - 'ee/spec/services/ee/merge_requests/create_pipeline_service_spec.rb' - 'ee/spec/services/ee/merge_requests/create_service_spec.rb' - 'ee/spec/services/ee/merge_requests/execute_approval_hooks_service_spec.rb' - 'ee/spec/services/ee/merge_requests/handle_assignees_change_service_spec.rb' - 'ee/spec/services/ee/merge_requests/post_merge_service_spec.rb' - - 'ee/spec/services/ee/merge_requests/refresh_service_spec.rb' - 'ee/spec/services/ee/merge_requests/update_assignees_service_spec.rb' - 'ee/spec/services/ee/merge_requests/update_reviewers_service_spec.rb' - - 'ee/spec/services/ee/merge_requests/update_service_spec.rb' - 'ee/spec/services/ee/namespace_settings/update_service_spec.rb' - 'ee/spec/services/ee/notes/destroy_service_spec.rb' - 'ee/spec/services/ee/notes/post_process_service_spec.rb' @@ -2017,7 +1998,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/services/group_saml/saml_provider/update_service_spec.rb' - 'ee/spec/services/group_saml/sign_up_service_spec.rb' - 'ee/spec/services/groups/create_service_spec.rb' - - 'ee/spec/services/groups/destroy_service_spec.rb' - 'ee/spec/services/groups/epics_count_service_spec.rb' - 'ee/spec/services/groups/mark_for_deletion_service_spec.rb' - 'ee/spec/services/groups/memberships/export_service_spec.rb' @@ -2121,7 +2101,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/services/projects/cleanup_service_spec.rb' - 'ee/spec/services/projects/create_from_template_service_spec.rb' - 'ee/spec/services/projects/create_service_spec.rb' - - 'ee/spec/services/projects/destroy_service_spec.rb' - 'ee/spec/services/projects/disable_deploy_key_service_spec.rb' - 'ee/spec/services/projects/disable_legacy_inactive_projects_service_spec.rb' - 'ee/spec/services/projects/enable_deploy_key_service_spec.rb' @@ -2168,14 +2147,8 @@ RSpec/MissingFeatureCategory: - 'ee/spec/services/security/ingestion/ingest_report_slice_service_spec.rb' - 'ee/spec/services/security/ingestion/ingest_reports_service_spec.rb' - 'ee/spec/services/security/ingestion/mark_as_resolved_service_spec.rb' - - 'ee/spec/services/security/ingestion/tasks/attach_findings_to_vulnerabilities_spec.rb' - 'ee/spec/services/security/ingestion/tasks/hooks_execution_spec.rb' - 'ee/spec/services/security/ingestion/tasks/ingest_finding_evidence_spec.rb' - - 'ee/spec/services/security/ingestion/tasks/ingest_finding_identifiers_spec.rb' - - 'ee/spec/services/security/ingestion/tasks/ingest_finding_links_spec.rb' - - 'ee/spec/services/security/ingestion/tasks/ingest_finding_pipelines_spec.rb' - - 'ee/spec/services/security/ingestion/tasks/ingest_finding_signatures_spec.rb' - - 'ee/spec/services/security/ingestion/tasks/ingest_findings_spec.rb' - 'ee/spec/services/security/ingestion/tasks/ingest_identifiers_spec.rb' - 'ee/spec/services/security/ingestion/tasks/ingest_remediations_spec.rb' - 'ee/spec/services/security/ingestion/tasks/ingest_vulnerabilities/mark_resolved_as_detected_spec.rb' @@ -2365,7 +2338,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/workers/analytics/cycle_analytics/reaggregation_worker_spec.rb' - 'ee/spec/workers/analytics/devops_adoption/create_all_snapshots_worker_spec.rb' - 'ee/spec/workers/analytics/devops_adoption/create_snapshot_worker_spec.rb' - - 'ee/spec/workers/app_sec/dast/profile_schedule_worker_spec.rb' - 'ee/spec/workers/app_sec/dast/scanner_profiles_builds/consistency_worker_spec.rb' - 'ee/spec/workers/app_sec/dast/scans/consistency_worker_spec.rb' - 'ee/spec/workers/app_sec/dast/site_profiles_builds/consistency_worker_spec.rb' @@ -2437,7 +2409,6 @@ RSpec/MissingFeatureCategory: - 'ee/spec/workers/geo/reverification_batch_worker_spec.rb' - 'ee/spec/workers/geo/scheduler/per_shard_scheduler_worker_spec.rb' - 'ee/spec/workers/geo/scheduler/scheduler_worker_spec.rb' - - 'ee/spec/workers/geo/secondary/registry_consistency_worker_spec.rb' - 'ee/spec/workers/geo/secondary_usage_data_cron_worker_spec.rb' - 'ee/spec/workers/geo/sidekiq_cron_config_worker_spec.rb' - 'ee/spec/workers/geo/sync_timeout_cron_worker_spec.rb' @@ -2542,7 +2513,6 @@ RSpec/MissingFeatureCategory: - 'spec/controllers/admin/application_settings_controller_spec.rb' - 'spec/controllers/admin/applications_controller_spec.rb' - 'spec/controllers/admin/ci/variables_controller_spec.rb' - - 'spec/controllers/admin/clusters_controller_spec.rb' - 'spec/controllers/admin/cohorts_controller_spec.rb' - 'spec/controllers/admin/dashboard_controller_spec.rb' - 'spec/controllers/admin/dev_ops_report_controller_spec.rb' @@ -2552,7 +2522,6 @@ RSpec/MissingFeatureCategory: - 'spec/controllers/admin/hooks_controller_spec.rb' - 'spec/controllers/admin/identities_controller_spec.rb' - 'spec/controllers/admin/impersonations_controller_spec.rb' - - 'spec/controllers/admin/instance_review_controller_spec.rb' - 'spec/controllers/admin/integrations_controller_spec.rb' - 'spec/controllers/admin/jobs_controller_spec.rb' - 'spec/controllers/admin/plan_limits_controller_spec.rb' @@ -2601,26 +2570,21 @@ RSpec/MissingFeatureCategory: - 'spec/controllers/dashboard/groups_controller_spec.rb' - 'spec/controllers/dashboard/labels_controller_spec.rb' - 'spec/controllers/dashboard/milestones_controller_spec.rb' - - 'spec/controllers/dashboard/projects_controller_spec.rb' - 'spec/controllers/dashboard/snippets_controller_spec.rb' - 'spec/controllers/dashboard/todos_controller_spec.rb' - 'spec/controllers/every_controller_spec.rb' - 'spec/controllers/explore/groups_controller_spec.rb' - - 'spec/controllers/explore/projects_controller_spec.rb' - 'spec/controllers/explore/snippets_controller_spec.rb' - 'spec/controllers/google_api/authorizations_controller_spec.rb' - 'spec/controllers/groups/application_controller_spec.rb' - 'spec/controllers/groups/avatars_controller_spec.rb' - 'spec/controllers/groups/boards_controller_spec.rb' - - 'spec/controllers/groups/children_controller_spec.rb' - - 'spec/controllers/groups/clusters_controller_spec.rb' - 'spec/controllers/groups/dependency_proxies_controller_spec.rb' - 'spec/controllers/groups/dependency_proxy_auth_controller_spec.rb' - 'spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb' - 'spec/controllers/groups/group_links_controller_spec.rb' - 'spec/controllers/groups/group_members_controller_spec.rb' - 'spec/controllers/groups/imports_controller_spec.rb' - - 'spec/controllers/groups/labels_controller_spec.rb' - 'spec/controllers/groups/milestones_controller_spec.rb' - 'spec/controllers/groups/packages_controller_spec.rb' - 'spec/controllers/groups/registry/repositories_controller_spec.rb' @@ -2679,13 +2643,10 @@ RSpec/MissingFeatureCategory: - 'spec/controllers/projects/blame_controller_spec.rb' - 'spec/controllers/projects/blob_controller_spec.rb' - 'spec/controllers/projects/boards_controller_spec.rb' - - 'spec/controllers/projects/branches_controller_spec.rb' - 'spec/controllers/projects/ci/daily_build_group_report_results_controller_spec.rb' - 'spec/controllers/projects/ci/lints_controller_spec.rb' - 'spec/controllers/projects/ci/pipeline_editor_controller_spec.rb' - - 'spec/controllers/projects/clusters_controller_spec.rb' - 'spec/controllers/projects/commit_controller_spec.rb' - - 'spec/controllers/projects/commits_controller_spec.rb' - 'spec/controllers/projects/compare_controller_spec.rb' - 'spec/controllers/projects/cycle_analytics/events_controller_spec.rb' - 'spec/controllers/projects/cycle_analytics_controller_spec.rb' @@ -2702,20 +2663,15 @@ RSpec/MissingFeatureCategory: - 'spec/controllers/projects/feature_flags_controller_spec.rb' - 'spec/controllers/projects/feature_flags_user_lists_controller_spec.rb' - 'spec/controllers/projects/find_file_controller_spec.rb' - - 'spec/controllers/projects/forks_controller_spec.rb' - 'spec/controllers/projects/graphs_controller_spec.rb' - 'spec/controllers/projects/hooks_controller_spec.rb' - 'spec/controllers/projects/import/jira_controller_spec.rb' - 'spec/controllers/projects/imports_controller_spec.rb' - 'spec/controllers/projects/incidents_controller_spec.rb' - 'spec/controllers/projects/issue_links_controller_spec.rb' - - 'spec/controllers/projects/issues_controller_spec.rb' - - 'spec/controllers/projects/labels_controller_spec.rb' - 'spec/controllers/projects/mattermosts_controller_spec.rb' - 'spec/controllers/projects/merge_requests/conflicts_controller_spec.rb' - 'spec/controllers/projects/merge_requests/content_controller_spec.rb' - - 'spec/controllers/projects/merge_requests/creations_controller_spec.rb' - - 'spec/controllers/projects/merge_requests/diffs_controller_spec.rb' - 'spec/controllers/projects/merge_requests/drafts_controller_spec.rb' - 'spec/controllers/projects/milestones_controller_spec.rb' - 'spec/controllers/projects/mirrors_controller_spec.rb' @@ -2738,7 +2694,6 @@ RSpec/MissingFeatureCategory: - 'spec/controllers/projects/security/configuration_controller_spec.rb' - 'spec/controllers/projects/service_desk_controller_spec.rb' - 'spec/controllers/projects/service_ping_controller_spec.rb' - - 'spec/controllers/projects/settings/ci_cd_controller_spec.rb' - 'spec/controllers/projects/settings/integration_hook_logs_controller_spec.rb' - 'spec/controllers/projects/settings/merge_requests_controller_spec.rb' - 'spec/controllers/projects/settings/operations_controller_spec.rb' @@ -2756,7 +2711,6 @@ RSpec/MissingFeatureCategory: - 'spec/controllers/projects/web_ide_schemas_controller_spec.rb' - 'spec/controllers/projects/web_ide_terminals_controller_spec.rb' - 'spec/controllers/projects/wikis_controller_spec.rb' - - 'spec/controllers/projects_controller_spec.rb' - 'spec/controllers/repositories/git_http_controller_spec.rb' - 'spec/controllers/repositories/lfs_storage_controller_spec.rb' - 'spec/controllers/root_controller_spec.rb' @@ -2771,10 +2725,8 @@ RSpec/MissingFeatureCategory: - 'spec/controllers/users/terms_controller_spec.rb' - 'spec/controllers/users/unsubscribes_controller_spec.rb' - 'spec/db/development/add_security_training_providers_spec.rb' - - 'spec/db/development/create_base_work_item_types_spec.rb' - 'spec/db/development/import_common_metrics_spec.rb' - 'spec/db/production/add_security_training_providers_spec.rb' - - 'spec/db/production/create_base_work_item_types_spec.rb' - 'spec/db/production/import_common_metrics_spec.rb' - 'spec/db/production/settings_spec.rb' - 'spec/dependencies/omniauth_saml_spec.rb' @@ -2915,7 +2867,6 @@ RSpec/MissingFeatureCategory: - 'spec/finders/prometheus_metrics_finder_spec.rb' - 'spec/finders/protected_branches_finder_spec.rb' - 'spec/finders/releases/evidence_pipeline_finder_spec.rb' - - 'spec/finders/releases/group_releases_finder_spec.rb' - 'spec/finders/releases_finder_spec.rb' - 'spec/finders/repositories/branch_names_finder_spec.rb' - 'spec/finders/repositories/changelog_commits_finder_spec.rb' @@ -3573,7 +3524,6 @@ RSpec/MissingFeatureCategory: - 'spec/helpers/listbox_helper_spec.rb' - 'spec/helpers/markup_helper_spec.rb' - 'spec/helpers/members_helper_spec.rb' - - 'spec/helpers/merge_requests_helper_spec.rb' - 'spec/helpers/milestones_helper_spec.rb' - 'spec/helpers/namespaces_helper_spec.rb' - 'spec/helpers/nav/top_nav_helper_spec.rb' @@ -3658,7 +3608,6 @@ RSpec/MissingFeatureCategory: - 'spec/initializers/google_api_client_spec.rb' - 'spec/initializers/hangouts_chat_http_override_spec.rb' - 'spec/initializers/hashie_mash_permitted_patch_spec.rb' - - 'spec/initializers/load_balancing_spec.rb' - 'spec/initializers/lograge_spec.rb' - 'spec/initializers/mail_encoding_patch_spec.rb' - 'spec/initializers/mailer_retries_spec.rb' @@ -4105,7 +4054,6 @@ RSpec/MissingFeatureCategory: - 'spec/lib/gitlab/build_access_spec.rb' - 'spec/lib/gitlab/bullet/exclusions_spec.rb' - 'spec/lib/gitlab/bullet_spec.rb' - - 'spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb' - 'spec/lib/gitlab/cache/helpers_spec.rb' - 'spec/lib/gitlab/cache/import/caching_spec.rb' - 'spec/lib/gitlab/cache/metrics_spec.rb' @@ -4409,7 +4357,6 @@ RSpec/MissingFeatureCategory: - 'spec/lib/gitlab/ci/templates/katalon_gitlab_ci_yaml_spec.rb' - 'spec/lib/gitlab/ci/templates/templates_spec.rb' - 'spec/lib/gitlab/ci/templates/terraform_gitlab_ci_yaml_spec.rb' - - 'spec/lib/gitlab/ci/trace/archive_spec.rb' - 'spec/lib/gitlab/ci/trace/backoff_spec.rb' - 'spec/lib/gitlab/ci/trace/checksum_spec.rb' - 'spec/lib/gitlab/ci/trace/chunked_io_spec.rb' @@ -4476,7 +4423,6 @@ RSpec/MissingFeatureCategory: - 'spec/lib/gitlab/crypto_helper_spec.rb' - 'spec/lib/gitlab/current_settings_spec.rb' - 'spec/lib/gitlab/cycle_analytics/permissions_spec.rb' - - 'spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb' - 'spec/lib/gitlab/cycle_analytics/summary/value_spec.rb' - 'spec/lib/gitlab/cycle_analytics/updater_spec.rb' - 'spec/lib/gitlab/daemon_spec.rb' @@ -4527,7 +4473,6 @@ RSpec/MissingFeatureCategory: - 'spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb' - 'spec/lib/gitlab/database/load_balancing/srv_resolver_spec.rb' - 'spec/lib/gitlab/database/load_balancing/sticking_spec.rb' - - 'spec/lib/gitlab/database/load_balancing_spec.rb' - 'spec/lib/gitlab/database/loose_foreign_keys_spec.rb' - 'spec/lib/gitlab/database/migration_helpers/announce_database_spec.rb' - 'spec/lib/gitlab/database/migration_helpers/cascading_namespace_settings_spec.rb' @@ -4552,7 +4497,6 @@ RSpec/MissingFeatureCategory: - 'spec/lib/gitlab/database/migrations/runner_spec.rb' - 'spec/lib/gitlab/database/migrations/sidekiq_helpers_spec.rb' - 'spec/lib/gitlab/database/migrations/test_background_runner_spec.rb' - - 'spec/lib/gitlab/database/migrations/timeout_helpers_spec.rb' - 'spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb' - 'spec/lib/gitlab/database/obsolete_ignored_columns_spec.rb' - 'spec/lib/gitlab/database/partitioning/convert_table_to_first_list_partition_spec.rb' @@ -4587,12 +4531,8 @@ RSpec/MissingFeatureCategory: - 'spec/lib/gitlab/database/query_analyzers/ci/partitioning_routing_analyzer_spec.rb' - 'spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb' - 'spec/lib/gitlab/database/query_analyzers/restrict_allowed_schemas_spec.rb' - - 'spec/lib/gitlab/database/reflection_spec.rb' - 'spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb' - 'spec/lib/gitlab/database/reindexing/reindex_concurrently_spec.rb' - - 'spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb' - - 'spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb' - - 'spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb' - 'spec/lib/gitlab/database/rename_reserved_paths_migration/v1_spec.rb' - 'spec/lib/gitlab/database/schema_cache_with_renamed_table_spec.rb' - 'spec/lib/gitlab/database/schema_cleaner_spec.rb' @@ -4601,20 +4541,16 @@ RSpec/MissingFeatureCategory: - 'spec/lib/gitlab/database/sha_attribute_spec.rb' - 'spec/lib/gitlab/database/similarity_score_spec.rb' - 'spec/lib/gitlab/database/tables_sorted_by_foreign_keys_spec.rb' - - 'spec/lib/gitlab/database/transaction/observer_spec.rb' - 'spec/lib/gitlab/database/type/color_spec.rb' - 'spec/lib/gitlab/database/type/indifferent_jsonb_spec.rb' - 'spec/lib/gitlab/database/type/json_pg_safe_spec.rb' - 'spec/lib/gitlab/database/type/symbolized_jsonb_spec.rb' - 'spec/lib/gitlab/database/unidirectional_copy_trigger_spec.rb' - - 'spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb' - - 'spec/lib/gitlab/database/with_lock_retries_spec.rb' - 'spec/lib/gitlab/database_importers/common_metrics/importer_spec.rb' - 'spec/lib/gitlab/database_importers/common_metrics/prometheus_metric_spec.rb' - 'spec/lib/gitlab/database_importers/instance_administrators/create_group_spec.rb' - 'spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb' - 'spec/lib/gitlab/database_importers/self_monitoring/project/delete_service_spec.rb' - - 'spec/lib/gitlab/database_importers/work_items/base_type_importer_spec.rb' - 'spec/lib/gitlab/database_spec.rb' - 'spec/lib/gitlab/default_branch_spec.rb' - 'spec/lib/gitlab/dependency_linker/base_linker_spec.rb' @@ -5214,7 +5150,6 @@ RSpec/MissingFeatureCategory: - 'spec/lib/gitlab/metrics/subscribers/action_view_spec.rb' - 'spec/lib/gitlab/metrics/subscribers/active_record_spec.rb' - 'spec/lib/gitlab/metrics/subscribers/external_http_spec.rb' - - 'spec/lib/gitlab/metrics/subscribers/load_balancing_spec.rb' - 'spec/lib/gitlab/metrics/subscribers/rack_attack_spec.rb' - 'spec/lib/gitlab/metrics/subscribers/rails_cache_spec.rb' - 'spec/lib/gitlab/metrics/system_spec.rb' @@ -5798,8 +5733,6 @@ RSpec/MissingFeatureCategory: - 'spec/mailers/notify_spec.rb' - 'spec/mailers/previews_spec.rb' - 'spec/mailers/repository_check_mailer_spec.rb' - - 'spec/migrations/20221122132812_schedule_prune_stale_project_export_jobs_spec.rb' - - 'spec/migrations/20221205151917_schedule_backfill_environment_tier_spec.rb' - 'spec/models/ability_spec.rb' - 'spec/models/active_session_spec.rb' - 'spec/models/acts_as_taggable_on/tag_spec.rb' @@ -5992,7 +5925,6 @@ RSpec/MissingFeatureCategory: - 'spec/models/concerns/optionally_search_spec.rb' - 'spec/models/concerns/participable_spec.rb' - 'spec/models/concerns/partitioned_table_spec.rb' - - 'spec/models/concerns/pg_full_text_searchable_spec.rb' - 'spec/models/concerns/presentable_spec.rb' - 'spec/models/concerns/project_api_compatibility_spec.rb' - 'spec/models/concerns/project_features_compatibility_spec.rb' @@ -6033,7 +5965,6 @@ RSpec/MissingFeatureCategory: - 'spec/models/concerns/x509_serial_number_attribute_spec.rb' - 'spec/models/container_expiration_policy_spec.rb' - 'spec/models/container_registry/event_spec.rb' - - 'spec/models/container_repository_spec.rb' - 'spec/models/context_commits_diff_spec.rb' - 'spec/models/custom_emoji_spec.rb' - 'spec/models/customer_relations/contact_spec.rb' @@ -6189,13 +6120,11 @@ RSpec/MissingFeatureCategory: - 'spec/models/list_user_preference_spec.rb' - 'spec/models/loose_foreign_keys/deleted_record_spec.rb' - 'spec/models/loose_foreign_keys/modification_tracker_spec.rb' - - 'spec/models/member_spec.rb' - 'spec/models/members/group_member_spec.rb' - 'spec/models/members/last_group_owner_assigner_spec.rb' - 'spec/models/members/member_task_spec.rb' - 'spec/models/members/project_member_spec.rb' - 'spec/models/merge_request/approval_removal_settings_spec.rb' - - 'spec/models/merge_request/cleanup_schedule_spec.rb' - 'spec/models/merge_request/diff_commit_user_spec.rb' - 'spec/models/merge_request/metrics_spec.rb' - 'spec/models/merge_request_assignee_spec.rb' @@ -7168,7 +7097,6 @@ RSpec/MissingFeatureCategory: - 'spec/services/groups/deploy_tokens/create_service_spec.rb' - 'spec/services/groups/deploy_tokens/destroy_service_spec.rb' - 'spec/services/groups/deploy_tokens/revoke_service_spec.rb' - - 'spec/services/groups/destroy_service_spec.rb' - 'spec/services/groups/group_links/create_service_spec.rb' - 'spec/services/groups/group_links/destroy_service_spec.rb' - 'spec/services/groups/group_links/update_service_spec.rb' @@ -7222,7 +7150,6 @@ RSpec/MissingFeatureCategory: - 'spec/services/issues/close_service_spec.rb' - 'spec/services/issues/create_service_spec.rb' - 'spec/services/issues/duplicate_service_spec.rb' - - 'spec/services/issues/move_service_spec.rb' - 'spec/services/issues/prepare_import_csv_service_spec.rb' - 'spec/services/issues/referenced_merge_requests_service_spec.rb' - 'spec/services/issues/related_branches_service_spec.rb' @@ -7279,19 +7206,15 @@ RSpec/MissingFeatureCategory: - 'spec/services/merge_requests/approval_service_spec.rb' - 'spec/services/merge_requests/assign_issues_service_spec.rb' - 'spec/services/merge_requests/cleanup_refs_service_spec.rb' - - 'spec/services/merge_requests/close_service_spec.rb' - 'spec/services/merge_requests/conflicts/list_service_spec.rb' - 'spec/services/merge_requests/conflicts/resolve_service_spec.rb' - 'spec/services/merge_requests/create_approval_event_service_spec.rb' - - 'spec/services/merge_requests/create_from_issue_service_spec.rb' - 'spec/services/merge_requests/create_pipeline_service_spec.rb' - - 'spec/services/merge_requests/create_service_spec.rb' - 'spec/services/merge_requests/delete_non_latest_diffs_service_spec.rb' - 'spec/services/merge_requests/execute_approval_hooks_service_spec.rb' - 'spec/services/merge_requests/ff_merge_service_spec.rb' - 'spec/services/merge_requests/get_urls_service_spec.rb' - 'spec/services/merge_requests/handle_assignees_change_service_spec.rb' - - 'spec/services/merge_requests/link_lfs_objects_service_spec.rb' - 'spec/services/merge_requests/mark_reviewer_reviewed_service_spec.rb' - 'spec/services/merge_requests/merge_orchestration_service_spec.rb' - 'spec/services/merge_requests/merge_service_spec.rb' @@ -7309,15 +7232,12 @@ RSpec/MissingFeatureCategory: - 'spec/services/merge_requests/migrate_external_diffs_service_spec.rb' - 'spec/services/merge_requests/post_merge_service_spec.rb' - 'spec/services/merge_requests/push_options_handler_service_spec.rb' - - 'spec/services/merge_requests/pushed_branches_service_spec.rb' - - 'spec/services/merge_requests/rebase_service_spec.rb' - 'spec/services/merge_requests/reload_diffs_service_spec.rb' - 'spec/services/merge_requests/reload_merge_head_diff_service_spec.rb' - 'spec/services/merge_requests/reopen_service_spec.rb' - 'spec/services/merge_requests/request_review_service_spec.rb' - 'spec/services/merge_requests/resolve_todos_service_spec.rb' - 'spec/services/merge_requests/resolved_discussion_notification_service_spec.rb' - - 'spec/services/merge_requests/retarget_chain_service_spec.rb' - 'spec/services/merge_requests/squash_service_spec.rb' - 'spec/services/merge_requests/update_assignees_service_spec.rb' - 'spec/services/merge_requests/update_reviewers_service_spec.rb' @@ -7420,7 +7340,6 @@ RSpec/MissingFeatureCategory: - 'spec/services/packages/update_package_file_service_spec.rb' - 'spec/services/packages/update_tags_service_spec.rb' - 'spec/services/pages/delete_service_spec.rb' - - 'spec/services/pages/migrate_from_legacy_storage_service_spec.rb' - 'spec/services/pages/migrate_legacy_storage_to_deployment_service_spec.rb' - 'spec/services/pages/zip_directory_service_spec.rb' - 'spec/services/pages_domains/create_acme_order_service_spec.rb' @@ -7455,7 +7374,6 @@ RSpec/MissingFeatureCategory: - 'spec/services/projects/create_from_template_service_spec.rb' - 'spec/services/projects/deploy_tokens/create_service_spec.rb' - 'spec/services/projects/deploy_tokens/destroy_service_spec.rb' - - 'spec/services/projects/destroy_service_spec.rb' - 'spec/services/projects/detect_repository_languages_service_spec.rb' - 'spec/services/projects/download_service_spec.rb' - 'spec/services/projects/enable_deploy_key_service_spec.rb' @@ -7904,7 +7822,6 @@ RSpec/MissingFeatureCategory: - 'spec/views/projects/jobs/show.html.haml_spec.rb' - 'spec/views/projects/merge_requests/_close_reopen_draft_report_toggle.html.haml_spec.rb' - 'spec/views/projects/merge_requests/_commits.html.haml_spec.rb' - - 'spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb' - 'spec/views/projects/merge_requests/edit.html.haml_spec.rb' - 'spec/views/projects/merge_requests/show.html.haml_spec.rb' - 'spec/views/projects/milestones/index.html.haml_spec.rb' @@ -7973,7 +7890,6 @@ RSpec/MissingFeatureCategory: - 'spec/workers/ci/delete_objects_worker_spec.rb' - 'spec/workers/ci/delete_unit_tests_worker_spec.rb' - 'spec/workers/ci/drop_pipeline_worker_spec.rb' - - 'spec/workers/ci/external_pull_requests/create_pipeline_worker_spec.rb' - 'spec/workers/ci/job_artifacts/expire_project_build_artifacts_worker_spec.rb' - 'spec/workers/ci/job_artifacts/track_artifact_report_worker_spec.rb' - 'spec/workers/ci/merge_requests/add_todo_when_build_fails_worker_spec.rb' diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 9153b5364c1..c75f591c824 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -cfc26d1625b38163a88a48c67fdf7e1598e38f81 +8d2bce18d28dcffcaac90d0b2cb8815af07beef1 @@ -378,7 +378,7 @@ group :development do gem 'solargraph', '~> 0.47.2', require: false gem 'letter_opener_web', '~> 2.0.0' - gem 'lookbook', '~> 1.4', '>= 1.4.5' + gem 'lookbook', '~> 1.5', '>= 1.5.3' # Better errors handler gem 'better_errors', '~> 2.9.1' diff --git a/Gemfile.checksum b/Gemfile.checksum index a68b2f221ef..338358973e2 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -163,7 +163,7 @@ {"name":"faraday_middleware-aws-sigv4","version":"0.3.0","platform":"ruby","checksum":"744654bd5b15539a54aed39b806e2dfb45aa47708fa1e6f6766fedcda6c262be"}, {"name":"faraday_middleware-multi_json","version":"0.0.6","platform":"ruby","checksum":"38fc4dab7a78916ad09827d5a164aab62fbf2cb8b9de0507763de1f561d7a118"}, {"name":"fast_blank","version":"1.0.0","platform":"ruby","checksum":"a67c93dbcb8c34ba40973688e4b600b640760503362f3aeb63b37ebe3d8d419b"}, -{"name":"fast_gettext","version":"2.1.0","platform":"ruby","checksum":"0d095dbc5a003b3caea13b9569288703086ae05aac2cc6d7b0881c8e0a07ae15"}, +{"name":"fast_gettext","version":"2.3.0","platform":"ruby","checksum":"0253e26423ccab68061c42387827e3b99243a1b15ad614df1c800ba870d64f84"}, {"name":"ffaker","version":"2.10.0","platform":"ruby","checksum":"4323b85b4bbdb0d932695b2ebffeb3645304215092e64e2a451630a9f5a5e507"}, {"name":"ffi","version":"1.15.5","platform":"java","checksum":"610b9a993e67b812123cfedc1c45a639aa2f2455747af5443d54f98e092b1abe"}, {"name":"ffi","version":"1.15.5","platform":"ruby","checksum":"6f2ed2fa68047962d6072b964420cba91d82ce6fa8ee251950c17fca6af3c2a0"}, @@ -326,7 +326,7 @@ {"name":"lockbox","version":"1.1.1","platform":"ruby","checksum":"0af16b14c54f791c148615a0115387b51903d868c7fe622f49606c97071c2ac0"}, {"name":"lograge","version":"0.11.2","platform":"ruby","checksum":"4cbd1554b86f545d795eff15a0c24fd25057d2ac4e1caa5fc186168b3da932ef"}, {"name":"loofah","version":"2.19.1","platform":"ruby","checksum":"6c6469efdefe3496010000a346f9d3bf710e11ac4661e353cf56852326fb1023"}, -{"name":"lookbook","version":"1.4.5","platform":"ruby","checksum":"bc15b332d2c84f51aca60353f070c0b6a363b7496259e1dd7572d5ec122c9cdb"}, +{"name":"lookbook","version":"1.5.3","platform":"ruby","checksum":"4a0ff475af85de0dcdf45a5541fbc40dd8f66669a559efe8297c1d7fee028b38"}, {"name":"lru_redux","version":"1.1.0","platform":"ruby","checksum":"ee71d0ccab164c51de146c27b480a68b3631d5b4297b8ffe8eda1c72de87affb"}, {"name":"lumberjack","version":"1.2.7","platform":"ruby","checksum":"a5c6aae6b4234f1420dbcd80b23e3bca0817bd239440dde097ebe3fa63c63b1f"}, {"name":"mail","version":"2.7.1","platform":"ruby","checksum":"ec2a3d489f7510b90d8eaa3f6abaad7038cf1d663cdf8ee66d0214a0bdf99c03"}, @@ -470,7 +470,7 @@ {"name":"re2","version":"1.6.0","platform":"ruby","checksum":"2e37f27971f6a76223eac688c04f3e48aea374f34b302ec22d75b4635cd64bc1"}, {"name":"recaptcha","version":"5.12.3","platform":"ruby","checksum":"37d1894add9e70a54d0c6c7f0ecbeedffbfa7d075acfbd4c509818dfdebdb7ee"}, {"name":"recursive-open-struct","version":"1.1.3","platform":"ruby","checksum":"a3538a72552fcebcd0ada657bdff313641a4a5fbc482c08cfb9a65acb1c9de5a"}, -{"name":"redcarpet","version":"3.5.1","platform":"ruby","checksum":"717f64cb6ec11c8d9ec9b521ed26ca2eeda68b4fe1fc3388a641176dbd47732f"}, +{"name":"redcarpet","version":"3.6.0","platform":"ruby","checksum":"8ad1889c0355ff4c47174af14edd06d62f45a326da1da6e8a121d59bdcd2e9e9"}, {"name":"redis","version":"4.8.0","platform":"ruby","checksum":"2000cf5014669c9dc821704b6d322a35a9a33852a95208911d9175d63b448a44"}, {"name":"redis-actionpack","version":"5.3.0","platform":"ruby","checksum":"3fb1ad0a8fd9d26a289c9399bb609dcaef38bf37711e6f677a53ca728fc19140"}, {"name":"redis-namespace","version":"1.9.0","platform":"ruby","checksum":"0923961f38cf15b86cb57d92507e0a3b32480729eb5033249f5de8b12e0d8612"}, diff --git a/Gemfile.lock b/Gemfile.lock index 2a5a163dcc5..ca37508841b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -478,7 +478,7 @@ GEM faraday_middleware multi_json fast_blank (1.0.0) - fast_gettext (2.1.0) + fast_gettext (2.3.0) ffaker (2.10.0) ffi (1.15.5) ffi-compiler (1.0.1) @@ -883,7 +883,7 @@ GEM loofah (2.19.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) - lookbook (1.4.5) + lookbook (1.5.3) actioncable activemodel css_parser @@ -893,7 +893,7 @@ GEM railties (>= 5.0) redcarpet (~> 3.5) rouge (>= 3.26, < 5.0) - view_component (~> 2.0) + view_component (> 2.0, < 4) yard (~> 0.9.25) zeitwerk (~> 2.5) lru_redux (1.1.0) @@ -1188,7 +1188,7 @@ GEM recaptcha (5.12.3) json recursive-open-struct (1.1.3) - redcarpet (3.5.1) + redcarpet (3.6.0) redis (4.8.0) redis-actionpack (5.3.0) actionpack (>= 5, < 8) @@ -1746,7 +1746,7 @@ DEPENDENCIES lockbox (~> 1.1.1) lograge (~> 0.5) loofah (~> 2.19.1) - lookbook (~> 1.4, >= 1.4.5) + lookbook (~> 1.5, >= 1.5.3) lru_redux mail (= 2.7.1) mail-smtp_pool (~> 0.1.0)! diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue index 2f521363c16..a1a49386b37 100644 --- a/app/assets/javascripts/boards/components/boards_selector.vue +++ b/app/assets/javascripts/boards/components/boards_selector.vue @@ -68,11 +68,11 @@ export default { data() { return { hasScrollFade: false, - loadingBoards: 0, - loadingRecentBoards: false, scrollFadeInitialized: false, boards: [], recentBoards: [], + loadingBoards: false, + loadingRecentBoards: false, throttledSetScrollFade: throttle(this.setScrollFade, this.throttleDuration), contentClientHeight: 0, maxPosition: 0, @@ -90,7 +90,7 @@ export default { return this.boardType; }, loading() { - return this.loadingRecentBoards || Boolean(this.loadingBoards); + return this.loadingRecentBoards || this.loadingBoards; }, filteredBoards() { return this.boards.filter((board) => @@ -171,8 +171,10 @@ export default { return { fullPath: this.fullPath }; }, query: this.boardQuery, - loadingKey: 'loadingBoards', update: (data) => this.boardUpdate(data, 'boards'), + watchLoading: (isLoading) => { + this.loadingBoards = isLoading; + }, }); this.loadRecentBoards(); @@ -183,8 +185,10 @@ export default { return { fullPath: this.fullPath }; }, query: this.recentBoardsQuery, - loadingKey: 'loadingRecentBoards', update: (data) => this.boardUpdate(data, 'recentIssueBoards'), + watchLoading: (isLoading) => { + this.loadingRecentBoards = isLoading; + }, }); }, isScrolledUp() { diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue index e5695c4390f..dfca6d61270 100644 --- a/app/assets/javascripts/diffs/components/diff_row.vue +++ b/app/assets/javascripts/diffs/components/diff_row.vue @@ -60,6 +60,16 @@ export default { type: Boolean, required: true, }, + isFirstHighlightedLine: { + type: Boolean, + required: false, + default: false, + }, + isLastHighlightedLine: { + type: Boolean, + required: false, + default: false, + }, fileLineCoverage: { type: Function, required: true, @@ -81,12 +91,23 @@ export default { ), parallelViewLeftLineType: memoize( (props) => { - return utils.parallelViewLeftLineType(props.line, props.isHighlighted || props.isCommented); + return utils.parallelViewLeftLineType({ + line: props.line, + highlighted: props.isHighlighted, + commented: props.isCommented, + selectionStart: props.isFirstHighlightedLine, + selectionEnd: props.isLastHighlightedLine, + }); }, (props) => - [props.line.left?.type, props.line.right?.type, props.isHighlighted, props.isCommented].join( - ':', - ), + [ + props.line.left?.type, + props.line.right?.type, + props.isHighlighted, + props.isCommented, + props.isFirstHighlightedLine, + props.isLastHighlightedLine, + ].join(':'), ), coverageStateLeft: memoize( (props) => { @@ -118,20 +139,40 @@ export default { classNameMapCellLeft: memoize( (props) => { return utils.classNameMapCell({ - line: props.line.left, - hll: props.isHighlighted || props.isCommented, + line: props.line?.left, + highlighted: props.isHighlighted, + commented: props.isCommented, + selectionStart: props.isFirstHighlightedLine, + selectionEnd: props.isLastHighlightedLine, }); }, - (props) => [props.line.left.type, props.isHighlighted, props.isCommented].join(':'), + (props) => + [ + props.line?.left?.type, + props.isHighlighted, + props.isCommented, + props.isFirstHighlightedLine, + props.isLastHighlightedLine, + ].join(':'), ), classNameMapCellRight: memoize( (props) => { return utils.classNameMapCell({ - line: props.line.right, - hll: props.isHighlighted || props.isCommented, + line: props.line?.right, + highlighted: props.isHighlighted, + commented: props.isCommented, + selectionStart: props.isFirstHighlightedLine, + selectionEnd: props.isLastHighlightedLine, }); }, - (props) => [props.line.right.type, props.isHighlighted, props.isCommented].join(':'), + (props) => + [ + props.line?.right?.type, + props.isHighlighted, + props.isCommented, + props.isFirstHighlightedLine, + props.isLastHighlightedLine, + ].join(':'), ), shouldRenderCommentButton: memoize( (props) => { @@ -303,15 +344,24 @@ export default { !props.inline || (props.line.left && props.line.left.type === $options.CONFLICT_MARKER) " > - <div data-testid="left-empty-cell" class="diff-td diff-line-num old_line empty-cell"> + <div + data-testid="left-empty-cell" + class="diff-td diff-line-num old_line empty-cell" + :class="$options.classNameMapCellLeft(props)" + > </div> - <div v-if="props.inline" class="diff-td diff-line-num old_line empty-cell"></div> - <div class="diff-td line-coverage left-side empty-cell"></div> - <div v-if="props.inline" class="diff-td line-codequality left-side empty-cell"></div> + <div + class="diff-td line-coverage left-side empty-cell" + :class="$options.classNameMapCellLeft(props)" + ></div> + <div + class="diff-td line-codequality left-side empty-cell" + :class="$options.classNameMapCellLeft(props)" + ></div> <div class="diff-td line_content with-coverage left-side empty-cell" - :class="[{ parallel: !props.inline }]" + :class="[{ parallel: !props.inline }, ...$options.classNameMapCellLeft(props)]" ></div> </template> </div> @@ -390,13 +440,13 @@ export default { :class="[ props.line.right.type, $options.coverageStateRight(props).class, - { hll: props.isHighlighted, hll: props.isCommented }, + ...$options.classNameMapCellRight(props), ]" class="diff-td line-coverage right-side has-tooltip" ></div> <div class="diff-td line-codequality right-side" - :class="[props.line.right.type, { hll: props.isHighlighted, hll: props.isCommented }]" + :class="$options.classNameMapCellRight(props)" > <component :is="$options.CodeQualityGutterIcon" @@ -414,10 +464,9 @@ export default { :class="[ props.line.right.type, { - hll: props.isHighlighted, - hll: props.isCommented, 'gl-font-weight-bold': props.line.right.type === $options.CONFLICT_MARKER_THEIR, }, + ...$options.classNameMapCellRight(props), ]" class="diff-td line_content with-coverage right-side parallel" v-html=" @@ -426,10 +475,23 @@ export default { ></div> </template> <template v-else> - <div data-testid="right-empty-cell" class="diff-td diff-line-num old_line empty-cell"></div> - <div class="diff-td line-coverage right-side empty-cell"></div> - <div class="diff-td line-codequality right-side empty-cell"></div> - <div class="diff-td line_content with-coverage right-side empty-cell parallel"></div> + <div + data-testid="right-empty-cell" + class="diff-td diff-line-num old_line empty-cell" + :class="$options.classNameMapCellRight(props)" + ></div> + <div + class="diff-td line-coverage right-side empty-cell" + :class="$options.classNameMapCellRight(props)" + ></div> + <div + class="diff-td line-codequality right-side empty-cell" + :class="$options.classNameMapCellRight(props)" + ></div> + <div + class="diff-td line_content with-coverage right-side empty-cell parallel" + :class="$options.classNameMapCellRight(props)" + ></div> </template> </div> </div> diff --git a/app/assets/javascripts/diffs/components/diff_row_utils.js b/app/assets/javascripts/diffs/components/diff_row_utils.js index 479853caae3..a489c96b0c9 100644 --- a/app/assets/javascripts/diffs/components/diff_row_utils.js +++ b/app/assets/javascripts/diffs/components/diff_row_utils.js @@ -40,19 +40,33 @@ export const lineCode = (line) => { return line.line_code || line.left?.line_code || line.right?.line_code; }; -export const classNameMapCell = ({ line, hll, isLoggedIn, isHover }) => { - if (!line) return []; - const { type } = line; +export const classNameMapCell = ({ + line, + highlighted, + commented, + selectionStart, + selectionEnd, + isLoggedIn, + isHover, +}) => { + const classes = { + 'highlight-top': highlighted || selectionStart, + 'highlight-bottom': highlighted || selectionEnd, + hll: highlighted, + commented, + }; - return [ - type, - { - hll, + if (line) { + const { type } = line; + Object.assign(classes, { + [type]: true, [LINE_HOVER_CLASS_NAME]: isLoggedIn && isHover && !isContextLine(type) && !isMetaLine(type), - old_line: line.type === 'old', - new_line: line.type === 'new', - }, - ]; + old_line: type === 'old', + new_line: type === 'new', + }); + } + + return [classes]; }; export const addCommentTooltip = (line) => { @@ -88,14 +102,28 @@ export const addCommentTooltip = (line) => { return tooltip; }; -export const parallelViewLeftLineType = (line, hll) => { +export const parallelViewLeftLineType = ({ + line, + highlighted, + commented, + selectionStart, + selectionEnd, +}) => { if (line?.right?.type === NEW_NO_NEW_LINE_TYPE) { return OLD_NO_NEW_LINE_TYPE; } const lineTypeClass = line?.left ? line.left.type : EMPTY_CELL_TYPE; - return [lineTypeClass, { hll }]; + return [ + lineTypeClass, + { + hll: highlighted, + commented, + 'highlight-top': highlighted || selectionStart, + 'highlight-bottom': highlighted || selectionEnd, + }, + ]; }; export const shouldShowCommentButton = (hover, context, meta, discussions) => { diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue index aa9a17d18e3..a2e052e0f93 100644 --- a/app/assets/javascripts/diffs/components/diff_view.vue +++ b/app/assets/javascripts/diffs/components/diff_view.vue @@ -59,7 +59,12 @@ export default { }, computed: { ...mapGetters('diffs', ['commitId', 'fileLineCoverage']), - ...mapState('diffs', ['codequalityDiff', 'highlightedRow', 'coverageLoaded']), + ...mapState('diffs', [ + 'codequalityDiff', + 'highlightedRow', + 'coverageLoaded', + 'selectedCommentPosition', + ]), ...mapState({ selectedCommentPosition: ({ notes }) => notes.selectedCommentPosition, selectedCommentPositionHover: ({ notes }) => notes.selectedCommentPositionHover, @@ -144,6 +149,14 @@ export default { false, ); }, + isFirstHighlightedLine(line) { + const lineCode = line.left?.line_code || line.right?.line_code; + return lineCode && lineCode === this.selectedCommentPosition?.start.line_code; + }, + isLastHighlightedLine(line) { + const lineCode = line.left?.line_code || line.right?.line_code; + return lineCode && lineCode === this.selectedCommentPosition?.end.line_code; + }, handleParallelLineMouseDown(e) { const line = e.target.closest('.diff-td'); if (line) { @@ -230,10 +243,14 @@ export default { :line="line" :is-bottom="index + 1 === diffLinesLength" :is-commented="index >= commentedLines.startLine && index <= commentedLines.endLine" + :is-highlighted="isHighlighted(line)" + :is-first-highlighted-line=" + isFirstHighlightedLine(line) || index === commentedLines.startLine + " + :is-last-highlighted-line="isLastHighlightedLine(line) || index === commentedLines.endLine" :inline="inline" :index="index" :code-quality-expanded="codeQualityExpandedLines.includes(getCodeQualityLine(line))" - :is-highlighted="isHighlighted(line)" :file-line-coverage="fileLineCoverage" :coverage-loaded="coverageLoaded" @showCommentForm="(code) => singleLineComment(code, line)" diff --git a/app/assets/javascripts/gpg_badges.js b/app/assets/javascripts/gpg_badges.js index 0a4733de65f..ad339155a59 100644 --- a/app/assets/javascripts/gpg_badges.js +++ b/app/assets/javascripts/gpg_badges.js @@ -13,7 +13,7 @@ export default class GpgBadges { return Promise.resolve(); } - const badges = $('.js-loading-gpg-badge'); + const badges = $('.js-loading-signature-badge'); badges.html(loadingIconForLegacyJS()); badges.children().attr('aria-label', __('Loading')); diff --git a/app/assets/javascripts/issuable/components/issuable_by_email.vue b/app/assets/javascripts/issuable/components/issuable_by_email.vue index fcebae3af71..71ec5544c34 100644 --- a/app/assets/javascripts/issuable/components/issuable_by_email.vue +++ b/app/assets/javascripts/issuable/components/issuable_by_email.vue @@ -9,6 +9,7 @@ import { GlFormInputGroup, GlIcon, } from '@gitlab/ui'; +import { TYPE_ISSUE } from '~/issues/constants'; import axios from '~/lib/utils/axios_utils'; import { sprintf, __ } from '~/locale'; import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue'; @@ -36,7 +37,7 @@ export default { default: null, }, issuableType: { - default: 'issue', + default: TYPE_ISSUE, }, emailsHelpPagePath: { default: '', @@ -54,7 +55,7 @@ export default { data() { return { email: this.initialEmail, - issuableName: this.issuableType === 'issue' ? __('issue') : __('merge request'), + issuableName: this.issuableType === TYPE_ISSUE ? __('issue') : __('merge request'), }; }, computed: { diff --git a/app/assets/javascripts/issues/show/components/fields/type.vue b/app/assets/javascripts/issues/show/components/fields/type.vue index c5064f46e97..5ade1a86d30 100644 --- a/app/assets/javascripts/issues/show/components/fields/type.vue +++ b/app/assets/javascripts/issues/show/components/fields/type.vue @@ -1,5 +1,6 @@ <script> import { GlFormGroup, GlIcon, GlListbox } from '@gitlab/ui'; +import { TYPE_ISSUE } from '~/issues/constants'; import { __ } from '~/locale'; import { issuableTypes, INCIDENT_TYPE } from '../../constants'; import getIssueStateQuery from '../../queries/get_issue_state.query.graphql'; @@ -22,7 +23,7 @@ export default { default: false, }, issueType: { - default: 'issue', + default: TYPE_ISSUE, }, }, data() { diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue index ecf06401ccd..abed95a9706 100644 --- a/app/assets/javascripts/notes/components/note_actions.vue +++ b/app/assets/javascripts/notes/components/note_actions.vue @@ -4,6 +4,7 @@ import { mapActions, mapGetters, mapState } from 'vuex'; import Api from '~/api'; import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status'; import { createAlert } from '~/flash'; +import { TYPE_ISSUE } from '~/issues/constants'; import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants'; import { __, sprintf } from '~/locale'; import eventHub from '~/sidebar/event_hub'; @@ -173,7 +174,7 @@ export default { return this.getNoteableData.assignees || []; }, isIssue() { - return this.targetType === 'issue'; + return this.targetType === TYPE_ISSUE; }, canAssign() { return this.getNoteableData.current_user?.can_set_issue_metadata && this.isIssue; @@ -235,7 +236,7 @@ export default { assignees.push({ id: this.author.id }); } - if (this.targetType === 'issue') { + if (this.targetType === TYPE_ISSUE) { Api.updateIssue(project_id, iid, { assignee_ids: assignees.map((assignee) => assignee.id), }) diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js index c37fbdacae2..f6b9be6ee9b 100644 --- a/app/assets/javascripts/notes/stores/actions.js +++ b/app/assets/javascripts/notes/stores/actions.js @@ -4,6 +4,7 @@ import Vue from 'vue'; import Api from '~/api'; import { createAlert, VARIANT_INFO } from '~/flash'; import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants'; +import { TYPE_ISSUE } from '~/issues/constants'; import axios from '~/lib/utils/axios_utils'; import { __, sprintf } from '~/locale'; import toast from '~/vue_shared/plugins/global_toast'; @@ -37,7 +38,8 @@ export const updateLockedAttribute = ({ commit, getters }, { locked, fullPath }) return utils.gqClient .mutate({ - mutation: targetType === 'issue' ? updateIssueLockMutation : updateMergeRequestLockMutation, + mutation: + targetType === TYPE_ISSUE ? updateIssueLockMutation : updateMergeRequestLockMutation, variables: { input: { projectPath: fullPath, @@ -48,7 +50,7 @@ export const updateLockedAttribute = ({ commit, getters }, { locked, fullPath }) }) .then(({ data }) => { const discussionLocked = - targetType === 'issue' + targetType === TYPE_ISSUE ? data.issueSetLocked.issue.discussionLocked : data.mergeRequestSetLocked.mergeRequest.discussionLocked; diff --git a/app/assets/javascripts/related_issues/components/related_issues_list.vue b/app/assets/javascripts/related_issues/components/related_issues_list.vue index 11de734f5d4..7387b9ab87c 100644 --- a/app/assets/javascripts/related_issues/components/related_issues_list.vue +++ b/app/assets/javascripts/related_issues/components/related_issues_list.vue @@ -2,6 +2,7 @@ import { GlLoadingIcon } from '@gitlab/ui'; import Sortable from 'sortablejs'; import RelatedIssuableItem from '~/issuable/components/related_issuable_item.vue'; +import { TYPE_ISSUE } from '~/issues/constants'; import { defaultSortableOptions } from '~/sortable/constants'; export default { @@ -88,7 +89,7 @@ export default { document.body.classList.remove('is-dragging'); }, issuableOrderingId({ epicIssueId, id }) { - return this.issuableType === 'issue' ? epicIssueId : id; + return this.issuableType === TYPE_ISSUE ? epicIssueId : id; }, }, }; diff --git a/app/assets/javascripts/related_issues/index.js b/app/assets/javascripts/related_issues/index.js index c42ee27fbdf..cc00ef10dda 100644 --- a/app/assets/javascripts/related_issues/index.js +++ b/app/assets/javascripts/related_issues/index.js @@ -1,9 +1,10 @@ import Vue from 'vue'; +import { TYPE_ISSUE } from '~/issues/constants'; import { apolloProvider } from '~/graphql_shared/issuable_client'; import { parseBoolean } from '~/lib/utils/common_utils'; import RelatedIssuesRoot from './components/related_issues_root.vue'; -export function initRelatedIssues(issueType = 'issue') { +export function initRelatedIssues(issueType = TYPE_ISSUE) { const el = document.querySelector('.js-related-issues-root'); if (!el) { diff --git a/app/assets/javascripts/repository/components/preview/index.vue b/app/assets/javascripts/repository/components/preview/index.vue index 8feac6b8e35..90949536cc1 100644 --- a/app/assets/javascripts/repository/components/preview/index.vue +++ b/app/assets/javascripts/repository/components/preview/index.vue @@ -14,7 +14,6 @@ export default { url: this.blob.webPath, }; }, - loadingKey: 'loading', }, }, components: { @@ -34,9 +33,13 @@ export default { data() { return { readme: null, - loading: 0, }; }, + computed: { + isLoading() { + return this.$apollo.queries.readme.loading; + }, + }, watch: { readme(newVal) { if (newVal) { @@ -64,7 +67,7 @@ export default { </div> </div> <div class="blob-viewer" data-qa-selector="blob_viewer_content" itemprop="about"> - <gl-loading-icon v-if="loading > 0" size="lg" color="dark" class="my-4 mx-auto" /> + <gl-loading-icon v-if="isLoading" size="lg" color="dark" class="my-4 mx-auto" /> <div v-else-if="readme" ref="readme" diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue index 240e12ee597..323f6f23df6 100644 --- a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue +++ b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar.vue @@ -1,6 +1,6 @@ <script> import { GlIcon } from '@gitlab/ui'; -import { IssuableType } from '~/issues/constants'; +import { IssuableType, TYPE_ISSUE } from '~/issues/constants'; import { __, sprintf } from '~/locale'; export default { @@ -19,7 +19,7 @@ export default { issuableType: { type: String, required: false, - default: 'issue', + default: TYPE_ISSUE, }, }, computed: { diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue index d17c8a123d5..73cd0044c16 100644 --- a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue +++ b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue @@ -1,6 +1,6 @@ <script> import { GlTooltipDirective, GlLink } from '@gitlab/ui'; -import { IssuableType } from '~/issues/constants'; +import { IssuableType, TYPE_ISSUE } from '~/issues/constants'; import { isGid, getIdFromGraphQLId } from '~/graphql_shared/utils'; import { __ } from '~/locale'; import { isUserBusy } from '~/set_status_modal/utils'; @@ -67,7 +67,7 @@ export default { }, issuableType: { type: String, - default: 'issue', + default: TYPE_ISSUE, required: false, }, }, diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees.vue b/app/assets/javascripts/sidebar/components/assignees/assignees.vue index cf07752a0b8..5cdebee04ad 100644 --- a/app/assets/javascripts/sidebar/components/assignees/assignees.vue +++ b/app/assets/javascripts/sidebar/components/assignees/assignees.vue @@ -1,4 +1,5 @@ <script> +import { TYPE_ISSUE } from '~/issues/constants'; import CollapsedAssigneeList from './collapsed_assignee_list.vue'; import UncollapsedAssigneeList from './uncollapsed_assignee_list.vue'; @@ -22,7 +23,7 @@ export default { issuableType: { type: String, required: false, - default: 'issue', + default: TYPE_ISSUE, }, }, computed: { diff --git a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee.vue b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee.vue index 46bda26c327..fab856883cc 100644 --- a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee.vue +++ b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee.vue @@ -1,4 +1,5 @@ <script> +import { TYPE_ISSUE } from '~/issues/constants'; import AssigneeAvatar from './assignee_avatar.vue'; import UserNameWithStatus from './user_name_with_status.vue'; @@ -15,7 +16,7 @@ export default { issuableType: { type: String, required: false, - default: 'issue', + default: TYPE_ISSUE, }, }, computed: { diff --git a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue index f894ef0c42d..d2f0ceb19c9 100644 --- a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue +++ b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue @@ -1,5 +1,6 @@ <script> import { GlIcon, GlTooltipDirective } from '@gitlab/ui'; +import { TYPE_ISSUE } from '~/issues/constants'; import { __, sprintf } from '~/locale'; import { isUserBusy } from '~/set_status_modal/utils'; import CollapsedAssignee from './collapsed_assignee.vue'; @@ -41,7 +42,7 @@ export default { issuableType: { type: String, required: false, - default: 'issue', + default: TYPE_ISSUE, }, }, computed: { diff --git a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue index fd51cd5bb16..ed29ccb3447 100644 --- a/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue +++ b/app/assets/javascripts/sidebar/components/assignees/issuable_assignees.vue @@ -1,5 +1,6 @@ <script> import { GlButton } from '@gitlab/ui'; +import { TYPE_ISSUE } from '~/issues/constants'; import { n__ } from '~/locale'; import UncollapsedAssigneeList from './uncollapsed_assignee_list.vue'; @@ -16,7 +17,7 @@ export default { issuableType: { type: String, required: false, - default: 'issue', + default: TYPE_ISSUE, }, signedIn: { type: Boolean, diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue index 7979f450fdd..caf3bb2f798 100644 --- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue +++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue @@ -1,6 +1,7 @@ <script> import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests'; import { createAlert } from '~/flash'; +import { TYPE_ISSUE } from '~/issues/constants'; import { __ } from '~/locale'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import eventHub from '../../event_hub'; @@ -34,7 +35,7 @@ export default { issuableType: { type: String, required: false, - default: 'issue', + default: TYPE_ISSUE, }, issuableIid: { type: String, @@ -63,7 +64,7 @@ export default { computed: { shouldEnableRealtime() { // Note: Realtime is only available on issues right now, future support for MR wil be built later. - return this.issuableType === 'issue'; + return this.issuableType === TYPE_ISSUE; }, queryVariables() { return { diff --git a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue index d83ae782e26..71f349bb87e 100644 --- a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue +++ b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue @@ -1,6 +1,6 @@ <script> import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; -import { IssuableType } from '~/issues/constants'; +import { IssuableType, TYPE_ISSUE } from '~/issues/constants'; import { __, sprintf } from '~/locale'; import AssigneeAvatarLink from './assignee_avatar_link.vue'; import UserNameWithStatus from './user_name_with_status.vue'; @@ -21,7 +21,7 @@ export default { issuableType: { type: String, required: false, - default: 'issue', + default: TYPE_ISSUE, }, }, data() { diff --git a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue index cdce6617591..9d8f1304911 100644 --- a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue +++ b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue @@ -1,6 +1,7 @@ <script> import { GlIcon, GlTooltipDirective, GlOutsideDirective as Outside } from '@gitlab/ui'; import { mapGetters, mapActions } from 'vuex'; +import { TYPE_ISSUE } from '~/issues/constants'; import { __, sprintf } from '~/locale'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { createAlert } from '~/flash'; @@ -9,7 +10,6 @@ import eventHub from '../../event_hub'; import EditForm from './edit_form.vue'; export default { - issue: 'issue', locked: { icon: 'lock', class: 'value', @@ -49,7 +49,7 @@ export default { return this.getNoteableData.targetType === 'merge_request' && this.glFeatures.movedMrSidebar; }, issuableDisplayName() { - const isInIssuePage = this.getNoteableData.targetType === this.$options.issue; + const isInIssuePage = this.getNoteableData.targetType === TYPE_ISSUE; return isInIssuePage ? __('issue') : __('merge request'); }, isLocked() { diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue index f69c027e201..56ac4c39e84 100644 --- a/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue +++ b/app/assets/javascripts/sidebar/components/reviewers/reviewer_avatar_link.vue @@ -2,6 +2,7 @@ // NOTE! For the first iteration, we are simply copying the implementation of Assignees // It will soon be overhauled in Issue https://gitlab.com/gitlab-org/gitlab/-/issues/233736 import { GlTooltipDirective, GlLink } from '@gitlab/ui'; +import { TYPE_ISSUE } from '~/issues/constants'; import { __, sprintf } from '~/locale'; import ReviewerAvatar from './reviewer_avatar.vue'; @@ -34,7 +35,7 @@ export default { }, issuableType: { type: String, - default: 'issue', + default: TYPE_ISSUE, required: false, }, }, diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue index 7af8dcb4e3e..bd1d9fbff0c 100644 --- a/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue +++ b/app/assets/javascripts/sidebar/components/reviewers/reviewers.vue @@ -1,6 +1,7 @@ <script> // NOTE! For the first iteration, we are simply copying the implementation of Assignees // It will soon be overhauled in Issue https://gitlab.com/gitlab-org/gitlab/-/issues/233736 +import { TYPE_ISSUE } from '~/issues/constants'; import CollapsedReviewerList from './collapsed_reviewer_list.vue'; import UncollapsedReviewerList from './uncollapsed_reviewer_list.vue'; @@ -28,7 +29,7 @@ export default { issuableType: { type: String, required: false, - default: 'issue', + default: TYPE_ISSUE, }, }, computed: { diff --git a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue index a5577d45f92..8dd58d33ecf 100644 --- a/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue +++ b/app/assets/javascripts/sidebar/components/reviewers/sidebar_reviewers.vue @@ -4,6 +4,7 @@ import Vue from 'vue'; import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests'; import { createAlert } from '~/flash'; +import { TYPE_ISSUE } from '~/issues/constants'; import { __ } from '~/locale'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import eventHub from '../../event_hub'; @@ -37,7 +38,7 @@ export default { issuableType: { type: String, required: false, - default: 'issue', + default: TYPE_ISSUE, }, issuableIid: { type: String, diff --git a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue index 217ca2e2548..a3710d9534e 100644 --- a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue +++ b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue @@ -1,5 +1,6 @@ <script> import { GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui'; +import { TYPE_ISSUE } from '~/issues/constants'; import { __, sprintf, s__ } from '~/locale'; import ReviewerAvatarLink from './reviewer_avatar_link.vue'; @@ -30,7 +31,7 @@ export default { issuableType: { type: String, required: false, - default: 'issue', + default: TYPE_ISSUE, }, }, data() { diff --git a/app/assets/javascripts/sidebar/components/time_tracking/create_timelog_form.vue b/app/assets/javascripts/sidebar/components/time_tracking/create_timelog_form.vue index abd84abef6e..964da3b6138 100644 --- a/app/assets/javascripts/sidebar/components/time_tracking/create_timelog_form.vue +++ b/app/assets/javascripts/sidebar/components/time_tracking/create_timelog_form.vue @@ -10,6 +10,7 @@ import { GlSprintf, } from '@gitlab/ui'; import { convertToGraphQLId } from '~/graphql_shared/utils'; +import { TYPE_ISSUE } from '~/issues/constants'; import { formatDate } from '~/lib/utils/datetime_utility'; import { TYPENAME_ISSUE, TYPENAME_MERGE_REQUEST } from '~/graphql_shared/constants'; import { joinPaths } from '~/lib/utils/url_utility'; @@ -127,7 +128,7 @@ export default { }); }, isIssue() { - return this.issuableType === 'issue'; + return this.issuableType === TYPE_ISSUE; }, getGraphQLEntityType() { return this.isIssue() ? TYPENAME_ISSUE : TYPENAME_MERGE_REQUEST; diff --git a/app/assets/javascripts/sidebar/components/time_tracking/report.vue b/app/assets/javascripts/sidebar/components/time_tracking/report.vue index 12705baf33a..cffbb6466f2 100644 --- a/app/assets/javascripts/sidebar/components/time_tracking/report.vue +++ b/app/assets/javascripts/sidebar/components/time_tracking/report.vue @@ -3,6 +3,7 @@ import { GlLoadingIcon, GlTableLite, GlButton, GlTooltipDirective } from '@gitla import { createAlert } from '~/flash'; import { TYPENAME_ISSUE, TYPENAME_MERGE_REQUEST } from '~/graphql_shared/constants'; import { convertToGraphQLId } from '~/graphql_shared/utils'; +import { TYPE_ISSUE } from '~/issues/constants'; import { formatDate, parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility'; import { __, s__ } from '~/locale'; import { timelogQueries } from '../../constants'; @@ -61,7 +62,7 @@ export default { return this.removingIds.includes(timelogId); }, isIssue() { - return this.issuableType === 'issue'; + return this.issuableType === TYPE_ISSUE; }, getQueryVariables() { return { diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue index 1e7dd639247..b78293a9815 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue @@ -293,7 +293,7 @@ export default { } }, onClickedAction(action) { - if (action.fullReport) { + if (action.trackFullReportClicked) { this.telemetry?.fullReportClicked(); } }, diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue index 6003aa40c6d..73129a86877 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue @@ -111,7 +111,7 @@ export default { * "testId":string, * "text": string, * "class": string | Object, - * "fullReport": boolean, + * "trackFullReportClicked": boolean, * } */ actionButtons: { @@ -204,7 +204,7 @@ export default { }, methods: { onActionClick(action) { - if (action.fullReport) { + if (action.trackFullReportClicked) { this.telemetryHub?.fullReportClicked(); } }, diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js index ca95e1b5de8..ff225afbc7b 100644 --- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js +++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js @@ -44,7 +44,12 @@ export default { console.log('Hello world'); }, }, - { text: 'Full report', href: this.conflictsDocsPath, target: '_blank', fullReport: true }, + { + text: 'Full report', + href: this.conflictsDocsPath, + target: '_blank', + trackFullReportClicked: true, + }, ]; }, shouldCollapse() { diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js b/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js index 626a99f7d64..c5cbed4a280 100644 --- a/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js +++ b/app/assets/javascripts/vue_merge_request_widget/extensions/terraform/index.js @@ -115,7 +115,7 @@ export default { href: report.job_path, text: this.$options.i18n.fullLog, target: '_blank', - fullReport: true, + trackFullReportClicked: true, }; actions.push(action); } diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/index.js b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/index.js index 7566e083f14..6ac462d4ad5 100644 --- a/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/index.js +++ b/app/assets/javascripts/vue_merge_request_widget/extensions/test_report/index.js @@ -75,7 +75,7 @@ export default { text: this.$options.i18n.fullReport, href: `${this.pipeline.path}/test_report`, target: '_blank', - fullReport: true, + trackFullReportClicked: true, testId: 'full-report-link', }); diff --git a/app/assets/stylesheets/framework/diffs.scss b/app/assets/stylesheets/framework/diffs.scss index f7cd5d7e183..4eb26d533c2 100644 --- a/app/assets/stylesheets/framework/diffs.scss +++ b/app/assets/stylesheets/framework/diffs.scss @@ -450,6 +450,16 @@ } } +.code .diff-grid-row.line_holder.diff-tr .diff-td.commented:not(.hll) { + --highlight-border-color: #{$blue-300}; + background-color: $blue-50; + + .gl-dark & { + --highlight-border-color: #{$blue-600}; + background-color: $blue-900; + } +} + .diff-table.code, table.code { width: 100%; @@ -461,6 +471,21 @@ table.code { table-layout: fixed; border-radius: 0 0 $border-radius-default $border-radius-default; + .diff-td.highlight-top { + box-shadow: 0 -1px var(--highlight-border-color, $blue-300); + z-index: 1; + } + + .diff-td.highlight-bottom { + box-shadow: 0 1px var(--highlight-border-color, $blue-300); + z-index: 1; + } + + .diff-td.highlight-top.highlight-bottom { + box-shadow: 0 -1px var(--highlight-border-color, $blue-300), 0 1px var(--highlight-border-color, $blue-300); + z-index: 2; + } + .diff-tr.line_holder .diff-td, tr.line_holder td { line-height: $code-line-height; @@ -485,13 +510,16 @@ table.code { user-select: none; margin: 0; padding: 0 10px 0 5px; - border-right-width: 1px; - border-right-style: solid; text-align: right; width: 50px; position: relative; white-space: nowrap; + &:nth-of-type(2) { + border-right-width: 1px; + border-right-style: solid; + } + a { transition: none; float: left; diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss index 96df8487c0e..085e25a0cdc 100644 --- a/app/assets/stylesheets/highlight/common.scss +++ b/app/assets/stylesheets/highlight/common.scss @@ -57,6 +57,15 @@ } } +@mixin line-number-hover-dark { + background-color: $purple-800; + border-color: $purple-300; + + a { + color: $purple-50; + } +} + @mixin conflict-colors($theme) { .diff-line-num { &.conflict_marker_our, @@ -75,6 +84,8 @@ .line_holder { .line_content, .line-coverage { + position: relative; + &.conflict_marker_our { background-color: map-get($conflict-colors, #{$theme}-header-head-neutral); border-color: map-get($conflict-colors, #{$theme}-header-head-neutral); diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss index 3438a73eff6..02469cf5165 100644 --- a/app/assets/stylesheets/highlight/themes/dark.scss +++ b/app/assets/stylesheets/highlight/themes/dark.scss @@ -131,7 +131,7 @@ $dark-il: #de935f; @include hljs-override('title\\.class\\.inherited', $dark-no); @include hljs-override('variable\\.constant', $dark-no); @include hljs-override('title\\.function', $dark-nf); - + // Line numbers .file-line-num { @@ -174,6 +174,11 @@ $dark-il: #de935f; @include diff-expansion($gray-600, $gray-200, $gray-300, $white); } + .diff-grid-row.line_holder.diff-tr .diff-td.commented:not(.hll) { + --highlight-border-color: #{$blue-600}; + background-color: $blue-900; + } + // Diff line .line_holder { &.match .line_content, @@ -188,15 +193,15 @@ $dark-il: #de935f; @include dark-diff-expansion-line; } - .diff-td.diff-line-num.hll:not(.empty-cell), - .diff-td.line-coverage.hll:not(.empty-cell), - .diff-td.line-codequality.hll:not(.empty-cell), - .diff-td.line_content.hll:not(.empty-cell), - td.diff-line-num.hll:not(.empty-cell), - td.line-coverage.hll:not(.empty-cell), - td.line_content.hll:not(.empty-cell) { - background-color: $dark-diff-not-empty-bg; - border-color: darken($dark-diff-not-empty-bg, 15%); + .diff-td.diff-line-num.hll, + .diff-td.line-coverage.hll, + .diff-td.line-codequality.hll, + .diff-td.line_content.hll, + td.diff-line-num.hll, + td.line-coverage.hll, + td.line_content.hll { + --highlight-border-color: #{$orange-500}; + background-color: $orange-800; } .line-coverage { @@ -239,14 +244,14 @@ $dark-il: #de935f; &:not(.match) .diff-grid-right:hover, &.code-search-line:hover { .diff-line-num:not(.empty-cell) { - @include line-number-hover; + @include line-number-hover-dark; } } .diff-line-num { &.is-over, &.hll:not(.empty-cell).is-over { - @include line-number-hover; + @include line-number-hover-dark; } } diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss index 02aa9ed6b16..30d04b4002e 100644 --- a/app/assets/stylesheets/highlight/themes/monokai.scss +++ b/app/assets/stylesheets/highlight/themes/monokai.scss @@ -148,6 +148,11 @@ $monokai-gh: #75715e; color: $monokai-line-num-color; } + .diff-grid-row.line_holder.diff-tr .diff-td.commented:not(.hll) { + --highlight-border-color: #{$blue-600}; + background-color: $blue-900; + } + // Code itself pre.code, .diff-line-num { @@ -179,15 +184,15 @@ $monokai-gh: #75715e; @include dark-diff-expansion-line; } - .diff-td.diff-line-num.hll:not(.empty-cell), - .diff-td.line-coverage.hll:not(.empty-cell), - .diff-td.line-codequality.hll:not(.empty-cell), - .diff-td.line_content.hll:not(.empty-cell), - td.diff-line-num.hll:not(.empty-cell), - td.line-coverage.hll:not(.empty-cell), - td.line_content.hll:not(.empty-cell) { - background-color: $monokai-line-empty-bg; - border-color: $monokai-line-empty-border; + .diff-td.diff-line-num.hll, + .diff-td.line-coverage.hll, + .diff-td.line-codequality.hll, + .diff-td.line_content.hll, + td.diff-line-num.hll, + td.line-coverage.hll, + td.line_content.hll { + --highlight-border-color: #{$orange-500}; + background-color: $orange-800; } .line-coverage { @@ -230,14 +235,14 @@ $monokai-gh: #75715e; &:not(.match) .diff-grid-right:hover, &.code-search-line:hover { .diff-line-num:not(.empty-cell) { - @include line-number-hover; + @include line-number-hover-dark; } } .diff-line-num { &.is-over, &.hll:not(.empty-cell).is-over { - @include line-number-hover; + @include line-number-hover-dark; } } diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss index fa1f7211b3e..8339d7eff80 100644 --- a/app/assets/stylesheets/highlight/themes/none.scss +++ b/app/assets/stylesheets/highlight/themes/none.scss @@ -55,7 +55,7 @@ &, pre.code, - .line_holder .line_content { + .line_holder .line_content:not(.hll) { background-color: $white; color: $gl-text-color; } @@ -84,8 +84,8 @@ @include line-coverage-border-color($green-500, $orange-500); } - .line-coverage, - .line-codequality { + .line-coverage:not(.hll), + .line-codequality:not(.hll) { &.old, &.new, &.new-nomappinginraw, @@ -119,11 +119,6 @@ &.hll:not(.empty-cell).is-over { @include line-number-hover; } - - &.hll:not(.empty-cell) { - background-color: $white; - border-color: $white-normal; - } } &:not(.diff-expanded) + .diff-expanded, @@ -158,7 +153,7 @@ } } - &.new, &.new-nomappinginraw { + &.new:not(.hll), &.new-nomappinginraw:not(.hll) { background-color: $white-normal; &::before { @@ -174,18 +169,9 @@ &.match { @include match-line; } - - &.hll:not(.empty-cell) { - background-color: $white-normal; - } } } - // highlight line via anchor - pre .hll { - background-color: $white-normal; - } - // Search result highlight span.highlight_word { background-color: $white-normal; @@ -197,7 +183,10 @@ text-decoration: underline; } - .hll { background-color: $white; } + .hll { + --highlight-border-color: #{$orange-200}; + background-color: $orange-50; + } .gd { color: $gl-text-color; diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss index 18e18619c09..075510e6e5f 100644 --- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss +++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss @@ -151,6 +151,11 @@ $solarized-dark-il: #2aa198; color: $solarized-dark-line-color; } + .diff-grid-row.line_holder.diff-tr .diff-td.commented:not(.hll) { + --highlight-border-color: #{$blue-600}; + background-color: $blue-900; + } + // Code itself pre.code, .diff-line-num { @@ -182,15 +187,15 @@ $solarized-dark-il: #2aa198; @include dark-diff-expansion-line; } - .diff-td.diff-line-num.hll:not(.empty-cell), - .diff-td.line-coverage.hll:not(.empty-cell), - .diff-td.line-codequality.hll:not(.empty-cell), - .diff-td.line_content.hll:not(.empty-cell), - td.diff-line-num.hll:not(.empty-cell), - td.line-coverage.hll:not(.empty-cell), - td.line_content.hll:not(.empty-cell) { - background-color: $solarized-dark-hll-bg; - border-color: darken($solarized-dark-hll-bg, 15%); + .diff-td.diff-line-num.hll, + .diff-td.line-coverage.hll, + .diff-td.line-codequality.hll, + .diff-td.line_content.hll, + td.diff-line-num.hll, + td.line-coverage.hll, + td.line_content.hll { + --highlight-border-color: #{$orange-500}; + background-color: $orange-800; } .line-coverage { @@ -201,7 +206,7 @@ $solarized-dark-il: #2aa198; &:not(.match) .diff-grid-right:hover, &.code-search-line:hover { .diff-line-num:not(.empty-cell) { - @include line-number-hover; + @include line-number-hover-dark; } } @@ -240,7 +245,7 @@ $solarized-dark-il: #2aa198; .diff-line-num { &.is-over, &.hll:not(.empty-cell).is-over { - @include line-number-hover; + @include line-number-hover-dark; } } diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss index d2dea024408..4e244ed7420 100644 --- a/app/assets/stylesheets/highlight/themes/solarized-light.scss +++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss @@ -116,7 +116,7 @@ $solarized-light-il: #2aa198; @include hljs-override('variable\\.constant', $solarized-light-no); @include hljs-override('variable\\.language', $solarized-light-nb); @include hljs-override('params', $solarized-light-nb); - + // Line numbers .file-line-num { @include line-link($black, 'link'); @@ -174,13 +174,13 @@ $solarized-light-il: #2aa198; background-color: $solarized-light-matchline-bg; } - .diff-td.diff-line-num.hll:not(.empty-cell), - .diff-td.line-coverage.hll:not(.empty-cell), - .diff-td.line-codequality.hll:not(.empty-cell), - .diff-td.line_content.hll:not(.empty-cell), - td.diff-line-num.hll:not(.empty-cell), - td.line-coverage.hll:not(.empty-cell), - td.line_content.hll:not(.empty-cell) { + .diff-td.diff-line-num.hll, + .diff-td.line-coverage.hll, + .diff-td.line-codequality.hll, + .diff-td.line_content.hll, + td.diff-line-num.hll, + td.line-coverage.hll, + td.line_content.hll { background-color: $solarized-light-hll-bg; border-color: darken($solarized-light-hll-bg, 15%); } diff --git a/app/assets/stylesheets/highlight/themes/white.scss b/app/assets/stylesheets/highlight/themes/white.scss index f6cce25671f..0a283254a4c 100644 --- a/app/assets/stylesheets/highlight/themes/white.scss +++ b/app/assets/stylesheets/highlight/themes/white.scss @@ -19,4 +19,4 @@ :root { --default-diff-color-deletion: #eb919b; --default-diff-color-addition: #a0f5b4; -}
\ No newline at end of file +} diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss index 816aa88cfde..ccb5d96e966 100644 --- a/app/assets/stylesheets/highlight/white_base.scss +++ b/app/assets/stylesheets/highlight/white_base.scss @@ -125,13 +125,13 @@ $white-gc-bg: #eaf2f5; .diff-line-num, .diff-line-num a { - color: $black-transparent; + color: $gray-400; } // Code itself pre.code, .diff-line-num { - border-color: $white-normal; + border-color: rgba(0, 0, 0, 0.1); } &, @@ -173,7 +173,7 @@ pre.code, background-color: $line-number-old; a { - color: scale-color($line-number-old, $red: -30%, $green: -30%, $blue: -30%); + color: scale-color($gray-300, $red: -30%, $green: -30%, $blue: -30%); } } @@ -182,7 +182,7 @@ pre.code, background-color: $line-number-new; a { - color: scale-color($line-number-new, $red: -30%, $green: -30%, $blue: -30%); + color: scale-color($gray-200, $red: -30%, $green: -30%, $blue: -30%); } } @@ -191,9 +191,9 @@ pre.code, @include line-number-hover; } - &.hll:not(.empty-cell) { - background-color: $line-number-select; - border-color: $line-select-yellow-dark; + &.hll { + --highlight-border-color: #{$orange-200}; + background-color: $orange-50; } } @@ -246,8 +246,9 @@ pre.code, @include match-line; } - &.hll:not(.empty-cell) { - background-color: $line-select-yellow; + &.hll { + --highlight-border-color: #{$orange-200}; + background-color: $orange-50; } } @@ -267,8 +268,9 @@ pre.code, background-color: $line-added; } - &.hll:not(.empty-cell) { - background-color: $line-select-yellow; + &.hll { + --highlight-border-color: #{$orange-200}; + background-color: $orange-50; } } } diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index dd24e3fcb5d..7d465dbcc04 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -266,24 +266,9 @@ } } -.gpg-status-box { - padding: 2px 10px; - - &:empty { - display: none; - } - - &.valid { - @include green-status-color; - } - - &.invalid { - @include status-color($gray-dark, color('gray'), $gray-darkest); - border-color: $gray-darkest; - - &:not(span):hover { - color: color('gray'); - } +.signature-badge { + &:hover { + @include gl-text-decoration-none; } } @@ -297,7 +282,7 @@ } } -.gpg-popover-status { +.signature-popover { display: flex; align-items: center; font-weight: $gl-font-weight-normal; diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index c6fa1d50997..5d03281a30a 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -671,6 +671,7 @@ $system-note-svg-size: 1rem; } .discussion-reply-holder { + border-top: 0; border-radius: 0 0 $border-radius-default $border-radius-default; position: relative; diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss index df81d9fbbd0..3b28025053b 100644 --- a/app/assets/stylesheets/startup/startup-dark.scss +++ b/app/assets/stylesheets/startup/startup-dark.scss @@ -1631,8 +1631,6 @@ svg.s16 { --gray-200: #535158; --gray-700: #bfbfc3; --gray-900: #ececef; - --green-100: #0d532a; - --green-700: #91d4a8; --gl-text-color: #ececef; --border-color: #434248; --white: #333238; diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index 813e8d7f84d..9a88a8160b6 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -58,8 +58,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController render json: { environments: serialize_environments(request, response, params[:nested]), review_app: serialize_review_app, - can_stop_stale_environments: Feature.enabled?(:stop_stale_environments, @project) && - can?(current_user, :stop_environment, @project), + can_stop_stale_environments: can?(current_user, :stop_environment, @project), available_count: environments_count_by_state[:available], stopped_count: environments_count_by_state[:stopped] } diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb index 33d711133d5..c105ab9814c 100644 --- a/app/graphql/types/project_type.rb +++ b/app/graphql/types/project_type.rb @@ -571,6 +571,16 @@ module Types resolver: Resolvers::DataTransferResolver.project, description: 'Data transfer data point for a specific period. This is mocked data under a development feature flag.' + field :visible_forks, Types::ProjectType.connection_type, + null: true, + alpha: { milestone: '15.10' }, + description: "Visible forks of the project." do + argument :minimum_access_level, + type: ::Types::AccessLevelEnum, + required: false, + description: 'Minimum access level.' + end + def timelog_categories object.project_namespace.timelog_categories if Feature.enabled?(:timelog_categories) end @@ -663,6 +673,14 @@ module Types ::Projects::RepositoryLanguagesService.new(project, current_user).execute end + def visible_forks(minimum_access_level: nil) + if minimum_access_level.nil? + object.forks.public_or_visible_to_user(current_user) + else + object.forks.visible_to_user_and_access_level(current_user, minimum_access_level) + end + end + private def project diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 53781364af7..f75d3657986 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -131,10 +131,6 @@ module CommitsHelper } end - def commit_signature_badge_classes(additional_classes) - %w(btn gpg-status-box) + Array(additional_classes) - end - def conditionally_paginate_diff_files(diffs, paginate:, page:, per:) if paginate diff_files = diffs.diff_files.to_a diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 62023c6da74..46d2d2c42d9 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -6,7 +6,7 @@ module IssuablesHelper include ::Sidebars::Concerns::HasPill def sidebar_gutter_toggle_icon - content_tag(:span, class: 'js-sidebar-toggle-container', data: { is_expanded: !sidebar_gutter_collapsed? }) do + content_tag(:span, class: 'js-sidebar-toggle-container gl-button-text', data: { is_expanded: !sidebar_gutter_collapsed? }) do sprite_icon('chevron-double-lg-left', css_class: "js-sidebar-expand #{'hidden' unless sidebar_gutter_collapsed?}") + sprite_icon('chevron-double-lg-right', css_class: "js-sidebar-collapse #{'hidden' if sidebar_gutter_collapsed?}") end diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb index 49c4bf46695..7addcf9e2ec 100644 --- a/app/models/concerns/noteable.rb +++ b/app/models/concerns/noteable.rb @@ -116,7 +116,9 @@ module Noteable relations += synthetic_note_ids_relations end - Note.from_union(relations, remove_duplicates: false).fresh + Note.from_union(relations, remove_duplicates: false) + .select(:table_name, :id, :created_at, :ids) + .fresh end def capped_notes_count(max) diff --git a/app/models/note.rb b/app/models/note.rb index 1bc664936ab..a64f7311725 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -23,6 +23,9 @@ class Note < ApplicationRecord include FromUnion include Sortable include EachBatch + include IgnorableColumns + + ignore_column :id_convert_to_bigint, remove_with: '16.0', remove_after: '2023-05-22' ISSUE_TASK_SYSTEM_NOTE_PATTERN = /\A.*marked\sthe\stask.+as\s(completed|incomplete).*\z/.freeze diff --git a/app/views/projects/commit/_ajax_signature.html.haml b/app/views/projects/commit/_ajax_signature.html.haml index e1bf0940f59..87ccf01c011 100644 --- a/app/views/projects/commit/_ajax_signature.html.haml +++ b/app/views/projects/commit/_ajax_signature.html.haml @@ -1,2 +1,2 @@ - if commit.has_signature? - %button{ tabindex: 0, class: commit_signature_badge_classes('js-loading-gpg-badge'), data: { toggle: 'tooltip', placement: 'top', title: _('GPG signature (loading...)'), 'commit-sha' => commit.sha } } + %a.js-loading-signature-badge{ tabindex: 0, role: 'button', data: { toggle: 'tooltip', placement: 'top', title: _('GPG signature (loading...)'), 'commit-sha' => commit.sha } } diff --git a/app/views/projects/commit/_multiple_signatures_signature_badge.html.haml b/app/views/projects/commit/_multiple_signatures_signature_badge.html.haml index 2568a69cc2c..f80f194bd4d 100644 --- a/app/views/projects/commit/_multiple_signatures_signature_badge.html.haml +++ b/app/views/projects/commit/_multiple_signatures_signature_badge.html.haml @@ -1,5 +1,5 @@ - title = _('Multiple signatures') - description = _('This commit was signed with multiple signatures.') -- locals = { signature: signature, title: title, description: description, label: _('Unverified'), css_class: 'invalid' } +- locals = { signature: signature, title: title, description: description, label: _('Unverified'), variant: 'muted' } = render partial: 'projects/commit/signature_badge', locals: locals diff --git a/app/views/projects/commit/_other_user_signature_badge.html.haml b/app/views/projects/commit/_other_user_signature_badge.html.haml index ffc4b25dc21..345a1964259 100644 --- a/app/views/projects/commit/_other_user_signature_badge.html.haml +++ b/app/views/projects/commit/_other_user_signature_badge.html.haml @@ -1,5 +1,5 @@ - title = _("Different user's signature") - description = _("This commit was signed with a different user's verified signature.") -- locals = { signature: signature, title: title, description: description, label: _('Unverified'), css_class: 'invalid' } +- locals = { signature: signature, title: title, description: description, label: _('Unverified'), variant: 'muted' } = render partial: 'projects/commit/signature_badge', locals: locals diff --git a/app/views/projects/commit/_revoked_key_signature_badge.html.haml b/app/views/projects/commit/_revoked_key_signature_badge.html.haml index 2e0ca42561a..cbcc39249ce 100644 --- a/app/views/projects/commit/_revoked_key_signature_badge.html.haml +++ b/app/views/projects/commit/_revoked_key_signature_badge.html.haml @@ -1,5 +1,5 @@ - title = s_('CommitSignature|Unverified signature') - description = s_('CommitSignature|This commit was signed with a key that was revoked.') -- locals = { signature: signature, title: title, description: description, label: s_('CommitSignature|Unverified'), css_class: 'invalid' } +- locals = { signature: signature, title: title, description: description, label: s_('CommitSignature|Unverified'), variant: 'muted' } = render partial: 'projects/commit/signature_badge', locals: locals diff --git a/app/views/projects/commit/_same_user_different_email_signature_badge.html.haml b/app/views/projects/commit/_same_user_different_email_signature_badge.html.haml index 61fdf6fc87a..afce5c10065 100644 --- a/app/views/projects/commit/_same_user_different_email_signature_badge.html.haml +++ b/app/views/projects/commit/_same_user_different_email_signature_badge.html.haml @@ -1,5 +1,5 @@ - title = _('GPG key mismatch') - description = _('This commit was signed with a verified signature, but the committer email is not associated with the GPG Key.') -- locals = { signature: signature, title: title, description: description, label: _('Unverified'), css_class: ['invalid'] } +- locals = { signature: signature, title: title, description: description, label: _('Unverified'), variant: 'muted' } = render partial: 'projects/commit/signature_badge', locals: locals diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml index 41ba581b9d9..88631f14e56 100644 --- a/app/views/projects/commit/_signature_badge.html.haml +++ b/app/views/projects/commit/_signature_badge.html.haml @@ -2,12 +2,10 @@ - title = local_assigns.fetch(:title) - description = local_assigns.fetch(:description, nil) - label = local_assigns.fetch(:label) -- css_class = local_assigns.fetch(:css_class) - -- css_classes = commit_signature_badge_classes(css_class) +- variant = local_assigns.fetch(:variant) - title = capture do - .gpg-popover-status + .signature-popover %div %strong = title @@ -31,5 +29,5 @@ = link_to(_('Learn about signing commits'), help_page_path('user/project/repository/gpg_signed_commits/index.md'), class: 'gl-link gl-display-block gl-mt-3') -%a{ role: 'button', tabindex: 0, class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'top', title: title, content: content } } - = label +%a.signature-badge.gl-display-flex{ role: 'button', tabindex: 0, data: { toggle: 'popover', html: 'true', placement: 'top', title: title, content: content } } + = gl_badge_tag label, variant: variant diff --git a/app/views/projects/commit/_unverified_signature_badge.html.haml b/app/views/projects/commit/_unverified_signature_badge.html.haml index 0eae8d5564d..62a27aea60e 100644 --- a/app/views/projects/commit/_unverified_signature_badge.html.haml +++ b/app/views/projects/commit/_unverified_signature_badge.html.haml @@ -1,5 +1,5 @@ - title = _('Unverified signature') - description = _('This commit was signed with an unverified signature.') -- locals = { signature: signature, title: title, description: description, label: _('Unverified'), css_class: 'invalid' } +- locals = { signature: signature, title: title, description: description, label: _('Unverified'), variant: 'muted' } = render partial: 'projects/commit/signature_badge', locals: locals diff --git a/app/views/projects/commit/_verified_signature_badge.html.haml b/app/views/projects/commit/_verified_signature_badge.html.haml index 417d816c711..dd5d0d7d6eb 100644 --- a/app/views/projects/commit/_verified_signature_badge.html.haml +++ b/app/views/projects/commit/_verified_signature_badge.html.haml @@ -1,5 +1,5 @@ - title = _('Verified commit') - description = _('This commit was signed with a verified signature and the committer email was verified to belong to the same user.') -- locals = { signature: signature, title: title, description: description, label: _('Verified'), css_class: 'valid' } +- locals = { signature: signature, title: title, description: description, label: _('Verified'), variant: 'success' } = render partial: 'projects/commit/signature_badge', locals: locals diff --git a/app/views/projects/commit/x509/_unverified_signature_badge.html.haml b/app/views/projects/commit/x509/_unverified_signature_badge.html.haml index 6204a6977c0..94b9abda69e 100644 --- a/app/views/projects/commit/x509/_unverified_signature_badge.html.haml +++ b/app/views/projects/commit/x509/_unverified_signature_badge.html.haml @@ -1,6 +1,6 @@ - title = capture do = html_escape(_('This commit was signed with an %{strong_open}unverified%{strong_close} signature.')) % { strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe } -- locals = { signature: signature, title: title, label: _('Unverified'), css_class: 'invalid', icon: 'status_notfound_borderless', show_user: true } +- locals = { signature: signature, title: title, label: _('Unverified'), variant: 'muted', icon: 'status_notfound_borderless', show_user: true } = render partial: 'projects/commit/signature_badge', locals: locals diff --git a/app/views/projects/commit/x509/_verified_signature_badge.html.haml b/app/views/projects/commit/x509/_verified_signature_badge.html.haml index 357ad467539..a10516d275a 100644 --- a/app/views/projects/commit/x509/_verified_signature_badge.html.haml +++ b/app/views/projects/commit/x509/_verified_signature_badge.html.haml @@ -1,6 +1,6 @@ - title = capture do = html_escape(_('This commit was signed with a %{strong_open}verified%{strong_close} signature and the committer email is verified to belong to the same user.')) % { strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe } -- locals = { signature: signature, title: title, label: _('Verified'), css_class: 'valid', icon: 'status_success_borderless', show_user: true } +- locals = { signature: signature, title: title, label: _('Verified'), variant: 'success', icon: 'status_success_borderless', show_user: true } = render partial: 'projects/commit/signature_badge', locals: locals diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index be4a9291d95..f54354674e2 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -14,7 +14,7 @@ %aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in }, issuable_type: issuable_type }, class: "#{sidebar_gutter_collapsed_class} #{'right-sidebar-merge-requests' if moved_sidebar_enabled}", 'aria-live' => 'polite', 'aria-label': issuable_type } .issuable-sidebar{ class: "#{'is-merge-request' if moved_sidebar_enabled}" } .issuable-sidebar-header{ class: "#{'gl-pb-2! gl-md-display-flex gl-justify-content-end gl-lg-display-none!' if moved_sidebar_enabled}" } - %a.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ role: "button", class: "#{'gl-display-block' if moved_sidebar_enabled}", href: "#", "aria-label" => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } } + %button.btn.gl-button.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ type: "reset", class: "gl-shadow-none! #{'gl-display-block' if moved_sidebar_enabled}", "aria-label" => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } } = sidebar_gutter_toggle_icon - if signed_in && !moved_sidebar_enabled .js-sidebar-todo-widget-root{ data: { project_path: issuable_sidebar[:project_full_path], iid: issuable_sidebar[:iid], id: issuable_sidebar[:id] } } diff --git a/config/feature_flags/development/stop_stale_environments.yml b/config/feature_flags/development/stop_stale_environments.yml deleted file mode 100644 index ea1484f0970..00000000000 --- a/config/feature_flags/development/stop_stale_environments.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: stop_stale_environments -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108616 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/387820 -milestone: '15.8' -type: development -group: group::release -default_enabled: false diff --git a/db/migrate/20230131004948_initialize_conversion_of_notes_id_to_bigint.rb b/db/migrate/20230131004948_initialize_conversion_of_notes_id_to_bigint.rb new file mode 100644 index 00000000000..a376ba50e87 --- /dev/null +++ b/db/migrate/20230131004948_initialize_conversion_of_notes_id_to_bigint.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class InitializeConversionOfNotesIdToBigint < Gitlab::Database::Migration[2.1] + TABLE = :notes + COLUMNS = %i[id] + + enable_lock_retries! + + def up + initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end + + def down + revert_initialize_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end +end diff --git a/db/post_migrate/20230131005411_backfill_notes_id_for_bigint_conversion.rb b/db/post_migrate/20230131005411_backfill_notes_id_for_bigint_conversion.rb new file mode 100644 index 00000000000..b0ccc14e947 --- /dev/null +++ b/db/post_migrate/20230131005411_backfill_notes_id_for_bigint_conversion.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class BackfillNotesIdForBigintConversion < Gitlab::Database::Migration[2.1] + TABLE = :notes + COLUMNS = %i[id] + + restrict_gitlab_migration gitlab_schema: :gitlab_main + + def up + backfill_conversion_of_integer_to_bigint(TABLE, COLUMNS, sub_batch_size: 500) + end + + def down + revert_backfill_conversion_of_integer_to_bigint(TABLE, COLUMNS) + end +end diff --git a/db/post_migrate/20230214122717_fix_partition_ids_for_ci_job_variables.rb b/db/post_migrate/20230214122717_fix_partition_ids_for_ci_job_variables.rb new file mode 100644 index 00000000000..0a201c51467 --- /dev/null +++ b/db/post_migrate/20230214122717_fix_partition_ids_for_ci_job_variables.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class FixPartitionIdsForCiJobVariables < Gitlab::Database::Migration[2.1] + disable_ddl_transaction! + restrict_gitlab_migration gitlab_schema: :gitlab_ci + + BATCH_SIZE = 50 + + def up + return unless Gitlab.com? + + define_batchable_model(:ci_job_variables) + .where(partition_id: 101) + .each_batch(of: BATCH_SIZE) do |batch| + batch.update_all(partition_id: 100) + sleep 0.1 + end + end + + def down + # no-op + end +end diff --git a/db/post_migrate/20230216054348_prepare_async_foreign_key_validation_for_ci_job_artifacts.rb b/db/post_migrate/20230216054348_prepare_async_foreign_key_validation_for_ci_job_artifacts.rb new file mode 100644 index 00000000000..6d545361e10 --- /dev/null +++ b/db/post_migrate/20230216054348_prepare_async_foreign_key_validation_for_ci_job_artifacts.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class PrepareAsyncForeignKeyValidationForCiJobArtifacts < Gitlab::Database::Migration[2.1] + TABLE_NAME = :ci_job_artifacts + COLUMN_NAMES = [:partition_id, :job_id] + FOREIGN_KEY_NAME = :fk_rails_c5137cb2c1_p + + def up + prepare_async_foreign_key_validation(TABLE_NAME, COLUMN_NAMES, name: FOREIGN_KEY_NAME) + end + + def down + unprepare_async_foreign_key_validation(TABLE_NAME, COLUMN_NAMES, name: FOREIGN_KEY_NAME) + end +end diff --git a/db/schema_migrations/20230131004948 b/db/schema_migrations/20230131004948 new file mode 100644 index 00000000000..843732944a4 --- /dev/null +++ b/db/schema_migrations/20230131004948 @@ -0,0 +1 @@ +a72828f13fa31c30338ba1b833addbf7fd439e4ea2c51ded252db943826289d9
\ No newline at end of file diff --git a/db/schema_migrations/20230131005411 b/db/schema_migrations/20230131005411 new file mode 100644 index 00000000000..31ba576c9c9 --- /dev/null +++ b/db/schema_migrations/20230131005411 @@ -0,0 +1 @@ +21088bc90a263d5fd5e4cff9cfdea3b778dd98f9207ef6729acafadec40383b6
\ No newline at end of file diff --git a/db/schema_migrations/20230214122717 b/db/schema_migrations/20230214122717 new file mode 100644 index 00000000000..6f69502caa3 --- /dev/null +++ b/db/schema_migrations/20230214122717 @@ -0,0 +1 @@ +803a4aa4c28aecf498d2a70046850d8128327feb12fe1a42f1255cd08da7746e
\ No newline at end of file diff --git a/db/schema_migrations/20230216054348 b/db/schema_migrations/20230216054348 new file mode 100644 index 00000000000..c878ce97f9e --- /dev/null +++ b/db/schema_migrations/20230216054348 @@ -0,0 +1 @@ +d86d07d1a1f02b72cfa45ebe83088366d200af00c8ab77f3a287af8476d00f14
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 48186e629b3..c277291e823 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -225,6 +225,15 @@ RETURN NULL; END $$; +CREATE FUNCTION trigger_080e73845bfd() RETURNS trigger + LANGUAGE plpgsql + AS $$ +BEGIN + NEW."id_convert_to_bigint" := NEW."id"; + RETURN NEW; +END; +$$; + CREATE FUNCTION trigger_0e214b8a14f2() RETURNS trigger LANGUAGE plpgsql AS $$ @@ -18657,7 +18666,8 @@ CREATE TABLE notes ( review_id bigint, confidential boolean, last_edited_at timestamp with time zone, - internal boolean DEFAULT false NOT NULL + internal boolean DEFAULT false NOT NULL, + id_convert_to_bigint bigint DEFAULT 0 NOT NULL ); CREATE SEQUENCE notes_id_seq @@ -33737,6 +33747,8 @@ CREATE TRIGGER nullify_merge_request_metrics_build_data_on_update BEFORE UPDATE CREATE TRIGGER projects_loose_fk_trigger AFTER DELETE ON projects REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records(); +CREATE TRIGGER trigger_080e73845bfd BEFORE INSERT OR UPDATE ON notes FOR EACH ROW EXECUTE FUNCTION trigger_080e73845bfd(); + CREATE TRIGGER trigger_0e214b8a14f2 BEFORE INSERT OR UPDATE ON vulnerability_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_0e214b8a14f2(); CREATE TRIGGER trigger_17c3a95ee58a BEFORE INSERT OR UPDATE ON commit_user_mentions FOR EACH ROW EXECUTE FUNCTION trigger_17c3a95ee58a(); diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 5c66c98cb0c..7dc5b557d33 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -18976,6 +18976,26 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="projecttimelogsstarttime"></a>`startTime` | [`Time`](#time) | List timelogs within a time range where the logged time is equal to or after startTime. | | <a id="projecttimelogsusername"></a>`username` | [`String`](#string) | List timelogs for a user. | +##### `Project.visibleForks` + +Visible forks of the project. + +WARNING: +**Introduced** in 15.10. +This feature is in Alpha. It can be changed or removed at any time. + +Returns [`ProjectConnection`](#projectconnection). + +This field returns a [connection](#connections). It accepts the +four standard [pagination arguments](#connection-pagination-arguments): +`before: String`, `after: String`, `first: Int`, `last: Int`. + +###### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="projectvisibleforksminimumaccesslevel"></a>`minimumAccessLevel` | [`AccessLevelEnum`](#accesslevelenum) | Minimum access level. | + ##### `Project.vulnerabilities` Vulnerabilities reported on the project. diff --git a/doc/integration/partner_marketplace.md b/doc/integration/partner_marketplace.md new file mode 100644 index 00000000000..a15457b5b0c --- /dev/null +++ b/doc/integration/partner_marketplace.md @@ -0,0 +1,64 @@ +--- +stage: Fulfillment +group: Commerce Integrations +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Marketplace partner integration guide + +GitLab supports automation for selected distribution marketplaces to process sales of GitLab products to authorized +channel partners. Marketplace partners can use the GitLab Marketplace APIs to integrate their systems with GitLab to +sell GitLab subscriptions on their site. + +This document's target audience is third-party developers for Marketplace partners. + +## How the Marketplace APIs work + +The Marketplace APIs are hosted in the [Customers Portal](https://customers.gitlab.com/). The Customers Portal allows +individual customers to purchase and manage GitLab subscriptions and supports APIs for partners +to make sales on behalf of their customers. The Customers Portal integrates with other GitLab services, including +Zuora and Salesforce, to provide a task-oriented interface for users. + +The following example shows a typical purchase flow of request and response between the following components: + +- Customer +- Marketplace partner system +- Customers Portal +- Zuora +- Salesforce + +```mermaid +sequenceDiagram + participant Customer + participant Marketplace partner system + participant Customers Portal + participant Zuora + participant Salesforce + Customer ->> Marketplace partner system: Place order to purchase GitLab subscription + Marketplace partner system ->> Customers Portal: Get OAuth token + Customers Portal ->> Marketplace partner system: Access token + Marketplace partner system ->> Customers Portal: Place order + Customers Portal ->> Zuora: Create Zuora subscription + Customers Portal ->> Salesforce: Create Salesforce objects + Zuora ->> Customers Portal: Success response with Zuora subscription data + Customers Portal ->> Marketplace partner system: Success response with order ID + Zuora ->> Customers Portal: Zuora callout event + Customers Portal ->> Customer: send license notification + Marketplace partner system ->> Customers Portal: Poll order status + Customers Portal ->> Marketplace partner system: Success response with order status +``` + +## Prerequisites + +Before a marketplace partner client can use the Marketplace API, GitLab must set up the following configurations for the client: + +1. Client credential. Marketplace APIs are secured with OAuth 2.0. A client credential is required to get the OAuth token. +1. Invoice owner account in Zuora system. Required for invoice processing. +1. Distributor account in Salesforce system. +1. Trading partner account in Salesforce system. + +Interested GitLab Partners should contact their GitLab Partner Manager or email [`partnerorderops`](mailto:partnerorderops@gitlab.com). + +## Marketplace API Specification + +OpenAPI specs for the Marketplace APIs are available upon request. The specs will be made public before the end of Q1 2023. diff --git a/doc/operations/img/copy-group-id.png b/doc/operations/img/copy-group-id.png Binary files differnew file mode 100644 index 00000000000..7837f49c3e3 --- /dev/null +++ b/doc/operations/img/copy-group-id.png diff --git a/doc/operations/img/create-gitlab-application.png b/doc/operations/img/create-gitlab-application.png Binary files differnew file mode 100644 index 00000000000..430b830cdb2 --- /dev/null +++ b/doc/operations/img/create-gitlab-application.png diff --git a/doc/operations/img/listing_groups.png b/doc/operations/img/listing_groups.png Binary files differnew file mode 100644 index 00000000000..1094bf4ff28 --- /dev/null +++ b/doc/operations/img/listing_groups.png diff --git a/doc/operations/quickstart-guide.md b/doc/operations/quickstart-guide.md new file mode 100644 index 00000000000..91c5f25405c --- /dev/null +++ b/doc/operations/quickstart-guide.md @@ -0,0 +1,229 @@ +--- +stage: Monitor +group: Observability +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# GitLab Observability Quickstart + +You can try GitLab Observability by [cloning or forking the project](https://gitlab.com/gitlab-org/opstrace/opstrace.git) and creating a local installation. + +## Prerequisites and dependencies + +To install GitLab Observability Platform (GOP), install and configure the following third-party dependencies. You can do this manually, or [automatically by using asdf](#install-dependencies-using-asdf): + +- [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) for creating a local Kubernetes cluster. +- [Docker](https://docs.docker.com/install) + - [Docker Compose](https://docs.docker.com/compose/compose-v2/) is now part of the `docker` distribution. +- [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) for interacting with GitLab Observability. +- [Telepresence](https://www.telepresence.io/) allows you to code and test microservices locally against a remote Kubernetes cluster. +- [jq](https://stedolan.github.io/jq/download/) for some Makefile utilities. +- [Go 1.19](https://go.dev/doc/install). + +The current versions of these dependencies are pinned in the `.tool-versions` file in the project. + +You can run the following commands to check the availability and versions of these dependencies on your machine: + +```shell +kind --version +docker --version +kubectl version +telepresence version +jq --version +go version +``` + +### Run GOP on macOS + +If you're running GOP on macOS, ensure you have enough resources dedicated to Docker Desktop. The recommended minimum is: + +- CPUs: 4+ +- Memory: 8 GB+ +- Swap: 1 GB+ + +It's possible to run GOP with fewer resources, but this specification works. + +### Install dependencies using asdf + +If you install dependencies using [`asdf`](https://asdf-vm.com/#/core-manage-asdf), GOP manages them for you automatically. + +1. If you have not already done so, clone the `opstrace` repository into your preferred location: + + ```shell + git clone https://gitlab.com/gitlab-org/opstrace/opstrace.git + ``` + +1. Change into the project directory: + + ```shell + cd opstrace + ``` + +1. Optional. If you need to install `asdf`, run: + + ```shell + make install-asdf + ``` + +1. Install dependencies using `asdf`: + + ```shell + make bootstrap + ``` + +## Step 1: Create a local Kubernetes cluster with kind + +Make sure Docker Desktop is running. In the `opstrace` project you cloned, run the following command: + +```shell +make kind +``` + +Wait a few minutes while kind creates your Kubernetes cluster. When it's finished, you should see the following message: + +```plaintext +Traffic Manager installed successfully +``` + +Now deploy the scheduler by running the following command in the `opstrace` project: + +```shell +make deploy +``` + +This takes around 1 minute. + +## Step 2: Create a GitLab application for authentication + +You must create a GitLab application to use for authentication. + +In the GitLab instance you'd like to connect with GOP, [create an OAuth application](../integration/oauth_provider.md). +This application can be a user-owned, group-owned or instance-wide application. +In production, you would create a trusted instance-wide application so that users are explicitly authorized without the consent screen. +The following example shows how to configure the application. + +1. Select the API scope and enter `http://localhost/v1/auth/callback` as the redirect URI. + +1. Run the following command to create the secret that holds the authentication data: + + ```shell + kubectl create secret generic \ + --from-literal=gitlab_oauth_client_id=<gitlab_application_client_id> \ + --from-literal=gitlab_oauth_client_secret=<gitlab_application_client_secret> \ + --from-literal=internal_endpoint_token=<error_tracking_internal_endpoint_token> \ + dev-secret + ``` + +1. Replace `<gitlab_application_client_id>` and `<gitlab_application_client_secret>` with the values from the GitLab application you just created. +Replace `<error_tracking_internal_endpoint_token>` with any string if you do not plan to use error tracking. + +You can also view [this MR on how to get the token to test error tracking](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91928). +You must specify all the parameters when creating the secret. + +## Step 3: Create the cluster definition + +1. In your `opstrace` project, run the following command to create a `Cluster.yaml` manifest file: + + ```shell + cat <<EOF > Cluster.yaml + apiVersion: opstrace.com/v1alpha1 + kind: Cluster + metadata: + name: dev-cluster + spec: + target: kind + goui: + image: "registry.gitlab.com/gitlab-org/opstrace/opstrace-ui/ gitlab-observability-ui:c9fb6e70" + dns: + acmeEmail: "" + dns01Challenge: {} + externalDNSProvider: {} + gitlab: + groupAllowedAccess: '*' + groupAllowedSystemAccess: "6543" + instanceUrl: https://gitlab.com + authSecret: + name: dev-secret + EOF + ``` + +1. Apply the file you just created with the following command: + + ```shell + kubectl apply -f Cluster.yaml + ``` + +1. Run the following command to wait for the cluster to be ready: + + ```shell + kubectl wait --for=condition=ready cluster/dev-cluster --timeout=600s + ``` + +After the previous command exits, the cluster is ready. + +## Step 4: Enable Observability on a GitLab namespace you own + +Go to a namespace you own in the connected GitLab instance and copy the Group ID below the group name. + +GOP can only be enabled for groups you own. +To list all the groups that your user owns, go to the menu in upper left corner and select `Groups`->`View all Groups`. You then see the **Your groups** tab. + +In your browser, go to `http://localhost/-/{GroupID}`. For example, `http://localhost/-/14485840`. + +Follow the on-screen instructions to enable observability for the namespace. +This can take a couple of minutes if it's the first time observability has been enabled for the root level namespace (GitLab.org in the previous example.) + +Once your namespace has been enabled and is ready, the page automatically redirects you to the GitLab Observability UI. + +## Step 5: Send traces to GOP + +[Follow this guide to send traces to your namespace and monitor them in the UI](https://gitlab.com/gitlab-org/opstrace/opstrace/-/blob/main/docs/guides/user/sending-traces-locally.md). + +## Step 6: Clean up your local GOP + +To tear down your locally running GOP instance, run the following command: + +```shell +make destroy +``` + +## Known issues + +### Incorrect architecture for `kind/node` image + +If your machine has an Apple silicon (M1/M2) chip, you might encounter an architecture problem with the `kind/node` image when running the `make kind` command. For more details, see [issue 1802](https://gitlab.com/gitlab-org/opstrace/opstrace/-/issues/1802). + +To fix this problem, you first need to create a Dockerfile. Then build and deploy the image: + +1. Create a new Dockerfile (without a file extension) and paste the following commands: + + ```Dockerfile + FROM --platform=arm64 kindest/node:v1.23.13 + RUN arch + ``` + +1. Save your Dockerfile, then build the image with the following command: + + ```shell + docker build -t tempkind . + ``` + + Do not forget the period at the end. + +1. Create a cluster using your new image with the following command: + + ```shell + kind create cluster --image tempkind + ``` + +### scheduler-controller-manager pod cannot start due to ImagePullBackOff + +If while executing `make deploy` in step 1, the `scheduler-controller-manager` pod cannot start due to `ImagePullBackOff`, you must set the `CI_COMMIT_TAG` to a non-dirty state. By setting the commit tag to the latest commit, you ensure the Docker image can be pulled from the container registry. + +Run the following command to set the commit tag: + +```shell +make kind +export CI_COMMIT_TAG=0.2.0-e1206acf +make deploy +``` diff --git a/locale/gitlab.pot b/locale/gitlab.pot index c8b63b58559..a811c9b16bb 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -34678,9 +34678,15 @@ msgstr "" msgid "ProtectedEnvironments|Set which groups, access levels or users that are allowed to deploy to this environment" msgstr "" +msgid "ProtectedEnvironments|Unified approval rules have been removed from the settings UI" +msgstr "" + msgid "ProtectedEnvironments|Users" msgstr "" +msgid "ProtectedEnvironments|You can still use the %{apiLinkStart}API%{apiLinkEnd} to configure unified approval rules. Consider using %{docsLinkStart}multiple approval rules%{docsLinkEnd} instead, because they provide greater flexibility." +msgstr "" + msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?" msgstr "" diff --git a/qa/gdk/Dockerfile b/qa/gdk/Dockerfile new file mode 100644 index 00000000000..ed8f3f317eb --- /dev/null +++ b/qa/gdk/Dockerfile @@ -0,0 +1,50 @@ +FROM registry.gitlab.com/gitlab-org/gitlab-development-kit/asdf-bootstrapped-gdk-installed-gitlab-e2e:ml-create-image-for-gitlab-qa-tests + +ENV CHROME_DRIVER_VERSION="107.0.5304.62" +ENV CHROME_VERSION="107.0.5304.87-1" +ENV CHROME_DEB="google-chrome-stable_${CHROME_VERSION}_amd64.deb" +ENV CHROME_URL="https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab-build-images/packages/generic/google-chrome-stable/${CHROME_VERSION}/${CHROME_DEB}" + +WORKDIR /home/gdk/gdk + +COPY --chown=gdk qa/gdk/gdk.yml . + +RUN cat gdk.yml && \ + gdk update && \ + gdk restart && \ + ./support/test_url http://gdk.test:3000 && \ + gdk stop && sleep 5 && \ + GDK_KILL_CONFIRM=true gdk kill && \ + ps -ef && \ + cd gitlab && git reset --hard && \ + sudo rm -rf "$HOME/gdk/gitaly/_build/deps/git/source" \ + "$HOME/gdk/gitaly/_build/deps/libgit2/source" \ + "$HOME/gdk/gitaly/_build/cache" \ + "$HOME/gdk/gitaly/_build/deps" \ + "$HOME/gdk/gitaly/_build/intermediate" \ + "$HOME/.cache/" \ + "$HOME/gdk/gdk/gitlab" \ + /tmp/* + +# Install Google Chrome version with headless support +# Download from our local S3 bucket, populated by https://gitlab.com/gitlab-org/gitlab-build-images/-/blob/master/scripts/cache-google-chrome +# +RUN echo "${CHROME_URL}" && \ + curl --silent --show-error --fail -O "${CHROME_URL}" && \ + sudo apt update && \ + sudo dpkg -i "./${CHROME_DEB}" || true && \ + sudo apt install -f -y && \ + rm -f "./${CHROME_DEB}" + +WORKDIR /home/gdk/gdk/gitlab + +RUN bundle install --jobs=$(nproc) --retry=3 --quiet +RUN cd qa && \ + bundle install --jobs=$(nproc) --retry=3 --quiet && \ + bundle exec rake -f tasks/webdrivers.rake webdrivers:chromedriver:update[${CHROME_DRIVER_VERSION}] + +RUN git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" + +COPY --chown=gdk qa/gdk/launch . + +ENTRYPOINT ["./launch"] diff --git a/qa/gdk/gdk.yml b/qa/gdk/gdk.yml new file mode 100644 index 00000000000..0494cd0d3c1 --- /dev/null +++ b/qa/gdk/gdk.yml @@ -0,0 +1,26 @@ +--- +hostname: gdk.test +sshd: + additional_config: 'AcceptEnv GIT_PROTOCOL' +webpack: + live_reload: false + sourcemaps: false + incremental: false +gdk: + ask_to_restart_after_update: false + auto_reconfigure: false + overwrite_changes: true + quiet: false +gitlab: + rails: + bootsnap: false + hostname: gdk.test +gitlab_k8s_agent: + enabled: false +gitlab_pages: + enabled: false +prometheus: + enabled: false +tracer: + jaeger: + enabled: false diff --git a/qa/gdk/launch b/qa/gdk/launch new file mode 100755 index 00000000000..4b1fc6ae191 --- /dev/null +++ b/qa/gdk/launch @@ -0,0 +1,40 @@ +#!/bin/bash + +COMMIT_REF=${1:-$CI_COMMIT_REF_SLUG} +RSPEC_ARGS=$2 + +if [ -z "${COMMIT_REF}" ]; then + echo "Please provide a commit ref with the code to be tested as the first argument" + exit 1 +fi + +# Set the GitLab license mode to "test" so that GitLab uses the appropriate encryption key +export GITLAB_LICENSE_MODE="test" + +# Create the temporary directory that screenshots are saved to +sudo install -m 777 -d /home/gdk/gdk/gitlab/qa/tmp + +# Update GDK +(cd .. ; gdk update ; cat gdk.yml) + +# Reset, fetch, and checkout the GitLab repository with the code from the ref to be tested +git reset --hard +git fetch origin $COMMIT_REF +git checkout $COMMIT_REF + +# Install the required gems +bundle install --jobs=$(nproc) --retry=3 --quiet + +# Run the database migrations +bundle exec rake db:migrate + +# Restart GDK to be sure any changes are accounted for in running services, start any stopped services, and wait until the GDK is reachable +(cd .. ; gdk restart ; ./support/test_url http://gdk.test:3000) + +# Install the required gems in the QA directory +cd qa +bundle install --jobs=$(nproc) --retry=3 --quiet + +# Run the tests +bundle exec rake "knapsack:download[test]" +bundle exec bin/qa Test::Instance::All http://gdk.test:3000 -- $RSPEC_ARGS || true @@ -85,11 +85,6 @@ module QA "fips" => "FIPS" ) - # Configure knapsack at the very begining of the setup - loader.on_setup do - QA::Support::KnapsackReport.configure! - end - loader.setup loader.eager_load end diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb index 8af78bb86c6..f4f8820bc04 100644 --- a/qa/qa/page/main/login.rb +++ b/qa/qa/page/main/login.rb @@ -76,16 +76,13 @@ module QA end def sign_in_using_admin_credentials - admin = QA::Resource::User.init do |user| - user.username = QA::Runtime::User.admin_username - user.password = QA::Runtime::User.admin_password - end - using_wait_time 0 do set_initial_password_if_present sign_in_using_gitlab_credentials(user: admin) end + set_up_new_admin_password_if_required + Page::Main::Menu.perform(&:has_personal_area?) end @@ -105,6 +102,24 @@ module QA Page::Main::Menu.perform(&:signed_in?) end + # Handle request for password change + # Happens on clean GDK installations when seeded root admin password is expired + # + def set_up_new_password_if_required(user:, skip_page_validation:) + return unless has_content?('Set up new password') + + Profile::Password.perform do |new_password_page| + password = user&.password || Runtime::User.password + new_password_page.set_new_password(password, password) + end + + sign_in_using_credentials(user: user, skip_page_validation: skip_page_validation) + end + + def set_up_new_admin_password_if_required + set_up_new_password_if_required(user: admin, skip_page_validation: false) + end + def self.path '/users/sign_in' end @@ -181,6 +196,13 @@ module QA private + def admin + @admin ||= QA::Resource::User.init do |user| + user.username = QA::Runtime::User.admin_username + user.password = QA::Runtime::User.admin_password + end + end + def sign_in_using_gitlab_credentials(user:, skip_page_validation: false) wait_if_retry_later @@ -219,20 +241,6 @@ module QA fill_element :password_field, user.password end - # Handle request for password change - # Happens on clean GDK installations when seeded root admin password is expired - # - def set_up_new_password_if_required(user:, skip_page_validation:) - return unless has_content?('Set up new password') - - Profile::Password.perform do |new_password_page| - password = user&.password || Runtime::User.password - new_password_page.set_new_password(password, password) - end - - sign_in_using_credentials(user: user, skip_page_validation: skip_page_validation) - end - def set_initial_password_if_present return unless has_content?('Change your password') diff --git a/qa/qa/specs/knapsack_runner.rb b/qa/qa/specs/knapsack_runner.rb index 4908553e43d..0c4f938ee28 100644 --- a/qa/qa/specs/knapsack_runner.rb +++ b/qa/qa/specs/knapsack_runner.rb @@ -4,6 +4,8 @@ module QA module Specs class KnapsackRunner def self.run(args) + QA::Support::KnapsackReport.configure! + allocator = Knapsack::AllocatorBuilder.new(Knapsack::Adapters::RSpecAdapter).allocator Knapsack.logger.info '==== Knapsack specs to execute =====' diff --git a/qa/qa/specs/spec_helper.rb b/qa/qa/specs/spec_helper.rb index 0e6e3973de9..1bf189ed6ac 100644 --- a/qa/qa/specs/spec_helper.rb +++ b/qa/qa/specs/spec_helper.rb @@ -11,6 +11,7 @@ QA::Support::GitlabAddress.define_gitlab_address_attribute! QA::Runtime::Browser.configure! unless QA::Runtime::Env.dry_run QA::Runtime::AllureReport.configure! QA::Runtime::Scenario.from_env(QA::Runtime::Env.runtime_scenario_attributes) +QA::Support::KnapsackReport.configure! # Enable zero monkey patching mode before loading any other RSpec code. RSpec.configure(&:disable_monkey_patching!) diff --git a/qa/tasks/ci.rake b/qa/tasks/ci.rake index bfb364aa5ee..aaf691de1b5 100644 --- a/qa/tasks/ci.rake +++ b/qa/tasks/ci.rake @@ -60,4 +60,9 @@ namespace :ci do QA::Tools::Ci::TestMetrics.export(args[:glob]) end + + desc "Get available QA environment variables" + task :env_var_name_list do + puts Gitlab::QA::Runtime::Env.variables.keys.join("\n") + end end diff --git a/qa/tasks/knapsack.rake b/qa/tasks/knapsack.rake index c502d1cbb4a..5e60703ced3 100644 --- a/qa/tasks/knapsack.rake +++ b/qa/tasks/knapsack.rake @@ -20,6 +20,7 @@ namespace :knapsack do test_stage_name = args[:stage_name] knapsack_reports = ENV["QA_KNAPSACK_REPORTS"]&.split(",") ci_token = ENV["QA_GITLAB_CI_TOKEN"] + QA::Support::KnapsackReport.configure! reports = if knapsack_reports knapsack_reports @@ -43,6 +44,7 @@ namespace :knapsack do desc "Merge and upload knapsack report" task :upload, [:glob] do |_task, args| + QA::Support::KnapsackReport.configure! QA::Support::KnapsackReport.upload_report(args[:glob]) end diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb index 86a4ac61194..8e62aeed7d0 100644 --- a/spec/controllers/admin/clusters_controller_spec.rb +++ b/spec/controllers/admin/clusters_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Admin::ClustersController do +RSpec.describe Admin::ClustersController, feature_category: :kubernetes_management do include AccessMatchersForController include GoogleApi::CloudPlatformHelpers diff --git a/spec/controllers/admin/instance_review_controller_spec.rb b/spec/controllers/admin/instance_review_controller_spec.rb index 342562618b2..6eab135b3a6 100644 --- a/spec/controllers/admin/instance_review_controller_spec.rb +++ b/spec/controllers/admin/instance_review_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Admin::InstanceReviewController do +RSpec.describe Admin::InstanceReviewController, feature_category: :service_ping do include UsageDataHelpers let(:admin) { create(:admin) } diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb index e9b39d44e46..97729d181b1 100644 --- a/spec/controllers/autocomplete_controller_spec.rb +++ b/spec/controllers/autocomplete_controller_spec.rb @@ -6,7 +6,7 @@ RSpec.describe AutocompleteController do let(:project) { create(:project) } let(:user) { project.first_owner } - context 'GET users' do + context 'GET users', feature_category: :user_management do let!(:user2) { create(:user) } let!(:non_member) { create(:user) } @@ -248,7 +248,7 @@ RSpec.describe AutocompleteController do end end - context 'GET projects' do + context 'GET projects', feature_category: :projects do let(:authorized_project) { create(:project) } let(:authorized_search_project) { create(:project, name: 'rugged') } @@ -339,7 +339,7 @@ RSpec.describe AutocompleteController do end end - context 'GET award_emojis' do + context 'GET award_emojis', feature_category: :team_planning do let(:user2) { create(:user) } let!(:award_emoji1) { create_list(:award_emoji, 2, user: user, name: 'thumbsup') } let!(:award_emoji2) { create_list(:award_emoji, 1, user: user, name: 'thumbsdown') } @@ -377,7 +377,7 @@ RSpec.describe AutocompleteController do end end - context 'GET deploy_keys_with_owners' do + context 'GET deploy_keys_with_owners', feature_category: :continuous_delivery do let_it_be(:public_project) { create(:project, :public) } let_it_be(:user) { create(:user) } let_it_be(:deploy_key) { create(:deploy_key, user: user) } @@ -451,7 +451,7 @@ RSpec.describe AutocompleteController do end end - context 'Get merge_request_target_branches' do + context 'Get merge_request_target_branches', feature_category: :code_review_workflow do let!(:merge_request) { create(:merge_request, source_project: project, target_branch: 'feature') } context 'anonymous user' do diff --git a/spec/controllers/dashboard/projects_controller_spec.rb b/spec/controllers/dashboard/projects_controller_spec.rb index b4a4ac56fce..e8ee146a13a 100644 --- a/spec/controllers/dashboard/projects_controller_spec.rb +++ b/spec/controllers/dashboard/projects_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Dashboard::ProjectsController, :aggregate_failures do +RSpec.describe Dashboard::ProjectsController, :aggregate_failures, feature_category: :projects do include ExternalAuthorizationServiceHelpers let_it_be(:user) { create(:user) } diff --git a/spec/controllers/explore/projects_controller_spec.rb b/spec/controllers/explore/projects_controller_spec.rb index a79d9fa1276..c4f0feb21e2 100644 --- a/spec/controllers/explore/projects_controller_spec.rb +++ b/spec/controllers/explore/projects_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Explore::ProjectsController do +RSpec.describe Explore::ProjectsController, feature_category: :projects do shared_examples 'explore projects' do let(:expected_default_sort) { 'latest_activity_desc' } diff --git a/spec/controllers/groups/children_controller_spec.rb b/spec/controllers/groups/children_controller_spec.rb index f05551432fa..d0656ee47ce 100644 --- a/spec/controllers/groups/children_controller_spec.rb +++ b/spec/controllers/groups/children_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::ChildrenController do +RSpec.describe Groups::ChildrenController, feature_category: :subgroups do include ExternalAuthorizationServiceHelpers let(:group) { create(:group, :public) } diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb index 46f507c34ba..01ea7101f2e 100644 --- a/spec/controllers/groups/clusters_controller_spec.rb +++ b/spec/controllers/groups/clusters_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::ClustersController do +RSpec.describe Groups::ClustersController, feature_category: :kubernetes_management do include AccessMatchersForController include GoogleApi::CloudPlatformHelpers diff --git a/spec/controllers/groups/labels_controller_spec.rb b/spec/controllers/groups/labels_controller_spec.rb index 0521c5e02a8..916b2cf10dd 100644 --- a/spec/controllers/groups/labels_controller_spec.rb +++ b/spec/controllers/groups/labels_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::LabelsController do +RSpec.describe Groups::LabelsController, feature_category: :team_planning do let_it_be(:group) { create(:group) } let_it_be(:user) { create(:user) } let_it_be(:project) { create(:project, namespace: group) } diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index fd01aee709a..dcde22c1fd6 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::BranchesController do +RSpec.describe Projects::BranchesController, feature_category: :source_code_management do let(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:developer) { create(:user) } diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb index 894f0f8354d..a4f7c92f5cd 100644 --- a/spec/controllers/projects/clusters_controller_spec.rb +++ b/spec/controllers/projects/clusters_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ClustersController do +RSpec.describe Projects::ClustersController, feature_category: :kubernetes_management do include AccessMatchersForController include GoogleApi::CloudPlatformHelpers include KubernetesHelpers diff --git a/spec/controllers/projects/commits_controller_spec.rb b/spec/controllers/projects/commits_controller_spec.rb index 26d4725656f..67aa82dacbb 100644 --- a/spec/controllers/projects/commits_controller_spec.rb +++ b/spec/controllers/projects/commits_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::CommitsController do +RSpec.describe Projects::CommitsController, feature_category: :source_code_management do let(:project) { create(:project, :repository) } let(:user) { create(:user) } diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb index 48e58cc0e38..169fed1ab17 100644 --- a/spec/controllers/projects/environments_controller_spec.rb +++ b/spec/controllers/projects/environments_controller_spec.rb @@ -104,30 +104,16 @@ RSpec.describe Projects::EnvironmentsController, feature_category: :continuous_d end context 'can access stop stale environments feature' do - context 'when stop_stale_environments FF is enabled' do - it 'maintainers can access the feature' do - get :index, params: environment_params(format: :json) - - expect(json_response['can_stop_stale_environments']).to be_truthy - end - - context 'when user is a reporter' do - let(:user) { reporter } + it 'maintainers can access the feature' do + get :index, params: environment_params(format: :json) - it 'reporters cannot access the feature' do - get :index, params: environment_params(format: :json) - - expect(json_response['can_stop_stale_environments']).to be_falsey - end - end + expect(json_response['can_stop_stale_environments']).to be_truthy end - context 'when stop_stale_environments FF is disabled' do - before do - stub_feature_flags(stop_stale_environments: false) - end + context 'when user is a reporter' do + let(:user) { reporter } - it 'maintainers cannot access the feature' do + it 'reporters cannot access the feature' do get :index, params: environment_params(format: :json) expect(json_response['can_stop_stale_environments']).to be_falsey diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb index 962ef93dc72..25c722173c1 100644 --- a/spec/controllers/projects/forks_controller_spec.rb +++ b/spec/controllers/projects/forks_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::ForksController do +RSpec.describe Projects::ForksController, feature_category: :source_code_management do let(:user) { create(:user) } let(:project) { create(:project, :public, :repository) } let(:forked_project) { Projects::ForkService.new(project, user, name: 'Some name').execute } diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index b4084e0f9eb..9c272872a73 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::IssuesController do +RSpec.describe Projects::IssuesController, feature_category: :team_planning do include ProjectForksHelper include_context 'includes Spam constants' diff --git a/spec/controllers/projects/labels_controller_spec.rb b/spec/controllers/projects/labels_controller_spec.rb index dfa6ed639b6..98982856d6c 100644 --- a/spec/controllers/projects/labels_controller_spec.rb +++ b/spec/controllers/projects/labels_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::LabelsController do +RSpec.describe Projects::LabelsController, feature_category: :team_planning do let_it_be(:group) { create(:group) } let_it_be(:project, reload: true) { create(:project, namespace: group) } let_it_be(:user) { create(:user) } diff --git a/spec/controllers/projects/merge_requests/creations_controller_spec.rb b/spec/controllers/projects/merge_requests/creations_controller_spec.rb index 7db708e0e78..3d4a884587f 100644 --- a/spec/controllers/projects/merge_requests/creations_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/creations_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::MergeRequests::CreationsController do +RSpec.describe Projects::MergeRequests::CreationsController, feature_category: :code_review_workflow do let(:project) { create(:project, :repository) } let(:user) { project.first_owner } let(:fork_project) { create(:forked_project_with_submodules) } diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb index 05c07c9f00d..23a33d7e0b1 100644 --- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::MergeRequests::DiffsController do +RSpec.describe Projects::MergeRequests::DiffsController, feature_category: :code_review_workflow do include ProjectForksHelper include TrackingHelpers diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb index dcd1072612a..ba917fa3a31 100644 --- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb +++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb @@ -2,7 +2,7 @@ require('spec_helper') -RSpec.describe Projects::Settings::CiCdController do +RSpec.describe Projects::Settings::CiCdController, feature_category: :continuous_integration do let_it_be(:user) { create(:user) } let_it_be(:project_auto_devops) { create(:project_auto_devops) } diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index cf87b2c4437..51f8a3b1197 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -2,7 +2,7 @@ require('spec_helper') -RSpec.describe ProjectsController do +RSpec.describe ProjectsController, feature_category: :projects do include ExternalAuthorizationServiceHelpers include ProjectForksHelper using RSpec::Parameterized::TableSyntax diff --git a/spec/features/profiles/keys_spec.rb b/spec/features/profiles/keys_spec.rb index e1c21f2117a..ae61f1cf492 100644 --- a/spec/features/profiles/keys_spec.rb +++ b/spec/features/profiles/keys_spec.rb @@ -126,7 +126,7 @@ RSpec.describe 'Profile > SSH Keys', feature_category: :user_profile do visit project_commit_path(project, commit) wait_for_all_requests - page.find('a.gpg-status-box', text: 'Verified').click + find('a.signature-badge', text: 'Verified').click within('.popover') do expect(page).to have_content("Verified commit") @@ -138,7 +138,7 @@ RSpec.describe 'Profile > SSH Keys', feature_category: :user_profile do visit project_commit_path(project, commit) wait_for_all_requests - page.find('a.gpg-status-box', text: 'Unverified').click + find('a.signature-badge', text: 'Unverified').click within('.popover') do expect(page).to have_content("Unverified signature") diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 0c5985f7735..7faf0e1a6b1 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -1007,8 +1007,8 @@ RSpec.describe 'File blob', :js, feature_category: :projects do it 'displays a GPG badge' do visit_blob('CONTRIBUTING.md', ref: '33f3729a45c02fc67d00adb1b8bca394b0e761d9') - expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge' - expect(page).to have_selector '.gpg-status-box.invalid' + expect(page).not_to have_selector '.js-loading-signature-badge' + expect(page).to have_selector '.gl-badge.badge-muted' end end @@ -1016,8 +1016,8 @@ RSpec.describe 'File blob', :js, feature_category: :projects do it 'displays a GPG badge' do visit_blob('conflicting-file.md', ref: '6101e87e575de14b38b4e1ce180519a813671e10') - expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge' - expect(page).to have_selector '.gpg-status-box.invalid' + expect(page).not_to have_selector '.js-loading-signature-badge' + expect(page).to have_selector '.gl-badge.badge-muted' end end diff --git a/spec/features/projects/tree/tree_show_spec.rb b/spec/features/projects/tree/tree_show_spec.rb index da589b97e3f..52c6cb2192b 100644 --- a/spec/features/projects/tree/tree_show_spec.rb +++ b/spec/features/projects/tree/tree_show_spec.rb @@ -94,8 +94,8 @@ RSpec.describe 'Projects tree', :js, feature_category: :web_ide do visit project_tree_path(project, '33f3729a45c02fc67d00adb1b8bca394b0e761d9') wait_for_requests - expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge' - expect(page).to have_selector '.gpg-status-box.invalid' + expect(page).not_to have_selector '.js-loading-signature-badge' + expect(page).to have_selector '.gl-badge.badge-muted' end context 'on a directory that has not changed recently' do @@ -104,8 +104,8 @@ RSpec.describe 'Projects tree', :js, feature_category: :web_ide do visit project_tree_path(project, tree_path) wait_for_requests - expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge' - expect(page).to have_selector '.gpg-status-box.invalid' + expect(page).not_to have_selector '.js-loading-signature-badge' + expect(page).to have_selector '.gl-badge.badge-muted' end end end @@ -152,8 +152,8 @@ RSpec.describe 'Projects tree', :js, feature_category: :web_ide do visit project_tree_path(project, '33f3729a45c02fc67d00adb1b8bca394b0e761d9') wait_for_requests - expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge' - expect(page).to have_selector '.gpg-status-box.invalid' + expect(page).not_to have_selector '.js-loading-signature-badge' + expect(page).to have_selector '.gl-badge.badge-muted' end end end diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index 84702b3a6bb..73ee250a8b8 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -343,8 +343,8 @@ RSpec.describe 'Project', feature_category: :projects do visit project_path(project) wait_for_requests - expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge' - expect(page).to have_selector '.gpg-status-box.invalid' + expect(page).not_to have_selector '.js-loading-signature-badge' + expect(page).to have_selector '.gl-badge.badge-muted' end end @@ -371,8 +371,8 @@ RSpec.describe 'Project', feature_category: :projects do visit project_path(project) wait_for_requests - expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge' - expect(page).to have_selector '.gpg-status-box.invalid' + expect(page).not_to have_selector '.gl-badge.js-loading-signature-badge' + expect(page).to have_selector '.gl-badge.badge-muted' end end end diff --git a/spec/features/signed_commits_spec.rb b/spec/features/signed_commits_spec.rb index bc82afc70a3..5d9b451cdf6 100644 --- a/spec/features/signed_commits_spec.rb +++ b/spec/features/signed_commits_spec.rb @@ -16,7 +16,7 @@ RSpec.describe 'GPG signed commits', feature_category: :source_code_management d visit project_commit_path(project, ref) - expect(page).to have_selector('.gpg-status-box', text: 'Unverified') + expect(page).to have_selector('.gl-badge', text: 'Unverified') # user changes their email which makes the gpg key verified perform_enqueued_jobs do @@ -26,7 +26,7 @@ RSpec.describe 'GPG signed commits', feature_category: :source_code_management d visit project_commit_path(project, ref) - expect(page).to have_selector('.gpg-status-box', text: 'Verified') + expect(page).to have_selector('.gl-badge', text: 'Verified') end it 'changes from unverified to verified when the user adds the missing gpg key', :sidekiq_might_not_need_inline do @@ -35,7 +35,7 @@ RSpec.describe 'GPG signed commits', feature_category: :source_code_management d visit project_commit_path(project, ref) - expect(page).to have_selector('.gpg-status-box', text: 'Unverified') + expect(page).to have_selector('.gl-badge', text: 'Unverified') # user adds the gpg key which makes the signature valid perform_enqueued_jobs do @@ -44,7 +44,7 @@ RSpec.describe 'GPG signed commits', feature_category: :source_code_management d visit project_commit_path(project, ref) - expect(page).to have_selector('.gpg-status-box', text: 'Verified') + expect(page).to have_selector('.gl-badge', text: 'Verified') end context 'shows popover badges', :js do @@ -75,7 +75,7 @@ RSpec.describe 'GPG signed commits', feature_category: :source_code_management d visit project_commit_path(project, GpgHelpers::SIGNED_COMMIT_SHA) wait_for_all_requests - page.find('.gpg-status-box', text: 'Unverified').click + page.find('.gl-badge', text: 'Unverified').click within '.popover' do expect(page).to have_content 'This commit was signed with an unverified signature.' @@ -90,7 +90,7 @@ RSpec.describe 'GPG signed commits', feature_category: :source_code_management d visit project_commit_path(project, GpgHelpers::SIGNED_COMMIT_SHA) wait_for_all_requests - page.find('.gpg-status-box', text: 'Unverified').click + page.find('.gl-badge', text: 'Unverified').click within '.popover' do expect(page).to have_content 'This commit was signed with a verified signature, but the committer email is not associated with the GPG Key.' @@ -104,7 +104,7 @@ RSpec.describe 'GPG signed commits', feature_category: :source_code_management d visit project_commit_path(project, GpgHelpers::SIGNED_COMMIT_SHA) wait_for_all_requests - page.find('.gpg-status-box', text: 'Unverified').click + page.find('.gl-badge', text: 'Unverified').click within '.popover' do expect(page).to have_content "This commit was signed with a different user's verified signature." @@ -118,7 +118,7 @@ RSpec.describe 'GPG signed commits', feature_category: :source_code_management d visit project_commit_path(project, GpgHelpers::MULTIPLE_SIGNATURES_SHA) wait_for_all_requests - page.find('.gpg-status-box', text: 'Unverified').click + page.find('.gl-badge', text: 'Unverified').click within '.popover' do expect(page).to have_content "This commit was signed with multiple signatures." @@ -131,7 +131,7 @@ RSpec.describe 'GPG signed commits', feature_category: :source_code_management d visit project_commit_path(project, GpgHelpers::SIGNED_AND_AUTHORED_SHA) wait_for_all_requests - page.find('.gpg-status-box', text: 'Verified').click + page.find('.gl-badge', text: 'Verified').click within '.popover' do expect(page).to have_content 'This commit was signed with a verified signature and the committer email was verified to belong to the same user.' @@ -146,14 +146,14 @@ RSpec.describe 'GPG signed commits', feature_category: :source_code_management d wait_for_all_requests # wait for the signature to get generated - expect(page).to have_selector('.gpg-status-box', text: 'Verified') + expect(page).to have_selector('.gl-badge', text: 'Verified') user_1.destroy! refresh wait_for_all_requests - page.find('.gpg-status-box', text: 'Verified').click + page.find('.gl-badge', text: 'Verified').click within '.popover' do expect(page).to have_content 'This commit was signed with a verified signature and the committer email was verified to belong to the same user.' @@ -170,9 +170,9 @@ RSpec.describe 'GPG signed commits', feature_category: :source_code_management d end it 'displays commit signature' do - expect(page).to have_selector('.gpg-status-box', text: 'Unverified') + expect(page).to have_selector('.gl-badge', text: 'Unverified') - page.find('.gpg-status-box', text: 'Unverified').click + page.find('.gl-badge', text: 'Unverified').click within '.popover' do expect(page).to have_content 'This commit was signed with multiple signatures.' diff --git a/spec/finders/releases/group_releases_finder_spec.rb b/spec/finders/releases/group_releases_finder_spec.rb index 5eac6f4fbdc..c47477eb3d5 100644 --- a/spec/finders/releases/group_releases_finder_spec.rb +++ b/spec/finders/releases/group_releases_finder_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Releases::GroupReleasesFinder do +RSpec.describe Releases::GroupReleasesFinder, feature_category: :subgroups do let(:user) { create(:user) } let(:group) { create(:group) } let(:project) { create(:project, :repository, group: group) } diff --git a/spec/frontend/boards/board_card_inner_spec.js b/spec/frontend/boards/board_card_inner_spec.js index 0edc8359b6a..1e823e3321a 100644 --- a/spec/frontend/boards/board_card_inner_spec.js +++ b/spec/frontend/boards/board_card_inner_spec.js @@ -1,7 +1,9 @@ import { GlLabel, GlLoadingIcon, GlTooltip } from '@gitlab/ui'; import { range } from 'lodash'; import Vue, { nextTick } from 'vue'; +import VueApollo from 'vue-apollo'; import Vuex from 'vuex'; +import createMockApollo from 'helpers/mock_apollo_helper'; import setWindowLocation from 'helpers/set_window_location_helper'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; import { mountExtended } from 'helpers/vue_test_utils_helper'; @@ -18,6 +20,7 @@ jest.mock('~/lib/utils/url_utility'); jest.mock('~/boards/eventhub'); Vue.use(Vuex); +Vue.use(VueApollo); describe('Board card component', () => { const user = { @@ -69,6 +72,7 @@ describe('Board card component', () => { const createWrapper = ({ props = {}, isEpicBoard = false, isGroupBoard = true } = {}) => { wrapper = mountExtended(BoardCardInner, { store, + apolloProvider: createMockApollo(), propsData: { list, item: issue, @@ -82,13 +86,6 @@ describe('Board card component', () => { directives: { GlTooltip: createMockDirective(), }, - mocks: { - $apollo: { - queries: { - blockingIssuables: { loading: false }, - }, - }, - }, provide: { rootPath: '/', scopedLabelsAvailable: false, diff --git a/spec/frontend/diffs/components/commit_item_spec.js b/spec/frontend/diffs/components/commit_item_spec.js index 75d55376d09..08be3fa2745 100644 --- a/spec/frontend/diffs/components/commit_item_spec.js +++ b/spec/frontend/diffs/components/commit_item_spec.js @@ -9,8 +9,8 @@ import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_sta const TEST_AUTHOR_NAME = 'test'; const TEST_AUTHOR_EMAIL = 'test+test@gitlab.com'; const TEST_AUTHOR_GRAVATAR = `${TEST_HOST}/avatar/test?s=40`; -const TEST_SIGNATURE_HTML = `<a class="btn gpg-status-box valid" data-content="signature-content" data-html="true" data-placement="top" data-title="signature-title" data-toggle="popover" role="button" tabindex="0"> - Verified +const TEST_SIGNATURE_HTML = `<a class="btn signature-badge" data-content="signature-content" data-html="true" data-placement="top" data-title="signature-title" data-toggle="popover" role="button" tabindex="0"> + <span class="gl-badge badge badge-pill badge-success md">Verified</span> </a>`; const TEST_PIPELINE_STATUS_PATH = `${TEST_HOST}/pipeline/status`; @@ -156,7 +156,7 @@ describe('diffs/components/commit_item', () => { it('renders signature html', () => { const actionsElement = getCommitActionsElement(); - const signatureElement = actionsElement.find('.gpg-status-box'); + const signatureElement = actionsElement.find('.signature-badge'); expect(signatureElement.html()).toBe(TEST_SIGNATURE_HTML); }); diff --git a/spec/frontend/diffs/components/diff_row_utils_spec.js b/spec/frontend/diffs/components/diff_row_utils_spec.js index a6f508c73eb..6e9eb433924 100644 --- a/spec/frontend/diffs/components/diff_row_utils_spec.js +++ b/spec/frontend/diffs/components/diff_row_utils_spec.js @@ -21,262 +21,287 @@ function problemsClone({ }; } -describe('isHighlighted', () => { - it('should return true if line is highlighted', () => { - const line = { line_code: LINE_CODE }; - const isCommented = false; - expect(utils.isHighlighted(LINE_CODE, line, isCommented)).toBe(true); - }); - - it('should return false if line is not highlighted', () => { - const line = { line_code: LINE_CODE }; - const isCommented = false; - expect(utils.isHighlighted('xxx', line, isCommented)).toBe(false); - }); - - it('should return true if isCommented is true', () => { - const line = { line_code: LINE_CODE }; - const isCommented = true; - expect(utils.isHighlighted('xxx', line, isCommented)).toBe(true); - }); -}); - -describe('isContextLine', () => { - it('return true if line type is context', () => { - expect(utils.isContextLine(CONTEXT_LINE_TYPE)).toBe(true); - }); - - it('return false if line type is not context', () => { - expect(utils.isContextLine('xxx')).toBe(false); - }); -}); - -describe('isMatchLine', () => { - it('return true if line type is match', () => { - expect(utils.isMatchLine(MATCH_LINE_TYPE)).toBe(true); - }); - - it('return false if line type is not match', () => { - expect(utils.isMatchLine('xxx')).toBe(false); - }); -}); - -describe('isMetaLine', () => { - it.each` - type | expectation - ${OLD_NO_NEW_LINE_TYPE} | ${true} - ${NEW_NO_NEW_LINE_TYPE} | ${true} - ${EMPTY_CELL_TYPE} | ${true} - ${'xxx'} | ${false} - `('should return $expectation if type is $type', ({ type, expectation }) => { - expect(utils.isMetaLine(type)).toBe(expectation); - }); -}); - -describe('shouldRenderCommentButton', () => { - it('should return false if comment button is not rendered', () => { - expect(utils.shouldRenderCommentButton(true, false)).toBe(false); - }); - - it('should return false if not logged in', () => { - expect(utils.shouldRenderCommentButton(false, true)).toBe(false); - }); - - it('should return true logged in and rendered', () => { - expect(utils.shouldRenderCommentButton(true, true)).toBe(true); - }); -}); - -describe('hasDiscussions', () => { - it('should return false if line is undefined', () => { - expect(utils.hasDiscussions()).toBe(false); - }); - - it('should return false if discussions is undefined', () => { - expect(utils.hasDiscussions({})).toBe(false); - }); - - it('should return false if discussions has legnth of 0', () => { - expect(utils.hasDiscussions({ discussions: [] })).toBe(false); - }); +describe('diff_row_utils', () => { + describe('isHighlighted', () => { + it('should return true if line is highlighted', () => { + const line = { line_code: LINE_CODE }; + const isCommented = false; + expect(utils.isHighlighted(LINE_CODE, line, isCommented)).toBe(true); + }); + + it('should return false if line is not highlighted', () => { + const line = { line_code: LINE_CODE }; + const isCommented = false; + expect(utils.isHighlighted('xxx', line, isCommented)).toBe(false); + }); - it('should return true if discussions has legnth > 0', () => { - expect(utils.hasDiscussions({ discussions: [1] })).toBe(true); - }); -}); - -describe('lineHref', () => { - it(`should return #${LINE_CODE}`, () => { - expect(utils.lineHref({ line_code: LINE_CODE })).toEqual(`#${LINE_CODE}`); - }); - - it(`should return '#' if line is undefined`, () => { - expect(utils.lineHref()).toEqual('#'); - }); - - it(`should return '#' if line_code is undefined`, () => { - expect(utils.lineHref({})).toEqual('#'); - }); -}); - -describe('lineCode', () => { - it(`should return undefined if line_code is undefined`, () => { - expect(utils.lineCode()).toEqual(undefined); - expect(utils.lineCode({ left: {} })).toEqual(undefined); - expect(utils.lineCode({ right: {} })).toEqual(undefined); - }); - - it(`should return ${LINE_CODE}`, () => { - expect(utils.lineCode({ line_code: LINE_CODE })).toEqual(LINE_CODE); - expect(utils.lineCode({ left: { line_code: LINE_CODE } })).toEqual(LINE_CODE); - expect(utils.lineCode({ right: { line_code: LINE_CODE } })).toEqual(LINE_CODE); - }); -}); - -describe('classNameMapCell', () => { - it.each` - line | hll | isLoggedIn | isHover | expectation - ${undefined} | ${true} | ${true} | ${true} | ${[]} - ${{ type: 'new' }} | ${false} | ${false} | ${false} | ${['new', { hll: false, 'is-over': false, new_line: true, old_line: false }]} - ${{ type: 'new' }} | ${true} | ${true} | ${false} | ${['new', { hll: true, 'is-over': false, new_line: true, old_line: false }]} - ${{ type: 'new' }} | ${true} | ${false} | ${true} | ${['new', { hll: true, 'is-over': false, new_line: true, old_line: false }]} - ${{ type: 'new' }} | ${true} | ${true} | ${true} | ${['new', { hll: true, 'is-over': true, new_line: true, old_line: false }]} - `('should return $expectation', ({ line, hll, isLoggedIn, isHover, expectation }) => { - const classes = utils.classNameMapCell({ line, hll, isLoggedIn, isHover }); - expect(classes).toEqual(expectation); - }); -}); - -describe('addCommentTooltip', () => { - const brokenSymLinkTooltip = - 'Commenting on symbolic links that replace or are replaced by files is not supported'; - const brokenRealTooltip = - 'Commenting on files that replace or are replaced by symbolic links is not supported'; - const lineMovedOrRenamedFileTooltip = - 'Commenting on files that are only moved or renamed is not supported'; - const lineWithNoLineCodeTooltip = 'Commenting on this line is not supported'; - const dragTooltip = 'Add a comment to this line or drag for multiple lines'; - - it('should return default tooltip', () => { - expect(utils.addCommentTooltip()).toBeUndefined(); - }); - - it('should return drag comment tooltip when dragging is enabled', () => { - expect(utils.addCommentTooltip({ problems: problemsClone() })).toEqual(dragTooltip); - }); - - it('should return broken symlink tooltip', () => { - expect( - utils.addCommentTooltip({ - problems: problemsClone({ brokenSymlink: { wasSymbolic: true } }), - }), - ).toEqual(brokenSymLinkTooltip); - expect( - utils.addCommentTooltip({ problems: problemsClone({ brokenSymlink: { isSymbolic: true } }) }), - ).toEqual(brokenSymLinkTooltip); - }); - - it('should return broken real tooltip', () => { - expect( - utils.addCommentTooltip({ problems: problemsClone({ brokenSymlink: { wasReal: true } }) }), - ).toEqual(brokenRealTooltip); - expect( - utils.addCommentTooltip({ problems: problemsClone({ brokenSymlink: { isReal: true } }) }), - ).toEqual(brokenRealTooltip); - }); - - it('reports a tooltip when the line is in a file that has only been moved or renamed', () => { - expect(utils.addCommentTooltip({ problems: problemsClone({ fileOnlyMoved: true }) })).toEqual( - lineMovedOrRenamedFileTooltip, + it('should return true if isCommented is true', () => { + const line = { line_code: LINE_CODE }; + const isCommented = true; + expect(utils.isHighlighted('xxx', line, isCommented)).toBe(true); + }); + }); + + describe('isContextLine', () => { + it('return true if line type is context', () => { + expect(utils.isContextLine(CONTEXT_LINE_TYPE)).toBe(true); + }); + + it('return false if line type is not context', () => { + expect(utils.isContextLine('xxx')).toBe(false); + }); + }); + + describe('isMatchLine', () => { + it('return true if line type is match', () => { + expect(utils.isMatchLine(MATCH_LINE_TYPE)).toBe(true); + }); + + it('return false if line type is not match', () => { + expect(utils.isMatchLine('xxx')).toBe(false); + }); + }); + + describe('isMetaLine', () => { + it.each` + type | expectation + ${OLD_NO_NEW_LINE_TYPE} | ${true} + ${NEW_NO_NEW_LINE_TYPE} | ${true} + ${EMPTY_CELL_TYPE} | ${true} + ${'xxx'} | ${false} + `('should return $expectation if type is $type', ({ type, expectation }) => { + expect(utils.isMetaLine(type)).toBe(expectation); + }); + }); + + describe('shouldRenderCommentButton', () => { + it('should return false if comment button is not rendered', () => { + expect(utils.shouldRenderCommentButton(true, false)).toBe(false); + }); + + it('should return false if not logged in', () => { + expect(utils.shouldRenderCommentButton(false, true)).toBe(false); + }); + + it('should return true logged in and rendered', () => { + expect(utils.shouldRenderCommentButton(true, true)).toBe(true); + }); + }); + + describe('hasDiscussions', () => { + it('should return false if line is undefined', () => { + expect(utils.hasDiscussions()).toBe(false); + }); + + it('should return false if discussions is undefined', () => { + expect(utils.hasDiscussions({})).toBe(false); + }); + + it('should return false if discussions has legnth of 0', () => { + expect(utils.hasDiscussions({ discussions: [] })).toBe(false); + }); + + it('should return true if discussions has legnth > 0', () => { + expect(utils.hasDiscussions({ discussions: [1] })).toBe(true); + }); + }); + + describe('lineHref', () => { + it(`should return #${LINE_CODE}`, () => { + expect(utils.lineHref({ line_code: LINE_CODE })).toEqual(`#${LINE_CODE}`); + }); + + it(`should return '#' if line is undefined`, () => { + expect(utils.lineHref()).toEqual('#'); + }); + + it(`should return '#' if line_code is undefined`, () => { + expect(utils.lineHref({})).toEqual('#'); + }); + }); + + describe('lineCode', () => { + it(`should return undefined if line_code is undefined`, () => { + expect(utils.lineCode()).toEqual(undefined); + expect(utils.lineCode({ left: {} })).toEqual(undefined); + expect(utils.lineCode({ right: {} })).toEqual(undefined); + }); + + it(`should return ${LINE_CODE}`, () => { + expect(utils.lineCode({ line_code: LINE_CODE })).toEqual(LINE_CODE); + expect(utils.lineCode({ left: { line_code: LINE_CODE } })).toEqual(LINE_CODE); + expect(utils.lineCode({ right: { line_code: LINE_CODE } })).toEqual(LINE_CODE); + }); + }); + + describe('classNameMapCell', () => { + it.each` + line | highlighted | commented | selectionStart | selectionEnd | isLoggedIn | isHover | expectation + ${undefined} | ${true} | ${false} | ${false} | ${false} | ${true} | ${true} | ${[{ 'highlight-top': true, 'highlight-bottom': true, hll: true, commented: false }]} + ${undefined} | ${false} | ${true} | ${false} | ${false} | ${true} | ${true} | ${[{ 'highlight-top': false, 'highlight-bottom': false, hll: false, commented: true }]} + ${{ type: 'new' }} | ${false} | ${false} | ${false} | ${false} | ${false} | ${false} | ${[{ new: true, 'highlight-top': false, 'highlight-bottom': false, hll: false, commented: false, 'is-over': false, new_line: true, old_line: false }]} + ${{ type: 'new' }} | ${true} | ${false} | ${false} | ${false} | ${true} | ${false} | ${[{ new: true, 'highlight-top': true, 'highlight-bottom': true, hll: true, commented: false, 'is-over': false, new_line: true, old_line: false }]} + ${{ type: 'new' }} | ${true} | ${false} | ${false} | ${false} | ${false} | ${true} | ${[{ new: true, 'highlight-top': true, 'highlight-bottom': true, hll: true, commented: false, 'is-over': false, new_line: true, old_line: false }]} + ${{ type: 'new' }} | ${true} | ${false} | ${false} | ${false} | ${true} | ${true} | ${[{ new: true, 'highlight-top': true, 'highlight-bottom': true, hll: true, commented: false, 'is-over': true, new_line: true, old_line: false }]} + `( + 'should return $expectation', + ({ + line, + highlighted, + commented, + selectionStart, + selectionEnd, + isLoggedIn, + isHover, + expectation, + }) => { + const classes = utils.classNameMapCell({ + line, + highlighted, + commented, + selectionStart, + selectionEnd, + isLoggedIn, + isHover, + }); + expect(classes).toEqual(expectation); + }, ); }); - it("reports a tooltip when the line doesn't have a line code to leave a comment on", () => { - expect(utils.addCommentTooltip({ problems: problemsClone({ brokenLineCode: true }) })).toEqual( - lineWithNoLineCodeTooltip, + describe('addCommentTooltip', () => { + const brokenSymLinkTooltip = + 'Commenting on symbolic links that replace or are replaced by files is not supported'; + const brokenRealTooltip = + 'Commenting on files that replace or are replaced by symbolic links is not supported'; + const lineMovedOrRenamedFileTooltip = + 'Commenting on files that are only moved or renamed is not supported'; + const lineWithNoLineCodeTooltip = 'Commenting on this line is not supported'; + const dragTooltip = 'Add a comment to this line or drag for multiple lines'; + + it('should return default tooltip', () => { + expect(utils.addCommentTooltip()).toBeUndefined(); + }); + + it('should return drag comment tooltip when dragging is enabled', () => { + expect(utils.addCommentTooltip({ problems: problemsClone() })).toEqual(dragTooltip); + }); + + it('should return broken symlink tooltip', () => { + expect( + utils.addCommentTooltip({ + problems: problemsClone({ brokenSymlink: { wasSymbolic: true } }), + }), + ).toEqual(brokenSymLinkTooltip); + expect( + utils.addCommentTooltip({ + problems: problemsClone({ brokenSymlink: { isSymbolic: true } }), + }), + ).toEqual(brokenSymLinkTooltip); + }); + + it('should return broken real tooltip', () => { + expect( + utils.addCommentTooltip({ problems: problemsClone({ brokenSymlink: { wasReal: true } }) }), + ).toEqual(brokenRealTooltip); + expect( + utils.addCommentTooltip({ problems: problemsClone({ brokenSymlink: { isReal: true } }) }), + ).toEqual(brokenRealTooltip); + }); + + it('reports a tooltip when the line is in a file that has only been moved or renamed', () => { + expect(utils.addCommentTooltip({ problems: problemsClone({ fileOnlyMoved: true }) })).toEqual( + lineMovedOrRenamedFileTooltip, + ); + }); + + it("reports a tooltip when the line doesn't have a line code to leave a comment on", () => { + expect( + utils.addCommentTooltip({ problems: problemsClone({ brokenLineCode: true }) }), + ).toEqual(lineWithNoLineCodeTooltip); + }); + }); + + describe('parallelViewLeftLineType', () => { + it(`should return ${OLD_NO_NEW_LINE_TYPE}`, () => { + expect( + utils.parallelViewLeftLineType({ line: { right: { type: NEW_NO_NEW_LINE_TYPE } } }), + ).toEqual(OLD_NO_NEW_LINE_TYPE); + }); + + it(`should return 'new'`, () => { + expect(utils.parallelViewLeftLineType({ line: { left: { type: 'new' } } })[0]).toBe('new'); + }); + + it(`should return ${EMPTY_CELL_TYPE}`, () => { + expect(utils.parallelViewLeftLineType({})).toContain(EMPTY_CELL_TYPE); + }); + + it(`should return hll:true`, () => { + expect(utils.parallelViewLeftLineType({ highlighted: true })[1].hll).toBe(true); + }); + }); + + describe('shouldShowCommentButton', () => { + it.each` + hover | context | meta | discussions | expectation + ${true} | ${false} | ${false} | ${false} | ${true} + ${false} | ${false} | ${false} | ${false} | ${false} + ${true} | ${true} | ${false} | ${false} | ${false} + ${true} | ${true} | ${true} | ${false} | ${false} + ${true} | ${true} | ${true} | ${true} | ${false} + `( + 'should return $expectation when hover is $hover', + ({ hover, context, meta, discussions, expectation }) => { + expect(utils.shouldShowCommentButton(hover, context, meta, discussions)).toBe(expectation); + }, ); }); -}); - -describe('parallelViewLeftLineType', () => { - it(`should return ${OLD_NO_NEW_LINE_TYPE}`, () => { - expect(utils.parallelViewLeftLineType({ right: { type: NEW_NO_NEW_LINE_TYPE } })).toEqual( - OLD_NO_NEW_LINE_TYPE, - ); - }); - - it(`should return 'new'`, () => { - expect(utils.parallelViewLeftLineType({ left: { type: 'new' } })).toContain('new'); - }); - - it(`should return ${EMPTY_CELL_TYPE}`, () => { - expect(utils.parallelViewLeftLineType({})).toContain(EMPTY_CELL_TYPE); - }); - - it(`should return hll:true`, () => { - expect(utils.parallelViewLeftLineType({}, true)[1]).toEqual({ hll: true }); - }); -}); - -describe('shouldShowCommentButton', () => { - it.each` - hover | context | meta | discussions | expectation - ${true} | ${false} | ${false} | ${false} | ${true} - ${false} | ${false} | ${false} | ${false} | ${false} - ${true} | ${true} | ${false} | ${false} | ${false} - ${true} | ${true} | ${true} | ${false} | ${false} - ${true} | ${true} | ${true} | ${true} | ${false} - `( - 'should return $expectation when hover is $hover', - ({ hover, context, meta, discussions, expectation }) => { - expect(utils.shouldShowCommentButton(hover, context, meta, discussions)).toBe(expectation); - }, - ); -}); -describe('mapParallel', () => { - it('should assign computed properties to the line object', () => { - const side = { - discussions: [{}], - discussionsExpanded: true, - hasForm: true, - problems: problemsClone(), - }; - const content = { - diffFile: {}, - hasParallelDraftLeft: () => false, - hasParallelDraftRight: () => false, - draftsForLine: () => [], - }; - const line = { left: side, right: side }; - const expectation = { - commentRowClasses: '', - draftRowClasses: 'js-temp-notes-holder', - hasDiscussionsLeft: true, - hasDiscussionsRight: true, - isContextLineLeft: false, - isContextLineRight: false, - isMatchLineLeft: false, - isMatchLineRight: false, - isMetaLineLeft: false, - isMetaLineRight: false, - }; - const leftExpectation = { - renderDiscussion: true, - hasDraft: false, - lineDrafts: [], - hasCommentForm: true, - }; - const rightExpectation = { - renderDiscussion: false, - hasDraft: false, - lineDrafts: [], - hasCommentForm: false, - }; - const mapped = utils.mapParallel(content)(line); - - expect(mapped).toMatchObject(expectation); - expect(mapped.left).toMatchObject(leftExpectation); - expect(mapped.right).toMatchObject(rightExpectation); + describe('mapParallel', () => { + it('should assign computed properties to the line object', () => { + const side = { + discussions: [{}], + discussionsExpanded: true, + hasForm: true, + problems: problemsClone(), + }; + const content = { + diffFile: {}, + hasParallelDraftLeft: () => false, + hasParallelDraftRight: () => false, + draftsForLine: () => [], + }; + const line = { left: side, right: side }; + const expectation = { + commentRowClasses: '', + draftRowClasses: 'js-temp-notes-holder', + hasDiscussionsLeft: true, + hasDiscussionsRight: true, + isContextLineLeft: false, + isContextLineRight: false, + isMatchLineLeft: false, + isMatchLineRight: false, + isMetaLineLeft: false, + isMetaLineRight: false, + }; + const leftExpectation = { + renderDiscussion: true, + hasDraft: false, + lineDrafts: [], + hasCommentForm: true, + }; + const rightExpectation = { + renderDiscussion: false, + hasDraft: false, + lineDrafts: [], + hasCommentForm: false, + }; + const mapped = utils.mapParallel(content)(line); + + expect(mapped).toMatchObject(expectation); + expect(mapped.left).toMatchObject(leftExpectation); + expect(mapped.right).toMatchObject(rightExpectation); + }); }); }); diff --git a/spec/frontend/gpg_badges_spec.js b/spec/frontend/gpg_badges_spec.js index 4c2242bae4b..2d961e6872e 100644 --- a/spec/frontend/gpg_badges_spec.js +++ b/spec/frontend/gpg_badges_spec.js @@ -28,7 +28,7 @@ describe('GpgBadges', () => { <input type="search" name="search" value="${search}" id="commits-search"class="form-control search-text-input input-short"> </form> <div class="parent-container"> - <div class="js-loading-gpg-badge" data-commit-sha="${dummyCommitSha}"></div> + <div class="js-loading-signature-badge" data-commit-sha="${dummyCommitSha}"></div> </div> `); }; @@ -105,8 +105,8 @@ describe('GpgBadges', () => { mock.onGet(dummyUrl).replyOnce(HTTP_STATUS_OK); await GpgBadges.fetch(); - expect(document.querySelector('.js-loading-gpg-badge:empty')).toBe(null); - const spinners = document.querySelectorAll('.js-loading-gpg-badge span.gl-spinner'); + expect(document.querySelector('.js-loading-signature-badge:empty')).toBe(null); + const spinners = document.querySelectorAll('.js-loading-signature-badge span.gl-spinner'); expect(spinners.length).toBe(1); }); @@ -115,7 +115,7 @@ describe('GpgBadges', () => { mock.onGet(dummyUrl).replyOnce(HTTP_STATUS_OK, dummyResponse); await GpgBadges.fetch(); - expect(document.querySelector('.js-loading-gpg-badge')).toBe(null); + expect(document.querySelector('.js-loading-signature-badge')).toBe(null); const parentContainer = document.querySelector('.parent-container'); expect(parentContainer.innerHTML.trim()).toEqual(dummyBadgeHtml); diff --git a/spec/frontend/repository/components/last_commit_spec.js b/spec/frontend/repository/components/last_commit_spec.js index 964b135bee3..7226e7baa36 100644 --- a/spec/frontend/repository/components/last_commit_spec.js +++ b/spec/frontend/repository/components/last_commit_spec.js @@ -20,7 +20,7 @@ const findUserAvatarLink = () => wrapper.findComponent(UserAvatarLink); const findLastCommitLabel = () => wrapper.findByTestId('last-commit-id-label'); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); const findCommitRowDescription = () => wrapper.find('.commit-row-description'); -const findStatusBox = () => wrapper.find('.gpg-status-box'); +const findStatusBox = () => wrapper.find('.signature-badge'); const findItemTitle = () => wrapper.find('.item-title'); const defaultPipelineEdges = [ @@ -206,7 +206,7 @@ describe('Repository last commit component', () => { it('renders the signature HTML as returned by the backend', async () => { createComponent({ signatureHtml: `<a - class="btn gpg-status-box valid" + class="btn signature-badge" data-content="signature-content" data-html="true" data-placement="top" @@ -214,12 +214,12 @@ describe('Repository last commit component', () => { data-toggle="popover" role="button" tabindex="0" - >Verified</a>`, + ><span class="gl-badge badge badge-pill badge-success md">Verified</span></a>`, }); await waitForPromises(); expect(findStatusBox().html()).toBe( - `<a class="btn gpg-status-box valid" data-content="signature-content" data-html="true" data-placement="top" data-title="signature-title" data-toggle="popover" role="button" tabindex="0">Verified</a>`, + `<a class="btn signature-badge" data-content="signature-content" data-html="true" data-placement="top" data-title="signature-title" data-toggle="popover" role="button" tabindex="0"><span class="gl-badge badge badge-pill badge-success md">Verified</span></a>`, ); }); diff --git a/spec/frontend/repository/components/preview/index_spec.js b/spec/frontend/repository/components/preview/index_spec.js index e4eba65795e..d4c746b67d6 100644 --- a/spec/frontend/repository/components/preview/index_spec.js +++ b/spec/frontend/repository/components/preview/index_spec.js @@ -9,9 +9,14 @@ jest.mock('~/lib/utils/common_utils'); let vm; let $apollo; -function factory(blob) { +function factory(blob, loading) { $apollo = { - query: jest.fn().mockReturnValue(Promise.resolve({})), + queries: { + readme: { + query: jest.fn().mockReturnValue(Promise.resolve({})), + loading, + }, + }, }; vm = shallowMount(Preview, { @@ -58,14 +63,13 @@ describe('Repository file preview component', () => { }); it('renders loading icon', async () => { - factory({ - webPath: 'http://test.com', - name: 'README.md', - }); - - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - vm.setData({ loading: 1 }); + factory( + { + webPath: 'http://test.com', + name: 'README.md', + }, + true, + ); await nextTick(); expect(vm.findComponent(GlLoadingIcon).exists()).toBe(true); diff --git a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commits_header_spec.js b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commits_header_spec.js index 774e2bafed3..a6d3a6286a7 100644 --- a/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commits_header_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/states/mr_widget_commits_header_spec.js @@ -58,13 +58,8 @@ describe('Commits header component', () => { expect(findCommitToggle().attributes('aria-label')).toBe('Expand'); }); - it('has a chevron-right icon', async () => { + it('has a chevron-right icon', () => { createComponent(); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ expanded: false }); - - await nextTick(); expect(findCommitToggle().props('icon')).toBe('chevron-right'); }); @@ -110,25 +105,21 @@ describe('Commits header component', () => { }); describe('when expanded', () => { - beforeEach(() => { + beforeEach(async () => { createComponent(); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ expanded: true }); + findCommitToggle().trigger('click'); + await nextTick(); }); - it('toggle has aria-label equal to collapse', async () => { - await nextTick(); + it('toggle has aria-label equal to collapse', () => { expect(findCommitToggle().attributes('aria-label')).toBe('Collapse'); }); - it('has a chevron-down icon', async () => { - await nextTick(); + it('has a chevron-down icon', () => { expect(findCommitToggle().props('icon')).toBe('chevron-down'); }); - it('has a collapse text', async () => { - await nextTick(); + it('has a collapse text', () => { expect(findHeaderWrapper().text()).toBe('Collapse'); }); }); diff --git a/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js b/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js index c0cd5503cfc..973866176c2 100644 --- a/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js @@ -402,7 +402,7 @@ describe('~/vue_merge_request_widget/components/widget/widget.vue', () => { isCollapsible: true, actionButtons: [ { - fullReport: true, + trackFullReportClicked: true, href: '#', target: '_blank', id: 'full-report-button', diff --git a/spec/frontend/vue_merge_request_widget/test_extensions.js b/spec/frontend/vue_merge_request_widget/test_extensions.js index ff2dc38442f..e9e5d931323 100644 --- a/spec/frontend/vue_merge_request_widget/test_extensions.js +++ b/spec/frontend/vue_merge_request_widget/test_extensions.js @@ -153,7 +153,7 @@ export const fullReportExtension = { text: 'test', href: `testref`, target: '_blank', - fullReport: true, + trackFullReportClicked: true, }, ]; }, diff --git a/spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js b/spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js index c34041f9305..119d6448507 100644 --- a/spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js +++ b/spec/frontend/vue_shared/components/dropdown_keyboard_navigation_spec.js @@ -61,27 +61,8 @@ describe('DropdownKeyboardNavigation', () => { }); describe('keydown events', () => { - let incrementSpy; - beforeEach(() => { createComponent(); - incrementSpy = jest.spyOn(wrapper.vm, 'increment'); - }); - - afterEach(() => { - incrementSpy.mockRestore(); - }); - - it('onKeydown-Down calls increment(1)', () => { - helpers.arrowDown(); - - expect(incrementSpy).toHaveBeenCalledWith(1); - }); - - it('onKeydown-Up calls increment(-1)', () => { - helpers.arrowUp(); - - expect(incrementSpy).toHaveBeenCalledWith(-1); }); it('onKeydown-Tab $emits @tab event', () => { diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb index ea8018d4413..7f26190830e 100644 --- a/spec/graphql/types/project_type_spec.rb +++ b/spec/graphql/types/project_type_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['Project'] do include GraphqlHelpers + include ProjectForksHelper specify { expect(described_class).to expose_permissions_using(Types::PermissionTypes::Project) } @@ -37,7 +38,7 @@ RSpec.describe GitlabSchema.types['Project'] do ci_template timelogs merge_commit_template squash_commit_template work_item_types recent_issue_boards ci_config_path_or_default packages_cleanup_policy ci_variables timelog_categories fork_targets branch_rules ci_config_variables pipeline_schedules languages - incident_management_timeline_event_tags + incident_management_timeline_event_tags visible_forks ] expect(described_class).to include_graphql_fields(*expected_fields) @@ -859,4 +860,54 @@ RSpec.describe GitlabSchema.types['Project'] do end end end + + describe 'visible_forks' do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :public) } + let_it_be(:fork_reporter) { fork_project(project, nil, { repository: true }) } + let_it_be(:fork_developer) { fork_project(project, nil, { repository: true }) } + let_it_be(:fork_group_developer) { fork_project(project, nil, { repository: true }) } + let_it_be(:fork_public) { fork_project(project, nil, { repository: true }) } + let_it_be(:fork_private) { fork_project(project, nil, { repository: true }) } + + let(:minimum_access_level) { '' } + let(:query) do + %( + query { + project(fullPath: "#{project.full_path}") { + visibleForks#{minimum_access_level} { + nodes { + fullPath + } + } + } + } + ) + end + + let(:forks) do + subject.dig('data', 'project', 'visibleForks', 'nodes') + end + + subject { GitlabSchema.execute(query, context: { current_user: user }).as_json } + + before do + fork_reporter.add_reporter(user) + fork_developer.add_developer(user) + fork_group_developer.group.add_developer(user) + end + + it 'contains all forks' do + expect(forks.count).to eq(5) + end + + context 'with minimum_access_level DEVELOPER' do + let(:minimum_access_level) { '(minimumAccessLevel: DEVELOPER)' } + + it 'contains forks with developer access' do + expect(forks).to contain_exactly(a_hash_including('fullPath' => fork_developer.full_path), +a_hash_including('fullPath' => fork_group_developer.full_path)) + end + end + end end diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb index fb23b5c1dc8..6b43e97a0b4 100644 --- a/spec/helpers/merge_requests_helper_spec.rb +++ b/spec/helpers/merge_requests_helper_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe MergeRequestsHelper do +RSpec.describe MergeRequestsHelper, feature_category: :code_review_workflow do include ProjectForksHelper describe '#format_mr_branch_names' do diff --git a/spec/initializers/load_balancing_spec.rb b/spec/initializers/load_balancing_spec.rb index d9162acd2cd..66aaa52eef2 100644 --- a/spec/initializers/load_balancing_spec.rb +++ b/spec/initializers/load_balancing_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'load_balancing', :delete, :reestablished_active_record_base do +RSpec.describe 'load_balancing', :delete, :reestablished_active_record_base, feature_category: :pods do subject(:initialize_load_balancer) do load Rails.root.join('config/initializers/load_balancing.rb') end diff --git a/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb index 2dea0aef4cf..ec0bda3c300 100644 --- a/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb +++ b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cache do +RSpec.describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cache, feature_category: :continuous_integration do let_it_be(:project) { create(:project, :repository) } let(:pipeline_status) { described_class.new(project) } diff --git a/spec/lib/gitlab/ci/trace/archive_spec.rb b/spec/lib/gitlab/ci/trace/archive_spec.rb index 582c4ad343f..cce6477b91e 100644 --- a/spec/lib/gitlab/ci/trace/archive_spec.rb +++ b/spec/lib/gitlab/ci/trace/archive_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Ci::Trace::Archive do +RSpec.describe Gitlab::Ci::Trace::Archive, feature_category: :scalability do context 'with transactional fixtures' do let_it_be_with_reload(:job) { create(:ci_build, :success, :trace_live) } let_it_be_with_reload(:trace_metadata) { create(:ci_build_trace_metadata, build: job) } diff --git a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb index 92ffeee8509..f85fb1540d9 100644 --- a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::CycleAnalytics::StageSummary do +RSpec.describe Gitlab::CycleAnalytics::StageSummary, feature_category: :devops_reports do include CycleAnalyticsHelpers let_it_be(:project) { create(:project, :repository) } diff --git a/spec/lib/gitlab/database/load_balancing_spec.rb b/spec/lib/gitlab/database/load_balancing_spec.rb index 1c85abac91c..59e16e6ca8b 100644 --- a/spec/lib/gitlab/database/load_balancing_spec.rb +++ b/spec/lib/gitlab/database/load_balancing_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::LoadBalancing, :suppress_gitlab_schemas_validate_connection do +RSpec.describe Gitlab::Database::LoadBalancing, :suppress_gitlab_schemas_validate_connection, feature_category: :pods do describe '.base_models' do it 'returns the models to apply load balancing to' do models = described_class.base_models diff --git a/spec/lib/gitlab/database/migrations/timeout_helpers_spec.rb b/spec/lib/gitlab/database/migrations/timeout_helpers_spec.rb index d35211af680..ee63ea7174b 100644 --- a/spec/lib/gitlab/database/migrations/timeout_helpers_spec.rb +++ b/spec/lib/gitlab/database/migrations/timeout_helpers_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::Migrations::TimeoutHelpers do +RSpec.describe Gitlab::Database::Migrations::TimeoutHelpers, feature_category: :database do let(:model) do ActiveRecord::Migration.new.extend(described_class) end diff --git a/spec/lib/gitlab/database/reflection_spec.rb b/spec/lib/gitlab/database/reflection_spec.rb index 389e93364c8..779bdbe50f0 100644 --- a/spec/lib/gitlab/database/reflection_spec.rb +++ b/spec/lib/gitlab/database/reflection_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::Reflection do +RSpec.describe Gitlab::Database::Reflection, feature_category: :database do let(:database) { described_class.new(ApplicationRecord) } describe '#username' do diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb index 1edcd890370..2cb84e2f02a 100644 --- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb +++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :delete do +RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :delete, feature_category: :subgroups do let(:migration) { FakeRenameReservedPathMigrationV1.new } let(:subject) { described_class.new(['the-path'], migration) } diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb index c507bce634e..5b5661020b0 100644 --- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb +++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces, :delete do +RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces, :delete, +feature_category: :subgroups do let(:migration) { FakeRenameReservedPathMigrationV1.new } let(:subject) { described_class.new(['the-path'], migration) } let(:namespace) { create(:group, name: 'the-path') } diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb index aa2a3329477..787c9e87038 100644 --- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb +++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb @@ -2,7 +2,8 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameProjects, :delete do +RSpec.describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameProjects, :delete, +feature_category: :projects do let(:migration) { FakeRenameReservedPathMigrationV1.new } let(:subject) { described_class.new(['the-path'], migration) } let(:project) do diff --git a/spec/lib/gitlab/database/transaction/observer_spec.rb b/spec/lib/gitlab/database/transaction/observer_spec.rb index 074c18d406e..d1cb014a594 100644 --- a/spec/lib/gitlab/database/transaction/observer_spec.rb +++ b/spec/lib/gitlab/database/transaction/observer_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::Transaction::Observer do +RSpec.describe Gitlab::Database::Transaction::Observer, feature_category: :database do # Use the delete DB strategy so that the test won't be wrapped in a transaction describe '.instrument_transactions', :delete do let(:transaction_context) { ActiveRecord::Base.connection.transaction_manager.transaction_context } diff --git a/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb b/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb index 836332524a9..9ccae754a92 100644 --- a/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb +++ b/spec/lib/gitlab/database/with_lock_retries_outside_transaction_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction do +RSpec.describe Gitlab::Database::WithLockRetriesOutsideTransaction, feature_category: :database do let(:env) { {} } let(:logger) { Gitlab::Database::WithLockRetries::NULL_LOGGER } let(:subject) { described_class.new(connection: connection, env: env, logger: logger, timing_configuration: timing_configuration) } diff --git a/spec/lib/gitlab/database/with_lock_retries_spec.rb b/spec/lib/gitlab/database/with_lock_retries_spec.rb index 797a01c482d..7fe6362634b 100644 --- a/spec/lib/gitlab/database/with_lock_retries_spec.rb +++ b/spec/lib/gitlab/database/with_lock_retries_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Database::WithLockRetries do +RSpec.describe Gitlab::Database::WithLockRetries, feature_category: :database do let(:env) { {} } let(:logger) { Gitlab::Database::WithLockRetries::NULL_LOGGER } let(:subject) { described_class.new(connection: connection, env: env, logger: logger, allow_savepoints: allow_savepoints, timing_configuration: timing_configuration) } diff --git a/spec/lib/gitlab/metrics/subscribers/load_balancing_spec.rb b/spec/lib/gitlab/metrics/subscribers/load_balancing_spec.rb index 7f7efaffd9e..b401b7cc996 100644 --- a/spec/lib/gitlab/metrics/subscribers/load_balancing_spec.rb +++ b/spec/lib/gitlab/metrics/subscribers/load_balancing_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::Metrics::Subscribers::LoadBalancing, :request_store do +RSpec.describe Gitlab::Metrics::Subscribers::LoadBalancing, :request_store, feature_category: :pods do let(:subscriber) { described_class.new } describe '#caught_up_replica_pick' do diff --git a/spec/migrations/20221122132812_schedule_prune_stale_project_export_jobs_spec.rb b/spec/migrations/20221122132812_schedule_prune_stale_project_export_jobs_spec.rb index 5a5bc42a37b..9eaab56de7c 100644 --- a/spec/migrations/20221122132812_schedule_prune_stale_project_export_jobs_spec.rb +++ b/spec/migrations/20221122132812_schedule_prune_stale_project_export_jobs_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require_migration! -RSpec.describe SchedulePruneStaleProjectExportJobs, category: :importers do +RSpec.describe SchedulePruneStaleProjectExportJobs, feature_category: :importers do let!(:batched_migration) { described_class::MIGRATION } it 'schedules a new batched migration' do diff --git a/spec/migrations/20221205151917_schedule_backfill_environment_tier_spec.rb b/spec/migrations/20221205151917_schedule_backfill_environment_tier_spec.rb index b76f889d743..e03fd9c9daf 100644 --- a/spec/migrations/20221205151917_schedule_backfill_environment_tier_spec.rb +++ b/spec/migrations/20221205151917_schedule_backfill_environment_tier_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require_migration! -RSpec.describe ScheduleBackfillEnvironmentTier, category: :continuous_delivery do +RSpec.describe ScheduleBackfillEnvironmentTier, feature_category: :continuous_delivery do let!(:batched_migration) { described_class::MIGRATION } it 'schedules a new batched migration' do diff --git a/spec/migrations/20230214122717_fix_partition_ids_for_ci_job_variables_spec.rb b/spec/migrations/20230214122717_fix_partition_ids_for_ci_job_variables_spec.rb new file mode 100644 index 00000000000..64275855262 --- /dev/null +++ b/spec/migrations/20230214122717_fix_partition_ids_for_ci_job_variables_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe FixPartitionIdsForCiJobVariables, migration: :gitlab_ci, feature_category: :continuous_integration do + let(:builds) { table(:ci_builds, database: :ci) } + let(:job_variables) { table(:ci_job_variables, database: :ci) } + let(:connection) { job_variables.connection } + + around do |example| + connection.execute "ALTER TABLE #{job_variables.quoted_table_name} DISABLE TRIGGER ALL;" + + example.run + ensure + connection.execute "ALTER TABLE #{job_variables.quoted_table_name} ENABLE TRIGGER ALL;" + end + + before do + job = builds.create!(partition_id: 100) + + job_variables.insert_all!([ + { job_id: job.id, partition_id: 100, key: 'variable-100' }, + { job_id: job.id, partition_id: 101, key: 'variable-101' } + ]) + end + + describe '#up', :aggregate_failures do + context 'when on sass' do + before do + allow(Gitlab).to receive(:com?).and_return(true) + end + + it 'fixes partition_id' do + expect { migrate! }.not_to raise_error + + expect(job_variables.where(partition_id: 100).count).to eq(2) + expect(job_variables.where(partition_id: 101).count).to eq(0) + end + end + + context 'when on self managed' do + it 'does not change partition_id' do + expect { migrate! }.not_to raise_error + + expect(job_variables.where(partition_id: 100).count).to eq(1) + expect(job_variables.where(partition_id: 101).count).to eq(1) + end + end + end +end diff --git a/spec/models/concerns/pg_full_text_searchable_spec.rb b/spec/models/concerns/pg_full_text_searchable_spec.rb index 87f1dc5a27b..059df64f7d0 100644 --- a/spec/models/concerns/pg_full_text_searchable_spec.rb +++ b/spec/models/concerns/pg_full_text_searchable_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe PgFullTextSearchable do +RSpec.describe PgFullTextSearchable, feature_category: :global_search do let(:project) { build(:project, project_namespace: build(:project_namespace)) } let(:model_class) do diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb index 33d3cabb325..da7b54644bd 100644 --- a/spec/models/container_repository_spec.rb +++ b/spec/models/container_repository_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe ContainerRepository, :aggregate_failures do +RSpec.describe ContainerRepository, :aggregate_failures, feature_category: :container_registry do using RSpec::Parameterized::TableSyntax let(:group) { create(:group, name: 'group') } diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index e1a08a74ac0..6a52f12553f 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Member do +RSpec.describe Member, feature_category: :subgroups do include ExclusiveLeaseHelpers using RSpec::Parameterized::TableSyntax diff --git a/spec/models/merge_request/cleanup_schedule_spec.rb b/spec/models/merge_request/cleanup_schedule_spec.rb index 1f1f33db5ed..114413e8880 100644 --- a/spec/models/merge_request/cleanup_schedule_spec.rb +++ b/spec/models/merge_request/cleanup_schedule_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe MergeRequest::CleanupSchedule do +RSpec.describe MergeRequest::CleanupSchedule, feature_category: :code_review_workflow do describe 'associations' do it { is_expected.to belong_to(:merge_request) } end diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb index 2791203f395..7c3710aeeb2 100644 --- a/spec/services/groups/destroy_service_spec.rb +++ b/spec/services/groups/destroy_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Groups::DestroyService do +RSpec.describe Groups::DestroyService, feature_category: :subgroups do let!(:user) { create(:user) } let!(:group) { create(:group) } let!(:nested_group) { create(:group, parent: group) } diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb index 11f4d6a9ed4..12924df3200 100644 --- a/spec/services/issues/move_service_spec.rb +++ b/spec/services/issues/move_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Issues::MoveService do +RSpec.describe Issues::MoveService, feature_category: :team_planning do include DesignManagementTestHelpers let_it_be(:user) { create(:user) } diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb index b3c4ed4c544..2c0817550c6 100644 --- a/spec/services/merge_requests/close_service_spec.rb +++ b/spec/services/merge_requests/close_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe MergeRequests::CloseService do +RSpec.describe MergeRequests::CloseService, feature_category: :code_review_workflow do let(:user) { create(:user) } let(:user2) { create(:user) } let(:guest) { create(:user) } diff --git a/spec/services/merge_requests/create_from_issue_service_spec.rb b/spec/services/merge_requests/create_from_issue_service_spec.rb index 0eefbed252b..7bb0dd723a1 100644 --- a/spec/services/merge_requests/create_from_issue_service_spec.rb +++ b/spec/services/merge_requests/create_from_issue_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe MergeRequests::CreateFromIssueService do +RSpec.describe MergeRequests::CreateFromIssueService, feature_category: :code_review_workflow do include ProjectForksHelper let(:project) { create(:project, :repository) } diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index 24b15d2b18f..394fc269ac3 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do +RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state, feature_category: :code_review_workflow do include ProjectForksHelper let(:project) { create(:project, :repository) } diff --git a/spec/services/merge_requests/link_lfs_objects_service_spec.rb b/spec/services/merge_requests/link_lfs_objects_service_spec.rb index 96cb72baac2..9762b600eab 100644 --- a/spec/services/merge_requests/link_lfs_objects_service_spec.rb +++ b/spec/services/merge_requests/link_lfs_objects_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe MergeRequests::LinkLfsObjectsService, :sidekiq_inline do +RSpec.describe MergeRequests::LinkLfsObjectsService, :sidekiq_inline, feature_category: :code_review_workflow do include ProjectForksHelper include RepoHelpers diff --git a/spec/services/merge_requests/pushed_branches_service_spec.rb b/spec/services/merge_requests/pushed_branches_service_spec.rb index 59424263ec5..cb5d0a6bd25 100644 --- a/spec/services/merge_requests/pushed_branches_service_spec.rb +++ b/spec/services/merge_requests/pushed_branches_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe MergeRequests::PushedBranchesService do +RSpec.describe MergeRequests::PushedBranchesService, feature_category: :source_code_management do let(:project) { create(:project) } let!(:service) { described_class.new(project: project, current_user: nil, params: { changes: pushed_branches }) } diff --git a/spec/services/merge_requests/rebase_service_spec.rb b/spec/services/merge_requests/rebase_service_spec.rb index 316f20d8276..704dc1f9000 100644 --- a/spec/services/merge_requests/rebase_service_spec.rb +++ b/spec/services/merge_requests/rebase_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe MergeRequests::RebaseService do +RSpec.describe MergeRequests::RebaseService, feature_category: :source_code_management do include ProjectForksHelper let(:user) { create(:user) } diff --git a/spec/services/merge_requests/retarget_chain_service_spec.rb b/spec/services/merge_requests/retarget_chain_service_spec.rb index 187dd0cf589..ef8cd0a861e 100644 --- a/spec/services/merge_requests/retarget_chain_service_spec.rb +++ b/spec/services/merge_requests/retarget_chain_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe MergeRequests::RetargetChainService do +RSpec.describe MergeRequests::RetargetChainService, feature_category: :code_review_workflow do include ProjectForksHelper let_it_be(:user) { create(:user) } diff --git a/spec/services/pages/migrate_from_legacy_storage_service_spec.rb b/spec/services/pages/migrate_from_legacy_storage_service_spec.rb index d058324f3bb..4348ce4a271 100644 --- a/spec/services/pages/migrate_from_legacy_storage_service_spec.rb +++ b/spec/services/pages/migrate_from_legacy_storage_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Pages::MigrateFromLegacyStorageService do +RSpec.describe Pages::MigrateFromLegacyStorageService, feature_category: :pages do let(:batch_size) { 10 } let(:mark_projects_as_not_deployed) { false } let(:service) { described_class.new(Rails.logger, ignore_invalid_entries: false, mark_projects_as_not_deployed: mark_projects_as_not_deployed) } diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb index 05f699ed357..0689a65c2f4 100644 --- a/spec/services/projects/destroy_service_spec.rb +++ b/spec/services/projects/destroy_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publisher do +RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publisher, feature_category: :projects do include ProjectForksHelper include BatchDestroyDependentAssociationsHelper diff --git a/spec/support/models/ci/partitioning_testing/schema_helpers.rb b/spec/support/models/ci/partitioning_testing/schema_helpers.rb index 3a79ed1b5a9..4107bbcb976 100644 --- a/spec/support/models/ci/partitioning_testing/schema_helpers.rb +++ b/spec/support/models/ci/partitioning_testing/schema_helpers.rb @@ -24,13 +24,13 @@ module Ci each_partitionable_table do |table_name| change_column_default(table_name, from: DEFAULT_PARTITION, to: nil, connection: connection) change_column_default("p_#{table_name}", from: DEFAULT_PARTITION, to: nil, connection: connection) - create_test_partition(table_name, connection: connection) + create_test_partition("p_#{table_name}", connection: connection) end end def teardown(connection: Ci::ApplicationRecord.connection) each_partitionable_table do |table_name| - drop_test_partition(table_name, connection: connection) + drop_test_partition("p_#{table_name}", connection: connection) change_column_default(table_name, from: nil, to: DEFAULT_PARTITION, connection: connection) change_column_default("p_#{table_name}", from: nil, to: DEFAULT_PARTITION, connection: connection) end @@ -54,13 +54,13 @@ module Ci end def create_test_partition(table_name, connection:) - return unless table_available?("p_#{table_name}", connection: connection) + return unless table_available?(table_name, connection: connection) drop_test_partition(table_name, connection: connection) - connection.execute(<<~SQL) + connection.execute(<<~SQL.squish) CREATE TABLE #{full_partition_name(table_name)} - PARTITION OF p_#{table_name} + PARTITION OF #{table_name} FOR VALUES IN (#{PartitioningTesting::PartitionIdentifiers.ci_testing_partition_id}); SQL end @@ -68,7 +68,7 @@ module Ci def drop_test_partition(table_name, connection:) return unless table_available?(table_name, connection: connection) - connection.execute(<<~SQL) + connection.execute(<<~SQL.squish) DROP TABLE IF EXISTS #{full_partition_name(table_name)}; SQL end @@ -79,7 +79,12 @@ module Ci end def full_partition_name(table_name) - "#{Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA}._test_gitlab_#{table_name}_partition" + [ + Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA, + '._test_gitlab_', + table_name.delete_prefix('p_'), + '_partition' + ].join('') end end end diff --git a/spec/views/projects/commit/show.html.haml_spec.rb b/spec/views/projects/commit/show.html.haml_spec.rb index 5fe89102be3..eba54628215 100644 --- a/spec/views/projects/commit/show.html.haml_spec.rb +++ b/spec/views/projects/commit/show.html.haml_spec.rb @@ -79,7 +79,7 @@ RSpec.describe 'projects/commit/show.html.haml', feature_category: :source_code_ context 'when commit is signed' do let(:page) { Nokogiri::HTML.parse(rendered) } - let(:badge) { page.at('.gpg-status-box') } + let(:badge) { page.at('.signature-badge') } let(:badge_attributes) { badge.attributes } let(:title) { badge_attributes['data-title'].value } let(:content) { badge_attributes['data-content'].value } diff --git a/spec/views/projects/commits/_commit.html.haml_spec.rb b/spec/views/projects/commits/_commit.html.haml_spec.rb index 4e8a680b6de..90df0d381ed 100644 --- a/spec/views/projects/commits/_commit.html.haml_spec.rb +++ b/spec/views/projects/commits/_commit.html.haml_spec.rb @@ -39,7 +39,7 @@ RSpec.describe 'projects/commits/_commit.html.haml' do commit: commit } - within '.gpg-status-box' do + within '.signature-badge' do expect(page).not_to have_css('.gl-spinner') end end diff --git a/spec/views/projects/merge_requests/_commits.html.haml_spec.rb b/spec/views/projects/merge_requests/_commits.html.haml_spec.rb index 90ee6638142..4ce6755b89d 100644 --- a/spec/views/projects/merge_requests/_commits.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/_commits.html.haml_spec.rb @@ -37,6 +37,6 @@ RSpec.describe 'projects/merge_requests/_commits.html.haml', :sidekiq_might_not_ it 'shows signature verification badge' do render - expect(rendered).to have_css('.gpg-status-box') + expect(rendered).to have_css('.js-loading-signature-badge') end end diff --git a/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb b/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb index feb82e6a2b2..38f4daf7feb 100644 --- a/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb +++ b/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'projects/merge_requests/creations/_new_submit.html.haml' do +RSpec.describe 'projects/merge_requests/creations/_new_submit.html.haml', feature_category: :code_review_workflow do let(:merge_request) { create(:merge_request) } let!(:pipeline) { create(:ci_empty_pipeline) } diff --git a/spec/workers/ci/external_pull_requests/create_pipeline_worker_spec.rb b/spec/workers/ci/external_pull_requests/create_pipeline_worker_spec.rb index a637ac088ff..1f20729a821 100644 --- a/spec/workers/ci/external_pull_requests/create_pipeline_worker_spec.rb +++ b/spec/workers/ci/external_pull_requests/create_pipeline_worker_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Ci::ExternalPullRequests::CreatePipelineWorker do +RSpec.describe Ci::ExternalPullRequests::CreatePipelineWorker, feature_category: :continuous_integration do let_it_be(:project) { create(:project, :auto_devops, :repository) } let_it_be(:user) { project.first_owner } let_it_be(:external_pull_request) do |