diff --git a/.chronus/changes/ReleaseDashboardsStep3-2024-11-11-11-1-42.md b/.chronus/changes/ReleaseDashboardsStep3-2024-11-11-11-1-42.md deleted file mode 100644 index c85b6bfccf..0000000000 --- a/.chronus/changes/ReleaseDashboardsStep3-2024-11-11-11-1-42.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -changeKind: internal -packages: - - "@azure-tools/azure-http-specs" ---- - -Added a .gitignore file \ No newline at end of file diff --git a/.chronus/changes/azure-http-specs_client-namespace-2024-10-29-12-8-41.md b/.chronus/changes/azure-http-specs_client-namespace-2024-10-29-12-8-41.md deleted file mode 100644 index 8616a0116b..0000000000 --- a/.chronus/changes/azure-http-specs_client-namespace-2024-10-29-12-8-41.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -changeKind: feature -packages: - - "@azure-tools/azure-http-specs" ---- - -Add test scenario for clientNamespace \ No newline at end of file diff --git a/.chronus/changes/decorator-common-types-ref-2025-0-16-11-22-58.md b/.chronus/changes/decorator-common-types-ref-2025-0-16-11-22-58.md new file mode 100644 index 0000000000..bc843b7722 --- /dev/null +++ b/.chronus/changes/decorator-common-types-ref-2025-0-16-11-22-58.md @@ -0,0 +1,8 @@ +--- +changeKind: feature +packages: + - "@azure-tools/typespec-autorest" + - "@azure-tools/typespec-azure-resource-manager" +--- + +Add `@externalTypeRef` decorator, to been able to specify an external reference that should be used when emitting. diff --git a/.chronus/changes/dependabot-submodules-core-d378065-2025-0-24-7-49-44.md b/.chronus/changes/dependabot-submodules-core-d378065-2025-0-24-7-49-44.md new file mode 100644 index 0000000000..07fa3b33dc --- /dev/null +++ b/.chronus/changes/dependabot-submodules-core-d378065-2025-0-24-7-49-44.md @@ -0,0 +1,13 @@ +--- +changeKind: internal +packages: + - "@azure-tools/azure-http-specs" + - "@azure-tools/typespec-autorest-canonical" + - "@azure-tools/typespec-autorest" + - "@azure-tools/typespec-azure-core" + - "@azure-tools/typespec-azure-portal-core" + - "@azure-tools/typespec-azure-resource-manager" + - "@azure-tools/typespec-azure-rulesets" + - "@azure-tools/typespec-client-generator-core" +--- + diff --git a/.chronus/changes/fix-duplicate-warning-2025-0-15-11-39-29.md b/.chronus/changes/fix-duplicate-warning-2025-0-15-11-39-29.md new file mode 100644 index 0000000000..add103601c --- /dev/null +++ b/.chronus/changes/fix-duplicate-warning-2025-0-15-11-39-29.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@azure-tools/typespec-azure-resource-manager" +--- + +Exclude template instances from the `no-response-body` rule. diff --git a/.chronus/changes/rust-client-names-2025-0-6-15-6-10.md b/.chronus/changes/rust-client-names-2025-0-6-15-6-10.md deleted file mode 100644 index 6090fc7df1..0000000000 --- a/.chronus/changes/rust-client-names-2025-0-6-15-6-10.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking -changeKind: fix -packages: - - "@azure-tools/azure-http-specs" ---- - -Add Rust to client naming scenarios diff --git a/.chronus/changes/scope-decorator-2024-11-18-12-59-12.md b/.chronus/changes/scope-decorator-2024-11-18-12-59-12.md deleted file mode 100644 index 853a1683ec..0000000000 --- a/.chronus/changes/scope-decorator-2024-11-18-12-59-12.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -changeKind: feature -packages: - - "@azure-tools/typespec-client-generator-core" ---- - -Add `@scope` decorator to define the language scope for operation diff --git a/.chronus/changes/specs_arm_CheckNameAvailability_operations-2024-10-29-17-11-41.md b/.chronus/changes/specs_arm_CheckNameAvailability_operations-2024-10-29-17-11-41.md deleted file mode 100644 index 7c96ca18ab..0000000000 --- a/.chronus/changes/specs_arm_CheckNameAvailability_operations-2024-10-29-17-11-41.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -changeKind: feature -packages: - - "@azure-tools/azure-http-specs" ---- - -Added CheckNameAvailability operations case for ARM tests. \ No newline at end of file diff --git a/.chronus/changes/specs_arm_listing_available_operations-2024-10-29-16-23-15.md b/.chronus/changes/specs_arm_listing_available_operations-2024-10-29-16-23-15.md deleted file mode 100644 index e575d1085c..0000000000 --- a/.chronus/changes/specs_arm_listing_available_operations-2024-10-29-16-23-15.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -changeKind: feature -packages: - - "@azure-tools/azure-http-specs" ---- - -Added listing available operations case for ARM tests. \ No newline at end of file diff --git a/.chronus/changes/specs_arm_location_base_resource-2024-10-29-14-46-26.md b/.chronus/changes/specs_arm_location_base_resource-2024-10-29-14-46-26.md deleted file mode 100644 index ac7899d6b7..0000000000 --- a/.chronus/changes/specs_arm_location_base_resource-2024-10-29-14-46-26.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -changeKind: feature -packages: - - "@azure-tools/azure-http-specs" ---- - -Added Location-based Resource case for ARM tests. \ No newline at end of file diff --git a/.chronus/changes/tcgc-alternate-type-decorator-2024-11-31-14-53-46.md b/.chronus/changes/tcgc-alternate-type-decorator-2024-11-31-14-53-46.md deleted file mode 100644 index 9609dfcc68..0000000000 --- a/.chronus/changes/tcgc-alternate-type-decorator-2024-11-31-14-53-46.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -changeKind: feature -packages: - - "@azure-tools/typespec-client-generator-core" ---- - -add `@alternateType` decorator \ No newline at end of file diff --git a/.chronus/changes/upgrade-deps-jan-2025-2025-0-22-0-4-39.md b/.chronus/changes/upgrade-deps-jan-2025-2025-0-22-0-4-39.md new file mode 100644 index 0000000000..2a9f1c203d --- /dev/null +++ b/.chronus/changes/upgrade-deps-jan-2025-2025-0-22-0-4-39.md @@ -0,0 +1,15 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: dependencies +packages: + - "@azure-tools/azure-http-specs" + - "@azure-tools/typespec-autorest-canonical" + - "@azure-tools/typespec-autorest" + - "@azure-tools/typespec-azure-core" + - "@azure-tools/typespec-azure-portal-core" + - "@azure-tools/typespec-azure-resource-manager" + - "@azure-tools/typespec-azure-rulesets" + - "@azure-tools/typespec-client-generator-core" +--- + +Upgrade dependencies diff --git a/.npmrc b/.npmrc index 3e775efb0f..58dc245adf 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ auto-install-peers=true +manage-package-manager-versions=true diff --git a/core b/core index 98f7cd575b..88c8f3b328 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 98f7cd575be123cafc14c8c99f6e15ddf597b8b0 +Subproject commit 88c8f3b328661d319c56ac42e99eee0fd1b1bae3 diff --git a/eng/feeds/package.json b/eng/feeds/package.json index 204358f493..2a19ee7028 100644 --- a/eng/feeds/package.json +++ b/eng/feeds/package.json @@ -10,6 +10,6 @@ "description": "", "devDependencies": { "@typespec/compiler": "workspace:~", - "vitest": "^2.1.5" + "vitest": "^3.0.4" } } diff --git a/eng/pipelines/deploy-azure-spec-dashboard-storage-account.yml b/eng/pipelines/deploy-azure-spec-dashboard-storage-account.yml deleted file mode 100644 index 59c6aed7b1..0000000000 --- a/eng/pipelines/deploy-azure-spec-dashboard-storage-account.yml +++ /dev/null @@ -1,49 +0,0 @@ -trigger: - branches: - include: - - main - # For patch releases - - release/* - -pr: none - -extends: - template: /eng/pipelines/templates/1es-redirect.yml - parameters: - variables: - - template: /eng/pipelines/templates/variables/globals.yml@self - stages: - - stage: build - displayName: Build and Deploy - - pool: - name: $(WINDOWSPOOL) - image: $(WINDOWSVMIMAGE) - os: windows - - jobs: - - job: build - displayName: Build - - variables: - TYPESPEC_SKIP_DOCUSAURUS_BUILD: true # Disable docusaurus build - - steps: - - checkout: self - submodules: true - - - template: /eng/pipelines/templates/install.yml - parameters: - nodeVersion: "20.x" - - - template: /eng/pipelines/templates/build.yml - - - task: AzureCLI@2 - inputs: - azureSubscription: "TypeSpec Storage" - scriptType: "bash" - scriptLocation: "inlineScript" - inlineScript: | - echo "Uploading files to Azure Blob Storage..." - az storage blob upload-batch --account-name azurespecdashboard --source packages/azure-spec-dashboard/dist/ --destination '$web' --overwrite - displayName: "Upload files to Azure Blob Storage" diff --git a/eng/pipelines/publish.yml b/eng/pipelines/publish.yml index 505b8fdac0..dcf0dac5fb 100644 --- a/eng/pipelines/publish.yml +++ b/eng/pipelines/publish.yml @@ -58,6 +58,17 @@ extends: env: NPM_AUTH_TOKEN: $(azure-sdk-npm-token) + - pwsh: | + $publishSummary = Get-Content "./publish-summary.json" | ConvertFrom-Json + if ($publishSummary.packages.'@azure-tools/azure-http-specs'.published -eq $true) { + Write-Output "Setting PublishAzureHttpSpecs variable to true." + Write-Host "##vso[task.setvariable variable=PublishAzureHttpSpecs]true" + } else { + Write-Output "Setting PublishAzureHttpSpecs variable to false." + Write-Host "##vso[task.setvariable variable=PublishAzureHttpSpecs]false" + } + displayName: "Check if @azure-tools/azure-http-specs was published" + - script: | echo "Publish summary:" cat ./publish-summary.json @@ -97,6 +108,7 @@ extends: - task: AzureCLI@2 displayName: Upload scenario manifest + condition: eq(variables['PublishAzureHttpSpecs'], 'true') inputs: azureSubscription: "TypeSpec Storage" scriptType: "bash" diff --git a/eng/pipelines/templates/install.yml b/eng/pipelines/templates/install.yml index 11d920d4fe..ed522ae555 100644 --- a/eng/pipelines/templates/install.yml +++ b/eng/pipelines/templates/install.yml @@ -22,9 +22,7 @@ steps: key: 'pnpm | "$(Agent.OS)" | pnpm-lock.yaml' path: ${{ parameters.pnpmStorePath }} displayName: Cache pnpm store - - script: | - corepack enable - corepack prepare pnpm --activate + - script: npm install -g pnpm # Pnpm manage-package-manager-versions will respect packageManager field displayName: Install pnpm - script: pnpm config set store-dir ${{ parameters.pnpmStorePath }} displayName: Setup pnpm cache dir diff --git a/package.json b/package.json index dea18b36a0..cc9dc7313b 100644 --- a/package.json +++ b/package.json @@ -37,29 +37,29 @@ "upload-manifest": "pnpm -r --filter=@azure-tools/azure-http-specs run upload-manifest" }, "devDependencies": { - "@chronus/chronus": "^0.13.0", - "@chronus/github": "^0.4.4", - "@eslint/js": "^9.15.0", + "@chronus/chronus": "^0.14.0", + "@chronus/github": "^0.4.5", + "@eslint/js": "^9.18.0", "@pnpm/find-workspace-packages": "^6.0.9", - "@types/node": "~22.7.9", - "@vitest/coverage-v8": "^2.1.5", - "c8": "^10.1.2", - "cspell": "^8.16.0", - "eslint": "^9.15.0", + "@types/node": "~22.10.10", + "@vitest/coverage-v8": "^3.0.4", + "c8": "^10.1.3", + "cspell": "^8.17.2", + "eslint": "^9.18.0", "eslint-plugin-deprecation": "^3.0.0", "eslint-plugin-import": "^2.31.0", "eslint-plugin-unicorn": "^56.0.1", "eslint-plugin-vitest": "^0.5.4", - "playwright": "^1.49.0", - "prettier": "~3.3.3", + "playwright": "^1.50.0", + "prettier": "~3.4.2", "prettier-plugin-astro": "^0.14.1", "prettier-plugin-organize-imports": "~4.1.0", "rimraf": "~6.0.1", "syncpack": "^13.0.0", "tsx": "^4.19.2", - "typescript": "~5.6.3", - "typescript-eslint": "^8.15.0", - "vitest": "^2.1.5" + "typescript": "~5.7.3", + "typescript-eslint": "^8.21.0", + "vitest": "^3.0.4" }, "syncpack": { "dependencyTypes": [ diff --git a/packages/azure-http-specs/CHANGELOG.md b/packages/azure-http-specs/CHANGELOG.md index e9d12573fb..288d739eff 100644 --- a/packages/azure-http-specs/CHANGELOG.md +++ b/packages/azure-http-specs/CHANGELOG.md @@ -1,5 +1,20 @@ # @azure-tools/azure-http-specs +## 0.1.0-alpha.5 + +### Bug Fixes + +- [#2039](https://github.com/Azure/typespec-azure/pull/2039) Add Rust to client naming scenarios + +### Features + +- [#1929](https://github.com/Azure/typespec-azure/pull/1929) Add test scenario for clientNamespace +- [#1934](https://github.com/Azure/typespec-azure/pull/1934) Added CheckNameAvailability operations case for ARM tests. +- [#1924](https://github.com/Azure/typespec-azure/pull/1924) Added ExtensionResource case for ARM tests. +- [#1933](https://github.com/Azure/typespec-azure/pull/1933) Added listing available operations case for ARM tests. +- [#1932](https://github.com/Azure/typespec-azure/pull/1932) Added Location-based Resource case for ARM tests. + + ## 0.1.0-alpha.4 ### Bug Fixes diff --git a/packages/azure-http-specs/package.json b/packages/azure-http-specs/package.json index 5c1a64005a..b3ba1aed76 100644 --- a/packages/azure-http-specs/package.json +++ b/packages/azure-http-specs/package.json @@ -1,6 +1,6 @@ { "name": "@azure-tools/azure-http-specs", - "version": "0.1.0-alpha.4", + "version": "0.1.0-alpha.5", "description": "Azure Spec scenarios and mock apis", "main": "dist/index.js", "type": "module", @@ -35,27 +35,27 @@ }, "homepage": "https://azure.github.io/typespec-azure", "dependencies": { - "@typespec/spector": "workspace:~", - "@typespec/spec-api": "workspace:~" + "@typespec/spec-api": "workspace:~", + "@typespec/spector": "workspace:~" }, "devDependencies": { + "@azure-tools/typespec-autorest": "workspace:~", "@azure-tools/typespec-azure-resource-manager": "workspace:~", "@azure-tools/typespec-client-generator-core": "workspace:~", - "@azure-tools/typespec-autorest": "workspace:~", - "@typespec/openapi3": "workspace:~", - "@typespec/openapi": "workspace:~", "@types/multer": "^1.4.10", - "@types/node": "~22.7.9", - "concurrently": "^9.0.1", - "typescript": "~5.6.3", - "rimraf": "~6.0.1" + "@types/node": "~22.10.10", + "@typespec/openapi": "workspace:~", + "@typespec/openapi3": "workspace:~", + "concurrently": "^9.1.2", + "rimraf": "~6.0.1", + "typescript": "~5.7.3" }, "peerDependencies": { "@azure-tools/typespec-azure-core": "workspace:~", - "@typespec/versioning": "workspace:~", "@typespec/compiler": "workspace:~", - "@typespec/rest": "workspace:~", "@typespec/http": "workspace:~", + "@typespec/rest": "workspace:~", + "@typespec/versioning": "workspace:~", "@typespec/xml": "workspace:~" } } diff --git a/packages/azure-http-specs/spec-summary.md b/packages/azure-http-specs/spec-summary.md index fb2a049513..403acee5b7 100644 --- a/packages/azure-http-specs/spec-summary.md +++ b/packages/azure-http-specs/spec-summary.md @@ -1208,6 +1208,555 @@ Expected response body: } ``` +### Azure_ResourceManager_Resources_ExtensionsResources_createOrUpdate + +- Endpoint: `put https://management.azure.com` + +This test is passed by calling the API 4 times, by providing different parameters. +Resource PUT extension resource by tenant. +Expected path: /providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected request body: + +```json +{ + "properties": { + "description": "valid" + } +} +``` + +Expected response body: + +```json +{ + "id": "/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } +} +``` + +Resource PUT extension resource by subscription. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected request body: + +```json +{ + "properties": { + "description": "valid" + } +} +``` + +Expected response body: + +```json +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } +} +``` + +Resource PUT extension resource by resource group. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected request body: + +```json +{ + "properties": { + "description": "valid" + } +} +``` + +Expected response body: + +```json +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } +} +``` + +Resource PUT extension resource by resource. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected request body: + +```json +{ + "properties": { + "description": "valid" + } +} +``` + +Expected response body: + +```json +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } +} +``` + +### Azure_ResourceManager_Resources_ExtensionsResources_delete + +- Endpoint: `delete https://management.azure.com` + +This test is passed by calling the API 4 times, by providing different parameters. +Resource DELETE extension resource by tenant. +Expected path: /providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview +Expected response status code: 204 + +Resource DELETE extension resource by subscription. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview +Expected response status code: 204 + +Resource DELETE extension resource by resource group. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview +Expected response status code: 204 + +Resource DELETE extension resource by resource. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview +Expected response status code: 204 + +### Azure_ResourceManager_Resources_ExtensionsResources_get + +- Endpoint: `get https://management.azure.com` + +This test is passed by calling the API 4 times, by providing different parameters. +Resource GET extension resource by tenant. +Expected path: /providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected response body: + +```json +{ +"id": "/providers/Azure.ResourceManager.Resources/extensionsResources/extension", +"name": "extension", +"type": "Azure.ResourceManager.Resources/extensionsResources", +"properties":{ + "description": "valid", + "provisioningState": "Succeeded" +}, +"systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", +} +} +``` + +Resource GET extension resource by subscription. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected response body: + +```json +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } +} +``` + +Resource GET extension resource by resource group. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected response body: + +```json +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } +} +``` + +Resource GET extension resource by resource. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected response body: + +```json +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } +} +``` + +### Azure_ResourceManager_Resources_ExtensionsResources_listByScope + +- Endpoint: `get https://management.azure.com` + +This test is passed by calling the API 4 times, by providing different parameters. +Resource LIST extension resources by tenant. +Expected path: /providers/Azure.ResourceManager.Resources/extensionResources +Expected query parameter: api-version=2023-12-01-preview + +Expected response body: + +```json +{ + "value": [{ + "id": "/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + }] +} +``` + +Resource LIST extension resources by subscription. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionResources +Expected query parameter: api-version=2023-12-01-preview + +Expected response body: + +```json +{ + "value": [{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + }] +} +``` + +Resource LIST extension resources by resource group. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionResources +Expected query parameter: api-version=2023-12-01-preview + +Expected response body: + +```json +{ + "value": [{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + }] +} +``` + +Resource LIST extension resources by resource. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionResources +Expected query parameter: api-version=2023-12-01-preview + +Expected response body: + +```json +{ + "value": [{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + }] +} +``` + +### Azure_ResourceManager_Resources_ExtensionsResources_update + +- Endpoint: `patch https://management.azure.com` + +This test is passed by calling the API 4 times, by providing different parameters. +Resource Patch extension resource by tenant. +Expected path: /providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected request body: + +```json +{ + "properties": { + "description": "valid2" + } +} +``` + +Expected response body: + +```json +{ + "id": "/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid2", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } +} +``` + +Resource Patch extension resource by subscription. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected request body: + +```json +{ + "properties": { + "description": "valid2" + } +} +``` + +Expected response body: + +```json +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid2", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } +} +``` + +Resource Patch extension resource by resource group. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected request body: + +```json +{ + "properties": { + "description": "valid2" + } +} +``` + +Expected response body: + +```json +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid2", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } +} +``` + +Resource Patch extension resource by resource. +Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension +Expected query parameter: api-version=2023-12-01-preview + +Expected request body: + +```json +{ + "properties": { + "description": "valid2" + } +} +``` + +Expected response body: + +```json +{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid2", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } +} +``` + ### Azure_ResourceManager_Resources_LocationResources_createOrUpdate - Endpoint: `put https://management.azure.com` diff --git a/packages/azure-http-specs/specs/azure/resource-manager/resources/extension.tsp b/packages/azure-http-specs/specs/azure/resource-manager/resources/extension.tsp new file mode 100644 index 0000000000..e376767624 --- /dev/null +++ b/packages/azure-http-specs/specs/azure/resource-manager/resources/extension.tsp @@ -0,0 +1,559 @@ +import "@typespec/http"; +import "@typespec/rest"; +import "@azure-tools/typespec-azure-core"; +import "@azure-tools/typespec-azure-resource-manager"; +import "@typespec/spector"; + +using TypeSpec.Http; +using TypeSpec.Rest; +using Azure.Core; +using Azure.ResourceManager; +using TypeSpec.OpenAPI; +using Spector; + +namespace Azure.ResourceManager.Resources; + +model ExtensionsResource is ExtensionResource { + ...ResourceNameParameter; +} + +/** ExtensionsResource properties */ +model ExtensionsResourceProperties { + @doc("The description of the resource.") + description?: string; + + /** The status of the last operation. */ + @visibility("read") + provisioningState?: ProvisioningState; +} + +/** The interface of extensions resources, + * it contains 4 kinds of scopes (resource, resource group, subscription and tenant) + */ +@armResourceOperations +interface ExtensionsResources { + @scenario + @scenarioDoc(""" + This test is passed by calling the API 4 times, by providing different parameters. + Resource GET extension resource by tenant. + Expected path: /providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected response body: + ```json + { + "id": "/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + + Resource GET extension resource by subscription. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected response body: + ```json + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + + Resource GET extension resource by resource group. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected response body: + ```json + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + + Resource GET extension resource by resource. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected response body: + ```json + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + """) + get is ArmResourceRead; + + @scenario + @scenarioDoc(""" + This test is passed by calling the API 4 times, by providing different parameters. + Resource PUT extension resource by tenant. + Expected path: /providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected request body: + ```json + { + "properties":{ + "description": "valid", + } + } + ``` + + Expected response body: + ```json + { + "id": "/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + + Resource PUT extension resource by subscription. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected request body: + ```json + { + "properties":{ + "description": "valid", + } + } + ``` + + Expected response body: + ```json + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + + Resource PUT extension resource by resource group. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected request body: + ```json + { + "properties":{ + "description": "valid", + } + } + ``` + + Expected response body: + ```json + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + + Resource PUT extension resource by resource. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected request body: + ```json + { + "properties":{ + "description": "valid", + } + } + ``` + + Expected response body: + ```json + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + """) + createOrUpdate is ArmResourceCreateOrReplaceAsync; + + @scenario + @scenarioDoc(""" + This test is passed by calling the API 4 times, by providing different parameters. + Resource Patch extension resource by tenant. + Expected path: /providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected request body: + ```json + { + "properties":{ + "description": "valid2", + } + } + ``` + + Expected response body: + ```json + { + "id": "/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid2", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + + Resource Patch extension resource by subscription. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected request body: + ```json + { + "properties":{ + "description": "valid2", + } + } + ``` + + Expected response body: + ```json + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid2", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + + Resource Patch extension resource by resource group. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected request body: + ```json + { + "properties":{ + "description": "valid2", + } + } + ``` + + Expected response body: + ```json + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid2", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + + Resource Patch extension resource by resource. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + + Expected request body: + ```json + { + "properties":{ + "description": "valid2", + } + } + ``` + + Expected response body: + ```json + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid2", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + } + ``` + """) + update is ArmResourcePatchSync; + + @scenario + @scenarioDoc(""" + This test is passed by calling the API 4 times, by providing different parameters. + Resource DELETE extension resource by tenant. + Expected path: /providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + Expected response status code: 204 + + Resource DELETE extension resource by subscription. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + Expected response status code: 204 + + Resource DELETE extension resource by resource group. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + Expected response status code: 204 + + Resource DELETE extension resource by resource. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension + Expected query parameter: api-version=2023-12-01-preview + Expected response status code: 204 + """) + delete is ArmResourceDeleteSync; + + @scenario + @scenarioDoc(""" + This test is passed by calling the API 4 times, by providing different parameters. + Resource LIST extension resources by tenant. + Expected path: /providers/Azure.ResourceManager.Resources/extensionResources + Expected query parameter: api-version=2023-12-01-preview + + Expected response body: + ```json + { + "value": [{ + "id": "/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + }] + } + ``` + + Resource LIST extension resources by subscription. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionResources + Expected query parameter: api-version=2023-12-01-preview + + Expected response body: + ```json + { + "value": [{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + }] + } + ``` + + Resource LIST extension resources by resource group. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionResources + Expected query parameter: api-version=2023-12-01-preview + + Expected response body: + ```json + { + "value": [{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + }] + } + ``` + + Resource LIST extension resources by resource. + Expected path: /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionResources + Expected query parameter: api-version=2023-12-01-preview + + Expected response body: + ```json + { + "value": [{ + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension", + "name": "extension", + "type": "Azure.ResourceManager.Resources/extensionsResources", + "properties":{ + "description": "valid", + "provisioningState": "Succeeded" + }, + "systemData": { + "createdBy": "AzureSDK", + "createdByType": "User", + "createdAt": , + "lastModifiedBy": "AzureSDK", + "lastModifiedAt": , + "lastModifiedByType": "User", + } + }] + } + ``` + """) + listByScope is ArmResourceListByParent; +} diff --git a/packages/azure-http-specs/specs/azure/resource-manager/resources/main.tsp b/packages/azure-http-specs/specs/azure/resource-manager/resources/main.tsp index 7f5e5f47d2..e08712b643 100644 --- a/packages/azure-http-specs/specs/azure/resource-manager/resources/main.tsp +++ b/packages/azure-http-specs/specs/azure/resource-manager/resources/main.tsp @@ -7,6 +7,7 @@ import "@azure-tools/typespec-client-generator-core"; import "./toplevel.tsp"; import "./nested.tsp"; import "./singleton.tsp"; +import "./extension.tsp"; import "./location.tsp"; using TypeSpec.Http; diff --git a/packages/azure-http-specs/specs/azure/resource-manager/resources/mockapi.ts b/packages/azure-http-specs/specs/azure/resource-manager/resources/mockapi.ts index ee5d55331e..70d724674d 100644 --- a/packages/azure-http-specs/specs/azure/resource-manager/resources/mockapi.ts +++ b/packages/azure-http-specs/specs/azure/resource-manager/resources/mockapi.ts @@ -79,6 +79,500 @@ const validLocationResource = { }, }; +const validResourceGroupExtensionsResource = { + id: `/subscriptions/${SUBSCRIPTION_ID_EXPECTED}/resourceGroups/${RESOURCE_GROUP_EXPECTED}/providers/Azure.ResourceManager.Resources/extensionsResources/extension`, + name: "extension", + type: "Azure.ResourceManager.Resources/extensionsResources", + properties: { + description: "valid", + provisioningState: "Succeeded", + }, + systemData: { + createdBy: "AzureSDK", + createdByType: "User", + createdAt: "2024-10-04T00:56:07.442Z", + lastModifiedBy: "AzureSDK", + lastModifiedAt: "2024-10-04T00:56:07.442Z", + lastModifiedByType: "User", + }, +}; + +const validSubscriptionExtensionsResource = { + id: `/subscriptions/${SUBSCRIPTION_ID_EXPECTED}/providers/Azure.ResourceManager.Resources/extensionsResources/extension`, + name: "extension", + type: "Azure.ResourceManager.Resources/extensionsResources", + properties: { + description: "valid", + provisioningState: "Succeeded", + }, + systemData: { + createdBy: "AzureSDK", + createdByType: "User", + createdAt: "2024-10-04T00:56:07.442Z", + lastModifiedBy: "AzureSDK", + lastModifiedAt: "2024-10-04T00:56:07.442Z", + lastModifiedByType: "User", + }, +}; + +const validTenantExtensionsResource = { + id: `/providers/Azure.ResourceManager.Resources/extensionsResources/extension`, + name: "extension", + type: "Azure.ResourceManager.Resources/extensionsResources", + properties: { + description: "valid", + provisioningState: "Succeeded", + }, + systemData: { + createdBy: "AzureSDK", + createdByType: "User", + createdAt: "2024-10-04T00:56:07.442Z", + lastModifiedBy: "AzureSDK", + lastModifiedAt: "2024-10-04T00:56:07.442Z", + lastModifiedByType: "User", + }, +}; + +const validResourceExtensionsResource = { + id: `/subscriptions/${SUBSCRIPTION_ID_EXPECTED}/resourceGroups/${RESOURCE_GROUP_EXPECTED}/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/top/providers/Azure.ResourceManager.Resources/extensionsResources/extension`, + name: "extension", + type: "Azure.ResourceManager.Resources/extensionsResources", + properties: { + description: "valid", + provisioningState: "Succeeded", + }, + systemData: { + createdBy: "AzureSDK", + createdByType: "User", + createdAt: "2024-10-04T00:56:07.442Z", + lastModifiedBy: "AzureSDK", + lastModifiedAt: "2024-10-04T00:56:07.442Z", + lastModifiedByType: "User", + }, +}; + +// extension tracked resource +Scenarios.Azure_ResourceManager_Resources_ExtensionsResources_get = passOnSuccess([ + { + uri: "/subscriptions/:subscriptionId/resourceGroups/:resourceGroup/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "get", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + resourceGroup: RESOURCE_GROUP_EXPECTED, + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 200, + body: json(validResourceGroupExtensionsResource), + }, + kind: "MockApiDefinition", + }, + { + uri: "/subscriptions/:subscriptionId/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "get", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 200, + body: json(validSubscriptionExtensionsResource), + }, + kind: "MockApiDefinition", + }, + { + uri: "/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "get", + request: { + params: { + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 200, + body: json(validTenantExtensionsResource), + }, + kind: "MockApiDefinition", + }, + { + uri: "/subscriptions/:subscriptionId/resourceGroups/:resourceGroup/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/:topLevelResourceName/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "get", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + resourceGroup: RESOURCE_GROUP_EXPECTED, + extensionName: "extension", + topLevelResourceName: "top", + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 200, + body: json(validResourceExtensionsResource), + }, + kind: "MockApiDefinition", + }, +]); + +Scenarios.Azure_ResourceManager_Resources_ExtensionsResources_createOrUpdate = passOnSuccess([ + { + uri: "/subscriptions/:subscriptionId/resourceGroups/:resourceGroup/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "put", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + resourceGroup: RESOURCE_GROUP_EXPECTED, + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + body: { + properties: { + description: "valid", + }, + }, + }, + response: { + status: 200, + body: json(validResourceGroupExtensionsResource), + }, + kind: "MockApiDefinition", + }, + { + uri: "/subscriptions/:subscriptionId/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "put", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + body: { + properties: { + description: "valid", + }, + }, + }, + response: { + status: 200, + body: json(validSubscriptionExtensionsResource), + }, + kind: "MockApiDefinition", + }, + { + uri: "/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "put", + request: { + params: { + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + body: { + properties: { + description: "valid", + }, + }, + }, + response: { + status: 200, + body: json(validTenantExtensionsResource), + }, + kind: "MockApiDefinition", + }, + { + uri: "/subscriptions/:subscriptionId/resourceGroups/:resourceGroup/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/:topLevelResourceName/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "put", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + resourceGroup: RESOURCE_GROUP_EXPECTED, + topLevelResourceName: "top", + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + body: { + properties: { + description: "valid", + }, + }, + }, + response: { + status: 200, + body: json(validResourceExtensionsResource), + }, + kind: "MockApiDefinition", + }, +]); + +Scenarios.Azure_ResourceManager_Resources_ExtensionsResources_update = passOnSuccess([ + { + uri: "/subscriptions/:subscriptionId/resourceGroups/:resourceGroup/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "patch", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + resourceGroup: RESOURCE_GROUP_EXPECTED, + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + body: { + properties: { + description: "valid2", + }, + }, + headers: { + "Content-Type": "application/json", + }, + }, + response: { + status: 200, + body: json({ + ...validResourceGroupExtensionsResource, + properties: { + provisioningState: "Succeeded", + description: "valid2", + }, + }), + }, + kind: "MockApiDefinition", + }, + { + uri: "/subscriptions/:subscriptionId/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "patch", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + body: { + properties: { + description: "valid2", + }, + }, + headers: { + "Content-Type": "application/json", + }, + }, + response: { + status: 200, + body: json({ + ...validSubscriptionExtensionsResource, + properties: { + provisioningState: "Succeeded", + description: "valid2", + }, + }), + }, + kind: "MockApiDefinition", + }, + { + uri: "/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "patch", + request: { + params: { + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + body: { + properties: { + description: "valid2", + }, + }, + headers: { + "Content-Type": "application/json", + }, + }, + response: { + status: 200, + body: json({ + ...validTenantExtensionsResource, + properties: { + provisioningState: "Succeeded", + description: "valid2", + }, + }), + }, + kind: "MockApiDefinition", + }, + { + uri: "/subscriptions/:subscriptionId/resourceGroups/:resourceGroup/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/:topLevelResourceName/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "patch", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + resourceGroup: RESOURCE_GROUP_EXPECTED, + topLevelResourceName: "top", + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + body: { + properties: { + description: "valid2", + }, + }, + headers: { + "Content-Type": "application/json", + }, + }, + response: { + status: 200, + body: json({ + ...validResourceExtensionsResource, + properties: { + provisioningState: "Succeeded", + description: "valid2", + }, + }), + }, + kind: "MockApiDefinition", + }, +]); + +Scenarios.Azure_ResourceManager_Resources_ExtensionsResources_delete = passOnSuccess([ + { + uri: "/subscriptions/:subscriptionId/resourceGroups/:resourceGroup/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "delete", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + resourceGroup: RESOURCE_GROUP_EXPECTED, + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 204, + }, + kind: "MockApiDefinition", + }, + { + uri: "/subscriptions/:subscriptionId/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "delete", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 204, + }, + kind: "MockApiDefinition", + }, + { + uri: "/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "delete", + request: { + params: { + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 204, + }, + kind: "MockApiDefinition", + }, + { + uri: "/subscriptions/:subscriptionId/resourceGroups/:resourceGroup/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/:topLevelResourceName/providers/Azure.ResourceManager.Resources/extensionsResources/:extensionName", + method: "delete", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + resourceGroup: RESOURCE_GROUP_EXPECTED, + topLevelResourceName: "top", + extensionName: "extension", + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 204, + }, + kind: "MockApiDefinition", + }, +]); + +Scenarios.Azure_ResourceManager_Resources_ExtensionsResources_listByScope = passOnSuccess([ + { + uri: "/subscriptions/:subscriptionId/resourceGroups/:resourceGroup/providers/Azure.ResourceManager.Resources/extensionsResources", + method: "get", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + resourceGroup: RESOURCE_GROUP_EXPECTED, + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 200, + body: json({ + value: [validResourceGroupExtensionsResource], + }), + }, + kind: "MockApiDefinition", + }, + { + uri: "/subscriptions/:subscriptionId/providers/Azure.ResourceManager.Resources/extensionsResources", + method: "get", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 200, + body: json({ + value: [validSubscriptionExtensionsResource], + }), + }, + kind: "MockApiDefinition", + }, + { + uri: "/providers/Azure.ResourceManager.Resources/extensionsResources", + method: "get", + request: { + params: { + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 200, + body: json({ + value: [validTenantExtensionsResource], + }), + }, + kind: "MockApiDefinition", + }, + { + uri: "/subscriptions/:subscriptionId/resourceGroups/:resourceGroup/providers/Azure.ResourceManager.Resources/topLevelTrackedResources/:topLevelResourceName/providers/Azure.ResourceManager.Resources/extensionsResources", + method: "get", + request: { + params: { + subscriptionId: SUBSCRIPTION_ID_EXPECTED, + resourceGroup: RESOURCE_GROUP_EXPECTED, + topLevelResourceName: "top", + "api-version": "2023-12-01-preview", + }, + }, + response: { + status: 200, + body: json({ + value: [validResourceExtensionsResource], + }), + }, + kind: "MockApiDefinition", + }, +]); + // location resource Scenarios.Azure_ResourceManager_Resources_LocationResources_get = passOnSuccess({ uri: "/subscriptions/:subscriptionId/providers/Azure.ResourceManager.Resources/locations/:location/locationResources/:locationResourceName", diff --git a/packages/azure-spec-dashboard/CHANGELOG.md b/packages/azure-spec-dashboard/CHANGELOG.md deleted file mode 100644 index 39a02e1161..0000000000 --- a/packages/azure-spec-dashboard/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# @azure-tools/azure-spec-dashboard - -## 0.1.0-alpha.0 - -- Initial Release of Azure Spector Dashboard diff --git a/packages/azure-spec-dashboard/README.md b/packages/azure-spec-dashboard/README.md deleted file mode 100644 index cf9138a184..0000000000 --- a/packages/azure-spec-dashboard/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Azure Spector Dashboard - -## Dev - -```bash -npm run start -# or -npm run dev -``` - -## Show the test generator - -Add `?showtest=true` query parameter to url http://localhost:5173/?showtest=true diff --git a/packages/azure-spec-dashboard/index.html b/packages/azure-spec-dashboard/index.html deleted file mode 100644 index c99365845c..0000000000 --- a/packages/azure-spec-dashboard/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - Azure Spector Dashboard - - -
- - - diff --git a/packages/azure-spec-dashboard/package.json b/packages/azure-spec-dashboard/package.json deleted file mode 100644 index 2e46565621..0000000000 --- a/packages/azure-spec-dashboard/package.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "@azure-tools/azure-spec-dashboard", - "private": true, - "version": "0.1.0-alpha.0", - "description": "Azure Spector Dashboard website", - "main": "dist/index.js", - "type": "module", - "scripts": { - "start": "vite", - "dev": "vite", - "build": "tsc && vite build", - "preview": "vite preview", - "clean": "rimraf dist/ temp/", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "engines": { - "node": ">=18.0.0" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/Azure/typespec-azure.git" - }, - "author": "Microsoft", - "license": "MIT", - "bugs": { - "url": "https://github.com/Azure/typespec-azure/issues" - }, - "homepage": "https://azure.github.io/typespec-azure", - "dependencies": { - "@typespec/spec-coverage-sdk": "workspace:~", - "@emotion/react": "^11.13.3", - "@fluentui/react-components": "~9.55.0", - "@fluentui/react-icons": "^2.0.260", - "react": "~18.3.1", - "react-dom": "~18.3.1", - "react-markdown": "^9.0.1" - }, - "devDependencies": { - "@types/react": "~18.3.11", - "@types/react-dom": "~18.3.0", - "@vitejs/plugin-react": "~4.3.2", - "rimraf": "~6.0.1", - "rollup-plugin-visualizer": "~5.12.0", - "typescript": "~5.6.3", - "vite": "^5.4.8" - } -} diff --git a/packages/azure-spec-dashboard/src/apis.ts b/packages/azure-spec-dashboard/src/apis.ts deleted file mode 100644 index a3f9ecfea3..0000000000 --- a/packages/azure-spec-dashboard/src/apis.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { - CoverageReport, - ResolvedCoverageReport, - ScenarioManifest, - SpecCoverageClient, -} from "@typespec/spec-coverage-sdk"; - -const storageAccountName = "typespec"; - -export type GeneratorNames = - | "@azure-tools/typespec-python" - | "@azure-tools/typespec-go" - | "@azure-tools/typespec-csharp" - | "@azure-typespec/http-client-csharp" - | "@azure-tools/typespec-ts-rlc" - | "@azure-tools/typespec-ts-modular" - | "@azure-tools/typespec-java" - | "@azure-tools/typespec-cpp" - | "@azure-tools/typespec-rust" - | "test"; -const query = new URLSearchParams(window.location.search); -const generatorNames: GeneratorNames[] = [ - "@azure-tools/typespec-python", - "@azure-tools/typespec-go", - "@azure-tools/typespec-csharp", - "@azure-typespec/http-client-csharp", - "@azure-tools/typespec-ts-rlc", - "@azure-tools/typespec-ts-modular", - "@azure-tools/typespec-java", - "@azure-tools/typespec-cpp", - "@azure-tools/typespec-rust", - ...(query.has("showtest") ? (["test"] as const) : []), -]; - -export interface CoverageSummary { - manifest: ScenarioManifest; - generatorReports: Record; -} - -let client: SpecCoverageClient | undefined; -export function getCoverageClient() { - if (client === undefined) { - client = new SpecCoverageClient(storageAccountName); - } - return client; -} - -let manifestClient: SpecCoverageClient | undefined; -export function getManifestClient() { - if (manifestClient === undefined) { - manifestClient = new SpecCoverageClient(storageAccountName, { - containerName: "manifests-azure", - }); - } - return manifestClient; -} - -export function getCoverageForMode( - generatorReports: { [mode: string]: Record }, - key: string, - mode: string, -): CoverageReport { - /* - * The generator reports is an array from of reports from Standard and Azure mode in any order. - * So, if the first report is from Azure mode, the second one is from Standard mode and vice versa. - * When the mode is standard, check if the first report is from Azure mode, if so, return the second one. - * Otherwise, return the first one. - * When the mode is azure, check if the first report is from Azure mode, if so, return the first one. - * Otherwise, return the second one. - */ - const reports = (generatorReports["azure"] as any)[key]; - const isFirstReportAzure = - reports[0]["scenariosMetadata"].packageName === "@azure-tools/azure-http-specs"; - if (mode === "standard") { - return isFirstReportAzure ? reports[1] : reports[0]; - } else { - // mode === "azure" - return isFirstReportAzure ? reports[0] : reports[1]; - } -} - -export async function getCoverageSummaries(): Promise { - const coverageClient = getCoverageClient(); - const manifestClient = getManifestClient(); - const [manifests, generatorReports] = await Promise.all([ - manifestClient.manifest.get(), - loadReports(coverageClient, generatorNames), - ]); - - const manifestStandard = manifests.filter( - (manifest: ScenarioManifest) => manifest.setName !== "@azure-tools/azure-http-specs", - )[0]; - const manifestAzure = manifests.filter( - (manifest: ScenarioManifest) => manifest.setName === "@azure-tools/azure-http-specs", - )[0]; - - (generatorReports["standard"] as any) = {}; - - for (const key in generatorReports["azure"]) { - if (!(generatorReports["azure"] as any)[key]) { - (generatorReports["standard"] as any)[key] = undefined; - continue; - } - if ( - !(generatorReports["azure"] as any)[key][1] || - !(generatorReports["azure"] as any)[key][0] - ) { - (generatorReports["azure"] as any)[key] = undefined; - (generatorReports["standard"] as any)[key] = undefined; - continue; - } - (generatorReports["standard"] as any)[key] = { - ...getCoverageForMode(generatorReports, key, "standard"), - generatorMetadata: (generatorReports["azure"] as any)[key]["generatorMetadata"], - }; - (generatorReports["azure"] as any)[key] = { - ...getCoverageForMode(generatorReports, key, "azure"), - generatorMetadata: (generatorReports["azure"] as any)[key]["generatorMetadata"], - }; - } - - return [ - { - manifest: manifestAzure, - generatorReports: generatorReports["azure"], - }, - { - manifest: manifestStandard, - generatorReports: generatorReports["standard"], - }, - ]; -} - -enum GeneratorMode { - azure = "azure", -} - -async function loadReports( - coverageClient: SpecCoverageClient, - generatorNames: GeneratorNames[], -): Promise<{ [mode: string]: Record }> { - const results = await Promise.all( - Object.keys(GeneratorMode).map( - async ( - mode, - ): Promise<[string, Record]> => { - const items = await Promise.all( - generatorNames.map( - async ( - generatorName, - ): Promise<[GeneratorNames, ResolvedCoverageReport | undefined]> => { - try { - const report = await coverageClient.coverage.getLatestCoverageFor( - generatorName, - mode, - ); - return [generatorName, report]; - } catch (error) { - // eslint-disable-next-line no-console - console.error("Error resolving report", error); - return [generatorName, undefined]; - } - }, - ), - ); - return [mode, Object.fromEntries(items) as any]; - }, - ), - ); - - return results.reduce<{ - [mode: string]: Record; - }>((results, [mode, reports]) => { - results[mode] = reports; - return results; - }, {}); -} diff --git a/packages/azure-spec-dashboard/src/app.tsx b/packages/azure-spec-dashboard/src/app.tsx deleted file mode 100644 index 884991b94a..0000000000 --- a/packages/azure-spec-dashboard/src/app.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { FluentProvider, webLightTheme } from "@fluentui/react-components"; -import { FunctionComponent, useState } from "react"; -import { CoverageSummary, getCoverageSummaries } from "./apis.js"; -import { Dashboard } from "./components/dashboard.js"; -import { useEffectAsync } from "./utils.js"; - -export const App: FunctionComponent = () => { - const [coverageSummaries, setCoverageSummaries] = useState( - undefined, - ); - - useEffectAsync(async () => { - const coverageSummaries = await getCoverageSummaries(); - - if (coverageSummaries) { - setCoverageSummaries(() => coverageSummaries); - } - }, []); - return ( - -
- {coverageSummaries ? ( - - ) : ( - "Loading" - )} -
-
- ); -}; diff --git a/packages/azure-spec-dashboard/src/components/dashboard-table.tsx b/packages/azure-spec-dashboard/src/components/dashboard-table.tsx deleted file mode 100644 index 69b77b9443..0000000000 --- a/packages/azure-spec-dashboard/src/components/dashboard-table.tsx +++ /dev/null @@ -1,337 +0,0 @@ -import { css } from "@emotion/react"; -import { Popover, PopoverSurface, PopoverTrigger } from "@fluentui/react-components"; -import { CodeBlock16Filled, Print16Filled } from "@fluentui/react-icons"; -import { - ResolvedCoverageReport, - ScenarioData, - ScenarioManifest, -} from "@typespec/spec-coverage-sdk"; -import { FunctionComponent, useCallback, useMemo, useState } from "react"; -import { CoverageSummary, GeneratorNames } from "../apis.js"; -import { Colors } from "../constants.js"; -import { GeneratorInformation } from "./generator-information.js"; -import { ScenarioGroupRatioStatusBox } from "./scenario-group-status.js"; -import { ScenarioStatusBox } from "./scenario-status.js"; -import { RowLabelCell } from "./tree-table/row-label-cell.js"; -import { ManifestTreeNode, TreeTableRow } from "./tree-table/types.js"; - -export interface DashboardTableProps { - coverageSummary: CoverageSummary; -} - -function buildTreeRows( - node: ManifestTreeNode, - expandedRows: Record, - toggleExpand: (key: string) => void, - depth = 0, -): TreeTableRow[] { - const rows: TreeTableRow[] = []; - if (!node.children) { - return []; - } - for (const child of Object.values(node.children)) { - const hasChildren = Boolean(child.children && Object.keys(child.children).length > 0); - const key = child.fullName; - - const expanded = expandedRows[key] ?? false; - rows.push({ - key, - item: child, - expanded, - depth, - hasChildren, - index: -1, - toggleExpand: () => toggleExpand(key), - }); - if (hasChildren && expanded) { - for (const row of buildTreeRows(child, expandedRows, toggleExpand, depth + 1)) { - rows.push(row); - } - } - } - for (const [index, row] of rows.entries()) { - row.index = index; - row.key = index.toString(); - } - return rows; -} - -export const DashboardTable: FunctionComponent = ({ coverageSummary }) => { - const languages: GeneratorNames[] = Object.keys(coverageSummary.generatorReports) as any; - const tree = useMemo(() => createTree(coverageSummary.manifest), [coverageSummary.manifest]); - - const [expandedRows, setExpandedRows] = useState>({}); - const toggleExpand = useCallback( - (key: string) => { - setExpandedRows((state) => { - return { ...state, [key]: !state[key] }; - }); - }, - [setExpandedRows], - ); - const treeRows = useMemo(() => { - return buildTreeRows(tree, expandedRows, toggleExpand); - }, [tree, expandedRows, toggleExpand]); - - const rows = treeRows.map((x) => { - return ( - - ); - }); - - return ( - - - - - {rows} -
- ); -}; - -export interface DashboardRowProps { - row: TreeTableRow; - languages: GeneratorNames[]; - coverageSummary: CoverageSummary; -} - -const DashboardRow: FunctionComponent = ({ - row, - languages, - coverageSummary, -}) => { - const scenarioData = row.item.scenario; - return ( - - - {languages.map((lang) => ( - - {scenarioData ? ( - - ) : ( - - )} - - ))} - - ); -}; - -interface ScenarioGroupStatusBoxProps { - coverageSummary: CoverageSummary; - lang: GeneratorNames; - group: string; -} -const ScenarioGroupStatusBox: FunctionComponent = ({ - lang, - coverageSummary, - group, -}) => { - const report = coverageSummary.generatorReports[lang]; - const ratio = report ? getCompletedRatio(coverageSummary.manifest.scenarios, report, group) : 0; - return ; -}; - -function getCompletedRatio( - scenarios: ScenarioData[], - report: ResolvedCoverageReport, - scope: string = "", -) { - const filtered = scenarios.filter((x) => x.name.startsWith(scope)); - let coveredCount = 0; - for (const scenario of filtered) { - const status = report.results[scenario.name]; - if (status === "pass" || status === "not-applicable" || status === "not-supported") { - coveredCount++; - } - } - - return coveredCount / filtered.length; -} - -interface DashboardHeaderRowProps { - coverageSummary: CoverageSummary; -} - -const DashboardHeaderRow: FunctionComponent = ({ coverageSummary }) => { - const data: [string, number, ResolvedCoverageReport | undefined][] = Object.entries( - coverageSummary.generatorReports, - ).map(([language, report]) => { - if (report === undefined) { - return [language, 0, undefined]; - } - return [language, getCompletedRatio(coverageSummary.manifest.scenarios, report), report]; - }); - const tableHeaderName = - coverageSummary.manifest.setName === "@azure-tools/azure-http-specs" ? "Azure" : "Standard"; - const tableHeader = Scenario name ({tableHeaderName}); - return ( - - {tableHeader} - {data.map(([lang, status, report]) => ( - - ))} - - ); -}; -const TableStyles = css({ - borderCollapse: "collapse", - "& tr:nth-of-type(2n)": { - backgroundColor: Colors.bgSubtle, - }, - "& td, & th": { - border: `1px solid ${Colors.borderDefault}`, - height: "32px", - }, - "& th": { - padding: "6px 13px", - backgroundColor: Colors.bgSubtle, - }, -}); - -const ScenarioStatusCellStyles = css({ - padding: 0, - width: 120, -}); - -export interface GeneratorHeaderCellProps { - status: number; - report: ResolvedCoverageReport | undefined; - language: string; -} - -export const GeneratorHeaderCell: FunctionComponent = ({ - status, - report, - language, -}) => { - return ( - -
-
- - -
{report?.generatorMetadata?.name ?? language}
-
- - {report && } - -
-
-
- - - {report?.generatorMetadata?.version ?? "?"} -
-
- - {report?.scenariosMetadata?.version ?? "?"} -
-
- -
-
- - ); -}; - -const versionStyles = css({ - fontSize: "9pt", - fontWeight: "normal", - color: Colors.lightText, - padding: 5, - textOverflow: "ellipsis", - whiteSpace: "nowrap", - display: "flex", - width: 60, - overflow: "hidden", -}); - -function createTree(manifest: ScenarioManifest): ManifestTreeNode { - const root: ManifestTreeNode = { name: "", fullName: "", children: {} }; - - const sortedScenarios = [...manifest.scenarios].sort((a, b) => a.name.localeCompare(b.name)); - for (const scenario of sortedScenarios) { - const segments = scenario.name.split("_"); - let current: ManifestTreeNode = root; - - for (const [index, segment] of segments.entries()) { - if (!(segment in current.children)) { - current.children[segment] = { - name: segment, - fullName: segments.slice(0, index + 1).join("_"), - children: {}, - }; - } - current = current.children[segment]; - } - - current.scenario = scenario; - } - - return cutTillMultipleChildren(root); -} - -function cutTillMultipleChildren(node: ManifestTreeNode): ManifestTreeNode { - let newRoot: ManifestTreeNode = node; - while (newRoot.children) { - if (Object.keys(newRoot.children).length === 1) { - newRoot = Object.values(newRoot.children)[0]; - } else { - break; - } - } - - return newRoot; -} diff --git a/packages/azure-spec-dashboard/src/components/dashboard.tsx b/packages/azure-spec-dashboard/src/components/dashboard.tsx deleted file mode 100644 index 5274993342..0000000000 --- a/packages/azure-spec-dashboard/src/components/dashboard.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { Card, CardHeader, Text, tokens } from "@fluentui/react-components"; -import { FunctionComponent } from "react"; -import { CoverageSummary } from "../apis.js"; -import { DashboardTable } from "./dashboard-table.js"; -import { InfoEntry, InfoReport } from "./info-table.js"; - -export interface DashboardProps { - coverageSummaries: CoverageSummary[]; -} - -export const Dashboard: FunctionComponent = ({ coverageSummaries }) => { - const summaryTables = coverageSummaries.map((coverageSummary, i) => ( -
- -
- )); - - const specsCardTable = coverageSummaries.map((coverageSummary, i) => ( -
- -
- )); - - return ( -
-
-

Spector Coverage Dashboard

-
-
{specsCardTable}
-
- {summaryTables} -
- ); -}; - -const CadlRanchSpecsCard: FunctionComponent<{ coverageSummary: CoverageSummary }> = ({ - coverageSummary, -}) => { - let commitLink = "", - heading = "", - packageName = ""; - if (coverageSummary.manifest.setName === "@azure-tools/azure-http-specs") { - commitLink = `https://github.com/Azure/typespec-azure/commit/${coverageSummary.manifest.commit}`; - heading = `Azure Specs Manifest`; - packageName = "azure-http-specs"; - } else { - commitLink = `https://github.com/microsoft/typespec/commit/${coverageSummary.manifest.commit}`; - heading = `Typespec Specs Manifest`; - packageName = "http-specs"; - } - - return ( - - {heading}} /> - - {coverageSummary.manifest.commit.slice(0, 6)}} - /> - - - - - ); -}; diff --git a/packages/azure-spec-dashboard/src/components/generator-information.tsx b/packages/azure-spec-dashboard/src/components/generator-information.tsx deleted file mode 100644 index fc94af7db4..0000000000 --- a/packages/azure-spec-dashboard/src/components/generator-information.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { ResolvedCoverageReport } from "@typespec/spec-coverage-sdk"; -import { FunctionComponent } from "react"; -import { InfoEntry, InfoReport } from "./info-table.js"; -import { ScenarioGroupRatioStatusBox } from "./scenario-group-status.js"; - -export type GeneratorInformationProps = { - status: number; - report: ResolvedCoverageReport; -}; - -export const GeneratorInformation: FunctionComponent = ({ - status, - report, -}) => { - return ( - - - - - - - } - /> - - } - /> - - ); -}; - -function getCompletedRatioAtTimeOfReport(report: ResolvedCoverageReport) { - let coveredCount = 0; - const statues = Object.values(report.results); - for (const status of statues) { - if (status === "pass" || status === "not-applicable" || status === "not-supported") { - coveredCount++; - } - } - - return coveredCount / statues.length; -} diff --git a/packages/azure-spec-dashboard/src/components/info-table.tsx b/packages/azure-spec-dashboard/src/components/info-table.tsx deleted file mode 100644 index 746feb2627..0000000000 --- a/packages/azure-spec-dashboard/src/components/info-table.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Caption1, Text } from "@fluentui/react-components"; -import { FunctionComponent, ReactElement } from "react"; - -export const InfoReport = ({ children }: { children: ReactElement[] }) => { - return ( - - {children} -
- ); -}; -export type InfoEntryProps = { - readonly label: string; - readonly caption: string; - readonly value: string | any; - readonly valueTitle?: string; -}; - -export const InfoEntry: FunctionComponent = ({ - label, - caption, - value, - valueTitle, -}) => { - return ( - - - - - - {value} - - - ); -}; diff --git a/packages/azure-spec-dashboard/src/components/scenario-group-status.tsx b/packages/azure-spec-dashboard/src/components/scenario-group-status.tsx deleted file mode 100644 index 445cb31010..0000000000 --- a/packages/azure-spec-dashboard/src/components/scenario-group-status.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { SerializedStyles, css } from "@emotion/react"; -import { FunctionComponent } from "react"; -import { Colors, GroupRatioColors, GroupRatios } from "../constants.js"; - -export interface ScenarioGroupStatusRatioBoxProps { - readonly ratio: number; -} - -export const ScenarioGroupRatioStatusBox: FunctionComponent = ({ - ratio, -}) => { - let css = groupRatioStyles.bad; - - for (const [key, expectedRatio] of Object.entries(GroupRatios)) { - if (ratio >= expectedRatio) { - css = groupRatioStyles[key as keyof typeof GroupRatios]; - break; - } - } - return ( -
- {Math.floor(ratio * 100)}% -
- ); -}; - -const groupRatioStyles: Record = Object.fromEntries( - Object.entries(GroupRatioColors).map(([key, value]) => { - return [key, css({ backgroundColor: value })]; - }), -) as any; diff --git a/packages/azure-spec-dashboard/src/components/scenario-status.tsx b/packages/azure-spec-dashboard/src/components/scenario-status.tsx deleted file mode 100644 index b3edf4a60b..0000000000 --- a/packages/azure-spec-dashboard/src/components/scenario-status.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import { css } from "@emotion/react"; -import { - Checkmark20Filled, - ErrorCircle20Filled, - QuestionCircle20Filled, - SpeakerMute20Filled, - Warning20Filled, -} from "@fluentui/react-icons"; -import { ScenarioStatus } from "@typespec/spec-coverage-sdk"; -import { FunctionComponent } from "react"; -import { Colors, ScenarioStatusColors } from "../constants.js"; - -export interface ScenarioStatusBoxProps { - readonly status: ScenarioStatus | undefined; -} - -export const ScenarioStatusBox: FunctionComponent = ({ status }) => { - switch (status) { - case "pass": - return ; - case "fail": - return ; - case "not-applicable": - return ; - case "not-supported": - return ; - case "not-implemented": - return ; - case undefined: { - return ; - } - default: - return
Unexpected value {status}
; - } -}; - -const ScenarioStatusBoxStyles = css({ - height: "100%", - width: "100%", - color: Colors.bgSubtle, - display: "flex", - alignItems: "center", - justifyContent: "center", -}); - -export const PassStatus = () => ( -
- -
-); - -export const FailStatus = () => ( -
- -
-); - -export const NotSupportedStatus = () => ( -
- -
-); -export const NotApplicableStatus = () => ( -
- -
-); - -export const NotImplementedStatus = () => ( -
- -
-); - -export const NotReportedStatus = () => ( -
- -
-); diff --git a/packages/azure-spec-dashboard/src/components/tree-table/row-label-cell.tsx b/packages/azure-spec-dashboard/src/components/tree-table/row-label-cell.tsx deleted file mode 100644 index bb808ee601..0000000000 --- a/packages/azure-spec-dashboard/src/components/tree-table/row-label-cell.tsx +++ /dev/null @@ -1,153 +0,0 @@ -import { - Button, - Popover, - PopoverSurface, - PopoverTrigger, - Title3, - Tooltip, -} from "@fluentui/react-components"; -import { - BookInformation20Regular, - Braces20Filled, - ChevronDown20Filled, - ChevronRight20Filled, -} from "@fluentui/react-icons"; -import { ScenarioData } from "@typespec/spec-coverage-sdk"; -import { FunctionComponent, useMemo } from "react"; -import ReactMarkdown from "react-markdown"; -import { CoverageSummary } from "../../apis.js"; -import { ManifestTreeNode, TreeTableRow } from "./types.js"; - -export interface RowLabelCellProps { - row: TreeTableRow; - coverageSummary: CoverageSummary; -} -const INDENT_SIZE = 14; -export const RowLabelCell: FunctionComponent = ({ row, coverageSummary }) => { - const caret = row.hasChildren ? ( - row.expanded ? ( - - ) : ( - - ) - ) : null; - const marginLeft = row.depth * INDENT_SIZE; - const rowLabel = getLabelForRow(row); - return ( - -
-
- {caret} -
-
- {rowLabel} -
-
- {row.item.scenario && } - {row.item.scenario && ( - - )} -
-
- - ); -}; - -type ScenarioInfoButtonProps = { - scenario: ScenarioData; -}; - -const ScenarioInfoButton: FunctionComponent = ({ scenario }) => { - return ( - - - -