diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e285f87d1..1924e7e61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -113,21 +113,20 @@ jobs: NUGET_SOURCE: ${{ secrets.NUGET_SOURCE }} AZURE_DEVOPS_PAT: ${{ secrets.AZURE_DEVOPS_PAT }} steps: - - uses: nuget/setup-nuget@v1 - with: - nuget-api-key: ${{ secrets.NUGET_API_KEY }} - name: Download Dist Folder uses: actions/download-artifact@v4 with: name: dist - run: cp ./configs/prod.json config.json - - run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "jawelton@microsoft.com" -Password "$AZURE_DEVOPS_PAT" - - run: nuget pack -Version "2.0.0-github-${GITHUB_SHA}" - - run: nuget push -SkipDuplicate -Source "$NUGET_SOURCE" -ApiKey Az *.nupkg + - run: dotnet nuget add source "$NUGET_SOURCE" --name "ADO" --username "jawelton@microsoft.com" --password "$AZURE_DEVOPS_PAT" --store-password-in-clear-text + - run: dotnet pack DataExplorer.proj /p:PackageVersion="2.0.0-github-${GITHUB_SHA}" + - run: dotnet nuget push "bin/Release/*.nupkg" --skip-duplicate --api-key Az --source="$NUGET_SOURCE" + - run: dotnet nuget remove source "ADO" - uses: actions/upload-artifact@v4 name: packages with: - path: "*.nupkg" + path: "bin/Release/*.nupkg" + nugetmpac: name: Publish Nuget MPAC if: github.ref == 'refs/heads/master' || contains(github.ref, 'hotfix/') || contains(github.ref, 'release/') @@ -137,22 +136,20 @@ jobs: NUGET_SOURCE: ${{ secrets.NUGET_SOURCE }} AZURE_DEVOPS_PAT: ${{ secrets.AZURE_DEVOPS_PAT }} steps: - - uses: nuget/setup-nuget@v1 - with: - nuget-api-key: ${{ secrets.NUGET_API_KEY }} - name: Download Dist Folder uses: actions/download-artifact@v4 with: name: dist - run: cp ./configs/mpac.json config.json - run: sed -i 's/Azure.Cosmos.DB.Data.Explorer/Azure.Cosmos.DB.Data.Explorer.MPAC/g' DataExplorer.nuspec - - run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "jawelton@microsoft.com" -Password "$AZURE_DEVOPS_PAT" - - run: nuget pack -Version "2.0.0-github-${GITHUB_SHA}" - - run: nuget push -SkipDuplicate -Source "$NUGET_SOURCE" -ApiKey Az *.nupkg + - run: dotnet nuget add source "$NUGET_SOURCE" --name "ADO" --username "jawelton@microsoft.com" --password "$AZURE_DEVOPS_PAT" --store-password-in-clear-text + - run: dotnet pack DataExplorer.proj /p:PackageVersion="2.0.0-github-${GITHUB_SHA}" + - run: dotnet nuget push "bin/Release/*.nupkg" --skip-duplicate --api-key Az --source="$NUGET_SOURCE" + - run: dotnet nuget remove source "ADO" - uses: actions/upload-artifact@v4 name: packages with: - path: "*.nupkg" + path: "bin/Release/*.nupkg" playwright-tests: name: "Run Playwright Tests (Shard ${{ matrix.shardIndex }} of ${{ matrix.shardTotal }})" @@ -185,9 +182,9 @@ jobs: if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: - name: blob-report-${{ matrix.shardIndex }} - path: blob-report - retention-days: 1 + name: blob-report-${{ matrix.shardIndex }} + path: blob-report + retention-days: 1 merge-playwright-reports: name: "Merge Playwright Reports" @@ -197,26 +194,26 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 18 - - name: Install dependencies - run: npm ci + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + - name: Install dependencies + run: npm ci - - name: Download blob reports from GitHub Actions Artifacts - uses: actions/download-artifact@v4 - with: - path: all-blob-reports - pattern: blob-report-* - merge-multiple: true + - name: Download blob reports from GitHub Actions Artifacts + uses: actions/download-artifact@v4 + with: + path: all-blob-reports + pattern: blob-report-* + merge-multiple: true - - name: Merge into HTML Report - run: npx playwright merge-reports --reporter html ./all-blob-reports + - name: Merge into HTML Report + run: npx playwright merge-reports --reporter html ./all-blob-reports - - name: Upload HTML report - uses: actions/upload-artifact@v4 - with: - name: html-report--attempt-${{ github.run_attempt }} - path: playwright-report - retention-days: 14 \ No newline at end of file + - name: Upload HTML report + uses: actions/upload-artifact@v4 + with: + name: html-report--attempt-${{ github.run_attempt }} + path: playwright-report + retention-days: 14 diff --git a/DataExplorer.proj b/DataExplorer.proj new file mode 100644 index 000000000..aa18a3e83 --- /dev/null +++ b/DataExplorer.proj @@ -0,0 +1,9 @@ + + + net8.0 + true + false + DataExplorer.nuspec + version=$(PackageVersion) + + \ No newline at end of file diff --git a/src/Common/CosmosClient.ts b/src/Common/CosmosClient.ts index f7a4fbfc5..2779e1ba1 100644 --- a/src/Common/CosmosClient.ts +++ b/src/Common/CosmosClient.ts @@ -8,7 +8,7 @@ import { AuthType } from "../AuthType"; import { BackendApi, PriorityLevel } from "../Common/Constants"; import * as Logger from "../Common/Logger"; import { Platform, configContext } from "../ConfigContext"; -import { userContext } from "../UserContext"; +import { updateUserContext, userContext } from "../UserContext"; import { logConsoleError } from "../Utils/NotificationConsoleUtils"; import * as PriorityBasedExecutionUtils from "../Utils/PriorityBasedExecutionUtils"; import { EmulatorMasterKey, HttpHeaders } from "./Constants"; @@ -189,10 +189,19 @@ let _client: Cosmos.CosmosClient; export function client(): Cosmos.CosmosClient { if (_client) { - if (!userContext.hasDataPlaneRbacSettingChanged) { + if (!userContext.refreshCosmosClient) { return _client; } + _client.dispose(); + _client = null; } + + if (userContext.refreshCosmosClient) { + updateUserContext({ + refreshCosmosClient: false, + }); + } + let _defaultHeaders: Cosmos.CosmosHeaders = {}; _defaultHeaders["x-ms-cosmos-sdk-supportedcapabilities"] = SDKSupportedCapabilities.None | SDKSupportedCapabilities.PartitionMerge; diff --git a/src/Explorer/Panes/SettingsPane/SettingsPane.tsx b/src/Explorer/Panes/SettingsPane/SettingsPane.tsx index 12b5a8c47..aedf517eb 100644 --- a/src/Explorer/Panes/SettingsPane/SettingsPane.tsx +++ b/src/Explorer/Panes/SettingsPane/SettingsPane.tsx @@ -193,6 +193,17 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({ LocalStorageUtility.setEntryNumber(StorageKey.CustomItemPerPage, customItemPerPage); + if ( + enableDataPlaneRBACOption !== LocalStorageUtility.getEntryString(StorageKey.DataPlaneRbacEnabled) || + retryAttempts !== LocalStorageUtility.getEntryNumber(StorageKey.RetryAttempts) || + retryInterval !== LocalStorageUtility.getEntryNumber(StorageKey.RetryInterval) || + MaxWaitTimeInSeconds !== LocalStorageUtility.getEntryNumber(StorageKey.MaxWaitTimeInSeconds) + ) { + updateUserContext({ + refreshCosmosClient: true, + }); + } + if (configContext.platform !== Platform.Fabric) { LocalStorageUtility.setEntryString(StorageKey.DataPlaneRbacEnabled, enableDataPlaneRBACOption); if ( @@ -202,7 +213,6 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({ ) { updateUserContext({ dataPlaneRbacEnabled: true, - hasDataPlaneRbacSettingChanged: true, }); useDataPlaneRbac.setState({ dataPlaneRbacEnabled: true }); try { @@ -226,7 +236,6 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({ } else { updateUserContext({ dataPlaneRbacEnabled: false, - hasDataPlaneRbacSettingChanged: true, }); const { databaseAccount: account, subscriptionId, resourceGroup } = userContext; if (!userContext.features.enableAadDataPlane && !userContext.masterKey) { @@ -564,7 +573,6 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({ )} - {userContext.apiType === "SQL" && ( <> @@ -663,78 +671,79 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({ )} - - - -
Retry Settings
-
- -
-
- Retry policy associated with throttled requests during CosmosDB queries. + {(userContext.apiType === "SQL" || userContext.apiType === "Tables" || userContext.apiType === "Gremlin") && ( + + +
Retry Settings
+
+ +
+
+ Retry policy associated with throttled requests during CosmosDB queries. +
+
+ Max retry attempts + + Max number of retries to be performed for a request. Default value 9. + +
+ setRetryAttempts(parseInt(newValue) + 1 || retryAttempts)} + onDecrement={(newValue) => setRetryAttempts(parseInt(newValue) - 1 || retryAttempts)} + onValidate={(newValue) => setRetryAttempts(parseInt(newValue) || retryAttempts)} + styles={spinButtonStyles} + /> +
+ Fixed retry interval (ms) + + Fixed retry interval in milliseconds to wait between each retry ignoring the retryAfter returned + as part of the response. Default value is 0 milliseconds. + +
+ setRetryInterval(parseInt(newValue) + 1000 || retryInterval)} + onDecrement={(newValue) => setRetryInterval(parseInt(newValue) - 1000 || retryInterval)} + onValidate={(newValue) => setRetryInterval(parseInt(newValue) || retryInterval)} + styles={spinButtonStyles} + /> +
+ Max wait time (s) + + Max wait time in seconds to wait for a request while the retries are happening. Default value 30 + seconds. + +
+ setMaxWaitTimeInSeconds(parseInt(newValue) + 1 || MaxWaitTimeInSeconds)} + onDecrement={(newValue) => setMaxWaitTimeInSeconds(parseInt(newValue) - 1 || MaxWaitTimeInSeconds)} + onValidate={(newValue) => setMaxWaitTimeInSeconds(parseInt(newValue) || MaxWaitTimeInSeconds)} + styles={spinButtonStyles} + />
-
- Max retry attempts - - Max number of retries to be performed for a request. Default value 9. - -
- setRetryAttempts(parseInt(newValue) + 1 || retryAttempts)} - onDecrement={(newValue) => setRetryAttempts(parseInt(newValue) - 1 || retryAttempts)} - onValidate={(newValue) => setRetryAttempts(parseInt(newValue) || retryAttempts)} - styles={spinButtonStyles} - /> -
- Fixed retry interval (ms) - - Fixed retry interval in milliseconds to wait between each retry ignoring the retryAfter returned as - part of the response. Default value is 0 milliseconds. - -
- setRetryInterval(parseInt(newValue) + 1000 || retryInterval)} - onDecrement={(newValue) => setRetryInterval(parseInt(newValue) - 1000 || retryInterval)} - onValidate={(newValue) => setRetryInterval(parseInt(newValue) || retryInterval)} - styles={spinButtonStyles} - /> -
- Max wait time (s) - - Max wait time in seconds to wait for a request while the retries are happening. Default value 30 - seconds. - -
- setMaxWaitTimeInSeconds(parseInt(newValue) + 1 || MaxWaitTimeInSeconds)} - onDecrement={(newValue) => setMaxWaitTimeInSeconds(parseInt(newValue) - 1 || MaxWaitTimeInSeconds)} - onValidate={(newValue) => setMaxWaitTimeInSeconds(parseInt(newValue) || MaxWaitTimeInSeconds)} - styles={spinButtonStyles} - /> -
- - + + + )} @@ -758,7 +767,6 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({
- {shouldShowCrossPartitionOption && ( @@ -784,7 +792,6 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({ )} - {shouldShowParallelismOption && ( @@ -818,7 +825,6 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({ )} - {shouldShowPriorityLevelOption && ( @@ -842,7 +848,6 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({ )} - {shouldShowGraphAutoVizOption && ( @@ -864,7 +869,6 @@ export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({ )} - {shouldShowCopilotSampleDBOption && ( diff --git a/src/UserContext.ts b/src/UserContext.ts index 955452d3a..d30951780 100644 --- a/src/UserContext.ts +++ b/src/UserContext.ts @@ -104,7 +104,7 @@ export interface UserContext { readonly vcoreMongoConnectionParams?: VCoreMongoConnectionParams; readonly feedbackPolicies?: AdminFeedbackPolicySettings; readonly dataPlaneRbacEnabled?: boolean; - readonly hasDataPlaneRbacSettingChanged?: boolean; + readonly refreshCosmosClient?: boolean; } export type ApiType = "SQL" | "Mongo" | "Gremlin" | "Tables" | "Cassandra" | "Postgres" | "VCoreMongo"; diff --git a/webpack.config.js b/webpack.config.js index c21baf3ef..f594602d4 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -187,7 +187,12 @@ module.exports = function (_env = {}, argv = {}) { }), new MonacoWebpackPlugin(), new CopyWebpackPlugin({ - patterns: [{ from: "DataExplorer.nuspec" }, { from: "web.config" }, { from: "quickstart/*.zip" }], + patterns: [ + { from: "DataExplorer.nuspec" }, + { from: "DataExplorer.proj" }, + { from: "web.config" }, + { from: "quickstart/*.zip" }, + ], }), new EnvironmentPlugin(envVars), ];