Merge branch 'master' into locfiles/486ca1c2-3f14-4217-8aae-5aae878d249c

This commit is contained in:
sunghyunkang1111
2026-06-11 11:28:25 -05:00
committed by GitHub
10 changed files with 136 additions and 141 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ module.exports = {
}, },
], ],
rules: { rules: {
//CTODO uncomment when console debugging is reverted: "no-console": ["error", { allow: ["error", "warn", "dir"] }], "no-console": ["error", { allow: ["error", "warn", "dir"] }],
curly: "error", curly: "error",
"@typescript-eslint/switch-exhaustiveness-check": "error", "@typescript-eslint/switch-exhaustiveness-check": "error",
"@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-unused-vars": "error",
+73 -52
View File
@@ -299,13 +299,26 @@ jobs:
run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --list run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --list
- name: Run test shard ${{ matrix['shardIndex'] }} of ${{ matrix['shardTotal']}} - name: Run test shard ${{ matrix['shardIndex'] }} of ${{ matrix['shardTotal']}}
run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --workers=3 run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --workers=3
- name: Upload blob report to GitHub Actions Artifacts - name: "Re-auth for upload (refresh OIDC token)"
if: ${{ !cancelled() }} if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4 uses: Azure/login@v2
with: with:
name: blob-report-${{ matrix.shardIndex }} client-id: ${{ secrets.E2E_TESTS_CLIENT_ID }}
path: blob-report tenant-id: ${{ secrets.AZURE_TENANT_ID }}
retention-days: 1 subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Upload shard blob-report to Azure Storage
if: ${{ !cancelled() }}
env:
KEY: ${{ github.run_id }}-${{ github.run_attempt }}
SHARD: ${{ matrix.shardIndex }}
run: |
az storage blob upload-batch \
--account-name ${{ secrets.PREVIEW_STORAGE_ACCOUNT_NAME }} \
--auth-mode login \
-d playwright-reports \
-s blob-report \
--destination-path "${KEY}/shards/shard-${SHARD}" \
--overwrite true
merge-playwright-reports: merge-playwright-reports:
name: "Merge Playwright Reports" name: "Merge Playwright Reports"
@@ -317,6 +330,7 @@ jobs:
permissions: permissions:
contents: read contents: read
pull-requests: write pull-requests: write
id-token: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
@@ -325,29 +339,67 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci
- name: Download blob reports from GitHub Actions Artifacts - name: "Az CLI login"
uses: actions/download-artifact@v4 uses: Azure/login@v2
with: with:
path: all-blob-reports client-id: ${{ secrets.AZURE_CLIENT_ID }}
pattern: blob-report-* tenant-id: ${{ secrets.AZURE_TENANT_ID }}
merge-multiple: true subscription-id: ${{ secrets.PREVIEW_SUBSCRIPTION_ID }}
- name: Download all shard reports from Azure Storage
env:
KEY: ${{ github.run_id }}-${{ github.run_attempt }}
run: |
mkdir -p all-blob-reports
az storage blob download-batch \
--account-name ${{ secrets.PREVIEW_STORAGE_ACCOUNT_NAME }} \
--auth-mode login \
-s playwright-reports \
--pattern "${KEY}/shards/*" \
-d ./all-blob-reports
find ./all-blob-reports -type f -name "*.zip" -exec mv -t ./all-blob-reports {} +
find ./all-blob-reports -type d -empty -delete
ls -la ./all-blob-reports
- name: Merge into HTML Report - name: Merge into HTML Report
run: npx playwright merge-reports --reporter html ./all-blob-reports run: npx playwright merge-reports --reporter html ./all-blob-reports
- name: Upload HTML report - name: Bundle merged report into a single zip
uses: actions/upload-artifact@v4 run: |
with: cd playwright-report
name: html-report--attempt-${{ github.run_attempt }} zip -r ../report.zip .
path: playwright-report cd ..
retention-days: 14
- name: Upload report.zip to Azure Storage
env:
KEY: ${{ github.run_id }}-${{ github.run_attempt }}
run: |
az storage blob upload \
--account-name ${{ secrets.PREVIEW_STORAGE_ACCOUNT_NAME }} \
--auth-mode login \
-c playwright-reports \
-n "${KEY}/report.zip" \
-f report.zip \
--overwrite
- name: Clean up shard intermediates from Azure Storage
if: ${{ always() }}
env:
KEY: ${{ github.run_id }}-${{ github.run_attempt }}
run: |
az storage blob delete-batch \
--account-name ${{ secrets.PREVIEW_STORAGE_ACCOUNT_NAME }} \
--auth-mode login \
-s playwright-reports \
--pattern "${KEY}/shards/*"
- name: Comment Playwright results on PR - name: Comment Playwright results on PR
if: ${{ !cancelled() && github.event_name == 'pull_request' }} if: ${{ !cancelled() && github.event_name == 'pull_request' }}
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR: ${{ github.event.pull_request.number }} PR: ${{ github.event.pull_request.number }}
REPORT_URL: https://dataexplorerpreview.z5.web.core.windows.net/playwright-reports/${{ github.run_id }}-${{ github.run_attempt }}/index.html SA_ID: /subscriptions/${{ secrets.PREVIEW_SUBSCRIPTION_ID }}/resourceGroups/dataexplorer-preview/providers/Microsoft.Storage/storageAccounts/dataexplorerpreview
KEY: ${{ github.run_id }}-${{ github.run_attempt }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: | run: |
PLAYWRIGHT_JSON_OUTPUT_NAME=results.json npx playwright merge-reports --reporter json ./all-blob-reports PLAYWRIGHT_JSON_OUTPUT_NAME=results.json npx playwright merge-reports --reporter json ./all-blob-reports
@@ -355,6 +407,8 @@ jobs:
BROKEN=$(gh api "repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}/jobs" \ BROKEN=$(gh api "repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}/jobs" \
--jq '[.jobs[] | select(.name | startswith("Run Playwright Tests")) | select(.conclusion == "failure")] | length') --jq '[.jobs[] | select(.name | startswith("Run Playwright Tests")) | select(.conclusion == "failure")] | length')
if [ "$FAILED" -gt 0 ] || [ "$BROKEN" -gt 0 ]; then ICON="❌ failed"; else ICON="✅ passed"; fi if [ "$FAILED" -gt 0 ] || [ "$BROKEN" -gt 0 ]; then ICON="❌ failed"; else ICON="✅ passed"; fi
SA_ENC=$(printf '%s' "$SA_ID" | jq -sRr @uri)
CONTAINER_URL="https://portal.azure.com/#view/Microsoft_Azure_Storage/ContainerMenuBlade/~/overview/storageAccountId/${SA_ENC}/path/playwright-reports"
NOTE="" NOTE=""
[ "$BROKEN" -gt 0 ] && NOTE=" [ "$BROKEN" -gt 0 ] && NOTE="
@@ -365,38 +419,5 @@ jobs:
| :---: | :---: | :---: | :---: | | :---: | :---: | :---: | :---: |
| $PASSED | $FAILED | $FLAKY | ${DURATION}s | | $PASSED | $FAILED | $FLAKY | ${DURATION}s |
📊 [Open full report]($REPORT_URL) · [Workflow run]($RUN_URL)$NOTE" 📁 **Report:** \`${KEY}/report.zip\`
[Open container]($CONTAINER_URL) (Azure sign-in required) → click into \`${KEY}\` folder → click \`report.zip\` → **Download** → unzip → open \`index.html\` · [Workflow run]($RUN_URL)$NOTE"
publish-playwright-report:
name: "Publish Playwright Report to Blob"
if: ${{ !cancelled() }}
needs: [merge-playwright-reports]
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Download HTML report artifact
uses: actions/download-artifact@v4
with:
name: html-report--attempt-${{ github.run_attempt }}
path: playwright-report
- name: "Az CLI login"
uses: Azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.PREVIEW_SUBSCRIPTION_ID }}
- name: Upload Playwright report to blob storage
env:
KEY: ${{ github.run_id }}-${{ github.run_attempt }}
BASE: https://dataexplorerpreview.z5.web.core.windows.net
run: |
az storage blob upload-batch -d '$web' -s playwright-report \
--destination-path "playwright-reports/${KEY}" \
--account-name ${{ secrets.PREVIEW_STORAGE_ACCOUNT_NAME }} \
--auth-mode login --overwrite true
echo "📊 [Open Playwright report](${BASE}/playwright-reports/${KEY}/index.html)" >> $GITHUB_STEP_SUMMARY
+40 -21
View File
@@ -163,7 +163,7 @@
"@webpack-cli/serve": "2.0.5", "@webpack-cli/serve": "2.0.5",
"babel-jest": "29.7.0", "babel-jest": "29.7.0",
"babel-loader": "8.1.0", "babel-loader": "8.1.0",
"brace-expansion": "1.1.12", "brace-expansion": "1.1.15",
"buffer": "5.1.0", "buffer": "5.1.0",
"case-sensitive-paths-webpack-plugin": "2.4.0", "case-sensitive-paths-webpack-plugin": "2.4.0",
"create-file-webpack": "1.0.2", "create-file-webpack": "1.0.2",
@@ -11604,10 +11604,11 @@
} }
}, },
"node_modules/body-parser": { "node_modules/body-parser": {
"version": "1.20.4", "version": "1.20.5",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
"integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"bytes": "~3.1.2", "bytes": "~3.1.2",
"content-type": "~1.0.5", "content-type": "~1.0.5",
@@ -11617,7 +11618,7 @@
"http-errors": "~2.0.1", "http-errors": "~2.0.1",
"iconv-lite": "~0.4.24", "iconv-lite": "~0.4.24",
"on-finished": "~2.4.1", "on-finished": "~2.4.1",
"qs": "~6.14.0", "qs": "~6.15.1",
"raw-body": "~2.5.3", "raw-body": "~2.5.3",
"type-is": "~1.6.18", "type-is": "~1.6.18",
"unpipe": "~1.0.0" "unpipe": "~1.0.0"
@@ -11632,6 +11633,7 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"ms": "2.0.0" "ms": "2.0.0"
} }
@@ -11641,6 +11643,7 @@
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"safer-buffer": ">= 2.1.2 < 3" "safer-buffer": ">= 2.1.2 < 3"
}, },
@@ -11652,7 +11655,8 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true "dev": true,
"license": "MIT"
}, },
"node_modules/bonjour-service": { "node_modules/bonjour-service": {
"version": "1.3.0", "version": "1.3.0",
@@ -11679,9 +11683,10 @@
} }
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.12", "version": "1.1.15",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==",
"license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@@ -12347,6 +12352,7 @@
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
} }
@@ -15224,14 +15230,15 @@
} }
}, },
"node_modules/express": { "node_modules/express": {
"version": "4.22.1", "version": "4.22.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz",
"integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"accepts": "~1.3.8", "accepts": "~1.3.8",
"array-flatten": "1.1.1", "array-flatten": "1.1.1",
"body-parser": "~1.20.3", "body-parser": "~1.20.5",
"content-disposition": "~0.5.4", "content-disposition": "~0.5.4",
"content-type": "~1.0.4", "content-type": "~1.0.4",
"cookie": "~0.7.1", "cookie": "~0.7.1",
@@ -15250,7 +15257,7 @@
"parseurl": "~1.3.3", "parseurl": "~1.3.3",
"path-to-regexp": "~0.1.12", "path-to-regexp": "~0.1.12",
"proxy-addr": "~2.0.7", "proxy-addr": "~2.0.7",
"qs": "~6.14.0", "qs": "~6.15.1",
"range-parser": "~1.2.1", "range-parser": "~1.2.1",
"safe-buffer": "5.2.1", "safe-buffer": "5.2.1",
"send": "~0.19.0", "send": "~0.19.0",
@@ -22317,18 +22324,25 @@
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/launch-editor": { "node_modules/launch-editor": {
"version": "2.6.1", "version": "2.14.1",
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.14.1.tgz",
"integrity": "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"picocolors": "^1.0.0", "picocolors": "^1.1.1",
"shell-quote": "^1.8.1" "shell-quote": "^1.8.4"
} }
}, },
"node_modules/launch-editor/node_modules/shell-quote": { "node_modules/launch-editor/node_modules/shell-quote": {
"version": "1.8.1", "version": "1.8.4",
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.4.tgz",
"integrity": "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
@@ -22762,6 +22776,7 @@
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.6" "node": ">= 0.6"
} }
@@ -24498,9 +24513,10 @@
} }
}, },
"node_modules/qs": { "node_modules/qs": {
"version": "6.14.1", "version": "6.15.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
"license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"side-channel": "^1.1.0" "side-channel": "^1.1.0"
}, },
@@ -24585,6 +24601,7 @@
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
"integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"bytes": "~3.1.2", "bytes": "~3.1.2",
"http-errors": "~2.0.1", "http-errors": "~2.0.1",
@@ -24600,6 +24617,7 @@
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"safer-buffer": ">= 2.1.2 < 3" "safer-buffer": ">= 2.1.2 < 3"
}, },
@@ -27399,6 +27417,7 @@
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"media-typer": "0.3.0", "media-typer": "0.3.0",
"mime-types": "~2.1.24" "mime-types": "~2.1.24"
+1 -1
View File
@@ -173,7 +173,7 @@
"@webpack-cli/serve": "2.0.5", "@webpack-cli/serve": "2.0.5",
"babel-jest": "29.7.0", "babel-jest": "29.7.0",
"babel-loader": "8.1.0", "babel-loader": "8.1.0",
"brace-expansion": "1.1.12", "brace-expansion": "1.1.15",
"buffer": "5.1.0", "buffer": "5.1.0",
"case-sensitive-paths-webpack-plugin": "2.4.0", "case-sensitive-paths-webpack-plugin": "2.4.0",
"create-file-webpack": "1.0.2", "create-file-webpack": "1.0.2",
+3 -1
View File
@@ -695,7 +695,9 @@
} }
}, },
"node_modules/qs": { "node_modules/qs": {
"version": "6.14.1", "version": "6.15.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
"integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"side-channel": "^1.1.0" "side-channel": "^1.1.0"
-1
View File
@@ -21,7 +21,6 @@ export const handleError = (
consoleErrorPrefix?: string, consoleErrorPrefix?: string,
options?: HandleErrorOptions, options?: HandleErrorOptions,
): void => { ): void => {
console.log("{{cdbp}} in handleError(): raw error: " + stringifyError(error)); //CTODO in case a stray error happens
const errorMessage = getErrorMessage(error); const errorMessage = getErrorMessage(error);
const errorCode = error instanceof ARMError ? error.code : undefined; const errorCode = error instanceof ARMError ? error.code : undefined;
+17 -34
View File
@@ -1,4 +1,3 @@
import { stringifyError } from "Common/stringifyError";
import { CosmosDbArtifactType } from "Contracts/FabricMessagesContract"; import { CosmosDbArtifactType } from "Contracts/FabricMessagesContract";
import { isFabric, isFabricMirroredKey, isFabricNative } from "Platform/Fabric/FabricUtil"; import { isFabric, isFabricMirroredKey, isFabricNative } from "Platform/Fabric/FabricUtil";
import { AuthType } from "../../AuthType"; import { AuthType } from "../../AuthType";
@@ -27,7 +26,6 @@ export async function readDatabases(): Promise<DataModels.Database[]> {
(userContext.fabricContext?.artifactInfo as FabricArtifactInfo[CosmosDbArtifactType.MIRRORED_KEY]).resourceTokenInfo (userContext.fabricContext?.artifactInfo as FabricArtifactInfo[CosmosDbArtifactType.MIRRORED_KEY]).resourceTokenInfo
.resourceTokens .resourceTokens
) { ) {
console.log("{{cdbp}} in readDatabases(): isFabricMirroredKey && has resourceTokens"); //CTODO should not get here
const tokensData = (userContext.fabricContext.artifactInfo as FabricArtifactInfo[CosmosDbArtifactType.MIRRORED_KEY]) const tokensData = (userContext.fabricContext.artifactInfo as FabricArtifactInfo[CosmosDbArtifactType.MIRRORED_KEY])
.resourceTokenInfo; .resourceTokenInfo;
@@ -61,7 +59,6 @@ export async function readDatabases(): Promise<DataModels.Database[]> {
clearMessage(); clearMessage();
return databases; return databases;
} else if (isFabricNative() && userContext.fabricContext?.databaseName) { } else if (isFabricNative() && userContext.fabricContext?.databaseName) {
console.log("{{cdbp}} in readDatabases(): isFabricNative"); //CTODO should not get here
const databaseId = userContext.fabricContext.databaseName; const databaseId = userContext.fabricContext.databaseName;
databases = [ databases = [
{ {
@@ -84,15 +81,9 @@ export async function readDatabases(): Promise<DataModels.Database[]> {
userContext.apiType !== "Tables" && userContext.apiType !== "Tables" &&
!isFabric() !isFabric()
) { ) {
console.log("{{cdbp}} in readDatabases(): authType == AAD, enableSDKOperations, apiType != Tables, !isFabric");
console.log("{{cdbp}} in readDatabases(): databaseaccount: " + userContext.databaseAccount);
console.log("{{cdbp}} in readDatabases(): calling readDatabasesWithARM");
databases = await readDatabasesWithARM(); databases = await readDatabasesWithARM();
console.log("{{cdbp}} in readDatabases(): done readDatabasesWithARM");
} else { } else {
console.log("{{cdbp}} in readDatabases(): calling SDK");
const sdkResponse = await client().databases.readAll().fetchAll(); const sdkResponse = await client().databases.readAll().fetchAll();
console.log("{{cdbp}} in readDatabases(): done SDK");
databases = sdkResponse.resources as DataModels.Database[]; databases = sdkResponse.resources as DataModels.Database[];
} }
} catch (error) { } catch (error) {
@@ -117,30 +108,22 @@ export async function readDatabasesWithARM(accountOverride?: {
const accountName = accountOverride?.accountName ?? userContext?.databaseAccount?.name ?? ""; const accountName = accountOverride?.accountName ?? userContext?.databaseAccount?.name ?? "";
const apiType = accountOverride?.apiType ?? userContext.apiType; const apiType = accountOverride?.apiType ?? userContext.apiType;
try { switch (apiType) {
switch (apiType) { case "SQL":
case "SQL": rpResponse = await listSqlDatabases(subscriptionId, resourceGroup, accountName);
console.log("{{cdbp}} in readDatabasesWithARM(): calling listSqlDatabases"); break;
rpResponse = await listSqlDatabases(subscriptionId, resourceGroup, accountName); case "Mongo":
console.log("{{cdbp}} in readDatabasesWithARM(): done listSqlDatabases"); rpResponse = await listMongoDBDatabases(subscriptionId, resourceGroup, accountName);
break; break;
case "Mongo": case "Cassandra":
rpResponse = await listMongoDBDatabases(subscriptionId, resourceGroup, accountName); rpResponse = await listCassandraKeyspaces(subscriptionId, resourceGroup, accountName);
break; break;
case "Cassandra": case "Gremlin":
rpResponse = await listCassandraKeyspaces(subscriptionId, resourceGroup, accountName); rpResponse = await listGremlinDatabases(subscriptionId, resourceGroup, accountName);
break; break;
case "Gremlin": default:
rpResponse = await listGremlinDatabases(subscriptionId, resourceGroup, accountName); throw new Error(`Unsupported default experience type: ${apiType}`);
break;
default:
throw new Error(`Unsupported default experience type: ${apiType}`);
}
console.log("{{cdbp}} in readDatabasesWithARM(): response: " + JSON.stringify(rpResponse));
return rpResponse?.value?.map((database) => database.properties?.resource as DataModels.Database) ?? [];
} catch (error) {
console.log("{{cdbp}} in readDatabasesWithARM(): ERROR: " + stringifyError(error));
throw error;
} }
return rpResponse?.value?.map((database) => database.properties?.resource as DataModels.Database) ?? [];
} }
-11
View File
@@ -402,27 +402,19 @@ export default class Explorer {
}, },
startKey, startKey,
); );
console.log("{{cdbp}} in refreshAllDatabases(): done readDatabases");
const currentDatabases = useDatabases.getState().databases; const currentDatabases = useDatabases.getState().databases;
console.log("{{cdbp}} in refreshAllDatabases(): currentDatabases: " + currentDatabases);
const deltaDatabases = this.getDeltaDatabases(databases, currentDatabases); const deltaDatabases = this.getDeltaDatabases(databases, currentDatabases);
console.log("{{cdbp}} in refreshAllDatabases(): deltaDatabases: " + deltaDatabases);
let updatedDatabases = currentDatabases.filter( let updatedDatabases = currentDatabases.filter(
(database) => !deltaDatabases.toDelete.some((deletedDatabase) => deletedDatabase.id() === database.id()), (database) => !deltaDatabases.toDelete.some((deletedDatabase) => deletedDatabase.id() === database.id()),
); );
console.log("{{cdbp}} in refreshAllDatabases(): updatedDatabases after filter: " + updatedDatabases);
updatedDatabases = [...updatedDatabases, ...deltaDatabases.toAdd].sort((db1, db2) => updatedDatabases = [...updatedDatabases, ...deltaDatabases.toAdd].sort((db1, db2) =>
db1.id().localeCompare(db2.id()), db1.id().localeCompare(db2.id()),
); );
console.log("{{cdbp}} in refreshAllDatabases(): updatedDatabases after sort: " + updatedDatabases);
useDatabases.setState({ databases: updatedDatabases, databasesFetchedSuccessfully: true }); useDatabases.setState({ databases: updatedDatabases, databasesFetchedSuccessfully: true });
scenarioMonitor.completePhase(MetricScenario.DatabaseLoad, ApplicationMetricPhase.DatabasesFetched); scenarioMonitor.completePhase(MetricScenario.DatabaseLoad, ApplicationMetricPhase.DatabasesFetched);
console.log("{{cdbp}} in refreshAllDatabases(): calling refreshAndExpandNewDatabases");
await this.refreshAndExpandNewDatabases(deltaDatabases.toAdd, updatedDatabases); await this.refreshAndExpandNewDatabases(deltaDatabases.toAdd, updatedDatabases);
console.log("{{cdbp}} in refreshAllDatabases(): done refreshAndExpandNewDatabases");
} catch (error) { } catch (error) {
console.log("{{cdbp}} in refreshAllDatabases(): ERROR: " + stringifyError(error)); //CTODO this should be logged already but just in case
const errorMessage = getErrorMessage(error); const errorMessage = getErrorMessage(error);
TelemetryProcessor.traceFailure( TelemetryProcessor.traceFailure(
Action.LoadDatabases, Action.LoadDatabases,
@@ -612,7 +604,6 @@ export default class Explorer {
? databases ? databases
: databases.filter((db) => db.isDatabaseExpanded() || db.id() === Constants.SavedQueries.DatabaseName); : databases.filter((db) => db.isDatabaseExpanded() || db.id() === Constants.SavedQueries.DatabaseName);
console.log("{{cdbp}} in refreshAndExpandNewDatabases(): databasesToLoad: " + databasesToLoad);
const startKey: number = TelemetryProcessor.traceStart(Action.LoadCollections, { const startKey: number = TelemetryProcessor.traceStart(Action.LoadCollections, {
dataExplorerArea: Constants.Areas.ResourceTree, dataExplorerArea: Constants.Areas.ResourceTree,
}); });
@@ -621,7 +612,6 @@ export default class Explorer {
try { try {
await Promise.all( await Promise.all(
databasesToLoad.map(async (database: ViewModels.Database) => { databasesToLoad.map(async (database: ViewModels.Database) => {
console.log("{{cdbp}} in refreshAndExpandNewDatabases(): loadCollections for database: " + database.id);
await database.loadCollections(true); await database.loadCollections(true);
const isNewDatabase: boolean = _.some(newDatabases, (db: ViewModels.Database) => db.id() === database.id()); const isNewDatabase: boolean = _.some(newDatabases, (db: ViewModels.Database) => db.id() === database.id());
if (isNewDatabase) { if (isNewDatabase) {
@@ -641,7 +631,6 @@ export default class Explorer {
// Start DatabaseTreeRendered — React render cycle will complete it in ResourceTree // Start DatabaseTreeRendered — React render cycle will complete it in ResourceTree
scenarioMonitor.startPhase(MetricScenario.DatabaseLoad, ApplicationMetricPhase.DatabaseTreeRendered); scenarioMonitor.startPhase(MetricScenario.DatabaseLoad, ApplicationMetricPhase.DatabaseTreeRendered);
} catch (error) { } catch (error) {
console.log("{{cdbp}} in refreshAndExpandNewDatabases(): ERROR: " + stringifyError(error)); //CTODO this should be logged already but just in case
TelemetryProcessor.traceFailure( TelemetryProcessor.traceFailure(
Action.LoadCollections, Action.LoadCollections,
{ {
@@ -6,7 +6,6 @@
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/DocumentDB/preview/2025-11-01-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/DocumentDB/preview/2025-11-01-preview/cosmos-db.json
*/ */
import { stringifyError } from "Common/stringifyError";
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
@@ -19,14 +18,7 @@ export async function listSqlDatabases(
accountName: string, accountName: string,
): Promise<Types.SqlDatabaseListResult> { ): Promise<Types.SqlDatabaseListResult> {
const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases`; const path = `/subscriptions/${subscriptionId}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${accountName}/sqlDatabases`;
console.log("{{cdbp}} in listSqlDatabases(): path: " + path); return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion });
try {
console.log("{{cdbp}} in listSqlDatabases(): calling armRequest");
return armRequest({ host: configContext.ARM_ENDPOINT, path, method: "GET", apiVersion });
} catch (error) {
console.log("{{cdbp}} in listSqlDatabases(): ERROR: " + stringifyError(error));
throw error;
}
} }
/* Gets the SQL database under an existing Azure Cosmos DB database account with the provided name. */ /* Gets the SQL database under an existing Azure Cosmos DB database account with the provided name. */
-10
View File
@@ -5,7 +5,6 @@ Instead, generate ARM clients that consume this function with stricter typing.
*/ */
import { stringifyError } from "Common/stringifyError";
import promiseRetry, { AbortError } from "p-retry"; import promiseRetry, { AbortError } from "p-retry";
import { HttpHeaders } from "../../Common/Constants"; import { HttpHeaders } from "../../Common/Constants";
import { configContext } from "../../ConfigContext"; import { configContext } from "../../ConfigContext";
@@ -78,9 +77,6 @@ export async function armRequestWithoutPolling<T>({
} }
if (!userContext?.authorizationToken && !customHeaders?.["Authorization"]) { if (!userContext?.authorizationToken && !customHeaders?.["Authorization"]) {
console.log(
"{{cdbp}} in armRequestWithoutPolling(): condition '!userContext?.authorizationToken && !customHeaders?.['Authorization']' met, throwing 'No authority token provided' error",
);
throw new Error("No authority token provided"); throw new Error("No authority token provided");
} }
@@ -98,9 +94,6 @@ export async function armRequestWithoutPolling<T>({
}; };
const effectiveTimeoutMs = timeoutMs ?? DEFAULT_ARM_TIMEOUT_MS; const effectiveTimeoutMs = timeoutMs ?? DEFAULT_ARM_TIMEOUT_MS;
console.log(
`{{cdbp}} in armRequestWithoutPolling(): calling fetchWithRetry (method=${method}, timeoutMs=${effectiveTimeoutMs}, hasSignal=${!!signal})`,
);
const response = await fetchWithRetry(url.href, fetchInit, method, effectiveTimeoutMs, signal); const response = await fetchWithRetry(url.href, fetchInit, method, effectiveTimeoutMs, signal);
if (!response.ok) { if (!response.ok) {
@@ -115,11 +108,9 @@ export async function armRequestWithoutPolling<T>({
error.code = errorResponse.code; error.code = errorResponse.code;
} }
} catch (error) { } catch (error) {
console.log("{{cdbp}} in armRequestWithoutPolling(): ERROR: " + stringifyError(error));
throw new Error(await response.text()); throw new Error(await response.text());
} }
console.log("{{cdbp}} in armRequestWithoutPolling(): ERROR: " + stringifyError(error));
throw error; throw error;
} }
@@ -184,7 +175,6 @@ async function fetchWithRetry(
(attemptNumber: number) => { (attemptNumber: number) => {
const attemptTimeoutMs = const attemptTimeoutMs =
timeoutMs * RETRY_TIMEOUT_MULTIPLIERS[Math.min(attemptNumber - 1, RETRY_TIMEOUT_MULTIPLIERS.length - 1)]; timeoutMs * RETRY_TIMEOUT_MULTIPLIERS[Math.min(attemptNumber - 1, RETRY_TIMEOUT_MULTIPLIERS.length - 1)];
console.log(`{{cdbp}} in fetchWithRetry(): calling fetchWithTimeout: attempt=${attemptNumber} url=${url}`);
return fetchWithTimeout(url, fetchInit, attemptTimeoutMs); return fetchWithTimeout(url, fetchInit, attemptTimeoutMs);
}, },
{ {