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

JHipster mvnw verify fails due to an infinite loop (due to circular relationships) in the test generated entity code. #19801

Closed
1 task done
naris opened this issue Sep 21, 2022 · 13 comments · Fixed by #24746

Comments

@naris
Copy link
Contributor

naris commented Sep 21, 2022

Overview of the issue

I have a project with entities with relationships that refer to each other. There is an UPC Entity with a ManyToOne relationship with a Platform entity with a ManytoOne relationship to a Category entity.

The generated test code has a CategoryResourceIT class with this getAllCategoriesByPlatformIsEqualToSomething() method:

    @Test
    @Transactional
    void getAllCategoriesByPlatformIsEqualToSomething() throws Exception {
        // Initialize the database
        categoryRepository.saveAndFlush(category);
        Platform platform;
        if (TestUtil.findAll(em, Platform.class).isEmpty()) {
            platform = PlatformResourceIT.createEntity(em);
            em.persist(platform);
            em.flush();
        } else {
            platform = TestUtil.findAll(em, Platform.class).get(0);
        }
        em.persist(platform);
        em.flush();
        category.addPlatform(platform);
        categoryRepository.saveAndFlush(category);
        Long platformId = platform.getId();

        // Get all the categoryList where platform equals to platformId
        defaultCategoryShouldBeFound("platformId.equals=" + platformId);

        // Get all the categoryList where platform equals to (platformId + 1)
        defaultCategoryShouldNotBeFound("platformId.equals=" + (platformId + 1));
    }

which has a call to platform = PlatformResourceIT.createEntity(em) which is here:

    /**
     * Create an entity for this test.
     *
     * This is a static method, as tests for other entities might also need it,
     * if they test an entity which requires the current entity.
     */
    public static Platform createEntity(EntityManager em) {
        Platform platform = new Platform()
            .primarySymbol(DEFAULT_PRIMARY_SYMBOL)
            .fieldName(DEFAULT_FIELD_NAME)
            .fieldDescription(DEFAULT_FIELD_DESCRIPTION)
            .fieldLength(DEFAULT_FIELD_LENGTH)
            .fieldValue(DEFAULT_FIELD_VALUE)
            .inUse(DEFAULT_IN_USE)
            .premiumField(DEFAULT_PREMIUM_FIELD)
            .approvalRequired(DEFAULT_APPROVAL_REQUIRED)
            .token(DEFAULT_TOKEN)
            .sasKey(DEFAULT_SAS_KEY)
            .rateId(DEFAULT_RATE_ID)
            .countType(DEFAULT_COUNT_TYPE)
            .caseable(DEFAULT_CASEABLE)
            .sanRequired(DEFAULT_SAN_REQUIRED)
            .waiverRequired(DEFAULT_WAIVER_REQUIRED)
            .createUser(DEFAULT_CREATE_USER)
            .createDate(DEFAULT_CREATE_DATE)
            .modifyUser(DEFAULT_MODIFY_USER)
            .modifyDate(DEFAULT_MODIFY_DATE);
        // Add required entity
        FieldValue fieldValue;
        if (TestUtil.findAll(em, FieldValue.class).isEmpty()) {
            fieldValue = FieldValueResourceIT.createEntity(em);
            em.persist(fieldValue);
            em.flush();
        } else {
            fieldValue = TestUtil.findAll(em, FieldValue.class).get(0);
        }
        platform.getValues().add(fieldValue);
        // Add required entity
        UPC uPC;
        if (TestUtil.findAll(em, UPC.class).isEmpty()) {
            uPC = UPCResourceIT.createEntity(em);
            em.persist(uPC);
            em.flush();
        } else {
            uPC = TestUtil.findAll(em, UPC.class).get(0);
        }
        platform.setUpc(uPC);
        return platform;
    }

Which calls UPCResourceIT.createEntity(em) which had already been called and starts a infinite loop or circular references that continues until there is a stack overflow :(

    /**
     * Create an entity for this test.
     *
     * This is a static method, as tests for other entities might also need it,
     * if they test an entity which requires the current entity.
     */
    public static UPC createEntity(EntityManager em) {
        UPC uPC = new UPC()
            .upcKey(DEFAULT_UPC_KEY)
            .name(DEFAULT_NAME)
            .description(DEFAULT_DESCRIPTION)
            .dataSource(DEFAULT_DATA_SOURCE)
            .keywords(DEFAULT_KEYWORDS)
            .userNotes(DEFAULT_USER_NOTES)
            .restrictedResellerFlag(DEFAULT_RESTRICTED_RESELLER_FLAG)
            .hidden(DEFAULT_HIDDEN)
            .createUser(DEFAULT_CREATE_USER)
            .createDate(DEFAULT_CREATE_DATE)
            .modifyUser(DEFAULT_MODIFY_USER)
            .modifyDate(DEFAULT_MODIFY_DATE);
        // Add required entity
        Platform platform;
        if (TestUtil.findAll(em, Platform.class).isEmpty()) {
            platform = PlatformResourceIT.createEntity(em);
            em.persist(platform);
            em.flush();
        } else {
            platform = TestUtil.findAll(em, Platform.class).get(0);
        }
        uPC.getPlatforms().add(platform);
        // Add required entity
        Attribute attribute;
        if (TestUtil.findAll(em, Attribute.class).isEmpty()) {
            attribute = AttributeResourceIT.createEntity(em);
            em.persist(attribute);
            em.flush();
        } else {
            attribute = TestUtil.findAll(em, Attribute.class).get(0);
        }
        uPC.setAttribute(attribute);
        // Add required entity
        Category category;
        if (TestUtil.findAll(em, Category.class).isEmpty()) {
            category = CategoryResourceIT.createEntity(em);
            em.persist(category);
            em.flush();
        } else {
            category = TestUtil.findAll(em, Category.class).get(0);
        }
        uPC.setCategory(category);
        return uPC;
    }
Motivation for or Use Case

Running ./mvnw verify on a newly generated project, with no changes whosoever, should not ever fail.

Reproduce the error

Generate a jhipster project. Generate entities with the JDL shown below. run ./mvnw verify

Related issues

#19800

Suggest a Fix

I am still researching this issue, I have do not have a fix at this time.

JHipster Version(s)

7.8.1, but this applies to all versions of jhipster.

JHipster configuration

JDL definitions
@filter
@paginate(pagination)
entity UPC {
    upcKey String maxlength(15)
    name String maxlength(250) required
    description String maxlength(1024)
    dataSource TextBlob
    keywords TextBlob
    userNotes TextBlob
    restrictedResellerFlag Boolean
    hidden Boolean
    createUser String required
    createDate Date required
    modifyUser String
    modifyDate Date
}

@filter
@paginate(pagination)
entity UPCRule {
ruleText TextBlob required
ruleDate Date required
createUser String
createDate Date
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity PrivateNotes {
noteText TextBlob required
noteDate Date required
createUser String
createDate Date
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity PlatformType {
name String maxlength(10) required
description String
}

@filter
@paginate(pagination)
entity Platform {
primarySymbol String maxlength(128) required
fieldName String maxlength(250) required
fieldDescription String maxlength(1024)
fieldLength Integer
fieldValue String maxlength(100)
inUse Boolean
premiumField Boolean
approvalRequired Boolean
token String maxlength(50)
sasKey String maxlength(10)
rateId String maxlength(10)
countType String maxlength(1)
caseable Boolean
sanRequired Boolean
waiverRequired Boolean
createUser String
createDate Date
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity PlatformDE {
ecapsKey Integer
defaultValue String maxlength(10)
usedInBilling Boolean
displayZeroCounts Boolean
areaFillinRequired Boolean
omniKvp String maxlength(30)
createUser String
createDate Date
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity PlatformInst {
pricingFlag Boolean
selectFlag Boolean
outputFlag Boolean
crosstabFlag Boolean
omniKvp String maxlength(30)
createUser String
createDate Date
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity PlatformList {
pricingFlag Boolean
selectFlag Boolean
outputFlag Boolean
crosstabFlag Boolean
createUser String
createDate Date
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity Product {
name String
description String
productKey Integer min(0) max(999)
createUser String
createDate Date
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity Release {
version String
releaseDate Date
}

@filter
@paginate(pagination)
entity Dimension {
name String maxlength(128) required
description String
createUser String required
createDate Date required
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity Category {
name String maxlength(128) required
createUser String required
createDate Date required
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity Universe {
code String maxlength(10) required
name String maxlength(128) required
}

@filter
@paginate(pagination)
entity Attribute {
fieldLevel String maxlength(128)
createUser String required
createDate Date required
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity Section {
sectionKey String maxlength(10) required
name String maxlength(128) required
selfReported Boolean
modeled Boolean
thirdParty Boolean
areaLevel Boolean
compiled Boolean
updatedDaily Boolean
updatedWeekly Boolean
updatedBiWeeekly Boolean
updatedMonthly Boolean
updatedSixWeeeks Boolean
updatedQuatrerly Boolean
updatedSemiAnnually Boolean
createUser String
createDate Date
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity FieldValue {
fieldValue String maxlength(25) required
valueDefinition String
averageMatchRate Float min(0) max(100)
displayOrder Integer
activeFlag Boolean
createUser String
createDate Date
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity Task {
name String required
taskUser String maxlength(25) required
taskOrder Integer
showOnMainPage Boolean
createUser String
createDate Date
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity Step {
completed Boolean
notes TextBlob
createUser String
createDate Date
modifyUser String
modifyDate Date
}

@filter
@paginate(pagination)
entity ProtectedClass {
code Integer min(0) max(9) required
name String maxlength(128)
description String maxlength(1024)
}

@filter
@paginate(pagination)
entity Derivation {
code String maxlength(10) required
name String maxlength(128)
description String maxlength(1024)
}

@filter
@paginate(pagination)
entity SourceType {
code String maxlength(10) required
name String maxlength(128)
description String maxlength(1024)
}

@filter
@paginate(pagination)
entity EpsilonDataSource {
name String maxlength(128)
}

relationship OneToOne {
PlatformDE{platform} to Platform{de}
PlatformInst{platform} to Platform{install}
PlatformList{platform} to Platform{list}
}

relationship ManyToOne {
UPC{attribute required} to Attribute
UPC{category required} to Category
UPC{protectedClass} to ProtectedClass
UPC{epsilonDataSource} to EpsilonDataSource
PlatformDE{section} to Section
Platform{release} to Release
Platform{category} to Category{platform}
Platform{platformType} to PlatformType
Product{platformType} to PlatformType
Dimension{universe} to Universe
Step{task} to Task
}

relationship OneToMany {
UPC{rules} to UPCRule{upc required}
UPC{privateNotes} to PrivateNotes{upc required}
UPC{platforms required} to Platform{upc required}
Platform{values required} to FieldValue
Dimension{categories required} to Category
UPC{steps} to Step
}

relationship ManyToMany {
UPC{sourceType} to SourceType{upc}
Platform{product} to Product{platform}
Platform{derivation} to Derivation{platform}
}

Entity configuration(s) entityName.json files generated in the .jhipster directory
JHipster Version(s)
JHipster configuration, a .yo-rc.json file generated in the root folder
.yo-rc.json file
{
  "generator-jhipster": {
    "applicationType": "monolith",
    "authenticationType": "oauth2",
    "baseName": "TotalFact",
    "blueprints": [
    ],
    "buildTool": "maven",
    "cacheProvider": "infinispan",
    "clientFramework": "angularX",
    "clientPackageManager": "npm",
    "clientTheme": "none",
    "clientThemeVariant": "",
    "creationTimestamp": 1651244671759,
    "databaseType": "sql",
    "devDatabaseType": "postgresql",
    "dtoSuffix": "DTO",
    "enableGradleEnterprise": false,
    "enableHibernateCache": true,
    "enableSwaggerCodegen": true,
    "enableTranslation": true,
    "entities": [
      "UPC",
      "UPCRule",
      "PlatformType",
      "Platform",
      "PlatformDE",
      "PlatformInst",
      "PlatformList",
      "Product",
      "Release",
      "Dimension",
      "Category",
      "Attribute",
      "Section",
      "FieldValue",
      "Task",
      "Step",
      "PrivateNotes",
      "ProtectedClass",
      "Derivation",
      "SourceType",
      "Universe",
      "EpsilonDataSource",
      "Usage"
    ],
    "entitySuffix": "",
    "incrementalChangelog": true,
    "jhiPrefix": "jhi",
    "jhipsterVersion": "7.9.4",
    "languages": ["en"],
    "lastLiquibaseTimestamp": 1698155334000,
    "messageBroker": false,
    "nativeLanguage": "en",
    "otherModules": [
    ],
    "packageFolder": "com/epsilon/totalfact",
    "packageName": "com.epsilon.totalfact",
    "pages": [],
    "prodDatabaseType": "postgresql",
    "reactive": false,
    "searchEngine": false,
    "serverPort": "8080",
    "serverSideOptions": ["enableSwaggerCodegen:true"],
    "serviceDiscoveryType": false,
    "skipCheckLengthOfIdentifier": false,
    "skipClient": false,
    "skipFakeData": false,
    "skipServer": false,
    "skipUserManagement": true,
    "testFrameworks": ["gatling"],
    "websocket": false,
    "withAdminUi": true
  }
}
JDL for the Entity configuration(s) entityName.json files generated in the .jhipster directory
JDL entity definitions
entity UPC {
  upcKey String maxlength(15)
  name String maxlength(250) required
  description String maxlength(1024)
  dataSource TextBlob
  keywords TextBlob
  userNotes TextBlob
  restrictedResellerFlag Boolean
  hidden Boolean
  createUser String required
  createDate Instant required
  modifyUser String
  modifyDate Instant
}
entity UPCRule {
  ruleText TextBlob required
  ruleDate Instant required
  createUser String
  createDate Instant
  modifyUser String
  modifyDate Instant
}
entity PlatformType {
  name String maxlength(10) required
  description String
}
entity Platform {
  primarySymbol String maxlength(128) required
  fieldName String maxlength(250) required
  fieldDescription String maxlength(1024)
  fieldLength Integer
  fieldValue String maxlength(100)
  shortHeaderName String maxlength(10)
  longHeaderName String maxlength(200)
  inUse Boolean
  premiumField Boolean
  approvalRequired Boolean
  royalty Boolean
  token String maxlength(50)
  sasKey String maxlength(10)
  rateId String maxlength(10)
  countType String maxlength(1)
  kvp String maxlength(50)
  caseable Boolean
  sanRequired Boolean
  waiverRequired Boolean
  createUser String
  createDate Instant
  modifyUser String
  modifyDate Instant
}
entity PlatformDE {
  ecapsKey Integer
  defaultValue String maxlength(10)
  usedInBilling Boolean
  displayZeroCounts Boolean
  areaFillinRequired Boolean
  createUser String
  createDate Instant
  modifyUser String
  modifyDate Instant
}
entity PlatformInst {
  pricingFlag Boolean
  selectFlag Boolean
  outputFlag Boolean
  crosstabFlag Boolean
  createUser String
  createDate Instant
  modifyUser String
  modifyDate Instant
}
entity PlatformList {
  pricingFlag Boolean
  selectFlag Boolean
  outputFlag Boolean
  crosstabFlag Boolean
  createUser String
  createDate Instant
  modifyUser String
  modifyDate Instant
}
entity Product {
  name String
  description String
  productKey Integer min(0) max(999)
  createUser String
  createDate Instant
  modifyUser String
  modifyDate Instant
}
entity Release {
  version String
  releaseDate Instant
}
entity Dimension {
  name String maxlength(128) required
  description String
  createUser String required
  createDate Instant required
  modifyUser String
  modifyDate Instant
}
entity Category {
  name String maxlength(128) required
  createUser String required
  createDate Instant required
  modifyUser String
  modifyDate Instant
}
entity Attribute {
  fieldLevel String maxlength(128)
  createUser String required
  createDate Instant required
  modifyUser String
  modifyDate Instant
}
entity Section {
  sectionKey String maxlength(10) required
  name String maxlength(128) required
  selfReported Boolean
  modeled Boolean
  thirdParty Boolean
  areaLevel Boolean
  compiled Boolean
  updatedDaily Boolean
  updatedWeekly Boolean
  updatedBiWeeekly Boolean
  updatedMonthly Boolean
  updatedSixWeeeks Boolean
  updatedQuatrerly Boolean
  updatedSemiAnnually Boolean
  createUser String
  createDate Instant
  modifyUser String
  modifyDate Instant
}
entity FieldValue {
  fieldValue String maxlength(25) required
  valueDefinition String
  averageMatchRate Float min(0) max(100)
  displayOrder Integer
  activeFlag Boolean
  createUser String
  createDate Instant
  modifyUser String
  modifyDate Instant
}
entity Task {
  name String required
  taskUser String maxlength(25) required
  taskOrder Integer
  showOnMainPage Boolean
  createUser String
  createDate Instant
  modifyUser String
  modifyDate Instant
}
entity Step {
  completed Boolean
  notes TextBlob
  createUser String
  createDate Instant
  modifyUser String
  modifyDate Instant
}
entity PrivateNotes {
  noteText TextBlob
  noteDate Instant required
  createUser String
  createDate Instant
  modifyUser String
  modifyDate Instant
}
entity ProtectedClass {
  code Integer min(0) max(9) required
  name String maxlength(128)
  description String maxlength(1024)
}
entity Derivation {
  code String maxlength(10) required
  name String maxlength(128)
  description String maxlength(1024)
}
entity SourceType {
  code String maxlength(10) required
  name String maxlength(128)
  description String maxlength(1024)
}
entity Universe {
  code String maxlength(10) required
  name String maxlength(128) required
}
entity EpsilonDataSource {
  name String maxlength(128)
}
entity Usage (jhi_usage) {
  action String required
  parm String
  user String maxlength(25) required
  dateTime Instant required
}
relationship OneToOne {
  PlatformDE{platform} to Platform{de}
  PlatformInst{platform} to Platform{install}
  PlatformList{platform} to Platform{list}
}
relationship OneToMany {
  UPC{rules} to UPCRule{upc required}
  Category{platform} to Platform{category}
  UPC{platforms required} to Platform{upc required}
  Dimension{categories required} to Category{dimension}
  Platform{values required} to FieldValue{platform}
  UPC{steps} to Step{uPC}
  UPC{privateNotes} to PrivateNotes{upc required}
}
relationship ManyToOne {
  UPC{attribute required} to Attribute
  UPC{category required} to Category
  UPC{protectedClass} to ProtectedClass
  UPC{epsilonDataSource} to EpsilonDataSource
  Platform{release} to Release
  Platform{platformType} to PlatformType
  PlatformDE{section} to Section
  Product{platformType} to PlatformType
  Dimension{universe} to Universe
  Step{task} to Task
}
relationship ManyToMany {
  UPC{sourceType} to SourceType{upc}
  UPC{derivation} to Derivation{upc}
  Platform{product} to Product{platform}
}

paginate UPC, UPCRule, PlatformType, Platform, PlatformDE, PlatformInst, PlatformList, Product, Release, Dimension, Category, Attribute, Section, FieldValue, Task, Step, PrivateNotes, ProtectedClass, Derivation, SourceType, Universe, EpsilonDataSource, Usage with pagination
service UPC, UPCRule, PlatformType, Platform, PlatformDE, PlatformInst, PlatformList, Product, Release, Dimension, Category, Attribute, Section, FieldValue, Task, Step, PrivateNotes, ProtectedClass, Derivation, SourceType, Universe, EpsilonDataSource, Usage with serviceClass
filter UPC, UPCRule, PlatformType, Platform, PlatformDE, PlatformInst, PlatformList, Product, Release, Dimension, Category, Attribute, Section, FieldValue, Task, Step, PrivateNotes, ProtectedClass, Derivation, SourceType, Universe, EpsilonDataSource, Usage

Environment and Tools

openjdk version "17.0.6" 2023-01-17 LTS
OpenJDK Runtime Environment Microsoft-7209853 (build 17.0.6+10-LTS)
OpenJDK 64-Bit Server VM Microsoft-7209853 (build 17.0.6+10-LTS, mixed mode, sharing)

git version 2.40.1.windows.1

node: v16.8.0

npm: 7.21.0

Browsers and Operating System

Windows, Edge

  • Checking this box is mandatory (this is just to show you read everything)
Copy link
Contributor

This issue is stale because it has been open for too long without any activity.
Due to the moving nature of jhipster generated application, bugs can become invalid.
If this issue still applies please comment otherwise it will be closed in 7 days

@naris
Copy link
Contributor Author

naris commented Jan 3, 2024

Yes, this issue still applies and is still a problem

@mshima
Copy link
Member

mshima commented Jan 3, 2024

@naris please add a jhipster info output to the issue description so we can reproduce and use automated checks.

@naris
Copy link
Contributor Author

naris commented Jan 3, 2024

@mshima I have added the resilts of jhipster info to the description.
However, this happens with EVERY VERSION of jhipster.
If you have tables the refer to each other, the generated tests will fail or spin forever with infinite loops, especially if there are circular references where table a refers to table b which refers to table c which refers to table a or something similar.

Copy link
Contributor

github-actions bot commented Jan 3, 2024

JHipster has completed the sample check
.yo-rc.json: valid
Entities JDL: valid
Application: successfully generated
Frontend check: success
Backend check: failure
E2E check: success

This check uses jhipster info output from the issue description to generate the sample.
Bug report that does not contain this information will be marked as invalid.

@naris
Copy link
Contributor Author

naris commented Jan 3, 2024

@mshima , We use the generator-jhipster-primeng-blueprint blueprint, which the automated sample check complains about (Indeed I always have to use --skip-checks). However, that blueprint does not affect the backend tests this issue is about.

@naris
Copy link
Contributor Author

naris commented Jan 3, 2024

I have removed the blueprint from the jhipster info in the issue description

@mshima
Copy link
Member

mshima commented Jan 3, 2024

Blueprints should be disabled at checks.
Handled by #24737.

@mshima
Copy link
Member

mshima commented Jan 3, 2024

If a circular dependency with all required relationship is found. Every entity cannot be tested without bootstrapping the database.

At cypress if entity A has a required relationship with entity B and entity b has a required relationship with entity C the entity A test is skipped.
And only required relationships are tested.

I don’t recall much about junit behavior with relationships.

@naris
Copy link
Contributor Author

naris commented Jan 3, 2024

An example. There are 2 entities in the JDL above, UPC & Platform that have a OneToMany relationship ( UPC{platforms required} to Platform{upc required}).

The generated test code for UPC has a method called createEntity that calls Platform.createEntity() that calls UPC.createEntity() which then goes into an infinite loop with only 2 tables with a ManyToOne relationship

Here is an example of the generated test code in which I have had to comment out all the tests that produce infinite loops (even though there aren't any circular references -- I don't actually have any circular references)
example_tests.zip

@mshima
Copy link
Member

mshima commented Jan 4, 2024

I’ve switched to PostgreSQL due to missing testcontainer support with oracle.
I think it’s possible to add testcontainer to oracle https://java.testcontainers.org/modules/databases/oraclexe.

@naris
Copy link
Contributor Author

naris commented Jan 4, 2024

I’ve switched to PostgreSQL due to missing testcontainer support with oracle. I think it’s possible to add testcontainer to oracle https://java.testcontainers.org/modules/databases/oraclexe.

I can't use containers as my company won't license docker for my team.

Also, my project has some native sql queries that require oracle specific functions (listagg() & dbms_lob.substr()) which would make using another DB for testing problematic.

However, yeah -- those are my problems and the issue is really generic and not specific to my use case so you should indeed use another DB and/or the oracle testcontainer

@mshima
Copy link
Member

mshima commented Jan 4, 2024

CI confirmed the bug with the provided sample.
We should fix the cyclic issue by skipping tests at affected entities and relationships.

@deepu105 deepu105 added this to the 8.2.0 milestone Mar 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants