Compare commits

..

30 Commits

Author SHA1 Message Date
Charles Gagnon
e9c8eb8564 Fix Mac signing (#18534) (#18539)
* Install .NET SDK for Mac signing

* Install runtime

* Specify 2.1.0

* Install SDK

(cherry picked from commit 23cbb98162)
2022-02-23 08:40:05 -08:00
Charles Gagnon
c2d6a2f4ff Port url-parse update (#18537) 2022-02-23 08:29:21 -08:00
Charles Gagnon
b0d3c95bec Fixing query editor smoke test (#18515) (#18530)
* Fixing query editor smoke test

* Fixing notification toast for telemetry opt out

* Adding SQL Carbon edit

(cherry picked from commit 5731366a1c)

Co-authored-by: Aasim Khan <aasimkhan30@gmail.com>
2022-02-22 16:03:48 -08:00
Alan Ren
734de6251d highlight problematic property in the designer when error is selected (#18512) (#18518)
* navigate to property when selecting error message

* use list component

* highlight problematic property

* remove unnecessary call

* comment

* comment
2022-02-22 16:03:24 -08:00
Candice Ye
8fc95f45d4 Updated package.json for arc and azcli extensions to version 1.0.0 (#18526)
* Update arc extension to 1.0.0

* Update azcli extension version to 1.0.0
2022-02-22 13:57:08 -08:00
Karl Burtram
34aa77eea3 Fix opt out prompt behavior (#18498) (#18499)
* fix header

* fix product name

Co-authored-by: Aditya Bist <adbist@microsoft.com>
2022-02-18 15:57:39 -08:00
Karl Burtram
b292e4233e Port - Restrict which sites out webview iframe can frame (#18495) (#18497)
* protocol handler - normalize paths

* use `extUri` for normalizing paths

* :lipstick;

* Add content security policy to top level webview

This change hardens our webviews by adding a fairly restrictive csp to them. This CSP should only apply to the outer webview iframe, not to the inner iframe which is controlled by extensions

Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com>
Co-authored-by: Matt Bierner <matb@microsoft.com>

Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com>
Co-authored-by: Matt Bierner <matb@microsoft.com>
2022-02-18 15:39:44 -08:00
Aasim Khan
fc1e3a24ef Removing extra toUrl call (#18492) (#18496) 2022-02-18 15:39:16 -08:00
Karl Burtram
0148071c0d Add mxgraph to thirdyparty notices (#18486) (#18488) 2022-02-18 15:38:59 -08:00
Barbara Valdez
560e8974dd Fix search experience in notebooks (#18474) (#18485)
* fix search on notebooks

* keep focus on findwidget
2022-02-18 15:38:38 -08:00
Barbara Valdez
23fbd4c1ed fix section markdown and html link (#18478) (#18482)
* fix section markdown and html link
2022-02-18 11:39:09 -08:00
Charles Gagnon
f0186bc5c0 Add timeout delay to Notebook cell connect (#18475) (#18480)
(cherry picked from commit a1a1793221)
2022-02-18 11:31:31 -08:00
Alan Ren
295009ec3d fix a typo in table designer (#18464) (#18471) 2022-02-17 19:53:06 -08:00
Christopher Suh
ee835356be Clear account tokens before refresh (#18452) (#18470)
* clear account tokens on refresh

* update refresh button after refresh
2022-02-17 19:52:40 -08:00
Lewis Sanchez
62822874ad Adds a tooltip title prop to the diagram node. (#18458) (#18463)
* Adds a tooltip title prop to the diagram node. (#18458)

* Adds a tooltip title prop to the diagram node.

* Updates azdataGraph package version to 0.0.16

* Fixes ansi_up version in remote package.json to match root package.json

* Fixes ansi_up version in remote/web package.json to match root version
2022-02-17 19:52:17 -08:00
Charles Gagnon
932865ceee Add option to disable running integration tests (#18454)
* Add option to disable running integration tests

* succeeded
2022-02-17 14:14:10 -08:00
Alan Ren
b02e97e851 table designer validation support (#18438) (#18453)
* table designer validation

* vbump sts
2022-02-17 14:13:37 -08:00
Neetu Singh
3faf51b573 [Port] [SQL Migration] Bug fixes for new feature SKU Recommendation in migration extension (#18449)
* Bump follow-redirects in /extensions/resource-deployment (#18349)

Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* LEGO: check in for main to temporary branch. (#18347)

Co-authored-by: Alex Ma <alma1@microsoft.com>

* [Loc] update to sql.xlf and sql-migration (#18352)

* Bump follow-redirects in /extensions/github-authentication (#18348)

Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump follow-redirects from 1.14.7 to 1.14.8 in /extensions/azurecore (#18350)

Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump ajv from 6.12.0 to 6.12.6 in /extensions/mssql (#18316)

Bumps [ajv](https://github.com/ajv-validator/ajv) from 6.12.0 to 6.12.6.
- [Release notes](https://github.com/ajv-validator/ajv/releases)
- [Commits](https://github.com/ajv-validator/ajv/compare/v6.12.0...v6.12.6)

---
updated-dependencies:
- dependency-name: ajv
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Database Projects - Add existing file (#18066)

* Add existing file to sqlproj

* Address PR comments

* Fix failing test

* Add convertSlashesForSqlProj to test failure

* Using proper zoom icon (#18338)

* Bump ansi_up (#18190)

* Fixing graph editing (#18361)

* Update to langpacks and xlfs for February Release, (#18354)

* Update to langpacks and xlfs

* fixed id for git

* Added small fix for locFunc (#18364)

* Small update to the changelog (#18369)

* [Loc] small update to sql-database-projects xlf (#18396)

* azdataGraph version bump to 0.0.15 (#18388)

* azdataGraph version bump to 0.0.15

* Updates azdataGraph version in remote package.json

* Updates azdataGraph version in remote web package.json

* Adding tooltips and fixing spacing (#18400)

* avoid auto language detection for sql editor (#18402)

* avoid auto lang detection for sql editor

* update comment

* fix SDK style projects not being able to find system dacpacs (#18218)

* fix SDK style projects not being able to find system dacpacs

* fix tests

* LEGO: check in for main to temporary branch. (#18417)

* LEGO: check in for main to temporary branch. (#18419)

* Bump url-parse (#18422)

* make sure the content is not undefined (#18406)

* [SKU Recommendation] Adding telemetry for errors happening during data collection/ get  recommendation and telemetry (#18345)

* Adding telemetry for errors happening during data collection/ telemetry for sku recommendation

* log and error happended during get sku recommendation

* Resolving comments from PR https://github.com/microsoft/azuredatastudio/pull/18252. 1) Adding click and close events to dispoable collection to avoid leaks. 2) Adding readable constant for number representing minutes.

* Changes - 1) updating migration workflow strings, 2) adding more onclick events to disposable collection.

* Remove PaaS, IaaS terms from string

* Changes -
1) Renamed 'Saved assessment result' to 'saved session'.
2) Removed Title from 'saved session' page.
3) Added stop data collection on migration start.

* Fixing context menu strings (#18404)

* Fixing context menu strings

* Fixing string

* Adding zoom button (#18407)

* Adding zoom button

* Fixing string

* Fixing the height of the query plan (#18409)

* Fixing the height of the query plan

* Fixing layout issues

* Fix on click edit mode states (#18321)

* fix click code cell

* modified editmode when updating active cell

* Updating readme with new gif that includes SKU Recommendation (#18432)

* Fix contributed icons for ModelView trees not showing (#18430)

* Fix contributed icons for ModelView trees not showing

* Use asCssUrl

* Fixed color contrast for error message in connect a dc window. (#18411)

* Fixed color contrast for error message in connect a dc window.

* Remove color check for error message

* Remove more unneeded checks

Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>

* fix holding down key scrolling issue (#18322)

* Stop propagation + debounce scroll

Co-authored-by: chgagnon <chgagnon@microsoft.com>

* LEGO: check in for main to temporary branch. (#18443)

* Adds Operational Cost to Query Plan Vertex Labels. (#18435)

* Adds operational cost to graph node labels.

* Code clean up.

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: csigs <csigs@users.noreply.github.com>
Co-authored-by: Alex Ma <alma1@microsoft.com>
Co-authored-by: Z Chen <13544267+zijchen@users.noreply.github.com>
Co-authored-by: Aasim Khan <aasimkhan30@gmail.com>
Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
Co-authored-by: Lewis Sanchez <87730006+lewis-sanchez@users.noreply.github.com>
Co-authored-by: Alan Ren <alanren@microsoft.com>
Co-authored-by: Kim Santiago <31145923+kisantia@users.noreply.github.com>
Co-authored-by: Barbara Valdez <34872381+barbaravaldez@users.noreply.github.com>
Co-authored-by: Candice Ye <candiceye@berkeley.edu>
2022-02-17 14:12:58 -08:00
Barbara Valdez
1928d076b1 fix holding down key scrolling issue (#18322) (#18439)
* Stop propagation + debounce scroll

Co-authored-by: chgagnon <chgagnon@microsoft.com>

Co-authored-by: chgagnon <chgagnon@microsoft.com>
2022-02-17 09:23:52 -08:00
Aasim Khan
c2d294cb79 Fixing the height of the query plan (#18409) (#18433)
* Fixing the height of the query plan

* Fixing layout issues
2022-02-17 09:23:25 -08:00
Aasim Khan
5e7356d652 Adding zoom button (#18407) (#18431)
* Adding zoom button (#18407)

* Adding zoom button

* Fixing string

* Using proper zoom icon (#18338)
2022-02-17 09:22:54 -08:00
Aasim Khan
8335854015 Fixing context menu strings (#18404) (#18427)
* Fixing context menu strings

* Fixing string
2022-02-17 09:22:23 -08:00
Charles Gagnon
52d33b493a Fix contributed icons for ModelView trees not showing (#18430) (#18436)
* Fix contributed icons for ModelView trees not showing

* Use asCssUrl

(cherry picked from commit 2be1394748)
2022-02-16 19:41:45 -08:00
Barbara Valdez
2e53b4c241 Fix on click edit mode states (#18321) (#18434)
* fix click code cell

* modified editmode when updating active cell
2022-02-16 17:03:17 -08:00
Alan Ren
efade32c62 make sure the content is not undefined (#18406) (#18426) 2022-02-16 15:14:52 -08:00
Charles Gagnon
2fd6990e73 Bump url-parse (#18422) (#18424)
(cherry picked from commit 3dbd5ac2c1)
2022-02-16 14:42:34 -08:00
Aasim Khan
d204fa9940 Adding tooltips and fixing spacing (#18400) (#18403) 2022-02-16 13:30:53 -08:00
Alex Ma
1f08aded06 Port of langpacks for release/1.35 (#18365)
* Update to langpacks and xlfs

* fixed id for git

* changed release date
2022-02-16 12:34:19 -08:00
Alan Ren
fc2138228d avoid auto language detection for sql editor (#18402) (#18408)
* avoid auto lang detection for sql editor

* update comment
2022-02-16 11:02:31 -08:00
Aasim Khan
a830820915 Fixing graph editing (#18361) (#18398) 2022-02-15 13:32:32 -08:00
1329 changed files with 47539 additions and 165468 deletions

View File

@@ -8,17 +8,17 @@
**/semver/**
**/test/**/*.js
**/node_modules/**
/extensions/**/out/**
/extensions/**/build/**
/extensions/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts
/extensions/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts
/extensions/markdown-language-features/media/**
/extensions/markdown-language-features/notebook-out/**
/extensions/typescript-basics/test/colorize-fixtures/**
/extensions/**/dist/**
/extensions/types
/extensions/typescript-language-features/test-workspace/**
/test/automation/out
**/vscode-api-tests/testWorkspace/**
**/vscode-api-tests/testWorkspace2/**
**/extensions/**/out/**
**/extensions/**/build/**
**/big-data-cluster/src/bigDataCluster/controller/apiGenerated.ts
**/big-data-cluster/src/bigDataCluster/controller/clusterApiGenerated2.ts
**/extensions/markdown-language-features/media/**
**/extensions/markdown-language-features/notebook-out/**
**/extensions/typescript-basics/test/colorize-fixtures/**
**/extensions/**/dist/**
**/extensions/typescript-language-features/test-workspace/**
# These files are not linted by `yarn eslint`, so we exclude them from being linted in the editor.
# This ensures that if we add new rules and they pass CI, the are also no errors in the editor.

View File

@@ -212,8 +212,6 @@
"restrictions": [
"vs/nls",
"azdata",
"mssql",
"azurecore",
"**/{vs,sql}/base/common/**",
"**/{vs,sql}/base/parts/*/common/**",
"**/{vs,sql}/platform/*/common/**"
@@ -474,8 +472,6 @@
"restrictions": [
"vscode",
"azdata",
"mssql",
"azurecore",
"vs/nls",
"**/{vs,sql}/base/common/**",
"**/{vs,sql}/platform/*/common/**",
@@ -554,7 +550,6 @@
"**/{vs,sql}/workbench/common/**",
"**/{vs,sql}/workbench/services/**/common/**",
"**/{vs,sql}/workbench/api/**/common/**",
"**/{vs,sql}/workbench/contrib/**/common/**",
"vs/workbench/contrib/files/common/editors/fileEditorInput", // this should be fine, it only accesses constants from contrib
"vscode-textmate",
"vscode-oniguruma",
@@ -582,8 +577,6 @@
"vs/nls",
"vs/css!./**/*",
"azdata",
"mssql",
"azurecore",
"vscode",
"**/{vs,sql}/base/**/{common,browser,worker}/**",
"**/{vs,sql}/platform/**/{common,browser}/**",
@@ -592,7 +585,6 @@
"**/{vs,sql}/workbench/{common,browser}/**",
"**/{vs,sql}/workbench/api/{common,browser}/**",
"**/{vs,sql}/workbench/services/**/{common,browser}/**",
"**/{vs,sql}/workbench/contrib/**/common/**",
"vscode-textmate",
"vscode-oniguruma",
"iconv-lite-umd",
@@ -1151,7 +1143,6 @@
"src/sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin.ts",
"src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts",
"src/sql/base/browser/ui/table/plugins/rowDetailView.ts",
"src/sql/base/browser/ui/table/plugins/rowMoveManager.plugin.ts",
"src/sql/base/browser/ui/table/plugins/rowSelectionModel.plugin.ts",
"src/sql/workbench/services/notebook/browser/outputs/factories.ts",
"src/sql/workbench/services/notebook/browser/outputs/mimemodel.ts",

1
.github/CODEOWNERS vendored
View File

@@ -11,7 +11,6 @@
/extensions/query-history/ @Charles-Gagnon
/extensions/resource-deployment/ @Charles-Gagnon
/extensions/schema-compare/ @kisantia
/extensions/sql-bindings/ @vasubhog @Charles-Gagnon @lucyzhang929 @chlafreniere @MaddyDev
/extensions/sql-database-projects/ @Benjin @kisantia
/extensions/mssql/config.json @Charles-Gagnon @alanrenmsft @kburtram

View File

@@ -2,9 +2,8 @@
Needs Logs:
comment: "We need more info to debug your particular issue. If you could attach your logs to the issue (ensure no private data is in them), it would help us fix the issue much faster.
First open the Settings page, find the `Mssql: Tracing Level` setting and change that to `All` then restart ADS and repro your issue.
Next there are two types of logs to collect:
There are two types of logs to collect:
**Console Logs**
@@ -28,22 +27,6 @@ Next there are two types of logs to collect:
- This will open the log folder locally. Please zip up this folder and attach it to the issue."
# actions for Needs Logs - Azure label
Needs Logs - Azure:
comment: "We need more info to debug your Azure Active Directory issue. If you could attach your logs to the issue (ensure no private data is in them), it would help us fix the issue much faster.
- In the settings menu, find the setting titled `Azure: Logging Level` and select the `Verbose` option
- Run the process that produces your error
- Open command palette (Click **View** -> **Command Palette**)
- Run the command: **`Developer: Open Logs Folder`**
- Follow this path to find the Azure Accounts log file: `[default log folder]/exthost1/output_logging_[earliest timestamp]/#-Azure Acounts.log`
- Please attach the Azure-Accounts.log file to the issue."
# actions for Out of Scope label
Out of Scope:
comment: "Thank you for opening this suggestion! This enhancement is not planned in our

View File

@@ -13,7 +13,7 @@ on:
jobs:
windows:
name: Windows
runs-on: windows-2019
runs-on: windows-latest
timeout-minutes: 30
env:
CHILD_CONCURRENCY: "1"
@@ -131,15 +131,12 @@ jobs:
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
run: yarn --frozen-lockfile --network-timeout 180000
# Don't inline source maps so that we generate code coverage for ts files
- name: Compile and Download
run: yarn npm-run-all --max_old_space_size=4095 -lp compile "electron x64" playwright-install download-builtin-extensions
env:
SQL_NO_INLINE_SOURCEMAP: 1
- name: Run Unit Tests (Electron)
id: electron-unit-tests
run: DISPLAY=:10 ./scripts/test.sh --runGlob "**/sql/**/*.test.js" --coverage
run: DISPLAY=:10 ./scripts/test.sh --runGlob "**/sql/**/*.test.js" # {{SQL CARBON EDIT}} Run only our tests with coverage. Disable for now since it's currently broken --coverage
- name: Run Extension Unit Tests (Electron)
id: electron-extension-unit-tests

View File

@@ -1,3 +1,3 @@
disturl "https://electronjs.org/headers"
target "13.6.6"
target "13.5.0"
runtime "electron"

View File

@@ -1,74 +1,5 @@
# Change Log
## Version 1.36.1
* Release date: April 22, 2022
* Release status: General Availability
## What's new in this version
- April Hotfix addressing these issues https://github.com/microsoft/azuredatastudio/milestone/88?closed=1.
| Platform |
| --------------------------------------- |
| [Windows User Installer][win-user] |
| [Windows System Installer][win-system] |
| [Windows ZIP][win-zip] |
| [macOS ZIP][osx-zip] |
| [Linux TAR.GZ][linux-zip] |
| [Linux RPM][linux-rpm] |
| [Linux DEB][linux-deb] |
[win-user]: https://go.microsoft.com/fwlink/?linkid=2193235
[win-system]: https://go.microsoft.com/fwlink/?linkid=2193326
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2193236
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2192971
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2193237
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2193238
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2193327
## Version 1.36.2
* Release date: May 20, 2022
* Release status: General Availability
## What's new in this version
- Fix connectivity issue with PBI data source
- Fix query plan zoom and icon issues
- Issues fixed in this release https://github.com/microsoft/azuredatastudio/milestone/89?closed=1
## Version 1.36.1
* Release date: April 22, 2022
* Release status: General Availability
## What's new in this version
* April Hotfix addressing these issues https://github.com/microsoft/azuredatastudio/milestone/88?closed=1.
* Hotfix RCA - https://github.com/microsoft/azuredatastudio/wiki/ADS-April-2022-Hotfix-RCA
## Version 1.36.0
* Release date: April 20, 2022
* Release status: General Availability
## What's new in this version
- General Availability of the Azure SQL Migration Extension for ADS
- Support for .NET Interactive Notebooks Extension
- New Table Designer Features including support for System Versioned, Graph and Memory Optomized Tables
- Query Plan Viewer Updates includign warning and parallelism icons, the option to disable tooltips and support for opening .sqlplan files
- Improvements in SQL Projects and Schema Compare
## Version 1.35.1
* Release date: March 17, 2022
* Release status: General Availability
## Hotfix release
- Fix for [Excel number format #18615](https://github.com/microsoft/azuredatastudio/issues/18615)
- Fix for [Geometry Data Type Returned as Unknown Charset in Results Grid #18630](https://github.com/microsoft/azuredatastudio/issues/18630)
## Version 1.35.0
* Release date: February 24, 2022
* Release status: General Availability
## What's new in this version
* New Features:
* Table Designer - Added functionality for creation and management of tables for SQL Servers. Built using DacFx framework
* Query Plan Viewer - Added functionality for users to view a graphic view of estimated and actual query plans without need for an extension
* Azure Arc Extension - Updated the Data Controller deployment wizard and the SQL Managed Instance - Azure Arc deployment wizard to reflect the deployment experience in Azure Portal
* Bug Fixes:
* Azure Arc Extension - SQL Managed Instance-Azure Arc is now fixed for both indirect connectivity mode and direct connectivity mode
* Notebooks - Support for keyboard navigation between cells to minimize mouse clicking
## Version 1.34.0
* Release date: December 15, 2021
* Release status: General Availability
@@ -79,9 +10,9 @@
* Support for project build with .NET 6 in SQL Database Projects extension
* Publish to container in SQL Database Projects extension
* Undo and redo support for notebook cell-level operations
* Extension Updates:
* Azure SQL Migration
* Azure SQL Migration
* Langpacks
* SQL Database Projects
@@ -91,7 +22,7 @@
* Fix to pre-populate target database names in the migration wizard in Azure SQL Migration extension
* Fix to column sorting in grids where the presence of null values could lead to unexpected results
* Fix for Python upgrades when two or more notebooks were open
## Version 1.33.1
* Release date: Nov 4, 2021
* Release status: General Availability
@@ -100,23 +31,43 @@
- Fix for [#16535 Unable to See Saved Connections in Restricted Mode](https://github.com/microsoft/azuredatastudio/issues/17535)
- Fix for [#17579 Can't type in Notebook code cell after editing text cell](https://github.com/microsoft/azuredatastudio/issues/17579)
| Platform |
| --------------------------------------- |
| [Windows User Installer][win-user] |
| [Windows System Installer][win-system] |
| [Windows ZIP][win-zip] |
| [macOS ZIP][osx-zip] |
| [Linux TAR.GZ][linux-zip] |
| [Linux RPM][linux-rpm] |
| [Linux DEB][linux-deb] |
[win-user]: https://go.microsoft.com/fwlink/?linkid=2176805
[win-system]: https://go.microsoft.com/fwlink/?linkid=2175910
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2176806
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2176807
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2176505
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2176005
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2176006
## Version 1.33.0
* Release date: October 27, 2021
* Release status: General Availability
## What's new in this version
* New Notebook Features:
* Notebook Views
* Split cell support
* Keyboard shortcuts for Markdown Toolbar Cells
* Notebook Views
* Split cell support
* Keyboard shortcuts for Markdown Toolbar Cells
* Ctrl/Cmd + B = Bold Text
* Ctrl/Cmd + I = Italicize Text
* Ctrl/Cmd + U = Underline Text
* Ctrl/Cmd + Shift + K = Add Code Block
* Ctrl/Cmd + Shift + H = Highlight Text
* Book improvements
* Book improvements
* Add a new section
* Drag and Drop
* Extension Updates:
* Import
* Langpacks
@@ -132,8 +83,8 @@
* Release date: August 18, 2021
* Release status: General Availability
* Extension Updates:
* Arc/Az CLI extensions - Azure Arc extension now uses Azure CLI instead of Azure Data CLI for deploying and interacting with Azure Arc
instances
* Arc/Az CLI extensions - Azure Arc extension now uses Azure CLI instead of Azure Data CLI for deploying and interacting with Azure Arc
instances
* Langpacks
* SQL Database Projects
* Azure Monitor

View File

@@ -131,10 +131,10 @@ Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the [Source EULA](LICENSE.txt).
[win-user]: https://go.microsoft.com/fwlink/?linkid=2193235
[win-system]: https://go.microsoft.com/fwlink/?linkid=2193326
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2193236
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2192971
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2193237
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2193238
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2193327
[win-user]: https://go.microsoft.com/fwlink/?linkid=2183280
[win-system]: https://go.microsoft.com/fwlink/?linkid=2183423
[win-zip]: https://go.microsoft.com/fwlink/?linkid=2183190
[osx-zip]: https://go.microsoft.com/fwlink/?linkid=2183189
[linux-zip]: https://go.microsoft.com/fwlink/?linkid=2183277
[linux-rpm]: https://go.microsoft.com/fwlink/?linkid=2183342
[linux-deb]: https://go.microsoft.com/fwlink/?linkid=2183341

View File

@@ -0,0 +1,17 @@
{
"env": {
"commonjs": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
}
}

2
build/actions/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
node_modules
*.js.map

View File

@@ -1,7 +1,6 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <reference path='../../extensions/azurecore/src/azurecore.d.ts' />
/// <reference path='../../extensions/mssql/src/mssql.d.ts' />
Object.defineProperty(exports, "__esModule", { value: true });

96
build/actions/api/api.ts Normal file
View File

@@ -0,0 +1,96 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export interface GitHub {
query(query: Query): AsyncIterableIterator<GitHubIssue[]>
hasWriteAccess(user: User): Promise<boolean>
repoHasLabel(label: string): Promise<boolean>
createLabel(label: string, color: string, description: string): Promise<void>
deleteLabel(label: string): Promise<void>
readConfig(path: string): Promise<any>
createIssue(owner: string, repo: string, title: string, body: string): Promise<void>
releaseContainsCommit(release: string, commit: string): Promise<boolean>
}
export interface GitHubIssue extends GitHub {
getIssue(): Promise<Issue>
postComment(body: string): Promise<void>
deleteComment(id: number): Promise<void>
getComments(last?: boolean): AsyncIterableIterator<Comment[]>
closeIssue(): Promise<void>
lockIssue(): Promise<void>
setMilestone(milestoneId: number): Promise<void>
addLabel(label: string): Promise<void>
removeLabel(label: string): Promise<void>
addAssignee(assignee: string): Promise<void>
getClosingInfo(): Promise<{ hash: string | undefined; timestamp: number } | undefined>
}
type SortVar =
| 'comments'
| 'reactions'
| 'reactions-+1'
| 'reactions--1'
| 'reactions-smile'
| 'reactions-thinking_face'
| 'reactions-heart'
| 'reactions-tada'
| 'interactions'
| 'created'
| 'updated'
type SortOrder = 'asc' | 'desc'
export type Reactions = {
'+1': number
'-1': number
laugh: number
hooray: number
confused: number
heart: number
rocket: number
eyes: number
}
export interface User {
name: string
isGitHubApp?: boolean
}
export interface Comment {
author: User
body: string
id: number
timestamp: number
}
export interface Issue {
author: User
body: string
title: string
labels: string[]
open: boolean
locked: boolean
number: number
numComments: number
reactions: Reactions
milestoneId: number | null
assignee?: string
createdAt: number
updatedAt: number
closedAt?: number
}
export interface Query {
q: string
sort?: SortVar
order?: SortOrder
}

View File

@@ -0,0 +1,293 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@actions/core");
const github_1 = require("@actions/github");
const child_process_1 = require("child_process");
const utils_1 = require("../utils/utils");
class OctoKit {
constructor(token, params, options = { readonly: false }) {
this.token = token;
this.params = params;
this.options = options;
// when in readonly mode, record labels just-created so at to not throw unneccesary errors
this.mockLabels = new Set();
this.writeAccessCache = {};
this.octokit = new github_1.GitHub(token);
}
async *query(query) {
const q = query.q + ` repo:${this.params.owner}/${this.params.repo}`;
console.log(`Querying for ${q}:`);
const options = this.octokit.search.issuesAndPullRequests.endpoint.merge({
...query,
q,
per_page: 100,
headers: { Accept: 'application/vnd.github.squirrel-girl-preview+json' },
});
let pageNum = 0;
const timeout = async () => {
if (pageNum < 2) {
/* pass */
}
else if (pageNum < 4) {
await new Promise((resolve) => setTimeout(resolve, 3000));
}
else {
await new Promise((resolve) => setTimeout(resolve, 30000));
}
};
for await (const pageResponse of this.octokit.paginate.iterator(options)) {
await timeout();
await utils_1.logRateLimit(this.token);
const page = pageResponse.data;
console.log(`Page ${++pageNum}: ${page.map(({ number }) => number).join(' ')}`);
yield page.map((issue) => new OctoKitIssue(this.token, this.params, this.octokitIssueToIssue(issue)));
}
}
async createIssue(owner, repo, title, body) {
core_1.debug(`Creating issue \`${title}\` on ${owner}/${repo}`);
if (!this.options.readonly)
await this.octokit.issues.create({ owner, repo, title, body });
}
octokitIssueToIssue(issue) {
var _a, _b, _c, _d, _e, _f;
return {
author: { name: issue.user.login, isGitHubApp: issue.user.type === 'Bot' },
body: issue.body,
number: issue.number,
title: issue.title,
labels: issue.labels.map((label) => label.name),
open: issue.state === 'open',
locked: issue.locked,
numComments: issue.comments,
reactions: issue.reactions,
assignee: (_b = (_a = issue.assignee) === null || _a === void 0 ? void 0 : _a.login) !== null && _b !== void 0 ? _b : (_d = (_c = issue.assignees) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.login,
milestoneId: (_f = (_e = issue.milestone) === null || _e === void 0 ? void 0 : _e.number) !== null && _f !== void 0 ? _f : null,
createdAt: +new Date(issue.created_at),
updatedAt: +new Date(issue.updated_at),
closedAt: issue.closed_at ? +new Date(issue.closed_at) : undefined,
};
}
async hasWriteAccess(user) {
if (user.name in this.writeAccessCache) {
core_1.debug('Got permissions from cache for ' + user);
return this.writeAccessCache[user.name];
}
core_1.debug('Fetching permissions for ' + user);
const permissions = (await this.octokit.repos.getCollaboratorPermissionLevel({
...this.params,
username: user.name,
})).data.permission;
return (this.writeAccessCache[user.name] = permissions === 'admin' || permissions === 'write');
}
async repoHasLabel(name) {
try {
await this.octokit.issues.getLabel({ ...this.params, name });
return true;
}
catch (err) {
if (err.status === 404) {
return this.options.readonly && this.mockLabels.has(name);
}
throw err;
}
}
async createLabel(name, color, description) {
core_1.debug('Creating label ' + name);
if (!this.options.readonly)
await this.octokit.issues.createLabel({ ...this.params, color, description, name });
else
this.mockLabels.add(name);
}
async deleteLabel(name) {
core_1.debug('Deleting label ' + name);
try {
if (!this.options.readonly)
await this.octokit.issues.deleteLabel({ ...this.params, name });
}
catch (err) {
if (err.status === 404) {
return;
}
throw err;
}
}
async readConfig(path) {
core_1.debug('Reading config at ' + path);
const repoPath = `.github/${path}.json`;
const data = (await this.octokit.repos.getContents({ ...this.params, path: repoPath })).data;
if ('type' in data && data.type === 'file') {
if (data.encoding === 'base64' && data.content) {
return JSON.parse(Buffer.from(data.content, 'base64').toString('utf-8'));
}
throw Error(`Could not read contents "${data.content}" in encoding "${data.encoding}"`);
}
throw Error('Found directory at config path when expecting file' + JSON.stringify(data));
}
async releaseContainsCommit(release, commit) {
if (utils_1.getInput('commitReleasedDebuggingOverride')) {
return true;
}
return new Promise((resolve, reject) => child_process_1.exec(`git -C ./repo merge-base --is-ancestor ${commit} ${release}`, (err) => !err || err.code === 1 ? resolve(!err) : reject(err)));
}
}
exports.OctoKit = OctoKit;
class OctoKitIssue extends OctoKit {
constructor(token, params, issueData, options = { readonly: false }) {
super(token, params, options);
this.params = params;
this.issueData = issueData;
}
async addAssignee(assignee) {
core_1.debug('Adding assignee ' + assignee + ' to ' + this.issueData.number);
if (!this.options.readonly) {
await this.octokit.issues.addAssignees({
...this.params,
issue_number: this.issueData.number,
assignees: [assignee],
});
}
}
async closeIssue() {
core_1.debug('Closing issue ' + this.issueData.number);
if (!this.options.readonly)
await this.octokit.issues.update({
...this.params,
issue_number: this.issueData.number,
state: 'closed',
});
}
async lockIssue() {
core_1.debug('Locking issue ' + this.issueData.number);
if (!this.options.readonly)
await this.octokit.issues.lock({ ...this.params, issue_number: this.issueData.number });
}
async getIssue() {
if (isIssue(this.issueData)) {
core_1.debug('Got issue data from query result ' + this.issueData.number);
return this.issueData;
}
console.log('Fetching issue ' + this.issueData.number);
const issue = (await this.octokit.issues.get({
...this.params,
issue_number: this.issueData.number,
mediaType: { previews: ['squirrel-girl'] },
})).data;
return (this.issueData = this.octokitIssueToIssue(issue));
}
async postComment(body) {
core_1.debug(`Posting comment ${body} on ${this.issueData.number}`);
if (!this.options.readonly)
await this.octokit.issues.createComment({
...this.params,
issue_number: this.issueData.number,
body,
});
}
async deleteComment(id) {
core_1.debug(`Deleting comment ${id} on ${this.issueData.number}`);
if (!this.options.readonly)
await this.octokit.issues.deleteComment({
owner: this.params.owner,
repo: this.params.repo,
comment_id: id,
});
}
async setMilestone(milestoneId) {
core_1.debug(`Setting milestone for ${this.issueData.number} to ${milestoneId}`);
if (!this.options.readonly)
await this.octokit.issues.update({
...this.params,
issue_number: this.issueData.number,
milestone: milestoneId,
});
}
async *getComments(last) {
core_1.debug('Fetching comments for ' + this.issueData.number);
const response = this.octokit.paginate.iterator(this.octokit.issues.listComments.endpoint.merge({
...this.params,
issue_number: this.issueData.number,
per_page: 100,
...(last ? { per_page: 1, page: (await this.getIssue()).numComments } : {}),
}));
for await (const page of response) {
yield page.data.map((comment) => ({
author: { name: comment.user.login, isGitHubApp: comment.user.type === 'Bot' },
body: comment.body,
id: comment.id,
timestamp: +new Date(comment.created_at),
}));
}
}
async addLabel(name) {
core_1.debug(`Adding label ${name} to ${this.issueData.number}`);
if (!(await this.repoHasLabel(name))) {
throw Error(`Action could not execute becuase label ${name} is not defined.`);
}
if (!this.options.readonly)
await this.octokit.issues.addLabels({
...this.params,
issue_number: this.issueData.number,
labels: [name],
});
}
async removeLabel(name) {
core_1.debug(`Removing label ${name} from ${this.issueData.number}`);
try {
if (!this.options.readonly)
await this.octokit.issues.removeLabel({
...this.params,
issue_number: this.issueData.number,
name,
});
}
catch (err) {
if (err.status === 404) {
console.log(`Label ${name} not found on issue`);
return;
}
throw err;
}
}
async getClosingInfo() {
var _a;
if ((await this.getIssue()).open) {
return;
}
const options = this.octokit.issues.listEventsForTimeline.endpoint.merge({
...this.params,
issue_number: this.issueData.number,
});
let closingCommit;
for await (const event of this.octokit.paginate.iterator(options)) {
const timelineEvents = event.data;
for (const timelineEvent of timelineEvents) {
if (timelineEvent.event === 'closed') {
closingCommit = {
hash: (_a = timelineEvent.commit_id) !== null && _a !== void 0 ? _a : undefined,
timestamp: +new Date(timelineEvent.created_at),
};
}
}
}
console.log(`Got ${closingCommit} as closing commit of ${this.issueData.number}`);
return closingCommit;
}
}
exports.OctoKitIssue = OctoKitIssue;
function isIssue(object) {
const isIssue = 'author' in object &&
'body' in object &&
'title' in object &&
'labels' in object &&
'open' in object &&
'locked' in object &&
'number' in object &&
'numComments' in object &&
'reactions' in object &&
'milestoneId' in object;
return isIssue;
}

View File

@@ -0,0 +1,336 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { debug } from '@actions/core'
import { GitHub as GitHubAPI } from '@actions/github'
import { Octokit } from '@octokit/rest'
import { exec } from 'child_process'
import { getInput, logRateLimit } from '../utils/utils'
import { Comment, GitHub, GitHubIssue, Issue, Query, User } from './api'
export class OctoKit implements GitHub {
protected octokit: GitHubAPI
// when in readonly mode, record labels just-created so at to not throw unneccesary errors
protected mockLabels: Set<string> = new Set()
constructor(
private token: string,
protected params: { repo: string; owner: string },
protected options: { readonly: boolean } = { readonly: false },
) {
this.octokit = new GitHubAPI(token)
}
async *query(query: Query): AsyncIterableIterator<GitHubIssue[]> {
const q = query.q + ` repo:${this.params.owner}/${this.params.repo}`
console.log(`Querying for ${q}:`)
const options = this.octokit.search.issuesAndPullRequests.endpoint.merge({
...query,
q,
per_page: 100,
headers: { Accept: 'application/vnd.github.squirrel-girl-preview+json' },
})
let pageNum = 0
const timeout = async () => {
if (pageNum < 2) {
/* pass */
} else if (pageNum < 4) {
await new Promise((resolve) => setTimeout(resolve, 3000))
} else {
await new Promise((resolve) => setTimeout(resolve, 30000))
}
}
for await (const pageResponse of this.octokit.paginate.iterator(options)) {
await timeout()
await logRateLimit(this.token)
const page: Array<Octokit.SearchIssuesAndPullRequestsResponseItemsItem> = pageResponse.data
console.log(`Page ${++pageNum}: ${page.map(({ number }) => number).join(' ')}`)
yield page.map(
(issue) => new OctoKitIssue(this.token, this.params, this.octokitIssueToIssue(issue)),
)
}
}
async createIssue(owner: string, repo: string, title: string, body: string): Promise<void> {
debug(`Creating issue \`${title}\` on ${owner}/${repo}`)
if (!this.options.readonly) await this.octokit.issues.create({ owner, repo, title, body })
}
protected octokitIssueToIssue(
issue: Octokit.IssuesGetResponse | Octokit.SearchIssuesAndPullRequestsResponseItemsItem,
): Issue {
return {
author: { name: issue.user.login, isGitHubApp: issue.user.type === 'Bot' },
body: issue.body,
number: issue.number,
title: issue.title,
labels: (issue.labels as Octokit.IssuesGetLabelResponse[]).map((label) => label.name),
open: issue.state === 'open',
locked: (issue as any).locked,
numComments: issue.comments,
reactions: (issue as any).reactions,
assignee: issue.assignee?.login ?? (issue as any).assignees?.[0]?.login,
milestoneId: issue.milestone?.number ?? null,
createdAt: +new Date(issue.created_at),
updatedAt: +new Date(issue.updated_at),
closedAt: issue.closed_at ? +new Date((issue.closed_at as unknown) as string) : undefined,
}
}
private writeAccessCache: Record<string, boolean> = {}
async hasWriteAccess(user: User): Promise<boolean> {
if (user.name in this.writeAccessCache) {
debug('Got permissions from cache for ' + user)
return this.writeAccessCache[user.name]
}
debug('Fetching permissions for ' + user)
const permissions = (
await this.octokit.repos.getCollaboratorPermissionLevel({
...this.params,
username: user.name,
})
).data.permission
return (this.writeAccessCache[user.name] = permissions === 'admin' || permissions === 'write')
}
async repoHasLabel(name: string): Promise<boolean> {
try {
await this.octokit.issues.getLabel({ ...this.params, name })
return true
} catch (err) {
if (err.status === 404) {
return this.options.readonly && this.mockLabels.has(name)
}
throw err
}
}
async createLabel(name: string, color: string, description: string): Promise<void> {
debug('Creating label ' + name)
if (!this.options.readonly)
await this.octokit.issues.createLabel({ ...this.params, color, description, name })
else this.mockLabels.add(name)
}
async deleteLabel(name: string): Promise<void> {
debug('Deleting label ' + name)
try {
if (!this.options.readonly) await this.octokit.issues.deleteLabel({ ...this.params, name })
} catch (err) {
if (err.status === 404) {
return
}
throw err
}
}
async readConfig(path: string): Promise<any> {
debug('Reading config at ' + path)
const repoPath = `.github/${path}.json`
const data = (await this.octokit.repos.getContents({ ...this.params, path: repoPath })).data
if ('type' in data && data.type === 'file') {
if (data.encoding === 'base64' && data.content) {
return JSON.parse(Buffer.from(data.content, 'base64').toString('utf-8'))
}
throw Error(`Could not read contents "${data.content}" in encoding "${data.encoding}"`)
}
throw Error('Found directory at config path when expecting file' + JSON.stringify(data))
}
async releaseContainsCommit(release: string, commit: string): Promise<boolean> {
if (getInput('commitReleasedDebuggingOverride')) {
return true
}
return new Promise((resolve, reject) =>
exec(`git -C ./repo merge-base --is-ancestor ${commit} ${release}`, (err) =>
!err || err.code === 1 ? resolve(!err) : reject(err),
),
)
}
}
export class OctoKitIssue extends OctoKit implements GitHubIssue {
constructor(
token: string,
protected params: { repo: string; owner: string },
private issueData: { number: number } | Issue,
options: { readonly: boolean } = { readonly: false },
) {
super(token, params, options)
}
async addAssignee(assignee: string): Promise<void> {
debug('Adding assignee ' + assignee + ' to ' + this.issueData.number)
if (!this.options.readonly) {
await this.octokit.issues.addAssignees({
...this.params,
issue_number: this.issueData.number,
assignees: [assignee],
})
}
}
async closeIssue(): Promise<void> {
debug('Closing issue ' + this.issueData.number)
if (!this.options.readonly)
await this.octokit.issues.update({
...this.params,
issue_number: this.issueData.number,
state: 'closed',
})
}
async lockIssue(): Promise<void> {
debug('Locking issue ' + this.issueData.number)
if (!this.options.readonly)
await this.octokit.issues.lock({ ...this.params, issue_number: this.issueData.number })
}
async getIssue(): Promise<Issue> {
if (isIssue(this.issueData)) {
debug('Got issue data from query result ' + this.issueData.number)
return this.issueData
}
console.log('Fetching issue ' + this.issueData.number)
const issue = (
await this.octokit.issues.get({
...this.params,
issue_number: this.issueData.number,
mediaType: { previews: ['squirrel-girl'] },
})
).data
return (this.issueData = this.octokitIssueToIssue(issue))
}
async postComment(body: string): Promise<void> {
debug(`Posting comment ${body} on ${this.issueData.number}`)
if (!this.options.readonly)
await this.octokit.issues.createComment({
...this.params,
issue_number: this.issueData.number,
body,
})
}
async deleteComment(id: number): Promise<void> {
debug(`Deleting comment ${id} on ${this.issueData.number}`)
if (!this.options.readonly)
await this.octokit.issues.deleteComment({
owner: this.params.owner,
repo: this.params.repo,
comment_id: id,
})
}
async setMilestone(milestoneId: number) {
debug(`Setting milestone for ${this.issueData.number} to ${milestoneId}`)
if (!this.options.readonly)
await this.octokit.issues.update({
...this.params,
issue_number: this.issueData.number,
milestone: milestoneId,
})
}
async *getComments(last?: boolean): AsyncIterableIterator<Comment[]> {
debug('Fetching comments for ' + this.issueData.number)
const response = this.octokit.paginate.iterator(
this.octokit.issues.listComments.endpoint.merge({
...this.params,
issue_number: this.issueData.number,
per_page: 100,
...(last ? { per_page: 1, page: (await this.getIssue()).numComments } : {}),
}),
)
for await (const page of response) {
yield (page.data as Octokit.IssuesListCommentsResponseItem[]).map((comment) => ({
author: { name: comment.user.login, isGitHubApp: comment.user.type === 'Bot' },
body: comment.body,
id: comment.id,
timestamp: +new Date(comment.created_at),
}))
}
}
async addLabel(name: string): Promise<void> {
debug(`Adding label ${name} to ${this.issueData.number}`)
if (!(await this.repoHasLabel(name))) {
throw Error(`Action could not execute becuase label ${name} is not defined.`)
}
if (!this.options.readonly)
await this.octokit.issues.addLabels({
...this.params,
issue_number: this.issueData.number,
labels: [name],
})
}
async removeLabel(name: string): Promise<void> {
debug(`Removing label ${name} from ${this.issueData.number}`)
try {
if (!this.options.readonly)
await this.octokit.issues.removeLabel({
...this.params,
issue_number: this.issueData.number,
name,
})
} catch (err) {
if (err.status === 404) {
console.log(`Label ${name} not found on issue`)
return
}
throw err
}
}
async getClosingInfo(): Promise<{ hash: string | undefined; timestamp: number } | undefined> {
if ((await this.getIssue()).open) {
return
}
const options = this.octokit.issues.listEventsForTimeline.endpoint.merge({
...this.params,
issue_number: this.issueData.number,
})
let closingCommit: { hash: string | undefined; timestamp: number } | undefined
for await (const event of this.octokit.paginate.iterator(options)) {
const timelineEvents = event.data as Octokit.IssuesListEventsForTimelineResponseItem[]
for (const timelineEvent of timelineEvents) {
if (timelineEvent.event === 'closed') {
closingCommit = {
hash: timelineEvent.commit_id ?? undefined,
timestamp: +new Date(timelineEvent.created_at),
}
}
}
}
console.log(`Got ${closingCommit} as closing commit of ${this.issueData.number}`)
return closingCommit
}
}
function isIssue(object: any): object is Issue {
const isIssue =
'author' in object &&
'body' in object &&
'title' in object &&
'labels' in object &&
'open' in object &&
'locked' in object &&
'number' in object &&
'numComments' in object &&
'reactions' in object &&
'milestoneId' in object
return isIssue
}

View File

@@ -0,0 +1,123 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
class Testbed {
constructor(config) {
var _a, _b, _c, _d, _e;
this.config = {
globalLabels: (_a = config === null || config === void 0 ? void 0 : config.globalLabels) !== null && _a !== void 0 ? _a : [],
configs: (_b = config === null || config === void 0 ? void 0 : config.configs) !== null && _b !== void 0 ? _b : {},
writers: (_c = config === null || config === void 0 ? void 0 : config.writers) !== null && _c !== void 0 ? _c : [],
releasedCommits: (_d = config === null || config === void 0 ? void 0 : config.releasedCommits) !== null && _d !== void 0 ? _d : [],
queryRunner: (_e = config === null || config === void 0 ? void 0 : config.queryRunner) !== null && _e !== void 0 ? _e : async function* () {
yield [];
},
};
}
async *query(query) {
for await (const page of this.config.queryRunner(query)) {
yield page.map((issue) => issue instanceof TestbedIssue ? issue : new TestbedIssue(this.config, issue));
}
}
async createIssue(_owner, _repo, _title, _body) {
// pass...
}
async readConfig(path) {
return JSON.parse(JSON.stringify(this.config.configs[path]));
}
async hasWriteAccess(user) {
return this.config.writers.includes(user.name);
}
async repoHasLabel(label) {
return this.config.globalLabels.includes(label);
}
async createLabel(label, _color, _description) {
this.config.globalLabels.push(label);
}
async deleteLabel(labelToDelete) {
this.config.globalLabels = this.config.globalLabels.filter((label) => label !== labelToDelete);
}
async releaseContainsCommit(_release, commit) {
return this.config.releasedCommits.includes(commit);
}
}
exports.Testbed = Testbed;
class TestbedIssue extends Testbed {
constructor(globalConfig, issueConfig) {
var _a, _b, _c;
super(globalConfig);
issueConfig = issueConfig !== null && issueConfig !== void 0 ? issueConfig : {};
issueConfig.comments = (_a = issueConfig === null || issueConfig === void 0 ? void 0 : issueConfig.comments) !== null && _a !== void 0 ? _a : [];
issueConfig.labels = (_b = issueConfig === null || issueConfig === void 0 ? void 0 : issueConfig.labels) !== null && _b !== void 0 ? _b : [];
issueConfig.issue = {
author: { name: 'JacksonKearl' },
body: 'issue body',
locked: false,
numComments: ((_c = issueConfig === null || issueConfig === void 0 ? void 0 : issueConfig.comments) === null || _c === void 0 ? void 0 : _c.length) || 0,
number: 1,
open: true,
title: 'issue title',
assignee: undefined,
reactions: {
'+1': 0,
'-1': 0,
confused: 0,
eyes: 0,
heart: 0,
hooray: 0,
laugh: 0,
rocket: 0,
},
closedAt: undefined,
createdAt: +new Date(),
updatedAt: +new Date(),
...issueConfig.issue,
};
this.issueConfig = issueConfig;
}
async addAssignee(assignee) {
this.issueConfig.issue.assignee = assignee;
}
async setMilestone(milestoneId) {
this.issueConfig.issue.milestoneId = milestoneId;
}
async getIssue() {
const labels = [...this.issueConfig.labels];
return { ...this.issueConfig.issue, labels };
}
async postComment(body, author) {
this.issueConfig.comments.push({
author: { name: author !== null && author !== void 0 ? author : 'bot' },
body,
id: Math.random(),
timestamp: +new Date(),
});
}
async deleteComment(id) {
this.issueConfig.comments = this.issueConfig.comments.filter((comment) => comment.id !== id);
}
async *getComments(last) {
yield last
? [this.issueConfig.comments[this.issueConfig.comments.length - 1]]
: this.issueConfig.comments;
}
async addLabel(label) {
this.issueConfig.labels.push(label);
}
async removeLabel(labelToDelete) {
this.issueConfig.labels = this.issueConfig.labels.filter((label) => label !== labelToDelete);
}
async closeIssue() {
this.issueConfig.issue.open = false;
}
async lockIssue() {
this.issueConfig.issue.locked = true;
}
async getClosingInfo() {
return this.issueConfig.closingCommit;
}
}
exports.TestbedIssue = TestbedIssue;

View File

@@ -0,0 +1,170 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Comment, GitHub, GitHubIssue, Issue, Query, User } from './api'
type TestbedConfig = {
globalLabels: string[]
configs: Record<string, any>
writers: string[]
releasedCommits: string[]
queryRunner: (query: Query) => AsyncIterableIterator<(TestbedIssueConstructorArgs | TestbedIssue)[]>
}
export type TestbedConstructorArgs = Partial<TestbedConfig>
export class Testbed implements GitHub {
public config: TestbedConfig
constructor(config?: TestbedConstructorArgs) {
this.config = {
globalLabels: config?.globalLabels ?? [],
configs: config?.configs ?? {},
writers: config?.writers ?? [],
releasedCommits: config?.releasedCommits ?? [],
queryRunner:
config?.queryRunner ??
async function* () {
yield []
},
}
}
async *query(query: Query): AsyncIterableIterator<GitHubIssue[]> {
for await (const page of this.config.queryRunner(query)) {
yield page.map((issue) =>
issue instanceof TestbedIssue ? issue : new TestbedIssue(this.config, issue),
)
}
}
async createIssue(_owner: string, _repo: string, _title: string, _body: string): Promise<void> {
// pass...
}
async readConfig(path: string): Promise<any> {
return JSON.parse(JSON.stringify(this.config.configs[path]))
}
async hasWriteAccess(user: User): Promise<boolean> {
return this.config.writers.includes(user.name)
}
async repoHasLabel(label: string): Promise<boolean> {
return this.config.globalLabels.includes(label)
}
async createLabel(label: string, _color: string, _description: string): Promise<void> {
this.config.globalLabels.push(label)
}
async deleteLabel(labelToDelete: string): Promise<void> {
this.config.globalLabels = this.config.globalLabels.filter((label) => label !== labelToDelete)
}
async releaseContainsCommit(_release: string, commit: string): Promise<boolean> {
return this.config.releasedCommits.includes(commit)
}
}
type TestbedIssueConfig = {
issue: Omit<Issue, 'labels'>
comments: Comment[]
labels: string[]
closingCommit: { hash: string | undefined; timestamp: number } | undefined
}
export type TestbedIssueConstructorArgs = Partial<Omit<TestbedIssueConfig, 'issue'>> & {
issue?: Partial<Omit<Issue, 'labels'>>
}
export class TestbedIssue extends Testbed implements GitHubIssue {
public issueConfig: TestbedIssueConfig
constructor(globalConfig?: TestbedConstructorArgs, issueConfig?: TestbedIssueConstructorArgs) {
super(globalConfig)
issueConfig = issueConfig ?? {}
issueConfig.comments = issueConfig?.comments ?? []
issueConfig.labels = issueConfig?.labels ?? []
issueConfig.issue = {
author: { name: 'JacksonKearl' },
body: 'issue body',
locked: false,
numComments: issueConfig?.comments?.length || 0,
number: 1,
open: true,
title: 'issue title',
assignee: undefined,
reactions: {
'+1': 0,
'-1': 0,
confused: 0,
eyes: 0,
heart: 0,
hooray: 0,
laugh: 0,
rocket: 0,
},
closedAt: undefined,
createdAt: +new Date(),
updatedAt: +new Date(),
...issueConfig.issue,
}
this.issueConfig = issueConfig as TestbedIssueConfig
}
async addAssignee(assignee: string): Promise<void> {
this.issueConfig.issue.assignee = assignee
}
async setMilestone(milestoneId: number): Promise<void> {
this.issueConfig.issue.milestoneId = milestoneId
}
async getIssue(): Promise<Issue> {
const labels = [...this.issueConfig.labels]
return { ...this.issueConfig.issue, labels }
}
async postComment(body: string, author?: string): Promise<void> {
this.issueConfig.comments.push({
author: { name: author ?? 'bot' },
body,
id: Math.random(),
timestamp: +new Date(),
})
}
async deleteComment(id: number): Promise<void> {
this.issueConfig.comments = this.issueConfig.comments.filter((comment) => comment.id !== id)
}
async *getComments(last?: boolean): AsyncIterableIterator<Comment[]> {
yield last
? [this.issueConfig.comments[this.issueConfig.comments.length - 1]]
: this.issueConfig.comments
}
async addLabel(label: string): Promise<void> {
this.issueConfig.labels.push(label)
}
async removeLabel(labelToDelete: string): Promise<void> {
this.issueConfig.labels = this.issueConfig.labels.filter((label) => label !== labelToDelete)
}
async closeIssue(): Promise<void> {
this.issueConfig.issue.open = false
}
async lockIssue(): Promise<void> {
this.issueConfig.issue.locked = true
}
async getClosingInfo(): Promise<{ hash: string | undefined; timestamp: number } | undefined> {
return this.issueConfig.closingCommit
}
}

View File

@@ -0,0 +1,12 @@
name: 'PR Labeler'
description: 'Automatically add a Label to a PR'
inputs:
token:
description: GitHub token with issue, comment, and label read/write permissions
default: ${{ github.token }}
label:
description: Github label to add to the PR
required: true
runs:
using: 'node12'
main: 'index.js'

View File

@@ -0,0 +1,22 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const core = require("@actions/core");
const github_1 = require("@actions/github");
const octokit_1 = require("../api/octokit");
const utils_1 = require("../utils/utils");
const token = utils_1.getRequiredInput('token');
const label = utils_1.getRequiredInput('label');
async function main() {
const pr = new octokit_1.OctoKitIssue(token, github_1.context.repo, { number: github_1.context.issue.number });
pr.addLabel(label);
}
main()
.then(() => utils_1.logRateLimit(token))
.catch(async (error) => {
core.setFailed(error.message);
await utils_1.logErrorToIssue(error.message, true, token);
});

View File

@@ -0,0 +1,26 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as core from '@actions/core'
import { context } from '@actions/github'
import { OctoKitIssue } from '../api/octokit'
import { getRequiredInput, logErrorToIssue, logRateLimit } from '../utils/utils'
const token = getRequiredInput('token');
const label = getRequiredInput('label');
async function main() {
const pr = new OctoKitIssue(token, context.repo, { number: context.issue.number });
pr.addLabel(label);
}
main()
.then(() => logRateLimit(token))
.catch(async (error) => {
core.setFailed(error.message)
await logErrorToIssue(error.message, true, token)
})

View File

@@ -0,0 +1,24 @@
{
"name": "github-actions",
"version": "1.0.0",
"description": "GitHub Actions",
"scripts": {
"test": "mocha -r ts-node/register **/*.test.ts",
"build": "tsc -p ./tsconfig.json",
"lint": "eslint -c .eslintrc --fix --ext .ts .",
"watch-typecheck": "tsc --watch"
},
"repository": {
"type": "git",
"url": "git+https://github.com/microsoft/azuredatastudio.git"
},
"keywords": [],
"author": "",
"dependencies": {
"@actions/core": "^1.2.6",
"@actions/github": "^2.1.1",
"axios": "^0.21.4",
"ts-node": "^8.6.2",
"typescript": "^3.8.3"
}
}

View File

@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es2019",
"strict": true,
"module": "commonjs",
"moduleResolution": "node",
"removeComments": false,
"resolveJsonModule": true,
"lib": [
"es2020"
],
},
"include": [
"./**/*.ts"
],
"exclude": [
"node_modules"
]
}

View File

@@ -0,0 +1,72 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const core = require("@actions/core");
const github_1 = require("@actions/github");
const axios_1 = require("axios");
const octokit_1 = require("../api/octokit");
exports.getInput = (name) => core.getInput(name) || undefined;
exports.getRequiredInput = (name) => core.getInput(name, { required: true });
exports.normalizeIssue = (issue) => {
const { body, title } = issue;
const isBug = body.includes('bug_report_template') || /Issue Type:.*Bug.*/.test(body);
const isFeatureRequest = body.includes('feature_request_template') || /Issue Type:.*Feature Request.*/.test(body);
const cleanse = (str) => str
.toLowerCase()
.replace(/<!--.*?-->/gu, '')
.replace(/.* version: .*/gu, '')
.replace(/issue type: .*/gu, '')
.replace(/<details>(.|\s)*?<\/details>/gu, '')
.replace(/vs ?code/gu, '')
.replace(/we have written.*please paste./gu, '')
.replace(/steps to reproduce:/gu, '')
.replace(/does this issue occur when all extensions are disabled.*/gu, '')
.replace(/```(.|\s)*?```/gu, '')
.replace(/!?\[.*?\]\(.*?\)/gu, '')
.replace(/\s+/gu, ' ');
return {
body: cleanse(body),
title: cleanse(title),
issueType: isBug ? 'bug' : isFeatureRequest ? 'feature_request' : 'unknown',
};
};
exports.loadLatestRelease = async (quality) => (await axios_1.default.get(`https://vscode-update.azurewebsites.net/api/update/darwin/${quality}/latest`)).data;
exports.daysAgoToTimestamp = (days) => +new Date(Date.now() - days * 24 * 60 * 60 * 1000);
exports.daysAgoToHumanReadbleDate = (days) => new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '');
exports.logRateLimit = async (token) => {
const usageData = (await new github_1.GitHub(token).rateLimit.get()).data.resources;
['core', 'graphql', 'search'].forEach(async (category) => {
const usage = 1 - usageData[category].remaining / usageData[category].limit;
const message = `Usage at ${usage} for ${category}`;
if (usage > 0) {
console.log(message);
}
if (usage > 0.5) {
await exports.logErrorToIssue(message, false, token);
}
});
};
exports.logErrorToIssue = async (message, ping, token) => {
// Attempt to wait out abuse detection timeout if present
await new Promise((resolve) => setTimeout(resolve, 10000));
const dest = github_1.context.repo.repo === 'vscode-internalbacklog'
? { repo: 'vscode-internalbacklog', issue: 974 }
: { repo: 'vscode', issue: 93814 };
return new octokit_1.OctoKitIssue(token, { owner: 'Microsoft', repo: dest.repo }, { number: dest.issue })
.postComment(`
Workflow: ${github_1.context.workflow}
Error: ${message}
Issue: ${ping ? `${github_1.context.repo.owner}/${github_1.context.repo.repo}#` : ''}${github_1.context.issue.number}
Repo: ${github_1.context.repo.owner}/${github_1.context.repo.repo}
<!-- Context:
${JSON.stringify(github_1.context, null, 2).replace(/<!--/gu, '<@--').replace(/-->/gu, '--@>')}
-->
`);
};

View File

@@ -0,0 +1,95 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as core from '@actions/core'
import { context, GitHub } from '@actions/github'
import axios from 'axios'
import { OctoKitIssue } from '../api/octokit'
import { Issue } from '../api/api'
export const getInput = (name: string) => core.getInput(name) || undefined
export const getRequiredInput = (name: string) => core.getInput(name, { required: true })
export const normalizeIssue = (
issue: Issue,
): { body: string; title: string; issueType: 'bug' | 'feature_request' | 'unknown' } => {
const { body, title } = issue
const isBug = body.includes('bug_report_template') || /Issue Type:.*Bug.*/.test(body)
const isFeatureRequest =
body.includes('feature_request_template') || /Issue Type:.*Feature Request.*/.test(body)
const cleanse = (str: string) =>
str
.toLowerCase()
.replace(/<!--.*?-->/gu, '')
.replace(/.* version: .*/gu, '')
.replace(/issue type: .*/gu, '')
.replace(/<details>(.|\s)*?<\/details>/gu, '')
.replace(/vs ?code/gu, '')
.replace(/we have written.*please paste./gu, '')
.replace(/steps to reproduce:/gu, '')
.replace(/does this issue occur when all extensions are disabled.*/gu, '')
.replace(/```(.|\s)*?```/gu, '')
.replace(/!?\[.*?\]\(.*?\)/gu, '')
.replace(/\s+/gu, ' ')
return {
body: cleanse(body),
title: cleanse(title),
issueType: isBug ? 'bug' : isFeatureRequest ? 'feature_request' : 'unknown',
}
}
export interface Release {
productVersion: string
timestamp: number
version: string
}
export const loadLatestRelease = async (quality: 'stable' | 'insider'): Promise<Release | undefined> =>
(await axios.get(`https://vscode-update.azurewebsites.net/api/update/darwin/${quality}/latest`)).data
export const daysAgoToTimestamp = (days: number): number => +new Date(Date.now() - days * 24 * 60 * 60 * 1000)
export const daysAgoToHumanReadbleDate = (days: number) =>
new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString().replace(/\.\d{3}\w$/, '')
export const logRateLimit = async (token: string) => {
const usageData = (await new GitHub(token).rateLimit.get()).data.resources
;(['core', 'graphql', 'search'] as const).forEach(async (category) => {
const usage = 1 - usageData[category].remaining / usageData[category].limit
const message = `Usage at ${usage} for ${category}`
if (usage > 0) {
console.log(message)
}
if (usage > 0.5) {
await logErrorToIssue(message, false, token)
}
})
}
export const logErrorToIssue = async (message: string, ping: boolean, token: string): Promise<void> => {
// Attempt to wait out abuse detection timeout if present
await new Promise((resolve) => setTimeout(resolve, 10000))
const dest =
context.repo.repo === 'vscode-internalbacklog'
? { repo: 'vscode-internalbacklog', issue: 974 }
: { repo: 'vscode', issue: 93814 }
return new OctoKitIssue(token, { owner: 'Microsoft', repo: dest.repo }, { number: dest.issue })
.postComment(`
Workflow: ${context.workflow}
Error: ${message}
Issue: ${ping ? `${context.repo.owner}/${context.repo.repo}#` : ''}${context.issue.number}
Repo: ${context.repo.owner}/${context.repo.repo}
<!-- Context:
${JSON.stringify(context, null, 2).replace(/<!--/gu, '<@--').replace(/-->/gu, '--@>')}
-->
`)
}

421
build/actions/yarn.lock Normal file
View File

@@ -0,0 +1,421 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@actions/core@^1.2.6":
version "1.2.6"
resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.2.6.tgz#a78d49f41a4def18e88ce47c2cac615d5694bf09"
integrity sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==
"@actions/github@^2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@actions/github/-/github-2.1.1.tgz#bcabedff598196d953f58ba750d5e75549a75142"
integrity sha512-kAgTGUx7yf5KQCndVeHSwCNZuDBvPyxm5xKTswW2lofugeuC1AZX73nUUVDNaysnM9aKFMHv9YCdVJbg7syEyA==
dependencies:
"@actions/http-client" "^1.0.3"
"@octokit/graphql" "^4.3.1"
"@octokit/rest" "^16.43.1"
"@actions/http-client@^1.0.3":
version "1.0.8"
resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-1.0.8.tgz#8bd76e8eca89dc8bcf619aa128eba85f7a39af45"
integrity sha512-G4JjJ6f9Hb3Zvejj+ewLLKLf99ZC+9v+yCxoYf9vSyH+WkzPLB2LuUtRMGNkooMqdugGBFStIKXOuvH1W+EctA==
dependencies:
tunnel "0.0.6"
"@octokit/auth-token@^2.4.0":
version "2.4.0"
resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.0.tgz#b64178975218b99e4dfe948253f0673cbbb59d9f"
integrity sha512-eoOVMjILna7FVQf96iWc3+ZtE/ZT6y8ob8ZzcqKY1ibSQCnu4O/B7pJvzMx5cyZ/RjAff6DAdEb0O0Cjcxidkg==
dependencies:
"@octokit/types" "^2.0.0"
"@octokit/endpoint@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.1.tgz#16d5c0e7a83e3a644d1ddbe8cded6c3d038d31d7"
integrity sha512-pOPHaSz57SFT/m3R5P8MUu4wLPszokn5pXcB/pzavLTQf2jbU+6iayTvzaY6/BiotuRS0qyEUkx3QglT4U958A==
dependencies:
"@octokit/types" "^2.11.1"
is-plain-object "^3.0.0"
universal-user-agent "^5.0.0"
"@octokit/graphql@^4.3.1":
version "4.3.1"
resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.3.1.tgz#9ee840e04ed2906c7d6763807632de84cdecf418"
integrity sha512-hCdTjfvrK+ilU2keAdqNBWOk+gm1kai1ZcdjRfB30oA3/T6n53UVJb7w0L5cR3/rhU91xT3HSqCd+qbvH06yxA==
dependencies:
"@octokit/request" "^5.3.0"
"@octokit/types" "^2.0.0"
universal-user-agent "^4.0.0"
"@octokit/plugin-paginate-rest@^1.1.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz#004170acf8c2be535aba26727867d692f7b488fc"
integrity sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==
dependencies:
"@octokit/types" "^2.0.1"
"@octokit/plugin-request-log@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz#eef87a431300f6148c39a7f75f8cfeb218b2547e"
integrity sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw==
"@octokit/plugin-rest-endpoint-methods@2.4.0":
version "2.4.0"
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz#3288ecf5481f68c494dd0602fc15407a59faf61e"
integrity sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==
dependencies:
"@octokit/types" "^2.0.1"
deprecation "^2.3.1"
"@octokit/request-error@^1.0.2":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.1.tgz#ede0714c773f32347576c25649dc013ae6b31801"
integrity sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==
dependencies:
"@octokit/types" "^2.0.0"
deprecation "^2.0.0"
once "^1.4.0"
"@octokit/request-error@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.0.tgz#94ca7293373654400fbb2995f377f9473e00834b"
integrity sha512-rtYicB4Absc60rUv74Rjpzek84UbVHGHJRu4fNVlZ1mCcyUPPuzFfG9Rn6sjHrd95DEsmjSt1Axlc699ZlbDkw==
dependencies:
"@octokit/types" "^2.0.0"
deprecation "^2.0.0"
once "^1.4.0"
"@octokit/request@^5.2.0", "@octokit/request@^5.3.0":
version "5.4.2"
resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.2.tgz#74f8e5bbd39dc738a1b127629791f8ad1b3193ee"
integrity sha512-zKdnGuQ2TQ2vFk9VU8awFT4+EYf92Z/v3OlzRaSh4RIP0H6cvW1BFPXq4XYvNez+TPQjqN+0uSkCYnMFFhcFrw==
dependencies:
"@octokit/endpoint" "^6.0.1"
"@octokit/request-error" "^2.0.0"
"@octokit/types" "^2.11.1"
deprecation "^2.0.0"
is-plain-object "^3.0.0"
node-fetch "^2.3.0"
once "^1.4.0"
universal-user-agent "^5.0.0"
"@octokit/rest@^16.43.1":
version "16.43.1"
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.43.1.tgz#3b11e7d1b1ac2bbeeb23b08a17df0b20947eda6b"
integrity sha512-gfFKwRT/wFxq5qlNjnW2dh+qh74XgTQ2B179UX5K1HYCluioWj8Ndbgqw2PVqa1NnVJkGHp2ovMpVn/DImlmkw==
dependencies:
"@octokit/auth-token" "^2.4.0"
"@octokit/plugin-paginate-rest" "^1.1.1"
"@octokit/plugin-request-log" "^1.0.0"
"@octokit/plugin-rest-endpoint-methods" "2.4.0"
"@octokit/request" "^5.2.0"
"@octokit/request-error" "^1.0.2"
atob-lite "^2.0.0"
before-after-hook "^2.0.0"
btoa-lite "^1.0.0"
deprecation "^2.0.0"
lodash.get "^4.4.2"
lodash.set "^4.3.2"
lodash.uniq "^4.5.0"
octokit-pagination-methods "^1.1.0"
once "^1.4.0"
universal-user-agent "^4.0.0"
"@octokit/types@^2.0.0", "@octokit/types@^2.0.1", "@octokit/types@^2.11.1":
version "2.12.1"
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.12.1.tgz#4a26b4a85ec121043d3b0745b5798f9d8fd968ca"
integrity sha512-LRLR1tjbcCfAmUElvTmMvLEzstpx6Xt/aQVTg2xvd+kHA2Ekp1eWl5t+gU7bcwjXHYEAzh4hH4WH+kS3vh+wRw==
dependencies:
"@types/node" ">= 8"
"@types/node@>= 8":
version "13.13.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.2.tgz#160d82623610db590a64e8ca81784e11117e5a54"
integrity sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==
arg@^4.1.0:
version "4.1.3"
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
atob-lite@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/atob-lite/-/atob-lite-2.0.0.tgz#0fef5ad46f1bd7a8502c65727f0367d5ee43d696"
integrity sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=
axios@^0.21.4:
version "0.21.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
dependencies:
follow-redirects "^1.14.0"
before-after-hook@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635"
integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==
btoa-lite@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337"
integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc=
buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
cross-spawn@^6.0.0:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
dependencies:
nice-try "^1.0.4"
path-key "^2.0.1"
semver "^5.5.0"
shebang-command "^1.2.0"
which "^1.2.9"
deprecation@^2.0.0, deprecation@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
diff@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
dependencies:
once "^1.4.0"
execa@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
dependencies:
cross-spawn "^6.0.0"
get-stream "^4.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"
follow-redirects@^1.14.0:
version "1.14.8"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
get-stream@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
dependencies:
pump "^3.0.0"
is-plain-object@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928"
integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==
dependencies:
isobject "^4.0.0"
is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
isobject@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0"
integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==
lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
lodash.set@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=
lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
macos-release@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f"
integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA==
make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
nice-try@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
node-fetch@^2.3.0:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
dependencies:
path-key "^2.0.0"
octokit-pagination-methods@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4"
integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==
once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies:
wrappy "1"
os-name@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801"
integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==
dependencies:
macos-release "^2.2.0"
windows-release "^3.1.0"
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
pump@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
semver@^5.5.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
dependencies:
shebang-regex "^1.0.0"
shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
signal-exit@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
source-map-support@^0.5.17:
version "0.5.19"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"
source-map@^0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
ts-node@^8.6.2:
version "8.9.0"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.9.0.tgz#d7bf7272dcbecd3a2aa18bd0b96c7d2f270c15d4"
integrity sha512-rwkXfOs9zmoHrV8xE++dmNd6ZIS+nmHHCxcV53ekGJrxFLMbp+pizpPS07ARvhwneCIECPppOwbZHvw9sQtU4w==
dependencies:
arg "^4.1.0"
diff "^4.0.1"
make-error "^1.1.1"
source-map-support "^0.5.17"
yn "3.1.1"
tunnel@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
typescript@^3.8.3:
version "3.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
universal-user-agent@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.1.tgz#fd8d6cb773a679a709e967ef8288a31fcc03e557"
integrity sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==
dependencies:
os-name "^3.1.0"
universal-user-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-5.0.0.tgz#a3182aa758069bf0e79952570ca757de3579c1d9"
integrity sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q==
dependencies:
os-name "^3.1.0"
which@^1.2.9:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
dependencies:
isexe "^2.0.0"
windows-release@^3.1.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.0.tgz#dce167e9f8be733f21c849ebd4d03fe66b29b9f0"
integrity sha512-2HetyTg1Y+R+rUgrKeUEhAG/ZuOmTrI1NBb3ZyAGQMYmOJjBBPe4MTodghRkmLJZHwkuPi02anbeGP+Zf401LQ==
dependencies:
execa "^1.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
yn@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==

View File

@@ -106,7 +106,7 @@ steps:
- script: |
set -e
./scripts/test.sh --build --tfs "Unit Tests" --coverage
./scripts/test.sh --build --tfs "Unit Tests" # Disable code coverage since it's currently broken --coverage
displayName: Run unit tests
condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))
@@ -128,24 +128,14 @@ steps:
yarn gulp compile-extensions
displayName: Compile Extensions
# Per https://developercommunity.visualstudio.com/t/variablesexpressions-dont-work-with-continueonerro/1187733 we can't use variables
# in continueOnError directly so instead make two copies of the task and only run one or the other based on the SMOKE_FAIL_ON_ERROR value
- script: |
set -e
APP_ROOT=$(agent.builddirectory)/azuredatastudio-darwin-x64
APP_NAME="`ls $APP_ROOT | head -n 1`"
yarn smoketest --build "$APP_ROOT/$APP_NAME" --screenshots "$(build.artifactstagingdirectory)/smokeshots" --log "$(build.artifactstagingdirectory)/logs/darwin/smoke.log" --extensionsDir "$(build.sourcesdirectory)/extensions"
displayName: Run smoke tests (Electron) (Continue on Error)
displayName: Run smoke tests (Electron)
continueOnError: true
condition: and(succeeded(), and(eq(variables['RUN_TESTS'], 'true'), ne(variables['SMOKE_FAIL_ON_ERROR'], 'true')))
- script: |
set -e
APP_ROOT=$(agent.builddirectory)/azuredatastudio-darwin-x64
APP_NAME="`ls $APP_ROOT | head -n 1`"
yarn smoketest --build "$APP_ROOT/$APP_NAME" --screenshots "$(build.artifactstagingdirectory)/smokeshots" --log "$(build.artifactstagingdirectory)/logs/darwin/smoke.log" --extensionsDir "$(build.sourcesdirectory)/extensions"
displayName: Run smoke tests (Electron) (Fail on Error)
condition: and(succeeded(), and(eq(variables['RUN_TESTS'], 'true'), eq(variables['SMOKE_FAIL_ON_ERROR'], 'true')))
condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))
# - script: |
# set -e

View File

@@ -1,5 +1,5 @@
#Download base image ubuntu 22.04
FROM mcr.microsoft.com/mirror/docker/library/ubuntu:22.04
#Download base image ubuntu 21.04
FROM ubuntu:21.04
ENV TZ=America/Los_Angeles
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

View File

@@ -1,5 +1,5 @@
#Download base image ubuntu 18.04
FROM mcr.microsoft.com/mirror/docker/library/ubuntu:18.04
FROM ubuntu:18.04
#Adding apt repos for g++-4.9
RUN echo "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main" >> /etc/apt/sources.list

View File

@@ -119,7 +119,7 @@ steps:
- script: |
set -e
DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" --coverage
DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" # Disable code coverage since it's currently broken --coverage
displayName: Run unit tests (Electron)
condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))

View File

@@ -6,9 +6,6 @@ trigger:
pr: none
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool@0
inputs:
@@ -55,13 +52,13 @@ steps:
git reset --hard upstream/master
git push --force
# Update and format the typings file
# Update the type
cd ..
node build/azure-pipelines/publish-types/update-types.js
cd DefinitelyTyped
TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`)
# Create and push the branch
cd DefinitelyTyped
git diff --color | cat
git add -A
git status

View File

@@ -47,7 +47,7 @@ jobs:
steps:
- template: linux/sql-product-build-linux.yml
parameters:
extensionsToUnitTest: ["admin-tool-ext-win", "agent", "azcli", "azurecore", "cms", "dacpac", "data-workspace", "import", "machine-learning", "notebook", "resource-deployment", "schema-compare", "sql-bindings", "sql-database-projects"]
extensionsToUnitTest: ["admin-tool-ext-win", "agent", "azcli", "azurecore", "cms", "dacpac", "data-workspace", "import", "machine-learning", "notebook", "resource-deployment", "schema-compare", "sql-database-projects"]
timeoutInMinutes: 90
- job: Windows
@@ -60,17 +60,16 @@ jobs:
- template: win32/sql-product-build-win32.yml
timeoutInMinutes: 90
# disable due to invalid machine pool (karlb 3/9/2022)
# - job: Windows_Test
# condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32'], 'true'))
# pool:
# name: mssqltools
# dependsOn:
# - Linux
# - Windows
# steps:
# - template: win32/sql-product-test-win32.yml
# timeoutInMinutes: 90
- job: Windows_Test
condition: and(succeeded(), eq(variables['VSCODE_BUILD_WIN32'], 'true'))
pool:
name: mssqltools
dependsOn:
- Linux
- Windows
steps:
- template: win32/sql-product-test-win32.yml
timeoutInMinutes: 90
- job: Release
condition: and(succeeded(), or(eq(variables['VSCODE_RELEASE'], 'true'), and(eq(variables['VSCODE_QUALITY'], 'insider'), eq(variables['Build.Reason'], 'Schedule'))))
@@ -80,8 +79,7 @@ jobs:
- macOS
- Linux
- Windows
# disable due to invalid machine pool (karlb 3/9/2022)
# - Windows_Test
- Windows_Test
- macOS_Signing
steps:
- template: sql-release.yml

View File

@@ -77,11 +77,9 @@ steps:
node build/azure-pipelines/mixin
displayName: Mix in quality
# Run these separately to avoid OOM errors on pipeline machines
- script: |
set -e
yarn npm-run-all -lp core-ci extensions-ci
yarn npm-run-all -lp hygiene eslint valid-layers-check
yarn npm-run-all -lp core-ci extensions-ci hygiene eslint valid-layers-check
displayName: Compile & Hygiene
- script: |
@@ -95,7 +93,6 @@ steps:
AZURE_STORAGE_ACCESS_KEY="$(sourcemap-storage-key)" \
node build/azure-pipelines/upload-sourcemaps
displayName: Upload sourcemaps
condition: and(succeeded(), ne(variables['VSCODE_PUBLISH'], 'false'))
- script: |
set -e

View File

@@ -1,5 +1,5 @@
#Download base image ubuntu 22.04
FROM mcr.microsoft.com/mirror/docker/library/ubuntu:22.04
#Download base image ubuntu 21.04
FROM ubuntu:21.04
ENV TZ=America/Los_Angeles
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

View File

@@ -104,26 +104,14 @@ steps:
yarn gulp compile-extensions
displayName: Compile Extensions
# disable smoke tests (karlb 3/2/2022)
# # Per https://developercommunity.visualstudio.com/t/variablesexpressions-dont-work-with-continueonerro/1187733 we can't use variables
# # in continueOnError directly so instead make two copies of the task and only run one or the other based on the SMOKE_FAIL_ON_ERROR value
# - script: |
# set -e
# node ./node_modules/playwright/install.js
# APP_ROOT=$(Agent.BuildDirectory)/vscode-reh-web-linux-x64
# xvfb-run yarn smoketest --build "$(Agent.BuildDirectory)/vscode-reh-web-linux-x64" --web --headless --screenshots "$(Build.ArtifactStagingDirectory)/smokeshots" --log "$(Build.ArtifactStagingDirectory)/logs/web/smoke.log"
# displayName: Run smoke tests (Browser) (Continue on Error)
# continueOnError: true
# condition: and(succeeded(), and(eq(variables['RUN_TESTS'], 'true'), ne(variables['SMOKE_FAIL_ON_ERROR'], 'true')))
# disable smoke tests (karlb 3/2/2022)
# - script: |
# set -e
# node ./node_modules/playwright/install.js
# APP_ROOT=$(Agent.BuildDirectory)/vscode-reh-web-linux-x64
# xvfb-run yarn smoketest --build "$(Agent.BuildDirectory)/vscode-reh-web-linux-x64" --web --headless --screenshots "$(Build.ArtifactStagingDirectory)/smokeshots" --log "$(Build.ArtifactStagingDirectory)/logs/web/smoke.log"
# displayName: Run smoke tests (Browser) (Fail on Error)
# condition: and(succeeded(), and(eq(variables['RUN_TESTS'], 'true'), eq(variables['SMOKE_FAIL_ON_ERROR'], 'true')))
- script: |
set -e
node ./node_modules/playwright/install.js
APP_ROOT=$(Agent.BuildDirectory)/vscode-reh-web-linux-x64
xvfb-run yarn smoketest --build "$(Agent.BuildDirectory)/vscode-reh-web-linux-x64" --web --headless --screenshots "$(Build.ArtifactStagingDirectory)/smokeshots" --log "$(Build.ArtifactStagingDirectory)/logs/web/smoke.log"
displayName: Run smoke tests (Browser)
continueOnError: true
condition: and(succeeded(), eq(variables['RUN_TESTS'], 'true'))
# - script: |
# set -e

View File

@@ -122,8 +122,7 @@ module.exports.indentationFilter = [
'!extensions/simple-browser/media/*.js',
'!resources/xlf/LocProject.json',
'!build/**/*',
'!test/coverage/**',
'!extensions/**/coverage/**'
'!test/coverage/**'
];
module.exports.copyrightFilter = [
@@ -183,7 +182,6 @@ module.exports.copyrightFilter = [
'!src/sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin.ts',
'!src/sql/base/browser/ui/table/plugins/cellSelectionModel.plugin.ts',
'!src/sql/base/browser/ui/table/plugins/autoSizeColumns.plugin.ts',
'!src/sql/base/browser/ui/table/plugins/rowMoveManager.plugin.ts',
'!src/sql/workbench/services/notebook/browser/outputs/sanitizer.ts',
'!src/sql/workbench/contrib/notebook/browser/outputs/renderers.ts',
'!src/sql/workbench/services/notebook/browser/outputs/tableRenderers.ts',

View File

@@ -240,7 +240,7 @@ exports.compileExtensionsBuildTask = compileExtensionsBuildTask;
//Get every extension in 'extensions' to create XLF files.
const exportCompilations = glob.sync('**/package.json', {
cwd: extensionsPath,
ignore: ['**/out/**', '**/node_modules/**', '**/sqltoolsservice/**', 'package.json']
ignore: ['**/out/**', '**/node_modules/**', 'package.json']
});
//Run the localization packaging task on all extensions in ADS.

View File

@@ -129,19 +129,16 @@ gulp.task('package-external-extensions', task.series(
const packageManifestPath = path.join(packageDir, 'package.json');
const json = require('gulp-json-editor');
const packageJsonStream = gulp.src(packageManifestPath) // Create stream for the original package.json
.pipe(json(data => {
// And now use gulp-json-editor to modify the contents
.pipe(json(data => { // And now use gulp-json-editor to modify the contents
const updateData = JSON.parse(fs.readFileSync(vscodeManifestFullPath)); // Read in the set of values to replace from package.vscode.json
Object.keys(updateData).forEach(key => {
data[key] = updateData[key];
});
if(data.contributes?.menus){
// Remove ADS-only menus. This is a subset of the menus listed in https://github.com/microsoft/azuredatastudio/blob/main/src/vs/workbench/api/common/menusExtensionPoint.ts
// More can be added to the list as needed.
['objectExplorer/item/context', 'dataExplorer/context', 'dashboard/toolbar'].forEach(menu => {
delete data.contributes.menus[menu];
});
}
// Remove ADS-only menus. This is a subset of the menus listed in https://github.com/microsoft/azuredatastudio/blob/main/src/vs/workbench/api/common/menusExtensionPoint.ts
// More can be added to the list as needed.
['objectExplorer/item/context', 'dataExplorer/context', 'dashboard/toolbar'].forEach(menu => {
delete data.contributes.menus[menu];
});
return data;
}, { beautify: false }))
.pipe(gulp.dest(packageDir));

View File

@@ -135,7 +135,6 @@ const extensionsFilter = filter([
'**/schema-compare.xlf',
'**/server-report.xlf',
'**/sql-assessment.xlf',
'**/sql-bindings.xlf',
'**/sql-database-projects.xlf',
'**/sql-migration.xlf',
'**/xml-language-features.xlf'

View File

@@ -37,17 +37,9 @@ function createCompile(src, build, emitError) {
const sourcemaps = require('gulp-sourcemaps');
const projectPath = path.join(__dirname, '../../', src, 'tsconfig.json');
const overrideOptions = Object.assign(Object.assign({}, getTypeScriptCompilerOptions(src)), { inlineSources: Boolean(build) });
if (!build && !process.env['SQL_NO_INLINE_SOURCEMAP']) {
if (!build) {
overrideOptions.inlineSourceMap = true;
}
else if (!build) {
console.warn('********************************************************************************************');
console.warn('* Inlining of source maps is DISABLED, which will prevent debugging from working properly, *');
console.warn('* but is required to generate code coverage reports. *');
console.warn('* To re-enable inlining of source maps clear the SQL_NO_INLINE_SOURCEMAP environment var *');
console.warn('* and re-run the build/watch task *');
console.warn('********************************************************************************************');
}
const compilation = tsb.create(projectPath, overrideOptions, false, err => reporter(err));
function pipeline(token) {
const bom = require('gulp-bom');

View File

@@ -44,15 +44,8 @@ function createCompile(src: string, build: boolean, emitError?: boolean) {
const projectPath = path.join(__dirname, '../../', src, 'tsconfig.json');
const overrideOptions = { ...getTypeScriptCompilerOptions(src), inlineSources: Boolean(build) };
if (!build && !process.env['SQL_NO_INLINE_SOURCEMAP']) {
if (!build) {
overrideOptions.inlineSourceMap = true;
} else if (!build) {
console.warn('********************************************************************************************');
console.warn('* Inlining of source maps is DISABLED, which will prevent debugging from working properly, *');
console.warn('* but is required to generate code coverage reports. *');
console.warn('* To re-enable inlining of source maps clear the SQL_NO_INLINE_SOURCEMAP environment var *');
console.warn('* and re-run the build/watch task *');
console.warn('********************************************************************************************');
}
const compilation = tsb.create(projectPath, overrideOptions, false, err => reporter(err));
@@ -94,6 +87,7 @@ function createCompile(src: string, build: boolean, emitError?: boolean) {
export function compileTask(src: string, out: string, build: boolean): () => NodeJS.ReadWriteStream {
return function () {
if (os.totalmem() < 4_000_000_000) {
throw new Error('compilation requires 4GB of RAM');
}

View File

@@ -231,7 +231,6 @@ const externalExtensions = [
'schema-compare',
'server-report',
'sql-assessment',
'sql-bindings',
'sql-database-projects',
'sql-migration'
];

View File

@@ -267,7 +267,6 @@ const externalExtensions = [
'schema-compare',
'server-report',
'sql-assessment',
'sql-bindings',
'sql-database-projects',
'sql-migration'
];

View File

@@ -18,13 +18,6 @@ const File = require("vinyl");
const rimraf = require("rimraf");
const gulp = require("gulp");
const vfs = require("vinyl-fs");
/**
* If you need to compile this file for any changes, please run: yarn tsc -p ./build/tsconfig.json
*/
//List of extensions that we changed from vscode, so we can exclude them from having "Microsoft." appended in front.
const alteredVSCodeExtensions = [
'git'
];
const root = path.dirname(path.dirname(__dirname));
// Modified packageLocalExtensionsStream from extensions.ts, but for langpacks.
function packageLangpacksStream() {
@@ -141,13 +134,10 @@ function modifyI18nPackFiles(existingTranslationFolder, resultingTranslationPath
for (let extension in extensionsPacks) {
const translatedExtFile = i18n.createI18nFile(`extensions/${extension}`, extensionsPacks[extension]);
this.queue(translatedExtFile);
// exclude altered vscode extensions from having a new path even if we provide a new I18n file.
if (alteredVSCodeExtensions.indexOf(extension) === -1) {
//handle edge case for 'Microsoft.sqlservernotebook' where extension name is the same as extension ID.
//(Other extensions need to have publisher appended in front as their ID.)
let adsExtensionId = (extension === 'Microsoft.sqlservernotebook') ? extension : 'Microsoft.' + extension;
resultingTranslationPaths.push({ id: adsExtensionId, resourceName: `extensions/${extension}.i18n.json` });
}
//handle edge case for 'Microsoft.sqlservernotebook' where extension name is the same as extension ID.
//(Other extensions need to have publisher appended in front as their ID.)
const adsExtensionId = (extension === 'Microsoft.sqlservernotebook') ? extension : 'Microsoft.' + extension;
resultingTranslationPaths.push({ id: adsExtensionId, resourceName: `extensions/${extension}.i18n.json` });
}
this.queue(null);
})
@@ -172,6 +162,7 @@ const VSCODEExtensions = [
"bat",
"configuration-editing",
"docker",
"extension-editing",
"git-ui",
"git",
"github-authentication",

View File

@@ -17,15 +17,6 @@ import * as rimraf from 'rimraf';
import * as gulp from 'gulp';
import * as vfs from 'vinyl-fs';
/**
* If you need to compile this file for any changes, please run: yarn tsc -p ./build/tsconfig.json
*/
//List of extensions that we changed from vscode, so we can exclude them from having "Microsoft." appended in front.
const alteredVSCodeExtensions = [
'git'
]
const root = path.dirname(path.dirname(__dirname));
// Modified packageLocalExtensionsStream from extensions.ts, but for langpacks.
@@ -77,7 +68,7 @@ function updateMainI18nFile(existingTranslationFilePath: string, originalFilePat
// Delete any SQL strings that are no longer part of ADS in current langpack.
for (let contentKey of Object.keys(objectContents)) {
if (contentKey.startsWith('sql') && messages.contents[contentKey] === undefined) {
if(contentKey.startsWith('sql') && messages.contents[contentKey] === undefined){
delete objectContents[`${contentKey}`]
}
}
@@ -157,14 +148,10 @@ export function modifyI18nPackFiles(existingTranslationFolder: string, resulting
const translatedExtFile = i18n.createI18nFile(`extensions/${extension}`, extensionsPacks[extension]);
this.queue(translatedExtFile);
// exclude altered vscode extensions from having a new path even if we provide a new I18n file.
if (alteredVSCodeExtensions.indexOf(extension) === -1) {
//handle edge case for 'Microsoft.sqlservernotebook' where extension name is the same as extension ID.
//(Other extensions need to have publisher appended in front as their ID.)
let adsExtensionId = (extension === 'Microsoft.sqlservernotebook') ? extension : 'Microsoft.' + extension;
resultingTranslationPaths.push({ id: adsExtensionId, resourceName: `extensions/${extension}.i18n.json` });
}
//handle edge case for 'Microsoft.sqlservernotebook' where extension name is the same as extension ID.
//(Other extensions need to have publisher appended in front as their ID.)
const adsExtensionId = (extension === 'Microsoft.sqlservernotebook') ? extension : 'Microsoft.' + extension;
resultingTranslationPaths.push({ id: adsExtensionId, resourceName: `extensions/${extension}.i18n.json` });
}
this.queue(null);
})
@@ -412,7 +399,7 @@ export function renameVscodeLangpacks(): Promise<void> {
//Copy files to vscode langpack, then remove the ADS langpack, and finally rename the vscode langpack to match the ADS one.
globMDArray.forEach(element => {
fs.copyFileSync(element, path.join(locVSCODEFolder, path.parse(element).base));
fs.copyFileSync(element, path.join(locVSCODEFolder,path.parse(element).base));
});
rimraf.sync(locADSFolder);
fs.renameSync(locVSCODEFolder, locADSFolder);

View File

@@ -48,7 +48,6 @@ exports.dirs = [
'extensions/server-report',
'extensions/simple-browser',
'extensions/sql-assessment',
'extensions/sql-bindings',
'extensions/sql-database-projects',
'extensions/sql-migration',
'extensions/vscode-test-resolver',

View File

@@ -60,14 +60,14 @@
"mime": "^1.4.1",
"mkdirp": "^1.0.4",
"p-limit": "^3.1.0",
"plist": "^3.0.5",
"plist": "^3.0.1",
"rollup": "^1.20.3",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"source-map": "0.6.1",
"tmp": "^0.2.1",
"typescript": "^4.5.0-dev.20210817",
"vsce": "2.8.0",
"vsce": "1.48.0",
"vscode-universal-bundler": "^0.0.2"
},
"scripts": {

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,6 @@
{
"rules": {
"no-cond-assign": 2,
"jsdoc/check-param-names": "error",
"@typescript-eslint/explicit-function-return-type": ["error"],
"@typescript-eslint/await-thenable": ["error"]
"jsdoc/check-param-names": "error"
}
}

View File

@@ -108,17 +108,17 @@
},
"dependencies": {
"@microsoft/ads-extension-telemetry": "^1.1.3",
"@microsoft/ads-service-downloader": "0.2.4",
"@microsoft/ads-service-downloader": "0.2.3",
"vscode-nls": "^4.1.2"
},
"devDependencies": {
"@types/mocha": "^7.0.2",
"@types/mocha": "^5.2.5",
"@types/node": "^12.11.7",
"mocha": "^7.1.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"should": "^13.2.3",
"@microsoft/vscodetestcover": "^1.2.1"
"@microsoft/vscodetestcover": "^1.2.0"
},
"__metadata": {
"id": "41",

View File

@@ -82,7 +82,6 @@ async function handleLaunchSsmsMinGswDialogCommand(connectionContext?: azdata.Ob
if (!connectionContext) {
TelemetryReporter.sendErrorEvent(TelemetryViews.SsmsMinGsw, 'NoConnectionContext');
void vscode.window.showErrorMessage(localize('adminToolExtWin.noConnectionContextForGsw', "No ConnectionContext provided for handleLaunchSsmsMinPropertiesDialogCommand"));
return;
}
return launchSsmsDialog(
@@ -102,7 +101,7 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
return;
}
let oeNode: azdata.objectexplorer.ObjectExplorerNode | undefined;
let oeNode: azdata.objectexplorer.ObjectExplorerNode;
// Server node is a Connection node and so doesn't have the NodeInfo
if (connectionContext.isConnectionNode) {
oeNode = undefined;
@@ -154,11 +153,11 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
// Process has exited so remove from map of running processes
runningProcesses.delete(proc.pid);
const err = stderr.toString();
if ((execException?.code !== 0) || err !== '') {
if ((execException && execException.code !== 0) || err !== '') {
TelemetryReporter.sendErrorEvent(
TelemetryViews.SsmsMinDialog,
'LaunchSsmsDialogError',
execException ? execException?.code?.toString() : '',
execException ? execException.code.toString() : '',
getTelemetryErrorType(err));
}
@@ -171,7 +170,7 @@ async function launchSsmsDialog(action: string, connectionContext: azdata.Object
// If we're not using AAD the tool prompts for a password on stdin
if (params.useAad !== true) {
proc.stdin!.end(password ? password : '');
proc.stdin.end(password ? password : '');
}
// Save the process into our map so we can make sure to stop them if we exit before shutting down

View File

@@ -8,6 +8,6 @@ import * as vscode from 'vscode';
describe('Extension activate test', () => {
it('Extension should activate correctly', async function (): Promise<void> {
await vscode.extensions.getExtension('Microsoft.admin-tool-ext-win')!.activate();
await vscode.extensions.getExtension('Microsoft.admin-tool-ext-win').activate();
});
});

View File

@@ -11,7 +11,7 @@ import * as vscode from 'vscode';
*/
export class ExtHostObjectExplorerNodeStub implements azdata.objectexplorer.ObjectExplorerNode {
// Stub properties
private parent: azdata.objectexplorer.ObjectExplorerNode | undefined;
private parent: azdata.objectexplorer.ObjectExplorerNode;
// Base properties
public connectionId: string;
@@ -24,10 +24,10 @@ export class ExtHostObjectExplorerNodeStub implements azdata.objectexplorer.Obje
public metadata: azdata.ObjectMetadata;
public errorMessage: string;
constructor(nodeName: string, nodeSchema: string, nodeType: string, parent?: azdata.objectexplorer.ObjectExplorerNode) {
constructor(nodeName: string, nodeSchema: string, nodeType: string, parent: azdata.objectexplorer.ObjectExplorerNode) {
this.parent = parent;
this.nodeType = nodeType;
this.metadata = { metadataType: azdata.MetadataType.Table, metadataTypeName: 'MyMetadataTypeName', name: nodeName, schema: nodeSchema, urn: 'urn', parentName: undefined, parentTypeName: undefined };
this.metadata = { metadataType: undefined, metadataTypeName: undefined, name: nodeName, schema: nodeSchema, urn: undefined, parentName: undefined, parentTypeName: undefined };
}
isExpanded(): Thenable<boolean> {
@@ -38,7 +38,7 @@ export class ExtHostObjectExplorerNodeStub implements azdata.objectexplorer.Obje
throw new Error('Method not implemented');
}
setSelected(selected: boolean, clearOtherSelections: boolean): Thenable<void> {
setSelected(selected: boolean, clearOtherSelections: boolean = undefined): Thenable<void> {
throw new Error('Method not implemented');
}

View File

@@ -77,14 +77,14 @@ describe('buildUrn Method Tests', () => {
it('Urn should be correct with Server and only Databases folder', async function (): Promise<void> {
const leafNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('MyServer', 'MySchema', 'Server', undefined)
.createChild('Databases', '', 'Folder');
new ExtHostObjectExplorerNodeStub('MyServer', undefined, 'Server', undefined)
.createChild('Databases', undefined, 'Folder');
should(await buildUrn(leafNode)).equal('Server');
});
it('Urn should be correct with Server and Database node', async function (): Promise<void> {
const leafNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('Databases', 'MySchema', 'Folder', undefined)
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined)
.createChild(dbName, dbSchema, 'Database');
should(await buildUrn(leafNode)).equal(
`Server/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']`);
@@ -92,9 +92,9 @@ describe('buildUrn Method Tests', () => {
it('Urn should be correct with Multiple levels of Nodes', async function (): Promise<void> {
const rootNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('Databases', 'MySchema', 'Folder', undefined)
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined)
.createChild(dbName, dbSchema, 'Database')
.createChild('Tables', 'MySchema', 'Folder')
.createChild('Tables', undefined, 'Folder')
.createChild(tableName, tableSchema, 'Table');
should(await buildUrn(rootNode)).equal(
`Server/Database[@Name='${escapedDbName}' and @Schema='${escapedDbSchema}']/Table[@Name='${escapedTableName}' and @Schema='${escapedTableSchema}']`);
@@ -102,10 +102,10 @@ describe('buildUrn Method Tests', () => {
it('Urn should be correct with Multiple levels of Nodes without schemas', async function (): Promise<void> {
const rootNode: ExtHostObjectExplorerNodeStub =
new ExtHostObjectExplorerNodeStub('Databases', '', 'Folder', undefined)
.createChild(dbName, '', 'Database')
.createChild('Tables', '', 'Folder')
.createChild(tableName, '', 'Table');
new ExtHostObjectExplorerNodeStub('Databases', undefined, 'Folder', undefined)
.createChild(dbName, undefined, 'Database')
.createChild('Tables', undefined, 'Folder')
.createChild(tableName, undefined, 'Table');
should(await buildUrn(rootNode)).equal(
`Server/Database[@Name='${escapedDbName}']/Table[@Name='${escapedTableName}']`);
});

View File

@@ -126,7 +126,7 @@ export const nodeTypeToUrnNameMapping: { [oeNodeType: string]: SmoMapping } = {
* Builds the URN string for a given ObjectExplorerNode in the form understood by SsmsMin
* @param node The node to get the URN of
*/
export async function buildUrn(node?: azdata.objectexplorer.ObjectExplorerNode): Promise<string> {
export async function buildUrn(node: azdata.objectexplorer.ObjectExplorerNode): Promise<string> {
let urnNodes: string[] = [];
while (node) {
// Server is special since it's a connection node - always add it as the root

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +0,0 @@
{
"parserOptions": {
"project": "./extensions/agent/tsconfig.json"
},
"rules": {
// Disabled until the issues can be fixed
"@typescript-eslint/explicit-function-return-type": ["off"]
}
}

View File

@@ -19,12 +19,12 @@
"type": "git",
"url": "https://github.com/Microsoft/azuredatastudio.git"
},
"capabilities": {
"capabilities": {
"virtualWorkspaces": false,
"untrustedWorkspaces": {
"supported": true
}
},
},
"extensionDependencies": [
"Microsoft.mssql"
],
@@ -89,14 +89,14 @@
"vscode-nls": "^4.1.2"
},
"devDependencies": {
"@types/mocha": "^7.0.2",
"@types/mocha": "^5.2.5",
"@types/node": "^12.11.7",
"mocha": "^7.1.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"should": "^13.2.1",
"typemoq": "^2.1.0",
"@microsoft/vscodetestcover": "^1.2.1"
"@microsoft/vscodetestcover": "^1.2.0"
},
"__metadata": {
"id": "10",

View File

@@ -40,7 +40,7 @@ export abstract class AgentDialog<T extends IAgentDialogData> {
let event = dialogName ? dialogName : null;
this.dialog = azdata.window.createModelViewDialog(this.title, event);
this.model.initialize();
await this.model.initialize();
await this.initializeDialog(this.dialog);

View File

@@ -10,8 +10,7 @@
"experimentalDecorators": true,
"moduleResolution": "node",
"strict": false,
"noUnusedParameters": false,
"strictNullChecks": false
"noUnusedParameters": false
},
"exclude": [
"node_modules"

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
{
"parserOptions": {
"project": "./extensions/arc/tsconfig.json"
},
"rules": {
// Disabled until the issues can be fixed
"@typescript-eslint/explicit-function-return-type": ["off"]
}
}

View File

@@ -1,16 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18">
<defs>
<linearGradient id="a8a99b72-4483-4aed-9c09-505d227627b7" x1="9" y1="778.831" x2="9" y2="790.831" gradientTransform="matrix(1, 0, 0, -1, 0, 791.516)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#0078d4" />
<stop offset="0.82" stop-color="#5ea0ef" />
</linearGradient>
<linearGradient id="ab11b5a0-213c-48d8-9a74-d2a9e98a4058" x1="9" y1="774.201" x2="9" y2="778.831" gradientTransform="matrix(1, 0, 0, -1, 0, 791.516)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#ccc" />
<stop offset="1" stop-color="#707070" />
</linearGradient>
</defs>
<rect y="0.685" width="18" height="12" rx="0.6" fill="url(#a8a99b72-4483-4aed-9c09-505d227627b7)" />
<path d="M12.61,16.315c-1.78-.28-1.85-1.56-1.85-3.63H7.23c0,2.07-.06,3.35-1.84,3.63a1,1,0,0,0-.89,1h9A1,1,0,0,0,12.61,16.315Z" fill="url(#ab11b5a0-213c-48d8-9a74-d2a9e98a4058)" />
<path d="M4.939,6.782l0,2.588a.147.147,0,0,0,.147.147.149.149,0,0,0,.086-.028l.712-.512A4.174,4.174,0,0,0,7.506,10.3a4.084,4.084,0,0,0,1.674.361,3.909,3.909,0,0,0,.684-.06,3.993,3.993,0,0,0,1.123-.369,3.848,3.848,0,0,0,.952-.677,3.917,3.917,0,0,0,1.108-1.983.224.224,0,0,0-.153-.261.216.216,0,0,0-.066-.01.223.223,0,0,0-.214.158v0A3.372,3.372,0,0,1,11.52,9.079a3.186,3.186,0,0,1-1.762.712c-.093.009-.186.013-.278.013a3.161,3.161,0,0,1-1.531-.4,3.106,3.106,0,0,1-1.135-1.1l.99-.712a.147.147,0,0,0-.048-.261L5.123,6.641a.128.128,0,0,0-.038,0A.146.146,0,0,0,4.939,6.782Z" fill="#fff" opacity="0.8" />
<path d="M13.065,6.628V4.041a.148.148,0,0,0-.148-.147.146.146,0,0,0-.085.028l-.67.484a4.193,4.193,0,0,0-1.7-1.357,4.114,4.114,0,0,0-1.618-.335A3.929,3.929,0,0,0,4.962,5.857a.2.2,0,0,0,.136.227.225.225,0,0,0,.058.008.2.2,0,0,0,.188-.139v0a3.4,3.4,0,0,1,1.1-1.632A3.213,3.213,0,0,1,8.2,3.607c.094-.009.188-.014.281-.014a3.13,3.13,0,0,1,1.517.4,3.052,3.052,0,0,1,1.154,1.143l-.957.69a.147.147,0,0,0,.049.261l2.634.687a.122.122,0,0,0,.037.005A.147.147,0,0,0,13.065,6.628Z" fill="#fff" />
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -185,24 +185,21 @@
"print (f'Creating Azure Arc Data Controller: {arc_data_controller_name} using configuration {arc_cluster_context}')\n",
"os.environ[\"AZDATA_USERNAME\"] = arc_admin_username\n",
"os.environ[\"AZDATA_PASSWORD\"] = arc_admin_password\n",
"os.environ[\"LOG_WORKSPACE_ID\"] = log_analytics_workspace_id\n",
"os.environ[\"LOG_SHARED_KEY\"] = log_analytics_primary_key\n",
"\n",
"# If connection mode is indirect\n",
"namespace = f' --k8s-namespace {arc_data_controller_namespace}' if is_indirect else ''\n",
"use_k8s = ' --use-k8s' if is_indirect else ''\n",
"\n",
"# If connection mode is direct\n",
"custom_location = f' --custom-location {arc_data_controller_custom_location}' if not is_indirect else ''\n",
"cluster_name = f' --cluster-name {arc_cluster_context}' if not is_indirect else ''\n",
"\n",
"auto_upload_metrics_value = 'true' if arc_data_controller_auto_upload_metrics == 'true' else 'false'\n",
"auto_upload_logs_value = 'true' if arc_data_controller_auto_upload_logs == 'true' else 'false'\n",
"\n",
"auto_upload_metrics = f' --auto-upload-metrics {auto_upload_metrics_value}' if not is_indirect else ''\n",
"auto_upload_logs = f' --auto-upload-logs {auto_upload_logs_value}' if not is_indirect else ''\n",
"\n",
"if os.name == 'nt':\n",
" print(f'If you don\\'t see output produced by az, you can run the following command in a terminal window to check the deployment status:\\n\\t {os.environ[\"AZDATA_NB_VAR_KUBECTL\"]} get pods -n {arc_data_controller_namespace}')\n",
"run_command(f'az arcdata dc create --connectivity-mode {arc_data_controller_connectivity_mode} --name {arc_data_controller_name}{namespace} --subscription {arc_subscription} --resource-group {arc_resource_group} --location {arc_data_controller_location} --storage-class {arc_data_controller_storage_class} --profile-name {arc_profile} --infrastructure {arc_infrastructure}{custom_location}{cluster_name}{auto_upload_metrics}{auto_upload_logs}{use_k8s}')\n",
"run_command(f'az arcdata dc create --connectivity-mode {arc_data_controller_connectivity_mode} --name {arc_data_controller_name}{namespace} --subscription {arc_subscription} --resource-group {arc_resource_group} --location {arc_data_controller_location} --storage-class {arc_data_controller_storage_class} --profile-name {arc_profile} --infrastructure {arc_infrastructure}{custom_location}{auto_upload_metrics}{auto_upload_logs}{use_k8s}')\n",
"print(f'Azure Arc Data Controller: {arc_data_controller_name} created.') "
]
},

View File

@@ -2,7 +2,7 @@
"name": "arc",
"displayName": "%arc.displayName%",
"description": "%arc.description%",
"version": "1.3.0",
"version": "1.0.0",
"publisher": "Microsoft",
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
"icon": "images/extension.png",
@@ -20,12 +20,12 @@
"Microsoft.azcli",
"Microsoft.resource-deployment"
],
"capabilities": {
"capabilities": {
"virtualWorkspaces": false,
"untrustedWorkspaces": {
"supported": true
}
},
},
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/azuredatastudio.git"
@@ -360,49 +360,6 @@
"target": "AZDATA_NB_VAR_ARC_DATA_CONTROLLER_CONNECTIVITY_MODE",
"value": "Direct"
}
},
{
"type": "options",
"label": "%arc.data.controller.log.analytics.workspace.names%",
"variableName": "AZDATA_NB_VAR_LOG_ANALYTICS_WORKSPACE_NAMES",
"required": true,
"options": {
"source": {
"providerId": "arc.logAnalyticsWorkspaceNames"
},
"optionsType": "dropdown"
},
"enabled": {
"target": "AZDATA_NB_VAR_ARC_DATA_CONTROLLER_AUTO_UPLOAD_LOGS",
"value": "true"
}
},
{
"type": "text",
"label": "%arc.data.controller.log.analytics.workspace.id%",
"required": true,
"isEvaluated": true,
"variableName": "AZDATA_NB_VAR_LOG_ANALYTICS_WORKSPACE_ID",
"valueProvider": {
"providerId": "workspace-name-to-id",
"triggerFields": [
"AZDATA_NB_VAR_LOG_ANALYTICS_WORKSPACE_NAMES"
]
},
"enabled": {
"target": "AZDATA_NB_VAR_ARC_DATA_CONTROLLER_AUTO_UPLOAD_LOGS",
"value": "true"
}
},
{
"type": "text",
"label": "%arc.data.controller.log.analytics.primary.key%",
"required": true,
"variableName": "AZDATA_NB_VAR_LOG_ANALYTICS_PRIMARY_KEY",
"enabled": {
"target": "AZDATA_NB_VAR_ARC_DATA_CONTROLLER_AUTO_UPLOAD_LOGS",
"value": "true"
}
}
]
},
@@ -1134,7 +1091,8 @@
"defaultValue": "2",
"optionsType": "radio"
},
"dynamicOptions": {
"dynamicOptions":
{
"target": "AZDATA_NB_VAR_SQL_SERVICE_TIER",
"alternates": [
{
@@ -1386,7 +1344,7 @@
}
]
}
]
]
}
]
},
@@ -1432,9 +1390,6 @@
"resourceDeploymentOptionsSources": [
{
"id": "arc.controllers"
},
{
"id": "arc.logAnalyticsWorkspaceNames"
}
]
},
@@ -1444,19 +1399,19 @@
"yamljs": "^0.3.0"
},
"devDependencies": {
"@types/mocha": "^7.0.2",
"@types/mocha": "^5.2.5",
"@types/node": "^12.11.7",
"@types/sinon": "^9.0.4",
"@types/uuid": "^8.3.0",
"@types/yamljs": "^0.2.31",
"@microsoft/azdata-test": "^1.5.1",
"mocha": "^7.1.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"should": "^13.2.3",
"sinon": "^9.0.2",
"typemoq": "2.1.0",
"@microsoft/vscodetestcover": "^1.2.1"
"@microsoft/vscodetestcover": "^1.2.0"
},
"__metadata": {
"id": "68",

View File

@@ -14,7 +14,7 @@
"arc.openDashboard": "Manage",
"resource.type.azure.arc.display.name": "Azure Arc data controller",
"resource.type.azure.arc.description": "Creates an Azure Arc data controller. Ensure that you have run az login before starting this wizard.",
"resource.type.azure.arc.description": "Creates an Azure Arc data controller",
"arc.data.controller.new.wizard.title": "Create Azure Arc data controller",
"arc.data.controller.cluster.environment.title": "What is your target existing Kubernetes cluster environment?",
"arc.data.controller.select.cluster.title": "Select from existing Kubernetes clusters",
@@ -43,9 +43,6 @@
"arc.data.controller.auto.upload.metrics.description": "Enable the automatic upload of metrics. Direct mode only.",
"arc.data.controller.auto.upload.logs": "Auto-upload Logs",
"arc.data.controller.auto.upload.logs.description": "Enable the automatic upload of logs. Direct mode only.",
"arc.data.controller.log.analytics.workspace.names": "Log Analytics workspace",
"arc.data.controller.log.analytics.workspace.id": "Log Analytics workspace ID",
"arc.data.controller.log.analytics.primary.key": "Log Analytics primary key",
"arc.data.controller.metrics.and.logs.dashboard.credentials.title": "Metrics and Logs Dashboard Credentials",
"arc.data.controller.metrics.and.logs.dashboard.credentials.username": "Username",
@@ -105,7 +102,7 @@
"arc.sql.high.availability": "High availability",
"arc.sql.high.availability.description": "Enable additional replicas for high availabilty. The compute and storage configuration selected below will be applied to all replicas.",
"arc.sql.service.tier.general.purpose": "General Purpose (Up to 24 vCores and 128 Gi of RAM, standard high availability)",
"arc.sql.service.tier.business.critical": "Business Critical (Unlimited vCores and RAM, advanced high availability)",
"arc.sql.service.tier.business.critical": "[PREVIEW] Business Critical (Unlimited vCores and RAM, advanced high availability)",
"arc.sql.one.replica": "1 replica",
"arc.sql.two.replicas": "2 replicas",
"arc.sql.three.replicas": "3 replicas",

View File

@@ -12,19 +12,24 @@ export const SqlManagedInstanceGeneralPurpose = {
licenseIncludedPricePerCore: 153,
maxMemorySize: 128,
maxVCores: 24,
replicaOptions: [
{
text: loc.replicaOne,
value: 1,
}
],
defaultReplicaValue: 1
};
const SqlManagedInstanceBusinessCritical = {
tierName: loc.businessCriticalLabel,
basePricePerCore: 160,
licenseIncludedPricePerCore: 434,
// Set to real values when BC is ready
basePricePerCore: 0,
licenseIncludedPricePerCore: 0,
replicaOptions: [
{
text: loc.replicaTwo,
@@ -35,6 +40,7 @@ const SqlManagedInstanceBusinessCritical = {
value: 3,
}
],
defaultReplicaValue: 3
};

View File

@@ -1,28 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { InputValueType } from 'resource-deployment';
import * as azExt from 'az-ext';
import * as vscode from 'vscode';
import { errorListingLogAnalyticsWorkspaces } from '../localizedConstants';
export const licenseTypeVarName = 'AZDATA_NB_VAR_LOG_ANALYTICS_WORKSPACE_NAMES';
// Gets the Log Analytics workspace id from the workspace name.
export async function getWorkspaceIdFromName(triggerFields: { [key: string]: InputValueType }): Promise<string | undefined> {
try {
const _azApi = <azExt.IExtension>vscode.extensions.getExtension(azExt.extension.name)?.exports;
const workspaces = await _azApi.az.monitor.logAnalytics.workspace.list();
const targetWorkspace = workspaces.stdout.find(workspace => workspace.name === triggerFields[licenseTypeVarName]);
if (targetWorkspace) {
return targetWorkspace.customerId;
} else {
return undefined;
}
} catch (e) {
vscode.window.showErrorMessage(errorListingLogAnalyticsWorkspaces(e));
throw e;
}
}

View File

@@ -35,7 +35,6 @@ export class IconPathHelper {
public static properties: IconPath;
public static networking: IconPath;
public static pitr: IconPath;
public static upgrade: IconPath;
public static refresh: IconPath;
public static reset: IconPath;
public static support: IconPath;
@@ -161,10 +160,6 @@ export class IconPathHelper {
light: context.asAbsolutePath('images/pitr.svg'),
dark: context.asAbsolutePath('images/pitr.svg'),
};
IconPathHelper.upgrade = {
light: context.asAbsolutePath('images/upgrade.svg'),
dark: context.asAbsolutePath('images/upgrade.svg'),
};
}
}
@@ -183,7 +178,6 @@ export const enum ConnectionMode {
export namespace cssStyles {
export const text = { 'user-select': 'text', 'cursor': 'text' };
export const code = { 'user-select': 'text', 'cursor': 'text', 'font-style': 'italic' };
export const title = { ...text, 'font-weight': 'bold', 'font-size': '14px' };
export const tableHeader = { ...text, 'text-align': 'left', 'border': 'none' };
export const tableRow = { ...text, 'border-top': 'solid 1px #ccc', 'border-bottom': 'solid 1px #ccc', 'border-left': 'none', 'border-right': 'none' };

View File

@@ -15,8 +15,6 @@ import { AzureArcTreeDataProvider } from './ui/tree/azureArcTreeDataProvider';
import { ControllerTreeNode } from './ui/tree/controllerTreeNode';
import { TreeNode } from './ui/tree/treeNode';
import * as pricing from './common/pricingUtils';
import * as workspace from './common/workspaceUtils';
import { LogAnalyticsWorkspaceOptionsSourceProvider } from './providers/logAnalyticsWorkspaceOptionsSourceProvider';
export async function activate(context: vscode.ExtensionContext): Promise<arc.IExtension> {
IconPathHelper.setExtensionContext(context);
@@ -63,15 +61,6 @@ export async function activate(context: vscode.ExtensionContext): Promise<arc.IE
// register option sources
const rdApi = <rd.IExtension>vscode.extensions.getExtension(rd.extension.name)?.exports;
context.subscriptions.push(rdApi.registerOptionsSourceProvider(new ArcControllersOptionsSourceProvider(treeDataProvider)));
context.subscriptions.push(rdApi.registerOptionsSourceProvider(new LogAnalyticsWorkspaceOptionsSourceProvider()));
// Register valueprovider for getting the Log Analytics workspace id from the workspace name.
context.subscriptions.push(rdApi.registerValueProvider({
id: 'workspace-name-to-id',
getValue: async (triggerFields: { [key: string]: rd.InputValueType }) => {
return workspace.getWorkspaceIdFromName(triggerFields);
}
}));
// Register valueprovider for getting the calculated cost per VCore.
context.subscriptions.push(rdApi.registerValueProvider({

View File

@@ -127,7 +127,7 @@ export const indirect = localize('arc.indirect', "Indirect");
export const loading = localize('arc.loading', "Loading...");
export const refreshToEnterCredentials = localize('arc.refreshToEnterCredentials', "Refresh node to enter credentials");
export const noInstancesAvailable = localize('arc.noInstancesAvailable', "No instances available");
export const connectToServer = localize('arc.connectToServer', "Connect to Server");
export const connectToServer = localize('arc.connecToServer', "Connect to Server");
export const connectToController = localize('arc.connectToController', "Connect to Existing Controller");
export function connectToMSSql(name: string): string { return localize('arc.connectToMSSql', "Connect to SQL managed instance - Azure Arc ({0})", name); }
export function connectToPGSql(name: string): string { return localize('arc.connectToPGSql', "Connect to PostgreSQL Hyperscale - Azure Arc ({0})", name); }
@@ -334,29 +334,3 @@ export const userCancelledError = localize('arc.userCancelledError', "User cance
export const clusterContextConfigNoLongerValid = (configFile: string, clusterContext: string, error: any) => localize('clusterContextConfigNoLongerValid', "The cluster context information specified by config file: {0} and cluster context: {1} is no longer valid. Error is:\n\t{2}\n Do you want to update this information?", configFile, clusterContext, getErrorMessage(error));
export const invalidConfigPath = localize('arc.invalidConfigPath', "Invalid config path");
export const loadingClusterContextsError = (error: any): string => localize('arc.loadingClusterContextsError', "Error loading cluster contexts. {0}", getErrorMessage(error));
// Upgrade
export const upgradeManagement = localize('arc.upgradeManagement', "Upgrade Management");
export const availableUpgrades = localize('arc.availableUpgrades', "Available Upgrades");
export const availableUpgradesDescription = localize('arc.availableUpgradesDescription', "Available upgrades for this resource are listed below. You can apply upgrades by clicking the upgrade button.");
export const versionLog = localize('arc.versionLog', "Learn more about each release here.");
export const onlyNextImmediateVersion = localize('arc.onlyNextImmediateVersion', "Currently, only upgrading to the next immediate version is supported.");
export const onlyNextImmediateVersionMiaa = localize('arc.onlyNextImmediateVersionMiaa', "The version of a SQL Managed Instance can not be newer than the version of its data controller. Currently, only upgrading to the next immediate version is supported.");
export const version = localize('arc.version', "Version");
export const releaseDate = localize('arc.releaseDate', "Release Date");
export const releaseNotes = localize('arc.releaseNotes', "Release Notes");
export const upgrade = localize('arc.upgrade', "Upgrade");
export const upgradeDataController = localize('arc.upgradeDataController', "Upgrade Data Controller");
export const upgradeMiaa = localize('arc.upgradeMiaa', "Upgrade SQL Managed Instance");
export const areYouSure = localize('arc.areYouSure', "Are you sure you want to apply the selected upgrade?");
export const upgradeDialogController = localize('arc.upgradeDialogController', "During a data controller upgrade, portions of the data control plane such as Custom Resource Definitions (CRDs) and containers may be upgraded. An upgrade of the data controller will not cause downtime for the data services (SQL Managed Instance or PostgreSQL server).");
export const upgradeDialogMiaa = localize('arc.upgradeDialogMiaa', "During a SQL managed instance upgrade, portions of the data control plane such as Custom Resource Definitions (CRDs) and containers may be upgraded. An upgrade of the SQL managed instance will not cause downtime for the data services (SQL Managed Instance or PostgreSQL server).");
export const monitorUpgrade = localize('arc.monitorUpgrade', "You can check the status of the upgrade by running the following command:");
export function errorListingLogAnalyticsWorkspaces(error: any): string { return localize('arc.errorListingLogAnalyticsWorkspaces', "Error listing Log Analytics workspaces {0}", getErrorMessage(error, true)); }
export const noUpgrades = localize('arc.noUpgrades', 'The current version is the latest version. No upgrades available.');
export function upgradingController(param: any): string { return localize('arc.upgradingController', "Data controller is being upgraded. You can check the status of the upgrade by running the following command: 'kubectl get datacontrollers -A'", param); }
export function upgradingMiaa(param: any): string { return localize('arc.upgradingMiaa', "SQL managed instance is being upgraded. You can check the status of the upgrade by running the following command: 'kubectl get sqlmi -A'", param); }
export const currentVersion = localize('arc.currentVersion', "Current version");
export const showMiaaError = localize('arc.showMiaaError', "Error showing details of SQL managed instance.");
export const miaaVersionError = localize('arc.miaaVersionError', "Error getting SQL managed instance version number.");
export const errorGettingConnectionMode = localize('arc.errorGettingConnectionMode', "Error getting data controller connection mode.");

View File

@@ -6,7 +6,6 @@
import { ControllerInfo, ResourceType } from 'arc';
import * as azExt from 'az-ext';
import * as vscode from 'vscode';
import { ConnectionMode } from '../constants';
import * as loc from '../localizedConstants';
import { AzureArcTreeDataProvider } from '../ui/tree/azureArcTreeDataProvider';
@@ -67,17 +66,8 @@ export class ControllerModel {
await this.refresh(false, this.info.namespace);
}
}
public async refresh(showErrors: boolean = true, namespace: string): Promise<void> {
await this.refreshController(showErrors, namespace);
if (this._controllerConfig?.spec.settings.azure.connectionMode === ConnectionMode.direct) {
await this.refreshDirectMode(this._controllerConfig?.spec.settings.azure.resourceGroup, namespace);
} else {
await this.refreshIndirectMode(namespace);
}
}
public async refreshController(showErrors: boolean = true, namespace: string): Promise<void> {
const newRegistrations: Registration[] = [];
await Promise.all([
this._azApi.az.arcdata.dc.config.show(namespace, this.azAdditionalEnvVars).then(result => {
this._controllerConfig = result.stdout;
@@ -106,68 +96,35 @@ export class ControllerModel {
}
this._onEndpointsUpdated.fire(this._endpoints);
throw err;
}),
Promise.all([
this._azApi.az.postgres.arcserver.list(namespace, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.postgresInstances
};
}));
}),
this._azApi.az.sql.miarc.list(namespace, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.sqlManagedInstances
};
}));
})
]).then(() => {
this._registrations = newRegistrations;
this.registrationsLastUpdated = new Date();
this._onRegistrationsUpdated.fire(this._registrations);
})
]);
}
public async refreshDirectMode(resourceGroup: string, namespace: string): Promise<void> {
const newRegistrations: Registration[] = [];
await Promise.all([
this._azApi.az.postgres.arcserver.list(namespace, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.postgresInstances
};
}));
}),
this._azApi.az.sql.miarc.list({ resourceGroup: resourceGroup, namespace: undefined }, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.sqlManagedInstances
};
}));
})
]).then(() => {
this._registrations = newRegistrations;
this.registrationsLastUpdated = new Date();
this._onRegistrationsUpdated.fire(this._registrations);
});
}
public async refreshIndirectMode(namespace: string): Promise<void> {
const newRegistrations: Registration[] = [];
await Promise.all([
this._azApi.az.postgres.arcserver.list(namespace, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.postgresInstances
};
}));
}),
this._azApi.az.sql.miarc.list({ resourceGroup: undefined, namespace: namespace }, this.azAdditionalEnvVars).then(result => {
newRegistrations.push(...result.stdout.map(r => {
return {
instanceName: r.name,
state: r.state,
instanceType: ResourceType.sqlManagedInstances
};
}));
})
]).then(() => {
this._registrations = newRegistrations;
this.registrationsLastUpdated = new Date();
this._onRegistrationsUpdated.fire(this._registrations);
});
}
public get endpoints(): azExt.DcEndpointListResult[] {
return this._endpoints;
}

View File

@@ -15,7 +15,6 @@ import { ConnectToMiaaSqlDialog } from '../ui/dialogs/connectMiaaDialog';
import { AzureArcTreeDataProvider } from '../ui/tree/azureArcTreeDataProvider';
import { ControllerModel, Registration } from './controllerModel';
import { ResourceModel } from './resourceModel';
import { ConnectionMode } from '../constants';
export type DatabaseModel = { name: string, status: string, earliestBackup: string, lastBackup: string };
export type RPModel = { recoveryPointObjective: string, retentionDays: string };
@@ -30,7 +29,6 @@ export type PITRModel = {
latestPitr: string,
destDbName: string
};
export type UpgradeModel = {};
export const systemDbs = ['master', 'msdb', 'tempdb', 'model'];
export class MiaaModel extends ResourceModel {
@@ -99,26 +97,7 @@ export class MiaaModel extends ResourceModel {
this._refreshPromise = new Deferred();
try {
try {
let result;
if (this.controllerModel.info.connectionMode === ConnectionMode.direct) {
result = await this._azApi.az.sql.miarc.show(
this.info.name,
{
resourceGroup: this.controllerModel.info.resourceGroup,
namespace: undefined
},
this.controllerModel.azAdditionalEnvVars
);
} else {
result = await this._azApi.az.sql.miarc.show(
this.info.name,
{
resourceGroup: undefined,
namespace: this.controllerModel.info.namespace
},
this.controllerModel.azAdditionalEnvVars
);
}
const result = await this._azApi.az.sql.miarc.show(this.info.name, this.controllerModel.info.namespace, this.controllerModel.azAdditionalEnvVars);
this._config = result.stdout;
this.configLastUpdated = new Date();
this.rpSettings.retentionDays = this._config?.spec?.backup?.retentionPeriodInDays?.toString() ?? '';
@@ -187,7 +166,7 @@ export class MiaaModel extends ResourceModel {
if (!result.connected) {
throw new Error(result.errorMessage);
}
this._activeConnectionId = result.connectionId!;
this._activeConnectionId = result.connectionId;
}
const provider = azdata.dataprotocol.getProvider<azdata.MetadataProvider>(this._connectionProfile!.providerName, azdata.DataProviderType.MetadataProvider);

View File

@@ -148,7 +148,7 @@ export class PostgresModel extends ResourceModel {
if (!result.connected) {
throw new Error(result.errorMessage);
}
this._activeConnectionId = result.connectionId!;
this._activeConnectionId = result.connectionId;
}
// TODO Need to make separate calls for worker nodes and coordinator node

View File

@@ -1,31 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azExt from 'az-ext';
import * as rd from 'resource-deployment';
import * as vscode from 'vscode';
import { errorListingLogAnalyticsWorkspaces } from '../localizedConstants';
/**
* Class that provides options sources for Log Analytics workspace names
*/
export class LogAnalyticsWorkspaceOptionsSourceProvider implements rd.IOptionsSourceProvider {
readonly id = 'arc.logAnalyticsWorkspaceNames';
private readonly _azApi: azExt.IExtension;
constructor() {
this._azApi = <azExt.IExtension>vscode.extensions.getExtension(azExt.extension.name)?.exports;
}
public async getOptions(): Promise<string[]> {
try {
const workspacesListResult = await this._azApi.az.monitor.logAnalytics.workspace.list();
return workspacesListResult.stdout.map(workspace => workspace.name);
} catch (err) {
vscode.window.showErrorMessage(errorListingLogAnalyticsWorkspaces(err));
throw err;
}
}
}

View File

@@ -52,6 +52,9 @@ describe('radioOptionsGroup', function (): void {
const label = radioOptionsGroup.items[0] as azdata.TextComponent;
should(label.value).not.be.undefined();
label.value!.should.deepEqual(loc.loadingClusterContextsError(loadingError));
should(label.CSSStyles).not.be.undefined();
should(label.CSSStyles!.color).not.be.undefined();
label.CSSStyles!.color.should.equal('Red');
});
describe('getters and setters', async () => {

View File

@@ -67,7 +67,7 @@ export class RadioOptionsGroup {
this.component().loadingCompletedText = this._loadingCompleteMessage;
}
catch (e) {
const errorLabel = this._modelBuilder.text().withProps({ value: loc.loadingClusterContextsError(e), textType: azdata.TextType.Error }).component();
const errorLabel = this._modelBuilder.text().withProps({ value: loc.loadingClusterContextsError(e), CSSStyles: { 'color': 'Red' } }).component();
this._divContainer.addItem(errorLabel);
this.component().loadingCompletedText = this._loadingCompleteErrorMessage(e);
}

View File

@@ -8,7 +8,6 @@ import { Dashboard } from '../../components/dashboard';
import { ControllerModel } from '../../../models/controllerModel';
import { ControllerDashboardOverviewPage } from './controllerDashboardOverviewPage';
import * as loc from '../../../localizedConstants';
import { ControllerUpgradesPage } from './controllerUpgrades';
export class ControllerDashboard extends Dashboard {
@@ -24,10 +23,8 @@ export class ControllerDashboard extends Dashboard {
protected async registerTabs(modelView: azdata.ModelView): Promise<(azdata.DashboardTab | azdata.DashboardTabGroup)[]> {
const overviewPage = new ControllerDashboardOverviewPage(modelView, this.dashboard, this._controllerModel);
const upgradesPage = new ControllerUpgradesPage(modelView, this.dashboard, this._controllerModel);
return [
overviewPage.tab,
upgradesPage.tab
overviewPage.tab
];
}

View File

@@ -32,7 +32,6 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
subscriptionId: '-',
connectionMode: '-',
instanceNamespace: '-',
status: '-'
};
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel) {
@@ -220,7 +219,6 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
this.controllerProperties.subscriptionId = config?.spec.settings.azure.subscription || this.controllerProperties.subscriptionId;
this.controllerProperties.connectionMode = getConnectionModeDisplayText(config?.spec.settings.azure.connectionMode) || this.controllerProperties.connectionMode;
this.controllerProperties.instanceNamespace = config?.metadata.namespace || this.controllerProperties.instanceNamespace;
this.controllerProperties.status = config?.status.state || this.controllerProperties.status;
this.refreshDisplayedProperties();
let registrations: (string | azdata.ImageComponent | azdata.HyperlinkComponent)[][] = this._controllerModel.registrations
@@ -287,10 +285,6 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
{
displayName: loc.namespace,
value: this.controllerProperties.instanceNamespace
},
{
displayName: loc.status,
value: this.controllerProperties.status
}
];

View File

@@ -1,268 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as azExt from 'az-ext';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles, ConnectionMode } from '../../../constants';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel } from '../../../models/controllerModel';
import { UpgradeController } from '../../dialogs/upgradeController';
export class ControllerUpgradesPage extends DashboardPage {
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel) {
super(modelView, dashboard);
this._azApi = vscode.extensions.getExtension(azExt.extension.name)?.exports;
}
private _upgradesContainer!: azdata.DivContainer;
private _upgradesTableLoading!: azdata.LoadingComponent;
private _upgradesTable!: azdata.DeclarativeTableComponent;
private _upgradesMessage!: azdata.TextComponent;
private readonly _azApi: azExt.IExtension;
public get title(): string {
return loc.upgradeManagement;
}
public get id(): string {
return 'upgrades';
}
public get icon(): { dark: string, light: string } {
return IconPathHelper.upgrade;
}
protected async refresh(): Promise<void> {
await Promise.resolve(this._controllerModel.refresh(false, this._controllerModel.info.namespace));
this.handleTableUpdated();
}
public get container(): azdata.Component {
const root = this.modelView.modelBuilder.flexContainer()
.withLayout({ flexFlow: 'column' })
.withProps({ CSSStyles: { 'margin': '18px' } })
.component();
const content = this.modelView.modelBuilder.divContainer().component();
this._upgradesContainer = this.modelView.modelBuilder.divContainer().component();
root.addItem(content, { CSSStyles: { 'margin': '5px' } });
// Upgrades title and description
const availableUpgradesTitle = this.modelView.modelBuilder.text().withProps({
value: loc.availableUpgrades,
CSSStyles: { ...cssStyles.title },
}).component();
content.addItem(availableUpgradesTitle);
const infoAvailableUpgrades = this.modelView.modelBuilder.text().withProps({
value: loc.availableUpgradesDescription,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
}).component();
const upgradesVersionLogLink = this.modelView.modelBuilder.hyperlink().withProps({
label: loc.versionLog,
url: 'https://docs.microsoft.com/azure/azure-arc/data/version-log'
}).component();
const upgradesInfoAndLink = this.modelView.modelBuilder.flexContainer()
.withLayout({ flexWrap: 'wrap' })
.withItems([
infoAvailableUpgrades,
upgradesVersionLogLink
], { CSSStyles: { 'margin-right': '5px' } }).component();
content.addItem(upgradesInfoAndLink, { CSSStyles: { 'min-height': '30px' } });
const infoOnlyNextImmediateVersion = this.modelView.modelBuilder.text().withProps({
value: loc.onlyNextImmediateVersion,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px', 'max-width': 'auto' }
}).component();
content.addItem(infoOnlyNextImmediateVersion, { CSSStyles: { 'min-height': '30px' } });
// Create loaded components
this._upgradesTableLoading = this.modelView.modelBuilder.loadingComponent().component();
this._upgradesTable = this.modelView.modelBuilder.declarativeTable().withProps({
width: '100%',
columns: [
{
displayName: loc.version,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '30%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
},
{
displayName: loc.releaseDate,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '30%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
},
{
displayName: loc.upgrade,
valueType: azdata.DeclarativeDataType.component,
isReadOnly: true,
width: '10%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow,
}
],
dataValues: []
}).component();
this._upgradesMessage = this.modelView.modelBuilder.text()
.withProps({ CSSStyles: { 'text-align': 'center' } })
.component();
this.handleTableUpdated();
this._upgradesTableLoading.component = this._upgradesTable;
root.addItem(this._upgradesContainer);
root.addItem(this._upgradesMessage);
this.initialized = true;
this._upgradesTableLoading.loading = false;
this._upgradesContainer.addItem(this._upgradesTableLoading, { CSSStyles: { 'margin-bottom': '20px' } });
return root;
}
public get toolbarContainer(): azdata.ToolbarContainer {
// Refresh
const refreshButton = this.modelView.modelBuilder.button().withProps({
label: loc.refresh,
iconPath: IconPathHelper.refresh
}).component();
this.disposables.push(
refreshButton.onDidClick(async () => {
refreshButton.enabled = false;
try {
await this.refresh();
} finally {
refreshButton.enabled = true;
}
}));
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems(
[
{ component: refreshButton, toolbarSeparatorAfter: true },
]
).component();
}
private formatTableData(result: azExt.AzOutput<azExt.DcListUpgradesResult>): (string | azdata.ButtonComponent)[][] {
let formattedValues: (string | azdata.ButtonComponent)[][] = [];
const versions = result.stdout.versions;
const dates = result.stdout.dates;
const currentVersion = result.stdout.currentVersion;
const nextVersion = this.getNextVersion(versions, currentVersion);
// Iterate through all data controller versions from latest to oldest and stop when the loop reaches the current version.
// Only makes table entries for the current version and newer. The upgrade button will only be enabled for the very next
// version due to Azure CLI constraints.
for (let i = 0; i < versions.length; i++) {
if (versions[i] === currentVersion) {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.currentVersion, false, '')]);
break;
} else if (versions[i] === nextVersion) {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.upgrade, true, nextVersion)]);
} else {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.upgrade, false, '')]);
}
}
return formattedValues;
}
private async handleTableUpdated(): Promise<void> {
const result = await this._azApi.az.arcdata.dc.listUpgrades(this._controllerModel.info.namespace);
let tableDisplay = this.formatTableData(result);
let tableValues = tableDisplay.map(d => {
return d.map((value: any): azdata.DeclarativeTableCellValue => {
return { value: value };
});
});
this._upgradesTable.setDataValues(tableValues);
this._upgradesTableLoading.loading = false;
this._upgradesContainer.addItem(this._upgradesTableLoading, { CSSStyles: { 'margin-bottom': '20px' } });
}
// Given the list of available versions and the current version, if the current version is not the newest,
// then return the next version available. List of versions is ordered newest to oldest.
// If current version is the newest, then return undefined.
private getNextVersion(versions: string[], currentVersion: string): string | undefined {
let index = versions.indexOf(currentVersion);
// The version at index 0 will be the newest
if (index > 0) {
return versions[index - 1];
} else {
return undefined;
}
}
//Create restore button for every database entry in the database table
private createUpgradeButton(label: string, enabled: boolean, nextVersion: string): azdata.ButtonComponent | string {
let upgradeButton = this.modelView.modelBuilder.button().withProps({
label: label,
enabled: enabled
}).component();
this.disposables.push(
upgradeButton.onDidClick(async () => {
const upgradeDialog = new UpgradeController(this._controllerModel);
upgradeDialog.showDialog(loc.upgradeDataController);
let dialogClosed = await upgradeDialog.waitForClose();
if (dialogClosed) {
try {
upgradeButton.enabled = false;
vscode.window.showInformationMessage(loc.upgradingController('kubectl get datacontrollers -A\' should not be localized.'));
await vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: loc.updatingInstance(this._controllerModel.info.name),
cancellable: true
},
async (_progress, _token): Promise<void> => {
if (nextVersion !== '') {
if (this._controllerModel.info.connectionMode === ConnectionMode.direct) {
await this._azApi.az.arcdata.dc.upgrade(
nextVersion,
this._controllerModel.info.name,
this._controllerModel.info.resourceGroup,
undefined, // Indirect mode argument - namespace
);
} else {
await this._azApi.az.arcdata.dc.upgrade(
nextVersion,
this._controllerModel.info.name,
undefined, // Direct mode argument - resourceGroup
this._controllerModel.info.namespace,
);
}
} else {
vscode.window.showInformationMessage(loc.noUpgrades);
}
try {
await this._controllerModel.refresh(false, this._controllerModel.info.namespace);
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
}
}
);
} catch (error) {
console.log(error);
}
}
}));
return upgradeButton;
}
}

View File

@@ -12,7 +12,6 @@ import { MiaaConnectionStringsPage } from './miaaConnectionStringsPage';
import { MiaaModel } from '../../../models/miaaModel';
import { MiaaComputeAndStoragePage } from './miaaComputeAndStoragePage';
import { MiaaBackupsPage } from './miaaBackupsPage';
import { MiaaUpgradeManagementPage } from './miaaUpgradeManagementPage';
export class MiaaDashboard extends Dashboard {
@@ -32,7 +31,6 @@ export class MiaaDashboard extends Dashboard {
const connectionStringsPage = new MiaaConnectionStringsPage(modelView, this.dashboard, this._miaaModel);
const computeAndStoragePage = new MiaaComputeAndStoragePage(modelView, this.dashboard, this._miaaModel);
const miaaBackupsPage = new MiaaBackupsPage(modelView, this.dashboard, this._controllerModel, this._miaaModel);
const upgradeManagementPage = new MiaaUpgradeManagementPage(modelView, this.dashboard, this._controllerModel, this._miaaModel);
return [
overviewPage.tab,
{
@@ -40,8 +38,7 @@ export class MiaaDashboard extends Dashboard {
tabs: [
connectionStringsPage.tab,
computeAndStoragePage.tab,
miaaBackupsPage.tab,
upgradeManagementPage.tab
miaaBackupsPage.tab
]
},
];

View File

@@ -8,7 +8,7 @@ import * as azExt from 'az-ext';
import * as azurecore from 'azurecore';
import * as vscode from 'vscode';
import { getDatabaseStateDisplayText, promptForInstanceDeletion } from '../../../common/utils';
import { ConnectionMode, cssStyles, IconPathHelper, miaaTroubleshootDocsUrl } from '../../../constants';
import { cssStyles, IconPathHelper, miaaTroubleshootDocsUrl } from '../../../constants';
import * as loc from '../../../localizedConstants';
import { ControllerModel } from '../../../models/controllerModel';
import { MiaaModel } from '../../../models/miaaModel';
@@ -243,25 +243,7 @@ export class MiaaDashboardOverviewPage extends DashboardPage {
cancellable: false
},
async (_progress, _token) => {
if (this._controllerModel.info.connectionMode === ConnectionMode.direct) {
return await this._azApi.az.sql.miarc.delete(
this._miaaModel.info.name,
{
resourceGroup: this._controllerModel.info.resourceGroup,
namespace: undefined,
},
this._controllerModel.azAdditionalEnvVars
);
} else {
return await this._azApi.az.sql.miarc.delete(
this._miaaModel.info.name,
{
resourceGroup: undefined,
namespace: this._controllerModel.info.namespace,
},
this._controllerModel.azAdditionalEnvVars
);
}
return await this._azApi.az.sql.miarc.delete(this._miaaModel.info.name, this._controllerModel.info.namespace, this._controllerModel.azAdditionalEnvVars);
}
);
await this._controllerModel.refreshTreeNode();
@@ -355,7 +337,7 @@ export class MiaaDashboardOverviewPage extends DashboardPage {
if (this._miaaModel.config) {
this._instanceProperties.status = this._miaaModel.config.status.state || '-';
this._instanceProperties.externalEndpoint = this._miaaModel.config.status.primaryEndpoint || loc.notConfigured;
this._instanceProperties.vCores = this._miaaModel.config.spec?.scheduling?.default?.resources?.limits?.cpu?.toString() || '';
this._instanceProperties.vCores = this._miaaModel.config.spec.scheduling?.default?.resources?.limits?.cpu?.toString() || '';
this._databasesMessage.value = !this._miaaModel.config.status.primaryEndpoint ? loc.noExternalEndpoint : '';
if (!this._miaaModel.config.status.primaryEndpoint) {
this._databasesContainer.removeItem(this._connectToServerLoading);

View File

@@ -1,307 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as azExt from 'az-ext';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles, ConnectionMode } from '../../../constants';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel } from '../../../models/controllerModel';
import { UpgradeSqlMiaa } from '../../dialogs/upgradeSqlMiaa';
import { MiaaModel } from '../../../models/miaaModel';
export class MiaaUpgradeManagementPage extends DashboardPage {
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel, private _miaaModel: MiaaModel) {
super(modelView, dashboard);
this._azApi = vscode.extensions.getExtension(azExt.extension.name)?.exports;
}
private _upgradesContainer!: azdata.DivContainer;
private _upgradesTableLoading!: azdata.LoadingComponent;
private _upgradesTable!: azdata.DeclarativeTableComponent;
private _upgradesMessage!: azdata.TextComponent;
private readonly _azApi: azExt.IExtension;
public get title(): string {
return loc.upgradeManagement;
}
public get id(): string {
return 'upgrades';
}
public get icon(): { dark: string, light: string } {
return IconPathHelper.upgrade;
}
protected async refresh(): Promise<void> {
await Promise.resolve(this._controllerModel.refresh(false, this._controllerModel.info.namespace));
this.handleTableUpdated();
}
public get container(): azdata.Component {
const root = this.modelView.modelBuilder.flexContainer()
.withLayout({ flexFlow: 'column' })
.withProps({ CSSStyles: { 'margin': '18px' } })
.component();
const content = this.modelView.modelBuilder.divContainer().component();
this._upgradesContainer = this.modelView.modelBuilder.divContainer().component();
root.addItem(content, { CSSStyles: { 'margin': '5px' } });
// Upgrades title and description
const availableUpgradesTitle = this.modelView.modelBuilder.text().withProps({
value: loc.availableUpgrades,
CSSStyles: { ...cssStyles.title },
}).component();
content.addItem(availableUpgradesTitle);
const infoAvailableUpgrades = this.modelView.modelBuilder.text().withProps({
value: loc.availableUpgradesDescription,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
}).component();
const upgradesVersionLogLink = this.modelView.modelBuilder.hyperlink().withProps({
label: loc.versionLog,
url: 'https://docs.microsoft.com/azure/azure-arc/data/upgrade-sql-managed-instance-direct-cli?WT.mc_id=Portal-Microsoft_Azure_HybridData_Platform'
}).component();
const upgradesInfoAndLink = this.modelView.modelBuilder.flexContainer()
.withLayout({ flexWrap: 'wrap' })
.withItems([
infoAvailableUpgrades,
upgradesVersionLogLink
], { CSSStyles: { 'margin-right': '5px' } }).component();
content.addItem(upgradesInfoAndLink, { CSSStyles: { 'min-height': '30px' } });
const infoOnlyNextImmediateVersion = this.modelView.modelBuilder.text().withProps({
value: loc.onlyNextImmediateVersionMiaa,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px', 'max-width': 'auto' }
}).component();
content.addItem(infoOnlyNextImmediateVersion, { CSSStyles: { 'min-height': '30px' } });
// Create loaded components
this._upgradesTableLoading = this.modelView.modelBuilder.loadingComponent().component();
this._upgradesTable = this.modelView.modelBuilder.declarativeTable().withProps({
width: '100%',
columns: [
{
displayName: loc.version,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '30%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
},
{
displayName: loc.releaseDate,
valueType: azdata.DeclarativeDataType.string,
isReadOnly: true,
width: '30%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow
},
{
displayName: loc.upgrade,
valueType: azdata.DeclarativeDataType.component,
isReadOnly: true,
width: '10%',
headerCssStyles: cssStyles.tableHeader,
rowCssStyles: cssStyles.tableRow,
}
],
dataValues: []
}).component();
this._upgradesMessage = this.modelView.modelBuilder.text()
.withProps({ CSSStyles: { 'text-align': 'center' } })
.component();
this.handleTableUpdated();
this._upgradesTableLoading.component = this._upgradesTable;
root.addItem(this._upgradesContainer);
root.addItem(this._upgradesMessage);
this.initialized = true;
this._upgradesTableLoading.loading = false;
this._upgradesContainer.addItem(this._upgradesTableLoading, { CSSStyles: { 'margin-bottom': '20px' } });
return root;
}
public get toolbarContainer(): azdata.ToolbarContainer {
// Refresh
const refreshButton = this.modelView.modelBuilder.button().withProps({
label: loc.refresh,
iconPath: IconPathHelper.refresh
}).component();
this.disposables.push(
refreshButton.onDidClick(async () => {
refreshButton.enabled = false;
try {
await this.refresh();
} finally {
refreshButton.enabled = true;
}
}));
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems(
[
{ component: refreshButton, toolbarSeparatorAfter: true },
]
).component();
}
private async getMiaaVersion(): Promise<string | undefined> {
try {
let miaaShowResult;
if (this._controllerModel.info.connectionMode === ConnectionMode.direct || this._controllerModel.controllerConfig?.spec.settings.azure.connectionMode === ConnectionMode.direct) {
miaaShowResult = await this._azApi.az.sql.miarc.show(
this._miaaModel.info.name,
{
resourceGroup: this._controllerModel.info.resourceGroup,
namespace: undefined
},
this._controllerModel.azAdditionalEnvVars
);
} else {
miaaShowResult = await this._azApi.az.sql.miarc.show(
this._miaaModel.info.name,
{
resourceGroup: undefined,
namespace: this._controllerModel.info.namespace
},
this._controllerModel.azAdditionalEnvVars
);
}
return miaaShowResult.stdout.status.runningVersion;
} catch (e) {
console.error(loc.showMiaaError, e);
return undefined;
}
}
private async formatTableData(result: azExt.AzOutput<azExt.DcListUpgradesResult>): Promise<(string | azdata.ButtonComponent)[][]> {
let formattedValues: (string | azdata.ButtonComponent)[][] = [];
const versions = result.stdout.versions;
const dates = result.stdout.dates;
const currentControllerVersion = result.stdout.currentVersion;
const currentMiaaVersion = await this.getMiaaVersion();
const nextMiaaVersion = currentMiaaVersion ? this.getNextVersion(versions, currentMiaaVersion) : console.error(loc.miaaVersionError);
if (currentMiaaVersion === currentControllerVersion) {
for (let i = 0; i < versions.length; i++) {
if (versions[i] === currentMiaaVersion) {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.currentVersion, false)]);
break;
} else {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.upgrade, false)]);
}
}
} else {
for (let i = 0; i < versions.length; i++) {
if (versions[i] === nextMiaaVersion) {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.upgrade, true)]);
formattedValues.push([versions[i + 1], dates[i + 1], this.createUpgradeButton(loc.currentVersion, false)]);
break;
} else {
formattedValues.push([versions[i], dates[i], this.createUpgradeButton(loc.upgrade, false)]);
}
}
}
return formattedValues;
}
private async handleTableUpdated(): Promise<void> {
const result = await this._azApi.az.arcdata.dc.listUpgrades(this._controllerModel.info.namespace);
let tableDisplay = await this.formatTableData(result);
let tableValues = tableDisplay.map(d => {
return d.map((value: any): azdata.DeclarativeTableCellValue => {
return { value: value };
});
});
this._upgradesTable.setDataValues(tableValues);
this._upgradesTableLoading.loading = false;
this._upgradesContainer.addItem(this._upgradesTableLoading, { CSSStyles: { 'margin-bottom': '20px' } });
}
// Given the list of available versions and the current version, if the current version is not the newest,
// then return the next version available. List of versions is ordered newest to oldest.
// If current version is the newest, then return undefined.
private getNextVersion(versions: string[], currentVersion: string): string | undefined {
let index = versions.indexOf(currentVersion);
// The version at index 0 will be the newest
if (index > 0) {
return versions[index - 1];
} else {
return undefined;
}
}
//Create restore button for every database entry in the database table
private createUpgradeButton(label: string, enabled: boolean): azdata.ButtonComponent | string {
let upgradeButton = this.modelView.modelBuilder.button().withProps({
label: label,
enabled: enabled
}).component();
this.disposables.push(
upgradeButton.onDidClick(async () => {
const upgradeDialog = new UpgradeSqlMiaa(this._controllerModel);
upgradeDialog.showDialog(loc.upgradeMiaa);
let dialogClosed = await upgradeDialog.waitForClose();
if (dialogClosed) {
try {
upgradeButton.enabled = false;
vscode.window.showInformationMessage(loc.upgradingMiaa('kubectl get sqlmi -A\' should not be localized.'));
await vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: loc.updatingInstance(this._miaaModel.info.name),
cancellable: true
},
async (_progress, _token): Promise<void> => {
if (this._controllerModel.info.connectionMode === ConnectionMode.direct) {
await this._azApi.az.sql.miarc.upgrade(
this._miaaModel.info.name,
{
resourceGroup: this._controllerModel.info.resourceGroup,
namespace: undefined
}
);
} else {
await this._azApi.az.sql.miarc.upgrade(
this._miaaModel.info.name,
{
resourceGroup: undefined,
namespace: this._controllerModel.info.namespace,
}
);
}
try {
await this._controllerModel.refresh(false, this._controllerModel.info.namespace);
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
}
}
);
} catch (error) {
console.log(error);
}
}
}));
return upgradeButton;
}
}

View File

@@ -15,7 +15,6 @@ import { AzureArcTreeDataProvider } from '../tree/azureArcTreeDataProvider';
import { RadioOptionsGroup } from '../components/radioOptionsGroup';
import { getCurrentClusterContext, getDefaultKubeConfigPath, getKubeConfigClusterContexts, KubeClusterContext } from '../../common/kubeUtils';
import { FilePicker } from '../components/filePicker';
import { ConnectionMode } from '../../constants';
export type ConnectToControllerDialogModel = { controllerModel: ControllerModel };
@@ -204,9 +203,9 @@ export class ConnectToControllerDialog extends ControllerDialogBase {
controllerModel.info.connectionMode = <string>controllerModel.controllerConfig?.spec.settings.azure.connectionMode;
controllerModel.info.location = <string>controllerModel.controllerConfig?.spec.settings.azure.location;
if (controllerModel.info.connectionMode === ConnectionMode.direct) {
if (controllerModel.info.connectionMode === 'direct') {
const rawCustomLocation = <string>controllerModel.controllerConfig?.metadata.annotations['management.azure.com/customLocation'];
const exp = /customlocations\/([\S]*)/;
const exp = /\/\bsubscriptions\b\/[\S]*\/\bresourceGroups\/[\S]*\/providers\/[\S]*\/customLocations\/([\S]*)/;
controllerModel.info.customLocation = <string>exp.exec(rawCustomLocation)?.pop();
}
} catch (err) {

View File

@@ -111,7 +111,7 @@ export abstract class ConnectToSqlDialog extends InitializingComponent {
};
const result = await azdata.connection.connect(connectionProfile, false, false);
if (result.connected) {
connectionProfile.id = result.connectionId!;
connectionProfile.id = result.connectionId;
const credentialProvider = await azdata.credentials.getProvider(credentialNamespace);
if (connectionProfile.savePassword) {
await credentialProvider.saveCredential(createCredentialId(this._controllerModel.info.id, this._model.info.resourceType, this._model.info.name), connectionProfile.password);

View File

@@ -303,7 +303,7 @@ export class RestoreSqlDialog extends InitializingComponent {
}
public refreshPitrSettings(): void {
this.pitrSettings.instanceName = this._miaaModel?.config?.name || this.pitrSettings.instanceName;
this.pitrSettings.instanceName = this._miaaModel?.config?.metadata.name || this.pitrSettings.instanceName;
this.pitrSettings.resourceGroupName = this._controllerModel?.controllerConfig?.spec.settings.azure.resourceGroup || this.pitrSettings.resourceGroupName;
this.pitrSettings.location = this._azurecoreApi.getRegionDisplayName(this._controllerModel?.controllerConfig?.spec.settings.azure.location) || this.pitrSettings.location;
this.pitrSettings.subscriptionId = this._controllerModel?.controllerConfig?.spec.settings.azure.subscription || this.pitrSettings.subscriptionId;

View File

@@ -1,94 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import { Deferred } from '../../common/promise';
import * as loc from '../../localizedConstants';
import * as vscode from 'vscode';
import { cssStyles } from '../../constants';
import { InitializingComponent } from '../components/initializingComponent';
import { UpgradeModel } from '../../models/miaaModel';
import { ControllerModel } from '../../models/controllerModel';
export class UpgradeController extends InitializingComponent {
protected modelBuilder!: azdata.ModelBuilder;
private pitrSettings: UpgradeModel = [];
private upgradeControllerDialogName = 'UpgradeControllerDialog';
protected _completionPromise = new Deferred<UpgradeModel | undefined>();
protected disposables: vscode.Disposable[] = [];
constructor(protected _controllerModel: ControllerModel) {
super();
}
public showDialog(dialogTitle: string): azdata.window.Dialog {
const dialog = azdata.window.createModelViewDialog(dialogTitle, this.upgradeControllerDialogName, 'narrow', 'flyout');
dialog.cancelButton.onClick(() => this.handleCancel());
dialog.registerContent(async view => {
this.modelBuilder = view.modelBuilder;
const areYouSure = this.modelBuilder.text().withProps({
value: loc.areYouSure,
CSSStyles: { ...cssStyles.title, 'margin-block-start': '0px', 'margin-block-end': '0px', 'max-width': 'auto' },
}).component();
const areYouSureInfo = this.modelBuilder.text().withProps({
value: loc.upgradeDialogController,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
const upgradeDialog = this.modelBuilder.flexContainer().withLayout({ flexWrap: 'wrap' }).component();
upgradeDialog.addItem(areYouSureInfo, { CSSStyles: { 'margin-right': '5px' } });
const monitorUpgradeInfo = this.modelBuilder.text().withProps({
value: loc.monitorUpgrade,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
upgradeDialog.addItem(monitorUpgradeInfo, { CSSStyles: { 'margin-right': '5px' } });
const monitorUpgradeCommandInfo = this.modelBuilder.text().withProps({
value: 'kubectl get datacontrollers -A',
CSSStyles: { ...cssStyles.code, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
upgradeDialog.addItem(monitorUpgradeCommandInfo, { CSSStyles: { 'margin-right': '5px' } });
let formModel = this.modelBuilder.formContainer()
.withFormItems([{
components: [
{
component: areYouSure
},
{
component: upgradeDialog
}
],
title: ''
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.initialized = true;
});
dialog.okButton.label = loc.upgrade;
dialog.cancelButton.label = loc.cancel;
dialog.registerCloseValidator(async () => await this.validate());
dialog.okButton.onClick(() => {
this._completionPromise.resolve(this.pitrSettings);
});
azdata.window.openDialog(dialog);
return dialog;
}
public async validate(): Promise<boolean> {
return true;
}
private handleCancel(): void {
this._completionPromise.resolve(undefined);
}
public waitForClose(): Promise<UpgradeModel | undefined> {
return this._completionPromise.promise;
}
}

View File

@@ -1,94 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import { Deferred } from '../../common/promise';
import * as loc from '../../localizedConstants';
import * as vscode from 'vscode';
import { cssStyles } from '../../constants';
import { InitializingComponent } from '../components/initializingComponent';
import { UpgradeModel } from '../../models/miaaModel';
import { ControllerModel } from '../../models/controllerModel';
export class UpgradeSqlMiaa extends InitializingComponent {
protected modelBuilder!: azdata.ModelBuilder;
private pitrSettings: UpgradeModel = [];
private upgradeMiaaDialogName = 'UpgradeSqlMiaaDialog';
protected _completionPromise = new Deferred<UpgradeModel | undefined>();
protected disposables: vscode.Disposable[] = [];
constructor(protected _controllerModel: ControllerModel) {
super();
}
public showDialog(dialogTitle: string): azdata.window.Dialog {
const dialog = azdata.window.createModelViewDialog(dialogTitle, this.upgradeMiaaDialogName, 'narrow', 'flyout');
dialog.cancelButton.onClick(() => this.handleCancel());
dialog.registerContent(async view => {
this.modelBuilder = view.modelBuilder;
const areYouSure = this.modelBuilder.text().withProps({
value: loc.areYouSure,
CSSStyles: { ...cssStyles.title, 'margin-block-start': '0px', 'margin-block-end': '0px', 'max-width': 'auto' },
}).component();
const areYouSureInfo = this.modelBuilder.text().withProps({
value: loc.upgradeDialogMiaa,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
const upgradeDialog = this.modelBuilder.flexContainer().withLayout({ flexWrap: 'wrap' }).component();
upgradeDialog.addItem(areYouSureInfo, { CSSStyles: { 'margin-right': '5px' } });
const monitorUpgradeInfo = this.modelBuilder.text().withProps({
value: loc.monitorUpgrade,
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
upgradeDialog.addItem(monitorUpgradeInfo, { CSSStyles: { 'margin-right': '5px' } });
const monitorUpgradeCommandInfo = this.modelBuilder.text().withProps({
value: 'kubectl get sqlmi -A',
CSSStyles: { ...cssStyles.code, 'margin-block-start': '0px', 'max-width': 'auto' }
}).component();
upgradeDialog.addItem(monitorUpgradeCommandInfo, { CSSStyles: { 'margin-right': '5px' } });
let formModel = this.modelBuilder.formContainer()
.withFormItems([{
components: [
{
component: areYouSure
},
{
component: upgradeDialog
}
],
title: ''
}]).withLayout({ width: '100%' }).component();
await view.initializeModel(formModel);
this.initialized = true;
});
dialog.okButton.label = loc.upgrade;
dialog.cancelButton.label = loc.cancel;
dialog.registerCloseValidator(async () => await this.validate());
dialog.okButton.onClick(() => {
this._completionPromise.resolve(this.pitrSettings);
});
azdata.window.openDialog(dialog);
return dialog;
}
public async validate(): Promise<boolean> {
return true;
}
private handleCancel(): void {
this._completionPromise.resolve(undefined);
}
public waitForClose(): Promise<UpgradeModel | undefined> {
return this._completionPromise.promise;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
{
"parserOptions": {
"project": "./extensions/azcli/tsconfig.json"
},
"rules": {
// Disabled until the issues can be fixed
"@typescript-eslint/explicit-function-return-type": ["off"]
}
}

View File

@@ -2,7 +2,7 @@
"name": "azcli",
"displayName": "%azcli.arc.displayName%",
"description": "%azcli.arc.description%",
"version": "1.3.0",
"version": "1.0.0",
"publisher": "Microsoft",
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
"icon": "images/extension.png",
@@ -94,21 +94,21 @@
"which": "^2.0.2"
},
"devDependencies": {
"@types/mocha": "^7.0.2",
"@types/mocha": "^5.2.5",
"@types/node": "^12.11.7",
"@types/request": "^2.48.5",
"@types/semver": "^7.3.1",
"@types/sinon": "^9.0.4",
"@types/uuid": "^8.0.0",
"@types/which": "^1.3.2",
"mocha": "^7.1.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"nock": "^13.0.2",
"should": "^13.2.3",
"sinon": "^9.0.2",
"typemoq": "^2.1.0",
"@microsoft/vscodetestcover": "^1.2.1"
"@microsoft/vscodetestcover": "^1.2.0"
},
"__metadata": {
"id": "84",

View File

@@ -54,22 +54,6 @@ export function getAzApi(localAzDiscovered: Promise<IAzTool | undefined>, azTool
validateAz(azToolService.localAz);
return azToolService.localAz!.arcdata.dc.config.show(namespace, additionalEnvVars);
}
},
listUpgrades: async (namespace: string, usek8s?: boolean, additionalEnvVars?: azExt.AdditionalEnvVars) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.arcdata.dc.listUpgrades(namespace, usek8s, additionalEnvVars);
},
upgrade: async (
desiredVersion: string,
name: string,
resourceGroup?: string,
namespace?: string,
additionalEnvVars?: azExt.AdditionalEnvVars
) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.arcdata.dc.upgrade(desiredVersion, name, resourceGroup, namespace, additionalEnvVars);
}
}
},
@@ -117,47 +101,20 @@ export function getAzApi(localAzDiscovered: Promise<IAzTool | undefined>, azTool
},
sql: {
miarc: {
delete: async (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string;
// Indirect mode arguments
namespace?: string;
},
additionalEnvVars?: azExt.AdditionalEnvVars
) => {
delete: async (name: string, namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.sql.miarc.delete(name, args, additionalEnvVars);
return azToolService.localAz!.sql.miarc.delete(name, namespace, additionalEnvVars);
},
list: async (
args: {
// Direct mode arguments
resourceGroup?: string;
// Indirect mode arguments
namespace?: string;
},
additionalEnvVars?: azExt.AdditionalEnvVars
) => {
list: async (namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.sql.miarc.list(args, additionalEnvVars);
return azToolService.localAz!.sql.miarc.list(namespace, additionalEnvVars);
},
show: async (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string;
// Indirect mode arguments
namespace?: string;
},
// Additional arguments
additionalEnvVars?: azExt.AdditionalEnvVars
) => {
show: async (name: string, namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.sql.miarc.show(name, args, additionalEnvVars);
return azToolService.localAz!.sql.miarc.show(name, namespace, additionalEnvVars);
},
update: async (
name: string,
@@ -179,21 +136,6 @@ export function getAzApi(localAzDiscovered: Promise<IAzTool | undefined>, azTool
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.sql.miarc.update(name, args, resourceGroup, namespace, usek8s, additionalEnvVars);
},
upgrade: async (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string;
// Indirect mode arguments
namespace?: string;
},
// Additional arguments
additionalEnvVars?: azExt.AdditionalEnvVars
) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.sql.miarc.upgrade(name, args, additionalEnvVars);
}
},
midbarc: {
@@ -212,17 +154,6 @@ export function getAzApi(localAzDiscovered: Promise<IAzTool | undefined>, azTool
}
}
},
monitor: {
logAnalytics: {
workspace: {
list: async (resourceGroup?: string, subscription?: string, additionalEnvVars?: azExt.AdditionalEnvVars) => {
await localAzDiscovered;
validateAz(azToolService.localAz);
return azToolService.localAz!.monitor.logAnalytics.workspace.list(resourceGroup, subscription, additionalEnvVars);
}
}
}
},
getPath: async () => {
await localAzDiscovered;
throwIfNoAz(azToolService.localAz);

View File

@@ -90,38 +90,6 @@ export class AzTool implements azExt.IAzApi {
show: (namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<azExt.DcConfigShowResult>> => {
return this.executeCommand<azExt.DcConfigShowResult>(['arcdata', 'dc', 'config', 'show', '--k8s-namespace', namespace, '--use-k8s'], additionalEnvVars);
}
},
listUpgrades: async (namespace: string, usek8s?: boolean, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<azExt.DcListUpgradesResult>> => {
const argsArray = ['arcdata', 'dc', 'list-upgrades'];
if (namespace) { argsArray.push('--k8s-namespace', namespace); }
if (usek8s) { argsArray.push('--use-k8s'); }
const output = await this.executeCommand<string>(argsArray, additionalEnvVars);
const versions = <string[]>parseDcListUpgrades(output.stdout);
const currentVersion = <string>parseCurrentVersion(output.stdout);
let dates: string[] = [];
for (let i = 0; i < versions.length; i++) {
dates.push(parseReleaseDateFromUpgrade(versions[i]));
}
return {
stdout: {
versions: versions,
currentVersion: currentVersion,
dates: dates
},
stderr: output.stderr
};
},
upgrade: (desiredVersion: string, name: string, resourceGroup?: string, namespace?: string, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<void>> => {
const argsArray = ['arcdata', 'dc', 'upgrade', '--desired-version', desiredVersion, '--name', name];
// Direct mode argument
if (resourceGroup) { argsArray.push('--resource-group', resourceGroup); }
// Indirect mode arguments
if (namespace) {
argsArray.push('--k8s-namespace', namespace);
argsArray.push('--use-k8s');
}
return this.executeCommand<void>(argsArray, additionalEnvVars);
}
}
};
@@ -177,67 +145,14 @@ export class AzTool implements azExt.IAzApi {
public sql = {
miarc: {
delete: (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
// Additional arguments
},
additionalEnvVars?: azExt.AdditionalEnvVars
): Promise<azExt.AzOutput<void>> => {
const argsArray = ['sql', 'mi-arc', 'delete', '-n', name];
if (args.resourceGroup) {
argsArray.push('--resource-group', args.resourceGroup);
}
if (args.namespace) {
argsArray.push('--k8s-namespace', args.namespace);
argsArray.push('--use-k8s');
}
return this.executeCommand<void>(argsArray, additionalEnvVars);
delete: (name: string, namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<void>> => {
return this.executeCommand<void>(['sql', 'mi-arc', 'delete', '-n', name, '--k8s-namespace', namespace, '--use-k8s'], additionalEnvVars);
},
list: (
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
// Additional arguments
},
additionalEnvVars?: azExt.AdditionalEnvVars
): Promise<azExt.AzOutput<azExt.SqlMiListResult[]>> => {
const argsArray = ['sql', 'mi-arc', 'list'];
if (args.resourceGroup) {
argsArray.push('--resource-group', args.resourceGroup);
}
if (args.namespace) {
argsArray.push('--k8s-namespace', args.namespace);
argsArray.push('--use-k8s');
}
return this.executeCommand<azExt.SqlMiListResult[]>(argsArray, additionalEnvVars);
list: (namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<azExt.SqlMiListResult[]>> => {
return this.executeCommand<azExt.SqlMiListResult[]>(['sql', 'mi-arc', 'list', '--k8s-namespace', namespace, '--use-k8s'], additionalEnvVars);
},
show: (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
// Additional arguments
},
additionalEnvVars?: azExt.AdditionalEnvVars
): Promise<azExt.AzOutput<azExt.SqlMiShowResult>> => {
const argsArray = ['sql', 'mi-arc', 'show', '-n', name];
if (args.resourceGroup) {
argsArray.push('--resource-group', args.resourceGroup);
}
if (args.namespace) {
argsArray.push('--k8s-namespace', args.namespace);
argsArray.push('--use-k8s');
}
return this.executeSqlMiShow(argsArray, additionalEnvVars);
show: (name: string, namespace: string, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<azExt.SqlMiShowResult>> => {
return this.executeCommand<azExt.SqlMiShowResult>(['sql', 'mi-arc', 'show', '-n', name, '--k8s-namespace', namespace, '--use-k8s'], additionalEnvVars);
},
update: (
name: string,
@@ -268,25 +183,6 @@ export class AzTool implements azExt.IAzApi {
if (namespace) { argsArray.push('--k8s-namespace', namespace); }
if (usek8s) { argsArray.push('--use-k8s'); }
return this.executeCommand<void>(argsArray, additionalEnvVars);
},
upgrade: (
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
// Additional arguments
},
additionalEnvVars?: azExt.AdditionalEnvVars
): Promise<azExt.AzOutput<void>> => {
const argsArray = ['sql', 'mi-arc', 'upgrade', '--name', name];
if (args.resourceGroup) { argsArray.push('--resource-group', args.resourceGroup); }
if (args.namespace) {
argsArray.push('--k8s-namespace', args.namespace);
argsArray.push('--use-k8s');
}
return this.executeCommand<void>(argsArray, additionalEnvVars);
}
},
midbarc: {
@@ -313,19 +209,6 @@ export class AzTool implements azExt.IAzApi {
}
};
public monitor = {
logAnalytics: {
workspace: {
list: (resourceGroup?: string, subscription?: string, additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<azExt.LogAnalyticsWorkspaceListResult[]>> => {
const argsArray = ['monitor', 'log-analytics', 'workspace', 'list'];
if (resourceGroup) { argsArray.push('--resource-group', resourceGroup); }
if (subscription) { argsArray.push('--subscription', subscription); }
return this.executeCommand<azExt.LogAnalyticsWorkspaceListResult[]>(argsArray, additionalEnvVars);
}
}
}
};
/**
* Gets the output of running '--version' command on the az tool.
@@ -340,64 +223,6 @@ export class AzTool implements azExt.IAzApi {
};
}
/**
* Executes az sql mi-arc show and returns a normalized object, SqlMiShowResult, regardless of the indirect or direct mode raw output shape.
* @param args The args to pass to az
* @param additionalEnvVars Additional environment variables to set for this execution
*/
public async executeSqlMiShow(args: string[], additionalEnvVars?: azExt.AdditionalEnvVars): Promise<azExt.AzOutput<azExt.SqlMiShowResult>> {
try {
const result = await executeAzCommand(`"${this._path}"`, args.concat(['--output', 'json']), additionalEnvVars);
let stdout = <unknown>result.stdout;
let stderr = <unknown>result.stderr;
try {
// Automatically try parsing the JSON. This is expected to fail for some az commands such as resource delete.
stdout = JSON.parse(result.stdout);
} catch (err) {
// If the output was not pure JSON, catch the error and log it here.
Logger.log(loc.azOutputParseErrorCaught(args.concat(['--output', 'json']).toString()));
throw err;
}
if ((<azExt.SqlMiShowResultDirect>stdout).properties) {
// Then it is direct mode
return {
stdout: {
name: (<azExt.SqlMiShowResultDirect>stdout).name,
spec: (<azExt.SqlMiShowResultDirect>stdout).properties.k8SRaw.spec,
status: (<azExt.SqlMiShowResultDirect>stdout).properties.k8SRaw.status
},
stderr: <string[]>stderr
};
} else {
// It must be indirect mode
return {
stdout: {
name: (<azExt.SqlMiShowResultIndirect>stdout).metadata?.name,
spec: (<azExt.SqlMiShowResultIndirect>stdout).spec,
status: (<azExt.SqlMiShowResultIndirect>stdout).status
},
stderr: <string[]>stderr
};
}
} catch (err) {
if (err instanceof ExitCodeError) {
try {
await fs.promises.access(this._path);
//this.path exists
} catch (e) {
// this.path does not exist
await vscode.commands.executeCommand('setContext', azFound, false);
throw new NoAzureCLIError();
}
}
throw err;
}
}
/**
* Executes the specified az command.
* @param args The args to pass to az
@@ -718,70 +543,6 @@ function parseArcExtensionVersion(raw: string): string | undefined {
return exp.exec(raw)?.pop();
}
/**
* Parses out all available upgrades
* @param raw The raw version output from az arcdata dc list-upgrades
*/
function parseDcListUpgrades(raw: string): string[] | undefined {
// Currently the version is a multi-line string that contains other version information such
// as the Python installation, with the first line holding the version of az itself.
//
// Found 6 valid versions. The current datacontroller version is v1.2.0_2021-12-15.
// v1.4.1_2022-03-08
// v1.4.0_2022-02-25
// v1.3.0_2022-01-27
// v1.2.0_2021-12-15 << current version
// v1.1.0_2021-11-02
// v1.0.0_2021-07-30
let versions: string[] = [];
const lines = raw.split('\n');
const exp = /^(v\d*.\d*.\d*.\d*.\d*.\d*.\d)/;
for (let i = 1; i < lines.length; i++) {
let result = exp.exec(lines[i])?.pop();
if (result) {
versions.push(result);
}
}
return versions;
}
/**
* Parses out the release date from the upgrade version number and formats it into MM/DD/YYYY format.
* For example: v1.4.1_2022-03-08 ==> 03/08/2022
* @param raw The raw upgrade version number, such as: v1.4.1_2022-03-08
*/
function parseReleaseDateFromUpgrade(raw: string): string {
let formattedDate = '';
const exp = /^v\d*.\d*.\d*_(\d*).(\d*).(\d*.\d)/;
let rawDate = exp.exec(raw);
if (rawDate) {
formattedDate += rawDate[2] + '/' + rawDate[3] + '/' + rawDate[1];
} else {
console.error(loc.releaseDateNotParsed);
}
return formattedDate;
}
/**
* Parses out the current version number out of all available upgrades
* @param raw The raw version output from az arcdata dc list-upgrades
*/
function parseCurrentVersion(raw: string): string | undefined {
// Currently the version is a multi-line string that contains other version information such
// as the Python installation, with the first line holding the version of az itself.
//
// Found 6 valid versions. The current datacontroller version is v1.2.0_2021-12-15.
// v1.4.1_2022-03-08
// v1.4.0_2022-02-25
// v1.3.0_2022-01-27
// v1.2.0_2021-12-15 << current version
// v1.1.0_2021-11-02
// v1.0.0_2021-07-30
const exp = /The current datacontroller version is\s*(v\d*.\d*.\d*.\d*.\d*.\d*.\d)/;
return exp.exec(raw)?.pop();
}
async function executeAzCommand(command: string, args: string[], additionalEnvVars: azExt.AdditionalEnvVars = {}): Promise<ProcessOutput> {
const debug = vscode.workspace.getConfiguration(azConfigSection).get(debugConfigKey);
if (debug) {

View File

@@ -72,4 +72,3 @@ export const userResponseToInstallPrompt = (response: string | undefined): strin
export const userResponseToUpdatePrompt = (response: string | undefined): string => localize('az.userResponseUpdate', "User Response on prompt to update Azure CLI: {0}", response);
export const userRequestedInstall = localize('az.userRequestedInstall', "User requested to install Azure CLI and arcdata extension using 'Azure CLI: Install' command");
export const updateCheckSkipped = localize('az.updateCheckSkipped', "No check for new Azure CLI version availability performed as Azure CLI was not found to be installed");
export const releaseDateNotParsed = localize('arc.releaseDateNotParsed', "Release date could not be parsed.");

View File

@@ -110,18 +110,15 @@ describe('az', function () {
describe('sql', function (): void {
describe('mi-arc', function (): void {
it('delete', async function (): Promise<void> {
// Assume indirect mode
await azTool.sql.miarc.delete(name, {resourceGroup: undefined, namespace: namespace});
await azTool.sql.miarc.delete(name, namespace);
verifyExecuteCommandCalledWithArgs(['sql', 'mi-arc', 'delete', name, '--k8s-namespace', namespace, '--use-k8s']);
});
it('list', async function (): Promise<void> {
// Assume indirect mode
await azTool.sql.miarc.list({resourceGroup: undefined, namespace: namespace});
await azTool.sql.miarc.list(namespace);
verifyExecuteCommandCalledWithArgs(['sql', 'mi-arc', 'list', '--k8s-namespace', namespace, '--use-k8s']);
});
it('show', async function (): Promise<void> {
// Assume indirect mode
await azTool.sql.miarc.show(name, {resourceGroup: undefined, namespace: namespace});
await azTool.sql.miarc.show(name, namespace);
verifyExecuteCommandCalledWithArgs(['sql', 'mi-arc', 'show', name, '--k8s-namespace', namespace, '--use-k8s']);
});
});

View File

@@ -116,12 +116,6 @@ declare module 'az-ext' {
}
}
export interface DcListUpgradesResult {
versions: string[], // ["v1.4.1_2022-03-08", "v1.4.0_2022-02-25"]
currentVersion: string, // "v1.4.1_2022-03-08"
dates: string[] // ["03/08/2022", "02/25/2022"]
}
export interface StorageVolume {
className?: string, // "local-storage"
size: string // "5Gi"
@@ -138,42 +132,6 @@ declare module 'az-ext' {
}
export interface SqlMiShowResult {
name: string, // "miaa-instance"
spec: {
backup?: {
retentionPeriodInDays: number, // 1
}
scheduling?: {
default?: {
resources?: {
limits?: SchedulingOptions,
requests?: SchedulingOptions
}
}
}
services: {
primary: ServiceSpec
}
storage: {
data: {
volumes: StorageVolume[]
},
logs: {
volumes: StorageVolume[]
}
}
},
status: {
readyReplicas: string, // "1/1"
state: string, // "Ready",
logSearchDashboard: string, // https://127.0.0.1:30777/kibana/app/kibana#/discover?_a=(query:(language:kuery,query:'custom_resource_name:miaa1'))
metricsDashboard: string, // https://127.0.0.1:30777/grafana/d/40q72HnGk/sql-managed-instance-metrics?var-hostname=miaa1-0
primaryEndpoint?: string // "10.91.86.39:32718"
runningVersion: string // "v1.5.0_2022-04-05"
}
}
export interface SqlMiShowResultIndirect {
apiVersion: string, // "sql.arcdata.microsoft.com/v1alpha1"
kind: string, // "sqlmanagedinstance"
metadata: {
@@ -215,167 +173,9 @@ declare module 'az-ext' {
logSearchDashboard: string, // https://127.0.0.1:30777/kibana/app/kibana#/discover?_a=(query:(language:kuery,query:'custom_resource_name:miaa1'))
metricsDashboard: string, // https://127.0.0.1:30777/grafana/d/40q72HnGk/sql-managed-instance-metrics?var-hostname=miaa1-0
primaryEndpoint?: string // "10.91.86.39:32718"
runningVersion: string // "v1.5.0_2022-04-05"
}
}
export interface SqlMiShowResultDirect {
extendedLocation: {
name: string, // /subscriptions/a2382b66-3h2k-3h2k-2gdd-8ef45dgfdc33/resourcegroups/name-rg/providers/microsoft.extendedlocation/customlocations/custom-loc,
type: string, // CustomLocation
},
id: string, // /subscriptions/a2382b66-3h2k-3h2k-2gdd-8ef45dgfdc33/resourceGroups/name-rg/providers/Microsoft.AzureArcData/sqlManagedInstances/sql1,
location: string, // eastus2,
name: string, // sql2,
properties: {
activeDirectoryInformation: string, // null,
admin: string, // admin,
basicLoginInformation: string, // null,
clusterId: string, // null,
dataControllerId: string, // dc-name,
endTime: string, // null,
extensionId: string, // null,
k8SRaw: {
spec: {
backup: {
retentionPeriodInDays: number, // 7
},
dev: boolean, // true,
licenseType: string, // BasePrice,
metadata: {
annotations: string, // ,
labels: string, // ,
namespace: string, // namespace-name
},
replicas: number, // 1,
scheduling: {
additionalProperties: string, // null,
default: {
additionalProperties: string, // null,
resources: {
additionalProperties: string, // null,
limits: {
cpu: string, // 4,
memory: string, // 8Gi
},
requests: {
cpu: string, // 2,
memory: string, // 4Gi
}
}
}
},
security: {
adminLoginSecret: string, // sql-login-secret,
serviceCertificateSecret: string, //
},
services: {
primary: {
annotations: string, // ,
labels: string, // ,
type: string, // NodePort
}
},
settings: {
collation: string, // SQL_Latin1_General_CP1_CI_AS,
language: {
lcid: number, // 1234
},
sqlagent: {
enabled: boolean, // false
},
timezone: string, // UTC,
traceFlags: boolean, // false
},
storage: {
backups: {
volumes: [
{
annotations: string, // ,
className: string, // azurefile,
labels: string, // ,
size: string, // 5Gi
}
]
},
data: {
volumes: [
{
annotations: string, // ,
className: string, // default,
labels: string, // ,
size: string, // 5Gi
}
]
},
datalogs: {
volumes: [
{
annotations: string, // ,
className: string, // default,
labels: string, // ,
size: string, // 5Gi
}
]
},
logs: {
volumes: [
{
annotations: string, // ,
className: string, // default,
labels: string, // ,
size: string, // 5Gi
}
]
}
},
tier: string, // GeneralPurpose
},
status: {
endpoints: {
logSearchDashboard: string, // https://localhost:12345/app/kibana#/discover?_a=(query:(language:kuery,query:'custom_resource_name:sql1')),
metricsDashboard: string, // https://12.123.1.4:12345/d/sdfgwseg/sql-managed-instance-metrics?var-hostname=sql1-0,
mirroring: string, // 10.224.0.4:32040,
primary: string, // 10.224.0.4,32477
},
highAvailability: {
lastUpdateTime: string, // 2022-05-09T23:40:19.626856Z,
mirroringCertificate: string,
},
lastUpdateTime: string, // 2022-05-09T23:41:00.137919Z,
logSearchDashboard: string,
metricsDashboard: string,
observedGeneration: number, // 1,
primaryEndpoint: string, // 10.224.0.4,32477,
readyReplicas: string, // 1/1,
roles: {
sql: {
lastUpdateTime: string, // 2022-05-09T23:39:53.364002Z,
readyReplicas: number, // 1,
replicas: number, // 1
}
},
runningVersion: string, // v1.4.0_2022-02-25,
state: string, // Ready
}
},
lastUploadedDate: string, // null,
licenseType: string, // BasePrice,
provisioningState: string, // Succeeded,
startTime: string, // null
},
resourceGroup: string, // rg-name,
sku: {
capacity: string, // null,
dev: string, // null,
family: string, // null,
size: string, // null,
tier: string, // GeneralPurpose
},
tags: {},
type: string, // microsoft.azurearcdata/sqlmanagedinstances
}
export interface SqlMiDbRestoreResult {
destDatabase: string, //testDbToRestore
earliestRestoreTime: string, // "2020-08-19T20:25:11Z"
@@ -387,45 +187,6 @@ declare module 'az-ext' {
state: string //Completed
}
export interface LogAnalyticsWorkspaceListResult {
createdDate: string, // "2020-02-25T16:59:38Z"
customerId: string, // "7e136a79-c0b6-4878-86bf-7bf7a6a7e6f6",
eTag: string, // null,
etag: string, // "\"00006df1-0000-0700-0000-61ee552f0000\"",
features: {
clusterResourceId: string, // null,
disableLocalAuth: boolean, // null,
enableDataExport: boolean, // null,
enableLogAccessUsingOnlyResourcePermissions: boolean, //true,
immediatePurgeDataOn30Days: boolean, // null,
legacy: number, // 0,
searchVersion: number // 1
},
forceCmkForQuery: boolean, // null,
id: string, // "/subscriptions/a5082b19-8a6e-4bc5-8fdd-8ef39dfebc39/resourcegroups/bugbash/providers/microsoft.operationalinsights/workspaces/bugbash-logs",
location: string, // "westus",
modifiedDate: string, // "2022-02-21T09:18:22.3906451Z",
name: string, // "bugbash-logs",
privateLinkScopedResources: string, // null,
provisioningState: string, // "Succeeded",
publicNetworkAccessForIngestion: string, // "Enabled",
publicNetworkAccessForQuery: string, // "Enabled",
resourceGroup: string, // "bugbash",
retentionInDays: number, // 30,
sku: {
capacityReservationLevel: number, // null,
lastSkuUpdate: string, // "2020-02-25T16:59:38Z",
name: string, // "pergb2018"
},
tags: string[], //null,
type: string, //"Microsoft.OperationalInsights/workspaces",
workspaceCapping: {
dailyQuotaGb: number, //-1.0,
dataIngestionStatus: string, // "RespectQuota",
quotaNextResetTime: string, // "2022-02-21T19:00:00Z"
}
}
export interface PostgresServerShowResult {
apiVersion: string, // "arcdata.microsoft.com/v1alpha1"
kind: string, // "postgresql"
@@ -532,9 +293,7 @@ declare module 'az-ext' {
config: {
list(additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<DcConfigListResult[]>>,
show(namespace?: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<DcConfigShowResult>>
},
listUpgrades(namespace: string, usek8s?: boolean, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<DcListUpgradesResult>>,
upgrade(desiredVersion: string, name: string, resourceGroup?: string, namespace?: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<void>>,
}
}
},
postgres: {
@@ -566,38 +325,9 @@ declare module 'az-ext' {
},
sql: {
miarc: {
delete(
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
},
// Additional arguments
additionalEnvVars?: AdditionalEnvVars
): Promise<AzOutput<void>>,
list(
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
},
// Additional arguments
additionalEnvVars?: AdditionalEnvVars
): Promise<AzOutput<SqlMiListResult[]>>,
show(
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
},
// Additional arguments
additionalEnvVars?: AdditionalEnvVars
): Promise<AzOutput<SqlMiShowResult>>,
delete(name: string, namespace?: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<void>>,
list(namespace?: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<SqlMiListResult[]>>,
show(name: string, namespace?: string, additionalEnvVars?: AdditionalEnvVars): Promise<AzOutput<SqlMiShowResult>>,
update(
name: string,
args: {
@@ -615,17 +345,6 @@ declare module 'az-ext' {
usek8s?: boolean,
// Additional arguments
additionalEnvVars?: AdditionalEnvVars
): Promise<AzOutput<void>>,
upgrade(
name: string,
args: {
// Direct mode arguments
resourceGroup?: string,
// Indirect mode arguments
namespace?: string
},
// Additional arguments
additionalEnvVars?: AdditionalEnvVars
): Promise<AzOutput<void>>
},
midbarc: {
@@ -643,17 +362,6 @@ declare module 'az-ext' {
): Promise<AzOutput<SqlMiDbRestoreResult>>
}
},
monitor: {
logAnalytics: {
workspace: {
list(
resourceGroup?: string, // test-rg
subscription?: string, // 122c121a-095a-4f5d-22e4-cc6b238490a3
additionalEnvVars?: AdditionalEnvVars
): Promise<AzOutput<LogAnalyticsWorkspaceListResult[]>>
}
}
},
getPath(): Promise<string>,
/**
* The semVersion corresponding to this installation of the Azure CLI. version() method should have been run

File diff suppressed because it is too large Load Diff

View File

@@ -8,8 +8,6 @@
{
"ignoreVoid": true
}
],
// Disabled until the issues can be fixed
"@typescript-eslint/explicit-function-return-type": ["off"]
]
}
}

View File

@@ -348,26 +348,26 @@
"@azure/arm-resourcegraph": "^4.0.0",
"@azure/arm-subscriptions": "^3.0.0",
"@azure/storage-blob": "^12.6.0",
"axios": "^0.27.2",
"axios": "^0.21.4",
"node-fetch": "^2.6.7",
"qs": "^6.9.1",
"vscode-nls": "^4.0.0",
"ws": "^7.4.6"
"ws": "^7.2.0"
},
"devDependencies": {
"@types/keytar": "4.4.0",
"@types/mocha": "^7.0.2",
"@types/mocha": "^5.2.5",
"@types/node": "^12.11.7",
"@types/qs": "^6.9.1",
"@types/request": "^2.48.1",
"@types/sinon": "^9.0.4",
"@types/ws": "^6.0.4",
"mocha": "^7.1.1",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.17.0",
"mocha-multi-reporters": "^1.1.7",
"should": "^13.2.1",
"sinon": "^9.0.2",
"typemoq": "^2.1.0",
"@microsoft/vscodetestcover": "^1.2.1"
"@microsoft/vscodetestcover": "^1.2.0"
}
}

View File

@@ -1,24 +1,6 @@
<svg width="150" height="150" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="e399c19f-b68f-429d-b176-18c2117ff73c" x1="-1032.172" x2="-1059.213" y1="145.312" y2="65.426" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#114a8b"/>
<stop offset="1" stop-color="#0669bc"/>
</linearGradient>
<linearGradient id="ac2a6fc2-ca48-4327-9a3c-d4dcc3256e15" x1="-1023.725" x2="-1029.98" y1="108.083" y2="105.968" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-opacity=".3"/>
<stop offset=".071" stop-opacity=".2"/>
<stop offset=".321" stop-opacity=".1"/>
<stop offset=".623" stop-opacity=".05"/>
<stop offset="1" stop-opacity="0"/>
</linearGradient>
<linearGradient id="a7fee970-a784-4bb1-af8d-63d18e5f7db9" x1="-1027.165" x2="-997.482" y1="147.642" y2="68.561" gradientTransform="matrix(1 0 0 -1 1075 158)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#3ccbf4"/>
<stop offset="1" stop-color="#2892df"/>
</linearGradient>
</defs>
<path fill="url(#e399c19f-b68f-429d-b176-18c2117ff73c)" d="M33.338 6.544h26.038l-27.03 80.087a4.152 4.152 0 0 1-3.933 2.824H8.149a4.145 4.145 0 0 1-3.928-5.47L29.404 9.368a4.152 4.152 0 0 1 3.934-2.825z"/>
<path fill="#0078d4" d="M71.175 60.261h-41.29a1.911 1.911 0 0 0-1.305 3.309l26.532 24.764a4.171 4.171 0 0 0 2.846 1.121h23.38z"/>
<path fill="url(#ac2a6fc2-ca48-4327-9a3c-d4dcc3256e15)" d="M33.338 6.544a4.118 4.118 0 0 0-3.943 2.879L4.252 83.917a4.14 4.14 0 0 0 3.908 5.538h20.787a4.443 4.443 0 0 0 3.41-2.9l5.014-14.777 17.91 16.705a4.237 4.237 0 0 0 2.666.972H81.24L71.024 60.261l-29.781.007L59.47 6.544z"/>
<path fill="url(#a7fee970-a784-4bb1-af8d-63d18e5f7db9)" d="M66.595 9.364a4.145 4.145 0 0 0-3.928-2.82H33.648a4.146 4.146 0 0 1 3.928 2.82l25.184 74.62a4.146 4.146 0 0 1-3.928 5.472h29.02a4.146 4.146 0 0 0 3.927-5.472z"/>
<?xml version="1.0" encoding="UTF-8"?>
<svg height="28" width="28" version="1.1" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<g>
<path fill="#0072C6" d="M11.423,44.326l23.623-4.156L22.894,25.748l6.328-17.346L50,44.33L11.423,44.326z M27.566,5.67L11.469,40.109v-0.034H0l12.717-21.975L27.566,5.67z" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 331 B

View File

@@ -1,19 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_725:32860)">
<path d="M1.92584 4.68122C1.88418 4.68135 1.84417 4.66492 1.81462 4.63555C1.78507 4.60617 1.7684 4.56627 1.76827 4.5246C1.76506 3.53697 0.962946 2.73832 -0.0247012 2.7394C-0.0826423 2.74262 -0.137618 2.71355 -0.167561 2.66385C-0.197503 2.61412 -0.197503 2.55195 -0.167561 2.50222C-0.137618 2.45252 -0.0826423 2.42344 -0.0247012 2.42667C0.963056 2.42801 1.76533 1.62921 1.76827 0.641457C1.76827 0.554162 1.83903 0.483395 1.92633 0.483395C2.01362 0.483395 2.08439 0.554162 2.08439 0.641457C2.0876 1.62948 2.89031 2.42828 3.87834 2.42667C3.96481 2.42667 4.03494 2.49678 4.03494 2.58327C4.03494 2.66977 3.96481 2.73987 3.87834 2.73987C2.89031 2.73827 2.0876 3.53707 2.08439 4.5251C2.08413 4.56685 2.06727 4.60677 2.03752 4.63607C2.00778 4.66535 1.96759 4.6816 1.92584 4.68122Z" fill="white"/>
<path d="M12.9813 14.751C12.9296 14.751 12.8875 14.7092 12.8873 14.6575C12.8849 14.0673 12.4055 13.5902 11.8153 13.5908C11.7636 13.5908 11.7217 13.5489 11.7217 13.4972C11.7217 13.4455 11.7636 13.4036 11.8153 13.4036C12.4055 13.4042 12.8849 12.9272 12.8873 12.337C12.8873 12.285 12.9294 12.2429 12.9813 12.2429C13.0333 12.2429 13.0754 12.285 13.0754 12.337C13.0778 12.9272 13.5572 13.4042 14.1474 13.4036C14.1991 13.4036 14.241 13.4455 14.241 13.4972C14.241 13.5489 14.1991 13.5908 14.1474 13.5908C13.5572 13.5902 13.0778 14.0673 13.0754 14.6575C13.0754 14.6824 13.0655 14.7062 13.0478 14.7238C13.0302 14.7414 13.0062 14.7512 12.9813 14.751Z" fill="white"/>
<path d="M5.39249 12.6482C6.97109 13.4359 8.84442 13.3531 10.3474 12.4292C11.8503 11.5054 12.7701 9.8713 12.7801 8.10712C11.6963 9.07732 10.5245 9.94457 9.27999 10.6977C8.04727 11.4666 6.74584 12.1196 5.39249 12.6482Z" fill="white"/>
<path d="M8.433 9.31202C9.7825 8.50402 11.0351 7.54424 12.1663 6.45139C12.2589 6.35929 12.3414 6.27492 12.4194 6.19395C12.1976 5.63 11.8764 5.11042 11.4711 4.6599C10.1951 3.2472 8.24175 2.6572 6.39707 3.1273C4.5524 3.5974 3.11967 5.05027 2.67542 6.90135C2.29705 8.51252 2.72197 10.2072 3.81577 11.4492C3.9336 11.4148 4.04947 11.3818 4.17797 11.3401C5.6688 10.828 7.09637 10.1476 8.433 9.31202Z" fill="white"/>
<path d="M15.1293 3.4817C14.642 2.68072 13.4114 2.49601 11.5763 2.94497C11.005 3.08947 10.443 3.2684 9.89338 3.48072C10.2476 3.65355 10.581 3.86632 10.8868 4.11492C11.1991 4.01212 11.5055 3.92097 11.7974 3.84872C12.2856 3.71947 12.7873 3.64835 13.2922 3.63685C13.8929 3.63685 14.2245 3.78522 14.3351 3.96607C14.5164 4.2628 14.3496 5.0463 13.283 6.2788C13.0934 6.49795 12.8796 6.72 12.6556 6.94352C11.4856 8.07417 10.1902 9.06745 8.7947 9.904C7.41253 10.7693 5.93533 11.4726 4.39228 12C2.5358 12.6046 1.26791 12.5925 0.984278 12.1285C0.70064 11.6645 1.26791 10.5285 2.6541 9.152C2.56913 8.76032 2.53088 8.35995 2.54015 7.95927C0.334095 9.95297 -0.380087 11.6815 0.190096 12.6138C0.488763 13.1021 1.14088 13.3794 2.09361 13.3794C3.2267 13.3317 4.3426 13.0856 5.39058 12.6521C6.74535 12.1233 8.04808 11.4699 9.28198 10.7001C10.5269 9.94677 11.699 9.0792 12.7831 8.10862C13.2088 7.72667 13.6114 7.31982 13.9889 6.8902C15.2238 5.45987 15.619 4.2817 15.1293 3.4817Z" fill="white"/>
<path d="M1.92584 4.68122C1.88418 4.68135 1.84417 4.66492 1.81462 4.63555C1.78507 4.60617 1.7684 4.56627 1.76827 4.5246C1.76506 3.53697 0.962946 2.73832 -0.0247012 2.7394C-0.0826423 2.74262 -0.137618 2.71355 -0.167561 2.66385C-0.197503 2.61412 -0.197503 2.55195 -0.167561 2.50222C-0.137618 2.45252 -0.0826423 2.42344 -0.0247012 2.42667C0.963056 2.42801 1.76533 1.62921 1.76827 0.641457C1.76827 0.554162 1.83903 0.483395 1.92633 0.483395C2.01362 0.483395 2.08439 0.554162 2.08439 0.641457C2.0876 1.62948 2.89031 2.42828 3.87834 2.42667C3.96481 2.42667 4.03494 2.49678 4.03494 2.58327C4.03494 2.66977 3.96481 2.73987 3.87834 2.73987C2.89031 2.73827 2.0876 3.53707 2.08439 4.5251C2.08413 4.56685 2.06727 4.60677 2.03752 4.63607C2.00778 4.66535 1.96759 4.6816 1.92584 4.68122Z" fill="white"/>
<path d="M12.9813 14.751C12.9296 14.751 12.8875 14.7092 12.8873 14.6575C12.8849 14.0673 12.4055 13.5902 11.8153 13.5908C11.7636 13.5908 11.7217 13.5489 11.7217 13.4972C11.7217 13.4455 11.7636 13.4036 11.8153 13.4036C12.4055 13.4042 12.8849 12.9272 12.8873 12.337C12.8873 12.285 12.9294 12.2429 12.9813 12.2429C13.0333 12.2429 13.0754 12.285 13.0754 12.337C13.0778 12.9272 13.5572 13.4042 14.1474 13.4036C14.1991 13.4036 14.241 13.4455 14.241 13.4972C14.241 13.5489 14.1991 13.5908 14.1474 13.5908C13.5572 13.5902 13.0778 14.0673 13.0754 14.6575C13.0754 14.6824 13.0655 14.7062 13.0478 14.7238C13.0302 14.7414 13.0062 14.7512 12.9813 14.751Z" fill="white"/>
<path opacity="0.93" d="M5.39249 12.6482C6.97109 13.4359 8.84442 13.3531 10.3474 12.4292C11.8503 11.5054 12.7701 9.8713 12.7801 8.10712C11.6963 9.07732 10.5245 9.94457 9.27999 10.6977C8.04727 11.4666 6.74584 12.1196 5.39249 12.6482Z" fill="white"/>
<path opacity="0.93" d="M8.433 9.31202C9.7825 8.50402 11.0351 7.54424 12.1663 6.45139C12.2589 6.35929 12.3414 6.27492 12.4194 6.19395C12.1976 5.63 11.8764 5.11042 11.4711 4.6599C10.1951 3.2472 8.24175 2.6572 6.39707 3.1273C4.5524 3.5974 3.11967 5.05027 2.67542 6.90135C2.29705 8.51252 2.72197 10.2072 3.81577 11.4492C3.9336 11.4148 4.04947 11.3818 4.17797 11.3401C5.6688 10.828 7.09637 10.1476 8.433 9.31202Z" fill="white"/>
<path d="M15.1293 3.4817C14.642 2.68072 13.4114 2.49601 11.5763 2.94497C11.005 3.08947 10.443 3.2684 9.89338 3.48072C10.2476 3.65355 10.581 3.86632 10.8868 4.11492C11.1991 4.01212 11.5055 3.92097 11.7974 3.84872C12.2856 3.71947 12.7873 3.64835 13.2922 3.63685C13.8929 3.63685 14.2245 3.78522 14.3351 3.96607C14.5164 4.2628 14.3496 5.0463 13.283 6.2788C13.0934 6.49795 12.8796 6.72 12.6556 6.94352C11.4856 8.07417 10.1902 9.06745 8.7947 9.904C7.41253 10.7693 5.93533 11.4726 4.39228 12C2.5358 12.6046 1.26791 12.5925 0.984278 12.1285C0.70064 11.6645 1.26791 10.5285 2.6541 9.152C2.56913 8.76032 2.53088 8.35995 2.54015 7.95927C0.334095 9.95297 -0.380087 11.6815 0.190096 12.6138C0.488763 13.1021 1.14088 13.3794 2.09361 13.3794C3.2267 13.3317 4.3426 13.0856 5.39058 12.6521C6.74535 12.1233 8.04808 11.4699 9.28198 10.7001C10.5269 9.94677 11.699 9.0792 12.7831 8.10862C13.2088 7.72667 13.6114 7.31982 13.9889 6.8902C15.2238 5.45987 15.619 4.2817 15.1293 3.4817Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_725:32860">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -1,19 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_724:59228)">
<path d="M1.92584 4.68122C1.88418 4.68135 1.84417 4.66492 1.81462 4.63555C1.78507 4.60617 1.7684 4.56627 1.76827 4.5246C1.76506 3.53697 0.962946 2.73832 -0.0247012 2.7394C-0.0826423 2.74262 -0.137618 2.71355 -0.167561 2.66385C-0.197503 2.61412 -0.197503 2.55195 -0.167561 2.50222C-0.137618 2.45252 -0.0826423 2.42344 -0.0247012 2.42667C0.963056 2.42801 1.76533 1.62921 1.76827 0.641457C1.76827 0.554162 1.83903 0.483395 1.92633 0.483395C2.01362 0.483395 2.08439 0.554162 2.08439 0.641457C2.0876 1.62948 2.89031 2.42828 3.87834 2.42667C3.96481 2.42667 4.03494 2.49678 4.03494 2.58327C4.03494 2.66977 3.96481 2.73987 3.87834 2.73987C2.89031 2.73827 2.0876 3.53707 2.08439 4.5251C2.08413 4.56685 2.06727 4.60677 2.03752 4.63607C2.00778 4.66535 1.96759 4.6816 1.92584 4.68122Z" fill="#212121"/>
<path d="M12.9813 14.751C12.9296 14.751 12.8875 14.7092 12.8873 14.6575C12.8849 14.0673 12.4055 13.5902 11.8153 13.5908C11.7636 13.5908 11.7217 13.5489 11.7217 13.4972C11.7217 13.4455 11.7636 13.4036 11.8153 13.4036C12.4055 13.4042 12.8849 12.9272 12.8873 12.337C12.8873 12.285 12.9294 12.2429 12.9813 12.2429C13.0333 12.2429 13.0754 12.285 13.0754 12.337C13.0778 12.9272 13.5572 13.4042 14.1474 13.4036C14.1991 13.4036 14.241 13.4455 14.241 13.4972C14.241 13.5489 14.1991 13.5908 14.1474 13.5908C13.5572 13.5902 13.0778 14.0673 13.0754 14.6575C13.0754 14.6824 13.0655 14.7062 13.0478 14.7238C13.0302 14.7414 13.0062 14.7512 12.9813 14.751Z" fill="#212121"/>
<path d="M5.39249 12.6482C6.97109 13.4359 8.84442 13.3531 10.3474 12.4292C11.8503 11.5054 12.7701 9.8713 12.7801 8.10712C11.6963 9.07732 10.5245 9.94457 9.27999 10.6977C8.04727 11.4666 6.74584 12.1196 5.39249 12.6482Z" fill="#212121"/>
<path d="M8.433 9.31202C9.7825 8.50402 11.0351 7.54424 12.1663 6.45139C12.2589 6.35929 12.3414 6.27492 12.4194 6.19395C12.1976 5.63 11.8764 5.11042 11.4711 4.6599C10.1951 3.2472 8.24175 2.6572 6.39708 3.1273C4.5524 3.5974 3.11968 5.05027 2.67543 6.90135C2.29705 8.51252 2.72198 10.2072 3.81578 11.4492C3.9336 11.4148 4.04948 11.3818 4.17798 11.3401C5.6688 10.828 7.09637 10.1476 8.433 9.31202Z" fill="#212121"/>
<path d="M15.1293 3.4817C14.642 2.68072 13.4114 2.49601 11.5763 2.94497C11.005 3.08947 10.443 3.2684 9.89338 3.48072C10.2476 3.65355 10.581 3.86632 10.8868 4.11492C11.1991 4.01212 11.5055 3.92097 11.7974 3.84872C12.2856 3.71947 12.7873 3.64835 13.2922 3.63685C13.8929 3.63685 14.2245 3.78522 14.3351 3.96607C14.5164 4.2628 14.3496 5.0463 13.283 6.2788C13.0934 6.49795 12.8796 6.72 12.6556 6.94352C11.4856 8.07417 10.1902 9.06745 8.7947 9.904C7.41253 10.7693 5.93533 11.4726 4.39228 12C2.5358 12.6046 1.26791 12.5925 0.98428 12.1285C0.700642 11.6645 1.26791 10.5285 2.6541 9.152C2.56913 8.76032 2.53088 8.35995 2.54015 7.95927C0.334097 9.95297 -0.380085 11.6815 0.190098 12.6138C0.488765 13.1021 1.14088 13.3794 2.09361 13.3794C3.2267 13.3317 4.3426 13.0856 5.39058 12.6521C6.74535 12.1233 8.04808 11.4699 9.28198 10.7001C10.5269 9.94677 11.699 9.0792 12.7831 8.10862C13.2088 7.72667 13.6114 7.31982 13.9889 6.8902C15.2238 5.45987 15.619 4.2817 15.1293 3.4817Z" fill="#212121"/>
<path d="M1.92584 4.68122C1.88418 4.68135 1.84417 4.66492 1.81462 4.63555C1.78507 4.60617 1.7684 4.56627 1.76827 4.5246C1.76506 3.53697 0.962946 2.73832 -0.0247012 2.7394C-0.0826423 2.74262 -0.137618 2.71355 -0.167561 2.66385C-0.197503 2.61412 -0.197503 2.55195 -0.167561 2.50222C-0.137618 2.45252 -0.0826423 2.42344 -0.0247012 2.42667C0.963056 2.42801 1.76533 1.62921 1.76827 0.641457C1.76827 0.554162 1.83903 0.483395 1.92633 0.483395C2.01362 0.483395 2.08439 0.554162 2.08439 0.641457C2.0876 1.62948 2.89031 2.42828 3.87834 2.42667C3.96481 2.42667 4.03494 2.49678 4.03494 2.58327C4.03494 2.66977 3.96481 2.73987 3.87834 2.73987C2.89031 2.73827 2.0876 3.53707 2.08439 4.5251C2.08413 4.56685 2.06727 4.60677 2.03752 4.63607C2.00778 4.66535 1.96759 4.6816 1.92584 4.68122Z" fill="#212121"/>
<path d="M12.9813 14.751C12.9296 14.751 12.8875 14.7092 12.8873 14.6575C12.8849 14.0673 12.4055 13.5902 11.8153 13.5908C11.7636 13.5908 11.7217 13.5489 11.7217 13.4972C11.7217 13.4455 11.7636 13.4036 11.8153 13.4036C12.4055 13.4042 12.8849 12.9272 12.8873 12.337C12.8873 12.285 12.9294 12.2429 12.9813 12.2429C13.0333 12.2429 13.0754 12.285 13.0754 12.337C13.0778 12.9272 13.5572 13.4042 14.1474 13.4036C14.1991 13.4036 14.241 13.4455 14.241 13.4972C14.241 13.5489 14.1991 13.5908 14.1474 13.5908C13.5572 13.5902 13.0778 14.0673 13.0754 14.6575C13.0754 14.6824 13.0655 14.7062 13.0478 14.7238C13.0302 14.7414 13.0062 14.7512 12.9813 14.751Z" fill="#212121"/>
<path opacity="0.93" d="M5.39249 12.6482C6.97109 13.4359 8.84442 13.3531 10.3474 12.4292C11.8503 11.5054 12.7701 9.8713 12.7801 8.10712C11.6963 9.07732 10.5245 9.94457 9.27999 10.6977C8.04727 11.4666 6.74584 12.1196 5.39249 12.6482Z" fill="#212121"/>
<path opacity="0.93" d="M8.433 9.31202C9.7825 8.50402 11.0351 7.54424 12.1663 6.45139C12.2589 6.35929 12.3414 6.27492 12.4194 6.19395C12.1976 5.63 11.8764 5.11042 11.4711 4.6599C10.1951 3.2472 8.24175 2.6572 6.39708 3.1273C4.5524 3.5974 3.11968 5.05027 2.67543 6.90135C2.29705 8.51252 2.72198 10.2072 3.81578 11.4492C3.9336 11.4148 4.04948 11.3818 4.17798 11.3401C5.6688 10.828 7.09637 10.1476 8.433 9.31202Z" fill="#212121"/>
<path d="M15.1293 3.4817C14.642 2.68072 13.4114 2.49601 11.5763 2.94497C11.005 3.08947 10.443 3.2684 9.89338 3.48072C10.2476 3.65355 10.581 3.86632 10.8868 4.11492C11.1991 4.01212 11.5055 3.92097 11.7974 3.84872C12.2856 3.71947 12.7873 3.64835 13.2922 3.63685C13.8929 3.63685 14.2245 3.78522 14.3351 3.96607C14.5164 4.2628 14.3496 5.0463 13.283 6.2788C13.0934 6.49795 12.8796 6.72 12.6556 6.94352C11.4856 8.07417 10.1902 9.06745 8.7947 9.904C7.41253 10.7693 5.93533 11.4726 4.39228 12C2.5358 12.6046 1.26791 12.5925 0.98428 12.1285C0.700642 11.6645 1.26791 10.5285 2.6541 9.152C2.56913 8.76032 2.53088 8.35995 2.54015 7.95927C0.334097 9.95297 -0.380085 11.6815 0.190098 12.6138C0.488765 13.1021 1.14088 13.3794 2.09361 13.3794C3.2267 13.3317 4.3426 13.0856 5.39058 12.6521C6.74535 12.1233 8.04808 11.4699 9.28198 10.7001C10.5269 9.94677 11.699 9.0792 12.7831 8.10862C13.2088 7.72667 13.6114 7.31982 13.9889 6.8902C15.2238 5.45987 15.619 4.2817 15.1293 3.4817Z" fill="#212121"/>
</g>
<defs>
<clipPath id="clip0_724:59228">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 6.3 KiB

Some files were not shown because too many files have changed in this diff Show More