mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
Merge branch 'feat_mistral-199' into dev
This commit is contained in:
commit
39fb3bc304
3281 changed files with 373986 additions and 135822 deletions
21
.config/1espt/PipelineAutobaseliningConfig.yml
Normal file
21
.config/1espt/PipelineAutobaseliningConfig.yml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
## DO NOT MODIFY THIS FILE MANUALLY. This is part of auto-baselining from 1ES Pipeline Templates. Go to [https://aka.ms/1espt-autobaselining] for more details.
|
||||||
|
|
||||||
|
pipelines:
|
||||||
|
111:
|
||||||
|
retail:
|
||||||
|
source:
|
||||||
|
credscan:
|
||||||
|
lastModifiedDate: 2024-09-10
|
||||||
|
eslint:
|
||||||
|
lastModifiedDate: 2024-09-10
|
||||||
|
psscriptanalyzer:
|
||||||
|
lastModifiedDate: 2024-09-10
|
||||||
|
armory:
|
||||||
|
lastModifiedDate: 2024-09-10
|
||||||
|
binary:
|
||||||
|
credscan:
|
||||||
|
lastModifiedDate: 2025-02-04
|
||||||
|
binskim:
|
||||||
|
lastModifiedDate: 2025-02-04
|
||||||
|
spotbugs:
|
||||||
|
lastModifiedDate: 2025-02-04
|
||||||
255
.config/guardian/.gdnbaselines
Normal file
255
.config/guardian/.gdnbaselines
Normal file
|
|
@ -0,0 +1,255 @@
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"helpUri": "https://eng.ms/docs/microsoft-security/security/azure-security/cloudai-security-fundamentals-engineering/security-integration/guardian-wiki/microsoft-guardian/general/baselines"
|
||||||
|
},
|
||||||
|
"version": "1.0.0",
|
||||||
|
"baselines": {
|
||||||
|
"default": {
|
||||||
|
"name": "default",
|
||||||
|
"createdDate": "2025-01-28 06:29:05Z",
|
||||||
|
"lastUpdatedDate": "2025-01-28 06:29:05Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"results": {
|
||||||
|
"ea3b2bf4f5b3d0bd8a6ad35cc61e49f2a1596660fd66d17d740e4806e7ed7dcc": {
|
||||||
|
"signature": "ea3b2bf4f5b3d0bd8a6ad35cc61e49f2a1596660fd66d17d740e4806e7ed7dcc",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"ff528c0b5a010ae7b5e9178b004a8b816a429a28ba98ce8336466b490a09dcef"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.97.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2009",
|
||||||
|
"createdDate": "2025-01-30 19:19:49Z",
|
||||||
|
"expirationDate": "2025-07-19 21:12:48Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
|
||||||
|
},
|
||||||
|
"12babbc85192ed1c8d927693da788537c1eef199bbecbe226f940a2d0e97637c": {
|
||||||
|
"signature": "12babbc85192ed1c8d927693da788537c1eef199bbecbe226f940a2d0e97637c",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"35b0519e201e56fb87fc6fb085e6fb1df5b89715142bb9086a5b2006e0fd4ced"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.97.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2018",
|
||||||
|
"createdDate": "2025-01-30 19:19:49Z",
|
||||||
|
"expirationDate": "2025-07-19 21:12:48Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
|
||||||
|
},
|
||||||
|
"49163bd1dc9d965d3baced1694dc8c43305b8bf96e884f478d8e4bd124454ba0": {
|
||||||
|
"signature": "49163bd1dc9d965d3baced1694dc8c43305b8bf96e884f478d8e4bd124454ba0",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"aa80bcf44aa8ddd20fb9802e9032c1257048b973896a944ded70bb195f060b2a"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.97.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2009",
|
||||||
|
"createdDate": "2025-01-30 19:21:17Z",
|
||||||
|
"expirationDate": "2025-07-19 21:12:48Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
|
||||||
|
},
|
||||||
|
"c405af02e021c3a473d4e45ec4daa658db1527ea7430c6be968d182e7b50fbd1": {
|
||||||
|
"signature": "c405af02e021c3a473d4e45ec4daa658db1527ea7430c6be968d182e7b50fbd1",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"619d2a1a77f55b4181493b8cfdf09be5261e539115752af2e4938f5ac04af132"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.97.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2018",
|
||||||
|
"createdDate": "2025-01-30 19:21:17Z",
|
||||||
|
"expirationDate": "2025-07-19 21:12:48Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
|
||||||
|
},
|
||||||
|
"71b8515b2eb51cfd5eace11cedb15189d51ce9e479095a5938334416088cbc03": {
|
||||||
|
"signature": "71b8515b2eb51cfd5eace11cedb15189d51ce9e479095a5938334416088cbc03",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"b34279fc5fec828b8dcd9ca873804e85d7d9cd78554ec109d2dd493351a7a244"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.97.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2009",
|
||||||
|
"createdDate": "2025-01-30 19:51:51Z",
|
||||||
|
"expirationDate": "2025-07-19 21:12:48Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
|
||||||
|
},
|
||||||
|
"9238de77a5320039def14694d1b6f501cc2288f13c9c688d2e0501fc5a56ee61": {
|
||||||
|
"signature": "9238de77a5320039def14694d1b6f501cc2288f13c9c688d2e0501fc5a56ee61",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"1d17616a549e9f36d814c4e802d651b1af453ce0a23d4478eef39be81adcc16b"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.97.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2018",
|
||||||
|
"createdDate": "2025-01-30 19:51:51Z",
|
||||||
|
"expirationDate": "2025-07-19 21:12:48Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
|
||||||
|
},
|
||||||
|
"bad8b698b48c1da9ece953903581c66bf98bc829ae1a6adcd3b5c2056a6fcd01": {
|
||||||
|
"signature": "bad8b698b48c1da9ece953903581c66bf98bc829ae1a6adcd3b5c2056a6fcd01",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"057376d31b97e8ce3ecf6a180a553b932d7e5be6e2b07a08027d5dfabe35e82c"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.97.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2009",
|
||||||
|
"createdDate": "2025-01-30 19:53:13Z",
|
||||||
|
"expirationDate": "2025-07-19 21:12:48Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
|
||||||
|
},
|
||||||
|
"cc7c248b0fd4c105e9a393ae232bf0d314ec50e65357a5e7e7d68f6f10c77077": {
|
||||||
|
"signature": "cc7c248b0fd4c105e9a393ae232bf0d314ec50e65357a5e7e7d68f6f10c77077",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"f3867098aff3368682df9926e85a35ec05cf905f27d0c157430021c3169f899d"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.97.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2018",
|
||||||
|
"createdDate": "2025-01-30 19:53:13Z",
|
||||||
|
"expirationDate": "2025-07-19 21:12:48Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-01-30 21:12:48Z"
|
||||||
|
},
|
||||||
|
"8c53250a171412b84dedcbb22cdab9ec365d9b52d74b09c070097fff45372de0": {
|
||||||
|
"signature": "8c53250a171412b84dedcbb22cdab9ec365d9b52d74b09c070097fff45372de0",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"314267784b0ea867006e00b809a93498fae3264e42d1a3a7745ab13180a5b6ef"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.98.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2009",
|
||||||
|
"createdDate": "2025-02-04 06:16:33Z",
|
||||||
|
"expirationDate": "2025-07-24 07:25:17Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
|
||||||
|
},
|
||||||
|
"a6a58d971da858f4af219672cef73ffd0aacc47f1e2c12b8b44a428e1330d3de": {
|
||||||
|
"signature": "a6a58d971da858f4af219672cef73ffd0aacc47f1e2c12b8b44a428e1330d3de",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"4e40f2f1683f0bf2245f35d0ebbcf2f446274d84b1db09d8e76ddfdcad5d4479"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-arm64/system-setup/VSCodeSetup-arm64-1.98.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2018",
|
||||||
|
"createdDate": "2025-02-04 06:16:33Z",
|
||||||
|
"expirationDate": "2025-07-24 07:25:17Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
|
||||||
|
},
|
||||||
|
"90e0f060e01e4a55620f609ac3241b62e8f54a059e9f4d292e93a4305fd3c39e": {
|
||||||
|
"signature": "90e0f060e01e4a55620f609ac3241b62e8f54a059e9f4d292e93a4305fd3c39e",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"377fe43ff8404d07f4a6ca763175004f360397ded6cf5d55b655646ada90e39c"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.98.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2009",
|
||||||
|
"createdDate": "2025-02-04 06:17:54Z",
|
||||||
|
"expirationDate": "2025-07-24 07:25:17Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
|
||||||
|
},
|
||||||
|
"f36c3dc19566098a923877d16d6ebfcbd971f8fcd8210afb8f5558fb5ba1f203": {
|
||||||
|
"signature": "f36c3dc19566098a923877d16d6ebfcbd971f8fcd8210afb8f5558fb5ba1f203",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"1af1f475c1617701e3d7a8fd465916bcc60c3125b8807af5d47d49137d9d468c"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-arm64/user-setup/VSCodeUserSetup-arm64-1.98.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2018",
|
||||||
|
"createdDate": "2025-02-04 06:17:54Z",
|
||||||
|
"expirationDate": "2025-07-24 07:25:17Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
|
||||||
|
},
|
||||||
|
"71193d108c53bb802f5c491276365bcff0645fb380be57288f3fbd6896166d3a": {
|
||||||
|
"signature": "71193d108c53bb802f5c491276365bcff0645fb380be57288f3fbd6896166d3a",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"420cae2e6e34b93d7b74fc1ffddfdf23b57650ae989d838bb2d67f28e4e1db0e"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.98.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2009",
|
||||||
|
"createdDate": "2025-02-04 07:11:19Z",
|
||||||
|
"expirationDate": "2025-07-24 07:25:17Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
|
||||||
|
},
|
||||||
|
"444c302f49bdedcafe772322a09727b2279e3265d99deb2e307defeae3ef200b": {
|
||||||
|
"signature": "444c302f49bdedcafe772322a09727b2279e3265d99deb2e307defeae3ef200b",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"4ff6ccbdb0745d43d3b61f82fb2f4d8a64fe9787525df81a6d7b825e79282085"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-x64/system-setup/VSCodeSetup-x64-1.98.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2018",
|
||||||
|
"createdDate": "2025-02-04 07:11:19Z",
|
||||||
|
"expirationDate": "2025-07-24 07:25:17Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
|
||||||
|
},
|
||||||
|
"4670c7c096a69ca428429ffa1f5250aac9f2e07beac0ffe587ffb37bdb1da4d4": {
|
||||||
|
"signature": "4670c7c096a69ca428429ffa1f5250aac9f2e07beac0ffe587ffb37bdb1da4d4",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"7cead96cb508ab6e37e27bcc0f8b7ed8d0761b77f4793958c46c5ff3892ab1b6"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.98.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2009",
|
||||||
|
"createdDate": "2025-02-04 07:13:22Z",
|
||||||
|
"expirationDate": "2025-07-24 07:25:17Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
|
||||||
|
},
|
||||||
|
"a359b4a5ed2378a73f3bba93e3fb1c595db7423c3082635d12d101bbeb0a51b8": {
|
||||||
|
"signature": "a359b4a5ed2378a73f3bba93e3fb1c595db7423c3082635d12d101bbeb0a51b8",
|
||||||
|
"alternativeSignatures": [
|
||||||
|
"125b52a21ef619a95e695085deb9492280bcf2c1decdd5e87e6416af5982d02d"
|
||||||
|
],
|
||||||
|
"target": ".build/win32-x64/user-setup/VSCodeUserSetup-x64-1.98.0-insider.exe",
|
||||||
|
"memberOf": [
|
||||||
|
"default"
|
||||||
|
],
|
||||||
|
"tool": "binskim",
|
||||||
|
"ruleId": "BA2018",
|
||||||
|
"createdDate": "2025-02-04 07:13:22Z",
|
||||||
|
"expirationDate": "2025-07-24 07:25:17Z",
|
||||||
|
"justification": "This error is baselined with an expiration date of 180 days from 2025-02-04 07:25:17Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "Void",
|
"name": "Code - OSS",
|
||||||
"build": {
|
"build": {
|
||||||
"dockerfile": "Dockerfile"
|
"dockerfile": "Dockerfile"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
0
.devcontainer/install-vscode.sh
Normal file → Executable file
0
.devcontainer/install-vscode.sh
Normal file → Executable file
0
.devcontainer/post-create.sh
Normal file → Executable file
0
.devcontainer/post-create.sh
Normal file → Executable file
|
|
@ -11,7 +11,11 @@
|
||||||
**/extensions/markdown-language-features/notebook-out/**
|
**/extensions/markdown-language-features/notebook-out/**
|
||||||
**/extensions/markdown-math/notebook-out/**
|
**/extensions/markdown-math/notebook-out/**
|
||||||
**/extensions/notebook-renderers/renderer-out/index.js
|
**/extensions/notebook-renderers/renderer-out/index.js
|
||||||
|
**/extensions/open-remote-ssh/out/extension.js
|
||||||
**/extensions/simple-browser/media/index.js
|
**/extensions/simple-browser/media/index.js
|
||||||
|
**/extensions/terminal-suggest/src/completions/upstream/**
|
||||||
|
**/extensions/terminal-suggest/src/shell/zshBuiltinsCache.ts
|
||||||
|
**/extensions/terminal-suggest/third_party/**
|
||||||
**/extensions/typescript-language-features/test-workspace/**
|
**/extensions/typescript-language-features/test-workspace/**
|
||||||
**/extensions/typescript-language-features/extension.webpack.config.js
|
**/extensions/typescript-language-features/extension.webpack.config.js
|
||||||
**/extensions/typescript-language-features/extension-browser.webpack.config.js
|
**/extensions/typescript-language-features/extension-browser.webpack.config.js
|
||||||
|
|
@ -30,15 +34,7 @@
|
||||||
**/src/vs/*/**/*.d.ts
|
**/src/vs/*/**/*.d.ts
|
||||||
**/src/vs/base/test/common/filters.perf.data.js
|
**/src/vs/base/test/common/filters.perf.data.js
|
||||||
**/src/vs/loader.js
|
**/src/vs/loader.js
|
||||||
**/src2/**/dompurify.js
|
|
||||||
**/src2/**/marked.js
|
|
||||||
**/src2/**/semver.js
|
|
||||||
**/src2/typings/**/*.d.ts
|
|
||||||
**/src2/vs/*/**/*.d.ts
|
|
||||||
**/src2/vs/base/test/common/filters.perf.data.js
|
|
||||||
**/src2/vs/loader.js
|
|
||||||
**/test/unit/assert.js
|
**/test/unit/assert.js
|
||||||
**/test/unit/assert-esm.js
|
|
||||||
**/test/automation/out/**
|
**/test/automation/out/**
|
||||||
**/typings/**
|
**/typings/**
|
||||||
!.vscode
|
!.vscode
|
||||||
|
|
@ -12,7 +12,8 @@ export = new class ApiProviderNaming implements eslint.Rule.RuleModule {
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
messages: {
|
messages: {
|
||||||
amdX: 'Use `import type` for import declarations, use `amdX#importAMDNodeModule` for import expressions'
|
amdX: 'Use `import type` for import declarations, use `amdX#importAMDNodeModule` for import expressions'
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -8,7 +8,8 @@ import * as eslint from 'eslint';
|
||||||
export = new class DeclareServiceBrand implements eslint.Rule.RuleModule {
|
export = new class DeclareServiceBrand implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
fixable: 'code'
|
fixable: 'code',
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -13,7 +13,8 @@ export = new class EnsureNoDisposablesAreLeakedInTestSuite implements eslint.Rul
|
||||||
messages: {
|
messages: {
|
||||||
ensure: 'Suites should include a call to `ensureNoDisposablesAreLeakedInTestSuite()` to ensure no disposables are leaked in tests.'
|
ensure: 'Suites should include a call to `ensureNoDisposablesAreLeakedInTestSuite()` to ensure no disposables are leaked in tests.'
|
||||||
},
|
},
|
||||||
fixable: 'code'
|
fixable: 'code',
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import minimatch from 'minimatch';
|
import minimatch from 'minimatch';
|
||||||
import { createImportRuleListener } from './utils';
|
import { createImportRuleListener } from './utils';
|
||||||
|
|
@ -50,7 +50,8 @@ export = new class implements eslint.Rule.RuleModule {
|
||||||
},
|
},
|
||||||
docs: {
|
docs: {
|
||||||
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
|
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -249,7 +250,7 @@ export = new class implements eslint.Rule.RuleModule {
|
||||||
const relativeFilename = getRelativeFilename(context);
|
const relativeFilename = getRelativeFilename(context);
|
||||||
importPath = path.posix.join(path.posix.dirname(relativeFilename), importPath);
|
importPath = path.posix.join(path.posix.dirname(relativeFilename), importPath);
|
||||||
if (/^src\/vs\//.test(importPath)) {
|
if (/^src\/vs\//.test(importPath)) {
|
||||||
// resolve using AMD base url
|
// resolve using base url
|
||||||
importPath = importPath.substring('src/'.length);
|
importPath = importPath.substring('src/'.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -20,7 +20,18 @@ export = new class implements eslint.Rule.RuleModule {
|
||||||
},
|
},
|
||||||
docs: {
|
docs: {
|
||||||
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
|
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
|
||||||
}
|
},
|
||||||
|
schema: [
|
||||||
|
{
|
||||||
|
type: 'object',
|
||||||
|
additionalProperties: {
|
||||||
|
type: 'array',
|
||||||
|
items: {
|
||||||
|
type: 'string'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
70
.eslint-plugin-local/code-limited-top-functions.ts
Normal file
70
.eslint-plugin-local/code-limited-top-functions.ts
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as eslint from 'eslint';
|
||||||
|
import { dirname, relative } from 'path';
|
||||||
|
import minimatch from 'minimatch';
|
||||||
|
|
||||||
|
export = new class implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
|
messages: {
|
||||||
|
layerbreaker: 'You are only allowed to define limited top level functions.'
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "object",
|
||||||
|
additionalProperties: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
let fileRelativePath = relative(dirname(__dirname), context.getFilename());
|
||||||
|
if (!fileRelativePath.endsWith('/')) {
|
||||||
|
fileRelativePath += '/';
|
||||||
|
}
|
||||||
|
const ruleArgs = <Record<string, string[]>>context.options[0];
|
||||||
|
|
||||||
|
const matchingKey = Object.keys(ruleArgs).find(key => fileRelativePath.startsWith(key) || minimatch(fileRelativePath, key));
|
||||||
|
if (!matchingKey) {
|
||||||
|
// nothing
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const restrictedFunctions = ruleArgs[matchingKey];
|
||||||
|
|
||||||
|
return {
|
||||||
|
FunctionDeclaration: (node: any) => {
|
||||||
|
const isTopLevel = node.parent.type === 'Program';
|
||||||
|
const functionName = node.id.name;
|
||||||
|
if (isTopLevel && !restrictedFunctions.includes(node.id.name)) {
|
||||||
|
context.report({
|
||||||
|
node,
|
||||||
|
message: `Top-level function '${functionName}' is restricted in this file. Allowed functions are: ${restrictedFunctions.join(', ')}.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ExportNamedDeclaration(node: any) {
|
||||||
|
if (node.declaration && node.declaration.type === 'FunctionDeclaration') {
|
||||||
|
const functionName = node.declaration.id.name;
|
||||||
|
const isTopLevel = node.parent.type === 'Program';
|
||||||
|
if (isTopLevel && !restrictedFunctions.includes(node.declaration.id.name)) {
|
||||||
|
context.report({
|
||||||
|
node,
|
||||||
|
message: `Top-level function '${functionName}' is restricted in this file. Allowed functions are: ${restrictedFunctions.join(', ')}.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
const VALID_USES = new Set<TSESTree.AST_NODE_TYPES | undefined>([
|
const VALID_USES = new Set<TSESTree.AST_NODE_TYPES | undefined>([
|
||||||
TSESTree.AST_NODE_TYPES.AwaitExpression,
|
TSESTree.AST_NODE_TYPES.AwaitExpression,
|
||||||
|
|
@ -12,6 +12,9 @@ const VALID_USES = new Set<TSESTree.AST_NODE_TYPES | undefined>([
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export = new class MustUseResults implements eslint.Rule.RuleModule {
|
export = new class MustUseResults implements eslint.Rule.RuleModule {
|
||||||
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
|
schema: false
|
||||||
|
}
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
export = new class NoDangerousTypeAssertions implements eslint.Rule.RuleModule {
|
export = new class NoDangerousTypeAssertions implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
|
|
@ -10,7 +10,8 @@ export = new class ApiProviderNaming implements eslint.Rule.RuleModule {
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
messages: {
|
messages: {
|
||||||
slow: 'Native private fields are much slower and should only be used when needed. Ignore this warning if you know what you are doing, use compile-time private otherwise. See https://github.com/microsoft/vscode/issues/185991#issuecomment-1614468158 for details',
|
slow: 'Native private fields are much slower and should only be used when needed. Ignore this warning if you know what you are doing, use compile-time private otherwise. See https://github.com/microsoft/vscode/issues/185991#issuecomment-1614468158 for details',
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -12,7 +12,8 @@ export = new class NoNlsInStandaloneEditorRule implements eslint.Rule.RuleModule
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
messages: {
|
messages: {
|
||||||
noNls: 'Not allowed to import vs/nls in standalone editor modules. Use standaloneStrings.ts'
|
noNls: 'Not allowed to import vs/nls in standalone editor modules. Use standaloneStrings.ts'
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -15,7 +15,8 @@ export = new class NoNlsInStandaloneEditorRule implements eslint.Rule.RuleModule
|
||||||
},
|
},
|
||||||
docs: {
|
docs: {
|
||||||
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
|
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WORKAROUND for https://github.com/evanw/esbuild/issues/3823
|
* WORKAROUND for https://github.com/evanw/esbuild/issues/3823
|
||||||
|
|
@ -15,7 +15,7 @@ export = new class implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
function checkProperty(inNode: any) {
|
function checkProperty(inNode: any) {
|
||||||
|
|
||||||
const classDeclaration = context.getAncestors().find(node => node.type === 'ClassDeclaration');
|
const classDeclaration = context.sourceCode.getAncestors(inNode).find(node => node.type === 'ClassDeclaration');
|
||||||
const propertyDefinition = <TSESTree.PropertyDefinition>inNode;
|
const propertyDefinition = <TSESTree.PropertyDefinition>inNode;
|
||||||
|
|
||||||
if (!classDeclaration || !classDeclaration.id?.name) {
|
if (!classDeclaration || !classDeclaration.id?.name) {
|
||||||
|
|
@ -33,7 +33,7 @@ export = new class implements eslint.Rule.RuleModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
const name = classDeclaration.id.name;
|
const name = classDeclaration.id.name;
|
||||||
const valueText = context.getSourceCode().getText(<any>propertyDefinition.value)
|
const valueText = context.sourceCode.getText(<any>propertyDefinition.value)
|
||||||
|
|
||||||
if (valueText.includes(name + '.')) {
|
if (valueText.includes(name + '.')) {
|
||||||
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
|
|
||||||
function isCallExpression(node: TSESTree.Node): node is TSESTree.CallExpression {
|
function isCallExpression(node: TSESTree.Node): node is TSESTree.CallExpression {
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/experimental-utils';
|
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
function isStringLiteral(node: TSESTree.Node | null | undefined): node is TSESTree.StringLiteral {
|
function isStringLiteral(node: TSESTree.Node | null | undefined): node is TSESTree.StringLiteral {
|
||||||
return !!node && node.type === AST_NODE_TYPES.Literal && typeof node.value === 'string';
|
return !!node && node.type === AST_NODE_TYPES.Literal && typeof node.value === 'string';
|
||||||
|
|
@ -24,7 +24,8 @@ export = new class NoUnexternalizedStrings implements eslint.Rule.RuleModule {
|
||||||
badKey: 'The key \'{{key}}\' doesn\'t conform to a valid localize identifier.',
|
badKey: 'The key \'{{key}}\' doesn\'t conform to a valid localize identifier.',
|
||||||
duplicateKey: 'Duplicate key \'{{key}}\' with different message value.',
|
duplicateKey: 'Duplicate key \'{{key}}\' with different message value.',
|
||||||
badMessage: 'Message argument to \'{{message}}\' must be a string literal.'
|
badMessage: 'Message argument to \'{{message}}\' must be a string literal.'
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
import * as ESTree from 'estree';
|
import * as ESTree from 'estree';
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
@ -141,7 +141,7 @@ module.exports = {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ExpressionStatement(node: TSESTree.ExpressionStatement) {
|
ExpressionStatement(node: TSESTree.ExpressionStatement) {
|
||||||
if (!isValidExpression(node.expression) && !isDirective(node, <TSESTree.Node[]>context.getAncestors())) {
|
if (!isValidExpression(node.expression) && !isDirective(node, <TSESTree.Node[]>context.sourceCode.getAncestors(node))) {
|
||||||
context.report({ node: <ESTree.Node>node, message: `Expected an assignment or function call and instead saw an expression. ${node.expression}` });
|
context.report({ node: <ESTree.Node>node, message: `Expected an assignment or function call and instead saw an expression. ${node.expression}` });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enforces that all parameter properties have an explicit access modifier (public, protected, private).
|
* Enforces that all parameter properties have an explicit access modifier (public, protected, private).
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { createImportRuleListener } from './utils';
|
import { createImportRuleListener } from './utils';
|
||||||
|
|
||||||
|
|
@ -16,7 +16,8 @@ export = new class TranslationRemind implements eslint.Rule.RuleModule {
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
messages: {
|
messages: {
|
||||||
missing: 'Please add \'{{resource}}\' to ./build/lib/i18n.resources.json file to use translations here.'
|
missing: 'Please add \'{{resource}}\' to ./build/lib/i18n.resources.json file to use translations here.'
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
3
.eslint-plugin-local/package.json
Normal file
3
.eslint-plugin-local/package.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
export function createImportRuleListener(validateImport: (node: TSESTree.Literal, value: string) => any): eslint.Rule.RuleListener {
|
export function createImportRuleListener(validateImport: (node: TSESTree.Literal, value: string) => any): eslint.Rule.RuleListener {
|
||||||
|
|
||||||
|
|
@ -4,14 +4,15 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/experimental-utils';
|
import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
export = new class ApiProviderNaming implements eslint.Rule.RuleModule {
|
export = new class ApiProviderNaming implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
messages: {
|
messages: {
|
||||||
noToken: 'Function lacks a cancellation token, preferable as last argument',
|
noToken: 'Function lacks a cancellation token, preferable as last argument',
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -4,13 +4,14 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/experimental-utils';
|
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
export = new class ApiLiteralOrTypes implements eslint.Rule.RuleModule {
|
export = new class ApiLiteralOrTypes implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#creating-objects' },
|
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#creating-objects' },
|
||||||
messages: { sync: '`createXYZ`-functions are constructor-replacements and therefore must return sync', }
|
messages: { sync: '`createXYZ`-functions are constructor-replacements and therefore must return sync', },
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/experimental-utils';
|
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
export = new class ApiEventNaming implements eslint.Rule.RuleModule {
|
export = new class ApiEventNaming implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
|
|
@ -19,7 +19,8 @@ export = new class ApiEventNaming implements eslint.Rule.RuleModule {
|
||||||
verb: 'Unknown verb \'{{verb}}\' - is this really a verb? Iff so, then add this verb to the configuration',
|
verb: 'Unknown verb \'{{verb}}\' - is this really a verb? Iff so, then add this verb to the configuration',
|
||||||
subject: 'Unknown subject \'{{subject}}\' - This subject has not been used before but it should refer to something in the API',
|
subject: 'Unknown subject \'{{subject}}\' - This subject has not been used before but it should refer to something in the API',
|
||||||
unknown: 'UNKNOWN event declaration, lint-rule needs tweaking'
|
unknown: 'UNKNOWN event declaration, lint-rule needs tweaking'
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
export = new class ApiInterfaceNaming implements eslint.Rule.RuleModule {
|
export = new class ApiInterfaceNaming implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
|
|
@ -13,7 +13,8 @@ export = new class ApiInterfaceNaming implements eslint.Rule.RuleModule {
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
messages: {
|
messages: {
|
||||||
naming: 'Interfaces must not be prefixed with uppercase `I`',
|
naming: 'Interfaces must not be prefixed with uppercase `I`',
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -4,13 +4,14 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
export = new class ApiLiteralOrTypes implements eslint.Rule.RuleModule {
|
export = new class ApiLiteralOrTypes implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#enums' },
|
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#enums' },
|
||||||
messages: { useEnum: 'Use enums, not literal-or-types', }
|
messages: { useEnum: 'Use enums, not literal-or-types', },
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -4,14 +4,15 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
export = new class ApiProviderNaming implements eslint.Rule.RuleModule {
|
export = new class ApiProviderNaming implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
messages: {
|
messages: {
|
||||||
naming: 'A provider should only have functions like provideXYZ or resolveXYZ',
|
naming: 'A provider should only have functions like provideXYZ or resolveXYZ',
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static _providerFunctionNames = /^(provide|resolve|prepare).+/;
|
private static _providerFunctionNames = /^(provide|resolve|prepare).+/;
|
||||||
|
|
@ -4,21 +4,21 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
import * as eslint from 'eslint';
|
||||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
|
|
||||||
export = new class ApiTypeDiscrimination implements eslint.Rule.RuleModule {
|
export = new class ApiTypeDiscrimination implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines' },
|
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines' },
|
||||||
messages: {
|
messages: {
|
||||||
noTypeDiscrimination: 'Do not use type descrimination properties'
|
noTypeDiscrimination: 'Do not use type discrimination properties'
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
return {
|
return {
|
||||||
['TSPropertySignature[optional=undefined] TSTypeAnnotation TSLiteralType Literal']: (node: any) => {
|
['TSPropertySignature[optional=false] TSTypeAnnotation TSLiteralType Literal']: (node: any) => {
|
||||||
|
|
||||||
const raw = String((<TSESTree.Literal>node).raw)
|
const raw = String((<TSESTree.Literal>node).raw)
|
||||||
|
|
||||||
if (/^('|").*\1$/.test(raw)) {
|
if (/^('|").*\1$/.test(raw)) {
|
||||||
32
.eslint-plugin-local/vscode-dts-use-export.ts
Normal file
32
.eslint-plugin-local/vscode-dts-use-export.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { TSESTree } from '@typescript-eslint/utils';
|
||||||
|
import * as eslint from 'eslint';
|
||||||
|
|
||||||
|
export = new class VscodeDtsUseExport implements eslint.Rule.RuleModule {
|
||||||
|
|
||||||
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
|
messages: {
|
||||||
|
useExport: `Public api types must use 'export'`,
|
||||||
|
},
|
||||||
|
schema: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
return {
|
||||||
|
['TSModuleDeclaration :matches(TSInterfaceDeclaration, ClassDeclaration, VariableDeclaration, TSEnumDeclaration, TSTypeAliasDeclaration)']: (node: any) => {
|
||||||
|
const parent = (<TSESTree.Node>node).parent;
|
||||||
|
if (parent && parent.type !== TSESTree.AST_NODE_TYPES.ExportNamedDeclaration) {
|
||||||
|
context.report({
|
||||||
|
node,
|
||||||
|
messageId: 'useExport'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -10,7 +10,8 @@ export = new class ApiEventNaming implements eslint.Rule.RuleModule {
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
messages: {
|
messages: {
|
||||||
usage: 'Use the Thenable-type instead of the Promise type',
|
usage: 'Use the Thenable-type instead of the Promise type',
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -11,7 +11,8 @@ export = new class ApiVsCodeInComments implements eslint.Rule.RuleModule {
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
readonly meta: eslint.Rule.RuleMetaData = {
|
||||||
messages: {
|
messages: {
|
||||||
comment: `Don't use the term 'vs code' in comments`
|
comment: `Don't use the term 'vs code' in comments`
|
||||||
}
|
},
|
||||||
|
schema: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
/*---------------------------------------------------------------------------------------------
|
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
import * as eslint from 'eslint';
|
|
||||||
|
|
||||||
export = new class ApiEventNaming implements eslint.Rule.RuleModule {
|
|
||||||
|
|
||||||
readonly meta: eslint.Rule.RuleMetaData = {
|
|
||||||
messages: {
|
|
||||||
comment: 'region comments should start with a camel case identifier, `:`, then either a GH issue link or owner, e.g #region myProposalName: https://github.com/microsoft/vscode/issues/<number>',
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
|
||||||
|
|
||||||
const sourceCode = context.getSourceCode();
|
|
||||||
|
|
||||||
return {
|
|
||||||
['Program']: (_node: any) => {
|
|
||||||
for (const comment of sourceCode.getAllComments()) {
|
|
||||||
if (comment.type !== 'Line') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!/^\s*#region /.test(comment.value)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!/^\s*#region ([a-z]+): (@[a-z]+|https:\/\/github.com\/microsoft\/vscode\/issues\/\d+)/i.test(comment.value)) {
|
|
||||||
context.report({
|
|
||||||
node: <any>comment,
|
|
||||||
messageId: 'comment',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
1230
.eslintrc.json
1230
.eslintrc.json
File diff suppressed because it is too large
Load diff
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -24,3 +24,5 @@ product.overrides.json
|
||||||
.tmp/
|
.tmp/
|
||||||
.tmp2/
|
.tmp2/
|
||||||
.tool-versions
|
.tool-versions
|
||||||
|
src/vs/workbench/contrib/void/browser/react/out/**
|
||||||
|
src/vs/workbench/contrib/void/browser/react/src2/**
|
||||||
|
|
|
||||||
4
.npmrc
4
.npmrc
|
|
@ -1,6 +1,6 @@
|
||||||
disturl="https://electronjs.org/headers"
|
disturl="https://electronjs.org/headers"
|
||||||
target="30.5.1"
|
target="34.2.0"
|
||||||
ms_build_id="10262041"
|
ms_build_id="11044223"
|
||||||
runtime="electron"
|
runtime="electron"
|
||||||
build_from_source="true"
|
build_from_source="true"
|
||||||
legacy-peer-deps="true"
|
legacy-peer-deps="true"
|
||||||
|
|
|
||||||
2
.nvmrc
2
.nvmrc
|
|
@ -1 +1 @@
|
||||||
20.16.0
|
20.18.2
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,15 @@
|
||||||
|
|
||||||
//@ts-check
|
//@ts-check
|
||||||
|
|
||||||
const path = require('path');
|
import { createRequire } from 'node:module';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as os from 'os';
|
||||||
|
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
const { defineConfig } = require('@vscode/test-cli');
|
const { defineConfig } = require('@vscode/test-cli');
|
||||||
const os = require('os');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of extension folders who have opted into tests, or configuration objects.
|
* A list of extension folders who have opted into tests, or configuration objects.
|
||||||
|
|
@ -36,6 +42,16 @@ const extensions = [
|
||||||
workspaceFolder: `extensions/vscode-colorize-tests/test`,
|
workspaceFolder: `extensions/vscode-colorize-tests/test`,
|
||||||
mocha: { timeout: 60_000 }
|
mocha: { timeout: 60_000 }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'terminal-suggest',
|
||||||
|
workspaceFolder: path.join(os.tmpdir(), `terminal-suggest-${Math.floor(Math.random() * 100000)}`),
|
||||||
|
mocha: { timeout: 60_000 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'vscode-colorize-perf-tests',
|
||||||
|
workspaceFolder: `extensions/vscode-colorize-perf-tests/test`,
|
||||||
|
mocha: { timeout: 6000_000 }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'configuration-editing',
|
label: 'configuration-editing',
|
||||||
workspaceFolder: path.join(os.tmpdir(), `confeditout-${Math.floor(Math.random() * 100000)}`),
|
workspaceFolder: path.join(os.tmpdir(), `confeditout-${Math.floor(Math.random() * 100000)}`),
|
||||||
|
|
@ -57,7 +73,7 @@ const defaultLaunchArgs = process.env.API_TESTS_EXTRA_ARGS?.split(' ') || [
|
||||||
'--disable-telemetry', '--skip-welcome', '--skip-release-notes', `--crash-reporter-directory=${__dirname}/.build/crashes`, `--logsPath=${__dirname}/.build/logs/integration-tests`, '--no-cached-data', '--disable-updates', '--use-inmemory-secretstorage', '--disable-extensions', '--disable-workspace-trust'
|
'--disable-telemetry', '--skip-welcome', '--skip-release-notes', `--crash-reporter-directory=${__dirname}/.build/crashes`, `--logsPath=${__dirname}/.build/logs/integration-tests`, '--no-cached-data', '--disable-updates', '--use-inmemory-secretstorage', '--disable-extensions', '--disable-workspace-trust'
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports = defineConfig(extensions.map(extension => {
|
const config = defineConfig(extensions.map(extension => {
|
||||||
/** @type {import('@vscode/test-cli').TestConfiguration} */
|
/** @type {import('@vscode/test-cli').TestConfiguration} */
|
||||||
const config = typeof extension === 'object'
|
const config = typeof extension === 'object'
|
||||||
? { files: `extensions/${extension.label}/out/**/*.test.js`, ...extension }
|
? { files: `extensions/${extension.label}/out/**/*.test.js`, ...extension }
|
||||||
|
|
@ -99,3 +115,5 @@ module.exports = defineConfig(extensions.map(extension => {
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@
|
||||||
"description": "Test provider for the VS Code project",
|
"description": "Test provider for the VS Code project",
|
||||||
"enabledApiProposals": [
|
"enabledApiProposals": [
|
||||||
"testObserver",
|
"testObserver",
|
||||||
"testRelatedCode",
|
"testRelatedCode"
|
||||||
"attributableCoverage"
|
|
||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"vscode": "^1.88.0"
|
"vscode": "^1.88.0"
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ class ScriptCoverageTracker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class V8CoverageFile extends vscode.FileCoverage2 {
|
export class V8CoverageFile extends vscode.FileCoverage {
|
||||||
public details: vscode.StatementCoverage[] = [];
|
public details: vscode.StatementCoverage[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
|
||||||
|
|
@ -86,10 +86,11 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||||
}, uri => ctrl.items.get(uri.toString().toLowerCase()));
|
}, uri => ctrl.items.get(uri.toString().toLowerCase()));
|
||||||
ctrl.relatedCodeProvider = graph;
|
ctrl.relatedCodeProvider = graph;
|
||||||
|
|
||||||
context.subscriptions.push(
|
if (context.storageUri) {
|
||||||
new FailureTracker(context, folder.uri.fsPath),
|
context.subscriptions.push(new FailureTracker(context.storageUri.fsPath, folder.uri.fsPath));
|
||||||
fileChangedEmitter.event(e => graph.didChange(e.uri, e.removed)),
|
}
|
||||||
);
|
|
||||||
|
context.subscriptions.push(fileChangedEmitter.event(e => graph.didChange(e.uri, e.removed)));
|
||||||
});
|
});
|
||||||
|
|
||||||
const createRunHandler = (
|
const createRunHandler = (
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ export class FailureTracker {
|
||||||
private readonly logFile: string;
|
private readonly logFile: string;
|
||||||
private logs?: ITrackedRemediation[];
|
private logs?: ITrackedRemediation[];
|
||||||
|
|
||||||
constructor(context: vscode.ExtensionContext, private readonly rootDir: string) {
|
constructor(storageLocation: string, private readonly rootDir: string) {
|
||||||
this.logFile = join(context.globalStorageUri.fsPath, '.build/vscode-test-failures.json');
|
this.logFile = join(storageLocation, '.build/vscode-test-failures.json');
|
||||||
mkdirSync(dirname(this.logFile), { recursive: true });
|
mkdirSync(dirname(this.logFile), { recursive: true });
|
||||||
|
|
||||||
const oldLogFile = join(rootDir, '.build/vscode-test-failures.json');
|
const oldLogFile = join(rootDir, '.build/vscode-test-failures.json');
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
"src/**/*",
|
"src/**/*",
|
||||||
"../../../src/vscode-dts/vscode.d.ts",
|
"../../../src/vscode-dts/vscode.d.ts",
|
||||||
"../../../src/vscode-dts/vscode.proposed.testObserver.d.ts",
|
"../../../src/vscode-dts/vscode.proposed.testObserver.d.ts",
|
||||||
"../../../src/vscode-dts/vscode.proposed.testRelatedCode.d.ts",
|
"../../../src/vscode-dts/vscode.proposed.testRelatedCode.d.ts"
|
||||||
"../../../src/vscode-dts/vscode.proposed.attributableCoverage.d.ts"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
.vscode/launch.json
vendored
22
.vscode/launch.json
vendored
|
|
@ -202,6 +202,24 @@
|
||||||
"order": 5
|
"order": 5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "extensionHost",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "VS Code Tokenizer Performance Tests",
|
||||||
|
"runtimeExecutable": "${execPath}",
|
||||||
|
"args": [
|
||||||
|
"${workspaceFolder}/extensions/vscode-colorize-perf-tests/test",
|
||||||
|
"--extensionDevelopmentPath=${workspaceFolder}/extensions/vscode-colorize-perf-tests",
|
||||||
|
"--extensionTestsPath=${workspaceFolder}/extensions/vscode-colorize-perf-tests/out"
|
||||||
|
],
|
||||||
|
"outFiles": [
|
||||||
|
"${workspaceFolder}/out/**/*.js"
|
||||||
|
],
|
||||||
|
"presentation": {
|
||||||
|
"group": "5_tests",
|
||||||
|
"order": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "chrome",
|
"type": "chrome",
|
||||||
"request": "attach",
|
"request": "attach",
|
||||||
|
|
@ -257,10 +275,6 @@
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"hidden": true,
|
"hidden": true,
|
||||||
},
|
},
|
||||||
// This is read by the vscode-diagnostic-tools extension
|
|
||||||
"vscode-diagnostic-tools.debuggerScripts": [
|
|
||||||
"${workspaceFolder}/scripts/hot-reload-injected-script.js"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "node",
|
"type": "node",
|
||||||
|
|
|
||||||
2
.vscode/notebooks/api.github-issues
vendored
2
.vscode/notebooks/api.github-issues
vendored
|
|
@ -7,7 +7,7 @@
|
||||||
{
|
{
|
||||||
"kind": 2,
|
"kind": 2,
|
||||||
"language": "github-issues",
|
"language": "github-issues",
|
||||||
"value": "$REPO=repo:microsoft/vscode\n$MILESTONE=milestone:\"September 2024\""
|
"value": "$REPO=repo:microsoft/vscode\n$MILESTONE=milestone:\"February 2025\""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": 1,
|
"kind": 1,
|
||||||
|
|
|
||||||
6
.vscode/notebooks/endgame.github-issues
vendored
6
.vscode/notebooks/endgame.github-issues
vendored
|
|
@ -7,7 +7,7 @@
|
||||||
{
|
{
|
||||||
"kind": 2,
|
"kind": 2,
|
||||||
"language": "github-issues",
|
"language": "github-issues",
|
||||||
"value": "$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n\n$MILESTONE=milestone:\"September 2024\""
|
"value": "$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\r\n\r\n$MILESTONE=milestone:\"February 2025\""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": 1,
|
"kind": 1,
|
||||||
|
|
@ -97,7 +97,7 @@
|
||||||
{
|
{
|
||||||
"kind": 2,
|
"kind": 2,
|
||||||
"language": "github-issues",
|
"language": "github-issues",
|
||||||
"value": "$REPOS $MILESTONE is:issue is:closed reason:completed label:verification-needed -label:verified"
|
"value": "$REPOS $MILESTONE is:issue is:closed reason:completed label:verification-needed -label:verified -label:on-testplan"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": 1,
|
"kind": 1,
|
||||||
|
|
@ -112,7 +112,7 @@
|
||||||
{
|
{
|
||||||
"kind": 2,
|
"kind": 2,
|
||||||
"language": "github-issues",
|
"language": "github-issues",
|
||||||
"value": "$REPOS $MILESTONE is:issue is:closed reason:completed sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:z-author-verified -label:unreleased -label:*not-reproducible"
|
"value": "$REPOS $MILESTONE is:issue is:closed reason:completed sort:updated-asc label:bug -label:verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:z-author-verified -label:unreleased -label:*not-reproducible -label:*out-of-scope"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": 1,
|
"kind": 1,
|
||||||
|
|
|
||||||
18
.vscode/notebooks/grooming.github-issues
vendored
18
.vscode/notebooks/grooming.github-issues
vendored
File diff suppressed because one or more lines are too long
10
.vscode/notebooks/my-endgame.github-issues
vendored
10
.vscode/notebooks/my-endgame.github-issues
vendored
|
|
@ -7,7 +7,7 @@
|
||||||
{
|
{
|
||||||
"kind": 2,
|
"kind": 2,
|
||||||
"language": "github-issues",
|
"language": "github-issues",
|
||||||
"value": "$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n\n$MILESTONE=milestone:\"September 2024\"\n\n$MINE=assignee:@me"
|
"value": "$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n\n$MILESTONE=milestone:\"February 2025\"\n\n$MINE=assignee:@me"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": 1,
|
"kind": 1,
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
{
|
{
|
||||||
"kind": 2,
|
"kind": 2,
|
||||||
"language": "github-issues",
|
"language": "github-issues",
|
||||||
"value": "$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:feature-request label:verification-needed -label:verified"
|
"value": "$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:feature-request label:verification-needed -label:verified -label:on-testplan"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": 1,
|
"kind": 1,
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
{
|
{
|
||||||
"kind": 2,
|
"kind": 2,
|
||||||
"language": "github-issues",
|
"language": "github-issues",
|
||||||
"value": "$REPOS $MILESTONE -$MINE is:issue is:closed reason:completed -assignee:@me -label:verified -label:z-author-verified label:feature-request label:verification-needed -label:verification-steps-needed -label:unreleased"
|
"value": "$REPOS $MILESTONE -$MINE is:issue is:closed reason:completed -assignee:@me -label:verified -label:z-author-verified label:feature-request label:verification-needed -label:verification-steps-needed -label:unreleased -label:on-testplan"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": 1,
|
"kind": 1,
|
||||||
|
|
@ -157,7 +157,7 @@
|
||||||
{
|
{
|
||||||
"kind": 2,
|
"kind": 2,
|
||||||
"language": "github-issues",
|
"language": "github-issues",
|
||||||
"value": "$REPOS $MILESTONE -$MINE is:issue is:closed reason:completed sort:updated-asc label:bug -label:unreleased -label:verified -label:z-author-verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:*out-of-scope -label:error-telemetry -label:verification-steps-needed -label:verification-found -author:aeschli -author:alexdima -author:alexr00 -author:AmandaSilver -author:andreamah -author:bamurtaugh -author:bpasero -author:chrisdias -author:chrmarti -author:Chuxel -author:claudiaregio -author:connor4312 -author:dbaeumer -author:deepak1556 -author:devinvalenciano -author:digitarald -author:DonJayamanne -author:egamma -author:fiveisprime -author:gregvanl -author:hediet -author:isidorn -author:joaomoreno -author:joyceerhl -author:jrieken -author:kieferrm -author:lramos15 -author:lszomoru -author:meganrogge -author:misolori -author:mjbvz -author:rebornix -author:roblourens -author:rzhao271 -author:sandy081 -author:sbatten -author:stevencl -author:tanhakabir -author:TylerLeonhardt -author:Tyriar -author:weinand -author:amunger -author:karthiknadig -author:eleanorjboyd -author:Yoyokrazy -author:paulacamargo25 -author:ulugbekna -author:aiday-mar -author:daviddossett -author:bhavyaus -author:justschen -author:benibenj -author:luabud -author:anthonykim1 -author:joshspicer"
|
"value": "$REPOS $MILESTONE -$MINE is:issue is:closed reason:completed sort:updated-asc label:bug -label:unreleased -label:verified -label:z-author-verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:*out-of-scope -label:error-telemetry -label:verification-steps-needed -label:verification-found -author:aeschli -author:alexdima -author:alexr00 -author:AmandaSilver -author:andreamah -author:bamurtaugh -author:bpasero -author:chrisdias -author:chrmarti -author:Chuxel -author:claudiaregio -author:connor4312 -author:dbaeumer -author:deepak1556 -author:devinvalenciano -author:digitarald -author:DonJayamanne -author:egamma -author:fiveisprime -author:ntrogh -author:hediet -author:isidorn -author:joaomoreno -author:joyceerhl -author:jrieken -author:kieferrm -author:lramos15 -author:lszomoru -author:meganrogge -author:misolori -author:mjbvz -author:rebornix -author:roblourens -author:rzhao271 -author:sandy081 -author:sbatten -author:stevencl -author:tanhakabir -author:TylerLeonhardt -author:Tyriar -author:weinand -author:amunger -author:karthiknadig -author:eleanorjboyd -author:Yoyokrazy -author:paulacamargo25 -author:ulugbekna -author:aiday-mar -author:daviddossett -author:bhavyaus -author:justschen -author:benibenj -author:luabud -author:anthonykim1 -author:joshspicer -author:osortega -author:legomushroom"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": 1,
|
"kind": 1,
|
||||||
|
|
@ -187,6 +187,6 @@
|
||||||
{
|
{
|
||||||
"kind": 2,
|
"kind": 2,
|
||||||
"language": "github-issues",
|
"language": "github-issues",
|
||||||
"value": "$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:feature-request -label:on-release-notes\n$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:engineering -label:on-release-notes\n$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:plan-item -label:on-release-notes"
|
"value": "$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:feature-request -label:on-release-notes\r\n$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:engineering -label:on-release-notes\r\n$REPOS $MILESTONE $MINE is:issue is:closed reason:completed label:plan-item -label:on-release-notes"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
4
.vscode/notebooks/my-work.github-issues
vendored
4
.vscode/notebooks/my-work.github-issues
vendored
File diff suppressed because one or more lines are too long
29
.vscode/settings.json
vendored
29
.vscode/settings.json
vendored
|
|
@ -8,6 +8,7 @@
|
||||||
"**/.DS_Store": true,
|
"**/.DS_Store": true,
|
||||||
".vscode-test": true,
|
".vscode-test": true,
|
||||||
"cli/target": true,
|
"cli/target": true,
|
||||||
|
"build/**/*.js.map": true,
|
||||||
"build/**/*.js": {
|
"build/**/*.js": {
|
||||||
"when": "$(basename).ts"
|
"when": "$(basename).ts"
|
||||||
}
|
}
|
||||||
|
|
@ -41,8 +42,6 @@
|
||||||
"**/yarn.lock": true,
|
"**/yarn.lock": true,
|
||||||
"**/package-lock.json": true,
|
"**/package-lock.json": true,
|
||||||
"**/Cargo.lock": true,
|
"**/Cargo.lock": true,
|
||||||
"src/vs/workbench/workbench.web.main.css": true,
|
|
||||||
"src/vs/workbench/workbench.desktop.main.css": true,
|
|
||||||
"build/**/*.js": true,
|
"build/**/*.js": true,
|
||||||
"out/**": true,
|
"out/**": true,
|
||||||
"out-build/**": true,
|
"out-build/**": true,
|
||||||
|
|
@ -52,8 +51,7 @@
|
||||||
"extensions/**/out/**": true,
|
"extensions/**/out/**": true,
|
||||||
"test/smoke/out/**": true,
|
"test/smoke/out/**": true,
|
||||||
"test/automation/out/**": true,
|
"test/automation/out/**": true,
|
||||||
"test/integration/browser/out/**": true,
|
"test/integration/browser/out/**": true
|
||||||
"src2/**": true,
|
|
||||||
},
|
},
|
||||||
"files.readonlyExclude": {
|
"files.readonlyExclude": {
|
||||||
"build/builtin/*.js": true,
|
"build/builtin/*.js": true,
|
||||||
|
|
@ -94,13 +92,12 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"git.ignoreLimitWarning": true,
|
"git.ignoreLimitWarning": true,
|
||||||
// Removing this for Void:
|
"git.branchProtection": [
|
||||||
// "git.branchProtection": [
|
"main",
|
||||||
// "main",
|
"distro",
|
||||||
// "distro",
|
"release/*"
|
||||||
// "release/*"
|
],
|
||||||
// ],
|
"git.branchProtectionPrompt": "alwaysCommitToNewBranch",
|
||||||
// "git.branchProtectionPrompt": "alwaysCommitToNewBranch",
|
|
||||||
"git.branchRandomName.enable": true,
|
"git.branchRandomName.enable": true,
|
||||||
"git.pullBeforeCheckout": true,
|
"git.pullBeforeCheckout": true,
|
||||||
"git.mergeEditor": true,
|
"git.mergeEditor": true,
|
||||||
|
|
@ -171,5 +168,13 @@
|
||||||
},
|
},
|
||||||
"css.format.spaceAroundSelectorSeparator": true,
|
"css.format.spaceAroundSelectorSeparator": true,
|
||||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||||
"inlineChat.experimental.onlyZoneWidget": true
|
"eslint.useFlatConfig": true,
|
||||||
|
"editor.occurrencesHighlightDelay": 0,
|
||||||
|
"typescript.experimental.expandableHover": true,
|
||||||
|
"git.diagnosticsCommitHook.Enabled": true,
|
||||||
|
"git.diagnosticsCommitHook.Sources": {
|
||||||
|
"*": "error",
|
||||||
|
"ts": "warning",
|
||||||
|
"eslint": "warning"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
.vscode/shared.code-snippets
vendored
18
.vscode/shared.code-snippets
vendored
|
|
@ -36,23 +36,5 @@
|
||||||
"private readonly _onDid$1 = new Emitter<$2>();",
|
"private readonly _onDid$1 = new Emitter<$2>();",
|
||||||
"readonly onDid$1: Event<$2> = this._onDid$1.event;"
|
"readonly onDid$1: Event<$2> = this._onDid$1.event;"
|
||||||
],
|
],
|
||||||
},
|
|
||||||
"esm-comment": {
|
|
||||||
"scope": "typescript,javascript",
|
|
||||||
"prefix": "esm-comment",
|
|
||||||
"body": [
|
|
||||||
"// ESM-comment-begin",
|
|
||||||
"$SELECTION$0",
|
|
||||||
"// ESM-comment-end",
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"esm-uncomment": {
|
|
||||||
"scope": "typescript,javascript",
|
|
||||||
"prefix": "esm-uncomment",
|
|
||||||
"body": [
|
|
||||||
"// ESM-uncomment-begin",
|
|
||||||
"// $SELECTION$0",
|
|
||||||
"// ESM-uncomment-end",
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@ There are a few ways to contribute:
|
||||||
|
|
||||||
### Codebase Guide
|
### Codebase Guide
|
||||||
|
|
||||||
We highly recommend reading [this](https://github.com/microsoft/vscode/wiki/Source-Code-Organization) article on VSCode's sourcecode organization.
|
We [highly recommend reading this](https://github.com/microsoft/vscode/wiki/Source-Code-Organization) article on VSCode's sourcecode organization too. Void's codebase is pretty simple when you know what a service is and what `browser/` and `common/` mean, and the article covers all the jargon.
|
||||||
|
|
||||||
<!-- ADD BLOG HERE
|
<!-- ADD BLOG HERE
|
||||||
We wrote a [guide to working in VSCode].
|
We wrote a [guide to working in VSCode].
|
||||||
-->
|
-->
|
||||||
|
|
||||||
Most of Void's code lives in the two folders called `void/`.
|
Most of Void's code lives in the folder `src/vs/workbench/contrib/void/`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -61,13 +61,14 @@ To build Void, open `void/` inside VSCode. Then open your terminal and run:
|
||||||
3. Build Void.
|
3. Build Void.
|
||||||
- Press <kbd>Cmd+Shift+B</kbd> (Mac).
|
- Press <kbd>Cmd+Shift+B</kbd> (Mac).
|
||||||
- Press <kbd>Ctrl+Shift+B</kbd> (Windows/Linux).
|
- Press <kbd>Ctrl+Shift+B</kbd> (Windows/Linux).
|
||||||
- This step can take ~5 min. The build is done when you see two check marks.
|
- This step can take ~5 min. The build is done when you see two check marks (one of the items will continue spinning indefinitely - it compiles our React code).
|
||||||
4. Run Void.
|
4. Run Void.
|
||||||
- Run `./scripts/code.sh` (Mac/Linux).
|
- Run `./scripts/code.sh` (Mac/Linux).
|
||||||
- Run `./scripts/code.bat` (Windows).
|
- Run `./scripts/code.bat` (Windows).
|
||||||
6. Nice-to-knows.
|
6. Nice-to-knows.
|
||||||
- You can always press <kbd>Ctrl+R</kbd> (<kbd>Cmd+R</kbd>) inside the new window to reload and see your new changes. It's faster than <kbd>Ctrl+Shift+P</kbd> and `Reload Window`.
|
- You can always press <kbd>Ctrl+R</kbd> (<kbd>Cmd+R</kbd>) inside the new window to reload and see your new changes. It's faster than <kbd>Ctrl+Shift+P</kbd> and `Reload Window`.
|
||||||
- You might want to add the flags `--user-data-dir ./.tmp/user-data --extensions-dir ./.tmp/extensions` to the above run command, which lets you delete the `.tmp` folder to reset any IDE changes you made when testing.
|
- You might want to add the flags `--user-data-dir ./.tmp/user-data --extensions-dir ./.tmp/extensions` to the above run command, which lets you delete the `.tmp` folder to reset any IDE changes you made when testing.
|
||||||
|
- You can kill any of the build scripts by pressing `Ctrl+D` in VSCode terminal. If you press `Ctrl+C` the script will close but will keep running in the background (to open all background scripts, just re-build).
|
||||||
|
|
||||||
#### Building Void from Terminal
|
#### Building Void from Terminal
|
||||||
|
|
||||||
|
|
@ -85,7 +86,7 @@ Alternatively, if you want to build Void from the terminal, instead of pressing
|
||||||
#### Common Fixes
|
#### Common Fixes
|
||||||
|
|
||||||
- Make sure you followed the prerequisite steps.
|
- Make sure you followed the prerequisite steps.
|
||||||
- Make sure you have Node version `20.16.0` (the version in `.nvmrc`)!
|
- Make sure you have Node version `20.18.2` (the version in `.nvmrc`)!
|
||||||
- If you get `"TypeError: Failed to fetch dynamically imported module"`, make sure all imports end with `.js`.
|
- If you get `"TypeError: Failed to fetch dynamically imported module"`, make sure all imports end with `.js`.
|
||||||
- If you see missing styles, wait a few seconds and then reload.
|
- If you see missing styles, wait a few seconds and then reload.
|
||||||
- If you have any questions, feel free to [submit an issue](https://github.com/voideditor/void/issues/new). You can also refer to VSCode's complete [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute) page.
|
- If you have any questions, feel free to [submit an issue](https://github.com/voideditor/void/issues/new). You can also refer to VSCode's complete [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute) page.
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,34 @@ This repository incorporates material as listed below or described in the code.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
@fig/autocomplete-shared 1.1.2
|
||||||
|
https://github.com/withfig/autocomplete-tools
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Hercules Labs Inc. (Fig)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
@iktakahiro/markdown-it-katex 4.0.2 - MIT
|
@iktakahiro/markdown-it-katex 4.0.2 - MIT
|
||||||
|
|
@ -58,6 +86,34 @@ SOFTWARE.
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
amazon-q-developer-cli f66e0b0e917ab185eef528dc36eca56b78ca8b5d
|
||||||
|
https://github.com/aws/amazon-q-developer-cli
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Amazon.com, Inc. or its affiliates.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
atom/language-clojure 0.22.8 - MIT
|
atom/language-clojure 0.22.8 - MIT
|
||||||
https://github.com/atom/language-clojure
|
https://github.com/atom/language-clojure
|
||||||
|
|
||||||
|
|
@ -263,6 +319,34 @@ suitability for any purpose.
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
autocomplete 2.684.0 - MIT
|
||||||
|
https://github.com/withfig/autocomplete
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Hercules Labs Inc. (Fig)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
cacheable-request 7.0.4 - MIT
|
cacheable-request 7.0.4 - MIT
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -440,11 +524,11 @@ Title to copyright in this work will at all times remain with copyright holders.
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
dompurify 3.0.5 - Apache 2.0
|
dompurify 3.1.7 - Apache 2.0
|
||||||
https://github.com/cure53/DOMPurify
|
https://github.com/cure53/DOMPurify
|
||||||
|
|
||||||
DOMPurify
|
DOMPurify
|
||||||
Copyright 2024 Dr.-Ing. Mario Heiderich, Cure53
|
Copyright 2025 Dr.-Ing. Mario Heiderich, Cure53
|
||||||
|
|
||||||
DOMPurify is free software; you can redistribute it and/or modify it under the
|
DOMPurify is free software; you can redistribute it and/or modify it under the
|
||||||
terms of either:
|
terms of either:
|
||||||
|
|
@ -1119,7 +1203,7 @@ to the base-name name of the original file, and an extension of txt, html, or si
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
go-syntax 0.7.6 - MIT
|
go-syntax 0.7.9 - MIT
|
||||||
https://github.com/worlpaker/go-syntax
|
https://github.com/worlpaker/go-syntax
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
@ -1167,7 +1251,7 @@ without specific, written prior permission. Title to copyright in this document
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
Ionic documentation 1.2.4 - Apache2
|
Ionic documentation 1.2.4 - Apache-2.0
|
||||||
https://github.com/ionic-team/ionic-site
|
https://github.com/ionic-team/ionic-site
|
||||||
|
|
||||||
Copyright Drifty Co. http://drifty.com/.
|
Copyright Drifty Co. http://drifty.com/.
|
||||||
|
|
@ -1435,7 +1519,7 @@ SOFTWARE.
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
jlelong/vscode-latex-basics 1.9.0 - MIT
|
jlelong/vscode-latex-basics 1.10.0 - MIT
|
||||||
https://github.com/jlelong/vscode-latex-basics
|
https://github.com/jlelong/vscode-latex-basics
|
||||||
|
|
||||||
Copyright (c) vscode-latex-basics authors
|
Copyright (c) vscode-latex-basics authors
|
||||||
|
|
@ -1551,7 +1635,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SO
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
language-docker 0.0.0 - Apache2
|
language-docker 0.0.0 - Apache-2.0
|
||||||
https://github.com/moby/moby
|
https://github.com/moby/moby
|
||||||
|
|
||||||
Apache License
|
Apache License
|
||||||
|
|
@ -2108,7 +2192,7 @@ SOFTWARE.
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
RedCMD/YAML-Syntax-Highlighter 1.1.2 - MIT
|
RedCMD/YAML-Syntax-Highlighter 1.3.2 - MIT
|
||||||
https://github.com/RedCMD/YAML-Syntax-Highlighter
|
https://github.com/RedCMD/YAML-Syntax-Highlighter
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
@ -2164,7 +2248,7 @@ suitability for any purpose.
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
REditorSupport/vscode-R 2.8.1 - MIT
|
REditorSupport/vscode-R 2.8.4 - MIT
|
||||||
https://github.com/REditorSupport/vscode-R
|
https://github.com/REditorSupport/vscode-R
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
@ -2297,6 +2381,55 @@ SOFTWARE.
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
Shopify/ruby-lsp 0.0.0 - MIT License
|
||||||
|
https://github.com/Shopify/ruby-lsp
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2022-present, Shopify Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
The following files and related configuration in package.json are based on a
|
||||||
|
sequence of adaptions: grammars/ruby.cson.json, grammars/erb.cson.json,
|
||||||
|
languages/erb.json.
|
||||||
|
|
||||||
|
Copyright (c) 2016 Peng Lv
|
||||||
|
Copyright (c) 2017-2019 Stafford Brunk
|
||||||
|
https://github.com/rubyide/vscode-ruby
|
||||||
|
|
||||||
|
Released under the MIT license
|
||||||
|
https://github.com/rubyide/vscode-ruby/blob/main/LICENSE.txt
|
||||||
|
|
||||||
|
Copyright (c) 2014 GitHub Inc.
|
||||||
|
https://github.com/atom/language-ruby
|
||||||
|
|
||||||
|
Released under the MIT license
|
||||||
|
https://github.com/atom/language-ruby/blob/master/LICENSE.md
|
||||||
|
|
||||||
|
https://github.com/textmate/ruby.tmbundle
|
||||||
|
https://github.com/textmate/ruby.tmbundle#license
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
sumneko/lua.tmbundle 1.0.0 - TextMate Bundle License
|
sumneko/lua.tmbundle 1.0.0 - TextMate Bundle License
|
||||||
https://github.com/sumneko/lua.tmbundle
|
https://github.com/sumneko/lua.tmbundle
|
||||||
|
|
||||||
|
|
@ -2526,26 +2659,6 @@ to the base-name name of the original file, and an extension of txt, html, or si
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
textmate/ruby.tmbundle 0.0.0 - TextMate Bundle License
|
|
||||||
https://github.com/textmate/ruby.tmbundle
|
|
||||||
|
|
||||||
Copyright (c) textmate-ruby.tmbundle project authors
|
|
||||||
|
|
||||||
If not otherwise specified (see below), files in this folder fall under the following license:
|
|
||||||
|
|
||||||
Permission to copy, use, modify, sell and distribute this
|
|
||||||
software is granted. This software is provided "as is" without
|
|
||||||
express or implied warranty, and with no claim as to its
|
|
||||||
suitability for any purpose.
|
|
||||||
|
|
||||||
An exception is made for files in readable text which contain their own license information,
|
|
||||||
or files where an accompanying file exists (in the same directory) with a "-license" suffix added
|
|
||||||
to the base-name name of the original file, and an extension of txt, html, or similar. For example
|
|
||||||
"tidy" is accompanied by "tidy-license.txt".
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
trond-snekvik/vscode-rst 1.5.3 - MIT
|
trond-snekvik/vscode-rst 1.5.3 - MIT
|
||||||
https://github.com/trond-snekvik/vscode-rst
|
https://github.com/trond-snekvik/vscode-rst
|
||||||
|
|
||||||
|
|
@ -3056,7 +3169,7 @@ Creative Commons may be contacted at creativecommons.org.
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
vscode-logfile-highlighter 2.17.0 - MIT
|
vscode-logfile-highlighter 3.3.4 - MIT
|
||||||
https://github.com/emilast/vscode-logfile-highlighter
|
https://github.com/emilast/vscode-logfile-highlighter
|
||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
@ -3168,7 +3281,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
Web Background Synchronization - Apache2
|
Web Background Synchronization - Apache-2.0
|
||||||
https://github.com/WICG/background-sync
|
https://github.com/WICG/background-sync
|
||||||
|
|
||||||
Apache License
|
Apache License
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
The Void team put together this list of links to get up and running with VSCode's sourcecode. We hope it's helpful!
|
The Void team put together this list of links to get up and running with VSCode's sourcecode. We hope it's helpful!
|
||||||
|
|
||||||
|
For a complete guide on building Void, see [Contributing](https://github.com/voideditor/void/blob/main/CONTRIBUTING.md).
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
- [How VSCode's sourcecode is organized](https://github.com/microsoft/vscode/wiki/Source-Code-Organization) - this explains where the entry point files are, what `browser/` and `common/` mean, etc. This is the most important read on this whole list! We recommend reading the whole thing.
|
- [How VSCode's sourcecode is organized](https://github.com/microsoft/vscode/wiki/Source-Code-Organization) - this explains where the entry point files are, what `browser/` and `common/` mean, etc. This is the most important read on this whole list! We recommend reading the whole thing.
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
2024-09-04T10:21:29.952Z
|
2024-12-11T00:28:56.838Z
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,11 @@ fsevents/test/**
|
||||||
@vscode/windows-registry/build/**
|
@vscode/windows-registry/build/**
|
||||||
!@vscode/windows-registry/build/Release/*.node
|
!@vscode/windows-registry/build/Release/*.node
|
||||||
|
|
||||||
|
@vscode/tree-sitter-wasm/wasm/tree-sitter-*.wasm
|
||||||
|
!@vscode/tree-sitter-wasm/wasm/tree-sitter-typescript.wasm
|
||||||
|
!@vscode/tree-sitter-wasm/wasm/tree-sitter-regex.wasm
|
||||||
|
!@vscode/tree-sitter-wasm/wasm/tree-sitter-ini.wasm
|
||||||
|
|
||||||
native-keymap/binding.gyp
|
native-keymap/binding.gyp
|
||||||
native-keymap/build/**
|
native-keymap/build/**
|
||||||
native-keymap/src/**
|
native-keymap/src/**
|
||||||
|
|
@ -110,15 +115,13 @@ node-pty/third_party/**
|
||||||
@parcel/watcher/src/**
|
@parcel/watcher/src/**
|
||||||
!@parcel/watcher/build/Release/*.node
|
!@parcel/watcher/build/Release/*.node
|
||||||
|
|
||||||
vsda/build/**
|
vsda/**
|
||||||
vsda/ci/**
|
!vsda/index.js
|
||||||
vsda/src/**
|
!vsda/index.d.ts
|
||||||
vsda/.gitignore
|
!vsda/package.json
|
||||||
vsda/binding.gyp
|
|
||||||
vsda/README.md
|
|
||||||
vsda/SECURITY.md
|
|
||||||
vsda/targets
|
|
||||||
!vsda/build/Release/vsda.node
|
!vsda/build/Release/vsda.node
|
||||||
|
!vsda/rust/web/**
|
||||||
|
!vsda/rust/bundler/**
|
||||||
|
|
||||||
@vscode/policy-watcher/build/**
|
@vscode/policy-watcher/build/**
|
||||||
@vscode/policy-watcher/.husky/**
|
@vscode/policy-watcher/.husky/**
|
||||||
|
|
@ -132,6 +135,7 @@ vsda/targets
|
||||||
!@vscode/windows-ca-certs/package.json
|
!@vscode/windows-ca-certs/package.json
|
||||||
!@vscode/windows-ca-certs/**/*.node
|
!@vscode/windows-ca-certs/**/*.node
|
||||||
|
|
||||||
|
@vscode/node-addon-api/**/*
|
||||||
node-addon-api/**/*
|
node-addon-api/**/*
|
||||||
prebuild-install/**/*
|
prebuild-install/**/*
|
||||||
|
|
||||||
|
|
@ -163,7 +167,7 @@ typescript/lib/tsserverlibrary.js
|
||||||
|
|
||||||
jschardet/index.js
|
jschardet/index.js
|
||||||
jschardet/src/**
|
jschardet/src/**
|
||||||
# TODO@esm uncomment when we can use jschardet.min.js again jschardet/dist/jschardet.js
|
jschardet/dist/jschardet.js
|
||||||
|
|
||||||
es6-promise/lib/**
|
es6-promise/lib/**
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
jschardet/index.js
|
jschardet/index.js
|
||||||
jschardet/src/**
|
jschardet/src/**
|
||||||
# TODO@esm uncomment when we can use jschardet.min.js again jschardet/dist/jschardet.js
|
jschardet/dist/jschardet.js
|
||||||
|
|
||||||
vscode-textmate/webpack.config.js
|
vscode-textmate/webpack.config.js
|
||||||
|
|
||||||
|
|
@ -26,6 +26,9 @@ vscode-textmate/webpack.config.js
|
||||||
@xterm/addon-image/src/**
|
@xterm/addon-image/src/**
|
||||||
@xterm/addon-image/out/**
|
@xterm/addon-image/out/**
|
||||||
|
|
||||||
|
@xterm/addon-ligatures/src/**
|
||||||
|
@xterm/addon-ligatures/out/**
|
||||||
|
|
||||||
@xterm/addon-search/src/**
|
@xterm/addon-search/src/**
|
||||||
@xterm/addon-search/out/**
|
@xterm/addon-search/out/**
|
||||||
@xterm/addon-search/fixtures/**
|
@xterm/addon-search/fixtures/**
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,15 @@ steps:
|
||||||
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
|
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
|
||||||
|
|
||||||
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
|
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||||
|
- template: ../cli/cli-apply-patches.yml@self
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
npm ci
|
npm ci
|
||||||
workingDirectory: build
|
workingDirectory: build
|
||||||
displayName: Install pipeline build
|
env:
|
||||||
|
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||||
- template: ../cli/cli-apply-patches.yml@self
|
displayName: Install build dependencies
|
||||||
|
|
||||||
- task: Npm@1
|
- task: Npm@1
|
||||||
displayName: Download openssl prebuilt
|
displayName: Download openssl prebuilt
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ steps:
|
||||||
- task: AzureKeyVault@2
|
- task: AzureKeyVault@2
|
||||||
displayName: "Azure Key Vault: Get Secrets"
|
displayName: "Azure Key Vault: Get Secrets"
|
||||||
inputs:
|
inputs:
|
||||||
azureSubscription: "vscode-builds-subscription"
|
azureSubscription: vscode
|
||||||
KeyVaultName: vscode-build-secrets
|
KeyVaultName: vscode-build-secrets
|
||||||
SecretsFilter: "github-distro-mixin-password"
|
SecretsFilter: "github-distro-mixin-password"
|
||||||
|
|
||||||
|
|
@ -59,7 +59,7 @@ steps:
|
||||||
|
|
||||||
- task: Docker@1
|
- task: Docker@1
|
||||||
inputs:
|
inputs:
|
||||||
azureSubscriptionEndpoint: "vscode-builds-subscription"
|
azureSubscriptionEndpoint: vscode
|
||||||
azureContainerRegistry: vscodehub.azurecr.io
|
azureContainerRegistry: vscodehub.azurecr.io
|
||||||
command: "Run an image"
|
command: "Run an image"
|
||||||
imageName: "vscode-linux-build-agent:alpine-$(VSCODE_ARCH)"
|
imageName: "vscode-linux-build-agent:alpine-$(VSCODE_ARCH)"
|
||||||
|
|
@ -73,6 +73,7 @@ steps:
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
for i in {1..5}; do # try 5 times
|
for i in {1..5}; do # try 5 times
|
||||||
npm ci && break
|
npm ci && break
|
||||||
if [ $i -eq 5 ]; then
|
if [ $i -eq 5 ]; then
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,34 @@ steps:
|
||||||
${{ pair.key }}: ${{ pair.value }}
|
${{ pair.key }}: ${{ pair.value }}
|
||||||
|
|
||||||
- ${{ if contains(parameters.VSCODE_CLI_TARGET, '-windows-') }}:
|
- ${{ if contains(parameters.VSCODE_CLI_TARGET, '-windows-') }}:
|
||||||
|
- task: PublishSymbols@2
|
||||||
|
inputs:
|
||||||
|
IndexSources: false
|
||||||
|
SymbolsFolder: $(Build.SourcesDirectory)/cli/target/${{ parameters.VSCODE_CLI_TARGET }}/release
|
||||||
|
SearchPattern: 'code.pdb'
|
||||||
|
SymbolServerType: TeamServices
|
||||||
|
SymbolsProduct: 'code'
|
||||||
|
ArtifactServices.Symbol.AccountName: microsoft
|
||||||
|
ArtifactServices.Symbol.PAT: $(System.AccessToken)
|
||||||
|
ArtifactServices.Symbol.UseAAD: false
|
||||||
|
displayName: Publish Symbols
|
||||||
|
|
||||||
|
- task: CopyFiles@2
|
||||||
|
inputs:
|
||||||
|
SourceFolder: $(Build.SourcesDirectory)/cli/target/${{ parameters.VSCODE_CLI_TARGET }}/release
|
||||||
|
Contents: 'code.*'
|
||||||
|
TargetFolder: $(Agent.TempDirectory)/binskim-cli
|
||||||
|
displayName: Copy files for BinSkim
|
||||||
|
|
||||||
|
- task: BinSkim@4
|
||||||
|
inputs:
|
||||||
|
InputType: Basic
|
||||||
|
Function: analyze
|
||||||
|
TargetPattern: guardianGlob
|
||||||
|
AnalyzeTargetGlob: $(Agent.TempDirectory)/binskim-cli/*.*
|
||||||
|
AnalyzeSymPath: $(Agent.TempDirectory)/binskim-cli
|
||||||
|
displayName: Run BinSkim
|
||||||
|
|
||||||
- powershell: |
|
- powershell: |
|
||||||
. build/azure-pipelines/win32/exec.ps1
|
. build/azure-pipelines/win32/exec.ps1
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,21 @@ parameters:
|
||||||
default: []
|
default: []
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: AzureKeyVault@2
|
|
||||||
displayName: "Azure Key Vault: Get Secrets"
|
|
||||||
inputs:
|
|
||||||
azureSubscription: "vscode-builds-subscription"
|
|
||||||
KeyVaultName: vscode-build-secrets
|
|
||||||
SecretsFilter: "ESRP-PKI,esrp-aad-username,esrp-aad-password"
|
|
||||||
|
|
||||||
- task: UseDotNet@2
|
- task: UseDotNet@2
|
||||||
inputs:
|
inputs:
|
||||||
version: 6.x
|
version: 6.x
|
||||||
|
|
||||||
- task: EsrpClientTool@1
|
- task: EsrpCodeSigning@5
|
||||||
continueOnError: true
|
inputs:
|
||||||
displayName: Download ESRPClient
|
UseMSIAuthentication: true
|
||||||
|
ConnectedServiceName: vscode-esrp
|
||||||
|
AppRegistrationClientId: $(ESRP_CLIENT_ID)
|
||||||
|
AppRegistrationTenantId: $(ESRP_TENANT_ID)
|
||||||
|
AuthAKVName: vscode-esrp
|
||||||
|
AuthSignCertName: esrp-sign
|
||||||
|
FolderPath: .
|
||||||
|
Pattern: noop
|
||||||
|
displayName: 'Install ESRP Tooling'
|
||||||
|
|
||||||
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
|
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
|
|
@ -32,10 +33,14 @@ steps:
|
||||||
archiveFilePatterns: $(Build.ArtifactStagingDirectory)/pkg/${{ target }}/*.zip
|
archiveFilePatterns: $(Build.ArtifactStagingDirectory)/pkg/${{ target }}/*.zip
|
||||||
destinationFolder: $(Build.ArtifactStagingDirectory)/sign/${{ target }}
|
destinationFolder: $(Build.ArtifactStagingDirectory)/sign/${{ target }}
|
||||||
|
|
||||||
- script: node build/azure-pipelines/common/sign $(Agent.ToolsDirectory)/esrpclient/*/*/net6.0/esrpcli.dll sign-darwin $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) $(Build.ArtifactStagingDirectory)/pkg "*.zip"
|
- script: node build/azure-pipelines/common/sign $(Agent.RootDirectory)/_tasks/EsrpCodeSigning_*/*/net6.0/esrpcli.dll sign-darwin $(Build.ArtifactStagingDirectory)/pkg "*.zip"
|
||||||
|
env:
|
||||||
|
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||||
displayName: Codesign
|
displayName: Codesign
|
||||||
|
|
||||||
- script: node build/azure-pipelines/common/sign $(Agent.ToolsDirectory)/esrpclient/*/*/net6.0/esrpcli.dll notarize-darwin $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) $(Build.ArtifactStagingDirectory)/pkg "*.zip"
|
- script: node build/azure-pipelines/common/sign $(Agent.RootDirectory)/_tasks/EsrpCodeSigning_*/*/net6.0/esrpcli.dll notarize-darwin $(Build.ArtifactStagingDirectory)/pkg "*.zip"
|
||||||
|
env:
|
||||||
|
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||||
displayName: Notarize
|
displayName: Notarize
|
||||||
|
|
||||||
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
|
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,29 @@ parameters:
|
||||||
default: []
|
default: []
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: AzureKeyVault@2
|
|
||||||
displayName: "Azure Key Vault: Get Secrets"
|
|
||||||
inputs:
|
|
||||||
azureSubscription: "vscode-builds-subscription"
|
|
||||||
KeyVaultName: vscode-build-secrets
|
|
||||||
SecretsFilter: "ESRP-PKI,esrp-aad-username,esrp-aad-password"
|
|
||||||
|
|
||||||
- task: UseDotNet@2
|
- task: UseDotNet@2
|
||||||
inputs:
|
inputs:
|
||||||
version: 6.x
|
version: 6.x
|
||||||
|
|
||||||
- task: EsrpClientTool@1
|
- task: EsrpCodeSigning@5
|
||||||
displayName: "Use ESRP client"
|
inputs:
|
||||||
|
UseMSIAuthentication: true
|
||||||
|
ConnectedServiceName: vscode-esrp
|
||||||
|
AppRegistrationClientId: $(ESRP_CLIENT_ID)
|
||||||
|
AppRegistrationTenantId: $(ESRP_TENANT_ID)
|
||||||
|
AuthAKVName: vscode-esrp
|
||||||
|
AuthSignCertName: esrp-sign
|
||||||
|
FolderPath: .
|
||||||
|
Pattern: noop
|
||||||
|
displayName: 'Install ESRP Tooling'
|
||||||
|
|
||||||
|
- powershell: |
|
||||||
|
. build/azure-pipelines/win32/exec.ps1
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
$EsrpCodeSigningTool = (gci -directory -filter EsrpCodeSigning_* $(Agent.RootDirectory)\_tasks | Select-Object -last 1).FullName
|
||||||
|
$Version = (gci -directory $EsrpCodeSigningTool | Select-Object -last 1).FullName
|
||||||
|
echo "##vso[task.setvariable variable=EsrpCliDllPath]$Version\net6.0\esrpcli.dll"
|
||||||
|
displayName: Find ESRP CLI
|
||||||
|
|
||||||
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
|
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
|
|
@ -31,18 +41,9 @@ steps:
|
||||||
archiveFilePatterns: $(Build.ArtifactStagingDirectory)/pkg/${{ target }}/*.zip
|
archiveFilePatterns: $(Build.ArtifactStagingDirectory)/pkg/${{ target }}/*.zip
|
||||||
destinationFolder: $(Build.ArtifactStagingDirectory)/sign/${{ target }}
|
destinationFolder: $(Build.ArtifactStagingDirectory)/sign/${{ target }}
|
||||||
|
|
||||||
- powershell: |
|
- powershell: node build\azure-pipelines\common\sign $env:EsrpCliDllPath sign-windows $(Build.ArtifactStagingDirectory)/sign "*.exe"
|
||||||
. build/azure-pipelines/win32/exec.ps1
|
env:
|
||||||
$ErrorActionPreference = "Stop"
|
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||||
$EsrpClientTool = (gci -directory -filter EsrpClientTool_* $(Agent.RootDirectory)\_tasks | Select-Object -last 1).FullName
|
|
||||||
$EsrpCliZip = (gci -recurse -filter esrpcli.*.zip $EsrpClientTool | Select-Object -last 1).FullName
|
|
||||||
mkdir -p $(Agent.TempDirectory)\esrpcli
|
|
||||||
Expand-Archive -Path $EsrpCliZip -DestinationPath $(Agent.TempDirectory)\esrpcli
|
|
||||||
$EsrpCliDllPath = (gci -recurse -filter esrpcli.dll $(Agent.TempDirectory)\esrpcli | Select-Object -last 1).FullName
|
|
||||||
echo "##vso[task.setvariable variable=EsrpCliDllPath]$EsrpCliDllPath"
|
|
||||||
displayName: Find ESRP CLI
|
|
||||||
|
|
||||||
- powershell: node build\azure-pipelines\common\sign $env:EsrpCliDllPath sign-windows $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) $(Build.ArtifactStagingDirectory)/sign "*.exe"
|
|
||||||
displayName: Codesign
|
displayName: Codesign
|
||||||
|
|
||||||
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
|
- ${{ each target in parameters.VSCODE_CLI_ARTIFACTS }}:
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,15 @@
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const fs = require("fs");
|
const fs_1 = __importDefault(require("fs"));
|
||||||
const path = require("path");
|
const path_1 = __importDefault(require("path"));
|
||||||
const crypto = require("crypto");
|
const crypto_1 = __importDefault(require("crypto"));
|
||||||
const productjson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../../product.json'), 'utf8'));
|
const productjson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(__dirname, '../../../product.json'), 'utf8'));
|
||||||
const shasum = crypto.createHash('sha256');
|
const shasum = crypto_1.default.createHash('sha256');
|
||||||
for (const ext of productjson.builtInExtensions) {
|
for (const ext of productjson.builtInExtensions) {
|
||||||
shasum.update(`${ext.name}@${ext.version}`);
|
shasum.update(`${ext.name}@${ext.version}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as path from 'path';
|
import path from 'path';
|
||||||
import * as crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
|
|
||||||
const productjson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../../product.json'), 'utf8'));
|
const productjson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../../product.json'), 'utf8'));
|
||||||
const shasum = crypto.createHash('sha256');
|
const shasum = crypto.createHash('sha256');
|
||||||
|
|
|
||||||
|
|
@ -3,21 +3,24 @@
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const fs = require("fs");
|
const fs_1 = __importDefault(require("fs"));
|
||||||
const path = require("path");
|
const path_1 = __importDefault(require("path"));
|
||||||
const crypto = require("crypto");
|
const crypto_1 = __importDefault(require("crypto"));
|
||||||
const { dirs } = require('../../npm/dirs');
|
const { dirs } = require('../../npm/dirs');
|
||||||
const ROOT = path.join(__dirname, '../../../');
|
const ROOT = path_1.default.join(__dirname, '../../../');
|
||||||
const shasum = crypto.createHash('sha256');
|
const shasum = crypto_1.default.createHash('sha256');
|
||||||
shasum.update(fs.readFileSync(path.join(ROOT, 'build/.cachesalt')));
|
shasum.update(fs_1.default.readFileSync(path_1.default.join(ROOT, 'build/.cachesalt')));
|
||||||
shasum.update(fs.readFileSync(path.join(ROOT, '.npmrc')));
|
shasum.update(fs_1.default.readFileSync(path_1.default.join(ROOT, '.npmrc')));
|
||||||
shasum.update(fs.readFileSync(path.join(ROOT, 'build', '.npmrc')));
|
shasum.update(fs_1.default.readFileSync(path_1.default.join(ROOT, 'build', '.npmrc')));
|
||||||
shasum.update(fs.readFileSync(path.join(ROOT, 'remote', '.npmrc')));
|
shasum.update(fs_1.default.readFileSync(path_1.default.join(ROOT, 'remote', '.npmrc')));
|
||||||
// Add `package.json` and `package-lock.json` files
|
// Add `package.json` and `package-lock.json` files
|
||||||
for (const dir of dirs) {
|
for (const dir of dirs) {
|
||||||
const packageJsonPath = path.join(ROOT, dir, 'package.json');
|
const packageJsonPath = path_1.default.join(ROOT, dir, 'package.json');
|
||||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString());
|
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath).toString());
|
||||||
const relevantPackageJsonSections = {
|
const relevantPackageJsonSections = {
|
||||||
dependencies: packageJson.dependencies,
|
dependencies: packageJson.dependencies,
|
||||||
devDependencies: packageJson.devDependencies,
|
devDependencies: packageJson.devDependencies,
|
||||||
|
|
@ -26,8 +29,8 @@ for (const dir of dirs) {
|
||||||
distro: packageJson.distro
|
distro: packageJson.distro
|
||||||
};
|
};
|
||||||
shasum.update(JSON.stringify(relevantPackageJsonSections));
|
shasum.update(JSON.stringify(relevantPackageJsonSections));
|
||||||
const packageLockPath = path.join(ROOT, dir, 'package-lock.json');
|
const packageLockPath = path_1.default.join(ROOT, dir, 'package-lock.json');
|
||||||
shasum.update(fs.readFileSync(packageLockPath));
|
shasum.update(fs_1.default.readFileSync(packageLockPath));
|
||||||
}
|
}
|
||||||
// Add any other command line arguments
|
// Add any other command line arguments
|
||||||
for (let i = 2; i < process.argv.length; i++) {
|
for (let i = 2; i < process.argv.length; i++) {
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as path from 'path';
|
import path from 'path';
|
||||||
import * as crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
const { dirs } = require('../../npm/dirs');
|
const { dirs } = require('../../npm/dirs');
|
||||||
|
|
||||||
const ROOT = path.join(__dirname, '../../../');
|
const ROOT = path.join(__dirname, '../../../');
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ async function main() {
|
||||||
assets: [],
|
assets: [],
|
||||||
updates: {}
|
updates: {}
|
||||||
};
|
};
|
||||||
const aadCredentials = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']);
|
const aadCredentials = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN']));
|
||||||
const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials });
|
const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials });
|
||||||
const scripts = client.database('builds').container(quality).scripts;
|
const scripts = client.database('builds').container(quality).scripts;
|
||||||
await (0, retry_1.retry)(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }]));
|
await (0, retry_1.retry)(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }]));
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { ClientSecretCredential } from '@azure/identity';
|
import { ClientAssertionCredential } from '@azure/identity';
|
||||||
import { CosmosClient } from '@azure/cosmos';
|
import { CosmosClient } from '@azure/cosmos';
|
||||||
import { retry } from './retry';
|
import { retry } from './retry';
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ async function main(): Promise<void> {
|
||||||
updates: {}
|
updates: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
const aadCredentials = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!);
|
const aadCredentials = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!));
|
||||||
const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials });
|
const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials });
|
||||||
const scripts = client.database('builds').container(quality).scripts;
|
const scripts = client.database('builds').container(quality).scripts;
|
||||||
await retry(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }]));
|
await retry(() => scripts.storedProcedure('createBuild').execute('', [{ ...build, _partitionKey: '' }]));
|
||||||
|
|
|
||||||
0
build/azure-pipelines/common/extract-telemetry.sh
Normal file → Executable file
0
build/azure-pipelines/common/extract-telemetry.sh
Normal file → Executable file
47
build/azure-pipelines/common/getPublishAuthTokens.js
Normal file
47
build/azure-pipelines/common/getPublishAuthTokens.js
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
"use strict";
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.getAccessToken = getAccessToken;
|
||||||
|
const msal_node_1 = require("@azure/msal-node");
|
||||||
|
function e(name) {
|
||||||
|
const result = process.env[name];
|
||||||
|
if (typeof result !== 'string') {
|
||||||
|
throw new Error(`Missing env: ${name}`);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
async function getAccessToken(endpoint, tenantId, clientId, idToken) {
|
||||||
|
const app = new msal_node_1.ConfidentialClientApplication({
|
||||||
|
auth: {
|
||||||
|
clientId,
|
||||||
|
authority: `https://login.microsoftonline.com/${tenantId}`,
|
||||||
|
clientAssertion: idToken
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const result = await app.acquireTokenByClientCredential({ scopes: [`${endpoint}.default`] });
|
||||||
|
if (!result) {
|
||||||
|
throw new Error('Failed to get access token');
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
token: result.accessToken,
|
||||||
|
expiresOnTimestamp: result.expiresOn.getTime(),
|
||||||
|
refreshAfterTimestamp: result.refreshOn?.getTime()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
async function main() {
|
||||||
|
const cosmosDBAccessToken = await getAccessToken(e('AZURE_DOCUMENTDB_ENDPOINT'), e('AZURE_TENANT_ID'), e('AZURE_CLIENT_ID'), e('AZURE_ID_TOKEN'));
|
||||||
|
const blobServiceAccessToken = await getAccessToken(`https://${e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')}.blob.core.windows.net/`, process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_ID_TOKEN']);
|
||||||
|
console.log(JSON.stringify({ cosmosDBAccessToken, blobServiceAccessToken }));
|
||||||
|
}
|
||||||
|
if (require.main === module) {
|
||||||
|
main().then(() => {
|
||||||
|
process.exit(0);
|
||||||
|
}, err => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=getPublishAuthTokens.js.map
|
||||||
54
build/azure-pipelines/common/getPublishAuthTokens.ts
Normal file
54
build/azure-pipelines/common/getPublishAuthTokens.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { AccessToken } from '@azure/core-auth';
|
||||||
|
import { ConfidentialClientApplication } from '@azure/msal-node';
|
||||||
|
|
||||||
|
function e(name: string): string {
|
||||||
|
const result = process.env[name];
|
||||||
|
|
||||||
|
if (typeof result !== 'string') {
|
||||||
|
throw new Error(`Missing env: ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getAccessToken(endpoint: string, tenantId: string, clientId: string, idToken: string): Promise<AccessToken> {
|
||||||
|
const app = new ConfidentialClientApplication({
|
||||||
|
auth: {
|
||||||
|
clientId,
|
||||||
|
authority: `https://login.microsoftonline.com/${tenantId}`,
|
||||||
|
clientAssertion: idToken
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await app.acquireTokenByClientCredential({ scopes: [`${endpoint}.default`] });
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
throw new Error('Failed to get access token');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
token: result.accessToken,
|
||||||
|
expiresOnTimestamp: result.expiresOn!.getTime(),
|
||||||
|
refreshAfterTimestamp: result.refreshOn?.getTime()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const cosmosDBAccessToken = await getAccessToken(e('AZURE_DOCUMENTDB_ENDPOINT')!, e('AZURE_TENANT_ID')!, e('AZURE_CLIENT_ID')!, e('AZURE_ID_TOKEN')!);
|
||||||
|
const blobServiceAccessToken = await getAccessToken(`https://${e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')}.blob.core.windows.net/`, process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_ID_TOKEN']!);
|
||||||
|
console.log(JSON.stringify({ cosmosDBAccessToken, blobServiceAccessToken }));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
main().then(() => {
|
||||||
|
process.exit(0);
|
||||||
|
}, err => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -3,16 +3,19 @@
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const fs = require("fs");
|
const fs_1 = __importDefault(require("fs"));
|
||||||
const path = require("path");
|
const path_1 = __importDefault(require("path"));
|
||||||
if (process.argv.length !== 3) {
|
if (process.argv.length !== 3) {
|
||||||
console.error('Usage: node listNodeModules.js OUTPUT_FILE');
|
console.error('Usage: node listNodeModules.js OUTPUT_FILE');
|
||||||
process.exit(-1);
|
process.exit(-1);
|
||||||
}
|
}
|
||||||
const ROOT = path.join(__dirname, '../../../');
|
const ROOT = path_1.default.join(__dirname, '../../../');
|
||||||
function findNodeModulesFiles(location, inNodeModules, result) {
|
function findNodeModulesFiles(location, inNodeModules, result) {
|
||||||
const entries = fs.readdirSync(path.join(ROOT, location));
|
const entries = fs_1.default.readdirSync(path_1.default.join(ROOT, location));
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
const entryPath = `${location}/${entry}`;
|
const entryPath = `${location}/${entry}`;
|
||||||
if (/(^\/out)|(^\/src$)|(^\/.git$)|(^\/.build$)/.test(entryPath)) {
|
if (/(^\/out)|(^\/src$)|(^\/.git$)|(^\/.build$)/.test(entryPath)) {
|
||||||
|
|
@ -20,7 +23,7 @@ function findNodeModulesFiles(location, inNodeModules, result) {
|
||||||
}
|
}
|
||||||
let stat;
|
let stat;
|
||||||
try {
|
try {
|
||||||
stat = fs.statSync(path.join(ROOT, entryPath));
|
stat = fs_1.default.statSync(path_1.default.join(ROOT, entryPath));
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -37,5 +40,5 @@ function findNodeModulesFiles(location, inNodeModules, result) {
|
||||||
}
|
}
|
||||||
const result = [];
|
const result = [];
|
||||||
findNodeModulesFiles('', false, result);
|
findNodeModulesFiles('', false, result);
|
||||||
fs.writeFileSync(process.argv[2], result.join('\n') + '\n');
|
fs_1.default.writeFileSync(process.argv[2], result.join('\n') + '\n');
|
||||||
//# sourceMappingURL=listNodeModules.js.map
|
//# sourceMappingURL=listNodeModules.js.map
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
if (process.argv.length !== 3) {
|
if (process.argv.length !== 3) {
|
||||||
console.error('Usage: node listNodeModules.js OUTPUT_FILE');
|
console.error('Usage: node listNodeModules.js OUTPUT_FILE');
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,25 @@
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const fs = require("fs");
|
const fs_1 = __importDefault(require("fs"));
|
||||||
const path = require("path");
|
const path_1 = __importDefault(require("path"));
|
||||||
const stream_1 = require("stream");
|
const stream_1 = require("stream");
|
||||||
const promises_1 = require("node:stream/promises");
|
const promises_1 = require("node:stream/promises");
|
||||||
const yauzl = require("yauzl");
|
const yauzl_1 = __importDefault(require("yauzl"));
|
||||||
const crypto = require("crypto");
|
const crypto_1 = __importDefault(require("crypto"));
|
||||||
const retry_1 = require("./retry");
|
const retry_1 = require("./retry");
|
||||||
const cosmos_1 = require("@azure/cosmos");
|
const cosmos_1 = require("@azure/cosmos");
|
||||||
const identity_1 = require("@azure/identity");
|
const child_process_1 = __importDefault(require("child_process"));
|
||||||
const cp = require("child_process");
|
const os_1 = __importDefault(require("os"));
|
||||||
const os = require("os");
|
|
||||||
const node_worker_threads_1 = require("node:worker_threads");
|
const node_worker_threads_1 = require("node:worker_threads");
|
||||||
|
const msal_node_1 = require("@azure/msal-node");
|
||||||
|
const storage_blob_1 = require("@azure/storage-blob");
|
||||||
|
const jws_1 = __importDefault(require("jws"));
|
||||||
|
const node_timers_1 = require("node:timers");
|
||||||
function e(name) {
|
function e(name) {
|
||||||
const result = process.env[name];
|
const result = process.env[name];
|
||||||
if (typeof result !== 'string') {
|
if (typeof result !== 'string') {
|
||||||
|
|
@ -23,260 +29,264 @@ function e(name) {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
class Temp {
|
|
||||||
_files = [];
|
|
||||||
tmpNameSync() {
|
|
||||||
const file = path.join(os.tmpdir(), crypto.randomBytes(20).toString('hex'));
|
|
||||||
this._files.push(file);
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
dispose() {
|
|
||||||
for (const file of this._files) {
|
|
||||||
try {
|
|
||||||
fs.unlinkSync(file);
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function isCreateProvisionedFilesErrorResponse(response) {
|
|
||||||
return response?.ErrorDetails?.Code !== undefined;
|
|
||||||
}
|
|
||||||
class ProvisionService {
|
|
||||||
log;
|
|
||||||
accessToken;
|
|
||||||
constructor(log, accessToken) {
|
|
||||||
this.log = log;
|
|
||||||
this.accessToken = accessToken;
|
|
||||||
}
|
|
||||||
async provision(releaseId, fileId, fileName) {
|
|
||||||
const body = JSON.stringify({
|
|
||||||
ReleaseId: releaseId,
|
|
||||||
PortalName: 'VSCode',
|
|
||||||
PublisherCode: 'VSCode',
|
|
||||||
ProvisionedFilesCollection: [{
|
|
||||||
PublisherKey: fileId,
|
|
||||||
IsStaticFriendlyFileName: true,
|
|
||||||
FriendlyFileName: fileName,
|
|
||||||
MaxTTL: '1440',
|
|
||||||
CdnMappings: ['ECN']
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
this.log(`Provisioning ${fileName} (releaseId: ${releaseId}, fileId: ${fileId})...`);
|
|
||||||
const res = await (0, retry_1.retry)(() => this.request('POST', '/api/v2/ProvisionedFiles/CreateProvisionedFiles', { body }));
|
|
||||||
if (isCreateProvisionedFilesErrorResponse(res) && res.ErrorDetails.Code === 'FriendlyFileNameAlreadyProvisioned') {
|
|
||||||
this.log(`File already provisioned (most likley due to a re-run), skipping: ${fileName}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!res.IsSuccess) {
|
|
||||||
throw new Error(`Failed to submit provisioning request: ${JSON.stringify(res.ErrorDetails)}`);
|
|
||||||
}
|
|
||||||
this.log(`Successfully provisioned ${fileName}`);
|
|
||||||
}
|
|
||||||
async request(method, url, options) {
|
|
||||||
const opts = {
|
|
||||||
method,
|
|
||||||
body: options?.body,
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${this.accessToken}`,
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const res = await fetch(`https://dsprovisionapi.microsoft.com${url}`, opts);
|
|
||||||
// 400 normally means the request is bad or something is already provisioned, so we will return as retries are useless
|
|
||||||
// Otherwise log the text body and headers. We do text because some responses are not JSON.
|
|
||||||
if ((!res.ok || res.status < 200 || res.status >= 500) && res.status !== 400) {
|
|
||||||
throw new Error(`Unexpected status code: ${res.status}\nResponse Headers: ${JSON.stringify(res.headers)}\nBody Text: ${await res.text()}`);
|
|
||||||
}
|
|
||||||
return await res.json();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function hashStream(hashName, stream) {
|
function hashStream(hashName, stream) {
|
||||||
return new Promise((c, e) => {
|
return new Promise((c, e) => {
|
||||||
const shasum = crypto.createHash(hashName);
|
const shasum = crypto_1.default.createHash(hashName);
|
||||||
stream
|
stream
|
||||||
.on('data', shasum.update.bind(shasum))
|
.on('data', shasum.update.bind(shasum))
|
||||||
.on('error', e)
|
.on('error', e)
|
||||||
.on('close', () => c(shasum.digest('hex')));
|
.on('close', () => c(shasum.digest()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
class ESRPClient {
|
var StatusCode;
|
||||||
log;
|
(function (StatusCode) {
|
||||||
tmp;
|
StatusCode["Pass"] = "pass";
|
||||||
authPath;
|
StatusCode["Aborted"] = "aborted";
|
||||||
constructor(log, tmp, tenantId, clientId, authCertSubjectName, requestSigningCertSubjectName) {
|
StatusCode["Inprogress"] = "inprogress";
|
||||||
this.log = log;
|
StatusCode["FailCanRetry"] = "failCanRetry";
|
||||||
this.tmp = tmp;
|
StatusCode["FailDoNotRetry"] = "failDoNotRetry";
|
||||||
this.authPath = this.tmp.tmpNameSync();
|
StatusCode["PendingAnalysis"] = "pendingAnalysis";
|
||||||
fs.writeFileSync(this.authPath, JSON.stringify({
|
StatusCode["Cancelled"] = "cancelled";
|
||||||
Version: '1.0.0',
|
})(StatusCode || (StatusCode = {}));
|
||||||
AuthenticationType: 'AAD_CERT',
|
function getCertificateBuffer(input) {
|
||||||
TenantId: tenantId,
|
return Buffer.from(input.replace(/-----BEGIN CERTIFICATE-----|-----END CERTIFICATE-----|\n/g, ''), 'base64');
|
||||||
ClientId: clientId,
|
|
||||||
AuthCert: {
|
|
||||||
SubjectName: authCertSubjectName,
|
|
||||||
StoreLocation: 'LocalMachine',
|
|
||||||
StoreName: 'My',
|
|
||||||
SendX5c: 'true'
|
|
||||||
},
|
|
||||||
RequestSigningCert: {
|
|
||||||
SubjectName: requestSigningCertSubjectName,
|
|
||||||
StoreLocation: 'LocalMachine',
|
|
||||||
StoreName: 'My'
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
async release(version, filePath) {
|
|
||||||
this.log(`Submitting release for ${version}: ${filePath}`);
|
|
||||||
const submitReleaseResult = await this.SubmitRelease(version, filePath);
|
|
||||||
if (submitReleaseResult.submissionResponse.statusCode !== 'pass') {
|
|
||||||
throw new Error(`Unexpected status code: ${submitReleaseResult.submissionResponse.statusCode}`);
|
|
||||||
}
|
|
||||||
const releaseId = submitReleaseResult.submissionResponse.operationId;
|
|
||||||
this.log(`Successfully submitted release ${releaseId}. Polling for completion...`);
|
|
||||||
let details;
|
|
||||||
// Poll every 5 seconds, wait 60 minutes max -> poll 60/5*60=720 times
|
|
||||||
for (let i = 0; i < 720; i++) {
|
|
||||||
details = await this.ReleaseDetails(releaseId);
|
|
||||||
if (details.releaseDetails[0].statusCode === 'pass') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (details.releaseDetails[0].statusCode !== 'inprogress') {
|
|
||||||
throw new Error(`Failed to submit release: ${JSON.stringify(details)}`);
|
|
||||||
}
|
|
||||||
await new Promise(c => setTimeout(c, 5000));
|
|
||||||
}
|
|
||||||
if (details.releaseDetails[0].statusCode !== 'pass') {
|
|
||||||
throw new Error(`Timed out waiting for release ${releaseId}: ${JSON.stringify(details)}`);
|
|
||||||
}
|
|
||||||
const fileId = details.releaseDetails[0].fileDetails[0].publisherKey;
|
|
||||||
this.log('Release completed successfully with fileId: ', fileId);
|
|
||||||
return { releaseId, fileId };
|
|
||||||
}
|
|
||||||
async SubmitRelease(version, filePath) {
|
|
||||||
const policyPath = this.tmp.tmpNameSync();
|
|
||||||
fs.writeFileSync(policyPath, JSON.stringify({
|
|
||||||
Version: '1.0.0',
|
|
||||||
Audience: 'InternalLimited',
|
|
||||||
Intent: 'distribution',
|
|
||||||
ContentType: 'InstallPackage'
|
|
||||||
}));
|
|
||||||
const inputPath = this.tmp.tmpNameSync();
|
|
||||||
const size = fs.statSync(filePath).size;
|
|
||||||
const istream = fs.createReadStream(filePath);
|
|
||||||
const sha256 = await hashStream('sha256', istream);
|
|
||||||
fs.writeFileSync(inputPath, JSON.stringify({
|
|
||||||
Version: '1.0.0',
|
|
||||||
ReleaseInfo: {
|
|
||||||
ReleaseMetadata: {
|
|
||||||
Title: 'VS Code',
|
|
||||||
Properties: {
|
|
||||||
ReleaseContentType: 'InstallPackage'
|
|
||||||
},
|
|
||||||
MinimumNumberOfApprovers: 1
|
|
||||||
},
|
|
||||||
ProductInfo: {
|
|
||||||
Name: 'VS Code',
|
|
||||||
Version: version,
|
|
||||||
Description: path.basename(filePath, path.extname(filePath)),
|
|
||||||
},
|
|
||||||
Owners: [
|
|
||||||
{
|
|
||||||
Owner: {
|
|
||||||
UserPrincipalName: 'jomo@microsoft.com'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
Approvers: [
|
|
||||||
{
|
|
||||||
Approver: {
|
|
||||||
UserPrincipalName: 'jomo@microsoft.com'
|
|
||||||
},
|
|
||||||
IsAutoApproved: true,
|
|
||||||
IsMandatory: false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
AccessPermissions: {
|
|
||||||
MainPublisher: 'VSCode',
|
|
||||||
ChannelDownloadEntityDetails: {
|
|
||||||
Consumer: ['VSCode']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CreatedBy: {
|
|
||||||
UserPrincipalName: 'jomo@microsoft.com'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ReleaseBatches: [
|
|
||||||
{
|
|
||||||
ReleaseRequestFiles: [
|
|
||||||
{
|
|
||||||
SizeInBytes: size,
|
|
||||||
SourceHash: sha256,
|
|
||||||
HashType: 'SHA256',
|
|
||||||
SourceLocation: path.basename(filePath)
|
|
||||||
}
|
|
||||||
],
|
|
||||||
SourceLocationType: 'UNC',
|
|
||||||
SourceRootDirectory: path.dirname(filePath),
|
|
||||||
DestinationLocationType: 'AzureBlob'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}));
|
|
||||||
const outputPath = this.tmp.tmpNameSync();
|
|
||||||
cp.execSync(`ESRPClient SubmitRelease -a ${this.authPath} -p ${policyPath} -i ${inputPath} -o ${outputPath}`, { stdio: 'inherit' });
|
|
||||||
const output = fs.readFileSync(outputPath, 'utf8');
|
|
||||||
return JSON.parse(output);
|
|
||||||
}
|
|
||||||
async ReleaseDetails(releaseId) {
|
|
||||||
const inputPath = this.tmp.tmpNameSync();
|
|
||||||
fs.writeFileSync(inputPath, JSON.stringify({
|
|
||||||
Version: '1.0.0',
|
|
||||||
OperationIds: [releaseId]
|
|
||||||
}));
|
|
||||||
const outputPath = this.tmp.tmpNameSync();
|
|
||||||
cp.execSync(`ESRPClient ReleaseDetails -a ${this.authPath} -i ${inputPath} -o ${outputPath}`, { stdio: 'inherit' });
|
|
||||||
const output = fs.readFileSync(outputPath, 'utf8');
|
|
||||||
return JSON.parse(output);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async function releaseAndProvision(log, releaseTenantId, releaseClientId, releaseAuthCertSubjectName, releaseRequestSigningCertSubjectName, provisionTenantId, provisionAADUsername, provisionAADPassword, version, quality, filePath) {
|
function getThumbprint(input, algorithm) {
|
||||||
const fileName = `${quality}/${version}/${path.basename(filePath)}`;
|
const buffer = getCertificateBuffer(input);
|
||||||
const result = `${e('PRSS_CDN_URL')}/${fileName}`;
|
return crypto_1.default.createHash(algorithm).update(buffer).digest();
|
||||||
const res = await (0, retry_1.retry)(() => fetch(result));
|
}
|
||||||
if (res.status === 200) {
|
function getKeyFromPFX(pfx) {
|
||||||
log(`Already released and provisioned: ${result}`);
|
const pfxCertificatePath = path_1.default.join(os_1.default.tmpdir(), 'cert.pfx');
|
||||||
|
const pemKeyPath = path_1.default.join(os_1.default.tmpdir(), 'key.pem');
|
||||||
|
try {
|
||||||
|
const pfxCertificate = Buffer.from(pfx, 'base64');
|
||||||
|
fs_1.default.writeFileSync(pfxCertificatePath, pfxCertificate);
|
||||||
|
child_process_1.default.execSync(`openssl pkcs12 -in "${pfxCertificatePath}" -nocerts -nodes -out "${pemKeyPath}" -passin pass:`);
|
||||||
|
const raw = fs_1.default.readFileSync(pemKeyPath, 'utf-8');
|
||||||
|
const result = raw.match(/-----BEGIN PRIVATE KEY-----[\s\S]+?-----END PRIVATE KEY-----/g)[0];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
const tmp = new Temp();
|
finally {
|
||||||
process.on('exit', () => tmp.dispose());
|
fs_1.default.rmSync(pfxCertificatePath, { force: true });
|
||||||
const esrpclient = new ESRPClient(log, tmp, releaseTenantId, releaseClientId, releaseAuthCertSubjectName, releaseRequestSigningCertSubjectName);
|
fs_1.default.rmSync(pemKeyPath, { force: true });
|
||||||
const release = await esrpclient.release(version, filePath);
|
}
|
||||||
const credential = new identity_1.ClientSecretCredential(provisionTenantId, provisionAADUsername, provisionAADPassword);
|
}
|
||||||
const accessToken = await credential.getToken(['https://microsoft.onmicrosoft.com/DS.Provisioning.WebApi/.default']);
|
function getCertificatesFromPFX(pfx) {
|
||||||
const service = new ProvisionService(log, accessToken.token);
|
const pfxCertificatePath = path_1.default.join(os_1.default.tmpdir(), 'cert.pfx');
|
||||||
await service.provision(release.releaseId, release.fileId, fileName);
|
const pemCertificatePath = path_1.default.join(os_1.default.tmpdir(), 'cert.pem');
|
||||||
return result;
|
try {
|
||||||
|
const pfxCertificate = Buffer.from(pfx, 'base64');
|
||||||
|
fs_1.default.writeFileSync(pfxCertificatePath, pfxCertificate);
|
||||||
|
child_process_1.default.execSync(`openssl pkcs12 -in "${pfxCertificatePath}" -nokeys -out "${pemCertificatePath}" -passin pass:`);
|
||||||
|
const raw = fs_1.default.readFileSync(pemCertificatePath, 'utf-8');
|
||||||
|
const matches = raw.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g);
|
||||||
|
return matches ? matches.reverse() : [];
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
fs_1.default.rmSync(pfxCertificatePath, { force: true });
|
||||||
|
fs_1.default.rmSync(pemCertificatePath, { force: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ESRPReleaseService {
|
||||||
|
log;
|
||||||
|
clientId;
|
||||||
|
accessToken;
|
||||||
|
requestSigningCertificates;
|
||||||
|
requestSigningKey;
|
||||||
|
containerClient;
|
||||||
|
stagingSasToken;
|
||||||
|
static async create(log, tenantId, clientId, authCertificatePfx, requestSigningCertificatePfx, containerClient, stagingSasToken) {
|
||||||
|
const authKey = getKeyFromPFX(authCertificatePfx);
|
||||||
|
const authCertificate = getCertificatesFromPFX(authCertificatePfx)[0];
|
||||||
|
const requestSigningKey = getKeyFromPFX(requestSigningCertificatePfx);
|
||||||
|
const requestSigningCertificates = getCertificatesFromPFX(requestSigningCertificatePfx);
|
||||||
|
const app = new msal_node_1.ConfidentialClientApplication({
|
||||||
|
auth: {
|
||||||
|
clientId,
|
||||||
|
authority: `https://login.microsoftonline.com/${tenantId}`,
|
||||||
|
clientCertificate: {
|
||||||
|
thumbprintSha256: getThumbprint(authCertificate, 'sha256').toString('hex'),
|
||||||
|
privateKey: authKey,
|
||||||
|
x5c: authCertificate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const response = await app.acquireTokenByClientCredential({
|
||||||
|
scopes: ['https://api.esrp.microsoft.com/.default']
|
||||||
|
});
|
||||||
|
return new ESRPReleaseService(log, clientId, response.accessToken, requestSigningCertificates, requestSigningKey, containerClient, stagingSasToken);
|
||||||
|
}
|
||||||
|
static API_URL = 'https://api.esrp.microsoft.com/api/v3/releaseservices/clients/';
|
||||||
|
constructor(log, clientId, accessToken, requestSigningCertificates, requestSigningKey, containerClient, stagingSasToken) {
|
||||||
|
this.log = log;
|
||||||
|
this.clientId = clientId;
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
this.requestSigningCertificates = requestSigningCertificates;
|
||||||
|
this.requestSigningKey = requestSigningKey;
|
||||||
|
this.containerClient = containerClient;
|
||||||
|
this.stagingSasToken = stagingSasToken;
|
||||||
|
}
|
||||||
|
async createRelease(version, filePath, friendlyFileName) {
|
||||||
|
const correlationId = crypto_1.default.randomUUID();
|
||||||
|
const blobClient = this.containerClient.getBlockBlobClient(correlationId);
|
||||||
|
this.log(`Uploading ${filePath} to ${blobClient.url}`);
|
||||||
|
await blobClient.uploadFile(filePath);
|
||||||
|
this.log('Uploaded blob successfully');
|
||||||
|
try {
|
||||||
|
this.log(`Submitting release for ${version}: ${filePath}`);
|
||||||
|
const submitReleaseResult = await this.submitRelease(version, filePath, friendlyFileName, correlationId, blobClient);
|
||||||
|
this.log(`Successfully submitted release ${submitReleaseResult.operationId}. Polling for completion...`);
|
||||||
|
// Poll every 5 seconds, wait 60 minutes max -> poll 60/5*60=720 times
|
||||||
|
for (let i = 0; i < 720; i++) {
|
||||||
|
await new Promise(c => setTimeout(c, 5000));
|
||||||
|
const releaseStatus = await this.getReleaseStatus(submitReleaseResult.operationId);
|
||||||
|
if (releaseStatus.status === 'pass') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (releaseStatus.status === 'aborted') {
|
||||||
|
this.log(JSON.stringify(releaseStatus));
|
||||||
|
throw new Error(`Release was aborted`);
|
||||||
|
}
|
||||||
|
else if (releaseStatus.status !== 'inprogress') {
|
||||||
|
this.log(JSON.stringify(releaseStatus));
|
||||||
|
throw new Error(`Unknown error when polling for release`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const releaseDetails = await this.getReleaseDetails(submitReleaseResult.operationId);
|
||||||
|
if (releaseDetails.status !== 'pass') {
|
||||||
|
throw new Error(`Timed out waiting for release: ${JSON.stringify(releaseDetails)}`);
|
||||||
|
}
|
||||||
|
this.log('Successfully created release:', releaseDetails.files[0].fileDownloadDetails[0].downloadUrl);
|
||||||
|
return releaseDetails.files[0].fileDownloadDetails[0].downloadUrl;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
this.log(`Deleting blob ${blobClient.url}`);
|
||||||
|
await blobClient.delete();
|
||||||
|
this.log('Deleted blob successfully');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async submitRelease(version, filePath, friendlyFileName, correlationId, blobClient) {
|
||||||
|
const size = fs_1.default.statSync(filePath).size;
|
||||||
|
const hash = await hashStream('sha256', fs_1.default.createReadStream(filePath));
|
||||||
|
const blobUrl = `${blobClient.url}?${this.stagingSasToken}`;
|
||||||
|
const message = {
|
||||||
|
customerCorrelationId: correlationId,
|
||||||
|
esrpCorrelationId: correlationId,
|
||||||
|
driEmail: ['joao.moreno@microsoft.com'],
|
||||||
|
createdBy: { userPrincipalName: 'jomo@microsoft.com' },
|
||||||
|
owners: [{ owner: { userPrincipalName: 'jomo@microsoft.com' } }],
|
||||||
|
approvers: [{ approver: { userPrincipalName: 'jomo@microsoft.com' }, isAutoApproved: true, isMandatory: false }],
|
||||||
|
releaseInfo: {
|
||||||
|
title: 'VS Code',
|
||||||
|
properties: {
|
||||||
|
'ReleaseContentType': 'InstallPackage'
|
||||||
|
},
|
||||||
|
minimumNumberOfApprovers: 1
|
||||||
|
},
|
||||||
|
productInfo: {
|
||||||
|
name: 'VS Code',
|
||||||
|
version,
|
||||||
|
description: 'VS Code'
|
||||||
|
},
|
||||||
|
accessPermissionsInfo: {
|
||||||
|
mainPublisher: 'VSCode',
|
||||||
|
channelDownloadEntityDetails: {
|
||||||
|
AllDownloadEntities: ['VSCode']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
routingInfo: {
|
||||||
|
intent: 'filedownloadlinkgeneration'
|
||||||
|
},
|
||||||
|
files: [{
|
||||||
|
name: path_1.default.basename(filePath),
|
||||||
|
friendlyFileName,
|
||||||
|
tenantFileLocation: blobUrl,
|
||||||
|
tenantFileLocationType: 'AzureBlob',
|
||||||
|
sourceLocation: {
|
||||||
|
type: 'azureBlob',
|
||||||
|
blobUrl
|
||||||
|
},
|
||||||
|
hashType: 'sha256',
|
||||||
|
hash: Array.from(hash),
|
||||||
|
sizeInBytes: size
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
message.jwsToken = await this.generateJwsToken(message);
|
||||||
|
const res = await fetch(`${ESRPReleaseService.API_URL}${this.clientId}/workflows/release/operations`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${this.accessToken}`
|
||||||
|
},
|
||||||
|
body: JSON.stringify(message)
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const text = await res.text();
|
||||||
|
throw new Error(`Failed to submit release: ${res.statusText}\n${text}`);
|
||||||
|
}
|
||||||
|
return await res.json();
|
||||||
|
}
|
||||||
|
async getReleaseStatus(releaseId) {
|
||||||
|
const url = `${ESRPReleaseService.API_URL}${this.clientId}/workflows/release/operations/grs/${releaseId}`;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${this.accessToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const text = await res.text();
|
||||||
|
throw new Error(`Failed to get release status: ${res.statusText}\n${text}`);
|
||||||
|
}
|
||||||
|
return await res.json();
|
||||||
|
}
|
||||||
|
async getReleaseDetails(releaseId) {
|
||||||
|
const url = `${ESRPReleaseService.API_URL}${this.clientId}/workflows/release/operations/grd/${releaseId}`;
|
||||||
|
const res = await fetch(url, {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${this.accessToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
const text = await res.text();
|
||||||
|
throw new Error(`Failed to get release status: ${res.statusText}\n${text}`);
|
||||||
|
}
|
||||||
|
return await res.json();
|
||||||
|
}
|
||||||
|
async generateJwsToken(message) {
|
||||||
|
return jws_1.default.sign({
|
||||||
|
header: {
|
||||||
|
alg: 'RS256',
|
||||||
|
crit: ['exp', 'x5t'],
|
||||||
|
// Release service uses ticks, not seconds :roll_eyes: (https://stackoverflow.com/a/7968483)
|
||||||
|
exp: ((Date.now() + (6 * 60 * 1000)) * 10000) + 621355968000000000,
|
||||||
|
// Release service uses hex format, not base64url :roll_eyes:
|
||||||
|
x5t: getThumbprint(this.requestSigningCertificates[0], 'sha1').toString('hex'),
|
||||||
|
// Release service uses a '.' separated string, not an array of strings :roll_eyes:
|
||||||
|
x5c: this.requestSigningCertificates.map(c => getCertificateBuffer(c).toString('base64url')).join('.'),
|
||||||
|
},
|
||||||
|
payload: message,
|
||||||
|
privateKey: this.requestSigningKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class State {
|
class State {
|
||||||
statePath;
|
statePath;
|
||||||
set = new Set();
|
set = new Set();
|
||||||
constructor() {
|
constructor() {
|
||||||
const pipelineWorkspacePath = e('PIPELINE_WORKSPACE');
|
const pipelineWorkspacePath = e('PIPELINE_WORKSPACE');
|
||||||
const previousState = fs.readdirSync(pipelineWorkspacePath)
|
const previousState = fs_1.default.readdirSync(pipelineWorkspacePath)
|
||||||
.map(name => /^artifacts_processed_(\d+)$/.exec(name))
|
.map(name => /^artifacts_processed_(\d+)$/.exec(name))
|
||||||
.filter((match) => !!match)
|
.filter((match) => !!match)
|
||||||
.map(match => ({ name: match[0], attempt: Number(match[1]) }))
|
.map(match => ({ name: match[0], attempt: Number(match[1]) }))
|
||||||
.sort((a, b) => b.attempt - a.attempt)[0];
|
.sort((a, b) => b.attempt - a.attempt)[0];
|
||||||
if (previousState) {
|
if (previousState) {
|
||||||
const previousStatePath = path.join(pipelineWorkspacePath, previousState.name, previousState.name + '.txt');
|
const previousStatePath = path_1.default.join(pipelineWorkspacePath, previousState.name, previousState.name + '.txt');
|
||||||
fs.readFileSync(previousStatePath, 'utf8').split(/\n/).filter(name => !!name).forEach(name => this.set.add(name));
|
fs_1.default.readFileSync(previousStatePath, 'utf8').split(/\n/).filter(name => !!name).forEach(name => this.set.add(name));
|
||||||
}
|
}
|
||||||
const stageAttempt = e('SYSTEM_STAGEATTEMPT');
|
const stageAttempt = e('SYSTEM_STAGEATTEMPT');
|
||||||
this.statePath = path.join(pipelineWorkspacePath, `artifacts_processed_${stageAttempt}`, `artifacts_processed_${stageAttempt}.txt`);
|
this.statePath = path_1.default.join(pipelineWorkspacePath, `artifacts_processed_${stageAttempt}`, `artifacts_processed_${stageAttempt}.txt`);
|
||||||
fs.mkdirSync(path.dirname(this.statePath), { recursive: true });
|
fs_1.default.mkdirSync(path_1.default.dirname(this.statePath), { recursive: true });
|
||||||
fs.writeFileSync(this.statePath, [...this.set.values()].map(name => `${name}\n`).join(''));
|
fs_1.default.writeFileSync(this.statePath, [...this.set.values()].map(name => `${name}\n`).join(''));
|
||||||
}
|
}
|
||||||
get size() {
|
get size() {
|
||||||
return this.set.size;
|
return this.set.size;
|
||||||
|
|
@ -286,7 +296,7 @@ class State {
|
||||||
}
|
}
|
||||||
add(name) {
|
add(name) {
|
||||||
this.set.add(name);
|
this.set.add(name);
|
||||||
fs.appendFileSync(this.statePath, `${name}\n`);
|
fs_1.default.appendFileSync(this.statePath, `${name}\n`);
|
||||||
}
|
}
|
||||||
[Symbol.iterator]() {
|
[Symbol.iterator]() {
|
||||||
return this.set[Symbol.iterator]();
|
return this.set[Symbol.iterator]();
|
||||||
|
|
@ -332,7 +342,7 @@ async function downloadArtifact(artifact, downloadPath) {
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error(`Unexpected status code: ${res.status}`);
|
throw new Error(`Unexpected status code: ${res.status}`);
|
||||||
}
|
}
|
||||||
await (0, promises_1.pipeline)(stream_1.Readable.fromWeb(res.body), fs.createWriteStream(downloadPath));
|
await (0, promises_1.pipeline)(stream_1.Readable.fromWeb(res.body), fs_1.default.createWriteStream(downloadPath));
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
|
|
@ -340,7 +350,7 @@ async function downloadArtifact(artifact, downloadPath) {
|
||||||
}
|
}
|
||||||
async function unzip(packagePath, outputPath) {
|
async function unzip(packagePath, outputPath) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
yauzl.open(packagePath, { lazyEntries: true, autoClose: true }, (err, zipfile) => {
|
yauzl_1.default.open(packagePath, { lazyEntries: true, autoClose: true }, (err, zipfile) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
|
|
@ -354,9 +364,9 @@ async function unzip(packagePath, outputPath) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
const filePath = path.join(outputPath, entry.fileName);
|
const filePath = path_1.default.join(outputPath, entry.fileName);
|
||||||
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
fs_1.default.mkdirSync(path_1.default.dirname(filePath), { recursive: true });
|
||||||
const ostream = fs.createWriteStream(filePath);
|
const ostream = fs_1.default.createWriteStream(filePath);
|
||||||
ostream.on('finish', () => {
|
ostream.on('finish', () => {
|
||||||
result.push(filePath);
|
result.push(filePath);
|
||||||
zipfile.readEntry();
|
zipfile.readEntry();
|
||||||
|
|
@ -473,33 +483,102 @@ function getRealType(type) {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function processArtifact(artifact, artifactFilePath) {
|
async function withLease(client, fn) {
|
||||||
|
const lease = client.getBlobLeaseClient();
|
||||||
|
for (let i = 0; i < 360; i++) { // Try to get lease for 30 minutes
|
||||||
|
try {
|
||||||
|
await client.uploadData(new ArrayBuffer()); // blob needs to exist for lease to be acquired
|
||||||
|
await lease.acquireLease(60);
|
||||||
|
try {
|
||||||
|
const abortController = new AbortController();
|
||||||
|
const refresher = new Promise((c, e) => {
|
||||||
|
abortController.signal.onabort = () => {
|
||||||
|
(0, node_timers_1.clearInterval)(interval);
|
||||||
|
c();
|
||||||
|
};
|
||||||
|
const interval = (0, node_timers_1.setInterval)(() => {
|
||||||
|
lease.renewLease().catch(err => {
|
||||||
|
(0, node_timers_1.clearInterval)(interval);
|
||||||
|
e(new Error('Failed to renew lease ' + err));
|
||||||
|
});
|
||||||
|
}, 30_000);
|
||||||
|
});
|
||||||
|
const result = await Promise.race([fn(), refresher]);
|
||||||
|
abortController.abort();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
await lease.releaseLease();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err.statusCode !== 409 && err.statusCode !== 412) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
await new Promise(c => setTimeout(c, 5000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error('Failed to acquire lease on blob after 30 minutes');
|
||||||
|
}
|
||||||
|
async function processArtifact(artifact, filePath) {
|
||||||
const log = (...args) => console.log(`[${artifact.name}]`, ...args);
|
const log = (...args) => console.log(`[${artifact.name}]`, ...args);
|
||||||
const match = /^vscode_(?<product>[^_]+)_(?<os>[^_]+)(?:_legacy)?_(?<arch>[^_]+)_(?<unprocessedType>[^_]+)$/.exec(artifact.name);
|
const match = /^vscode_(?<product>[^_]+)_(?<os>[^_]+)(?:_legacy)?_(?<arch>[^_]+)_(?<unprocessedType>[^_]+)$/.exec(artifact.name);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
throw new Error(`Invalid artifact name: ${artifact.name}`);
|
throw new Error(`Invalid artifact name: ${artifact.name}`);
|
||||||
}
|
}
|
||||||
// getPlatform needs the unprocessedType
|
const { cosmosDBAccessToken, blobServiceAccessToken } = JSON.parse(e('PUBLISH_AUTH_TOKENS'));
|
||||||
const quality = e('VSCODE_QUALITY');
|
const quality = e('VSCODE_QUALITY');
|
||||||
const commit = e('BUILD_SOURCEVERSION');
|
const version = e('BUILD_SOURCEVERSION');
|
||||||
const { product, os, arch, unprocessedType } = match.groups;
|
const friendlyFileName = `${quality}/${version}/${path_1.default.basename(filePath)}`;
|
||||||
const isLegacy = artifact.name.includes('_legacy');
|
const blobServiceClient = new storage_blob_1.BlobServiceClient(`https://${e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')}.blob.core.windows.net/`, { getToken: async () => blobServiceAccessToken });
|
||||||
const platform = getPlatform(product, os, arch, unprocessedType, isLegacy);
|
const leasesContainerClient = blobServiceClient.getContainerClient('leases');
|
||||||
const type = getRealType(unprocessedType);
|
await leasesContainerClient.createIfNotExists();
|
||||||
const size = fs.statSync(artifactFilePath).size;
|
const leaseBlobClient = leasesContainerClient.getBlockBlobClient(friendlyFileName);
|
||||||
const stream = fs.createReadStream(artifactFilePath);
|
log(`Acquiring lease for: ${friendlyFileName}`);
|
||||||
const [hash, sha256hash] = await Promise.all([hashStream('sha1', stream), hashStream('sha256', stream)]); // CodeQL [SM04514] Using SHA1 only for legacy reasons, we are actually only respecting SHA256
|
await withLease(leaseBlobClient, async () => {
|
||||||
const url = await releaseAndProvision(log, e('RELEASE_TENANT_ID'), e('RELEASE_CLIENT_ID'), e('RELEASE_AUTH_CERT_SUBJECT_NAME'), e('RELEASE_REQUEST_SIGNING_CERT_SUBJECT_NAME'), e('PROVISION_TENANT_ID'), e('PROVISION_AAD_USERNAME'), e('PROVISION_AAD_PASSWORD'), commit, quality, artifactFilePath);
|
log(`Successfully acquired lease for: ${friendlyFileName}`);
|
||||||
const asset = { platform, type, url, hash, sha256hash, size, supportsFastUpdate: true };
|
const url = `${e('PRSS_CDN_URL')}/${friendlyFileName}`;
|
||||||
log('Creating asset...', JSON.stringify(asset, undefined, 2));
|
const res = await (0, retry_1.retry)(() => fetch(url));
|
||||||
await (0, retry_1.retry)(async (attempt) => {
|
if (res.status === 200) {
|
||||||
log(`Creating asset in Cosmos DB (attempt ${attempt})...`);
|
log(`Already released and provisioned: ${url}`);
|
||||||
const aadCredentials = new identity_1.ClientSecretCredential(e('AZURE_TENANT_ID'), e('AZURE_CLIENT_ID'), e('AZURE_CLIENT_SECRET'));
|
}
|
||||||
const client = new cosmos_1.CosmosClient({ endpoint: e('AZURE_DOCUMENTDB_ENDPOINT'), aadCredentials });
|
else {
|
||||||
const scripts = client.database('builds').container(quality).scripts;
|
const stagingContainerClient = blobServiceClient.getContainerClient('staging');
|
||||||
await scripts.storedProcedure('createAsset').execute('', [commit, asset, true]);
|
await stagingContainerClient.createIfNotExists();
|
||||||
|
const now = new Date().valueOf();
|
||||||
|
const oneHour = 60 * 60 * 1000;
|
||||||
|
const oneHourAgo = new Date(now - oneHour);
|
||||||
|
const oneHourFromNow = new Date(now + oneHour);
|
||||||
|
const userDelegationKey = await blobServiceClient.getUserDelegationKey(oneHourAgo, oneHourFromNow);
|
||||||
|
const sasOptions = { containerName: 'staging', permissions: storage_blob_1.ContainerSASPermissions.from({ read: true }), startsOn: oneHourAgo, expiresOn: oneHourFromNow };
|
||||||
|
const stagingSasToken = (0, storage_blob_1.generateBlobSASQueryParameters)(sasOptions, userDelegationKey, e('VSCODE_STAGING_BLOB_STORAGE_ACCOUNT_NAME')).toString();
|
||||||
|
const releaseService = await ESRPReleaseService.create(log, e('RELEASE_TENANT_ID'), e('RELEASE_CLIENT_ID'), e('RELEASE_AUTH_CERT'), e('RELEASE_REQUEST_SIGNING_CERT'), stagingContainerClient, stagingSasToken);
|
||||||
|
await releaseService.createRelease(version, filePath, friendlyFileName);
|
||||||
|
}
|
||||||
|
const { product, os, arch, unprocessedType } = match.groups;
|
||||||
|
const isLegacy = artifact.name.includes('_legacy');
|
||||||
|
const platform = getPlatform(product, os, arch, unprocessedType, isLegacy);
|
||||||
|
const type = getRealType(unprocessedType);
|
||||||
|
const size = fs_1.default.statSync(filePath).size;
|
||||||
|
const stream = fs_1.default.createReadStream(filePath);
|
||||||
|
const [hash, sha256hash] = await Promise.all([hashStream('sha1', stream), hashStream('sha256', stream)]); // CodeQL [SM04514] Using SHA1 only for legacy reasons, we are actually only respecting SHA256
|
||||||
|
const asset = { platform, type, url, hash: hash.toString('hex'), sha256hash: sha256hash.toString('hex'), size, supportsFastUpdate: true };
|
||||||
|
log('Creating asset...');
|
||||||
|
const result = await (0, retry_1.retry)(async (attempt) => {
|
||||||
|
log(`Creating asset in Cosmos DB (attempt ${attempt})...`);
|
||||||
|
const client = new cosmos_1.CosmosClient({ endpoint: e('AZURE_DOCUMENTDB_ENDPOINT'), tokenProvider: () => Promise.resolve(`type=aad&ver=1.0&sig=${cosmosDBAccessToken.token}`) });
|
||||||
|
const scripts = client.database('builds').container(quality).scripts;
|
||||||
|
const { resource: result } = await scripts.storedProcedure('createAsset').execute('', [version, asset, true]);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
if (result === 'already exists') {
|
||||||
|
log('Asset already exists!');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log('Asset successfully created: ', JSON.stringify(asset, undefined, 2));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
log('Asset successfully created');
|
log(`Successfully released lease for: ${friendlyFileName}`);
|
||||||
}
|
}
|
||||||
// It is VERY important that we don't download artifacts too much too fast from AZDO.
|
// It is VERY important that we don't download artifacts too much too fast from AZDO.
|
||||||
// AZDO throttles us SEVERELY if we do. Not just that, but they also close open
|
// AZDO throttles us SEVERELY if we do. Not just that, but they also close open
|
||||||
|
|
@ -518,7 +597,13 @@ async function main() {
|
||||||
for (const name of done) {
|
for (const name of done) {
|
||||||
console.log(`\u2705 ${name}`);
|
console.log(`\u2705 ${name}`);
|
||||||
}
|
}
|
||||||
const stages = new Set(['Compile', 'CompileCLI']);
|
const stages = new Set(['Compile']);
|
||||||
|
if (e('VSCODE_BUILD_STAGE_LINUX') === 'True' ||
|
||||||
|
e('VSCODE_BUILD_STAGE_ALPINE') === 'True' ||
|
||||||
|
e('VSCODE_BUILD_STAGE_MACOS') === 'True' ||
|
||||||
|
e('VSCODE_BUILD_STAGE_WINDOWS') === 'True') {
|
||||||
|
stages.add('CompileCLI');
|
||||||
|
}
|
||||||
if (e('VSCODE_BUILD_STAGE_WINDOWS') === 'True') {
|
if (e('VSCODE_BUILD_STAGE_WINDOWS') === 'True') {
|
||||||
stages.add('Windows');
|
stages.add('Windows');
|
||||||
}
|
}
|
||||||
|
|
@ -561,12 +646,12 @@ async function main() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
console.log(`[${artifact.name}] Found new artifact`);
|
console.log(`[${artifact.name}] Found new artifact`);
|
||||||
const artifactZipPath = path.join(e('AGENT_TEMPDIRECTORY'), `${artifact.name}.zip`);
|
const artifactZipPath = path_1.default.join(e('AGENT_TEMPDIRECTORY'), `${artifact.name}.zip`);
|
||||||
await (0, retry_1.retry)(async (attempt) => {
|
await (0, retry_1.retry)(async (attempt) => {
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
console.log(`[${artifact.name}] Downloading (attempt ${attempt})...`);
|
console.log(`[${artifact.name}] Downloading (attempt ${attempt})...`);
|
||||||
await downloadArtifact(artifact, artifactZipPath);
|
await downloadArtifact(artifact, artifactZipPath);
|
||||||
const archiveSize = fs.statSync(artifactZipPath).size;
|
const archiveSize = fs_1.default.statSync(artifactZipPath).size;
|
||||||
const downloadDurationS = (Date.now() - start) / 1000;
|
const downloadDurationS = (Date.now() - start) / 1000;
|
||||||
const downloadSpeedKBS = Math.round((archiveSize / 1024) / downloadDurationS);
|
const downloadSpeedKBS = Math.round((archiveSize / 1024) / downloadDurationS);
|
||||||
console.log(`[${artifact.name}] Successfully downloaded after ${Math.floor(downloadDurationS)} seconds(${downloadSpeedKBS} KB/s).`);
|
console.log(`[${artifact.name}] Successfully downloaded after ${Math.floor(downloadDurationS)} seconds(${downloadSpeedKBS} KB/s).`);
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -31,7 +31,7 @@ async function getConfig(client, quality) {
|
||||||
async function main(force) {
|
async function main(force) {
|
||||||
const commit = getEnv('BUILD_SOURCEVERSION');
|
const commit = getEnv('BUILD_SOURCEVERSION');
|
||||||
const quality = getEnv('VSCODE_QUALITY');
|
const quality = getEnv('VSCODE_QUALITY');
|
||||||
const aadCredentials = new identity_1.ClientSecretCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], process.env['AZURE_CLIENT_SECRET']);
|
const aadCredentials = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN']));
|
||||||
const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials });
|
const client = new cosmos_1.CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT'], aadCredentials });
|
||||||
if (!force) {
|
if (!force) {
|
||||||
const config = await getConfig(client, quality);
|
const config = await getConfig(client, quality);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { ClientSecretCredential } from '@azure/identity';
|
import { ClientAssertionCredential } from '@azure/identity';
|
||||||
import { CosmosClient } from '@azure/cosmos';
|
import { CosmosClient } from '@azure/cosmos';
|
||||||
import { retry } from './retry';
|
import { retry } from './retry';
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ async function main(force: boolean): Promise<void> {
|
||||||
const commit = getEnv('BUILD_SOURCEVERSION');
|
const commit = getEnv('BUILD_SOURCEVERSION');
|
||||||
const quality = getEnv('VSCODE_QUALITY');
|
const quality = getEnv('VSCODE_QUALITY');
|
||||||
|
|
||||||
const aadCredentials = new ClientSecretCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, process.env['AZURE_CLIENT_SECRET']!);
|
const aadCredentials = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!));
|
||||||
const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials });
|
const client = new CosmosClient({ endpoint: process.env['AZURE_DOCUMENTDB_ENDPOINT']!, aadCredentials });
|
||||||
|
|
||||||
if (!force) {
|
if (!force) {
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,16 @@
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const sign_1 = require("./sign");
|
const sign_1 = require("./sign");
|
||||||
const path = require("path");
|
const path_1 = __importDefault(require("path"));
|
||||||
(0, sign_1.main)([
|
(0, sign_1.main)([
|
||||||
process.env['EsrpCliDllPath'],
|
process.env['EsrpCliDllPath'],
|
||||||
'sign-windows',
|
'sign-windows',
|
||||||
process.env['ESRPPKI'],
|
path_1.default.dirname(process.argv[2]),
|
||||||
process.env['ESRPAADUsername'],
|
path_1.default.basename(process.argv[2])
|
||||||
process.env['ESRPAADPassword'],
|
|
||||||
path.dirname(process.argv[2]),
|
|
||||||
path.basename(process.argv[2])
|
|
||||||
]);
|
]);
|
||||||
//# sourceMappingURL=sign-win32.js.map
|
//# sourceMappingURL=sign-win32.js.map
|
||||||
|
|
@ -4,14 +4,11 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { main } from './sign';
|
import { main } from './sign';
|
||||||
import * as path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
main([
|
main([
|
||||||
process.env['EsrpCliDllPath']!,
|
process.env['EsrpCliDllPath']!,
|
||||||
'sign-windows',
|
'sign-windows',
|
||||||
process.env['ESRPPKI']!,
|
|
||||||
process.env['ESRPAADUsername']!,
|
|
||||||
process.env['ESRPAADPassword']!,
|
|
||||||
path.dirname(process.argv[2]),
|
path.dirname(process.argv[2]),
|
||||||
path.basename(process.argv[2])
|
path.basename(process.argv[2])
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -3,25 +3,28 @@
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.Temp = void 0;
|
exports.Temp = void 0;
|
||||||
exports.main = main;
|
exports.main = main;
|
||||||
const cp = require("child_process");
|
const child_process_1 = __importDefault(require("child_process"));
|
||||||
const fs = require("fs");
|
const fs_1 = __importDefault(require("fs"));
|
||||||
const crypto = require("crypto");
|
const crypto_1 = __importDefault(require("crypto"));
|
||||||
const path = require("path");
|
const path_1 = __importDefault(require("path"));
|
||||||
const os = require("os");
|
const os_1 = __importDefault(require("os"));
|
||||||
class Temp {
|
class Temp {
|
||||||
_files = [];
|
_files = [];
|
||||||
tmpNameSync() {
|
tmpNameSync() {
|
||||||
const file = path.join(os.tmpdir(), crypto.randomBytes(20).toString('hex'));
|
const file = path_1.default.join(os_1.default.tmpdir(), crypto_1.default.randomBytes(20).toString('hex'));
|
||||||
this._files.push(file);
|
this._files.push(file);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
dispose() {
|
dispose() {
|
||||||
for (const file of this._files) {
|
for (const file of this._files) {
|
||||||
try {
|
try {
|
||||||
fs.unlinkSync(file);
|
fs_1.default.unlinkSync(file);
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
// noop
|
// noop
|
||||||
|
|
@ -105,37 +108,61 @@ function getParams(type) {
|
||||||
toolName: 'sign',
|
toolName: 'sign',
|
||||||
toolVersion: '1.0'
|
toolVersion: '1.0'
|
||||||
}];
|
}];
|
||||||
|
case 'nuget':
|
||||||
|
return [{
|
||||||
|
keyCode: 'CP-401405',
|
||||||
|
operationSetCode: 'NuGetSign',
|
||||||
|
parameters: [],
|
||||||
|
toolName: 'sign',
|
||||||
|
toolVersion: '1.0'
|
||||||
|
}, {
|
||||||
|
keyCode: 'CP-401405',
|
||||||
|
operationSetCode: 'NuGetVerify',
|
||||||
|
parameters: [],
|
||||||
|
toolName: 'sign',
|
||||||
|
toolVersion: '1.0'
|
||||||
|
}];
|
||||||
default:
|
default:
|
||||||
throw new Error(`Sign type ${type} not found`);
|
throw new Error(`Sign type ${type} not found`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function main([esrpCliPath, type, cert, username, password, folderPath, pattern]) {
|
function main([esrpCliPath, type, folderPath, pattern]) {
|
||||||
const tmp = new Temp();
|
const tmp = new Temp();
|
||||||
process.on('exit', () => tmp.dispose());
|
process.on('exit', () => tmp.dispose());
|
||||||
|
const key = crypto_1.default.randomBytes(32);
|
||||||
|
const iv = crypto_1.default.randomBytes(16);
|
||||||
|
const cipher = crypto_1.default.createCipheriv('aes-256-cbc', key, iv);
|
||||||
|
const encryptedToken = cipher.update(process.env['SYSTEM_ACCESSTOKEN'].trim(), 'utf8', 'hex') + cipher.final('hex');
|
||||||
|
const encryptionDetailsPath = tmp.tmpNameSync();
|
||||||
|
fs_1.default.writeFileSync(encryptionDetailsPath, JSON.stringify({ key: key.toString('hex'), iv: iv.toString('hex') }));
|
||||||
|
const encryptedTokenPath = tmp.tmpNameSync();
|
||||||
|
fs_1.default.writeFileSync(encryptedTokenPath, encryptedToken);
|
||||||
const patternPath = tmp.tmpNameSync();
|
const patternPath = tmp.tmpNameSync();
|
||||||
fs.writeFileSync(patternPath, pattern);
|
fs_1.default.writeFileSync(patternPath, pattern);
|
||||||
const paramsPath = tmp.tmpNameSync();
|
const paramsPath = tmp.tmpNameSync();
|
||||||
fs.writeFileSync(paramsPath, JSON.stringify(getParams(type)));
|
fs_1.default.writeFileSync(paramsPath, JSON.stringify(getParams(type)));
|
||||||
const keyFile = tmp.tmpNameSync();
|
const dotnetVersion = child_process_1.default.execSync('dotnet --version', { encoding: 'utf8' }).trim();
|
||||||
const key = crypto.randomBytes(32);
|
const adoTaskVersion = path_1.default.basename(path_1.default.dirname(path_1.default.dirname(esrpCliPath)));
|
||||||
const iv = crypto.randomBytes(16);
|
const federatedTokenData = {
|
||||||
fs.writeFileSync(keyFile, JSON.stringify({ key: key.toString('hex'), iv: iv.toString('hex') }));
|
jobId: process.env['SYSTEM_JOBID'],
|
||||||
const clientkeyPath = tmp.tmpNameSync();
|
planId: process.env['SYSTEM_PLANID'],
|
||||||
const clientkeyCypher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
projectId: process.env['SYSTEM_TEAMPROJECTID'],
|
||||||
let clientkey = clientkeyCypher.update(password, 'utf8', 'hex');
|
hub: process.env['SYSTEM_HOSTTYPE'],
|
||||||
clientkey += clientkeyCypher.final('hex');
|
uri: process.env['SYSTEM_COLLECTIONURI'],
|
||||||
fs.writeFileSync(clientkeyPath, clientkey);
|
managedIdentityId: process.env['VSCODE_ESRP_CLIENT_ID'],
|
||||||
const clientcertPath = tmp.tmpNameSync();
|
managedIdentityTenantId: process.env['VSCODE_ESRP_TENANT_ID'],
|
||||||
const clientcertCypher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
serviceConnectionId: process.env['VSCODE_ESRP_SERVICE_CONNECTION_ID'],
|
||||||
let clientcert = clientcertCypher.update(cert, 'utf8', 'hex');
|
tempDirectory: os_1.default.tmpdir(),
|
||||||
clientcert += clientcertCypher.final('hex');
|
systemAccessToken: encryptedTokenPath,
|
||||||
fs.writeFileSync(clientcertPath, clientcert);
|
encryptionKey: encryptionDetailsPath
|
||||||
|
};
|
||||||
const args = [
|
const args = [
|
||||||
esrpCliPath,
|
esrpCliPath,
|
||||||
'vsts.sign',
|
'vsts.sign',
|
||||||
'-a', username,
|
'-a', process.env['ESRP_CLIENT_ID'],
|
||||||
'-k', clientkeyPath,
|
'-d', process.env['ESRP_TENANT_ID'],
|
||||||
'-z', clientcertPath,
|
'-k', JSON.stringify({ akv: 'vscode-esrp' }),
|
||||||
|
'-z', JSON.stringify({ akv: 'vscode-esrp', cert: 'esrp-sign' }),
|
||||||
'-f', folderPath,
|
'-f', folderPath,
|
||||||
'-p', patternPath,
|
'-p', patternPath,
|
||||||
'-u', 'false',
|
'-u', 'false',
|
||||||
|
|
@ -154,10 +181,17 @@ function main([esrpCliPath, type, cert, username, password, folderPath, pattern]
|
||||||
'-i', 'https://www.microsoft.com',
|
'-i', 'https://www.microsoft.com',
|
||||||
'-n', '5',
|
'-n', '5',
|
||||||
'-r', 'true',
|
'-r', 'true',
|
||||||
'-e', keyFile,
|
'-w', dotnetVersion,
|
||||||
|
'-skipAdoReportAttachment', 'false',
|
||||||
|
'-pendingAnalysisWaitTimeoutMinutes', '5',
|
||||||
|
'-adoTaskVersion', adoTaskVersion,
|
||||||
|
'-resourceUri', 'https://msazurecloud.onmicrosoft.com/api.esrp.microsoft.com',
|
||||||
|
'-esrpClientId', process.env['ESRP_CLIENT_ID'],
|
||||||
|
'-useMSIAuthentication', 'true',
|
||||||
|
'-federatedTokenData', JSON.stringify(federatedTokenData)
|
||||||
];
|
];
|
||||||
try {
|
try {
|
||||||
cp.execFileSync('dotnet', args, { stdio: 'inherit' });
|
child_process_1.default.execFileSync('dotnet', args, { stdio: 'inherit' });
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.error('ESRP failed');
|
console.error('ESRP failed');
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as cp from 'child_process';
|
import cp from 'child_process';
|
||||||
import * as fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import * as path from 'path';
|
import path from 'path';
|
||||||
import * as os from 'os';
|
import os from 'os';
|
||||||
|
|
||||||
export class Temp {
|
export class Temp {
|
||||||
private _files: string[] = [];
|
private _files: string[] = [];
|
||||||
|
|
@ -115,44 +115,70 @@ function getParams(type: string): Params[] {
|
||||||
toolName: 'sign',
|
toolName: 'sign',
|
||||||
toolVersion: '1.0'
|
toolVersion: '1.0'
|
||||||
}];
|
}];
|
||||||
|
case 'nuget':
|
||||||
|
return [{
|
||||||
|
keyCode: 'CP-401405',
|
||||||
|
operationSetCode: 'NuGetSign',
|
||||||
|
parameters: [],
|
||||||
|
toolName: 'sign',
|
||||||
|
toolVersion: '1.0'
|
||||||
|
}, {
|
||||||
|
keyCode: 'CP-401405',
|
||||||
|
operationSetCode: 'NuGetVerify',
|
||||||
|
parameters: [],
|
||||||
|
toolName: 'sign',
|
||||||
|
toolVersion: '1.0'
|
||||||
|
}];
|
||||||
default:
|
default:
|
||||||
throw new Error(`Sign type ${type} not found`);
|
throw new Error(`Sign type ${type} not found`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function main([esrpCliPath, type, cert, username, password, folderPath, pattern]: string[]) {
|
export function main([esrpCliPath, type, folderPath, pattern]: string[]) {
|
||||||
const tmp = new Temp();
|
const tmp = new Temp();
|
||||||
process.on('exit', () => tmp.dispose());
|
process.on('exit', () => tmp.dispose());
|
||||||
|
|
||||||
|
const key = crypto.randomBytes(32);
|
||||||
|
const iv = crypto.randomBytes(16);
|
||||||
|
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
||||||
|
const encryptedToken = cipher.update(process.env['SYSTEM_ACCESSTOKEN']!.trim(), 'utf8', 'hex') + cipher.final('hex');
|
||||||
|
|
||||||
|
const encryptionDetailsPath = tmp.tmpNameSync();
|
||||||
|
fs.writeFileSync(encryptionDetailsPath, JSON.stringify({ key: key.toString('hex'), iv: iv.toString('hex') }));
|
||||||
|
|
||||||
|
const encryptedTokenPath = tmp.tmpNameSync();
|
||||||
|
fs.writeFileSync(encryptedTokenPath, encryptedToken);
|
||||||
|
|
||||||
const patternPath = tmp.tmpNameSync();
|
const patternPath = tmp.tmpNameSync();
|
||||||
fs.writeFileSync(patternPath, pattern);
|
fs.writeFileSync(patternPath, pattern);
|
||||||
|
|
||||||
const paramsPath = tmp.tmpNameSync();
|
const paramsPath = tmp.tmpNameSync();
|
||||||
fs.writeFileSync(paramsPath, JSON.stringify(getParams(type)));
|
fs.writeFileSync(paramsPath, JSON.stringify(getParams(type)));
|
||||||
|
|
||||||
const keyFile = tmp.tmpNameSync();
|
const dotnetVersion = cp.execSync('dotnet --version', { encoding: 'utf8' }).trim();
|
||||||
const key = crypto.randomBytes(32);
|
const adoTaskVersion = path.basename(path.dirname(path.dirname(esrpCliPath)));
|
||||||
const iv = crypto.randomBytes(16);
|
|
||||||
fs.writeFileSync(keyFile, JSON.stringify({ key: key.toString('hex'), iv: iv.toString('hex') }));
|
|
||||||
|
|
||||||
const clientkeyPath = tmp.tmpNameSync();
|
const federatedTokenData = {
|
||||||
const clientkeyCypher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
jobId: process.env['SYSTEM_JOBID'],
|
||||||
let clientkey = clientkeyCypher.update(password, 'utf8', 'hex');
|
planId: process.env['SYSTEM_PLANID'],
|
||||||
clientkey += clientkeyCypher.final('hex');
|
projectId: process.env['SYSTEM_TEAMPROJECTID'],
|
||||||
fs.writeFileSync(clientkeyPath, clientkey);
|
hub: process.env['SYSTEM_HOSTTYPE'],
|
||||||
|
uri: process.env['SYSTEM_COLLECTIONURI'],
|
||||||
const clientcertPath = tmp.tmpNameSync();
|
managedIdentityId: process.env['VSCODE_ESRP_CLIENT_ID'],
|
||||||
const clientcertCypher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
managedIdentityTenantId: process.env['VSCODE_ESRP_TENANT_ID'],
|
||||||
let clientcert = clientcertCypher.update(cert, 'utf8', 'hex');
|
serviceConnectionId: process.env['VSCODE_ESRP_SERVICE_CONNECTION_ID'],
|
||||||
clientcert += clientcertCypher.final('hex');
|
tempDirectory: os.tmpdir(),
|
||||||
fs.writeFileSync(clientcertPath, clientcert);
|
systemAccessToken: encryptedTokenPath,
|
||||||
|
encryptionKey: encryptionDetailsPath
|
||||||
|
};
|
||||||
|
|
||||||
const args = [
|
const args = [
|
||||||
esrpCliPath,
|
esrpCliPath,
|
||||||
'vsts.sign',
|
'vsts.sign',
|
||||||
'-a', username,
|
'-a', process.env['ESRP_CLIENT_ID']!,
|
||||||
'-k', clientkeyPath,
|
'-d', process.env['ESRP_TENANT_ID']!,
|
||||||
'-z', clientcertPath,
|
'-k', JSON.stringify({ akv: 'vscode-esrp' }),
|
||||||
|
'-z', JSON.stringify({ akv: 'vscode-esrp', cert: 'esrp-sign' }),
|
||||||
'-f', folderPath,
|
'-f', folderPath,
|
||||||
'-p', patternPath,
|
'-p', patternPath,
|
||||||
'-u', 'false',
|
'-u', 'false',
|
||||||
|
|
@ -171,7 +197,14 @@ export function main([esrpCliPath, type, cert, username, password, folderPath, p
|
||||||
'-i', 'https://www.microsoft.com',
|
'-i', 'https://www.microsoft.com',
|
||||||
'-n', '5',
|
'-n', '5',
|
||||||
'-r', 'true',
|
'-r', 'true',
|
||||||
'-e', keyFile,
|
'-w', dotnetVersion,
|
||||||
|
'-skipAdoReportAttachment', 'false',
|
||||||
|
'-pendingAnalysisWaitTimeoutMinutes', '5',
|
||||||
|
'-adoTaskVersion', adoTaskVersion,
|
||||||
|
'-resourceUri', 'https://msazurecloud.onmicrosoft.com/api.esrp.microsoft.com',
|
||||||
|
'-esrpClientId', process.env['ESRP_CLIENT_ID']!,
|
||||||
|
'-useMSIAuthentication', 'true',
|
||||||
|
'-federatedTokenData', JSON.stringify(federatedTokenData)
|
||||||
];
|
];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
12
build/azure-pipelines/config/tsaoptions.json
Normal file
12
build/azure-pipelines/config/tsaoptions.json
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"codebaseName": "devdiv_microsoft_vscode",
|
||||||
|
"serviceTreeID": "79c048b2-322f-4ed5-a1ea-252a1250e4b3",
|
||||||
|
"instanceUrl": "https://devdiv.visualstudio.com/defaultcollection",
|
||||||
|
"projectName": "DevDiv",
|
||||||
|
"areaPath": "DevDiv\\VS Code (compliance tracking only)\\Visual Studio Code Client",
|
||||||
|
"notificationAliases": [
|
||||||
|
"monacotools@microsoft.com"
|
||||||
|
],
|
||||||
|
"validateToolOutput": "None",
|
||||||
|
"allTools": true
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,8 @@ parameters:
|
||||||
type: boolean
|
type: boolean
|
||||||
- name: VSCODE_BUILD_MACOS_ARM64
|
- name: VSCODE_BUILD_MACOS_ARM64
|
||||||
type: boolean
|
type: boolean
|
||||||
|
- name: VSCODE_QUALITY
|
||||||
|
type: string
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: NodeTool@0
|
- task: NodeTool@0
|
||||||
|
|
@ -11,6 +13,14 @@ steps:
|
||||||
versionFilePath: .nvmrc
|
versionFilePath: .nvmrc
|
||||||
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
|
nodejsMirror: https://github.com/joaomoreno/node-mirror/releases/download
|
||||||
|
|
||||||
|
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||||
|
- task: AzureKeyVault@2
|
||||||
|
displayName: "Azure Key Vault: Get Secrets"
|
||||||
|
inputs:
|
||||||
|
azureSubscription: vscode
|
||||||
|
KeyVaultName: vscode-build-secrets
|
||||||
|
SecretsFilter: "github-distro-mixin-password"
|
||||||
|
|
||||||
- script: node build/setup-npm-registry.js $NPM_REGISTRY build
|
- script: node build/setup-npm-registry.js $NPM_REGISTRY build
|
||||||
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
|
condition: and(succeeded(), ne(variables['NPM_REGISTRY'], 'none'))
|
||||||
displayName: Setup NPM Registry
|
displayName: Setup NPM Registry
|
||||||
|
|
@ -43,6 +53,8 @@ steps:
|
||||||
echo "Npm install failed $i, trying again..."
|
echo "Npm install failed $i, trying again..."
|
||||||
done
|
done
|
||||||
workingDirectory: build
|
workingDirectory: build
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||||
displayName: Install build dependencies
|
displayName: Install build dependencies
|
||||||
|
|
||||||
- template: ../cli/cli-darwin-sign.yml@self
|
- template: ../cli/cli-darwin-sign.yml@self
|
||||||
|
|
|
||||||
|
|
@ -9,25 +9,49 @@ steps:
|
||||||
inputs:
|
inputs:
|
||||||
version: 6.x
|
version: 6.x
|
||||||
|
|
||||||
- task: EsrpClientTool@1
|
- task: EsrpCodeSigning@5
|
||||||
continueOnError: true
|
|
||||||
displayName: Download ESRPClient
|
|
||||||
|
|
||||||
- task: AzureKeyVault@2
|
|
||||||
displayName: "Azure Key Vault: Get Secrets"
|
|
||||||
inputs:
|
inputs:
|
||||||
azureSubscription: "vscode-builds-subscription"
|
UseMSIAuthentication: true
|
||||||
KeyVaultName: vscode-build-secrets
|
ConnectedServiceName: vscode-esrp
|
||||||
SecretsFilter: "ESRP-PKI,esrp-aad-username,esrp-aad-password"
|
AppRegistrationClientId: $(ESRP_CLIENT_ID)
|
||||||
|
AppRegistrationTenantId: $(ESRP_TENANT_ID)
|
||||||
|
AuthAKVName: vscode-esrp
|
||||||
|
AuthSignCertName: esrp-sign
|
||||||
|
FolderPath: .
|
||||||
|
Pattern: noop
|
||||||
|
displayName: 'Install ESRP Tooling'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
# For legacy purposes, arch for x64 is just 'darwin'
|
||||||
|
case $VSCODE_ARCH in
|
||||||
|
x64) ASSET_ID="darwin" ;;
|
||||||
|
arm64) ASSET_ID="darwin-arm64" ;;
|
||||||
|
universal) ASSET_ID="darwin-universal" ;;
|
||||||
|
esac
|
||||||
|
echo "##vso[task.setvariable variable=ASSET_ID]$ASSET_ID"
|
||||||
|
displayName: Set asset id variable
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
if [ -z "$(ASSET_ID)" ]; then
|
||||||
|
echo "ASSET_ID is empty"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "ASSET_ID is set to $(ASSET_ID)"
|
||||||
|
fi
|
||||||
|
displayName: Check ASSET_ID variable
|
||||||
|
|
||||||
- download: current
|
- download: current
|
||||||
artifact: unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive
|
artifact: unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive
|
||||||
displayName: Download $(VSCODE_ARCH) artifact
|
displayName: Download $(VSCODE_ARCH) artifact
|
||||||
|
|
||||||
- script: node build/azure-pipelines/common/sign $(Agent.ToolsDirectory)/esrpclient/*/*/net6.0/esrpcli.dll sign-darwin $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive VSCode-darwin-$(VSCODE_ARCH).zip
|
- script: node build/azure-pipelines/common/sign $(Agent.RootDirectory)/_tasks/EsrpCodeSigning_*/*/net6.0/esrpcli.dll sign-darwin $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive VSCode-darwin-$(VSCODE_ARCH).zip
|
||||||
|
env:
|
||||||
|
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||||
displayName: Codesign
|
displayName: Codesign
|
||||||
|
|
||||||
- script: node build/azure-pipelines/common/sign $(Agent.ToolsDirectory)/esrpclient/*/*/net6.0/esrpcli.dll notarize-darwin $(ESRP-PKI) $(esrp-aad-username) $(esrp-aad-password) $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive VSCode-darwin-$(VSCODE_ARCH).zip
|
- script: node build/azure-pipelines/common/sign $(Agent.RootDirectory)/_tasks/EsrpCodeSigning_*/*/net6.0/esrpcli.dll notarize-darwin $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive VSCode-darwin-$(VSCODE_ARCH).zip
|
||||||
|
env:
|
||||||
|
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||||
displayName: Notarize
|
displayName: Notarize
|
||||||
|
|
||||||
- script: unzip $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-darwin-$(VSCODE_ARCH).zip -d $(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)
|
- script: unzip $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-darwin-$(VSCODE_ARCH).zip -d $(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)
|
||||||
|
|
@ -43,16 +67,6 @@ steps:
|
||||||
displayName: Verify signature
|
displayName: Verify signature
|
||||||
condition: and(succeeded(), ne(variables['VSCODE_ARCH'], 'arm64'))
|
condition: and(succeeded(), ne(variables['VSCODE_ARCH'], 'arm64'))
|
||||||
|
|
||||||
- script: |
|
|
||||||
# For legacy purposes, arch for x64 is just 'darwin'
|
|
||||||
case $VSCODE_ARCH in
|
|
||||||
x64) ASSET_ID="darwin" ;;
|
|
||||||
arm64) ASSET_ID="darwin-arm64" ;;
|
|
||||||
universal) ASSET_ID="darwin-universal" ;;
|
|
||||||
esac
|
|
||||||
echo "##vso[task.setvariable variable=ASSET_ID]$ASSET_ID"
|
|
||||||
displayName: Set asset id variable
|
|
||||||
|
|
||||||
- script: mv $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-darwin-x64.zip $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-darwin.zip
|
- script: mv $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-darwin-x64.zip $(Pipeline.Workspace)/unsigned_vscode_client_darwin_$(VSCODE_ARCH)_archive/VSCode-darwin.zip
|
||||||
displayName: Rename x64 build to its legacy name
|
displayName: Rename x64 build to its legacy name
|
||||||
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'))
|
condition: and(succeeded(), eq(variables['VSCODE_ARCH'], 'x64'))
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,6 @@ parameters:
|
||||||
type: boolean
|
type: boolean
|
||||||
- name: VSCODE_RUN_SMOKE_TESTS
|
- name: VSCODE_RUN_SMOKE_TESTS
|
||||||
type: boolean
|
type: boolean
|
||||||
- name: VSCODE_BUILD_AMD
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- script: npm exec -- npm-run-all -lp "electron $(VSCODE_ARCH)" "playwright-install"
|
- script: npm exec -- npm-run-all -lp "electron $(VSCODE_ARCH)" "playwright-install"
|
||||||
|
|
@ -20,56 +17,30 @@ steps:
|
||||||
|
|
||||||
- ${{ if eq(parameters.VSCODE_RUN_UNIT_TESTS, true) }}:
|
- ${{ if eq(parameters.VSCODE_RUN_UNIT_TESTS, true) }}:
|
||||||
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
|
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||||
- ${{ if eq(parameters.VSCODE_BUILD_AMD, true) }}:
|
- script: ./scripts/test.sh --tfs "Unit Tests"
|
||||||
- script: ./scripts/test-amd.sh --tfs "Unit Tests"
|
displayName: Run unit tests (Electron)
|
||||||
displayName: Run unit tests (Electron) [AMD]
|
timeoutInMinutes: 15
|
||||||
timeoutInMinutes: 15
|
- script: npm run test-node
|
||||||
- script: npm run test-node-amd
|
displayName: Run unit tests (node.js)
|
||||||
displayName: Run unit tests (node.js) [AMD]
|
timeoutInMinutes: 15
|
||||||
timeoutInMinutes: 15
|
- script: npm run test-browser-no-install -- --sequential --browser chromium --browser webkit --tfs "Browser Unit Tests"
|
||||||
- script: npm run test-browser-amd-no-install -- --sequential --browser chromium --browser webkit --tfs "Browser Unit Tests"
|
env:
|
||||||
env:
|
DEBUG: "*browser*"
|
||||||
DEBUG: "*browser*"
|
displayName: Run unit tests (Browser, Chromium & Webkit)
|
||||||
displayName: Run unit tests (Browser, Chromium & Webkit) [AMD]
|
timeoutInMinutes: 30
|
||||||
timeoutInMinutes: 30
|
|
||||||
- ${{ if eq(parameters.VSCODE_BUILD_AMD, false) }}:
|
|
||||||
- script: ./scripts/test.sh --tfs "Unit Tests"
|
|
||||||
displayName: Run unit tests (Electron)
|
|
||||||
timeoutInMinutes: 15
|
|
||||||
- script: npm run test-node
|
|
||||||
displayName: Run unit tests (node.js)
|
|
||||||
timeoutInMinutes: 15
|
|
||||||
- script: npm run test-browser-no-install -- --sequential --browser chromium --browser webkit --tfs "Browser Unit Tests"
|
|
||||||
env:
|
|
||||||
DEBUG: "*browser*"
|
|
||||||
displayName: Run unit tests (Browser, Chromium & Webkit)
|
|
||||||
timeoutInMinutes: 30
|
|
||||||
|
|
||||||
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
|
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||||
- ${{ if eq(parameters.VSCODE_BUILD_AMD, true) }}:
|
- script: ./scripts/test.sh --build --tfs "Unit Tests"
|
||||||
- script: ./scripts/test-amd.sh --build --tfs "Unit Tests"
|
displayName: Run unit tests (Electron)
|
||||||
displayName: Run unit tests (Electron) [AMD]
|
timeoutInMinutes: 15
|
||||||
timeoutInMinutes: 15
|
- script: npm run test-node -- --build
|
||||||
- script: npm run test-node-amd -- --build
|
displayName: Run unit tests (node.js)
|
||||||
displayName: Run unit tests (node.js) [AMD]
|
timeoutInMinutes: 15
|
||||||
timeoutInMinutes: 15
|
- script: npm run test-browser-no-install -- --sequential --build --browser chromium --browser webkit --tfs "Browser Unit Tests"
|
||||||
- script: npm run test-browser-amd-no-install -- --sequential --build --browser chromium --browser webkit --tfs "Browser Unit Tests"
|
env:
|
||||||
env:
|
DEBUG: "*browser*"
|
||||||
DEBUG: "*browser*"
|
displayName: Run unit tests (Browser, Chromium & Webkit)
|
||||||
displayName: Run unit tests (Browser, Chromium & Webkit) [AMD]
|
timeoutInMinutes: 30
|
||||||
timeoutInMinutes: 30
|
|
||||||
- ${{ if eq(parameters.VSCODE_BUILD_AMD, false) }}:
|
|
||||||
- script: ./scripts/test.sh --build --tfs "Unit Tests"
|
|
||||||
displayName: Run unit tests (Electron)
|
|
||||||
timeoutInMinutes: 15
|
|
||||||
- script: npm run test-node -- --build
|
|
||||||
displayName: Run unit tests (node.js)
|
|
||||||
timeoutInMinutes: 15
|
|
||||||
- script: npm run test-browser-no-install -- --sequential --build --browser chromium --browser webkit --tfs "Browser Unit Tests"
|
|
||||||
env:
|
|
||||||
DEBUG: "*browser*"
|
|
||||||
displayName: Run unit tests (Browser, Chromium & Webkit)
|
|
||||||
timeoutInMinutes: 30
|
|
||||||
|
|
||||||
- ${{ if eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true) }}:
|
- ${{ if eq(parameters.VSCODE_RUN_INTEGRATION_TESTS, true) }}:
|
||||||
- script: |
|
- script: |
|
||||||
|
|
@ -90,48 +61,29 @@ steps:
|
||||||
compile-extension:typescript-language-features \
|
compile-extension:typescript-language-features \
|
||||||
compile-extension:vscode-api-tests \
|
compile-extension:vscode-api-tests \
|
||||||
compile-extension:vscode-colorize-tests \
|
compile-extension:vscode-colorize-tests \
|
||||||
|
compile-extension:vscode-colorize-perf-tests \
|
||||||
compile-extension:vscode-test-resolver
|
compile-extension:vscode-test-resolver
|
||||||
displayName: Build integration tests
|
displayName: Build integration tests
|
||||||
|
|
||||||
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
|
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||||
- ${{ if eq(parameters.VSCODE_BUILD_AMD, true) }}:
|
- script: ./scripts/test-integration --tfs "Integration Tests"
|
||||||
- script: ./scripts/test-integration-amd.sh --tfs "Integration Tests"
|
displayName: Run integration tests (Electron)
|
||||||
displayName: Run integration tests (Electron) [AMD]
|
timeoutInMinutes: 20
|
||||||
timeoutInMinutes: 20
|
|
||||||
- ${{ if eq(parameters.VSCODE_BUILD_AMD, false) }}:
|
|
||||||
- script: ./scripts/test-integration --tfs "Integration Tests"
|
|
||||||
displayName: Run integration tests (Electron)
|
|
||||||
timeoutInMinutes: 20
|
|
||||||
|
|
||||||
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
|
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||||
- ${{ if eq(parameters.VSCODE_BUILD_AMD, true) }}:
|
- script: |
|
||||||
- script: |
|
# Figure out the full absolute path of the product we just built
|
||||||
# Figure out the full absolute path of the product we just built
|
# including the remote server and configure the integration tests
|
||||||
# including the remote server and configure the integration tests
|
# to run with these builds instead of running out of sources.
|
||||||
# to run with these builds instead of running out of sources.
|
set -e
|
||||||
set -e
|
APP_ROOT="$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)"
|
||||||
APP_ROOT="$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)"
|
APP_NAME="`ls $APP_ROOT | head -n 1`"
|
||||||
APP_NAME="`ls $APP_ROOT | head -n 1`"
|
INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME/Contents/MacOS/Electron" \
|
||||||
INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME/Contents/MacOS/Electron" \
|
./scripts/test-integration.sh --build --tfs "Integration Tests"
|
||||||
./scripts/test-integration-amd.sh --build --tfs "Integration Tests"
|
env:
|
||||||
env:
|
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-darwin-$(VSCODE_ARCH)
|
||||||
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-darwin-$(VSCODE_ARCH)
|
displayName: Run integration tests (Electron)
|
||||||
displayName: Run integration tests (Electron) [AMD]
|
timeoutInMinutes: 20
|
||||||
timeoutInMinutes: 20
|
|
||||||
- ${{ if eq(parameters.VSCODE_BUILD_AMD, false) }}:
|
|
||||||
- script: |
|
|
||||||
# Figure out the full absolute path of the product we just built
|
|
||||||
# including the remote server and configure the integration tests
|
|
||||||
# to run with these builds instead of running out of sources.
|
|
||||||
set -e
|
|
||||||
APP_ROOT="$(agent.builddirectory)/VSCode-darwin-$(VSCODE_ARCH)"
|
|
||||||
APP_NAME="`ls $APP_ROOT | head -n 1`"
|
|
||||||
INTEGRATION_TEST_ELECTRON_PATH="$APP_ROOT/$APP_NAME/Contents/MacOS/Electron" \
|
|
||||||
./scripts/test-integration.sh --build --tfs "Integration Tests"
|
|
||||||
env:
|
|
||||||
VSCODE_REMOTE_SERVER_PATH: $(agent.builddirectory)/vscode-server-darwin-$(VSCODE_ARCH)
|
|
||||||
displayName: Run integration tests (Electron)
|
|
||||||
timeoutInMinutes: 20
|
|
||||||
|
|
||||||
- script: ./scripts/test-web-integration.sh --browser webkit
|
- script: ./scripts/test-web-integration.sh --browser webkit
|
||||||
env:
|
env:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
# Void - this looks like the relevant file for us (product-build-darwin.yml is independent and maybe just used for testing)
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: NodeTool@0
|
- task: NodeTool@0
|
||||||
inputs:
|
inputs:
|
||||||
|
|
@ -12,7 +10,7 @@ steps:
|
||||||
- task: AzureKeyVault@2
|
- task: AzureKeyVault@2
|
||||||
displayName: "Azure Key Vault: Get Secrets"
|
displayName: "Azure Key Vault: Get Secrets"
|
||||||
inputs:
|
inputs:
|
||||||
azureSubscription: "vscode-builds-subscription"
|
azureSubscription: vscode
|
||||||
KeyVaultName: vscode-build-secrets
|
KeyVaultName: vscode-build-secrets
|
||||||
SecretsFilter: "github-distro-mixin-password,macos-developer-certificate,macos-developer-certificate-key"
|
SecretsFilter: "github-distro-mixin-password,macos-developer-certificate,macos-developer-certificate-key"
|
||||||
|
|
||||||
|
|
@ -48,6 +46,8 @@ steps:
|
||||||
echo "Npm install failed $i, trying again..."
|
echo "Npm install failed $i, trying again..."
|
||||||
done
|
done
|
||||||
workingDirectory: build
|
workingDirectory: build
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||||
displayName: Install build dependencies
|
displayName: Install build dependencies
|
||||||
|
|
||||||
- download: current
|
- download: current
|
||||||
|
|
@ -61,8 +61,6 @@ steps:
|
||||||
- script: node build/azure-pipelines/distro/mixin-quality
|
- script: node build/azure-pipelines/distro/mixin-quality
|
||||||
displayName: Mixin distro quality
|
displayName: Mixin distro quality
|
||||||
|
|
||||||
|
|
||||||
## Void - IMPORTANT
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
unzip $(Pipeline.Workspace)/unsigned_vscode_client_darwin_x64_archive/VSCode-darwin-x64.zip -d $(agent.builddirectory)/VSCode-darwin-x64
|
unzip $(Pipeline.Workspace)/unsigned_vscode_client_darwin_x64_archive/VSCode-darwin-x64.zip -d $(agent.builddirectory)/VSCode-darwin-x64
|
||||||
|
|
@ -70,7 +68,13 @@ steps:
|
||||||
DEBUG=* node build/darwin/create-universal-app.js $(agent.builddirectory)
|
DEBUG=* node build/darwin/create-universal-app.js $(agent.builddirectory)
|
||||||
displayName: Create Universal App
|
displayName: Create Universal App
|
||||||
|
|
||||||
## Void - IMPORTANT
|
- script: |
|
||||||
|
set -e
|
||||||
|
APP_ROOT="$(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)"
|
||||||
|
APP_NAME="`ls $APP_ROOT | head -n 1`"
|
||||||
|
APP_PATH="$APP_ROOT/$APP_NAME" node build/darwin/verify-macho.js universal
|
||||||
|
displayName: Verify arch of Mach-O objects
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain
|
security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,6 @@ parameters:
|
||||||
type: boolean
|
type: boolean
|
||||||
- name: VSCODE_RUN_SMOKE_TESTS
|
- name: VSCODE_RUN_SMOKE_TESTS
|
||||||
type: boolean
|
type: boolean
|
||||||
- name: VSCODE_BUILD_AMD
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
|
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||||
|
|
@ -31,7 +28,7 @@ steps:
|
||||||
- task: AzureKeyVault@2
|
- task: AzureKeyVault@2
|
||||||
displayName: "Azure Key Vault: Get Secrets"
|
displayName: "Azure Key Vault: Get Secrets"
|
||||||
inputs:
|
inputs:
|
||||||
azureSubscription: "vscode-builds-subscription"
|
azureSubscription: vscode
|
||||||
KeyVaultName: vscode-build-secrets
|
KeyVaultName: vscode-build-secrets
|
||||||
SecretsFilter: "github-distro-mixin-password,macos-developer-certificate,macos-developer-certificate-key"
|
SecretsFilter: "github-distro-mixin-password,macos-developer-certificate,macos-developer-certificate-key"
|
||||||
|
|
||||||
|
|
@ -78,16 +75,10 @@ steps:
|
||||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
|
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'), ne(variables['NPM_REGISTRY'], 'none'))
|
||||||
displayName: Setup NPM Authentication
|
displayName: Setup NPM Authentication
|
||||||
|
|
||||||
- script: |
|
|
||||||
set -e
|
|
||||||
# Refs https://github.com/microsoft/vscode/issues/219893#issuecomment-2209313109
|
|
||||||
sudo xcode-select --switch /Applications/Xcode_15.2.app
|
|
||||||
condition: and(succeeded(), ne(variables.NODE_MODULES_RESTORED, 'true'))
|
|
||||||
displayName: Switch to Xcode >= 15.1
|
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
set -e
|
set -e
|
||||||
c++ --version
|
c++ --version
|
||||||
|
xcode-select -print-path
|
||||||
python3 -m pip install setuptools
|
python3 -m pip install setuptools
|
||||||
|
|
||||||
for i in {1..5}; do # try 5 times
|
for i in {1..5}; do # try 5 times
|
||||||
|
|
@ -164,7 +155,7 @@ steps:
|
||||||
displayName: Build server (web)
|
displayName: Build server (web)
|
||||||
|
|
||||||
- ${{ else }}:
|
- ${{ else }}:
|
||||||
- script: npm run gulp transpile-client-swc transpile-extensions
|
- script: npm run gulp transpile-client-esbuild transpile-extensions
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
GITHUB_TOKEN: "$(github-distro-mixin-password)"
|
||||||
displayName: Transpile
|
displayName: Transpile
|
||||||
|
|
@ -176,7 +167,6 @@ steps:
|
||||||
VSCODE_RUN_UNIT_TESTS: ${{ parameters.VSCODE_RUN_UNIT_TESTS }}
|
VSCODE_RUN_UNIT_TESTS: ${{ parameters.VSCODE_RUN_UNIT_TESTS }}
|
||||||
VSCODE_RUN_INTEGRATION_TESTS: ${{ parameters.VSCODE_RUN_INTEGRATION_TESTS }}
|
VSCODE_RUN_INTEGRATION_TESTS: ${{ parameters.VSCODE_RUN_INTEGRATION_TESTS }}
|
||||||
VSCODE_RUN_SMOKE_TESTS: ${{ parameters.VSCODE_RUN_SMOKE_TESTS }}
|
VSCODE_RUN_SMOKE_TESTS: ${{ parameters.VSCODE_RUN_SMOKE_TESTS }}
|
||||||
VSCODE_BUILD_AMD: ${{ parameters.VSCODE_BUILD_AMD }}
|
|
||||||
|
|
||||||
- ${{ elseif and(ne(parameters.VSCODE_CIBUILD, true), ne(parameters.VSCODE_QUALITY, 'oss')) }}:
|
- ${{ elseif and(ne(parameters.VSCODE_CIBUILD, true), ne(parameters.VSCODE_QUALITY, 'oss')) }}:
|
||||||
- task: DownloadPipelineArtifact@2
|
- task: DownloadPipelineArtifact@2
|
||||||
|
|
@ -198,6 +188,14 @@ steps:
|
||||||
chmod +x "$APP_PATH/Contents/Resources/app/bin/$CLI_APP_NAME"
|
chmod +x "$APP_PATH/Contents/Resources/app/bin/$CLI_APP_NAME"
|
||||||
displayName: Make CLI executable
|
displayName: Make CLI executable
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
set -e
|
||||||
|
APP_ROOT="$(Agent.BuildDirectory)/VSCode-darwin-$(VSCODE_ARCH)"
|
||||||
|
APP_NAME="`ls $APP_ROOT | head -n 1`"
|
||||||
|
APP_PATH="$APP_ROOT/$APP_NAME" node build/darwin/verify-macho.js $(VSCODE_ARCH)
|
||||||
|
APP_PATH="$(Agent.BuildDirectory)/vscode-server-darwin-$(VSCODE_ARCH)" node build/darwin/verify-macho.js $(VSCODE_ARCH)
|
||||||
|
displayName: Verify arch of Mach-O objects
|
||||||
|
|
||||||
# Setting hardened entitlements is a requirement for:
|
# Setting hardened entitlements is a requirement for:
|
||||||
# * Apple notarization
|
# * Apple notarization
|
||||||
# * Running tests on Big Sur (because Big Sur has additional security precautions)
|
# * Running tests on Big Sur (because Big Sur has additional security precautions)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
pool:
|
pool:
|
||||||
vmImage: "ubuntu-latest"
|
name: 1es-ubuntu-22.04-x64
|
||||||
|
os: linux
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branches:
|
branches:
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ steps:
|
||||||
- task: AzureKeyVault@2
|
- task: AzureKeyVault@2
|
||||||
displayName: "Azure Key Vault: Get Secrets"
|
displayName: "Azure Key Vault: Get Secrets"
|
||||||
inputs:
|
inputs:
|
||||||
azureSubscription: "vscode-builds-subscription"
|
azureSubscription: vscode
|
||||||
KeyVaultName: vscode-build-secrets
|
KeyVaultName: vscode-build-secrets
|
||||||
SecretsFilter: "github-distro-mixin-password"
|
SecretsFilter: "github-distro-mixin-password"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,24 +3,27 @@
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const fs = require("fs");
|
const fs_1 = __importDefault(require("fs"));
|
||||||
const path = require("path");
|
const path_1 = __importDefault(require("path"));
|
||||||
const { dirs } = require('../../npm/dirs');
|
const { dirs } = require('../../npm/dirs');
|
||||||
function log(...args) {
|
function log(...args) {
|
||||||
console.log(`[${new Date().toLocaleTimeString('en', { hour12: false })}]`, '[distro]', ...args);
|
console.log(`[${new Date().toLocaleTimeString('en', { hour12: false })}]`, '[distro]', ...args);
|
||||||
}
|
}
|
||||||
function mixin(mixinPath) {
|
function mixin(mixinPath) {
|
||||||
if (!fs.existsSync(`${mixinPath}/node_modules`)) {
|
if (!fs_1.default.existsSync(`${mixinPath}/node_modules`)) {
|
||||||
log(`Skipping distro npm dependencies: ${mixinPath} (no node_modules)`);
|
log(`Skipping distro npm dependencies: ${mixinPath} (no node_modules)`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log(`Mixing in distro npm dependencies: ${mixinPath}`);
|
log(`Mixing in distro npm dependencies: ${mixinPath}`);
|
||||||
const distroPackageJson = JSON.parse(fs.readFileSync(`${mixinPath}/package.json`, 'utf8'));
|
const distroPackageJson = JSON.parse(fs_1.default.readFileSync(`${mixinPath}/package.json`, 'utf8'));
|
||||||
const targetPath = path.relative('.build/distro/npm', mixinPath);
|
const targetPath = path_1.default.relative('.build/distro/npm', mixinPath);
|
||||||
for (const dependency of Object.keys(distroPackageJson.dependencies)) {
|
for (const dependency of Object.keys(distroPackageJson.dependencies)) {
|
||||||
fs.rmSync(`./${targetPath}/node_modules/${dependency}`, { recursive: true, force: true });
|
fs_1.default.rmSync(`./${targetPath}/node_modules/${dependency}`, { recursive: true, force: true });
|
||||||
fs.cpSync(`${mixinPath}/node_modules/${dependency}`, `./${targetPath}/node_modules/${dependency}`, { recursive: true, force: true, dereference: true });
|
fs_1.default.cpSync(`${mixinPath}/node_modules/${dependency}`, `./${targetPath}/node_modules/${dependency}`, { recursive: true, force: true, dereference: true });
|
||||||
}
|
}
|
||||||
log(`Mixed in distro npm dependencies: ${mixinPath} ✔︎`);
|
log(`Mixed in distro npm dependencies: ${mixinPath} ✔︎`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue