Improve schema matcher to display errors
What does this MR do and why?
This MR improves schema matcher to display errors. See before/after below.
This MR also fixes JSON schema public_api/v4/merge_request.json
.
Prior this commit this schema expected an optional property named
properties
.
This commit:
- remove nested
properties
- references milestone schema for property
milestone
- references user basic schema for property
assignees
Refs !79409 (diffs, comment 829327771)
Follow-ups
#351777 (closed) and https://gitlab.com/gitlab-org/gitlab/-/issues/351904 track how to prevent future cases like these.
Screenshots or screen recordings
Before
Failures:
1) API::MergeRequests GET /projects/:id/merge_requests/:merge_request_iid matches json schema
Failure/Error: expect(response).to match_response_schema('public_api/v4/merge_request')
expected #<ActionDispatch::TestResponse:0x000056540647bc28 @mon_data=#<Monitor:0x000056540647ba98>, @mon_data_...w.example.com/api/v4/projects/1/merge_requests/1?private_token=yLENozMxcDy_BtwohpsT" for 127.0.0.1>> to match response schema "public_api/v4/merge_request"
# ./spec/requests/api/merge_requests_spec.rb:1193:in `block (3 levels) in <top (required)>'
# ./spec/spec_helper.rb:408:in `block (3 levels) in <top (required)>'
# ./spec/support/sidekiq_middleware.rb:9:in `with_sidekiq_server_middleware'
# ./spec/spec_helper.rb:399:in `block (2 levels) in <top (required)>'
# ./spec/spec_helper.rb:395:in `block (3 levels) in <top (required)>'
# ./lib/gitlab/application_context.rb:31:in `with_raw_context'
# ./spec/spec_helper.rb:395:in `block (2 levels) in <top (required)>'
# ./spec/support/system_exit_detected.rb:7:in `block (2 levels) in <main>'
# ./spec/support/database/prevent_cross_joins.rb:106:in `block (3 levels) in <main>'
# ./spec/support/database/prevent_cross_joins.rb:60:in `with_cross_joins_prevented'
# ./spec/support/database/prevent_cross_joins.rb:106:in `block (2 levels) in <main>'
Finished in 1 minute 1.58 seconds (files took 1 minute 0.97 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/requests/api/merge_requests_spec.rb:1188 # API::MergeRequests GET /projects/:id/merge_requests/:merge_request_iid matches json schema
After
1) API::MergeRequests GET /projects/:id/merge_requests/:merge_request_iid matches json schema
Failure/Error: expect(response).to match_response_schema('public_api/v4/merge_request')
expected JSON response to match schema #<Pathname:/home/peter/devel/gitlab/gdk-ee/gitlab/ee/spec/fixtures/api/schemas/public_api/v4/merge_request.json>.
JSON input: {
"id": 5,
"iid": 1,
"project_id": 5,
"title": "Test",
"description": null,
"state": "opened",
"created_at": "2022-02-04T14:16:46.056Z",
"updated_at": "2022-02-04T14:16:53.018Z",
"merged_by": null,
"merge_user": null,
"merged_at": null,
"closed_by": null,
"closed_at": null,
"target_branch": "feature",
"source_branch": "master",
"user_notes_count": 0,
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 13,
"username": "user1",
"name": "Sidney Jones2",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/10fc7f102be8de7657fb4d80898bbfe3?s=80&d=identicon",
"web_url": "http://localhost/user1"
},
"assignees": [
{
"id": 13,
"username": "user1",
"name": "Sidney Jones2",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/10fc7f102be8de7657fb4d80898bbfe3?s=80&d=identicon",
"web_url": "http://localhost/user1"
}
],
"assignee": {
"id": 13,
"username": "user1",
"name": "Sidney Jones2",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/10fc7f102be8de7657fb4d80898bbfe3?s=80&d=identicon",
"web_url": "http://localhost/user1"
},
"reviewers": [
],
"source_project_id": 5,
"target_project_id": 5,
"labels": [
],
"draft": false,
"work_in_progress": false,
"milestone": {
"id": 5,
"iid": 1,
"project_id": 5,
"title": "0.9",
"description": null,
"state": "active",
"created_at": "2022-02-04T14:16:52.461Z",
"updated_at": "2022-02-04T14:16:52.461Z",
"due_date": null,
"start_date": null,
"expired": null,
"web_url": "http://localhost/user1/project1/-/milestones/1"
},
"merge_when_pipeline_succeeds": false,
"merge_status": "can_be_merged",
"sha": "b83d6e391c22777fca1ed3012fce84f633d7fed0",
"merge_commit_sha": null,
"squash_commit_sha": null,
"discussion_locked": null,
"should_remove_source_branch": null,
"force_remove_source_branch": null,
"reference": "!1",
"references": {
"short": "!1",
"relative": "!1",
"full": "user1/project1!1"
},
"web_url": "http://localhost/user1/project1/-/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
},
"squash": false,
"task_completion_status": {
"count": 0,
"completed_count": 0
},
"has_conflicts": false,
"blocking_discussions_resolved": true,
"approvals_before_merge": null,
"subscribed": true,
"changes_count": "20",
"latest_build_started_at": null,
"latest_build_finished_at": null,
"first_deployed_to_production_at": null,
"pipeline": null,
"head_pipeline": {
"id": 5,
"iid": 1,
"project_id": 5,
"sha": "b83d6e391c22777fca1ed3012fce84f633d7fed0",
"ref": "master",
"status": "success",
"source": "push",
"created_at": "2022-02-04T14:16:52.917Z",
"updated_at": "2022-02-04T14:16:52.917Z",
"web_url": "http://localhost/user1/project1/-/pipelines/5",
"before_sha": "0000000000000000000000000000000000000000",
"tag": false,
"yaml_errors": null,
"user": null,
"started_at": null,
"finished_at": null,
"committed_at": null,
"duration": null,
"queued_duration": null,
"coverage": null,
"detailed_status": {
"icon": "status_success",
"text": "passed",
"label": "passed",
"group": "success",
"tooltip": "passed",
"has_details": true,
"details_path": "/user1/project1/-/pipelines/5",
"illustration": null,
"favicon": "/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png"
}
},
"diff_refs": {
"base_sha": "ae73cb07c9eeaf35924a10f713b364d32b2dd34f",
"head_sha": "b83d6e391c22777fca1ed3012fce84f633d7fed0",
"start_sha": "0b4bc9a49b562e85de7cc9e834518ea6828729b9"
},
"merge_error": null,
"first_contribution": false,
"user": {
"can_merge": true
}
}
Schema errors:
Property: /assignees/0
Actual value: {
"id": 13,
"username": "user1",
"name": "Sidney Jones2",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/10fc7f102be8de7657fb4d80898bbfe3?s=80&d=identicon",
"web_url": "http://localhost/user1"
}
Error: property '/assignees/0' is missing required keys: iid, project_id, title, description, 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, squash
Property: /milestone/due_date
Actual value: null
Error: property '/milestone/due_date' is not of type: string
Property: /milestone/start_date
Actual value: null
Error: property '/milestone/start_date' is not of type: string
Property: /milestone/expired
Actual value: null
Error: property '/milestone/expired' is invalid: error_type=schema
Property: /milestone/web_url
Actual value: "http://localhost/user1/project1/-/milestones/1"
Error: property '/milestone/web_url' is invalid: error_type=schema
# ./spec/requests/api/merge_requests_spec.rb:1193:in `block (3 levels) in <main>'
# ./spec/spec_helper.rb:408:in `block (3 levels) in <main>'
# ./spec/support/sidekiq_middleware.rb:9:in `with_sidekiq_server_middleware'
# ./spec/spec_helper.rb:399:in `block (2 levels) in <main>'
# ./spec/spec_helper.rb:395:in `block (3 levels) in <main>'
# ./lib/gitlab/application_context.rb:31:in `with_raw_context'
# ./spec/spec_helper.rb:395:in `block (2 levels) in <main>'
# ./spec/support/system_exit_detected.rb:7:in `block (2 levels) in <main>'
# ./spec/support/database/prevent_cross_joins.rb:106:in `block (3 levels) in <main>'
# ./spec/support/database/prevent_cross_joins.rb:60:in `with_cross_joins_prevented'
# ./spec/support/database/prevent_cross_joins.rb:106:in `block (2 levels) in <main>'
# -e:1:in `<main>'
Finished in 22.38 seconds (files took 5.56 seconds to load)
1 example, 1 failure
How to set up and validate locally
Numbered steps to set up and validate the change are strongly suggested.
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.
Edited by Peter Leitzen