Merge pull request #365 from 50Wliu/rethink-azureextensionui-dependency
Remove vscode-azureextensionui
This commit is contained in:
Коммит
f7d0079da8
|
@ -36,6 +36,12 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/html-to-text": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/html-to-text/-/html-to-text-5.1.2.tgz",
|
||||
"integrity": "sha512-56PHFwRe18fmZ+UsN6GqUaoKfalOwFzxaBMRA2O5URde3d5mxdH1HvnIV7LSugCiO8JWlRdSL2L3xJXykCTKVg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/minimatch": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
|
||||
|
@ -695,15 +701,6 @@
|
|||
"ms-rest-azure": "^2.5.5"
|
||||
}
|
||||
},
|
||||
"azure-arm-storage": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/azure-arm-storage/-/azure-arm-storage-3.2.0.tgz",
|
||||
"integrity": "sha512-jrew8qgqCiJ66QyjAhQis7AXhK6hp5soypvcxio3g/b1mNJr7RsQ6vD5zBRebcvM+QBGzvv7COiXy/xzibyOgA==",
|
||||
"requires": {
|
||||
"ms-rest": "^2.2.2",
|
||||
"ms-rest-azure": "^2.3.3"
|
||||
}
|
||||
},
|
||||
"azure-arm-website": {
|
||||
"version": "5.7.0",
|
||||
"resolved": "https://registry.npmjs.org/azure-arm-website/-/azure-arm-website-5.7.0.tgz",
|
||||
|
@ -1700,9 +1697,9 @@
|
|||
}
|
||||
},
|
||||
"diagnostic-channel-publishers": {
|
||||
"version": "0.3.4",
|
||||
"resolved": "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.3.4.tgz",
|
||||
"integrity": "sha512-SZ1zMfFiEabf4Qx0Og9V1gMsRoqz3O+5ENkVcNOfI+SMJ3QhQsdEoKX99r0zvreagXot2parPxmrwwUM/ja8ug=="
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.3.5.tgz",
|
||||
"integrity": "sha512-AOIjw4T7Nxl0G2BoBPhkQ6i7T4bUd9+xvdYizwvG7vVAM1dvr+SDrcUudlmzwH0kbEwdR2V1EcnKT0wAeYLQNQ=="
|
||||
},
|
||||
"diff": {
|
||||
"version": "3.5.0",
|
||||
|
@ -1739,14 +1736,14 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"domelementtype": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
|
||||
"integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ=="
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz",
|
||||
"integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA=="
|
||||
},
|
||||
"entities": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.2.tgz",
|
||||
"integrity": "sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw=="
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
|
||||
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -2280,16 +2277,6 @@
|
|||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"dev": true
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz",
|
||||
"integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"fs-write-stream-atomic": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
|
||||
|
@ -2431,7 +2418,8 @@
|
|||
"graceful-fs": {
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
|
||||
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
|
||||
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
|
||||
"dev": true
|
||||
},
|
||||
"growl": {
|
||||
"version": "1.10.5",
|
||||
|
@ -2566,14 +2554,14 @@
|
|||
}
|
||||
},
|
||||
"html-to-text": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-4.0.0.tgz",
|
||||
"integrity": "sha512-QQl5EEd97h6+3crtgBhkEAO6sQnZyDff8DAeJzoSkOc1Dqe1UvTUZER0B+KjBe6fPZqq549l2VUhtracus3ndA==",
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-5.1.1.tgz",
|
||||
"integrity": "sha512-Bci6bD/JIfZSvG4s0gW/9mMKwBRoe/1RWLxUME/d6WUSZCdY7T60bssf/jFf7EYXRyqU4P5xdClVqiYU0/ypdA==",
|
||||
"requires": {
|
||||
"he": "^1.0.0",
|
||||
"htmlparser2": "^3.9.2",
|
||||
"lodash": "^4.17.4",
|
||||
"optimist": "^0.6.1"
|
||||
"he": "^1.2.0",
|
||||
"htmlparser2": "^3.10.1",
|
||||
"lodash": "^4.17.11",
|
||||
"minimist": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
|
@ -2830,7 +2818,8 @@
|
|||
"is-wsl": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
|
||||
"integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0="
|
||||
"integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
|
||||
"dev": true
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
|
@ -2919,6 +2908,7 @@
|
|||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
|
@ -3255,9 +3245,9 @@
|
|||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
|
||||
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
},
|
||||
"mississippi": {
|
||||
"version": "3.0.0",
|
||||
|
@ -3697,23 +3687,6 @@
|
|||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"opn": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/opn/-/opn-6.0.0.tgz",
|
||||
"integrity": "sha512-I9PKfIZC+e4RXZ/qr1RhgyCnGgYX0UEIlXgWnCOVACIvFgaC9rz6Won7xbdhoHrd8IIhV7YEpHjreNUNkqCGkQ==",
|
||||
"requires": {
|
||||
"is-wsl": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"optimist": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
|
||||
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
|
||||
"requires": {
|
||||
"minimist": "~0.0.1",
|
||||
"wordwrap": "~0.0.2"
|
||||
}
|
||||
},
|
||||
"os-browserify": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
|
||||
|
@ -5684,7 +5657,8 @@
|
|||
"universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
|
||||
"dev": true
|
||||
},
|
||||
"unset-value": {
|
||||
"version": "1.0.0",
|
||||
|
@ -5860,70 +5834,12 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"vscode-azureextensionui": {
|
||||
"version": "0.26.3",
|
||||
"resolved": "https://registry.npmjs.org/vscode-azureextensionui/-/vscode-azureextensionui-0.26.3.tgz",
|
||||
"integrity": "sha512-bWWj7S4+PSAFgwoHUcZSnjo0s7qLNAHxn/yY4EbvyzjPff83BgMe6Mkla+h0F7l33Pfc75VZoZKl3v6kNNzwcA==",
|
||||
"requires": {
|
||||
"azure-arm-resource": "^3.0.0-preview",
|
||||
"azure-arm-storage": "^3.1.0",
|
||||
"fs-extra": "^4.0.3",
|
||||
"html-to-text": "^4.0.0",
|
||||
"ms-rest": "^2.2.2",
|
||||
"ms-rest-azure": "^2.4.4",
|
||||
"opn": "^6.0.0",
|
||||
"semver": "^5.6.0",
|
||||
"vscode-extension-telemetry": "^0.1.0",
|
||||
"vscode-nls": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"azure-arm-resource": {
|
||||
"version": "3.0.0-preview",
|
||||
"resolved": "https://registry.npmjs.org/azure-arm-resource/-/azure-arm-resource-3.0.0-preview.tgz",
|
||||
"integrity": "sha512-5AxK9Nnk9hRDtyiXkaqvHV2BvII12JpPpTTHL8p9ZKgkwy67mWk+repoe9PnjxwG2Rm1RadutonccynJ+VHVAw==",
|
||||
"requires": {
|
||||
"ms-rest": "^2.0.0",
|
||||
"ms-rest-azure": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"vscode-extension-telemetry": {
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.6.tgz",
|
||||
"integrity": "sha512-rbzSg7k4NnsCdF4Lz0gI4jl3JLXR0hnlmfFgsY8CSDYhXgdoIxcre8jw5rjkobY0xhSDhbG7xCjP8zxskySJ/g==",
|
||||
"requires": {
|
||||
"applicationinsights": "1.7.4"
|
||||
}
|
||||
},
|
||||
"vscode-nls": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.2.tgz",
|
||||
"integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"vscode-extension-telemetry": {
|
||||
"version": "0.0.18",
|
||||
"resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.18.tgz",
|
||||
"integrity": "sha512-Vw3Sr+dZwl+c6PlsUwrTtCOJkgrmvS3OUVDQGcmpXWAgq9xGq6as0K4pUx+aGqTjzLAESmWSrs6HlJm6J6Khcg==",
|
||||
"version": "0.1.6",
|
||||
"resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.6.tgz",
|
||||
"integrity": "sha512-rbzSg7k4NnsCdF4Lz0gI4jl3JLXR0hnlmfFgsY8CSDYhXgdoIxcre8jw5rjkobY0xhSDhbG7xCjP8zxskySJ/g==",
|
||||
"requires": {
|
||||
"applicationinsights": "1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"applicationinsights": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-1.0.1.tgz",
|
||||
"integrity": "sha1-U0Rrgw/o1dYZ7uKieLMdPSUDCSc=",
|
||||
"requires": {
|
||||
"diagnostic-channel": "0.2.0",
|
||||
"diagnostic-channel-publishers": "0.2.1",
|
||||
"zone.js": "0.7.6"
|
||||
}
|
||||
},
|
||||
"diagnostic-channel-publishers": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz",
|
||||
"integrity": "sha1-ji1geottef6IC1SLxYzGvrKIxPM="
|
||||
}
|
||||
"applicationinsights": "1.7.4"
|
||||
}
|
||||
},
|
||||
"vscode-json-languageservice": {
|
||||
|
@ -5935,6 +5851,13 @@
|
|||
"vscode-languageserver-types": "^3.6.1",
|
||||
"vscode-nls": "^3.2.1",
|
||||
"vscode-uri": "^1.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-uri": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz",
|
||||
"integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"vscode-jsonrpc": {
|
||||
|
@ -5968,25 +5891,6 @@
|
|||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"vscode-jsonrpc": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz",
|
||||
"integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg=="
|
||||
},
|
||||
"vscode-languageserver-protocol": {
|
||||
"version": "3.16.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz",
|
||||
"integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==",
|
||||
"requires": {
|
||||
"vscode-jsonrpc": "6.0.0",
|
||||
"vscode-languageserver-types": "3.16.0"
|
||||
}
|
||||
},
|
||||
"vscode-languageserver-types": {
|
||||
"version": "3.16.0",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz",
|
||||
"integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA=="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
|
@ -6001,6 +5905,13 @@
|
|||
"requires": {
|
||||
"vscode-languageserver-protocol": "^3.7.0",
|
||||
"vscode-uri": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-uri": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.8.tgz",
|
||||
"integrity": "sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"vscode-languageserver-protocol": {
|
||||
|
@ -6041,9 +5952,9 @@
|
|||
}
|
||||
},
|
||||
"vscode-uri": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.6.tgz",
|
||||
"integrity": "sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww=="
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.2.tgz",
|
||||
"integrity": "sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA=="
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "1.7.2",
|
||||
|
@ -6968,11 +6879,6 @@
|
|||
"source-map": "~0.6.1"
|
||||
}
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
|
||||
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
|
||||
},
|
||||
"worker-farm": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
|
||||
|
@ -7037,11 +6943,6 @@
|
|||
"compress-commons": "^2.1.1",
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"zone.js": {
|
||||
"version": "0.7.6",
|
||||
"resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.7.6.tgz",
|
||||
"integrity": "sha1-+7w50+AmHQmG8boGMG6zrrDSIAk="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
24
package.json
24
package.json
|
@ -38,8 +38,7 @@
|
|||
],
|
||||
"activationEvents": [
|
||||
"onLanguage:azure-pipelines",
|
||||
"onCommand:azure-pipelines.configure-pipeline",
|
||||
"onCommand:azure-pipelines.browse-pipeline"
|
||||
"onCommand:azure-pipelines.configure-pipeline"
|
||||
],
|
||||
"main": "./out/extension",
|
||||
"contributes": {
|
||||
|
@ -103,11 +102,6 @@
|
|||
"command": "azure-pipelines.configure-pipeline",
|
||||
"title": "Configure Pipeline",
|
||||
"category": "Azure Pipelines"
|
||||
},
|
||||
{
|
||||
"command": "azure-pipelines.browse-pipeline",
|
||||
"title": "Browse Pipeline",
|
||||
"category": "Azure Pipelines"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
|
@ -117,12 +111,6 @@
|
|||
"group": "Azure Pipelines",
|
||||
"when": "explorerResourceIsFolder == true"
|
||||
}
|
||||
],
|
||||
"commandPalette": [
|
||||
{
|
||||
"command": "azure-pipelines.browse-pipeline",
|
||||
"when": "never"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -135,9 +123,10 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "4.0.5",
|
||||
"@types/html-to-text": "^5.1.2",
|
||||
"@types/mocha": "5.2.5",
|
||||
"@types/mustache": "0.8.32",
|
||||
"@types/node": "^12.0.0",
|
||||
"@types/node": "^12.12.2",
|
||||
"@types/q": "1.5.0",
|
||||
"@types/underscore": "1.8.9",
|
||||
"@types/vscode": "^1.45.1",
|
||||
|
@ -155,6 +144,7 @@
|
|||
"azure-arm-resource": "7.3.0",
|
||||
"azure-arm-website": "5.7.0",
|
||||
"azure-pipelines-language-server": "0.6.0",
|
||||
"html-to-text": "^5.1.1",
|
||||
"mustache": "3.0.1",
|
||||
"q": "1.5.1",
|
||||
"shelljs": "^0.3.0",
|
||||
|
@ -162,11 +152,9 @@
|
|||
"typed-rest-client": "1.0.7",
|
||||
"underscore": "1.9.1",
|
||||
"uuid": "^3.3.2",
|
||||
"vscode-azureextensionui": "0.26.3",
|
||||
"vscode-extension-telemetry": "0.0.18",
|
||||
"vscode-extension-telemetry": "^0.1.6",
|
||||
"vscode-languageclient": "^7.0.0",
|
||||
"vscode-nls": "3.2.4",
|
||||
"vscode-uri": "1.0.6"
|
||||
"vscode-uri": "^3.0.2"
|
||||
},
|
||||
"extensionDependencies": [
|
||||
"ms-vscode.azure-account"
|
||||
|
|
|
@ -1,44 +1,26 @@
|
|||
import * as vscode from 'vscode';
|
||||
import { registerCommand, IActionContext, createApiProvider, AzureTreeItem } from 'vscode-azureextensionui';
|
||||
import { AzureExtensionApi, AzureExtensionApiProvider } from 'vscode-azureextensionui/api';
|
||||
|
||||
import { browsePipeline } from './browse';
|
||||
import { configurePipeline } from './configure';
|
||||
import { Messages } from './resources/messages';
|
||||
import { AzureAccountExtensionExports, extensionVariables } from './model/models';
|
||||
import { telemetryHelper } from './helper/telemetryHelper';
|
||||
import { telemetryHelper } from '../helpers/telemetryHelper';
|
||||
|
||||
export async function activateConfigurePipeline(): Promise<AzureExtensionApiProvider> {
|
||||
export async function activateConfigurePipeline(): Promise<void> {
|
||||
let azureAccountExtension = vscode.extensions.getExtension("ms-vscode.azure-account");
|
||||
if (!azureAccountExtension) {
|
||||
throw new Error(Messages.azureAccountExntesionUnavailable);
|
||||
}
|
||||
|
||||
if (!azureAccountExtension.isActive) {
|
||||
await azureAccountExtension.activate();
|
||||
}
|
||||
|
||||
extensionVariables.azureAccountExtensionApi = <AzureAccountExtensionExports>azureAccountExtension.exports;
|
||||
|
||||
// The command has been defined in the package.json file
|
||||
// Now provide the implementation of the command with registerCommand
|
||||
// The commandId parameter must match the command field in package.json
|
||||
registerCommand('azure-pipelines.configure-pipeline', async (actionContext: IActionContext, node: any) => {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
telemetryHelper.initialize(actionContext, 'configure-pipeline');
|
||||
await configurePipeline(node);
|
||||
});
|
||||
vscode.commands.registerCommand('azure-pipelines.configure-pipeline', async () => {
|
||||
if (!azureAccountExtension.isActive) {
|
||||
await azureAccountExtension.activate();
|
||||
}
|
||||
|
||||
registerCommand('azure-pipelines.browse-pipeline', async (actionContext: IActionContext, node: AzureTreeItem) => {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
telemetryHelper.initialize(actionContext, 'browse-pipeline');
|
||||
await browsePipeline(node);
|
||||
telemetryHelper.initialize('configure-pipeline');
|
||||
await telemetryHelper.callWithTelemetryAndErrorHandling(async () => {
|
||||
await configurePipeline();
|
||||
});
|
||||
});
|
||||
|
||||
return createApiProvider([<AzureExtensionApi>
|
||||
{
|
||||
configurePipelineApi: configurePipeline,
|
||||
browsePipeline: browsePipeline,
|
||||
apiVersion: "0.0.1"
|
||||
}]);
|
||||
}
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
import * as vscode from 'vscode';
|
||||
import { AzureTreeItem, UserCancelledError } from 'vscode-azureextensionui';
|
||||
|
||||
import { AppServiceClient, ScmType } from './clients/azure/appServiceClient';
|
||||
import { getSubscriptionSession } from './helper/azureSessionHelper';
|
||||
import { ControlProvider } from './helper/controlProvider';
|
||||
import { AzureSession, ParsedAzureResourceId, extensionVariables } from './model/models';
|
||||
import * as constants from './resources/constants';
|
||||
import { Messages } from './resources/messages';
|
||||
import { telemetryHelper, Result } from './helper/telemetryHelper';
|
||||
import { TelemetryKeys } from './resources/telemetryKeys';
|
||||
|
||||
export async function browsePipeline(node: AzureTreeItem): Promise<void> {
|
||||
await telemetryHelper.executeFunctionWithTimeTelemetry(async () => {
|
||||
try {
|
||||
if (!!node && !!node.fullId) {
|
||||
let parsedAzureResourceId: ParsedAzureResourceId = new ParsedAzureResourceId(node.fullId);
|
||||
let session: AzureSession = getSubscriptionSession(parsedAzureResourceId.subscriptionId);
|
||||
let appServiceClient = new AppServiceClient(session.credentials, session.tenantId, session.environment.portalUrl, parsedAzureResourceId.subscriptionId);
|
||||
let siteConfig = await appServiceClient.getAppServiceConfig(node.fullId);
|
||||
telemetryHelper.setTelemetry(TelemetryKeys.ScmType, siteConfig.scmType);
|
||||
let controlProvider = new ControlProvider();
|
||||
|
||||
if (siteConfig.scmType.toLowerCase() === ScmType.VSTSRM.toLowerCase()) {
|
||||
let pipelineUrl = await appServiceClient.getAzurePipelineUrl(node.fullId);
|
||||
vscode.env.openExternal(vscode.Uri.parse(pipelineUrl));
|
||||
telemetryHelper.setTelemetry(TelemetryKeys.BrowsedExistingPipeline, 'true');
|
||||
}
|
||||
else if (siteConfig.scmType === '' || siteConfig.scmType.toLowerCase() === ScmType.NONE.toLowerCase()) {
|
||||
let result = await controlProvider.showInformationBox(
|
||||
constants.BrowseNotAvailableConfigurePipeline,
|
||||
Messages.browseNotAvailableConfigurePipeline,
|
||||
'Configure Pipeline');
|
||||
|
||||
if (result === 'Configure Pipeline') {
|
||||
vscode.commands.executeCommand('azure-pipelines.configure-pipeline', node);
|
||||
telemetryHelper.setTelemetry(TelemetryKeys.ClickedConfigurePipeline, 'true');
|
||||
}
|
||||
}
|
||||
else {
|
||||
let deploymentCenterUrl: string = await appServiceClient.getDeploymentCenterUrl(node.fullId);
|
||||
await vscode.env.openExternal(vscode.Uri.parse(deploymentCenterUrl));
|
||||
telemetryHelper.setTelemetry(TelemetryKeys.BrowsedDeploymentCenter, 'true');
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error(Messages.didNotRecieveAzureResourceNodeToProcess);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
if (!(error instanceof UserCancelledError)) {
|
||||
extensionVariables.outputChannel.appendLine(error.message);
|
||||
vscode.window.showErrorMessage(error.message);
|
||||
telemetryHelper.setResult(Result.Failed, error);
|
||||
}
|
||||
else {
|
||||
telemetryHelper.setResult(Result.Canceled, error);
|
||||
}
|
||||
}
|
||||
}, TelemetryKeys.CommandExecutionDuration);
|
||||
}
|
|
@ -5,7 +5,7 @@ import { AzureDevOpsBaseUrl, ReservedHostNames } from '../../resources/constants
|
|||
import { RestClient } from '../restClient';
|
||||
import { ServiceClientCredentials, UrlBasedRequestPrepareOptions } from 'ms-rest';
|
||||
import { sleepForMilliSeconds, stringCompareFunction } from "../../helper/commonHelper";
|
||||
import { telemetryHelper } from '../../helper/telemetryHelper';
|
||||
import { telemetryHelper } from '../../../helpers/telemetryHelper';
|
||||
import * as Q from 'q';
|
||||
import * as util from 'util';
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ const uuid = require('uuid/v4');
|
|||
import { AppServiceClient } from './clients/azure/appServiceClient';
|
||||
import { AzureDevOpsClient } from './clients/devOps/azureDevOpsClient';
|
||||
import { AzureDevOpsHelper } from './helper/devOps/azureDevOpsHelper';
|
||||
import { AzureTreeItem, UserCancelledError } from 'vscode-azureextensionui';
|
||||
import { generateDevOpsProjectName, generateDevOpsOrganizationName } from './helper/commonHelper';
|
||||
import { GenericResource } from 'azure-arm-resource/lib/resource/models';
|
||||
import { GraphHelper } from './helper/graphHelper';
|
||||
|
@ -11,55 +10,39 @@ import { Messages } from './resources/messages';
|
|||
import { ServiceConnectionHelper } from './helper/devOps/serviceConnectionHelper';
|
||||
import { SourceOptions, RepositoryProvider, extensionVariables, WizardInputs, WebAppKind, PipelineTemplate, QuickPickItemWithData, GitRepositoryParameters, GitBranchDetails, TargetResourceType } from './model/models';
|
||||
import { TracePoints } from './resources/tracePoints';
|
||||
import { TelemetryKeys } from './resources/telemetryKeys';
|
||||
import { TelemetryKeys } from '../helpers/telemetryKeys';
|
||||
import * as constants from './resources/constants';
|
||||
import * as path from 'path';
|
||||
import * as templateHelper from './helper/templateHelper';
|
||||
import * as utils from 'util';
|
||||
import * as vscode from 'vscode';
|
||||
import { Result, telemetryHelper } from './helper/telemetryHelper';
|
||||
import { telemetryHelper } from '../helpers/telemetryHelper';
|
||||
import { ControlProvider } from './helper/controlProvider';
|
||||
import { GitHubProvider } from './helper/gitHubHelper';
|
||||
import { getSubscriptionSession } from './helper/azureSessionHelper';
|
||||
import {Build} from './model/azureDevOps';
|
||||
import { Build } from './model/azureDevOps';
|
||||
import { UserCancelledError } from './helper/userCancelledError';
|
||||
|
||||
const Layer: string = 'configure';
|
||||
|
||||
export async function configurePipeline(node: AzureTreeItem) {
|
||||
await telemetryHelper.executeFunctionWithTimeTelemetry(async () => {
|
||||
try {
|
||||
if (!(await extensionVariables.azureAccountExtensionApi.waitForLogin())) {
|
||||
// set telemetry
|
||||
telemetryHelper.setTelemetry(TelemetryKeys.AzureLoginRequired, 'true');
|
||||
export async function configurePipeline() {
|
||||
if (!(await extensionVariables.azureAccountExtensionApi.waitForLogin())) {
|
||||
telemetryHelper.setTelemetry(TelemetryKeys.AzureLoginRequired, 'true');
|
||||
|
||||
let signIn = await vscode.window.showInformationMessage(Messages.azureLoginRequired, Messages.signInLabel);
|
||||
if (signIn && signIn.toLowerCase() === Messages.signInLabel.toLowerCase()) {
|
||||
await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: Messages.waitForAzureSignIn },
|
||||
async () => {
|
||||
await vscode.commands.executeCommand("azure-account.login");
|
||||
});
|
||||
}
|
||||
else {
|
||||
let error = new Error(Messages.azureLoginRequired);
|
||||
telemetryHelper.setResult(Result.Failed, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
let signIn = await vscode.window.showInformationMessage(Messages.azureLoginRequired, Messages.signInLabel);
|
||||
if (signIn && signIn.toLowerCase() === Messages.signInLabel.toLowerCase()) {
|
||||
await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: Messages.waitForAzureSignIn },
|
||||
async () => {
|
||||
await vscode.commands.executeCommand("azure-account.login");
|
||||
});
|
||||
}
|
||||
else {
|
||||
throw new Error(Messages.azureLoginRequired);
|
||||
}
|
||||
}
|
||||
|
||||
var configurer = new PipelineConfigurer();
|
||||
await configurer.configure(node);
|
||||
}
|
||||
catch (error) {
|
||||
if (!(error instanceof UserCancelledError)) {
|
||||
extensionVariables.outputChannel.appendLine(error.message);
|
||||
vscode.window.showErrorMessage(error.message);
|
||||
telemetryHelper.setResult(Result.Failed, error);
|
||||
}
|
||||
else {
|
||||
telemetryHelper.setResult(Result.Canceled, error);
|
||||
}
|
||||
}
|
||||
}, TelemetryKeys.CommandExecutionDuration);
|
||||
const configurer = new PipelineConfigurer();
|
||||
await configurer.configure();
|
||||
}
|
||||
|
||||
class PipelineConfigurer {
|
||||
|
@ -79,9 +62,9 @@ class PipelineConfigurer {
|
|||
this.controlProvider = new ControlProvider();
|
||||
}
|
||||
|
||||
public async configure(node: any) {
|
||||
public async configure() {
|
||||
telemetryHelper.setCurrentStep('GetAllRequiredInputs');
|
||||
await this.getAllRequiredInputs(node);
|
||||
await this.getAllRequiredInputs();
|
||||
|
||||
telemetryHelper.setCurrentStep('CreatePreRequisites');
|
||||
await this.createPreRequisites();
|
||||
|
@ -116,8 +99,7 @@ class PipelineConfigurer {
|
|||
});
|
||||
}
|
||||
|
||||
private async getAllRequiredInputs(node: any) {
|
||||
await this.analyzeNode(node);
|
||||
private async getAllRequiredInputs() {
|
||||
await this.getSourceRepositoryDetails();
|
||||
await this.getSelectedPipeline();
|
||||
|
||||
|
@ -171,16 +153,6 @@ class PipelineConfigurer {
|
|||
}
|
||||
}
|
||||
|
||||
private async analyzeNode(node: any): Promise<void> {
|
||||
if (!!node && !!node.fullId) {
|
||||
await this.extractAzureResourceFromNode(node);
|
||||
}
|
||||
else if (node && node.fsPath) {
|
||||
this.workspacePath = node.fsPath;
|
||||
telemetryHelper.setTelemetry(TelemetryKeys.SourceRepoLocation, SourceOptions.CurrentWorkspace);
|
||||
}
|
||||
}
|
||||
|
||||
private async getSourceRepositoryDetails(): Promise<void> {
|
||||
try {
|
||||
if (!this.workspacePath) { // This is to handle when we have already identified the repository details.
|
||||
|
@ -325,37 +297,6 @@ class PipelineConfigurer {
|
|||
return githubPat;
|
||||
}
|
||||
|
||||
private async extractAzureResourceFromNode(node: any): Promise<void> {
|
||||
this.inputs.targetResource.subscriptionId = node.root.subscriptionId;
|
||||
this.inputs.azureSession = getSubscriptionSession(this.inputs.targetResource.subscriptionId);
|
||||
this.appServiceClient = new AppServiceClient(this.inputs.azureSession.credentials, this.inputs.azureSession.tenantId, this.inputs.azureSession.environment.portalUrl, this.inputs.targetResource.subscriptionId);
|
||||
|
||||
try {
|
||||
let azureResource: GenericResource = await this.appServiceClient.getAppServiceResource((<AzureTreeItem>node).fullId);
|
||||
|
||||
switch (azureResource.type ? azureResource.type.toLowerCase() : '') {
|
||||
case 'Microsoft.Web/sites'.toLowerCase():
|
||||
switch (azureResource.kind ? azureResource.kind.toLowerCase() : '') {
|
||||
case WebAppKind.WindowsApp:
|
||||
this.inputs.targetResource.resource = azureResource;
|
||||
break;
|
||||
case WebAppKind.FunctionApp:
|
||||
case WebAppKind.LinuxApp:
|
||||
case WebAppKind.LinuxContainerApp:
|
||||
default:
|
||||
throw new Error(utils.format(Messages.appKindIsNotSupported, azureResource.kind));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error(utils.format(Messages.resourceTypeIsNotSupported, azureResource.type));
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
telemetryHelper.logError(Layer, TracePoints.ExtractAzureResourceFromNodeFailed, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async getAzureDevOpsDetails(): Promise<void> {
|
||||
try {
|
||||
this.createAzureDevOpsClient();
|
||||
|
@ -451,10 +392,10 @@ class PipelineConfigurer {
|
|||
let selectedSubscription: QuickPickItemWithData = await this.controlProvider.showQuickPick(constants.SelectSubscription, subscriptionList, { placeHolder: Messages.selectSubscription });
|
||||
this.inputs.targetResource.subscriptionId = selectedSubscription.data.subscription.subscriptionId;
|
||||
this.inputs.azureSession = getSubscriptionSession(this.inputs.targetResource.subscriptionId);
|
||||
|
||||
|
||||
// show available resources and get the chosen one
|
||||
this.appServiceClient = new AppServiceClient(this.inputs.azureSession.credentials, this.inputs.azureSession.tenantId, this.inputs.azureSession.environment.portalUrl, this.inputs.targetResource.subscriptionId);
|
||||
|
||||
|
||||
let resourceArray: Promise<Array<{label: string, data: GenericResource}>> = null;
|
||||
let selectAppText: string = "";
|
||||
let placeHolderText: string = "";
|
||||
|
@ -474,7 +415,7 @@ class PipelineConfigurer {
|
|||
resourceArray,
|
||||
{ placeHolder: placeHolderText },
|
||||
TelemetryKeys.WebAppListCount);
|
||||
|
||||
|
||||
this.inputs.targetResource.resource = selectedResource.data;
|
||||
} else if(subscriptionList.length > 0 ) {
|
||||
this.inputs.targetResource.subscriptionId = subscriptionList[0].data.subscription.subscriptionId;
|
||||
|
@ -623,7 +564,7 @@ class PipelineConfigurer {
|
|||
}
|
||||
else {
|
||||
telemetryHelper.setTelemetry(TelemetryKeys.PipelineDiscarded, 'true');
|
||||
throw new UserCancelledError(Messages.operationCancelled);
|
||||
throw new UserCancelledError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ import * as vscode from 'vscode';
|
|||
import { RemoteWithoutRefs } from 'simple-git/typings/response';
|
||||
import {AzureDevOpsHelper} from './devOps/azureDevOpsHelper';
|
||||
import {GitHubProvider} from './gitHubHelper';
|
||||
import { telemetryHelper } from "./telemetryHelper";
|
||||
import { TelemetryKeys } from "../resources/telemetryKeys";
|
||||
import { telemetryHelper } from "../../helpers/telemetryHelper";
|
||||
import { TelemetryKeys } from "../../helpers/telemetryKeys";
|
||||
|
||||
export class LocalGitRepoHelper {
|
||||
private gitReference: git.SimpleGit;
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
import { InputBoxOptions, QuickPickItem, window } from 'vscode';
|
||||
import { IAzureQuickPickOptions, UserCancelledError } from 'vscode-azureextensionui';
|
||||
import { telemetryHelper } from '../helper/telemetryHelper';
|
||||
import { extensionVariables } from '../model/models';
|
||||
import {Messages} from '../resources/messages';
|
||||
import { TelemetryKeys } from '../resources/telemetryKeys';
|
||||
import { InputBoxOptions, QuickPickItem, QuickPickOptions, window } from 'vscode';
|
||||
import { telemetryHelper } from '../../helpers/telemetryHelper';
|
||||
import { TelemetryKeys } from '../../helpers/telemetryKeys';
|
||||
import { UserCancelledError } from './userCancelledError';
|
||||
|
||||
export class ControlProvider {
|
||||
public async showQuickPick<T extends QuickPickItem>(listName: string, listItems: T[] | Thenable<T[]>, options: IAzureQuickPickOptions, itemCountTelemetryKey?: string): Promise<T> {
|
||||
public async showQuickPick<T extends QuickPickItem>(listName: string, listItems: T[] | Thenable<T[]>, options: QuickPickOptions, itemCountTelemetryKey?: string): Promise<T> {
|
||||
try {
|
||||
telemetryHelper.setTelemetry(TelemetryKeys.CurrentUserInput, listName);
|
||||
return await extensionVariables.ui.showQuickPick(listItems, options);
|
||||
return window.showQuickPick(listItems, options);
|
||||
}
|
||||
finally {
|
||||
if (itemCountTelemetryKey) {
|
||||
|
@ -20,7 +18,7 @@ export class ControlProvider {
|
|||
|
||||
public async showInputBox(inputName: string, options: InputBoxOptions): Promise<string> {
|
||||
telemetryHelper.setTelemetry(TelemetryKeys.CurrentUserInput, inputName);
|
||||
return await extensionVariables.ui.showInputBox(options);
|
||||
return window.showInputBox(options);
|
||||
}
|
||||
|
||||
public async showInformationBox(informationIdentifier: string, informationMessage: string, ...actions: string[]): Promise<string> {
|
||||
|
@ -28,13 +26,13 @@ export class ControlProvider {
|
|||
if (!!actions && actions.length > 0) {
|
||||
let result = await window.showInformationMessage(informationMessage, ...actions);
|
||||
if (!result) {
|
||||
throw new UserCancelledError(Messages.userCancelledExcecption);
|
||||
throw new UserCancelledError();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return await window.showInformationMessage(informationMessage, ...actions);
|
||||
return window.showInformationMessage(informationMessage, ...actions);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { AzureDevOpsClient } from '../../clients/devOps/azureDevOpsClient';
|
|||
import { BuildDefinition, BuildDefinitionRepositoryProperties, Build } from '../../model/azureDevOps';
|
||||
import { HostedVS2017QueueName } from '../../resources/constants';
|
||||
import { Messages } from '../../resources/messages';
|
||||
import { telemetryHelper } from '../telemetryHelper';
|
||||
import { telemetryHelper } from '../../../helpers/telemetryHelper';
|
||||
import { TracePoints } from '../../resources/tracePoints';
|
||||
import { WizardInputs, RepositoryProvider } from '../../model/models';
|
||||
import * as util from 'util';
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
import { IActionContext, ITelemetryReporter, parseError } from "vscode-azureextensionui";
|
||||
|
||||
import { extensionVariables } from "../model/models";
|
||||
import { TelemetryKeys } from '../resources/telemetryKeys';
|
||||
import * as logger from '../../logger';
|
||||
|
||||
const uuid = require('uuid/v4');
|
||||
|
||||
class TelemetryHelper {
|
||||
private actionContext: IActionContext;
|
||||
private telemetryReporter: ITelemetryReporter;
|
||||
private journeyId: string;
|
||||
private command: string;
|
||||
|
||||
public initialize(actionContext: IActionContext, command: string): void {
|
||||
this.actionContext = actionContext;
|
||||
this.telemetryReporter = extensionVariables.reporter;
|
||||
this.journeyId = uuid();
|
||||
this.command = command;
|
||||
this.setTelemetry(TelemetryKeys.JourneyId, this.journeyId);
|
||||
}
|
||||
|
||||
public getJourneyId(): string {
|
||||
return this.journeyId;
|
||||
}
|
||||
|
||||
public setTelemetry(key: string, value: string): void {
|
||||
if (key) {
|
||||
this.actionContext.telemetry.properties[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public setResult(result: Result, error?: Error): void {
|
||||
this.actionContext.telemetry.properties.result = result;
|
||||
if (error) {
|
||||
let parsedError = parseError(error);
|
||||
this.actionContext.telemetry.properties.error = JSON.stringify(parsedError);
|
||||
this.actionContext.telemetry.properties.errorMessage = parsedError.message;
|
||||
}
|
||||
}
|
||||
|
||||
public setCurrentStep(stepName: string): void {
|
||||
this.actionContext.telemetry.properties.cancelStep = stepName;
|
||||
}
|
||||
|
||||
public logError(layer: string, tracePoint: string, error: Error): void {
|
||||
let parsedError = parseError(error);
|
||||
this.telemetryReporter.sendTelemetryEvent(
|
||||
tracePoint,
|
||||
{
|
||||
'journeyId': this.journeyId,
|
||||
'command': this.command,
|
||||
'layer': layer,
|
||||
'error': JSON.stringify(parsedError)
|
||||
});
|
||||
|
||||
logger.log(JSON.stringify(parsedError));
|
||||
}
|
||||
|
||||
public logInfo(layer: string, tracePoint: string, info: string): void {
|
||||
this.telemetryReporter.sendTelemetryEvent(
|
||||
tracePoint,
|
||||
{
|
||||
'journeyId': this.journeyId,
|
||||
'command': this.command,
|
||||
'layer': layer,
|
||||
'info': info
|
||||
});
|
||||
}
|
||||
|
||||
public async executeFunctionWithTimeTelemetry<T>(callback: () => T, telemetryKey: string): Promise<T> {
|
||||
let startTime = Date.now();
|
||||
try {
|
||||
return await callback();
|
||||
}
|
||||
finally {
|
||||
this.setTelemetry(telemetryKey, ((Date.now() - startTime) / 1000).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
export let telemetryHelper = new TelemetryHelper();
|
||||
|
||||
export enum Result {
|
||||
'Succeeded' = 'Succeeded',
|
||||
'Failed' = 'Failed',
|
||||
'Canceled' = 'Canceled'
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// https://github.com/microsoft/vscode-azuretools/blob/5999c2ad4423e86f22d2c648027242d8816a50e4/ui/src/errors.ts
|
||||
// minus localization
|
||||
|
||||
export class UserCancelledError extends Error {
|
||||
constructor() {
|
||||
super('Operation cancelled.');
|
||||
}
|
||||
}
|
|
@ -1,18 +1,13 @@
|
|||
import { AzureEnvironment } from 'ms-rest-azure';
|
||||
import { GenericResource } from 'azure-arm-resource/lib/resource/models';
|
||||
import { OutputChannel, ExtensionContext, QuickPickItem } from 'vscode';
|
||||
import { OutputChannel, QuickPickItem, window } from 'vscode';
|
||||
import { ServiceClientCredentials } from 'ms-rest';
|
||||
import { SubscriptionModels } from 'azure-arm-resource';
|
||||
import { UIExtensionVariables, IAzureUserInput, ITelemetryReporter } from 'vscode-azureextensionui';
|
||||
import { Messages } from '../resources/messages';
|
||||
|
||||
class ExtensionVariables implements UIExtensionVariables {
|
||||
class ExtensionVariables {
|
||||
public azureAccountExtensionApi: AzureAccountExtensionExports;
|
||||
|
||||
public context: ExtensionContext;
|
||||
public outputChannel: OutputChannel;
|
||||
public reporter: ITelemetryReporter;
|
||||
public ui: IAzureUserInput;
|
||||
public outputChannel: OutputChannel = window.createOutputChannel('Azure Pipelines');
|
||||
}
|
||||
|
||||
let extensionVariables = new ExtensionVariables();
|
||||
|
|
|
@ -29,7 +29,6 @@ export class Messages {
|
|||
public static notAGitRepository: string = 'Selected workspace is not a [Git](https://git-scm.com/docs/git) repository. Please select a Git repository.';
|
||||
public static notAzureRepoUrl: string = 'The repo isn\'t hosted with Azure Repos.';
|
||||
public static noWorkSpaceSelectedError: string = 'Please select a workspace folder to configure pipeline.';
|
||||
public static operationCancelled: string = 'Operation cancelled.';
|
||||
public static operationTimedOut: string = 'Operation timed out.';
|
||||
public static organizationNameReservedMessage: string = 'The organization name %s isn\'t available. Please try another organization name.';
|
||||
public static organizationNameStaticValidationMessage: string = 'Organization names must start and end with a letter or number and can contain only letters, numbers, and hyphens.';
|
||||
|
@ -52,11 +51,8 @@ export class Messages {
|
|||
public static retryFailedMessage: string =`Failed after retrying: %s times. Internal Error: %s`;
|
||||
public static azureServicePrincipalFailedMessage: string =`Failed while creating Azure service principal.`;
|
||||
public static roleAssignmentFailedMessage: string =`Failed while role assignement.`;
|
||||
public static waitForAzureSignIn: string =`Waiting for Azure sign-in...`;
|
||||
public static userCancelledExcecption = 'User cancelled the action';
|
||||
public static waitForAzureSignIn: string = `Waiting for Azure sign-in...`;
|
||||
public static cannotFindPipelineUrlInMetaDataException = 'We were unable to find pipeline associated with the Azure Web App. Please click on "Browse Pipeline" to explore.';
|
||||
public static cannotFindOrganizationWithName = 'Unable to find organization with name: %s';
|
||||
public static browseNotAvailableConfigurePipeline = 'Unable to find a pipeline for this Azure Web App. Please click on "Configure Pipeline" to setup.';
|
||||
public static didNotRecieveAzureResourceNodeToProcess = 'Unable to browse the pipeline for you. Please raise an issue in the [repo](https://github.com/Microsoft/azure-pipelines-vscode/issues).';
|
||||
|
||||
}
|
||||
|
|
|
@ -5,50 +5,31 @@
|
|||
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import { createTelemetryReporter, callWithTelemetryAndErrorHandling, IActionContext, AzureUserInput, registerUIExtensionVariables } from 'vscode-azureextensionui';
|
||||
import * as languageclient from 'vscode-languageclient/node';
|
||||
|
||||
import { extensionVariables } from './configure/model/models';
|
||||
import * as logger from './logger';
|
||||
import { SchemaAssociationService, SchemaAssociationNotification } from './schema-association-service';
|
||||
import { schemaContributor, CUSTOM_SCHEMA_REQUEST, CUSTOM_CONTENT_REQUEST } from './schema-contributor';
|
||||
import { telemetryHelper } from './configure/helper/telemetryHelper';
|
||||
import { TelemetryKeys } from './configure/resources/telemetryKeys';
|
||||
import { telemetryHelper } from './helpers/telemetryHelper';
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext) {
|
||||
extensionVariables.reporter = createTelemetryReporter(context);
|
||||
registerUiVariables(context);
|
||||
|
||||
const configurePipelineEnabled = vscode.workspace.getConfiguration('azure-pipelines').get<boolean>('configure', true);
|
||||
await callWithTelemetryAndErrorHandling('azurePipelines.activate', async (activateContext: IActionContext) => {
|
||||
activateContext.telemetry.properties.isActivationEvent = 'true';
|
||||
telemetryHelper.initialize(activateContext, 'activate');
|
||||
telemetryHelper.setTelemetry('configurePipelineEnabled', `${configurePipelineEnabled}`);
|
||||
await telemetryHelper.executeFunctionWithTimeTelemetry(
|
||||
async () => {
|
||||
await activateYmlContributor(context);
|
||||
if (configurePipelineEnabled) {
|
||||
const { activateConfigurePipeline } = await import('./configure/activate');
|
||||
await activateConfigurePipeline();
|
||||
}
|
||||
},
|
||||
TelemetryKeys.ExtensionActivationDuration);
|
||||
telemetryHelper.initialize('azurePipelines.activate', {
|
||||
isActivationEvent: 'true',
|
||||
configurePipelineEnabled: `${configurePipelineEnabled}`,
|
||||
});
|
||||
await telemetryHelper.callWithTelemetryAndErrorHandling(async () => {
|
||||
await activateYmlContributor(context);
|
||||
if (configurePipelineEnabled) {
|
||||
const { activateConfigurePipeline } = await import('./configure/activate');
|
||||
await activateConfigurePipeline();
|
||||
}
|
||||
});
|
||||
|
||||
logger.log('Extension has been activated!', 'ExtensionActivated');
|
||||
return schemaContributor;
|
||||
}
|
||||
|
||||
function registerUiVariables(context: vscode.ExtensionContext) {
|
||||
// Register ui extension variables is required to be done for telemetry to start flowing for extension activation and other events.
|
||||
// It also facilitates registering command and called events telemetry.
|
||||
extensionVariables.outputChannel = vscode.window.createOutputChannel('Azure Pipelines');
|
||||
context.subscriptions.push(extensionVariables.outputChannel);
|
||||
extensionVariables.context = context;
|
||||
extensionVariables.ui = new AzureUserInput(context.globalState);
|
||||
registerUIExtensionVariables(extensionVariables);
|
||||
}
|
||||
|
||||
async function activateYmlContributor(context: vscode.ExtensionContext) {
|
||||
const serverOptions: languageclient.ServerOptions = getServerOptions(context);
|
||||
const clientOptions: languageclient.LanguageClientOptions = getClientOptions();
|
||||
|
@ -61,25 +42,23 @@ async function activateYmlContributor(context: vscode.ExtensionContext) {
|
|||
|
||||
const initialSchemaAssociations = schemaAssociationService.getSchemaAssociation();
|
||||
|
||||
await client.onReady().then(() => {
|
||||
// Notify the server which schemas to use.
|
||||
client.sendNotification(SchemaAssociationNotification.type, initialSchemaAssociations);
|
||||
// If this throws, the telemetry event in activate() will catch & log it
|
||||
await client.onReady();
|
||||
|
||||
// Fired whenever the server is about to validate a YAML file (e.g. on content change),
|
||||
// and allows us to return a custom schema to use for validation.
|
||||
client.onRequest(CUSTOM_SCHEMA_REQUEST, (resource: string) => {
|
||||
// TODO: Have a single instance for the extension but dont return a global from this namespace
|
||||
return schemaContributor.requestCustomSchema(resource);
|
||||
});
|
||||
// Notify the server which schemas to use.
|
||||
client.sendNotification(SchemaAssociationNotification.type, initialSchemaAssociations);
|
||||
|
||||
// Fired whenever the server encounters a URI scheme that it doesn't recognize,
|
||||
// and allows us to use the URI to determine the schema's content.
|
||||
client.onRequest(CUSTOM_CONTENT_REQUEST, (uri: string) => {
|
||||
return schemaContributor.requestCustomSchemaContent(uri);
|
||||
});
|
||||
}).catch((reason) => {
|
||||
logger.log(JSON.stringify(reason), 'ClientOnReadyError');
|
||||
extensionVariables.reporter.sendTelemetryEvent('extension.languageserver.onReadyError', { 'reason': JSON.stringify(reason) });
|
||||
// Fired whenever the server is about to validate a YAML file (e.g. on content change),
|
||||
// and allows us to return a custom schema to use for validation.
|
||||
client.onRequest(CUSTOM_SCHEMA_REQUEST, (resource: string) => {
|
||||
// TODO: Have a single instance for the extension but dont return a global from this namespace
|
||||
return schemaContributor.requestCustomSchema(resource);
|
||||
});
|
||||
|
||||
// Fired whenever the server encounters a URI scheme that it doesn't recognize,
|
||||
// and allows us to use the URI to determine the schema's content.
|
||||
client.onRequest(CUSTOM_CONTENT_REQUEST, (uri: string) => {
|
||||
return schemaContributor.requestCustomSchemaContent(uri);
|
||||
});
|
||||
|
||||
// TODO: Can we get rid of this since it's set in package.json?
|
||||
|
@ -125,4 +104,5 @@ function getClientOptions(): languageclient.LanguageClientOptions {
|
|||
|
||||
// this method is called when your extension is deactivated
|
||||
export function deactivate() {
|
||||
telemetryHelper.dispose();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,244 @@
|
|||
// Copied from https://github.com/microsoft/vscode-azuretools/blob/5999c2ad4423e86f22d2c648027242d8816a50e4/ui/src/parseError.ts
|
||||
// with inline IParsedError interface and no localization
|
||||
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as htmlToText from 'html-to-text';
|
||||
|
||||
export interface IParsedError {
|
||||
errorType: string;
|
||||
message: string;
|
||||
stack?: string;
|
||||
isUserCancelledError: boolean;
|
||||
}
|
||||
|
||||
// tslint:disable:no-unsafe-any
|
||||
// tslint:disable:no-any
|
||||
export function parseError(error: any): IParsedError {
|
||||
let errorType: string = '';
|
||||
let message: string = '';
|
||||
let stack: string | undefined;
|
||||
|
||||
if (typeof (error) === 'object' && error !== null) {
|
||||
if (error.constructor !== Object) {
|
||||
errorType = error.constructor.name;
|
||||
}
|
||||
|
||||
stack = getCallstack(error);
|
||||
errorType = getCode(error, errorType);
|
||||
|
||||
// See https://github.com/Microsoft/vscode-azureappservice/issues/419 for an example error that requires these 'unpack's
|
||||
error = unpackErrorFromField(error, 'value');
|
||||
error = unpackErrorFromField(error, '_value');
|
||||
error = unpackErrorFromField(error, 'error');
|
||||
error = unpackErrorFromField(error, 'error');
|
||||
if (Array.isArray(error.errors) && error.errors.length) {
|
||||
error = error.errors[0];
|
||||
}
|
||||
|
||||
errorType = getCode(error, errorType);
|
||||
message = getMessage(error, message);
|
||||
|
||||
if (!errorType || !message || /error.*deserializing.*response.*body/i.test(message)) {
|
||||
error = unpackErrorFromField(error, 'response');
|
||||
error = unpackErrorFromField(error, 'body');
|
||||
|
||||
errorType = getCode(error, errorType);
|
||||
message = getMessage(error, message);
|
||||
}
|
||||
|
||||
// Azure errors have a JSON object in the message
|
||||
let parsedMessage: any = parseIfJson(error.message);
|
||||
// For some reason, the message is sometimes serialized twice and we need to parse it again
|
||||
parsedMessage = parseIfJson(parsedMessage);
|
||||
// Extract out the "internal" error if it exists
|
||||
if (parsedMessage && parsedMessage.error) {
|
||||
parsedMessage = parsedMessage.error;
|
||||
}
|
||||
|
||||
errorType = getCode(parsedMessage, errorType);
|
||||
message = getMessage(parsedMessage, message);
|
||||
|
||||
message = message || convertCodeToError(errorType) || JSON.stringify(error);
|
||||
} else if (error !== undefined && error !== null && error.toString && error.toString().trim() !== '') {
|
||||
errorType = typeof (error);
|
||||
message = error.toString();
|
||||
}
|
||||
|
||||
message = unpackErrorsInMessage(message);
|
||||
|
||||
[message, errorType] = parseIfFileSystemError(message, errorType);
|
||||
|
||||
// tslint:disable-next-line:strict-boolean-expressions
|
||||
errorType = errorType || typeof (error);
|
||||
message = message || 'Unknown Error';
|
||||
|
||||
message = parseIfHtml(message);
|
||||
|
||||
// Azure storage SDK errors are presented in XML
|
||||
// https://github.com/Azure/azure-sdk-for-js/issues/6927
|
||||
message = parseIfXml(message);
|
||||
|
||||
return {
|
||||
errorType: errorType,
|
||||
message: message,
|
||||
stack: stack,
|
||||
// NOTE: Intentionally not using 'error instanceof UserCancelledError' because that doesn't work if multiple versions of the UI package are used in one extension
|
||||
// See https://github.com/Microsoft/vscode-azuretools/issues/51 for more info
|
||||
isUserCancelledError: errorType === 'UserCancelledError'
|
||||
};
|
||||
}
|
||||
|
||||
function convertCodeToError(errorType: string | undefined): string | undefined {
|
||||
if (errorType) {
|
||||
const code: number = parseInt(errorType, 10);
|
||||
if (!isNaN(code)) {
|
||||
return `Failed with code "${code}".`;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseIfJson(o: any): any {
|
||||
if (typeof o === 'string' && o.indexOf('{') >= 0) {
|
||||
try {
|
||||
return JSON.parse(o);
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
function parseIfHtml(message: string): string {
|
||||
if (/<html/i.test(message)) {
|
||||
try {
|
||||
return htmlToText.fromString(message, { wordwrap: false, uppercaseHeadings: false, ignoreImage: true });
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
function parseIfXml(message: string): string {
|
||||
const matches: RegExpMatchArray | null = message.match(/<Message>(.*)<\/Message>/si);
|
||||
if (matches) {
|
||||
return matches[1];
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
function getMessage(o: any, defaultMessage: string): string {
|
||||
return (o && (o.message || o.Message || o.detail || (typeof parseIfJson(o.body) === 'string' && o.body))) || defaultMessage;
|
||||
}
|
||||
|
||||
function getCode(o: any, defaultCode: string): string {
|
||||
const code: any = o && (o.code || o.Code || o.errorCode || o.statusCode);
|
||||
return code ? String(code) : defaultCode;
|
||||
}
|
||||
|
||||
function unpackErrorsInMessage(message: string): string {
|
||||
// Handle messages like this from Azure (just handle first error for now)
|
||||
// ["Errors":["The offer should have valid throughput]]",
|
||||
if (message) {
|
||||
const errorsInMessage: RegExpMatchArray | null = message.match(/"Errors":\[\s*"([^"]+)"/);
|
||||
if (errorsInMessage !== null) {
|
||||
const [, firstError] = errorsInMessage;
|
||||
return firstError;
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
function unpackErrorFromField(error: any, prop: string): any {
|
||||
// Handle objects from Azure SDK that contain the error information in a "body" field (serialized or not)
|
||||
let field: any = error && error[prop];
|
||||
if (field) {
|
||||
if (typeof field === 'string' && field.indexOf('{') >= 0) {
|
||||
try {
|
||||
field = JSON.parse(field);
|
||||
} catch (err) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof field === 'object') {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Example line in the stack:
|
||||
* at FileService.StorageServiceClient._processResponse (/path/ms-azuretools.vscode-azurestorage-0.6.0/node_modules/azure-storage/lib/common/services/storageserviceclient.js:751:50)
|
||||
*
|
||||
* Final minified line:
|
||||
* FileService.StorageServiceClient._processResponse azure-storage/storageserviceclient.js:751:50
|
||||
*/
|
||||
function getCallstack(error: { stack?: string }): string | undefined {
|
||||
// tslint:disable-next-line: strict-boolean-expressions
|
||||
const stack: string = error.stack || '';
|
||||
|
||||
const minifiedLines: (string | undefined)[] = stack
|
||||
.split(/(\r\n|\n)/g) // split by line ending
|
||||
.map(l => {
|
||||
let result: string = '';
|
||||
// Get just the file name, line number and column number
|
||||
// From above example: storageserviceclient.js:751:50
|
||||
const fileMatch: RegExpMatchArray | null = l.match(/[^\/\\\(\s]+\.(t|j)s:[0-9]+:[0-9]+/i);
|
||||
|
||||
// Ignore any lines without a file match (e.g. "at Generator.next (<anonymous>)")
|
||||
if (fileMatch) {
|
||||
// Get the function name
|
||||
// From above example: FileService.StorageServiceClient._processResponse
|
||||
const functionMatch: RegExpMatchArray | null = l.match(/^[\s]*at ([^\(\\\/]+(?:\\|\/)?)+/i);
|
||||
if (functionMatch) {
|
||||
result += functionMatch[1];
|
||||
}
|
||||
|
||||
const parts: string[] = [];
|
||||
|
||||
// Get the name of the node module (and any sub modules) containing the file
|
||||
// From above example: azure-storage
|
||||
const moduleRegExp: RegExp = /node_modules(?:\\|\/)([^\\\/]+)/ig;
|
||||
let moduleMatch: RegExpExecArray | null;
|
||||
do {
|
||||
moduleMatch = moduleRegExp.exec(l);
|
||||
if (moduleMatch) {
|
||||
parts.push(moduleMatch[1]);
|
||||
}
|
||||
} while (moduleMatch);
|
||||
|
||||
parts.push(fileMatch[0]);
|
||||
result += parts.join('/');
|
||||
}
|
||||
|
||||
return result;
|
||||
})
|
||||
.filter(l => !!l);
|
||||
|
||||
return minifiedLines.length > 0 ? minifiedLines.join('\n') : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* See https://github.com/microsoft/vscode-cosmosdb/issues/1580 for an example error
|
||||
*/
|
||||
function parseIfFileSystemError(message: string, errorType: string): [string, string] {
|
||||
const match: RegExpMatchArray | null = message.match(/\((([a-z]*) \(FileSystemError\).*)\)$/i);
|
||||
if (match) {
|
||||
message = match[1];
|
||||
errorType = match[2];
|
||||
}
|
||||
return [message, errorType];
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
import * as vscode from 'vscode';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
|
||||
import { TelemetryKeys } from './telemetryKeys';
|
||||
import * as logger from '../logger';
|
||||
import { parseError } from './parseError';
|
||||
|
||||
const uuid = require('uuid/v4');
|
||||
|
||||
const extensionName = 'ms-azure-devops.azure-pipelines';
|
||||
const packageJSON = vscode.extensions.getExtension(extensionName).packageJSON;
|
||||
const extensionVersion = packageJSON.version;
|
||||
const aiKey = packageJSON.aiKey;
|
||||
|
||||
interface TelemetryProperties {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
interface TelemetryOptions {
|
||||
suppressIfSuccessful: boolean;
|
||||
}
|
||||
|
||||
class TelemetryHelper {
|
||||
private journeyId: string;
|
||||
private command: string;
|
||||
private properties: TelemetryProperties;
|
||||
private options: TelemetryOptions;
|
||||
|
||||
private static reporter = new TelemetryReporter(extensionName, extensionVersion, aiKey);
|
||||
|
||||
public initialize(command: string, properties: TelemetryProperties = {}) {
|
||||
this.journeyId = uuid();
|
||||
this.command = command;
|
||||
this.properties = properties;
|
||||
this.options = {
|
||||
suppressIfSuccessful: false,
|
||||
};
|
||||
this.setTelemetry(TelemetryKeys.JourneyId, this.journeyId);
|
||||
this.setTelemetry(TelemetryKeys.Result, Result.Succeeded);
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
TelemetryHelper.reporter.dispose();
|
||||
}
|
||||
|
||||
public getJourneyId(): string {
|
||||
return this.journeyId;
|
||||
}
|
||||
|
||||
public setOptions(options: Partial<TelemetryOptions>): void {
|
||||
this.options = {
|
||||
...this.options,
|
||||
...options,
|
||||
};
|
||||
}
|
||||
|
||||
public setTelemetry(key: string, value: string): void {
|
||||
this.properties[key] = value;
|
||||
}
|
||||
|
||||
public setCurrentStep(stepName: string): void {
|
||||
this.properties.cancelStep = stepName;
|
||||
}
|
||||
|
||||
// Log an error.
|
||||
// No custom properties are logged alongside the error.
|
||||
// FIXME: This should really be sendTelemetryException but I'm maintaining
|
||||
// backwards-compatibility with how it used to be sent, especially because
|
||||
// I don't have access to the Application Insights logs :D (winstonliu).
|
||||
public logError(layer: string, tracePoint: string, error: Error): void {
|
||||
TelemetryHelper.reporter.sendTelemetryErrorEvent(
|
||||
tracePoint, {
|
||||
[TelemetryKeys.JourneyId]: this.journeyId,
|
||||
'command': this.command,
|
||||
'layer': layer,
|
||||
'errorMessage': error.message,
|
||||
'stack': error.stack ?? '',
|
||||
}, undefined, ['errorMesage', 'stack']);
|
||||
}
|
||||
|
||||
// Log an informational message.
|
||||
// No custom properties are logged alongside the message.
|
||||
public logInfo(layer: string, tracePoint: string, info: string): void {
|
||||
TelemetryHelper.reporter.sendTelemetryEvent(
|
||||
tracePoint, {
|
||||
[TelemetryKeys.JourneyId]: this.journeyId,
|
||||
'command': this.command,
|
||||
'layer': layer,
|
||||
'info': info
|
||||
});
|
||||
}
|
||||
|
||||
// Executes the given function, timing how long it takes.
|
||||
// This *does NOT* send any telemetry and must be called within the context
|
||||
// of an ongoing `callWithTelemetryAndErrorHandling` session to do anything useful.
|
||||
// Helpful for reporting fine-grained timing of individual functions.
|
||||
// TODO: Rename to something with less potential for confusion, like 'time' or 'timeFunction'?
|
||||
public async executeFunctionWithTimeTelemetry<T>(callback: () => Promise<T>, telemetryKey: string): Promise<T> {
|
||||
const startTime = Date.now();
|
||||
try {
|
||||
return await callback();
|
||||
}
|
||||
finally {
|
||||
this.setTelemetry(telemetryKey, ((Date.now() - startTime) / 1000).toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Wraps the given function in a telemetry event.
|
||||
// The telemetry event sent ater function execution will contain how long the function took as well as any custom properties
|
||||
// supplied through initialize() or setTelemetry().
|
||||
// If the function errors, the telemetry event will additionally contain metadata about the error that occurred.
|
||||
// https://github.com/microsoft/vscode-azuretools/blob/5999c2ad4423e86f22d2c648027242d8816a50e4/ui/src/callWithTelemetryAndErrorHandling.ts
|
||||
public async callWithTelemetryAndErrorHandling<T>(callback: () => Promise<T>): Promise<T | void> {
|
||||
try {
|
||||
return await this.executeFunctionWithTimeTelemetry(callback, 'duration');
|
||||
} catch (error) {
|
||||
const parsedError = parseError(error);
|
||||
if (parsedError.isUserCancelledError) {
|
||||
this.setTelemetry(TelemetryKeys.Result, Result.Canceled);
|
||||
} else {
|
||||
this.setTelemetry(TelemetryKeys.Result, Result.Failed);
|
||||
this.setTelemetry('error', parsedError.errorType);
|
||||
this.setTelemetry('errorMessage', parsedError.message);
|
||||
this.setTelemetry('stack', parsedError.stack ?? '');
|
||||
if (this.options.suppressIfSuccessful) {
|
||||
this.setTelemetry('suppressTelemetry', 'true');
|
||||
}
|
||||
|
||||
logger.log(parsedError.message);
|
||||
if (parsedError.message.includes('\n')) {
|
||||
vscode.window.showErrorMessage('An error has occurred. Check the output window for more details.');
|
||||
} else {
|
||||
vscode.window.showErrorMessage(parsedError.message);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (this.properties.result === Result.Failed) {
|
||||
TelemetryHelper.reporter.sendTelemetryErrorEvent(
|
||||
this.command, {
|
||||
...this.properties,
|
||||
[TelemetryKeys.JourneyId]: this.journeyId,
|
||||
}, undefined, ['error', 'errorMesage', 'stack']);
|
||||
} else if (!(this.options.suppressIfSuccessful && this.properties.result === Result.Succeeded)) {
|
||||
TelemetryHelper.reporter.sendTelemetryEvent(
|
||||
this.command, {
|
||||
...this.properties,
|
||||
[TelemetryKeys.JourneyId]: this.journeyId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const telemetryHelper = new TelemetryHelper();
|
||||
|
||||
enum Result {
|
||||
'Succeeded' = 'Succeeded',
|
||||
'Failed' = 'Failed',
|
||||
'Canceled' = 'Canceled'
|
||||
}
|
|
@ -3,6 +3,7 @@ export class TelemetryKeys {
|
|||
public static RepoProvider: string = 'repoProvider';
|
||||
public static AzureLoginRequired: string = 'azureLoginRequired';
|
||||
public static JourneyId: string = 'journeyId';
|
||||
public static Result: string = 'result';
|
||||
public static SourceRepoLocation: string = 'sourceRepoLocation';
|
||||
public static NewOrganization: string = 'newOrganization';
|
||||
public static ChosenTemplate: string = 'chosenTemplate';
|
||||
|
@ -14,10 +15,6 @@ export class TelemetryKeys {
|
|||
public static BrowsedDeploymentCenter = 'openedDeploymentCenter';
|
||||
public static BrowsedExistingPipeline = 'browsedExistingPipeline';
|
||||
public static ClickedConfigurePipeline = 'clickedConfigurePipeline';
|
||||
|
||||
// Durations
|
||||
public static ExtensionActivationDuration = 'extensionActivationDuration';
|
||||
public static CommandExecutionDuration = 'commandExecutionDuration';
|
||||
public static GitHubPatDuration = 'gitHubPatDuration';
|
||||
|
||||
// Count of drop down items
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import Uri from 'vscode-uri'
|
||||
import { URI } from 'vscode-uri';
|
||||
|
||||
interface SchemaContributorProvider {
|
||||
readonly requestSchema: (resource: string) => string;
|
||||
|
@ -75,10 +75,10 @@ class SchemaContributor {
|
|||
*/
|
||||
public requestCustomSchemaContent(uri: string): string {
|
||||
if (uri) {
|
||||
let _uri = Uri.parse(uri);
|
||||
if (_uri.scheme && this._customSchemaContributors[_uri.scheme] &&
|
||||
this._customSchemaContributors[_uri.scheme].requestSchemaContent) {
|
||||
return this._customSchemaContributors[_uri.scheme].requestSchemaContent(uri);
|
||||
const { scheme } = URI.parse(uri);
|
||||
if (scheme && this._customSchemaContributors[scheme] &&
|
||||
this._customSchemaContributors[scheme].requestSchemaContent) {
|
||||
return this._customSchemaContributors[scheme].requestSchemaContent(uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"alwaysStrict": true,
|
||||
|
||||
/* List of library files to be included in the compilation. */
|
||||
"lib": [ "es6" ],
|
||||
"lib": [ "es2019" ],
|
||||
|
||||
/* Specify module code generation. */
|
||||
"module": "commonjs",
|
||||
|
@ -45,10 +45,10 @@
|
|||
//"strict": true,
|
||||
|
||||
/* Specify ECMAScript target version. */
|
||||
"target": "es6",
|
||||
"target": "es2019",
|
||||
|
||||
/* */
|
||||
"allowJs": true,
|
||||
"allowJs": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
|
@ -59,4 +59,4 @@
|
|||
".vscode-test",
|
||||
"tools/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче