diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 8921e7112..1281acf0a 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -21,10 +21,9 @@ pr: variables: buildPlatform: 'Any CPU' buildConfiguration: 'Release' + NuGetOrganizationName: 'openapinet' + privateFeedBaseUrl: 'https://microsoftgraph.pkgs.visualstudio.com/0985d294-5762-4bc2-a565-161ef349ca3e/_packaging/GraphDeveloperExperiences_Public' ProductBinPath: '$(Build.SourcesDirectory)\src\Microsoft.OpenApi\bin\$(BuildConfiguration)' - REGISTRY: 'msgraphprodregistry.azurecr.io' - IMAGE_NAME: 'public/openapi/hidi' - PREVIEW_BRANCH: 'refs/heads/main' resources: repositories: @@ -51,10 +50,6 @@ extends: displayName: 'Publish Artifact: Nugets' artifactName: Nugets targetPath: '$(Build.ArtifactStagingDirectory)/Nugets' - - output: pipelineArtifact - displayName: 'Publish Artifact: RepoFiles' - artifactName: RepoFiles - targetPath: '$(Build.ArtifactStagingDirectory)/RepoFiles' steps: - task: UseDotNet@2 displayName: 'Use .NET 6' @@ -65,6 +60,11 @@ extends: displayName: 'Use .NET 8' inputs: version: 8.x + + - task: UseDotNet@2 + displayName: 'Use .NET 10' + inputs: + useGlobalJson: true # Install the nuget tool. - task: NuGetToolInstaller@1 @@ -74,21 +74,39 @@ extends: checkLatest: true # Build the Product project + - task: NuGetAuthenticate@1 + displayName: 'Authenticate to Azure Artifacts' + + - pwsh: | + @" + + + + + + + + "@ | Set-Content -Path "$(Build.SourcesDirectory)/nuget.config" -Encoding UTF8 + displayName: 'Create nuget.config (central feed)' - task: DotNetCoreCLI@2 displayName: 'build' inputs: - projects: '$(Build.SourcesDirectory)\Microsoft.OpenApi.sln' + projects: '$(Build.SourcesDirectory)\Microsoft.OpenApi.slnx' arguments: '--configuration $(BuildConfiguration) --no-incremental' # Run the Unit test - - task: DotNetCoreCLI@2 + - pwsh: | + dotnet test "$(Build.SourcesDirectory)\Microsoft.OpenApi.slnx" ` + --configuration $(BuildConfiguration) ` + --no-build ` + -- ` + --report-azdo ` + --publish-azdo-test-results ` + --results-directory="$(Agent.TempDirectory)\TestResults" ` + --minimum-expected-tests 1 displayName: 'test' - inputs: - command: test - projects: '$(Build.SourcesDirectory)\Microsoft.OpenApi.sln' - arguments: '--configuration $(BuildConfiguration) --no-build' - - task: EsrpCodeSigning@5 + - task: EsrpCodeSigning@6 displayName: 'ESRP CodeSigning binaries' inputs: ConnectedServiceName: 'Federated DevX ESRP Managed Identity Connection' @@ -150,11 +168,7 @@ extends: - pwsh: dotnet pack $(Build.SourcesDirectory)/src/Microsoft.OpenApi.YamlReader/Microsoft.OpenApi.YamlReader.csproj -o $(Build.ArtifactStagingDirectory) --configuration $(BuildConfiguration) --no-build --include-symbols --include-source /p:SymbolPackageFormat=snupkg displayName: 'pack YamlReader' - # Pack hidi - - pwsh: dotnet pack $(Build.SourcesDirectory)/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj -o $(Build.ArtifactStagingDirectory) --configuration $(BuildConfiguration) --no-build --include-symbols --include-source /p:SymbolPackageFormat=snupkg - displayName: 'pack Hidi' - - - task: EsrpCodeSigning@5 + - task: EsrpCodeSigning@6 displayName: 'ESRP CodeSigning Nuget Packages' inputs: ConnectedServiceName: 'Federated DevX ESRP Managed Identity Connection' @@ -188,68 +202,30 @@ extends: MaxRetryAttempts: '5' PendingAnalysisWaitTimeoutMinutes: '5' - # publish hidi as an .exe - - task: DotNetCoreCLI@2 - displayName: publish Hidi as executable - inputs: - command: 'publish' - arguments: -c Release --runtime win-x64 /p:PublishSingleFile=true /p:PackAsTool=false --self-contained --output $(Build.ArtifactStagingDirectory)/Microsoft.OpenApi.Hidi - projects: 'src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj' - publishWebProjects: False - zipAfterPublish: false - - task: CopyFiles@2 displayName: Prepare staging folder for upload inputs: targetFolder: $(Build.ArtifactStagingDirectory)/Nugets sourceFolder: $(Build.ArtifactStagingDirectory) - content: '*.nupkg' + Contents: | + *.nupkg + *.snupkg - # Copy repository files to be used in the deploy stage - task: CopyFiles@2 - displayName: 'Copy repository files for deploy stage' + displayName: 'Include version-check script in Nugets artifact' inputs: - SourceFolder: '$(Build.SourcesDirectory)' - Contents: | - **/* - !**/bin/** - !**/obj/** - !**/.git/** - TargetFolder: '$(Build.ArtifactStagingDirectory)/RepoFiles' + SourceFolder: '$(Build.SourcesDirectory)/scripts' + Contents: 'check-nuget-package-published.ps1' + TargetFolder: '$(Build.ArtifactStagingDirectory)/Nugets/scripts' - stage: deploy - condition: and(or(contains(variables['Build.SourceBranch'], 'refs/tags/v'), eq(variables['Build.SourceBranch'], variables['PREVIEW_BRANCH'])), succeeded()) + condition: and(contains(variables['Build.SourceBranch'], 'refs/tags/v'), succeeded()) dependsOn: build pool: name: Azure-Pipelines-1ESPT-ExDShared os: linux image: ubuntu-latest jobs: - - deployment: deploy_hidi - condition: and(contains(variables['build.SourceBranch'], 'refs/tags/v'), succeeded()) - templateContext: - type: releaseJob - isProduction: true - inputs: - - input: pipelineArtifact - artifactName: Nugets - targetPath: '$(Pipeline.Workspace)' - dependsOn: [] - environment: nuget-org - strategy: - runOnce: - deploy: - pool: - vmImage: ubuntu-latest - steps: - - task: 1ES.PublishNuget@1 - displayName: 'NuGet push' - inputs: - packagesToPush: '$(Pipeline.Workspace)/Microsoft.OpenApi.Hidi.*.nupkg' - packageParentPath: '$(Pipeline.Workspace)' - nuGetFeedType: external - publishFeedCredentials: 'OpenAPI Nuget Connection' - - deployment: deploy_lib condition: and(contains(variables['build.SourceBranch'], 'refs/tags/v'), succeeded()) templateContext: @@ -267,21 +243,47 @@ extends: pool: vmImage: ubuntu-latest steps: - - pwsh: | - $fileNames = "$(Pipeline.Workspace)/Microsoft.OpenApi.Hidi.*.nupkg", "$(Pipeline.Workspace)/Microsoft.OpenApi.YamlReader.*.nupkg", "$(Pipeline.Workspace)/Microsoft.OpenApi.Workbench.*.nupkg" - foreach($fileName in $fileNames) { - if(Test-Path $fileName) { - Remove-Item $fileName -Verbose - } - } - displayName: remove other nupkgs to avoid duplication - - task: 1ES.PublishNuget@1 - displayName: 'NuGet push' + - task: PowerShell@2 + displayName: 'Check whether NuGet package version already published (idempotent)' + inputs: + targetType: filePath + filePath: '$(Pipeline.Workspace)/scripts/check-nuget-package-published.ps1' + arguments: '-PackageId "Microsoft.OpenApi" -PackageDirectory "$(Pipeline.Workspace)" -NuGetServiceIndexUrl "$(privateFeedBaseUrl)/nuget/v3/index.json"' + pwsh: true + env: + FEED_ACCESS_TOKEN: $(System.AccessToken) + - task: CopyFiles@2 + displayName: 'Stage OpenAPI NuGet packages for ESRP release' + condition: and(succeeded(), ne(variables['nugetAlreadyPublished'], 'true')) + inputs: + SourceFolder: '$(Pipeline.Workspace)' + Contents: | + Microsoft.OpenApi.*.nupkg + Microsoft.OpenApi.*.snupkg + !Microsoft.OpenApi.YamlReader.* + TargetFolder: '$(Pipeline.Workspace)/nuget-packages/$(NuGetOrganizationName)/openapi' + CleanTargetFolder: true + - task: EsrpRelease@14 + displayName: 'ESRP Release - OpenAPI NuGet' + condition: and(succeeded(), ne(variables['nugetAlreadyPublished'], 'true')) inputs: - packagesToPush: '$(Pipeline.Workspace)/Microsoft.OpenApi.*.nupkg' - packageParentPath: '$(Pipeline.Workspace)' - nuGetFeedType: external - publishFeedCredentials: 'OpenAPI Nuget Connection' + connectedservicename: 'Federated DevX ESRP Managed Identity Connection' + usemanagedidentity: false + keyvaultname: 'akv-prod-eastus' + authcertname: 'ReferenceLibraryPrivateCert' + signcertname: 'ReferencePackagePublisherCertificate' + clientid: '65035b7f-7357-4f29-bf25-c5ee5c3949f8' + intent: 'packagedistribution' + contenttype: 'NuGet' + organizationname: '$(NuGetOrganizationName)' + contentsource: 'Folder' + folderlocation: '$(Pipeline.Workspace)/nuget-packages/$(NuGetOrganizationName)/openapi' + waitforreleasecompletion: true + owners: 'christiano@microsoft.com,ramsess@microsoft.com,gavinbarron@microsoft.com,jingjingjia@microsoft.com,peombwa@microsoft.com,treicys@microsoft.com' + approvers: 'christiano@microsoft.com,ramsess@microsoft.com,gavinbarron@microsoft.com,jingjingjia@microsoft.com,peombwa@microsoft.com,treicys@microsoft.com' + serviceendpointurl: 'https://api.esrp.microsoft.com/' + mainpublisher: 'ESRPRELPACMAN' + domaintenantid: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' - deployment: deploy_yaml_reader condition: and(contains(variables['build.SourceBranch'], 'refs/tags/v'), succeeded()) @@ -300,13 +302,46 @@ extends: pool: vmImage: ubuntu-latest steps: - - task: 1ES.PublishNuget@1 - displayName: 'NuGet push' + - task: PowerShell@2 + displayName: 'Check whether NuGet package version already published (idempotent)' inputs: - packagesToPush: '$(Pipeline.Workspace)/Microsoft.OpenApi.YamlReader.*.nupkg' - packageParentPath: '$(Pipeline.Workspace)' - nuGetFeedType: external - publishFeedCredentials: 'OpenAPI Nuget Connection' + targetType: filePath + filePath: '$(Pipeline.Workspace)/scripts/check-nuget-package-published.ps1' + arguments: '-PackageId "Microsoft.OpenApi.YamlReader" -PackageDirectory "$(Pipeline.Workspace)" -NuGetServiceIndexUrl "$(privateFeedBaseUrl)/nuget/v3/index.json"' + pwsh: true + env: + FEED_ACCESS_TOKEN: $(System.AccessToken) + - task: CopyFiles@2 + displayName: 'Stage YAML reader NuGet packages for ESRP release' + condition: and(succeeded(), ne(variables['nugetAlreadyPublished'], 'true')) + inputs: + SourceFolder: '$(Pipeline.Workspace)' + Contents: | + Microsoft.OpenApi.YamlReader.*.nupkg + Microsoft.OpenApi.YamlReader.*.snupkg + TargetFolder: '$(Pipeline.Workspace)/nuget-packages/$(NuGetOrganizationName)/yaml-reader' + CleanTargetFolder: true + - task: EsrpRelease@14 + displayName: 'ESRP Release - YAML reader NuGet' + condition: and(succeeded(), ne(variables['nugetAlreadyPublished'], 'true')) + inputs: + connectedservicename: 'Federated DevX ESRP Managed Identity Connection' + usemanagedidentity: false + keyvaultname: 'akv-prod-eastus' + authcertname: 'ReferenceLibraryPrivateCert' + signcertname: 'ReferencePackagePublisherCertificate' + clientid: '65035b7f-7357-4f29-bf25-c5ee5c3949f8' + intent: 'packagedistribution' + contenttype: 'NuGet' + organizationname: '$(NuGetOrganizationName)' + contentsource: 'Folder' + folderlocation: '$(Pipeline.Workspace)/nuget-packages/$(NuGetOrganizationName)/yaml-reader' + waitforreleasecompletion: true + owners: 'christiano@microsoft.com,ramsess@microsoft.com,gavinbarron@microsoft.com,jingjingjia@microsoft.com,peombwa@microsoft.com,treicys@microsoft.com' + approvers: 'christiano@microsoft.com,ramsess@microsoft.com,gavinbarron@microsoft.com,jingjingjia@microsoft.com,peombwa@microsoft.com,treicys@microsoft.com' + serviceendpointurl: 'https://api.esrp.microsoft.com/' + mainpublisher: 'ESRPRELPACMAN' + domaintenantid: 'cdc5aeea-15c5-4db6-b079-fcadd2505dc2' - deployment: create_github_release condition: and(contains(variables['build.SourceBranch'], 'refs/tags/v'), succeeded()) @@ -341,135 +376,8 @@ extends: tagSource: userSpecifiedTag tag: 'v$(artifactVersion)' releaseNotesSource: inline - assets: '$(Pipeline.Workspace)\**\*.exe' addChangeLog: false - - deployment: deploy_docker_image - environment: docker-images-deploy - templateContext: - type: releaseJob - isProduction: true - inputs: - - input: pipelineArtifact - artifactName: RepoFiles - targetPath: '$(Pipeline.Workspace)' - strategy: - runOnce: - deploy: - pool: - vmImage: 'ubuntu-latest' - steps: - - task: AzureCLI@2 - displayName: 'Login to Azure Container Registry' - inputs: - azureSubscription: 'ACR Images Push Service Connection' - scriptType: bash - scriptLocation: inlineScript - inlineScript: | - az acr login --name $(REGISTRY) - - - pwsh: | - $content = [XML](Get-Content $(Pipeline.Workspace)/Directory.Build.props) - Write-Host "XML loaded, finding version..." - - # Handle PropertyGroup as either a single element or array - $version = $null - if ($content.Project.PropertyGroup -is [array]) { - Write-Host "PropertyGroup is an array, checking each entry..." - foreach ($pg in $content.Project.PropertyGroup) { - if ($pg.Version) { - $version = $pg.Version.ToString().Trim() - Write-Host "Found version in PropertyGroup array: $version" - break - } - } - } else { - # Single PropertyGroup - $version = $content.Project.PropertyGroup.Version - if ($version) { - $version = $version.ToString().Trim() - Write-Host "Found version in PropertyGroup: $version" - } - } - - if (-not $version) { - Write-Host "##vso[task.logissue type=error]Version not found in Directory.Build.props" - exit 1 - } - - Write-Host "Version found: $version" - Write-Host "##vso[task.setvariable variable=version;isoutput=true]$version" - Write-Host "##vso[task.setvariable variable=VERSION]$version" - displayName: 'Get version from csproj' - name: getversion - - - bash: | - # Debug output to verify version variable - echo "Version from previous step: $VERSION" - displayName: 'Verify version variable' - - - bash: | - echo "Build Number: $(Build.BuildNumber)" - # Extract the last 3 characters for the run number - runnumber=$(echo "$(Build.BuildNumber)" | grep -o '[0-9]\+$') - echo "Extracted Run Number: $runnumber" - - # If extraction fails, set a default - if [ -z "$runnumber" ]; then - echo "Extraction failed, using default value" - runnumber=$(date +"%S%N" | cut -c1-3) - echo "Generated fallback run number: $runnumber" - fi - - # Set the variable for later steps - echo "##vso[task.setvariable variable=RUNNUMBER]$runnumber" - echo "##vso[task.setvariable variable=RUNNUMBER;isOutput=true]$runnumber" - displayName: 'Get truncated run number' - name: getrunnumber - condition: eq(variables['Build.SourceBranch'], variables['PREVIEW_BRANCH']) - - - bash: | - date=$(date +'%Y%m%d') - echo "Date value: $date" - echo "##vso[task.setvariable variable=BUILDDATE;isOutput=true]$date" - echo "##vso[task.setvariable variable=BUILDDATE]$date" - displayName: 'Get current date' - name: setdate - condition: eq(variables['Build.SourceBranch'], variables['PREVIEW_BRANCH']) - - - script: | - docker run --privileged --rm msgraphprodregistry.azurecr.io/tonistiigi/binfmt --install all - displayName: "Enable multi-platform builds" - - - script: | - docker buildx create --use --name mybuilder - displayName: "Set up Docker BuildX" - - - script: | - docker buildx inspect --bootstrap - displayName: "Ensure BuildX is working" - - - bash: | - echo "Building Docker image..." - echo "Using build date: ${BUILDDATE}" - # Using quotes around tags to prevent flag interpretation - docker buildx build \ - --platform linux/amd64,linux/arm64/v8 \ - --push \ - -t "$(REGISTRY)/$(IMAGE_NAME):nightly" \ - -t "$(REGISTRY)/$(IMAGE_NAME):${VERSION}.${BUILDDATE}${RUNNUMBER}" \ - "$(Pipeline.Workspace)" - - displayName: 'Build and Push Nightly Image' - condition: eq(variables['Build.SourceBranch'], variables['PREVIEW_BRANCH']) - - - bash: | - echo "Building Docker image for release..." - docker buildx build\ - --platform linux/amd64,linux/arm64/v8 \ - --push \ - -t "$(REGISTRY)/$(IMAGE_NAME):latest" \ - -t "$(REGISTRY)/$(IMAGE_NAME):${VERSION}" \ - "$(Pipeline.Workspace)" - displayName: 'Build and Push Release Image' - condition: contains(variables['Build.SourceBranch'], 'refs/tags/v') \ No newline at end of file +# once the nuget has been released, fill this form to get the public documentation updated. +# https://dev.azure.com/msft-skilling/Content/_workitems/create/User%20Story?templateId=39fb91e3-64a2-4c8a-83db-b2bdf3603dd3&ownerId=c4a28f90-17ae-4384-b514-7273392b082b +# https://learn.microsoft.com/en-us/dotnet/api/microsoft.openapi diff --git a/.config/1espt/PipelineAutobaseliningConfig.yml b/.config/1espt/PipelineAutobaseliningConfig.yml index a4d9608c6..37a1a42bd 100644 --- a/.config/1espt/PipelineAutobaseliningConfig.yml +++ b/.config/1espt/PipelineAutobaseliningConfig.yml @@ -8,15 +8,17 @@ pipelines: credscan: lastModifiedDate: 2024-09-13 eslint: - lastModifiedDate: 2024-09-13 + lastModifiedDate: 2026-05-13 psscriptanalyzer: - lastModifiedDate: 2024-09-13 + lastModifiedDate: 2026-05-13 armory: - lastModifiedDate: 2024-09-13 + lastModifiedDate: 2026-05-13 + accessibilityinsights: + lastModifiedDate: 2025-06-03 binary: credscan: - lastModifiedDate: 2025-01-27 + lastModifiedDate: 2025-01-28 binskim: - lastModifiedDate: 2025-01-27 + lastModifiedDate: 2026-05-13 spotbugs: - lastModifiedDate: 2025-01-27 + lastModifiedDate: 2026-05-13 diff --git a/.config/guardian/.gdnbaselines b/.config/guardian/.gdnbaselines new file mode 100644 index 000000000..5ed019a92 --- /dev/null +++ b/.config/guardian/.gdnbaselines @@ -0,0 +1,53 @@ +{ + "properties": { + "helpUri": "https://eng.ms/docs/microsoft-security/security/azure-security/cloudai-security-fundamentals-engineering/security-integration/guardian-wiki/microsoft-guardian/general/baselines" + }, + "version": "1.0.0", + "baselines": { + "default": { + "name": "default", + "createdDate": "2026-05-13 00:39:09Z", + "lastUpdatedDate": "2026-05-13 00:40:41Z" + } + }, + "results": { + "89411c6a070fd31f2836b38a16926ffbfb4882aff49c907cafe6c95dfba1104a": { + "signature": "89411c6a070fd31f2836b38a16926ffbfb4882aff49c907cafe6c95dfba1104a", + "alternativeSignatures": [ + "59104f1c3fec111fba3f6b5b6d2d37f3bc0d5267b425f82b8c3f852abc8b2b7a", + "4dee2b2a1887d7a952ae5c61e48c9b6f543096940991cdcd0209c60561a537ce", + "558e542a1dcc76100e4395b278f8b99f1dab960b2b3ae01a4c5cb84ac5cdc70f" + ], + "target": "src/Microsoft.OpenApi/Writers/SpecialCharacterStringExtensions.cs", + "line": 152, + "uriBaseId": "file:///D:/a/_work/1/s/", + "memberOf": [ + "default" + ], + "tool": "roslynanalyzers", + "ruleId": "CA1310", + "createdDate": "2026-05-13 00:39:09Z", + "expirationDate": "2026-10-30 00:42:11Z", + "justification": "This error is baselined with an expiration date of 180 days from 2026-05-13 00:42:11Z" + }, + "f6386b2f2aa1886a31fd1b57fa9e476ff5f24efbe144c82246f931e688010861": { + "signature": "f6386b2f2aa1886a31fd1b57fa9e476ff5f24efbe144c82246f931e688010861", + "alternativeSignatures": [ + "eb5bc1ea05b68f4106e441c8d441b39afaea833e5b2cbf6804d34cb869d9ed00", + "bbe095dbf06a503925246de4a84cdc73afdafeddde3dab2440302c40560f811e", + "aaac06605663a64f92dc03d6aacf9a424f2d861eba86f4ffa06cd231479734a8" + ], + "target": "src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs", + "line": 179, + "uriBaseId": "file:///D:/a/_work/1/s/", + "memberOf": [ + "default" + ], + "tool": "roslynanalyzers", + "ruleId": "CA1310", + "createdDate": "2026-05-13 00:39:09Z", + "expirationDate": "2026-10-30 00:42:11Z", + "justification": "This error is baselined with an expiration date of 180 days from 2026-05-13 00:42:11Z" + } + } +} \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..16abc6aef --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,11 @@ +{ + "name": "OpenAPI.NET", + "image": "mcr.microsoft.com/devcontainers/dotnet:10.0", + "customizations": { + "vscode": { + "extensions": [ + "ms-dotnettools.csdevkit" + ] + } + } +} diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..12f65c04f --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,63 @@ +# Copilot Instructions + +## Commit Message Format + +Always use conventional commits format when creating commits. Follow this structure: + +``` +(): + +[optional body] + +[optional footer(s)] +``` + +### Types + +- **feat**: A new feature +- **fix**: A bug fix +- **docs**: Documentation only changes +- **style**: Changes that do not affect the meaning of the code (white-space, formatting, etc) +- **refactor**: A code change that neither fixes a bug nor adds a feature +- **perf**: A code change that improves performance +- **test**: Adding missing tests or correcting existing tests +- **build**: Changes that affect the build system or external dependencies +- **ci**: Changes to CI configuration files and scripts +- **chore**: Other changes that don't modify src or test files + +### Scope + +The scope should indicate the package or area affected (e.g., `library`, `yaml-reader`, `hidi`). + +### Examples + +``` +feat(library): add support for pattern properties +fix(yaml-reader): updates boolean serialization +docs(README): update installation instructions +ci(release): configure automated release workflow +``` + +### Breaking Changes + +If a commit introduces a breaking change, add `BREAKING CHANGE:` in the footer or append `!` after the type/scope: + +``` +feat(identity-emitter)!: change output format for models + +BREAKING CHANGE: The emitter now generates TypeScript interfaces instead of types +``` + + +## Updating the benchmark information + +The user might request you update the benchmark information. You might do it on your own if a previous change added new properties to models under **src/Microsoft.OpenApi/Models**. Always use a separate commit for this change. + +To do so, run the following script: + +```shell +cd performance/benchmark +dotnet run -c Release +``` + +Then commit the report files using a "chore" commit. \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 87b987112..22ae8e30f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,27 +1,48 @@ version: 2 updates: - - package-ecosystem: "github-actions" - # default location of `.github/workflows` - directory: "/" - open-pull-requests-limit: 10 - schedule: - interval: "daily" - - package-ecosystem: "nuget" - # location of package manifests - directory: "/" - open-pull-requests-limit: 10 - schedule: - interval: "daily" - groups: - MicrosoftExtensions: - patterns: - - "Microsoft.Extensions.*" - - package-ecosystem: dotnet-sdk - directory: / - schedule: - interval: "daily" - ignore: - - dependency-name: '*' - update-types: - - version-update:semver-major - - version-update:semver-minor +- package-ecosystem: github-actions + directory: / + open-pull-requests-limit: 10 + schedule: + interval: daily + groups: + codeql: + patterns: + - github/codeql-action* + cooldown: + default-days: 7 +- package-ecosystem: nuget + directory: / + open-pull-requests-limit: 10 + schedule: + interval: daily + groups: + MicrosoftExtensions: + patterns: + - Microsoft.Extensions.* + testing: + patterns: + - coverlet.* + - Microsoft.NET.Test.Sdk + - Microsoft.Testing.* + - xunit.* + cooldown: + default-days: 7 +- package-ecosystem: dotnet-sdk + directory: / + schedule: + interval: daily + ignore: + - dependency-name: '*' + update-types: + - version-update:semver-major + - version-update:semver-minor + cooldown: + default-days: 7 +- package-ecosystem: devcontainers + directory: / + open-pull-requests-limit: 10 + schedule: + interval: daily + cooldown: + default-days: 7 diff --git a/.github/workflows/auto-merge-dependabot.yml b/.github/workflows/auto-merge-dependabot.yml index d454cd186..f6dafa170 100644 --- a/.github/workflows/auto-merge-dependabot.yml +++ b/.github/workflows/auto-merge-dependabot.yml @@ -19,14 +19,14 @@ jobs: steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v2.4.0 + uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" - name: Enable auto-merge for Dependabot PRs # Only if version bump is not a major version change if: ${{steps.metadata.outputs.update-type != 'version-update:semver-major'}} - run: gh pr merge --auto --merge "$PR_URL" + run: gh pr merge --auto --squash "$PR_URL" env: PR_URL: ${{github.event.pull_request.html_url}} GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 4d53ec759..b77f7d85e 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -9,19 +9,29 @@ jobs: ci: name: Continuous Integration runs-on: ubuntu-latest + permissions: + contents: read + code-quality: write + pull-requests: read env: ARTIFACTS_FOLDER: ${{ github.workspace }}/Artifacts GITHUB_RUN_NUMBER: ${{ github.run_number }} steps: - - name: Setup .NET - uses: actions/setup-dotnet@v5 + - name: Setup .NET 8 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: dotnet-version: 8.x + - name: Setup .NET 10 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 + with: + dotnet-version: 10.x + - name: Checkout repository id: checkout_repo - uses: actions/checkout@v6 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 @@ -29,27 +39,61 @@ jobs: id: build_projects shell: pwsh run: | - dotnet build Microsoft.OpenApi.sln -c Release + dotnet build Microsoft.OpenApi.slnx -c Release - name: Run unit tests id: run_unit_tests shell: pwsh run: | - dotnet test Microsoft.OpenApi.sln -c Release -v n + dotnet test --solution Microsoft.OpenApi.slnx -c Release -v n --results-directory=./TestResults --coverlet --coverlet-output-format cobertura --report-gh + + - name: Install report generator + shell: pwsh + run: | + dotnet tool install --global dotnet-reportgenerator-globaltool + + - name: Generate coverage report + shell: pwsh + run: | + reportgenerator -reports:./TestResults/**/coverage.cobertura.*.xml -targetdir:./reports/coverage -reporttypes:"Html;MarkdownSummaryGithub;Cobertura" + + - name: Add coverage to job summary + shell: bash + run: | + cat ./reports/coverage/SummaryGithub.md >> "$GITHUB_STEP_SUMMARY" + + - name: Upload coverage report + if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]') || (github.event_name != 'pull_request' && github.ref_name == github.event.repository.default_branch) + uses: actions/upload-code-coverage@2b21a77928be8d5168c2b9581a67f2adbebacc52 # v1.4.4 + with: + file: ./reports/coverage/Cobertura.xml + language: CSharp + label: code-coverage/dotnet + + - name: Upload coverage artifact + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: coverage + path: reports/coverage validate-trimming: name: Validate Project for Trimming runs-on: windows-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: Setup .NET - uses: actions/setup-dotnet@v5 + - name: Setup .NET 8 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: dotnet-version: 8.x + - name: Setup .NET 10 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 + with: + dotnet-version: 10.x + - name: Validate Trimming warnings - run: dotnet publish -c Release -r win-x64 /p:TreatWarningsAsErrors=true /warnaserror -f net8.0 + run: dotnet publish -c Release -r win-x64 /p:TreatWarningsAsErrors=true /warnaserror -f net10.0 working-directory: ./test/Microsoft.OpenApi.Trimming.Tests validate-performance: @@ -58,13 +102,18 @@ jobs: needs: [ci] steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: Setup .NET - uses: actions/setup-dotnet@v5 + - name: Setup .NET 8 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: dotnet-version: 8.x + - name: Setup .NET 10 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 + with: + dotnet-version: 10.x + - name: Copy committed results run: | mkdir -p ./performanceResults @@ -76,7 +125,7 @@ jobs: working-directory: ./performance/benchmark - name: Publish benchmark results - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: if-no-files-found: error name: benchmark-results diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 30c8acef4..819b50e4f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -20,16 +20,21 @@ jobs: steps: - name: Checkout repository id: checkout_repo - uses: actions/checkout@v6 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - name: Setup .NET - uses: actions/setup-dotnet@v5 + - name: Setup .NET 8 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: dotnet-version: 8.0.x + - name: Setup .NET 10 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 + with: + dotnet-version: 10.0.x + - name: Initialize CodeQL id: init_codeql - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1 with: queries: security-and-quality @@ -39,8 +44,7 @@ jobs: run: | $projectsArray = @( '.\src\Microsoft.OpenApi\Microsoft.OpenApi.csproj', - '.\src\Microsoft.OpenApi.YamlReader\Microsoft.OpenApi.YamlReader.csproj', - '.\src\Microsoft.OpenApi.Hidi\Microsoft.OpenApi.Hidi.csproj' + '.\src\Microsoft.OpenApi.YamlReader\Microsoft.OpenApi.YamlReader.csproj' ) $projectsArray | ForEach-Object { @@ -49,6 +53,6 @@ jobs: - name: Perform CodeQL Analysis id: analyze_codeql - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1 # Built with ❤ by [Pipeline Foundation](https://pipeline.foundation) \ No newline at end of file diff --git a/.github/workflows/promote-shipped-apis.yml b/.github/workflows/promote-shipped-apis.yml new file mode 100644 index 000000000..a93ac994b --- /dev/null +++ b/.github/workflows/promote-shipped-apis.yml @@ -0,0 +1,126 @@ +name: Promote Shipped APIs + +on: + push: + branches: + - main + - support/v2 + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +jobs: + promote-apis: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Generate GitHub App token + id: app-token + uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0 + with: + client-id: ${{ vars.RELEASE_PLEASE_TOKEN_PROVIDER_APP_ID }} + private-key: ${{ secrets.RELEASE_PLEASE_TOKEN_PROVIDER_PEM }} + permission-contents: write + permission-pull-requests: write + + - name: Get GitHub App user ID + id: get-user-id + shell: bash + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT" + + - name: Checkout code + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + token: ${{ steps.app-token.outputs.token }} + + - name: Configure git + shell: pwsh + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + run: | + git config --global user.name "${{ steps.app-token.outputs.app-slug }}[bot]" + git config --global user.email "${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com" + git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "https://github.com/" + + - name: Check for existing PR + id: check_pr + shell: pwsh + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + run: | + $branch = "${{ github.ref_name }}" + $prs = gh pr list --state open --head "promote-shipped-apis-$branch" --json number --jq '.[0].number' 2>$null + if ($prs) { + echo "pr_number=$prs" >> $env:GITHUB_OUTPUT + echo "pr_exists=true" >> $env:GITHUB_OUTPUT + Write-Host "Found existing PR: $prs" + } else { + echo "pr_exists=false" >> $env:GITHUB_OUTPUT + Write-Host "No existing PR found" + } + + - name: Checkout existing PR branch + if: steps.check_pr.outputs.pr_exists == 'true' + shell: pwsh + run: | + $branch = "${{ github.ref_name }}" + $prBranch = "promote-shipped-apis-$branch" + + git fetch origin + git checkout $prBranch + + - name: Merge trigger branch into PR branch + if: steps.check_pr.outputs.pr_exists == 'true' + shell: pwsh + run: | + $branch = "${{ github.ref_name }}" + git merge origin/$branch -m "Merge $branch into promote branch" + + - name: Run promote unshipped script + shell: pwsh + run: | + & .\scripts\promoteUnshipped.ps1 + + - name: Check for changes + id: check_changes + shell: pwsh + run: | + $changes = git diff --name-only -- "*Shipped.txt" + if ($changes) { + echo "has_changes=true" >> $env:GITHUB_OUTPUT + Write-Host "Changed files: $changes" + } else { + echo "has_changes=false" >> $env:GITHUB_OUTPUT + Write-Host "No changes detected" + } + + - name: Commit and push changes + if: steps.check_changes.outputs.has_changes == 'true' + shell: pwsh + run: | + git add *hipped.txt + git commit -m "chore: promote shipped APIs" + + $branch = "${{ github.ref_name }}" + $prBranch = "promote-shipped-apis-$branch" + git push -u origin HEAD:$prBranch + + - name: Create new PR + if: steps.check_pr.outputs.pr_exists == 'false' && steps.check_changes.outputs.has_changes == 'true' + shell: pwsh + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + run: | + $branch = "${{ github.ref_name }}" + $prBranch = "promote-shipped-apis-$branch" + $title = "automatic promotion of shipped APIs for $branch" + + gh pr create --title "$title" --base "$branch" --head "$prBranch" --body "Automatically promotes unshipped APIs to shipped after running the promotion script." + diff --git a/.github/workflows/release-please-gha.yml b/.github/workflows/release-please-gha.yml index c905a3f48..069cbcecb 100644 --- a/.github/workflows/release-please-gha.yml +++ b/.github/workflows/release-please-gha.yml @@ -22,20 +22,53 @@ permissions: contents: read jobs: + check-secret: + runs-on: ubuntu-latest + outputs: + has-token: ${{ steps.check.outputs.has-token }} + steps: + - id: check + run: echo "has-token=${{ secrets.RELEASE_PLEASE_TOKEN_PROVIDER_PEM != '' }}" >> $GITHUB_OUTPUT release: + needs: check-secret + if: needs.check-secret.outputs.has-token == 'true' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Validate PublicAPI.Unshipped.txt files are empty + shell: pwsh + run: | + $unshippedFiles = Get-ChildItem 'src/ ' -Recurse -Filter *.Unshipped.txt | Select -ExpandProperty FullName + + $hasUnshippedAPIs = $false + + foreach ($file in $unshippedFiles) { + $content = Get-Content -Path $file -Raw + # Remove the #nullable enable line and any whitespace + $trimmedContent = $content -replace '^\s*#nullable enable\s*$', '' -replace '^\s+', '' + + if ($trimmedContent -ne '') { + Write-Error "❌ $file contains unshipped APIs. Please promote them to PublicAPI.Shipped.txt before releasing.`nContent:`n$content" + $hasUnshippedAPIs = $true + } + } + + if ($hasUnshippedAPIs) { + exit 1 + } + + Write-Output "✅ All PublicAPI.Unshipped.txt files are clean" - name: Generate GitHub App token id: app-token - uses: actions/create-github-app-token@v2 + uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0 with: - app-id: ${{ vars.RELEASE_PLEASE_TOKEN_PROVIDER_APP_ID }} + client-id: ${{ vars.RELEASE_PLEASE_TOKEN_PROVIDER_APP_ID }} private-key: ${{ secrets.RELEASE_PLEASE_TOKEN_PROVIDER_PEM }} - name: Release Please - uses: googleapis/release-please-action@v4 + uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 with: token: ${{ steps.app-token.outputs.token }} config-file: release-please-config.json diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 3f969e825..9d6e25106 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -35,19 +35,23 @@ jobs: runs-on: windows-latest steps: - name: Set up JDK 17 - uses: actions/setup-java@v5 + uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0 with: - distribution: 'adopt' + distribution: 'temurin' java-version: 17 - - name: Setup .NET - uses: actions/setup-dotnet@v5 + - name: Setup .NET 8 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: dotnet-version: 8.0.x - - uses: actions/checkout@v6 + - name: Setup .NET 10 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 + with: + dotnet-version: 10.0.x + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Cache SonarCloud packages - uses: actions/cache@v4 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar @@ -57,12 +61,10 @@ jobs: - name: Build and analyze env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any - CollectCoverage: true - CoverletOutputFormat: 'opencover' # https://github.com/microsoft/vstest/issues/4014#issuecomment-1307913682 shell: pwsh run: | - dotnet tool run dotnet-sonarscanner begin /k:"microsoft_OpenAPI.NET" /o:"microsoft" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="test/**/coverage.opencover.xml" + dotnet tool run dotnet-sonarscanner begin /k:"microsoft_OpenAPI.NET" /o:"microsoft" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover*.xml" dotnet workload restore dotnet build - dotnet test Microsoft.OpenApi.sln --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover - dotnet tool run dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}" \ No newline at end of file + dotnet test --solution Microsoft.OpenApi.slnx --verbosity normal --coverlet --coverlet-output-format opencover --report-gh + dotnet tool run dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}" diff --git a/.gitignore b/.gitignore index 258fee87a..09353aba3 100644 --- a/.gitignore +++ b/.gitignore @@ -127,7 +127,7 @@ nCrunchTemp_* *.mm.* AutoTest.Net/ -# Web workbench (sass) +# Sass cache .sass-cache/ # Installshield output folder diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a1304a172..940f2ca3e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.0.2" + ".": "3.11.0" } \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 66912fac4..fb87186c4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,24 +1,6 @@ { "version": "0.2.0", "configurations": [ - { - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/main/debugger-launchjson.md - "name": "Launch Hidi", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build", - // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/src/Microsoft.OpenApi.Hidi/bin/Debug/net8.0/Microsoft.OpenApi.Hidi.dll", - "args": ["plugin", - "-m","${workspaceFolder}/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/exampleapimanifest.json", - "--of","./output"], - "cwd": "${workspaceFolder}/src/Microsoft.OpenApi.Hidi", - // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console - "console": "internalConsole", - "stopAtEntry": false - }, { // Use IntelliSense to find out which attributes exist for C# debugging // Use hover for the description of the existing attributes @@ -49,23 +31,7 @@ "console": "internalConsole", "stopAtEntry": false, "requireExactSource": false, - }, - { - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/main/debugger-launchjson.md - "name": "Launch Workbench", - "type": "coreclr", - "request": "launch", - "preLaunchTask": "build", - // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/src/Microsoft.OpenApi.WorkBench/bin/Debug/net8.0-windows/Microsoft.OpenApi.Workbench.exe", - "args": [], - "cwd": "${workspaceFolder}/src/Microsoft.OpenApi.Workbench", - // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console - "console": "internalConsole", - "stopAtEntry": false - }, + }, { "name": ".NET Core Attach", "type": "coreclr", diff --git a/.vscode/settings.json b/.vscode/settings.json index 186b10bea..4bfa8971f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,6 @@ }, "cSpell.words": [ "csdl", - "Hidi" + "Xunit" ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d2bd5722f..4372c2f45 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -10,7 +10,7 @@ "group": "build", "args": [ "build", - "${workspaceFolder}/Microsoft.OpenApi.sln", + "${workspaceFolder}/Microsoft.OpenApi.slnx", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], @@ -23,32 +23,12 @@ "group": "test", "args": [ "test", - "${workspaceFolder}/Microsoft.OpenApi.sln", + "${workspaceFolder}/Microsoft.OpenApi.slnx", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary", "--collect:\"XPlat Code Coverage\"" ], "problemMatcher": "$msCompile" - }, - { - "label": "watch", - "command": "dotnet", - "type": "process", - "group": "build", - "args": [ - "watch", - "run", - "${workspaceFolder}/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj", - "/property:GenerateFullPaths=true", - "/consoleloggerparameters:NoSummary" - ], - "problemMatcher": "$msCompile" - }, - { - "label": "workbench", - "type": "shell", - "command": "src/Microsoft.OpenApi.WorkBench/bin/Debug/Microsoft.OpenApi.WorkBench.exe", - "problemMatcher": [] } ] } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 83c66a66d..a3114853b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,264 @@ # Changelog -## [3.0.2](https://github.com/microsoft/OpenAPI.NET/compare/v3.0.1...v3.0.2) (2025-12-08) +## [3.11.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.10.2...v3.11.0) (2026-10-19) + + +### Features + +* **document:** add GetOperationById to search operations across path… ([#3025](https://github.com/microsoft/OpenAPI.NET/issues/3025)) ([1dae1ff](https://github.com/microsoft/OpenAPI.NET/commit/1dae1fff4fcd8170f38672593a30b023a66c052c)) + + +### Bug Fixes + +* components-key validation timeouts under load ([#3108](https://github.com/microsoft/OpenAPI.NET/issues/3108)) ([01d4729](https://github.com/microsoft/OpenAPI.NET/commit/01d472995b3c466feb5bbf61e303bcd7752da16a)) +* **openapi:** omit null response descriptions ([afd4967](https://github.com/microsoft/OpenAPI.NET/commit/afd4967a9e6db390175e2df9e6f34ff77168d19d)) +* **serialization:** potential infinite loop when inlining references ([c6ef130](https://github.com/microsoft/OpenAPI.NET/commit/c6ef130bd7f3bf55c59735b25392a58a599701fc)) +* **serialization:** references inlining ([#3124](https://github.com/microsoft/OpenAPI.NET/issues/3124)) ([c6ef130](https://github.com/microsoft/OpenAPI.NET/commit/c6ef130bd7f3bf55c59735b25392a58a599701fc)) + +## [3.10.2](https://github.com/microsoft/OpenAPI.NET/compare/v3.10.1...v3.10.2) (2026-08-20) + + +### Bug Fixes + +* duplicate schema example when serializing to v2 ([#3045](https://github.com/microsoft/OpenAPI.NET/issues/3045)) ([50f5a2b](https://github.com/microsoft/OpenAPI.NET/commit/50f5a2bb119089bb48987494d906cb1a95cddbd1)) + +## [3.10.1](https://github.com/microsoft/OpenAPI.NET/compare/v3.10.0...v3.10.1) (2026-08-19) + + +### Bug Fixes + +* circular ref guard ([#3033](https://github.com/microsoft/OpenAPI.NET/issues/3033)) ([8018d40](https://github.com/microsoft/OpenAPI.NET/commit/8018d40aac5fc6ed5e022e6203ee917ecf36472c)) +* harden yaml parsing ([#3027](https://github.com/microsoft/OpenAPI.NET/issues/3027)) ([e0d5e9d](https://github.com/microsoft/OpenAPI.NET/commit/e0d5e9d105ad1a7b29ff6c628793614f5610f048)) + +## [3.10.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.9.0...v3.10.0) (2026-08-11) + + +### Features + +* do not ignore multiple types when serializing to 3.0 ([#2960](https://github.com/microsoft/OpenAPI.NET/issues/2960)) ([ebaf27a](https://github.com/microsoft/OpenAPI.NET/commit/ebaf27ac46f8820e7b817cc33e693632c2fc908a)) + + +### Bug Fixes + +* bound YAML anchor/alias expansion to prevent OOM (billion laughs) ([#3000](https://github.com/microsoft/OpenAPI.NET/issues/3000)) ([2179326](https://github.com/microsoft/OpenAPI.NET/commit/21793261d6860fb6e607b71fd95c0bd320724764)) + +## [3.9.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.8.0...v3.9.0) (2026-07-15) + + +### Features + +* adds support for anchor and id external resolution ([1591007](https://github.com/microsoft/OpenAPI.NET/commit/15910070f2bf3006f79e1c43dd9c2b56e45d665c)) +* **schema:** resolve bare $dynamicRef via $dynamicAnchor index ([#2913](https://github.com/microsoft/OpenAPI.NET/issues/2913)) ([eacc2fc](https://github.com/microsoft/OpenAPI.NET/commit/eacc2fc06537fbb11fe95765e4fb6df09861c9af)) +* support relative URI resolution in $dynamicRef ([#2928](https://github.com/microsoft/OpenAPI.NET/issues/2928)) ([#2945](https://github.com/microsoft/OpenAPI.NET/issues/2945)) ([821053b](https://github.com/microsoft/OpenAPI.NET/commit/821053ba02129e92868df2ae0c26551fb3d5276a)) + + +### Bug Fixes + +* adds explicit error message for invalid json pointers ([63fc55d](https://github.com/microsoft/OpenAPI.NET/commit/63fc55d69274ebd405e677983e0a72efd2b96079)) +* adds explicit error message for invalid json pointers ([bc93efe](https://github.com/microsoft/OpenAPI.NET/commit/bc93efe9d4694e89da1ea30fbc2d031e7f1318ae)) +* default mapping is not being serialized with the correct shape ([fe4a25f](https://github.com/microsoft/OpenAPI.NET/commit/fe4a25f1f25c853404540d30f11812f1208f93c9)) +* differentiate unset value from null value in OpenApiSchema.Const ([#2936](https://github.com/microsoft/OpenAPI.NET/issues/2936)) ([07b525f](https://github.com/microsoft/OpenAPI.NET/commit/07b525f568b65b5003deaccc56829f5e7e8e2641)) +* handle nullability more accurately during serialization for 3.0/2.0 ([#2933](https://github.com/microsoft/OpenAPI.NET/issues/2933)) ([0ace243](https://github.com/microsoft/OpenAPI.NET/commit/0ace243ebbabe82aacc52d49fe58f54f039bdf76)) +* validate required properties of security scheme before serialization ([#2952](https://github.com/microsoft/OpenAPI.NET/issues/2952)) ([f31b192](https://github.com/microsoft/OpenAPI.NET/commit/f31b192e9d59d39671fdfd03b4fa4d309b03021b)) + +## [3.8.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.7.0...v3.8.0) (2026-07-03) + + +### Features + +* add JsonConverter for OpenApiSchema System.Text.Json serialization ([#2915](https://github.com/microsoft/OpenAPI.NET/issues/2915)) ([2f8b3d2](https://github.com/microsoft/OpenAPI.NET/commit/2f8b3d2a160f5b44b5aeaa3d83ff2025302ce1e2)) +* **library:** support schema keywords on references ([434b2f8](https://github.com/microsoft/OpenAPI.NET/commit/434b2f8b34e4a3a27bd99e43f61692f0b00c3054)) +* **library:** support schema keywords on references ([66a9d04](https://github.com/microsoft/OpenAPI.NET/commit/66a9d04036556945ee3222849b7d071a30016b81)), closes [#2903](https://github.com/microsoft/OpenAPI.NET/issues/2903) + + +### Bug Fixes + +* Don't silently skip null assignment to OpenApiDocument.Tags ([3764142](https://github.com/microsoft/OpenAPI.NET/commit/37641424837df0b5e142ca130cb16df699bdb09f)) +* handling of nullable enums for 3.0 ([#2920](https://github.com/microsoft/OpenAPI.NET/issues/2920)) ([beb68f5](https://github.com/microsoft/OpenAPI.NET/commit/beb68f52b86c1437e50f7561d9be1ebdbe146963)) +* **library:** keep v3 schema references ref-only ([c938727](https://github.com/microsoft/OpenAPI.NET/commit/c9387274be6a6955952174d677bea0a35bda2624)) +* preserve JSON Schema 2020-12 keyword siblings on $ref schemas for OAS 3.1+ ([#2896](https://github.com/microsoft/OpenAPI.NET/issues/2896)) ([08160c8](https://github.com/microsoft/OpenAPI.NET/commit/08160c872a5f931eecd12446335c2f51fdad083e)) +* use async method for crypto flush ([6e675d9](https://github.com/microsoft/OpenAPI.NET/commit/6e675d943537312386c9683790848ad1cbacb713)) + +## [3.7.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.6.0...v3.7.0) (2026-06-10) + + +### Features + +* add contains/minContains/maxContains members ([78475e3](https://github.com/microsoft/OpenAPI.NET/commit/78475e38f7c61e349f2d2ad477b5a96a9c3df848)) +* add contains/minContains/maxContains members ([1a974f8](https://github.com/microsoft/OpenAPI.NET/commit/1a974f8dfcd7850c70d80133ceecee08f6671cd7)) +* **library:** add missing json schema properties ([9b1aed6](https://github.com/microsoft/OpenAPI.NET/commit/9b1aed61041551b06926fc2ee4e12705190e16b3)) +* **library:** add missing json schema properties ([82f84e0](https://github.com/microsoft/OpenAPI.NET/commit/82f84e072d9f6b4b5907e9435212fbfc8f82d9c7)) + + +### Bug Fixes + +* **library:** always copy unevaluated properties ([4907d1c](https://github.com/microsoft/OpenAPI.NET/commit/4907d1c1c4d5b8450d32459752e64e5beb592f46)) +* **library:** avoid false circular refs for external schema re-exports ([b635242](https://github.com/microsoft/OpenAPI.NET/commit/b635242a402c3c468eb86dcf2b6d94a05717d92e)) +* **library:** avoid false circular refs for external schema re-exports ([7a443c2](https://github.com/microsoft/OpenAPI.NET/commit/7a443c298fb87346338095b5df86f6608fb4d582)) +* **library:** remove unshipped schema extension fallback ([cf54bb3](https://github.com/microsoft/OpenAPI.NET/commit/cf54bb3e2746c0f6c7a60fde5bcc7fa1139dd8b6)) +* **library:** use version-specific schema keyword callbacks ([6e22ec6](https://github.com/microsoft/OpenAPI.NET/commit/6e22ec6948509d2e256932ee55f1781a544cb53f)) +* **library:** use x-jsonschema schema extensions ([eb1891a](https://github.com/microsoft/OpenAPI.NET/commit/eb1891a8d77915add1cdd88949b40aa43cd525b8)) + +## [3.6.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.5.5...v3.6.0) (2026-06-01) + + +### Features + +* **reader:** remove ParseNode infrastructure ([9b4f45b](https://github.com/microsoft/OpenAPI.NET/commit/9b4f45bee83106e2e5309c9583220f690c66c716)) + +## [3.5.5](https://github.com/microsoft/OpenAPI.NET/compare/v3.5.4...v3.5.5) (2026-05-28) + + +### Bug Fixes + +* **reader:** preserve Null flag when nullable appears before type in V3.0/V3.1/V3.2 deserializers ([2b9d7f4](https://github.com/microsoft/OpenAPI.NET/commit/2b9d7f46bfcef3e2d5da3f73fd4bf83be677c79a)) + +## [3.5.4](https://github.com/microsoft/OpenAPI.NET/compare/v3.5.3...v3.5.4) (2026-05-26) + + +### Bug Fixes + +* **library:** handle circular schema references ([b3cd42b](https://github.com/microsoft/OpenAPI.NET/commit/b3cd42b7c2405b800e633ce63b044bb2409034a0)) +* **library:** handle circular schema references ([91a989f](https://github.com/microsoft/OpenAPI.NET/commit/91a989fdf412a1267debe925d2d586292fdd297d)) + +## [3.5.3](https://github.com/microsoft/OpenAPI.NET/compare/v3.5.2...v3.5.3) (2026-04-27) + + +### Bug Fixes + +* null reference exception for boolean component schemas ([f97f91a](https://github.com/microsoft/OpenAPI.NET/commit/f97f91a9f785b88039968024d5d1f4af51332631)) +* null reference exception for boolean component schemas ([fe0b50a](https://github.com/microsoft/OpenAPI.NET/commit/fe0b50aae372e5b08625f888ae424f22da759cdf)) +* **schema:** support boolean schemas in deserializer for OpenAPI 3.1/3.2 ([05b44be](https://github.com/microsoft/OpenAPI.NET/commit/05b44beb9783f5bab1d8988b3cb916d0278d42ce)) + + +### Performance Improvements + +* **schema:** optimize boolean schema deserialization ([7316e3f](https://github.com/microsoft/OpenAPI.NET/commit/7316e3f0e7b9acc11bc1e0255d7ca33837a1bbdc)) + +## [3.5.2](https://github.com/microsoft/OpenAPI.NET/compare/v3.5.1...v3.5.2) (2026-04-14) + + +### Bug Fixes + +* **hidi:** update Microsoft.OpenApi.OData to 3.2.1 ([b0a68fb](https://github.com/microsoft/OpenAPI.NET/commit/b0a68fbe53593139ba51e758bcc01fcd188d7cb8)) +* **hidi:** update Microsoft.OpenApi.OData to 3.2.1 ([8c22ab2](https://github.com/microsoft/OpenAPI.NET/commit/8c22ab2b3a885344197bf0f05d6df63ecb771927)), closes [#2811](https://github.com/microsoft/OpenAPI.NET/issues/2811) + +## [3.5.1](https://github.com/microsoft/OpenAPI.NET/compare/v3.5.0...v3.5.1) (2026-03-31) + + +### Bug Fixes + +* security scheme references serialization ([a5acb89](https://github.com/microsoft/OpenAPI.NET/commit/a5acb896cb46a58702c07bc742b5e114ba90f95a)) + +## [3.5.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.4.0...v3.5.0) (2026-03-20) + + +### Features + +* **library:** add Extensions support for schema references in v3.1/v3.2; add SerializeAsV32 with loop detection ([9b422bf](https://github.com/microsoft/OpenAPI.NET/commit/9b422bfbe1459588821ab011ba470336c63e4958)) + + +### Bug Fixes + +* a bug where path parameter validation would fail if they contained forbidden JSON pointer characters ([ef55b2c](https://github.com/microsoft/OpenAPI.NET/commit/ef55b2ce664014a854dbd4275e3fed783bc53385)) +* a bug where path parameter validation would fail if they contained forbidden JSON pointer characters ([4b3164a](https://github.com/microsoft/OpenAPI.NET/commit/4b3164a76b316951cb043aebf950663a17e51c90)) +* double encoding of json pointer for invalid reference rule ([b246cd0](https://github.com/microsoft/OpenAPI.NET/commit/b246cd0bafde78892aa22e6ffe046cf5a438eb7d)) +* encoding of special characters for JSON paths ([4c757e1](https://github.com/microsoft/OpenAPI.NET/commit/4c757e1e9806f95ed598f349e4fc35a0307b9342)) +* **library:** do not emit unevaluatedProperties for non-object schemas ([852fb4c](https://github.com/microsoft/OpenAPI.NET/commit/852fb4c744c51099a629d90797a2803d3bbdfc2a)) +* **library:** do not emit unevaluatedProperties for non-object schemas ([19538aa](https://github.com/microsoft/OpenAPI.NET/commit/19538aa169b708dac3baf04a1315bed1dd25eac6)) +* **library:** enforce spec-compliant $ref serialization; add Extensions support for schema references in v3.1/v3.2 ([9bf61de](https://github.com/microsoft/OpenAPI.NET/commit/9bf61de9c10092f744ab38fe0a41bd6adb8351d4)) +* potential double encoding of paths ([471a61a](https://github.com/microsoft/OpenAPI.NET/commit/471a61a2567bb517ede94f0bec1a53ef806b2db3)) + +## [3.4.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.3.1...v3.4.0) (2026-03-04) + + +### Features + +* **library:** preserve PatternProperties as x-jsonschema-patternProperties extension for OpenAPI v2/v3.0 serialization ([d969fdc](https://github.com/microsoft/OpenAPI.NET/commit/d969fdc12632ad0879b9fe07d3ab736b21ae68cf)) +* **library:** Preserve PatternProperties via x-jsonschema-patternProperties extension for OpenAPI v2/v3.0 ([16ab5e4](https://github.com/microsoft/OpenAPI.NET/commit/16ab5e42bdef6e08e2afaf7ad3921ac8178f059c)) +* **securityscheme:** add oauth2MetadataUrl support (OpenAPI 3.2) ([4509488](https://github.com/microsoft/OpenAPI.NET/commit/4509488f2e8725e37a60a3b7a3a8a0b6c0c74378)) + + +### Bug Fixes + +* implement unevaluatedProperties as schema per JSON Schema 2020-12 ([#2728](https://github.com/microsoft/OpenAPI.NET/issues/2728)) ([7c13fb3](https://github.com/microsoft/OpenAPI.NET/commit/7c13fb3910685b5c17897cd7799b9ef1bba7f80d)) +* **library:** serialize additionalProperties schema in OpenAPI V2 ([f3165fa](https://github.com/microsoft/OpenAPI.NET/commit/f3165fa874a8bb76788684742492f48b20aab892)) +* **library:** serialize additionalProperties schema in OpenAPI V2 documents ([3d07756](https://github.com/microsoft/OpenAPI.NET/commit/3d0775610a9e74b6d5ce845195ccb935576bcd31)) +* optimize parsing V3.1 documents by reducing GetLocation method allocation on hot path([#2748](https://github.com/microsoft/OpenAPI.NET/issues/2748)) ([f690681](https://github.com/microsoft/OpenAPI.NET/commit/f6906811e616f8e6875b8d839137c846fc7bbd9e)) + +## [3.3.1](https://github.com/microsoft/OpenAPI.NET/compare/v3.3.0...v3.3.1) (2026-01-22) + + +### Features + +* **models:** add shared Content interface ([#2695](https://github.com/microsoft/OpenAPI.NET/issues/2695)) ([338566f](https://github.com/microsoft/OpenAPI.NET/commit/338566fafce04ee1329f4ead61fe1e87e01144ad)) +### Bug Fixes + +* broken binary compatibility due to interface changes in previous version ([d96bba7](https://github.com/microsoft/OpenAPI.NET/commit/d96bba72c383cd5db2b7032530aee3b4d944ebc6)) + +## [3.3.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.2.0...v3.3.0) (2026-01-21) + + +### Features + +* **models:** add shared Content interface ([9e13b25](https://github.com/microsoft/OpenAPI.NET/commit/9e13b2574e68387ecc01c453b571208c40124b46)) +* **models:** add shared Content interface ([#2695](https://github.com/microsoft/OpenAPI.NET/issues/2695)) ([9e13b25](https://github.com/microsoft/OpenAPI.NET/commit/9e13b2574e68387ecc01c453b571208c40124b46)) +* **models:** support mutualTLS security scheme ([a4efdfe](https://github.com/microsoft/OpenAPI.NET/commit/a4efdfe43ee310fba4bb643d9fd28ce92da32338)) + +## [3.2.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.1.3...v3.2.0) (2026-01-19) + + +### Features + +* hidi validate command now logs warnings ([76a3c0f](https://github.com/microsoft/OpenAPI.NET/commit/76a3c0fe33a6c953263d9d91669b2f1bab562a79)) +* hidi validate command now logs warnings ([62e7d56](https://github.com/microsoft/OpenAPI.NET/commit/62e7d56ac0863875999240d68a2766d2cc2d594c)) + + +### Bug Fixes + +* discriminator property validation fails any/allOf cases when it shouldn't ([fb6cecc](https://github.com/microsoft/OpenAPI.NET/commit/fb6cecccafd5713bc1eb22e0cf07619cf495ebb5)) +* discriminator property validation fails any/allOf cases when it shouldn't ([a8fb81c](https://github.com/microsoft/OpenAPI.NET/commit/a8fb81cf9524a3f2f721aa808db244434e1cd177)) + +## [3.1.3](https://github.com/microsoft/OpenAPI.NET/compare/v3.1.2...v3.1.3) (2026-01-16) + + +### Bug Fixes + +* Support custom tag ordering ([008576c](https://github.com/microsoft/OpenAPI.NET/commit/008576c31f8dcecf59363c9c2f85d691601faa73)) +* Support custom tag ordering ([7610d07](https://github.com/microsoft/OpenAPI.NET/commit/7610d07bd11a99a4ce1cc31338d180dbd764d952)) + +## [3.1.2](https://github.com/microsoft/OpenAPI.NET/compare/v3.1.1...v3.1.2) (2026-01-06) + +### Bug Fixes + +* correct error pointer when extension parser throws OpenApiException ([43c75a9](https://github.com/microsoft/OpenAPI.NET/commit/43c75a90746344fcc975611100e995fe4045edf0)) +* wrap extension parser calls in try-catch to ensure correct error pointers ([50b44aa](https://github.com/microsoft/OpenAPI.NET/commit/50b44aad12d8fa86a46f7f6d62896a7b1c344d2e)) + +## [3.1.1](https://github.com/microsoft/OpenAPI.NET/compare/v3.1.0...v3.1.1) (2025-12-18) + + +### Bug Fixes + +* **schema:** always serialize `additionalProperties: false` ([6651c36](https://github.com/microsoft/OpenAPI.NET/commit/6651c36ff341329c053776d65b36b1b7fa9dd3ea)) +* **schema:** always serialize `additionalProperties: false` ([e36fc95](https://github.com/microsoft/OpenAPI.NET/commit/e36fc9565bce42916eb7bf64d1f74d491dd1f407)) + +## [3.1.0](https://github.com/microsoft/OpenAPI.NET/compare/v3.0.3...v3.1.0) (2025-12-17) + +### Features + +* Add `type: "null"` downcasting when in oneOf and anyOf for OpenAPI v3 ([782cf8d](https://github.com/microsoft/OpenAPI.NET/commit/782cf8d1ff8166e3c7be706e08dabf168b9616a4)) + +## [3.0.3](https://github.com/microsoft/OpenAPI.NET/compare/v3.0.2...v3.0.3) (2025-12-16) + + +* load JSON documents that are preceded by multiple whitespace ([6461bac](https://github.com/microsoft/OpenAPI.NET/commit/6461bac01c4176424210e9ac249698f665a514a6)) +* non-seekable json streams would fail to load as a document ([2436d73](https://github.com/microsoft/OpenAPI.NET/commit/2436d7382bfbf8b9ba501d88f682e952bdf27146)) +* reading streams in an asp.net context would cause async exceptions ([f9e5248](https://github.com/microsoft/OpenAPI.NET/commit/f9e524859722476b3111cb6006f77208c2d1f526)) + +## [3.0.2](https://github.com/microsoft/OpenAPI.NET/compare/v3.0.1...v3.0.2) (2025-12-08) + ### Bug Fixes * additional properties serialization should not emit a schema in v2 ([946cba9](https://github.com/microsoft/OpenAPI.NET/commit/946cba992a2733a60182453e38722b4ed789b729)) @@ -29,6 +285,51 @@ * adds support for OpenAPI 3.2.0 ([765a8dd](https://github.com/microsoft/OpenAPI.NET/commit/765a8dd4d6efd1a31b6a76d282ccffa5877a845a)) +## [2.4.3](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.2...v2.4.3) (2026-01-16) + +## Bug Fixes + +* Support custom tag ordering ([008576c](https://github.com/microsoft/OpenAPI.NET/commit/008576c31f8dcecf59363c9c2f85d691601faa73)) +* Support custom tag ordering ([7610d07](https://github.com/microsoft/OpenAPI.NET/commit/7610d07bd11a99a4ce1cc31338d180dbd764d952)) + +## [2.4.2](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.1...v2.4.2) (2025-12-22) + + +### Bug Fixes + +* wrap extension parser calls in try-catch to ensure correct error pointers ([63cf4a3](https://github.com/microsoft/OpenAPI.NET/commit/63cf4a3029fe2d285a6fe2724e30ffcf3bdd2f9f)) +* wrap extension parser calls in try-catch to ensure correct error pointers ([458cabe](https://github.com/microsoft/OpenAPI.NET/commit/458cabe6cd0fbdb192dbd17f2d6ab3b8162d1166)) + +## [2.4.1](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.0...v2.4.1) (2025-12-18) + +### Bug Fixes + +* **schema:** always serialize `additionalProperties: false` ([6651c36](https://github.com/microsoft/OpenAPI.NET/commit/6651c36ff341329c053776d65b36b1b7fa9dd3ea)) +* **schema:** always serialize `additionalProperties: false` ([e36fc95](https://github.com/microsoft/OpenAPI.NET/commit/e36fc9565bce42916eb7bf64d1f74d491dd1f407)) + +## [2.4.0](https://github.com/microsoft/OpenAPI.NET/compare/v2.3.12...v2.4.0) (2025-12-17) + +### Features + +* Add `type: "null"` downcasting when in oneOf and anyOf for OpenAPI v3 ([782cf8d](https://github.com/microsoft/OpenAPI.NET/commit/782cf8d1ff8166e3c7be706e08dabf168b9616a4)) + +## [2.3.12](https://github.com/microsoft/OpenAPI.NET/compare/v2.3.11...v2.3.12) (2025-12-15) + +### Bug Fixes + +* load JSON documents that are preceded by multiple whitespace ([640e59a](https://github.com/microsoft/OpenAPI.NET/commit/640e59a143a2a6d3b79c9f6a97a6029593d7dd8f)) +* non-seekable json streams would fail to load as a document ([76b0159](https://github.com/microsoft/OpenAPI.NET/commit/76b0159d12790ab00310ff107e37396ecdf13336)) +* non-seekable json streams would fail to load as a document ([2436d73](https://github.com/microsoft/OpenAPI.NET/commit/2436d7382bfbf8b9ba501d88f682e952bdf27146)) +* reading streams in an asp.net context would cause async exceptions ([f9e5248](https://github.com/microsoft/OpenAPI.NET/commit/f9e524859722476b3111cb6006f77208c2d1f526)) + +## [2.3.11](https://github.com/microsoft/OpenAPI.NET/compare/v2.3.10...v2.3.11) (2025-12-08) + +### Bug Fixes + +* additional properties serialization should not emit a schema in v2 ([946cba9](https://github.com/microsoft/OpenAPI.NET/commit/946cba992a2733a60182453e38722b4ed789b729)) +* additional properties serialization should not emit a schema in v2 fix: additional properties serialization should not emit booleans in v3.1+ ([275dd9d](https://github.com/microsoft/OpenAPI.NET/commit/275dd9d7525b1f490eccaf1e6e60829ae51bdf5d)) +* additional properties serialization should not emit booleans in v3.1+ ([946cba9](https://github.com/microsoft/OpenAPI.NET/commit/946cba992a2733a60182453e38722b4ed789b729)) + ## [2.3.10](https://github.com/microsoft/OpenAPI.NET/compare/v2.3.9...v2.3.10) (2025-11-17) * empty strings should be quoted in yaml ([e919b33](https://github.com/microsoft/OpenAPI.NET/commit/e919b33e9d09159217066248483ef4c767865c82)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 195723567..98e928d47 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,9 @@ OpenAPI.net is a mono-repo containing source code for the following packages: |----------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | [Microsoft.OpenAPI](./src/Microsoft.OpenAPI/README.md) | [![NuGet Version](https://img.shields.io/nuget/vpre/Microsoft.OpenAPI?label=Latest&logo=nuget)](https://www.nuget.org/packages/Microsoft.OpenAPI/) | | [Microsoft.OpenAPI.YamlReader](./src/Microsoft.OpenApi.YamlReader/README.md) | [![NuGet Version](https://img.shields.io/nuget/vpre/Microsoft.OpenAPI.YamlReader?label=Latest&logo=nuget)](https://www.nuget.org/packages/Microsoft.OpenAPI.YamlReader/) | -| [Microsoft.OpenAPI.Hidi](./src/Microsoft.OpenAPI.Hidi/README.md) | [![NuGet Version](https://img.shields.io/nuget/vpre/Microsoft.OpenAPI.Hidi?label=Latest&logo=nuget)](https://www.nuget.org/packages/Microsoft.OpenAPI.Hidi/) | + +The OpenAPI.NET v3-compatible [Microsoft.OpenApi.Hidi command line tool](https://github.com/microsoft/OpenAPI.NET.OData/blob/main/src/Microsoft.OpenApi.Hidi/readme.md) is maintained separately. +Contribute to Hidi in [OpenAPI.NET.OData's main branch](https://github.com/microsoft/OpenAPI.NET.OData/tree/main). OpenAPI.net is open to contributions. There are a couple of different recommended paths to get contributions into the released version of this library. @@ -74,4 +76,53 @@ The recommended commit types used are: - __ci__ for CI configuration file changes e.g. updating a pipeline - __chore__ for miscallaneous non-sdk changesin the repo e.g. removing an unused file -Adding an exclamation mark after the commit type (`feat!`) or footer with the prefix __BREAKING CHANGE:__ will cause an increment of the _major_ version. \ No newline at end of file +Adding an exclamation mark after the commit type (`feat!`) or footer with the prefix __BREAKING CHANGE:__ will cause an increment of the _major_ version. + +## Updates to public API surface + +Because we need to maintain a compatible public API surface within a major version, this project is using the public API analyzers to ensure no prior public API is changed/removed inadvertently. + +This means that: + +- All entries in an __Unshipped__ document need to be moved to the __Shipped__ document before any public release. +- All new APIs being added need to be __Unshipped__ document before the pull request can be merged, otherwise build will fail with a message like the example below. + +```txt +Error: /home/runner/work/OpenAPI.NET/OpenAPI.NET/src/Microsoft.OpenApi/Models/OpenApiSecurityScheme.cs(39,46): error RS0016: Symbol 'OAuth2MetadataUrl.set' is not part of the declared public API (https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md) [/home/runner/work/OpenAPI.NET/OpenAPI.NET/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj::TargetFramework=net8.0] +``` + +### Update the unshipped document + +To update the unshipped document, simply run the following commands + +```shell +# add the missing public api entries +dotnet format --diagnostics RS0016 +# discard changes to cs files to avoid creating conflicts +git checkout *.cs +``` + +### Move items from unshipped to unshipped document + +```pwsh +. ./scripts/promoteUnshipped.ps1 +``` + +> Note: the promotion of APIs is automated through the dedicated workflow and should result in pull requests being automatically opened. + +## Updating the benchmark information + +To ensure performance of the library does not degrade over time, we have continuous benchmarks running. You might see the continuous integration failing if your pull request changed any model under __src/Microsoft.OpenApi/Models__. + +```txt +Benchmark result for EmptyApiSchema does not match the existing benchmark result (original!=new). Allocated bytes differ: 408 != 416 +``` + +To update the benchmarks, run the following script: + +```shell +cd performance/benchmark +dotnet run -c Release +``` + +Then commit the report files using a "chore" commit. diff --git a/Directory.Build.props b/Directory.Build.props index 8582f5826..5eb725c09 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -8,17 +8,19 @@ https://github.com/Microsoft/OpenAPI.NET https://github.com/microsoft/OpenAPI.NET/releases true + OpenSource + 2027-09 http://go.microsoft.com/fwlink/?LinkID=288890 https://github.com/Microsoft/OpenAPI.NET © Microsoft Corporation. All rights reserved. OpenAPI .NET - 3.0.2 + 3.11.0 true - + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 25f1ec589..000000000 --- a/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env -WORKDIR /app - -COPY ./src ./hidi/src -COPY ./Directory.Build.props ./hidi/Directory.Build.props -COPY ./README.md ./hidi/README.md -WORKDIR /app/hidi -RUN dotnet publish ./src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj -c Release - -FROM mcr.microsoft.com/dotnet/runtime:8.0-jammy-chiseled AS runtime -WORKDIR /app - -COPY --from=build-env /app/hidi/src/Microsoft.OpenApi.Hidi/bin/Release/net8.0 ./ - -VOLUME /app/output -VOLUME /app/openapi.yml -VOLUME /app/api.csdl -VOLUME /app/collection.json -ENV HIDI_CONTAINER=true DOTNET_TieredPGO=1 DOTNET_TC_QuickJitForLoops=1 -ENTRYPOINT ["dotnet", "Microsoft.OpenApi.Hidi.dll"] -LABEL description="# Welcome to Hidi \ -To start transforming OpenAPI documents checkout [the getting started documentation](https://github.com/microsoft/OpenAPI.NET/tree/main/src/Microsoft.OpenApi.Hidi) \ -[Source dockerfile](https://github.com/microsoft/OpenAPI.NET/blob/main/Dockerfile)" diff --git a/Microsoft.OpenApi.sln b/Microsoft.OpenApi.sln deleted file mode 100644 index b91029eca..000000000 --- a/Microsoft.OpenApi.sln +++ /dev/null @@ -1,103 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.1.32210.238 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.OpenApi", "src\Microsoft.OpenApi\Microsoft.OpenApi.csproj", "{A8E50143-69B2-472A-9D45-3F9A05D13202}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4AEDAD90-F854-4940-BFEE-6374CC92CAB0}" - ProjectSection(SolutionItems) = preProject - .editorconfig = .editorconfig - build.cmd = build.cmd - readme.md = readme.md - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.OpenApi.Workbench", "src\Microsoft.OpenApi.Workbench\Microsoft.OpenApi.Workbench.csproj", "{6A5E91E5-0441-46EE-AEB9-8334981B7F08}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.OpenApi.YamlReader", "src\Microsoft.OpenApi.YamlReader\Microsoft.OpenApi.YamlReader.csproj", "{79933258-0126-4382-8755-D50820ECC483}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.OpenApi.Tests", "test\Microsoft.OpenApi.Tests\Microsoft.OpenApi.Tests.csproj", "{AD83F991-DBF3-4251-8613-9CC54C826964}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.OpenApi.Readers.Tests", "test\Microsoft.OpenApi.Readers.Tests\Microsoft.OpenApi.Readers.Tests.csproj", "{1ED3C2C1-E1E7-4925-B4E6-2D969C3F5237}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E546B92F-20A8-49C3-8323-4B25BB78F3E1}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6357D7FD-2DE4-4900-ADB9-ABC37052040A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.OpenApi.Trimming.Tests", "test\Microsoft.OpenApi.Trimming.Tests\Microsoft.OpenApi.Trimming.Tests.csproj", "{1D2E0C6E-B103-4CB6-912E-D56FA1501296}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.OpenApi.Hidi", "src\Microsoft.OpenApi.Hidi\Microsoft.OpenApi.Hidi.csproj", "{538936B4-5E14-4EA3-9FD0-F43E2DD014FB}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.OpenApi.Hidi.Tests", "test\Microsoft.OpenApi.Hidi.Tests\Microsoft.OpenApi.Hidi.Tests.csproj", "{6ADC5D41-EDD2-4206-B815-5DFF739C6832}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PerformanceTests", "performance\benchmark\PerformanceTests.csproj", "{537E49E3-325E-40EE-A90E-7556D4D333AA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "performance", "performance", "{4BB7E3F7-CA7E-45D3-B5AC-5DBB510FD528}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "resultsComparer", "performance\resultsComparer\resultsComparer.csproj", "{5EEA836B-3E08-4BE1-82B8-5236D031B497}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A8E50143-69B2-472A-9D45-3F9A05D13202}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A8E50143-69B2-472A-9D45-3F9A05D13202}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A8E50143-69B2-472A-9D45-3F9A05D13202}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A8E50143-69B2-472A-9D45-3F9A05D13202}.Release|Any CPU.Build.0 = Release|Any CPU - {6A5E91E5-0441-46EE-AEB9-8334981B7F08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6A5E91E5-0441-46EE-AEB9-8334981B7F08}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6A5E91E5-0441-46EE-AEB9-8334981B7F08}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6A5E91E5-0441-46EE-AEB9-8334981B7F08}.Release|Any CPU.Build.0 = Release|Any CPU - {79933258-0126-4382-8755-D50820ECC483}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {79933258-0126-4382-8755-D50820ECC483}.Debug|Any CPU.Build.0 = Debug|Any CPU - {79933258-0126-4382-8755-D50820ECC483}.Release|Any CPU.ActiveCfg = Release|Any CPU - {79933258-0126-4382-8755-D50820ECC483}.Release|Any CPU.Build.0 = Release|Any CPU - {AD83F991-DBF3-4251-8613-9CC54C826964}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AD83F991-DBF3-4251-8613-9CC54C826964}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AD83F991-DBF3-4251-8613-9CC54C826964}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AD83F991-DBF3-4251-8613-9CC54C826964}.Release|Any CPU.Build.0 = Release|Any CPU - {1ED3C2C1-E1E7-4925-B4E6-2D969C3F5237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1ED3C2C1-E1E7-4925-B4E6-2D969C3F5237}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1ED3C2C1-E1E7-4925-B4E6-2D969C3F5237}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1ED3C2C1-E1E7-4925-B4E6-2D969C3F5237}.Release|Any CPU.Build.0 = Release|Any CPU - {1D2E0C6E-B103-4CB6-912E-D56FA1501296}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1D2E0C6E-B103-4CB6-912E-D56FA1501296}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1D2E0C6E-B103-4CB6-912E-D56FA1501296}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1D2E0C6E-B103-4CB6-912E-D56FA1501296}.Release|Any CPU.Build.0 = Release|Any CPU - {538936B4-5E14-4EA3-9FD0-F43E2DD014FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {538936B4-5E14-4EA3-9FD0-F43E2DD014FB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {538936B4-5E14-4EA3-9FD0-F43E2DD014FB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {538936B4-5E14-4EA3-9FD0-F43E2DD014FB}.Release|Any CPU.Build.0 = Release|Any CPU - {6ADC5D41-EDD2-4206-B815-5DFF739C6832}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6ADC5D41-EDD2-4206-B815-5DFF739C6832}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6ADC5D41-EDD2-4206-B815-5DFF739C6832}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6ADC5D41-EDD2-4206-B815-5DFF739C6832}.Release|Any CPU.Build.0 = Release|Any CPU - {537E49E3-325E-40EE-A90E-7556D4D333AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {537E49E3-325E-40EE-A90E-7556D4D333AA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {537E49E3-325E-40EE-A90E-7556D4D333AA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {537E49E3-325E-40EE-A90E-7556D4D333AA}.Release|Any CPU.Build.0 = Release|Any CPU - {5EEA836B-3E08-4BE1-82B8-5236D031B497}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5EEA836B-3E08-4BE1-82B8-5236D031B497}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5EEA836B-3E08-4BE1-82B8-5236D031B497}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5EEA836B-3E08-4BE1-82B8-5236D031B497}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {A8E50143-69B2-472A-9D45-3F9A05D13202} = {E546B92F-20A8-49C3-8323-4B25BB78F3E1} - {6A5E91E5-0441-46EE-AEB9-8334981B7F08} = {E546B92F-20A8-49C3-8323-4B25BB78F3E1} - {79933258-0126-4382-8755-D50820ECC483} = {E546B92F-20A8-49C3-8323-4B25BB78F3E1} - {AD83F991-DBF3-4251-8613-9CC54C826964} = {6357D7FD-2DE4-4900-ADB9-ABC37052040A} - {1ED3C2C1-E1E7-4925-B4E6-2D969C3F5237} = {6357D7FD-2DE4-4900-ADB9-ABC37052040A} - {1D2E0C6E-B103-4CB6-912E-D56FA1501296} = {6357D7FD-2DE4-4900-ADB9-ABC37052040A} - {538936B4-5E14-4EA3-9FD0-F43E2DD014FB} = {E546B92F-20A8-49C3-8323-4B25BB78F3E1} - {6ADC5D41-EDD2-4206-B815-5DFF739C6832} = {6357D7FD-2DE4-4900-ADB9-ABC37052040A} - {5EEA836B-3E08-4BE1-82B8-5236D031B497} = {4BB7E3F7-CA7E-45D3-B5AC-5DBB510FD528} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {9F171EFC-0DB5-4B10-ABFA-AF48D52CC565} - EndGlobalSection -EndGlobal diff --git a/Microsoft.OpenApi.slnx b/Microsoft.OpenApi.slnx new file mode 100644 index 000000000..007071a9e --- /dev/null +++ b/Microsoft.OpenApi.slnx @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index 6a7f787f8..a4cf4171e 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ |--|--| |Models and Writers|[![nuget](https://img.shields.io/nuget/v/Microsoft.OpenApi.svg)](https://www.nuget.org/packages/Microsoft.OpenApi/) | |YamlReader | [![nuget](https://img.shields.io/nuget/v/Microsoft.OpenApi.YamlReader.svg)](https://www.nuget.org/packages/Microsoft.OpenApi.YamlReader/) | -|Hidi|[![nuget](https://img.shields.io/nuget/v/Microsoft.OpenApi.Hidi.svg)](https://www.nuget.org/packages/Microsoft.OpenApi.Hidi/) The **OpenAPI.NET** SDK contains a useful object model for OpenAPI documents in .NET along with common serializers to extract raw OpenAPI JSON and YAML documents from the model. @@ -86,26 +85,9 @@ var outputString = await openApiDocument.SerializeAsJsonAsync(OpenApiSpecVersion ``` # Validating/Testing OpenAPI descriptions -In order to test the validity of an OpenApi document, we avail the following tools: -- [Microsoft.OpenApi.Hidi](https://www.nuget.org/packages/Microsoft.OpenApi.Hidi) - - A commandline tool for validating and transforming OpenAPI descriptions. [Installation guidelines and documentation](https://github.com/microsoft/OpenAPI.NET/blob/main/src/Microsoft.OpenApi.Hidi/readme.md) - -- Microsoft.OpenApi.Workbench - - A workbench tool consisting of a GUI where you can test and convert OpenAPI descriptions in both JSON and YAML from v2-->v3 and vice versa. - - #### Installation guidelines: - 1. Clone the repo locally by running this command: - `git clone https://github.com/microsoft/OpenAPI.NET.git` - 2. Open the solution file `(.sln)` in the root of the project with Visual Studio - 3. Navigate to the `src/Microsoft.OpenApi.Workbench` directory and set it as the startup project - 4. Run the project and you'll see a GUI pop up resembling the one below: - - - ![workbench preview](https://raw.githubusercontent.com/microsoft/OpenAPI.NET/main/docs/images/workbench.png "a screenshot of the workbench application") - - 5. Copy and paste your OpenAPI descriptions in the **Input Content** window or paste the path to the descriptions file in the **Input File** textbox and click on `Convert` to render the results. +[Microsoft.OpenApi.Hidi](https://www.nuget.org/packages/Microsoft.OpenApi.Hidi) is a command line tool for validating and transforming OpenAPI descriptions. +The OpenAPI.NET v3-compatible tool is maintained in [OpenAPI.NET.OData's main branch](https://github.com/microsoft/OpenAPI.NET.OData/tree/main/src/Microsoft.OpenApi.Hidi). +See its [installation guidelines and documentation](https://github.com/microsoft/OpenAPI.NET.OData/blob/main/src/Microsoft.OpenApi.Hidi/readme.md). # Contributing diff --git a/agents.md b/agents.md new file mode 100644 index 000000000..abeed736e --- /dev/null +++ b/agents.md @@ -0,0 +1,7 @@ +# Regex handling + +- Analyze regex patterns for matching complexity and excessive backtracking, including on long and near-matching inputs. Prefer equivalent patterns with less backtracking when available, while preserving matching semantics and target-framework compatibility. +- For fixed patterns on modern targets, use source-generated regexes with explicit match timeouts (`GeneratedRegex` under `NET8_0_OR_GREATER`). +- Use conditional compilation to provide a regular `Regex` with the same pattern and an explicit match timeout for older targets. Do not duplicate regex validation with a manually maintained character scanner. +- Older-runtime regex matching may still time out under load because timeouts use wall-clock time. If consumers encounter this limitation, recommend upgrading to a modern runtime that uses the source-generated implementation. +- Keep shared patterns in constants and reference those constants in validation diagnostics and tests. diff --git a/build.cmd b/build.cmd index 07daf7b6c..4fa04e44a 100644 --- a/build.cmd +++ b/build.cmd @@ -13,11 +13,4 @@ dotnet msbuild %PROJ% /t:restore /p:Configuration=Release dotnet msbuild %PROJ% /t:build /p:Configuration=Release dotnet msbuild %PROJ% /t:pack /p:Configuration=Release;PackageOutputPath=%~dp0artifacts -Echo Building Microsoft.OpenApi.Hidi - -SET PROJ=%~dp0src\Microsoft.OpenApi.Hidi\Microsoft.OpenApi.Hidi.csproj -dotnet msbuild %PROJ% /t:restore /p:Configuration=Release -dotnet msbuild %PROJ% /t:build /p:Configuration=Release -dotnet msbuild %PROJ% /t:pack /p:Configuration=Release;PackageOutputPath=%~dp0artifacts - :end diff --git a/build.sh b/build.sh index 0de30b6df..1e6ae6313 100755 --- a/build.sh +++ b/build.sh @@ -12,11 +12,4 @@ echo "Building Microsoft.OpenApi.YamlReader" PROJ="$(dirname "$0")/src/Microsoft.OpenApi.YamlReader/Microsoft.OpenApi.YamlReader.csproj" dotnet msbuild "$PROJ" /t:restore /p:Configuration=Release dotnet msbuild "$PROJ" /t:build /p:Configuration=Release -dotnet msbuild "$PROJ" /t:pack "/p:Configuration=Release;PackageOutputPath=$(dirname "$0")/artifacts" - -echo "Building Microsoft.OpenApi.Hidi" - -PROJ="$(dirname "$0")/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj" -dotnet msbuild "$PROJ" /t:restore /p:Configuration=Release -dotnet msbuild "$PROJ" /t:build /p:Configuration=Release dotnet msbuild "$PROJ" /t:pack "/p:Configuration=Release;PackageOutputPath=$(dirname "$0")/artifacts" \ No newline at end of file diff --git a/docs/images/workbench.png b/docs/images/workbench.png deleted file mode 100644 index 898fe9b5b..000000000 Binary files a/docs/images/workbench.png and /dev/null differ diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 14eaacdf0..752b60c95 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -32,7 +32,7 @@ One of the key features of OpenAPI.NET is its performance. This version makes it In v1, instances of `$ref` were resolved in a second pass of the document to ensure the target of the reference has been parsed before attempting to resolve it. In v2, reference targets are lazily resolved when reference objects are accessed. This improves load time performance for documents that make heavy use of references. -[How does this change the behavior of external references?] +Because references are lazily loaded and depend on the workspace context, loading a document with unresolved references (internal or external) does not lead to an exception being thrown anymore. Instead warnings are logged in the diagnostics object. This gives you an opportunity to load additional documents in the workspace if needed, [more information](#component-registration-in-a-documents-workspace). ### Results diff --git a/docs/upgrade-guide-3.md b/docs/upgrade-guide-3.md index e874a8998..49e467d24 100644 --- a/docs/upgrade-guide-3.md +++ b/docs/upgrade-guide-3.md @@ -11,11 +11,11 @@ We are excited to announce OpenAPI.NET v3.0! This major update introduces suppor If you are using this library with [AspNetCore OpenAPI versions](https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi) `< 10.0` then you must remain on version `1.x` as it's not compatible with version 3 or above of this library. -If you are using this library with [AspNetCore OpenAPI versions](https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi) `= 10.0` then you must remain on version `2.x` as it's not compatible with version 3 or above of this library. +If you are using this library with [AspNetCore OpenAPI versions](https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi) `= 10.X` then you must remain on version `2.x` as it's not compatible with version 3 or above of this library. If you are using this library with [Swashbuckle.AspNetCore version](https://www.nuget.org/packages/Swashbuckle.AspNetCore/) `< 10.0` then you must remain on version `1.x` as it's not compatible with version 3 or above of this library. -If you are using this library with [Swashbuckle.AspNetCore version](https://www.nuget.org/packages/Swashbuckle.AspNetCore/) `= 10.0` then you must remain on version `2.x` as it's not compatible with version 3 or above of this library. +If you are using this library with [Swashbuckle.AspNetCore version](https://www.nuget.org/packages/Swashbuckle.AspNetCore/) `= 10.X` then you must remain on version `2.x` as it's not compatible with version 3 or above of this library. The latest support policy information for this library, and integration with ASP.NET Core can be found on [the contributing documentation](https://github.com/microsoft/OpenAPI.NET/blob/main/CONTRIBUTING.md#branches-and-support-policy). diff --git a/global.json b/global.json index 3d946171e..c6880be64 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,8 @@ { "sdk": { - "version": "8.0.416" + "version": "10.0.403" + }, + "test": { + "runner": "Microsoft.Testing.Platform" } } \ No newline at end of file diff --git a/install-tool.ps1 b/install-tool.ps1 deleted file mode 100644 index 0b4615c67..000000000 --- a/install-tool.ps1 +++ /dev/null @@ -1,7 +0,0 @@ -$latest = Get-ChildItem .\artifacts\Microsoft.OpenApi.Hidi* | select-object -Last 1 -$version = $latest.Name.Split(".")[3..5] | join-string -Separator "." - -if (Test-Path -Path ./artifacts/hidi.exe) { - dotnet tool uninstall --tool-path artifacts Microsoft.OpenApi.Hidi -} -dotnet tool install --tool-path artifacts --add-source .\artifacts\ --version $version Microsoft.OpenApi.Hidi \ No newline at end of file diff --git a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report-github.md b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report-github.md index 993b5da5e..95726f79a 100644 --- a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report-github.md +++ b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report-github.md @@ -1,18 +1,20 @@ ``` -BenchmarkDotNet v0.15.4, Windows 11 (10.0.26200.6899) -11th Gen Intel Core i7-1185G7 3.00GHz, 1 CPU, 8 logical and 4 physical cores -.NET SDK 8.0.415 - [Host] : .NET 8.0.21 (8.0.21, 8.0.2125.47513), X64 RyuJIT x86-64-v4 - ShortRun : .NET 8.0.21 (8.0.21, 8.0.2125.47513), X64 RyuJIT x86-64-v4 +BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat) +AMD EPYC 7763 2.45GHz, 1 CPU, 4 logical and 2 physical cores +.NET SDK 10.0.400 + [Host] : .NET 8.0.30 (8.0.30, 8.0.3026.36720), X64 RyuJIT x86-64-v3 + ShortRun : .NET 8.0.30 (8.0.30, 8.0.3026.36720), X64 RyuJIT x86-64-v3 Job=ShortRun IterationCount=3 LaunchCount=1 WarmupCount=3 ``` -| Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | -|------------- |---------------:|---------------:|--------------:|-----------:|-----------:|----------:|-------------:| -| PetStoreYaml | 913.5 μs | 3,348.1 μs | 183.52 μs | 58.5938 | 11.7188 | - | 361.25 KB | -| PetStoreJson | 425.1 μs | 327.5 μs | 17.95 μs | 35.1563 | 5.8594 | - | 223.39 KB | -| GHESYaml | 1,765,825.8 μs | 5,036,336.6 μs | 276,058.60 μs | 60000.0000 | 23000.0000 | 4000.0000 | 345082.98 KB | -| GHESJson | 848,197.4 μs | 1,381,723.6 μs | 75,736.93 μs | 33000.0000 | 12000.0000 | 2000.0000 | 206597.63 KB | +| Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|------------- |---------------:|--------------:|-------------:|-----------:|-----------:|----------:|-------------:| +| PetStoreYaml | 569.0 μs | 108.17 μs | 5.93 μs | 19.5313 | - | - | 327.8 KB | +| PetStoreJson | 250.8 μs | 20.85 μs | 1.14 μs | 11.7188 | 1.9531 | - | 209.67 KB | +| GHESYaml | 831,169.7 μs | 217,393.05 μs | 11,916.05 μs | 18000.0000 | 10000.0000 | 2000.0000 | 267570.8 KB | +| GHESJson | 367,711.4 μs | 135,955.63 μs | 7,452.19 μs | 9000.0000 | 8000.0000 | 2000.0000 | 140917.06 KB | +| GHESNextYaml | 1,040,243.2 μs | 167,595.29 μs | 9,186.46 μs | 30000.0000 | 11000.0000 | 2000.0000 | 469507.05 KB | +| GHESNextJson | 615,173.6 μs | 143,051.39 μs | 7,841.13 μs | 22000.0000 | 10000.0000 | 2000.0000 | 345247.91 KB | diff --git a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.csv b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.csv index ec3b99fae..bb632a223 100644 --- a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.csv +++ b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.csv @@ -1,5 +1,7 @@ Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,LargeAddressAware,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MemoryRandomization,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Mean,Error,StdDev,Gen0,Gen1,Gen2,Allocated -PetStoreYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,913.5 μs,"3,348.1 μs",183.52 μs,58.5938,11.7188,0.0000,361.25 KB -PetStoreJson,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,425.1 μs,327.5 μs,17.95 μs,35.1563,5.8594,0.0000,223.39 KB -GHESYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"1,765,825.8 μs","5,036,336.6 μs","276,058.60 μs",60000.0000,23000.0000,4000.0000,345082.98 KB -GHESJson,ShortRun,False,Default,Default,Default,Default,Default,Default,11111111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"848,197.4 μs","1,381,723.6 μs","75,736.93 μs",33000.0000,12000.0000,2000.0000,206597.63 KB +PetStoreYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,569.0 μs,108.17 μs,5.93 μs,19.5313,0.0000,0.0000,327.8 KB +PetStoreJson,ShortRun,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,250.8 μs,20.85 μs,1.14 μs,11.7188,1.9531,0.0000,209.67 KB +GHESYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"831,169.7 μs","217,393.05 μs","11,916.05 μs",18000.0000,10000.0000,2000.0000,267570.8 KB +GHESJson,ShortRun,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"367,711.4 μs","135,955.63 μs","7,452.19 μs",9000.0000,8000.0000,2000.0000,140917.06 KB +GHESNextYaml,ShortRun,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"1,040,243.2 μs","167,595.29 μs","9,186.46 μs",30000.0000,11000.0000,2000.0000,469507.05 KB +GHESNextJson,ShortRun,False,Default,Default,Default,Default,Default,Default,1111,Empty,RyuJit,Default,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET 8.0,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,Default,3,Default,1,Default,Default,Default,Default,Default,Default,16,3,"615,173.6 μs","143,051.39 μs","7,841.13 μs",22000.0000,10000.0000,2000.0000,345247.91 KB diff --git a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.html b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.html index feb037f9f..c9feca148 100644 --- a/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.html +++ b/performance/benchmark/BenchmarkDotNet.Artifacts/results/performance.Descriptions-report.html @@ -2,7 +2,7 @@ -performance.Descriptions-20251024-100447 +performance.Descriptions-20260819-014451 - - """); - writer.WriteLine("

" + document?.Info.Title + "

"); - writer.WriteLine(); - writer.WriteLine($"

API Description: {sourceUrl}

"); - - writer.WriteLine(@"
"); - // write a span for each mermaidcolorscheme - foreach (var style in OpenApiUrlTreeNode.MermaidNodeStyles) - { - writer.WriteLine($"{style.Key.Replace("_", " ", StringComparison.OrdinalIgnoreCase)}"); - } - - writer.WriteLine("
"); - writer.WriteLine("
"); - writer.WriteLine(""); - rootNode.WriteMermaid(writer); - writer.WriteLine(""); - - // Write script tag to include JS library for rendering markdown - writer.WriteLine( - """ - - """); - // Write script tag to include JS library for rendering mermaid - writer.WriteLine(" OpenApiDescriptionOption = new("--openapi", "-d") - { - Description = "Input OpenAPI description file path or URL", - }; - public readonly Option CsdlOption = new("--csdl", "--cs") - { - Description = "Input CSDL file path or URL", - }; - public readonly Option CsdlFilterOption = new("--csdl-filter", "--csf") - { - Description = "Comma delimited list of EntitySets or Singletons to filter CSDL on. e.g. tasks,accounts", - }; - public readonly Option OutputOption = new("--output", "-o") - { - Description = "The output file path for the generated file.", - Arity = ArgumentArity.ZeroOrOne - }; - public readonly Option OutputFolderOption = new("--output-folder", "--of") - { - Description = "The output directory path for the generated files.", - Arity = ArgumentArity.ZeroOrOne - }; - public readonly Option CleanOutputOption = new("--clean-output", "--co") - { - Description = "Overwrite an existing file", - }; - public readonly Option VersionOption = new("--version", "-v") - { - Description = "OpenAPI specification version", - }; - public readonly Option MetadataVersionOption = new("--metadata-version", "--mv") - { - Description = "Graph metadata version to use.", - }; - public readonly Option FormatOption = new("--format", "-f") - { - Description = "File format", - }; - public readonly Option TerseOutputOption = new("--terse-output", "--to") - { - Description = "Produce terse json output", - }; - public readonly Option SettingsFileOption = new("--settings-path", "--sp") - { - Description = "The configuration file with CSDL conversion settings.", - }; - public readonly Option LogLevelOption = new("--log-level", "--ll") - { - Description = "The log level to use when logging messages to the main output.", - DefaultValueFactory = (_) => LogLevel.Information, - }; - public readonly Option FilterByOperationIdsOption = new("--filter-by-operationids", "--op") - { - Description = "Filters OpenApiDocument by comma delimited list of OperationId(s) provided", - }; - public readonly Option FilterByTagsOption = new("--filter-by-tags", "-t") - { - Description = "Filters OpenApiDocument by comma delimited list of Tag(s) provided. Also accepts a single regex.", - }; - public readonly Option FilterByCollectionOption = new("--filter-by-collection", "-c") - { - Description = "Filters OpenApiDocument by Postman collection provided. Provide path to collection file.", - }; - public readonly Option ManifestOption = new("--manifest", "-m") - { - Description = "Path to API manifest file to locate and filter an OpenApiDocument", - }; - public readonly Option InlineLocalOption = new("--inline-local", "--il") - { - Description = "Inline local $ref instances", - }; - public readonly Option InlineExternalOption = new("--inline-external", "--ie") - { - Description = "Inline external $ref instances", - }; - - public IReadOnlyList