Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove unused components was skipping schemas with a top-level allOf #1220

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jedelson-pagerduty
Copy link
Contributor

fixes #1209

What/Why/How?

Details #1209 but essentially a schema like:

Unused:
  allOf:
    - type: object
      properties:
        one:
          type: string
    - type: object
      properties:
        two:
          type: string

will never be removed

Testing

Added a unit test for this case. Have also tested this change on a real-world document with this situation.

Check yourself

  • Code is linted
  • Tested with redoc/reference-docs/workflows
  • All new/updated code is covered with tests

Security

  • Security impact of change has been considered
  • Code follows company security practices and guidelines

@jedelson-pagerduty jedelson-pagerduty requested a review from a team as a code owner August 8, 2023 12:37
@changeset-bot
Copy link

changeset-bot bot commented Aug 8, 2023

🦋 Changeset detected

Latest commit: 9277248

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@redocly/openapi-core Minor
@redocly/cli Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@jedelson-pagerduty jedelson-pagerduty force-pushed the issue/fix-removed-unused-components-skipping-allof branch from 805ff4a to 68b0861 Compare August 8, 2023 12:58
@jedelson-pagerduty jedelson-pagerduty force-pushed the issue/fix-removed-unused-components-skipping-allof branch 3 times, most recently from 718aa7b to 97c2c06 Compare August 8, 2023 14:37
@jedelson-pagerduty
Copy link
Contributor Author

@tatomyr I've updated the code to deal with using discriminator from a referenced allOf. Still not 100% sure this is case that drew the original concern.

I should still add a test for the rule change but I'm less familiar with how rules are tested (vs. decorators) but wanted to push this up to see if this was what you were referring to.

@jedelson-pagerduty jedelson-pagerduty force-pushed the issue/fix-removed-unused-components-skipping-allof branch 2 times, most recently from 6d34f79 to 069d3e7 Compare August 8, 2023 20:30
@jedelson-pagerduty
Copy link
Contributor Author

@tatomyr I've added the rule test. To summarize:

  • If an "allOf" schema references some other schema and that schema has a discriminator the "allOf" schema is considered used (even though it may not actually be used... it is potentially used). no-unused-components will not create an issue and remove-unused-components will not remove it.
  • If an "allOf" schema references some other schema and none of the referenced schemas have a discriminator, the "allOf" schema is considered used following the normal usage rules (i.e. is ref'd somewhere else).
  • If an "allOf" schema doesn't reference other schemas, the "allOf" schema is considered used following the normal usage rules (i.e. is ref'd somewhere else).

I believe this addresses the original FIXME.

@jedelson-pagerduty
Copy link
Contributor Author

Open questions:

  • Should this be a minor change instead of a patch?
  • Should I create two separate changeset files?

@tatomyr
Copy link
Contributor

tatomyr commented Aug 9, 2023

Should this be a minor change instead of a patch?
Should I create two separate changeset files?

Please use minor (replace the existing one).

@jedelson-pagerduty jedelson-pagerduty force-pushed the issue/fix-removed-unused-components-skipping-allof branch from 069d3e7 to a1ba2e7 Compare August 9, 2023 11:47
@jedelson-pagerduty
Copy link
Contributor Author

Please use minor (replace the existing one).

Done

@tatomyr tatomyr force-pushed the issue/fix-removed-unused-components-skipping-allof branch from a1ba2e7 to 8d96193 Compare August 15, 2023 09:23
@tatomyr tatomyr force-pushed the issue/fix-removed-unused-components-skipping-allof branch from 8d96193 to 9277248 Compare August 15, 2023 11:31
@adamaltman
Copy link
Member

adamaltman commented Aug 21, 2023

@tatomyr I'm curious why this is a minor instead of a patch? I thought a bug fix would be a patch? Is this bugfix not considered backwards compatible perhaps? (if not, wouldn't it require a major revision?)

@jedelson-pagerduty overall great contribution 🎉 . Thank you so much for your contribution.

@tatomyr
Copy link
Contributor

tatomyr commented Aug 21, 2023

@adamaltman perhaps we decided this is more of an improvement rather than a fix. I don’t recall the exact reason though.
@IgorKarpiuk could you take a look and finalise this once you’re done with the current release?

Copy link
Contributor

@tatomyr tatomyr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @jedelson-pagerduty! Sorry that the review took so long 😅

I believe your approach is correct. However, there are some corner cases when we are removing actually used components (which is worse than leaving unused ones). I found one. Do you see anything else? Maybe @lornajane has more to suggest?

location,
'schemas',
key.toString(),
schema.allOf && schema.allOf.some((v) => v.$ref && resolve(v).node?.discriminator)
Copy link
Contributor

@tatomyr tatomyr Sep 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid this won't work correctly with a transient allOf-discriminator pair. Consider this example:

openapi: '3.0.0'

components: 
  schemas: 
    BaseVehicle: 
      type: object
      description: Vehicle
      discriminator:
        propertyName: powerSource
      properties:
        powerSource:
          description: How is the vehicle powered.
          type: string
          example: pedaling

    Vehicle:
      allOf: 
        - $ref: "#/components/schemas/BaseVehicle"
        - type: object 
          properties:
            vehicleType:
              description: The type of vehicle.
              type: string
              example: bicycle

    PedaledVehicle:
      allOf:
        - $ref: "#/components/schemas/Vehicle"
        - type: object
          description: Pedaled Vehicle
          properties:
            range:
              description: The 95th percentile range of a trip in kilometers.
              type: integer
              example: 100

The PedaledVehicle will be considered unused despite Vehicle resolves to BaseVehicle which actually contains the discriminator. I'm not sure this is a common use case but technically it looks like a valid one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tatomyr Appreciate the feedback! And yes, I suppose that is valid in the general case.

I'm wondering if this is fruitless -- I am trying to apply a very strict definition of "used" that works for my use case (in this example, I would actually expect all those schemas to be removed) but wouldn't be generally applicable.

I can look at taking another run at this (although it might be a few days) but I am starting to think a different approach is necessary.

location,
'schemas',
key.toString(),
schema.allOf && schema.allOf.some((v) => v.$ref && resolve(v).node?.discriminator)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
schema.allOf && schema.allOf.some((v) => v.$ref && resolve(v).node?.discriminator)
schema.allOf?.some((v) => v.$ref && resolve(v).node?.discriminator)

'@redocly/cli': minor
---

Fixed an issue where remove-unused-components would not remove schemas which had a top-level allOf and improved detection of unused schemas in no-unused-components rule.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you rephrase the description so it emphasises the improvement rather than the fix?

@tatomyr
Copy link
Contributor

tatomyr commented Nov 22, 2023

@jedelson-pagerduty do you have any updates on this?

FYI we've recently moved the remove-unused-components decorator, so that's why this MR got the conflicts 😅.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

remove-unused-components skips schemas that have a top-level allOf
3 participants