diff --git a/.rubocop_todo/rails/active_record_callbacks_order.yml b/.rubocop_todo/rails/active_record_callbacks_order.yml deleted file mode 100644 index 044bda81d22..00000000000 --- a/.rubocop_todo/rails/active_record_callbacks_order.yml +++ /dev/null @@ -1,22 +0,0 @@ ---- -# Cop supports --autocorrect. -Rails/ActiveRecordCallbacksOrder: - Exclude: - - 'app/models/award_emoji.rb' - - 'app/models/gpg_key.rb' - - 'app/models/group.rb' - - 'app/models/issue.rb' - - 'app/models/key.rb' - - 'app/models/merge_request.rb' - - 'app/models/namespace.rb' - - 'app/models/namespace_statistics.rb' - - 'app/models/note.rb' - - 'app/models/pages_domain.rb' - - 'app/models/prometheus_alert.rb' - - 'app/models/remote_mirror.rb' - - 'app/models/resource_label_event.rb' - - 'app/models/snippet_statistics.rb' - - 'app/models/upload.rb' - - 'app/models/user.rb' - - 'ee/app/models/dast_site_profile.rb' - - 'ee/app/models/geo_node.rb' diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 034cce40162..3ee269cd5e3 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -52fb0853a49b14abddfc5a824d680bd255773d39 +06b92cf488942c6746795b581d27854339becc60 diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json index 3b40970e62d..d94aa73e43a 100644 --- a/app/assets/javascripts/editor/schema/ci.json +++ b/app/assets/javascripts/editor/schema/ci.json @@ -336,10 +336,10 @@ "include_item": { "oneOf": [ { - "description": "Will infer the method based on the value. E.g. `https://...` strings will be of type `include:remote`, and `/templates/...` will be of type `include:local`.", + "description": "Will infer the method based on the value. E.g. `https://...` strings will be of type `include:remote`, and `/templates/...` or `templates/...` will be of type `include:local`.", "type": "string", "format": "uri-reference", - "pattern": "^(https?://|/).+\\.ya?ml$" + "pattern": "^(https?://|/?.?-?(?!\\w+://)\\w).+\\.ya?ml$" }, { "type": "object", diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb index 6d136e9861c..de7329ee661 100644 --- a/app/graphql/types/ci/runner_type.rb +++ b/app/graphql/types/ci/runner_type.rb @@ -106,8 +106,25 @@ module Types end def job_count - # We limit to 1 above the JOB_COUNT_LIMIT to indicate that more items exist after JOB_COUNT_LIMIT - runner.builds.limit(JOB_COUNT_LIMIT + 1).count + BatchLoader::GraphQL.for(runner.id).batch(key: :job_count) do |runner_ids, loader, _args| + # rubocop: disable CodeReuse/ActiveRecord + # We limit to 1 above the JOB_COUNT_LIMIT to indicate that more items exist after JOB_COUNT_LIMIT + builds_tbl = ::Ci::Build.arel_table + runners_tbl = ::Ci::Runner.arel_table + lateral_query = ::Ci::Build.select(1) + .where(builds_tbl['runner_id'].eq(runners_tbl['id'])) + .limit(JOB_COUNT_LIMIT) + counts = ::Ci::Runner.joins("JOIN LATERAL (#{lateral_query.to_sql}) builds_with_limit ON true") + .id_in(runner_ids) + .select(:id, Arel.star.count.as('count')) + .group(:id) + .index_by(&:id) + # rubocop: enable CodeReuse/ActiveRecord + + runner_ids.each do |runner_id| + loader.call(runner_id, counts[runner_id]&.count || 0) + end + end end def admin_url diff --git a/app/models/award_emoji.rb b/app/models/award_emoji.rb index 9d758cf75d8..f41f0a8be84 100644 --- a/app/models/award_emoji.rb +++ b/app/models/award_emoji.rb @@ -26,8 +26,8 @@ class AwardEmoji < ApplicationRecord scope :named, ->(names) { where(name: names) } scope :awarded_by, ->(users) { where(user: users) } - after_save :expire_cache after_destroy :expire_cache + after_save :expire_cache class << self def votes_for_collection(ids, type) diff --git a/app/models/gpg_key.rb b/app/models/gpg_key.rb index 2db074e733e..1bf35179393 100644 --- a/app/models/gpg_key.rb +++ b/app/models/gpg_key.rb @@ -40,8 +40,8 @@ class GpgKey < ApplicationRecord unless: -> { errors.has_key?(:key) } before_validation :extract_fingerprint, :extract_primary_keyid - after_commit :update_invalid_gpg_signatures, on: :create after_create :generate_subkeys + after_commit :update_invalid_gpg_signatures, on: :create def primary_keyid super&.upcase diff --git a/app/models/group.rb b/app/models/group.rb index afc31e38e81..0cdd7dd8596 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -155,10 +155,10 @@ class Group < Namespace prefix: RunnersTokenPrefixable::RUNNERS_TOKEN_PREFIX after_create :post_create_hook + after_create -> { create_or_load_association(:group_feature) } + after_update :path_changed_hook, if: :saved_change_to_path? after_destroy :post_destroy_hook after_commit :update_two_factor_requirement - after_update :path_changed_hook, if: :saved_change_to_path? - after_create -> { create_or_load_association(:group_feature) } scope :with_users, -> { includes(:users) } diff --git a/app/models/issue.rb b/app/models/issue.rb index d1fe11cb49e..b338ecfce88 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -216,8 +216,8 @@ class Issue < ApplicationRecord before_validation :ensure_namespace_id, :ensure_work_item_type - after_commit :expire_etag_cache, unless: :importing? after_save :ensure_metrics, unless: :importing? + after_commit :expire_etag_cache, unless: :importing? after_create_commit :record_create_action, unless: :importing? attr_spammable :title, spam_title: true diff --git a/app/models/key.rb b/app/models/key.rb index 35fc42a935f..1f2234129ed 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -38,12 +38,12 @@ class Key < ApplicationRecord signing: 2 } - after_commit :add_to_authorized_keys, on: :create after_create :post_create_hook after_create :refresh_user_cache - after_commit :remove_from_authorized_keys, on: :destroy after_destroy :post_destroy_hook after_destroy :refresh_user_cache + after_commit :add_to_authorized_keys, on: :create + after_commit :remove_from_authorized_keys, on: :destroy alias_attribute :fingerprint_md5, :fingerprint alias_attribute :name, :title diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index de708a8c03d..78c6d983a3d 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -140,6 +140,7 @@ class MergeRequest < ApplicationRecord after_create :ensure_merge_request_diff, unless: :skip_ensure_merge_request_diff after_update :clear_memoized_shas after_update :reload_diff_if_branch_changed + after_save :keep_around_commit, unless: :importing? after_commit :ensure_metrics, on: [:create, :update], unless: :importing? after_commit :expire_etag_cache, unless: :importing? @@ -441,8 +442,6 @@ class MergeRequest < ApplicationRecord .pick(MergeRequest::Metrics.time_to_merge_expression) end - after_save :keep_around_commit, unless: :importing? - alias_attribute :project, :target_project alias_attribute :project_id, :target_project_id diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 54cd97253cf..d7d53956656 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -139,21 +139,21 @@ class Namespace < ApplicationRecord :npm_package_requests_forwarding, to: :package_settings - after_save :reload_namespace_details - - after_commit :refresh_access_of_projects_invited_groups, on: :update, if: -> { previous_changes.key?('share_with_group_lock') } - before_create :sync_share_with_group_lock_with_parent before_update :sync_share_with_group_lock_with_parent, if: :parent_changed? after_update :force_share_with_group_lock_on_descendants, if: -> { saved_change_to_share_with_group_lock? && share_with_group_lock? } after_update :expire_first_auto_devops_config_cache, if: -> { saved_change_to_auto_devops_enabled? } + after_update :move_dir, if: :saved_change_to_path_or_parent?, unless: -> { is_a?(Namespaces::ProjectNamespace) } + after_destroy :rm_dir + after_save :reload_namespace_details + + after_commit :refresh_access_of_projects_invited_groups, on: :update, if: -> { previous_changes.key?('share_with_group_lock') } + after_sync_traversal_ids :schedule_sync_event_worker # custom callback defined in Namespaces::Traversal::Linear # Legacy Storage specific hooks - after_update :move_dir, if: :saved_change_to_path_or_parent?, unless: -> { is_a?(Namespaces::ProjectNamespace) } before_destroy(prepend: true) { prepare_for_destroy } - after_destroy :rm_dir after_commit :expire_child_caches, on: :update, if: -> { Feature.enabled?(:cached_route_lookups, self, type: :ops) && saved_change_to_name? || saved_change_to_path? || saved_change_to_parent_id? diff --git a/app/models/namespace_statistics.rb b/app/models/namespace_statistics.rb index 04ca05d85ff..a17ca2e2c1d 100644 --- a/app/models/namespace_statistics.rb +++ b/app/models/namespace_statistics.rb @@ -10,8 +10,8 @@ class NamespaceStatistics < ApplicationRecord # rubocop:disable Gitlab/Namespace scope :for_namespaces, -> (namespaces) { where(namespace: namespaces) } before_save :update_storage_size - after_save :update_root_storage_statistics, if: :saved_change_to_storage_size? after_destroy :update_root_storage_statistics + after_save :update_root_storage_statistics, if: :saved_change_to_storage_size? delegate :group_namespace?, to: :namespace diff --git a/app/models/note.rb b/app/models/note.rb index 8e1f4979602..052df6142c5 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -168,10 +168,10 @@ class Note < ApplicationRecord # Syncs `confidential` with `internal` as we rename the column. # https://gitlab.com/gitlab-org/gitlab/-/issues/367923 before_create :set_internal_flag + after_destroy :expire_etag_cache after_save :keep_around_commit, if: :for_project_noteable?, unless: -> { importing? || skip_keep_around_commits } after_save :expire_etag_cache, unless: :importing? after_save :touch_noteable, unless: :importing? - after_destroy :expire_etag_cache after_commit :notify_after_create, on: :create after_commit :notify_after_destroy, on: :destroy diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb index 328c67a0711..4e3f4b0c328 100644 --- a/app/models/pages_domain.rb +++ b/app/models/pages_domain.rb @@ -17,6 +17,7 @@ class PagesDomain < ApplicationRecord has_many :acme_orders, class_name: "PagesDomainAcmeOrder" has_many :serverless_domain_clusters, class_name: 'Serverless::DomainCluster', inverse_of: :pages_domain + after_initialize :set_verification_code before_validation :clear_auto_ssl_failure, unless: :auto_ssl_enabled validates :domain, hostname: { allow_numeric_hostname: true } @@ -44,8 +45,6 @@ class PagesDomain < ApplicationRecord key: Settings.attr_encrypted_db_key_base, algorithm: 'aes-256-cbc' - after_initialize :set_verification_code - scope :for_project, ->(project) { where(project: project) } scope :enabled, -> { where('enabled_until >= ?', Time.current) } diff --git a/app/models/prometheus_alert.rb b/app/models/prometheus_alert.rb index 9080f3d9de1..59440947d71 100644 --- a/app/models/prometheus_alert.rb +++ b/app/models/prometheus_alert.rb @@ -20,8 +20,8 @@ class PrometheusAlert < ApplicationRecord has_many :related_issues, through: :prometheus_alert_events has_many :alert_management_alerts, class_name: 'AlertManagement::Alert', inverse_of: :prometheus_alert - after_save :clear_prometheus_adapter_cache! after_destroy :clear_prometheus_adapter_cache! + after_save :clear_prometheus_adapter_cache! validates :environment, :project, :prometheus_metric, :threshold, :operator, presence: true validates :runbook_url, length: { maximum: 255 }, allow_blank: true, diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb index 45487cb908d..b830cf313af 100644 --- a/app/models/remote_mirror.rb +++ b/app/models/remote_mirror.rb @@ -22,10 +22,9 @@ class RemoteMirror < ApplicationRecord validates :url, presence: true, public_url: { schemes: Project::VALID_MIRROR_PROTOCOLS, allow_blank: true, enforce_user: true } - after_save :set_override_remote_mirror_available, unless: -> { Gitlab::CurrentSettings.current_application_settings.mirror_available } - after_update :reset_fields, if: :saved_change_to_mirror_url? - before_validation :store_credentials + after_update :reset_fields, if: :saved_change_to_mirror_url? + after_save :set_override_remote_mirror_available, unless: -> { Gitlab::CurrentSettings.current_application_settings.mirror_available } scope :enabled, -> { where(enabled: true) } scope :started, -> { with_update_status(:started) } diff --git a/app/models/resource_label_event.rb b/app/models/resource_label_event.rb index a1753df9294..a1426540cf5 100644 --- a/app/models/resource_label_event.rb +++ b/app/models/resource_label_event.rb @@ -14,8 +14,8 @@ class ResourceLabelEvent < ResourceEvent validates :label, presence: { unless: :importing? }, on: :create validate :exactly_one_issuable, unless: :importing? - after_save :expire_etag_cache after_destroy :expire_etag_cache + after_save :expire_etag_cache enum action: { add: 1, diff --git a/app/models/snippet_statistics.rb b/app/models/snippet_statistics.rb index 6fb6f0ef713..44bff0e1e5b 100644 --- a/app/models/snippet_statistics.rb +++ b/app/models/snippet_statistics.rb @@ -12,8 +12,8 @@ class SnippetStatistics < ApplicationRecord delegate :repository, :project, :project_id, to: :snippet - after_save :update_author_root_storage_statistics, if: :update_author_root_storage_statistics? after_destroy :update_author_root_storage_statistics, unless: :project_snippet? + after_save :update_author_root_storage_statistics, if: :update_author_root_storage_statistics? def update_commit_count self.commit_count = repository.commit_count diff --git a/app/models/upload.rb b/app/models/upload.rb index ac7ebb31abc..a4fbc703146 100644 --- a/app/models/upload.rb +++ b/app/models/upload.rb @@ -16,14 +16,13 @@ class Upload < ApplicationRecord scope :with_files_stored_locally, -> { where(store: ObjectStorage::Store::LOCAL) } scope :with_files_stored_remotely, -> { where(store: ObjectStorage::Store::REMOTE) } - before_save :calculate_checksum!, if: :foreground_checksummable? - after_commit :schedule_checksum, if: :needs_checksum? - - after_commit :update_project_statistics, on: [:create, :destroy], if: :project? - + before_save :calculate_checksum!, if: :foreground_checksummable? # as the FileUploader is not mounted, the default CarrierWave ActiveRecord # hooks are not executed and the file will not be deleted after_destroy :delete_file!, if: -> { uploader_class <= FileUploader } + after_commit :schedule_checksum, if: :needs_checksum? + + after_commit :update_project_statistics, on: [:create, :destroy], if: :project? class << self def inner_join_local_uploads_projects diff --git a/app/models/user.rb b/app/models/user.rb index fb742e7c11f..d50605b4aa3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -300,16 +300,17 @@ class User < ApplicationRecord validates :website_url, allow_blank: true, url: true, if: :website_url_changed? + after_initialize :set_projects_limit before_validation :sanitize_attrs + before_validation :ensure_namespace_correct + after_validation :set_username_errors before_save :default_private_profile_to_false before_save :ensure_incoming_email_token before_save :ensure_user_rights_and_limits, if: ->(user) { user.new_record? || user.external_changed? } before_save :skip_reconfirmation!, if: ->(user) { user.email_changed? && user.read_only_attribute?(:email) } before_save :check_for_verified_email, if: ->(user) { user.email_changed? && !user.new_record? } - before_validation :ensure_namespace_correct before_save :ensure_namespace_correct # in case validation is skipped before_save :ensure_user_detail_assigned - after_validation :set_username_errors after_update :username_changed_hook, if: :saved_change_to_username? after_destroy :post_destroy_hook after_destroy :remove_key_cache @@ -330,8 +331,6 @@ class User < ApplicationRecord update_invalid_gpg_signatures if previous_changes.key?('email') end - after_initialize :set_projects_limit - # User's Layout preference enum layout: { fixed: 0, fluid: 1 } diff --git a/data/deprecations/15-7-deprecate-dast-api-scan-in-dast-template.yml b/data/deprecations/15-7-deprecate-dast-api-scan-in-dast-template.yml new file mode 100644 index 00000000000..172683dcb86 --- /dev/null +++ b/data/deprecations/15-7-deprecate-dast-api-scan-in-dast-template.yml @@ -0,0 +1,11 @@ +- title: "DAST API scans using DAST template is deprecated" # (required) Actionable title. e.g., The `confidential` field for a `Note` is deprecated. Use `internal` instead. + announcement_milestone: "15.7" # (required) The milestone when this feature was first announced as deprecated. + announcement_date: "2022-12-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. + removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed + removal_date: "2023-05-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. + breaking_change: true # (required) If this deprecation is a breaking change, set this value to true + reporter: derekferguson # (required) GitLab username of the person reporting the deprecation + stage: Secure # (required) String value of the stage that the feature was created in. e.g., Growth + issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/384198 # (required) Link to the deprecation issue in GitLab + body: | # (required) Do not modify this line, instead modify the lines below. + With the move to the new DAST API analyzer and the `DAST-API.gitlab-ci.yml` template for DAST API scans, we will be removing the ability to scan APIs with the DAST analyzer. Use of the `DAST.gitlab-ci.yml` or `DAST-latest.gitlab-ci.yml` templates for API scans is deprecated as of GitLab 15.7 and will no longer work in GitLab 16.0. Please use `DAST-API.gitlab-ci.yml` template and refer to the [DAST API analyzer](https://docs.gitlab.com/ee/user/application_security/dast_api/#configure-dast-api-with-an-openapi-specification) documentation for configuration details. diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md index 7965e18e005..9e580d93609 100644 --- a/doc/update/deprecations.md +++ b/doc/update/deprecations.md @@ -52,6 +52,20 @@ sole discretion of GitLab Inc.
+### DAST API scans using DAST template is deprecated + +Planned removal: GitLab 16.0 (2023-05-22) + +WARNING: +This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/). +Review the details carefully before upgrading. + +With the move to the new DAST API analyzer and the `DAST-API.gitlab-ci.yml` template for DAST API scans, we will be removing the ability to scan APIs with the DAST analyzer. Use of the `DAST.gitlab-ci.yml` or `DAST-latest.gitlab-ci.yml` templates for API scans is deprecated as of GitLab 15.7 and will no longer work in GitLab 16.0. Please use `DAST-API.gitlab-ci.yml` template and refer to the [DAST API analyzer](https://docs.gitlab.com/ee/user/application_security/dast_api/#configure-dast-api-with-an-openapi-specification) documentation for configuration details. + +
+ +
+ ### DAST API variables Planned removal: GitLab 16.0 (2023-05-22) diff --git a/lib/api/entities/milestone.rb b/lib/api/entities/milestone.rb index b191210a234..ea73ade46cd 100644 --- a/lib/api/entities/milestone.rb +++ b/lib/api/entities/milestone.rb @@ -10,7 +10,7 @@ module API expose :state, :created_at, :updated_at expose :due_date expose :start_date - expose :expired?, as: :expired + expose :expired expose :web_url do |milestone, _options| Gitlab::UrlBuilder.build(milestone) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f18fb382037..f0b142047aa 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -31537,7 +31537,13 @@ msgstr "" msgid "Proceed" msgstr "" -msgid "Product Analytics|Onboarding view" +msgid "Product Analytics|Analyze your product with Product Analytics" +msgstr "" + +msgid "Product Analytics|Set up Product Analytics to track how your product is performing. Combine it with your GitLab data to better understand where you can improve your product and development processes." +msgstr "" + +msgid "Product Analytics|Set up product analytics..." msgstr "" msgid "Product analytics" @@ -36268,6 +36274,12 @@ msgstr "" msgid "ScanExecutionPolicy|A pipeline is run" msgstr "" +msgid "ScanExecutionPolicy|Ex, tag-name-1, tag-name-2" +msgstr "" + +msgid "ScanExecutionPolicy|If the field is empty, the runner will be automatically selected" +msgstr "" + msgid "ScanExecutionPolicy|Scanner profile" msgstr "" @@ -36292,9 +36304,6 @@ msgstr "" msgid "ScanExecutionPolicy|Select site profile" msgstr "" -msgid "ScanExecutionPolicy|Select tags (if any)" -msgstr "" - msgid "ScanExecutionPolicy|Site profile" msgstr "" @@ -37187,7 +37196,7 @@ msgstr "" msgid "SecurityOrchestration|Summary" msgstr "" -msgid "SecurityOrchestration|The following branches do not exist on this development project: %{branches}. Please review all branches to ensure the values are accurate before updating this policy." +msgid "SecurityOrchestration|The following branches do not exist on this development project: %{branches}. Please review all protected branches to ensure the values are accurate before updating this policy." msgstr "" msgid "SecurityOrchestration|There was a problem creating the new security policy" @@ -37250,10 +37259,10 @@ msgstr "" msgid "SecurityOrchestration|a" msgstr "" -msgid "SecurityOrchestration|all branches" +msgid "SecurityOrchestration|all namespaces" msgstr "" -msgid "SecurityOrchestration|all namespaces" +msgid "SecurityOrchestration|all protected branches" msgstr "" msgid "SecurityOrchestration|an" diff --git a/qa/qa/resource/runner.rb b/qa/qa/resource/runner.rb index d755c73e790..30c4dd56633 100644 --- a/qa/qa/resource/runner.rb +++ b/qa/qa/resource/runner.rb @@ -119,7 +119,12 @@ module QA end def this_runner - runners_list.find { |runner| runner[:description] == name } + runner = nil + Support::Retrier.retry_until(max_duration: 60, sleep_interval: 1) do + runner = runners_list.find { |runner| runner[:description] == name } + !runner.nil? + end + runner end def populate_runner_attributes diff --git a/spec/features/jira_connect/branches_spec.rb b/spec/features/jira_connect/branches_spec.rb index 585aa85b16d..489d3743a2a 100644 --- a/spec/features/jira_connect/branches_spec.rb +++ b/spec/features/jira_connect/branches_spec.rb @@ -65,7 +65,11 @@ RSpec.describe 'Create GitLab branches from Jira', :js, feature_category: :integ end click_on 'master' + wait_for_requests + fill_in 'Search', with: source_branch + wait_for_requests + within '[role="listbox"]' do find('li', text: source_branch).click end diff --git a/spec/fixtures/api/schemas/public_api/v4/issue.json b/spec/fixtures/api/schemas/public_api/v4/issue.json index 0e8de3cd3d7..9108d21c2ae 100644 --- a/spec/fixtures/api/schemas/public_api/v4/issue.json +++ b/spec/fixtures/api/schemas/public_api/v4/issue.json @@ -93,12 +93,31 @@ "format": "date-time" }, "due_date": { - "type": "string", - "format": "date-time" + "type": [ + "string", + "null" + ], + "format": [ + "date-time", + "date" + ] }, "start_date": { + "type": [ + "string", + "null" + ], + "format": [ + "date-time", + "date" + ] + }, + "expired": { + "type": "boolean" + }, + "web_url": { "type": "string", - "format": "date-time" + "format": "uri" } }, "additionalProperties": false diff --git a/spec/fixtures/api/schemas/public_api/v4/issues.json b/spec/fixtures/api/schemas/public_api/v4/issues.json index c76806705e8..5ef97b020f9 100644 --- a/spec/fixtures/api/schemas/public_api/v4/issues.json +++ b/spec/fixtures/api/schemas/public_api/v4/issues.json @@ -1,9 +1,6 @@ { "type": "array", "items": { - "type": "object", - "properties" : { - "$ref": "./issue.json" - } + "$ref": "./issue.json" } -} +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/public_api/v4/merge_request.json b/spec/fixtures/api/schemas/public_api/v4/merge_request.json index 1ef2f9f9534..9a6c1757eea 100644 --- a/spec/fixtures/api/schemas/public_api/v4/merge_request.json +++ b/spec/fixtures/api/schemas/public_api/v4/merge_request.json @@ -1,25 +1,75 @@ { "type": "object", - "properties" : { - "id": { "type": "integer" }, - "iid": { "type": "integer" }, - "project_id": { "type": "integer" }, - "title": { "type": "string" }, - "description": { "type": ["string", "null"] }, - "state": { "type": "string" }, - "merged_by": { "$ref": "user/basic.json" }, - "merge_user": { "$ref": "user/basic.json" }, - "merged_at": { "type": ["string", "null"] }, - "closed_by": { "$ref": "user/basic.json" }, - "closed_at": { "type": ["string", "null"], "format": "date-time" }, - "created_at": { "type": "string", "format": "date-time" }, - "updated_at": { "type": "string", "format": "date-time" }, - "target_branch": { "type": "string" }, - "source_branch": { "type": "string" }, - "upvotes": { "type": "integer" }, - "downvotes": { "type": "integer" }, - "author": { "$ref": "user/basic.json" }, - "assignee": { "$ref": "user/basic.json" }, + "properties": { + "id": { + "type": "integer" + }, + "iid": { + "type": "integer" + }, + "project_id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "state": { + "type": "string" + }, + "merged_by": { + "$ref": "user/basic.json" + }, + "merge_user": { + "$ref": "user/basic.json" + }, + "merged_at": { + "type": [ + "string", + "null" + ] + }, + "closed_by": { + "$ref": "user/basic.json" + }, + "closed_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "target_branch": { + "type": "string" + }, + "source_branch": { + "type": "string" + }, + "upvotes": { + "type": "integer" + }, + "downvotes": { + "type": "integer" + }, + "author": { + "$ref": "user/basic.json" + }, + "assignee": { + "$ref": "user/basic.json" + }, "assignees": { "type": "array", "items": { @@ -32,60 +82,159 @@ "$ref": "user/basic.json" } }, - "source_project_id": { "type": "integer" }, - "target_project_id": { "type": "integer" }, + "source_project_id": { + "type": "integer" + }, + "target_project_id": { + "type": "integer" + }, "labels": { "type": "array", "items": { "type": "string" } }, - "work_in_progress": { "type": "boolean" }, + "work_in_progress": { + "type": "boolean" + }, "milestone": { "oneOf": [ - { "type": "null" }, - { "$ref": "milestone.json" } + { + "type": "null" + }, + { + "$ref": "milestone.json" + } ] }, - "merge_when_pipeline_succeeds": { "type": "boolean" }, - "merge_status": { "type": "string" }, - "sha": { "type": "string" }, - "merge_commit_sha": { "type": ["string", "null"] }, - "user_notes_count": { "type": "integer" }, - "changes_count": { "type": "string" }, - "should_remove_source_branch": { "type": ["boolean", "null"] }, - "force_remove_source_branch": { "type": ["boolean", "null"] }, - "discussion_locked": { "type": ["boolean", "null"] }, - "web_url": { "type": "uri" }, - "squash": { "type": "boolean" }, - "time_stats": { - "time_estimate": { "type": "integer" }, - "total_time_spent": { "type": "integer" }, - "human_time_estimate": { "type": ["string", "null"] }, - "human_total_time_spent": { "type": ["string", "null"] } + "merge_when_pipeline_succeeds": { + "type": "boolean" + }, + "merge_status": { + "type": "string" + }, + "sha": { + "type": "string" + }, + "merge_commit_sha": { + "type": [ + "string", + "null" + ] + }, + "user_notes_count": { + "type": "integer" + }, + "changes_count": { + "type": "string" + }, + "should_remove_source_branch": { + "type": [ + "boolean", + "null" + ] + }, + "force_remove_source_branch": { + "type": [ + "boolean", + "null" + ] + }, + "discussion_locked": { + "type": [ + "boolean", + "null" + ] + }, + "web_url": { + "type": "string", + "format": "uri" + }, + "squash": { + "type": "boolean" + }, + "time_stats": { + "time_estimate": { + "type": "integer" + }, + "total_time_spent": { + "type": "integer" + }, + "human_time_estimate": { + "type": [ + "string", + "null" + ] + }, + "human_total_time_spent": { + "type": [ + "string", + "null" + ] + } + }, + "allow_collaboration": { + "type": [ + "boolean", + "null" + ] + }, + "allow_maintainer_to_push": { + "type": [ + "boolean", + "null" + ] }, - "allow_collaboration": { "type": ["boolean", "null"] }, - "allow_maintainer_to_push": { "type": ["boolean", "null"] }, "references": { - "short": {"type": "string"}, - "relative": {"type": "string"}, - "full": {"type": "string"} + "short": { + "type": "string" + }, + "relative": { + "type": "string" + }, + "full": { + "type": "string" + } } }, "required": [ - "id", "iid", "project_id", "title", "description", - "state", "created_at", "updated_at", "target_branch", - "source_branch", "upvotes", "downvotes", "author", - "assignee", "source_project_id", "target_project_id", - "labels", "work_in_progress", "milestone", "merge_when_pipeline_succeeds", - "merge_status", "sha", "merge_commit_sha", "user_notes_count", - "should_remove_source_branch", "force_remove_source_branch", - "web_url", "squash" + "id", + "iid", + "project_id", + "title", + "description", + "state", + "created_at", + "updated_at", + "target_branch", + "source_branch", + "upvotes", + "downvotes", + "author", + "assignee", + "source_project_id", + "target_project_id", + "labels", + "work_in_progress", + "milestone", + "merge_when_pipeline_succeeds", + "merge_status", + "sha", + "merge_commit_sha", + "user_notes_count", + "should_remove_source_branch", + "force_remove_source_branch", + "web_url", + "squash" ], "head_pipeline": { "oneOf": [ - { "type": "null" }, - { "$ref": "pipeline/detail.json" } + { + "type": "null" + }, + { + "$ref": "pipeline/detail.json" + } ] } -} +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/public_api/v4/merge_request_simple.json b/spec/fixtures/api/schemas/public_api/v4/merge_request_simple.json index f176e5ee261..48de8f13547 100644 --- a/spec/fixtures/api/schemas/public_api/v4/merge_request_simple.json +++ b/spec/fixtures/api/schemas/public_api/v4/merge_request_simple.json @@ -1,26 +1,59 @@ { "type": "object", - "properties" : { - "properties" : { - "id": { "type": "integer" }, - "iid": { "type": "integer" }, - "project_id": { "type": "integer" }, - "title": { "type": "string" }, - "description": { "type": ["string", "null"] }, - "state": { "type": "string" }, - "created_at": { "type": "string", "format": "date-time" }, - "updated_at": { "type": "string", "format": "date-time" }, - "web_url": { "type": "uri" } + "properties": { + "id": { + "type": "integer" + }, + "iid": { + "type": "integer" + }, + "project_id": { + "type": "integer" + }, + "title": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "state": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "web_url": { + "type": "string", + "format": "uri" }, - "required": [ - "id", "iid", "project_id", "title", "description", - "state", "created_at", "updated_at", "web_url" - ], "head_pipeline": { "oneOf": [ - { "type": "null" }, - { "$ref": "pipeline/detail.json" } + { + "type": "null" + }, + { + "$ref": "pipeline/detail.json" + } ] } - } -} + }, + "required": [ + "id", + "iid", + "project_id", + "title", + "description", + "state", + "created_at", + "updated_at", + "web_url" + ] +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/public_api/v4/milestone.json b/spec/fixtures/api/schemas/public_api/v4/milestone.json index e7e0e57f02f..c33c4044a62 100644 --- a/spec/fixtures/api/schemas/public_api/v4/milestone.json +++ b/spec/fixtures/api/schemas/public_api/v4/milestone.json @@ -1,24 +1,77 @@ { "type": "object", - "properties" : { - "id": { "type": "integer" }, - "iid": { "type": "integer" }, - "project_id": { "type": ["integer", "null"] }, - "group_id": { "type": ["integer", "null"] }, - "title": { "type": "string" }, - "description": { "type": ["string", "null"] }, - "state": { "type": "string" }, - "created_at": { "type": "string" }, - "updated_at": { "type": "string" }, - "start_date": { "type": ["string", "null"], "format": "date-time" }, - "due_date": { "type": ["string", "null"], "format": "date-time" }, - "expired": { "type": ["boolean", "null"] }, - "web_url": { "type": "string" } + "properties": { + "id": { + "type": "integer" + }, + "iid": { + "type": "integer" + }, + "project_id": { + "type": [ + "integer", + "null" + ] + }, + "group_id": { + "type": [ + "integer", + "null" + ] + }, + "title": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "state": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "start_date": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "due_date": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "expired": { + "type": [ + "boolean", + "null" + ] + }, + "web_url": { + "type": "string" + } }, "required": [ - "id", "iid", "title", "description", "state", - "state", "created_at", "updated_at", "start_date", - "due_date", "expired" + "id", + "iid", + "title", + "description", + "state", + "created_at", + "updated_at", + "start_date", + "due_date", + "expired" ], "additionalProperties": false -} +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/public_api/v4/milestone_with_stats.json b/spec/fixtures/api/schemas/public_api/v4/milestone_with_stats.json index d09d1634eb9..b5fa161ec2a 100644 --- a/spec/fixtures/api/schemas/public_api/v4/milestone_with_stats.json +++ b/spec/fixtures/api/schemas/public_api/v4/milestone_with_stats.json @@ -1,32 +1,95 @@ { "type": "object", - "properties" : { - "id": { "type": "integer" }, - "iid": { "type": "integer" }, - "project_id": { "type": ["integer", "null"] }, - "group_id": { "type": ["integer", "null"] }, - "title": { "type": "string" }, - "description": { "type": ["string", "null"] }, - "state": { "type": "string" }, - "created_at": { "type": "string", "format": "date-time" }, - "updated_at": { "type": "string", "format": "date-time" }, - "start_date": { "type": ["string", "null"], "format": "date-time" }, - "due_date": { "type": ["string", "null"], "format": "date-time" }, - "expired": { "type": ["boolean", "null"] }, - "web_url": { "type": "string" }, + "properties": { + "id": { + "type": "integer" + }, + "iid": { + "type": "integer" + }, + "project_id": { + "type": [ + "integer", + "null" + ] + }, + "group_id": { + "type": [ + "integer", + "null" + ] + }, + "title": { + "type": "string" + }, + "description": { + "type": [ + "string", + "null" + ] + }, + "state": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "start_date": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "due_date": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "expired": { + "type": [ + "boolean", + "null" + ] + }, + "web_url": { + "type": "string" + }, "issue_stats": { - "required": ["total", "closed"], + "required": [ + "total", + "closed" + ], "properties": { - "total": { "type": "integer" }, - "closed": { "type": "integer" } + "total": { + "type": "integer" + }, + "closed": { + "type": "integer" + } }, "additionalProperties": false } }, "required": [ - "id", "iid", "title", "description", "state", - "state", "created_at", "updated_at", "start_date", - "due_date", "expired", "issue_stats" + "id", + "iid", + "title", + "description", + "state", + "created_at", + "updated_at", + "start_date", + "due_date", + "expired", + "issue_stats" ], "additionalProperties": false -} +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/public_api/v4/notes.json b/spec/fixtures/api/schemas/public_api/v4/notes.json index d6d0300a64f..1987a0f2f71 100644 --- a/spec/fixtures/api/schemas/public_api/v4/notes.json +++ b/spec/fixtures/api/schemas/public_api/v4/notes.json @@ -2,43 +2,124 @@ "type": "array", "items": { "type": "object", - "properties" : { - "id": { "type": "integer" }, - "type": { "type": ["string", "null"] }, - "body": { "type": "string" }, - "attachment": { "type": ["string", "null"] }, + "properties": { + "id": { + "type": "integer" + }, + "type": { + "type": [ + "string", + "null" + ] + }, + "body": { + "type": "string" + }, + "attachment": { + "type": [ + "string", + "null" + ] + }, "author": { "type": "object", "properties": { - "name": { "type": "string" }, - "username": { "type": "string" }, - "id": { "type": "integer" }, - "state": { "type": "string" }, - "avatar_url": { "type": "uri" }, - "web_url": { "type": "uri" } + "name": { + "type": "string" + }, + "username": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "state": { + "type": "string" + }, + "avatar_url": { + "type": "string", + "format": "uri" + }, + "web_url": { + "type": "string", + "format": "uri" + } }, - "required" : [ - "id", "name", "username", "state", "avatar_url", "web_url" + "required": [ + "id", + "name", + "username", + "state", + "avatar_url", + "web_url" ] }, - "commands_changes": { "type": "object", "additionalProperties": true }, - "created_at": { "type": "string", "format": "date-time" }, - "updated_at": { "type": "string", "format": "date-time" }, - "system": { "type": "boolean" }, - "noteable_id": { "type": "integer" }, - "noteable_iid": { "type": "integer" }, - "noteable_type": { "type": "string" }, - "resolved": { "type": "boolean" }, - "resolvable": { "type": "boolean" }, - "resolved_by": { "type": ["string", "null"] }, - "resolved_at": { "type": ["string", "null"] }, - "confidential": { "type": ["boolean", "null"] }, - "internal": { "type": ["boolean", "null"] } + "commands_changes": { + "type": "object", + "additionalProperties": true + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "system": { + "type": "boolean" + }, + "noteable_id": { + "type": "integer" + }, + "noteable_iid": { + "type": "integer" + }, + "noteable_type": { + "type": "string" + }, + "resolved": { + "type": "boolean" + }, + "resolvable": { + "type": "boolean" + }, + "resolved_by": { + "type": [ + "string", + "null" + ] + }, + "resolved_at": { + "type": [ + "string", + "null" + ] + }, + "confidential": { + "type": [ + "boolean", + "null" + ] + }, + "internal": { + "type": [ + "boolean", + "null" + ] + } }, "required": [ - "id", "body", "attachment", "author", "created_at", "updated_at", - "system", "noteable_id", "noteable_type" + "id", + "body", + "attachment", + "author", + "created_at", + "updated_at", + "system", + "noteable_id", + "noteable_type" ], "additionalProperties": false } -} +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/public_api/v4/pages_domain/basic.json b/spec/fixtures/api/schemas/public_api/v4/pages_domain/basic.json index 66d4be529b1..9bcd191741f 100644 --- a/spec/fixtures/api/schemas/public_api/v4/pages_domain/basic.json +++ b/spec/fixtures/api/schemas/public_api/v4/pages_domain/basic.json @@ -1,23 +1,60 @@ { "type": "object", "properties": { - "domain": { "type": "string" }, - "url": { "type": "uri" }, - "project_id": { "type": "integer" }, - "verified": { "type": "boolean" }, - "verification_code": { "type": ["string", "null"] }, - "enabled_until": { "type": ["string", "null"], "format": "date-time" }, - "auto_ssl_enabled": { "type": "boolean" }, + "domain": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + }, + "project_id": { + "type": "integer" + }, + "verified": { + "type": "boolean" + }, + "verification_code": { + "type": [ + "string", + "null" + ] + }, + "enabled_until": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "auto_ssl_enabled": { + "type": "boolean" + }, "certificate_expiration": { "type": "object", "properties": { - "expired": { "type": "boolean" }, - "expiration": { "type": "string" } + "expired": { + "type": "boolean" + }, + "expiration": { + "type": "string" + } }, - "required": ["expired", "expiration"], + "required": [ + "expired", + "expiration" + ], "additionalProperties": false } }, - "required": ["domain", "url", "project_id", "verified", "verification_code", "enabled_until", "auto_ssl_enabled"], + "required": [ + "domain", + "url", + "project_id", + "verified", + "verification_code", + "enabled_until", + "auto_ssl_enabled" + ], "additionalProperties": false -} +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/public_api/v4/pages_domain/detail.json b/spec/fixtures/api/schemas/public_api/v4/pages_domain/detail.json index bbbc610eb27..6ce431a274a 100644 --- a/spec/fixtures/api/schemas/public_api/v4/pages_domain/detail.json +++ b/spec/fixtures/api/schemas/public_api/v4/pages_domain/detail.json @@ -1,24 +1,61 @@ { "type": "object", "properties": { - "domain": { "type": "string" }, - "url": { "type": "uri" }, - "verified": { "type": "boolean" }, - "verification_code": { "type": ["string", "null"] }, - "enabled_until": { "type": ["string", "null"] }, - "auto_ssl_enabled": { "type": "boolean" }, + "domain": { + "type": "string" + }, + "url": { + "type": "string", + "format": "uri" + }, + "verified": { + "type": "boolean" + }, + "verification_code": { + "type": [ + "string", + "null" + ] + }, + "enabled_until": { + "type": [ + "string", + "null" + ] + }, + "auto_ssl_enabled": { + "type": "boolean" + }, "certificate": { "type": "object", "properties": { - "subject": { "type": "string" }, - "expired": { "type": "boolean" }, - "certificate": { "type": "string" }, - "certificate_text": { "type": "string" } + "subject": { + "type": "string" + }, + "expired": { + "type": "boolean" + }, + "certificate": { + "type": "string" + }, + "certificate_text": { + "type": "string" + } }, - "required": ["subject", "expired"], + "required": [ + "subject", + "expired" + ], "additionalProperties": false } }, - "required": ["domain", "url", "verified", "verification_code", "enabled_until", "auto_ssl_enabled"], + "required": [ + "domain", + "url", + "verified", + "verification_code", + "enabled_until", + "auto_ssl_enabled" + ], "additionalProperties": false -} +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/public_api/v4/project_hooks.json b/spec/fixtures/api/schemas/public_api/v4/project_hooks.json index 8c542ebe3ad..8557e5cae40 100644 --- a/spec/fixtures/api/schemas/public_api/v4/project_hooks.json +++ b/spec/fixtures/api/schemas/public_api/v4/project_hooks.json @@ -1,10 +1,6 @@ { "type": "array", "items": { - "type": "object", - "properties" : { - "$ref": "./project_hook.json" - } + "$ref": "./project_hook.json" } -} - +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/public_api/v4/snippets.json b/spec/fixtures/api/schemas/public_api/v4/snippets.json index 65299901128..dab6b69f1c1 100644 --- a/spec/fixtures/api/schemas/public_api/v4/snippets.json +++ b/spec/fixtures/api/schemas/public_api/v4/snippets.json @@ -2,46 +2,107 @@ "type": "array", "items": { "type": "object", - "properties" : { - "id": { "type": "integer" }, - "project_id": { "type": ["integer", "null"] }, - "title": { "type": "string" }, - "file_name": { "type": ["string", "null"] }, - "files" : { + "properties": { + "id": { + "type": "integer" + }, + "project_id": { + "type": [ + "integer", + "null" + ] + }, + "title": { + "type": "string" + }, + "file_name": { + "type": [ + "string", + "null" + ] + }, + "files": { "type": "array", "items": { "type": "object", "properties": { - "path": { "type": "string" }, - "raw_url": { "type": "string" } + "path": { + "type": "string" + }, + "raw_url": { + "type": "string" + } } } }, - "description": { "type": ["string", "null"] }, - "visibility": { "type": "string" }, - "web_url": { "type": "string" }, - "raw_url": { "type": "string" }, - "created_at": { "type": "string", "format": "date-time" }, - "updated_at": { "type": "string", "format": "date-time" }, + "description": { + "type": [ + "string", + "null" + ] + }, + "visibility": { + "type": "string" + }, + "web_url": { + "type": "string" + }, + "raw_url": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, "author": { "type": "object", "properties": { - "name": { "type": "string" }, - "username": { "type": "string" }, - "id": { "type": "integer" }, - "state": { "type": "string" }, - "avatar_url": { "type": "uri" }, - "web_url": { "type": "uri" } + "name": { + "type": "string" + }, + "username": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "state": { + "type": "string" + }, + "avatar_url": { + "type": "string", + "format": "uri" + }, + "web_url": { + "type": "string", + "format": "uri" + } }, - "required" : [ - "id", "name", "username", "state", "avatar_url", "web_url" + "required": [ + "id", + "name", + "username", + "state", + "avatar_url", + "web_url" ] } }, "required": [ - "id", "title", "file_name", "description", "web_url", - "created_at", "updated_at", "author", "raw_url" + "id", + "title", + "file_name", + "description", + "web_url", + "created_at", + "updated_at", + "author", + "raw_url" ], "additionalProperties": false } -} +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/public_api/v4/system_hooks.json b/spec/fixtures/api/schemas/public_api/v4/system_hooks.json index a56542a8b99..a0800e4bc97 100644 --- a/spec/fixtures/api/schemas/public_api/v4/system_hooks.json +++ b/spec/fixtures/api/schemas/public_api/v4/system_hooks.json @@ -1,9 +1,6 @@ { "type": "array", "items": { - "type": "object", - "properties" : { - "$ref": "./system_hook.json" - } + "$ref": "./system_hook.json" } -} +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/public_api/v4/user/public.json b/spec/fixtures/api/schemas/public_api/v4/user/public.json index c4549e3ef63..53d67e041a1 100644 --- a/spec/fixtures/api/schemas/public_api/v4/user/public.json +++ b/spec/fixtures/api/schemas/public_api/v4/user/public.json @@ -28,32 +28,95 @@ "external" ], "properties": { - "id": { "type": "integer" }, - "username": { "type": "string" }, + "id": { + "type": "integer" + }, + "username": { + "type": "string" + }, "email": { "type": "string", "pattern": "^[^@]+@[^@]+$" }, - "name": { "type": "string" }, + "name": { + "type": "string" + }, "state": { "type": "string", - "enum": ["active", "blocked"] + "enum": [ + "active", + "blocked" + ] + }, + "avatar_url": { + "type": [ + "string", + "null" + ] + }, + "web_url": { + "type": "string" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "bio": { + "type": [ + "string", + "null" + ] + }, + "location": { + "type": [ + "string", + "null" + ] + }, + "skype": { + "type": "string" + }, + "linkedin": { + "type": "string" + }, + "twitter": { + "type": "string" + }, + "website_url": { + "type": "string" + }, + "organization": { + "type": [ + "string", + "null" + ] + }, + "last_sign_in_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "confirmed_at": { + "type": [ + "string", + "null" + ] + }, + "color_scheme_id": { + "type": "integer" + }, + "projects_limit": { + "type": "integer" + }, + "current_sign_in_at": { + "type": [ + "string", + "null" + ], + "format": "date-time" }, - "avatar_url": { "type": [ "string", "null" ] }, - "web_url": { "type": "string" }, - "created_at": { "type": "string", "format": "date-time" }, - "bio": { "type": ["string", "null"] }, - "location": { "type": ["string", "null"] }, - "skype": { "type": "string" }, - "linkedin": { "type": "string" }, - "twitter": { "type": "string "}, - "website_url": { "type": "string" }, - "organization": { "type": ["string", "null"] }, - "last_sign_in_at": { "type": ["string", "null"], "format": "date-time" }, - "confirmed_at": { "type": ["string", "null"] }, - "color_scheme_id": { "type": "integer" }, - "projects_limit": { "type": "integer" }, - "current_sign_in_at": { "type": ["string", "null"], "format": "date-time" }, "identities": { "type": "array", "items": { @@ -61,16 +124,35 @@ "properties": { "provider": { "type": "string", - "enum": ["github", "bitbucket", "google_oauth2"] + "enum": [ + "github", + "bitbucket", + "google_oauth2" + ] }, - "extern_uid": { "type": ["number", "string"] } + "extern_uid": { + "type": [ + "number", + "string" + ] + } } } }, - "can_create_group": { "type": "boolean" }, - "can_create_project": { "type": "boolean" }, - "two_factor_enabled": { "type": "boolean" }, - "external": { "type": "boolean" }, - "commit_email": { "type": "string" } + "can_create_group": { + "type": "boolean" + }, + "can_create_project": { + "type": "boolean" + }, + "two_factor_enabled": { + "type": "boolean" + }, + "external": { + "type": "boolean" + }, + "commit_email": { + "type": "string" + } } -} +} \ No newline at end of file diff --git a/spec/fixtures/api/schemas/registry/repository.json b/spec/fixtures/api/schemas/registry/repository.json index 18d2c68ac2f..078fba7a34a 100644 --- a/spec/fixtures/api/schemas/registry/repository.json +++ b/spec/fixtures/api/schemas/registry/repository.json @@ -1,6 +1,12 @@ { "type": "object", - "required": ["id", "name", "path", "location", "created_at"], + "required": [ + "id", + "name", + "path", + "location", + "created_at" + ], "properties": { "id": { "type": "integer" @@ -18,10 +24,15 @@ "type": "string" }, "created_at": { - "type": "date-time" + "type": "string", + "format": "date-time" }, "cleanup_policy_started_at": { - "type": "date-time" + "type": [ + "string", + "null" + ], + "format": "date-time" }, "tags_path": { "type": "string" @@ -31,14 +42,24 @@ }, "status": { "oneOf": [ - { "type": "null" }, - { "type": "string", "enum": ["delete_scheduled", "delete_failed"] } + { + "type": "null" + }, + { + "type": "string", + "enum": [ + "delete_scheduled", + "delete_failed" + ] + } ] }, - "tags": { "$ref": "tags.json" }, + "tags": { + "$ref": "tags.json" + }, "tags_count": { "type": "integer" } }, "additionalProperties": false -} +} \ No newline at end of file diff --git a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_full_syntax.json b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_full_syntax.json index a74b557dabe..145cc476d64 100644 --- a/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_full_syntax.json +++ b/spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_full_syntax.json @@ -2,12 +2,21 @@ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "required": [ - "type", "options" + "type", + "options" ], "properties": { - "type": { "enum": "metric_label_values" }, - "label": { "type": "string" }, - "options": { "$ref": "spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_options.json" } + "type": { + "enum": [ + "metric_label_values" + ] + }, + "label": { + "type": "string" + }, + "options": { + "$ref": "spec/fixtures/lib/gitlab/metrics/dashboard/schemas/metric_label_values_variable_options.json" + } }, "additionalProperties": false -} +} \ No newline at end of file diff --git a/spec/requests/api/graphql/ci/runner_spec.rb b/spec/requests/api/graphql/ci/runner_spec.rb index 2e840096814..b175ccf4c6f 100644 --- a/spec/requests/api/graphql/ci/runner_spec.rb +++ b/spec/requests/api/graphql/ci/runner_spec.rb @@ -232,6 +232,47 @@ RSpec.describe 'Query.runner(id)', feature_category: :runner_fleet do end end + describe 'jobCount' do + let_it_be(:pipeline1) { create(:ci_pipeline, project: project1) } + let_it_be(:pipeline2) { create(:ci_pipeline, project: project1) } + let_it_be(:build1) { create(:ci_build, :running, runner: active_project_runner, pipeline: pipeline1) } + let_it_be(:build2) { create(:ci_build, :running, runner: active_project_runner, pipeline: pipeline2) } + + let(:runner_query_fragment) { 'id jobCount' } + let(:query) do + %( + query { + runner1: runner(id: "#{active_project_runner.to_global_id}") { #{runner_query_fragment} } + runner2: runner(id: "#{inactive_instance_runner.to_global_id}") { #{runner_query_fragment} } + } + ) + end + + it 'retrieves correct jobCount values' do + post_graphql(query, current_user: user) + + expect(graphql_data).to match a_hash_including( + 'runner1' => a_graphql_entity_for(active_project_runner, job_count: 2), + 'runner2' => a_graphql_entity_for(inactive_instance_runner, job_count: 0) + ) + end + + context 'when JOB_COUNT_LIMIT is in effect' do + before do + stub_const('Types::Ci::RunnerType::JOB_COUNT_LIMIT', 1) + end + + it 'retrieves correct capped jobCount values' do + post_graphql(query, current_user: user) + + expect(graphql_data).to match a_hash_including( + 'runner1' => a_graphql_entity_for(active_project_runner, job_count: 1), + 'runner2' => a_graphql_entity_for(inactive_instance_runner, job_count: 0) + ) + end + end + end + describe 'ownerProject' do let_it_be(:project2) { create(:project) } let_it_be(:runner1) { create(:ci_runner, :project, projects: [project2, project1]) } @@ -510,8 +551,8 @@ RSpec.describe 'Query.runner(id)', feature_category: :runner_fleet do let(:active_project_runner2) { create(:ci_runner, :project) } let(:active_group_runner2) { create(:ci_runner, :group) } - # Currently excluding known N+1 issues, see https://gitlab.com/gitlab-org/gitlab/-/issues/334759 - let(:excluded_fields) { %w[jobCount jobs groups projects ownerProject] } + # Exclude fields that are already hardcoded above + let(:excluded_fields) { %w[jobs groups projects ownerProject] } let(:single_query) do <<~QUERY diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index dc2f12628d0..23083203cfe 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -39,8 +39,6 @@ require 'test_prof/factory_default' require 'test_prof/factory_prof/nate_heckler' require 'parslet/rig/rspec' -warn_missing_feature_category = Gitlab::Utils.to_boolean(ENV['RSPEC_WARN_MISSING_FEATURE_CATEGORY'], default: true) - rspec_profiling_is_configured = ENV['RSPEC_PROFILING_POSTGRES_URL'].present? || ENV['RSPEC_PROFILING'] @@ -463,13 +461,6 @@ RSpec.configure do |config| config.before(:each, :js) do allow_any_instance_of(VersionCheck).to receive(:response).and_return({ "severity" => "success" }) end - - # Add warning for example missing feature_category - config.before do |example| - if warn_missing_feature_category && example.metadata[:feature_category].blank? && !ENV['CI'] - warn "Missing metadata feature_category: #{example.location} See https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#feature-category-metadata" - end - end end ActiveRecord::Migration.maintain_test_schema! diff --git a/spec/support/rspec.rb b/spec/support/rspec.rb index 71dfc3fd5a3..ff0b5bebe33 100644 --- a/spec/support/rspec.rb +++ b/spec/support/rspec.rb @@ -8,6 +8,8 @@ require_relative "helpers/stub_object_storage" require_relative "helpers/stub_env" require_relative "helpers/fast_rails_root" +require_relative "../../lib/gitlab/utils" + RSpec::Expectations.configuration.on_potential_false_positives = :raise RSpec.configure do |config| @@ -35,4 +37,13 @@ RSpec.configure do |config| config.include StubObjectStorage config.include StubENV config.include FastRailsRoot + + warn_missing_feature_category = Gitlab::Utils.to_boolean(ENV['RSPEC_WARN_MISSING_FEATURE_CATEGORY'], default: true) + + # Add warning for example missing feature_category + config.before do |example| + if warn_missing_feature_category && example.metadata[:feature_category].blank? && !ENV['CI'] + warn "Missing metadata feature_category: #{example.location} See https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#feature-category-metadata" + end + end end