From 204b53e7b8cb13080b10eccf69afe17bd0893bee Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 4 Apr 2022 02:32:57 -0700 Subject: [PATCH] build: upload to AZ as well as S3 (#33573) * build: upload to AZ aswell as S3 * fix: provide env to azput --- package.json | 3 +- script/lib/azput.js | 48 +++++ script/lib/util.py | 21 +- script/release/release.js | 92 ++++---- script/release/uploaders/upload-index-json.py | 8 +- .../uploaders/upload-node-checksums.py | 8 +- .../release/uploaders/upload-node-headers.py | 30 ++- script/release/uploaders/upload-symbols.py | 11 +- script/release/uploaders/upload.py | 14 +- yarn.lock | 203 +++++++++++++++++- 10 files changed, 345 insertions(+), 93 deletions(-) create mode 100644 script/lib/azput.js diff --git a/package.json b/package.json index 3ef503b0bc..e976065ea1 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "repository": "https://github.com/electron/electron", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "devDependencies": { + "@azure/storage-blob": "^12.9.0", "@electron/docs-parser": "^0.12.4", "@electron/typescript-definitions": "^8.9.5", "@octokit/auth-app": "^2.10.0", @@ -141,4 +142,4 @@ "node script/gen-hunspell-filenames.js" ] } -} \ No newline at end of file +} diff --git a/script/lib/azput.js b/script/lib/azput.js new file mode 100644 index 0000000000..0e6a75cd2a --- /dev/null +++ b/script/lib/azput.js @@ -0,0 +1,48 @@ +/* eslint-disable camelcase */ +const { BlobServiceClient } = require('@azure/storage-blob'); +const fs = require('fs'); +const path = require('path'); + +const blobServiceClient = BlobServiceClient.fromConnectionString(process.env.ELECTRON_ARTIFACTS_BLOB_STORAGE); + +const args = require('minimist')(process.argv.slice(2)); + +let { prefix = '/', key_prefix = '', _: files } = args; +if (prefix && !prefix.endsWith(path.sep)) prefix = path.resolve(prefix) + path.sep; + +function filenameToKey (file) { + file = path.resolve(file); + if (file.startsWith(prefix)) file = file.substr(prefix.length - 1); + return key_prefix + (path.sep === '\\' ? file.replace(/\\/g, '/') : file); +} + +let anErrorOccurred = false; +function next (done) { + const file = files.shift(); + if (!file) return done(); + let key = filenameToKey(file); + // TODO: When we drop s3put, migrate the key to not include atom-shell in the callsites + key = key.replace('atom-shell/dist/', 'headers/dist/'); + key = key.replace('atom-shell/symbols/', 'symbols/'); + key = key.replace('atom-shell/tmp/', 'checksums-scratchpad/'); + key = key.replace('electron-artifacts/', 'release-builds/'); + + const [containerName, ...keyPath] = key.split('/'); + const blobKey = keyPath.join('/'); + console.log(`Uploading '${file}' to container '${containerName}' with key '${blobKey}'...`); + + const containerClient = blobServiceClient.getContainerClient(containerName); + const blockBlobClient = containerClient.getBlockBlobClient(blobKey); + blockBlobClient.uploadFile(file) + .then((uploadBlobResponse) => { + console.log(`Upload block blob ${blobKey} successfully: https://artifacts.electronjs.org/${key}`, uploadBlobResponse.requestId); + }) + .catch((err) => { + console.error(err); + anErrorOccurred = true; + }) + .then(() => next(done)); +} +next(() => { + process.exit(anErrorOccurred ? 1 : 0); +}); diff --git a/script/lib/util.py b/script/lib/util.py index 93b364c6a2..c7f448331a 100644 --- a/script/lib/util.py +++ b/script/lib/util.py @@ -15,7 +15,7 @@ except ImportError: from urllib2 import urlopen import zipfile -from lib.config import is_verbose_mode +from lib.config import is_verbose_mode, s3_config ELECTRON_DIR = os.path.abspath( os.path.dirname(os.path.dirname(os.path.dirname(__file__))) @@ -155,7 +155,14 @@ def get_electron_version(): with open(version_file) as f: return 'v' + f.read().strip() -def s3put(bucket, access_key, secret_key, prefix, key_prefix, files): +def store_artifact(prefix, key_prefix, files): + # Legacy S3 Bucket + s3put(prefix, key_prefix, files) + # New AZ Storage + azput(prefix, key_prefix, files) + +def s3put(prefix, key_prefix, files): + bucket, access_key, secret_key = s3_config() env = os.environ.copy() env['AWS_ACCESS_KEY_ID'] = access_key env['AWS_SECRET_ACCESS_KEY'] = secret_key @@ -169,6 +176,16 @@ def s3put(bucket, access_key, secret_key, prefix, key_prefix, files): ] + files, env) print(output) +def azput(prefix, key_prefix, files): + env = os.environ.copy() + output = execute([ + 'node', + os.path.join(os.path.dirname(__file__), 'azput.js'), + '--prefix', prefix, + '--key_prefix', key_prefix, + ] + files, env) + print(output) + def get_out_dir(): out_dir = 'Debug' override = os.environ.get('ELECTRON_OUT_DIR') diff --git a/script/release/release.js b/script/release/release.js index 3527f39ce2..21ebbc0836 100755 --- a/script/release/release.js +++ b/script/release/release.js @@ -17,8 +17,8 @@ const pkgVersion = `v${pkg.version}`; const path = require('path'); const temp = require('temp').track(); const { URL } = require('url'); +const { BlobServiceClient } = require('@azure/storage-blob'); const { Octokit } = require('@octokit/rest'); -const AWS = require('aws-sdk'); require('colors'); const pass = '✓'.green; @@ -80,6 +80,8 @@ async function validateReleaseAssets (release, validatingRelease) { } const s3RemoteFiles = s3RemoteFilesForVersion(release.tag_name); await verifyShasumsForRemoteFiles(s3RemoteFiles, true); + const azRemoteFiles = azRemoteFilesForVersion(release.tag_name); + await verifyShasumsForRemoteFiles(s3RemoteFiles, true); } } @@ -181,26 +183,36 @@ function assetsForVersion (version, validatingRelease) { return patterns; } +const cloudStoreFilePaths = (version) => [ + `iojs-${version}-headers.tar.gz`, + `iojs-${version}.tar.gz`, + `node-${version}.tar.gz`, + 'node.lib', + 'x64/node.lib', + 'win-x64/iojs.lib', + 'win-x86/iojs.lib', + 'win-arm64/iojs.lib', + 'win-x64/node.lib', + 'win-x86/node.lib', + 'win-arm64/node.lib', + 'arm64/node.lib', + 'SHASUMS.txt', + 'SHASUMS256.txt' +]; + function s3RemoteFilesForVersion (version) { const bucket = 'https://gh-contractor-zcbenz.s3.amazonaws.com/'; const versionPrefix = `${bucket}atom-shell/dist/${version}/`; - const filePaths = [ - `iojs-${version}-headers.tar.gz`, - `iojs-${version}.tar.gz`, - `node-${version}.tar.gz`, - 'node.lib', - 'x64/node.lib', - 'win-x64/iojs.lib', - 'win-x86/iojs.lib', - 'win-arm64/iojs.lib', - 'win-x64/node.lib', - 'win-x86/node.lib', - 'win-arm64/node.lib', - 'arm64/node.lib', - 'SHASUMS.txt', - 'SHASUMS256.txt' - ]; - return filePaths.map((filePath) => ({ + return cloudStoreFilePaths(version).map((filePath) => ({ + file: filePath, + url: `${versionPrefix}${filePath}` + })); +} + +function azRemoteFilesForVersion (version) { + const azCDN = 'https://artifacts.electronjs.org/headers/'; + const versionPrefix = `${azCDN}dist/${version}/`; + return cloudStoreFilePaths(version).map((filePath) => ({ file: filePath, url: `${versionPrefix}${filePath}` })); @@ -221,49 +233,39 @@ function runScript (scriptName, scriptArgs, cwd) { } function uploadNodeShasums () { - console.log('Uploading Node SHASUMS file to S3.'); + console.log('Uploading Node SHASUMS file to artifacts.electronjs.org.'); const scriptPath = path.join(ELECTRON_DIR, 'script', 'release', 'uploaders', 'upload-node-checksums.py'); runScript(scriptPath, ['-v', pkgVersion]); - console.log(`${pass} Done uploading Node SHASUMS file to S3.`); + console.log(`${pass} Done uploading Node SHASUMS file to artifacts.electronjs.org.`); } function uploadIndexJson () { - console.log('Uploading index.json to S3.'); + console.log('Uploading index.json to artifacts.electronjs.org.'); const scriptPath = path.join(ELECTRON_DIR, 'script', 'release', 'uploaders', 'upload-index-json.py'); runScript(scriptPath, [pkgVersion]); - console.log(`${pass} Done uploading index.json to S3.`); + console.log(`${pass} Done uploading index.json to artifacts.electronjs.org.`); } async function mergeShasums (pkgVersion) { - // Download individual checksum files for Electron zip files from S3, + // Download individual checksum files for Electron zip files from artifact storage, // concatenate them, and upload to GitHub. - const bucket = process.env.ELECTRON_S3_BUCKET; - const accessKeyId = process.env.ELECTRON_S3_ACCESS_KEY; - const secretAccessKey = process.env.ELECTRON_S3_SECRET_KEY; - if (!bucket || !accessKeyId || !secretAccessKey) { - throw new Error('Please set the $ELECTRON_S3_BUCKET, $ELECTRON_S3_ACCESS_KEY, and $ELECTRON_S3_SECRET_KEY environment variables'); + const connectionString = process.env.ELECTRON_ARTIFACTS_BLOB_STORAGE; + if (!connectionString) { + throw new Error('Please set the $ELECTRON_ARTIFACTS_BLOB_STORAGE environment variable'); } - const s3 = new AWS.S3({ - apiVersion: '2006-03-01', - accessKeyId, - secretAccessKey, - region: 'us-west-2' + const blobServiceClient = BlobServiceClient.fromConnectionString(connectionString); + const containerClient = blobServiceClient.getContainerClient('checksums-scratchpad'); + const blobsIter = containerClient.listBlobsFlat({ + prefix: `${pkgVersion}/` }); - const objects = await s3.listObjectsV2({ - Bucket: bucket, - Prefix: `atom-shell/tmp/${pkgVersion}/`, - Delimiter: '/' - }).promise(); const shasums = []; - for (const obj of objects.Contents) { - if (obj.Key.endsWith('.sha256sum')) { - const data = await s3.getObject({ - Bucket: bucket, - Key: obj.Key - }).promise(); - shasums.push(data.Body.toString('ascii').trim()); + for await (const blob of blobsIter) { + if (blob.name.endsWith('.sha256sum')) { + const blobClient = containerClient.getBlockBlobClient(blob.name); + const response = await blobClient.downloadToBuffer(); + shasums.push(response.toString('ascii').trim()); } } return shasums.join('\n'); diff --git a/script/release/uploaders/upload-index-json.py b/script/release/uploaders/upload-index-json.py index 4b2c4973aa..41880d5667 100755 --- a/script/release/uploaders/upload-index-json.py +++ b/script/release/uploaders/upload-index-json.py @@ -9,8 +9,8 @@ import urllib2 sys.path.append( os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + "/../..")) -from lib.config import s3_config -from lib.util import s3put, scoped_cwd, safe_mkdir, get_out_dir, ELECTRON_DIR +from lib.util import store_artifact, scoped_cwd, safe_mkdir, get_out_dir, \ + ELECTRON_DIR OUT_DIR = get_out_dir() @@ -59,9 +59,7 @@ def main(): with open(index_json, "w") as f: f.write(new_content) - bucket, access_key, secret_key = s3_config() - s3put(bucket, access_key, secret_key, OUT_DIR, 'atom-shell/dist', - [index_json]) + store_artifact(OUT_DIR, 'atom-shell/dist', [index_json]) if __name__ == '__main__': diff --git a/script/release/uploaders/upload-node-checksums.py b/script/release/uploaders/upload-node-checksums.py index 41d509f2a6..dfa8ef3595 100755 --- a/script/release/uploaders/upload-node-checksums.py +++ b/script/release/uploaders/upload-node-checksums.py @@ -10,8 +10,7 @@ import tempfile sys.path.append( os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + "/../..")) -from lib.config import s3_config -from lib.util import download, rm_rf, s3put, safe_mkdir +from lib.util import download, rm_rf, store_artifact, safe_mkdir DIST_URL = 'https://electronjs.org/headers/' @@ -30,9 +29,8 @@ def main(): ] if args.target_dir is None: - bucket, access_key, secret_key = s3_config() - s3put(bucket, access_key, secret_key, directory, - 'atom-shell/dist/{0}'.format(args.version), checksums) + store_artifact(directory, 'atom-shell/dist/{0}'.format(args.version), + checksums) else: copy_files(checksums, args.target_dir) diff --git a/script/release/uploaders/upload-node-headers.py b/script/release/uploaders/upload-node-headers.py index 0f81504fe1..862eea96e8 100755 --- a/script/release/uploaders/upload-node-headers.py +++ b/script/release/uploaders/upload-node-headers.py @@ -9,8 +9,9 @@ import sys sys.path.append( os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + "/../..")) -from lib.config import PLATFORM, get_target_arch, s3_config -from lib.util import safe_mkdir, scoped_cwd, s3put, get_out_dir, get_dist_dir +from lib.config import PLATFORM, get_target_arch +from lib.util import safe_mkdir, scoped_cwd, store_artifact, get_out_dir, \ + get_dist_dir DIST_DIR = get_dist_dir() OUT_DIR = get_out_dir() @@ -26,9 +27,8 @@ HEADER_TAR_NAMES = [ def main(): args = parse_args() - # Upload node's headers to S3. - bucket, access_key, secret_key = s3_config() - upload_node(bucket, access_key, secret_key, args.version) + # Upload node's headers to artifact storage. + upload_node(args.version) def parse_args(): @@ -38,17 +38,17 @@ def parse_args(): return parser.parse_args() -def upload_node(bucket, access_key, secret_key, version): +def upload_node(version): with scoped_cwd(GEN_DIR): generated_tar = os.path.join(GEN_DIR, 'node_headers.tar.gz') for header_tar in HEADER_TAR_NAMES: versioned_header_tar = header_tar.format(version) shutil.copy2(generated_tar, os.path.join(GEN_DIR, versioned_header_tar)) - s3put(bucket, access_key, secret_key, GEN_DIR, - 'atom-shell/dist/{0}'.format(version), glob.glob('node-*.tar.gz')) - s3put(bucket, access_key, secret_key, GEN_DIR, - 'atom-shell/dist/{0}'.format(version), glob.glob('iojs-*.tar.gz')) + store_artifact(GEN_DIR, 'atom-shell/dist/{0}'.format(version), + glob.glob('node-*.tar.gz')) + store_artifact(GEN_DIR, 'atom-shell/dist/{0}'.format(version), + glob.glob('iojs-*.tar.gz')) if PLATFORM == 'win32': if get_target_arch() == 'ia32': @@ -73,16 +73,14 @@ def upload_node(bucket, access_key, secret_key, version): shutil.copy2(electron_lib, v4_node_lib) # Upload the node.lib. - s3put(bucket, access_key, secret_key, DIST_DIR, - 'atom-shell/dist/{0}'.format(version), [node_lib]) + store_artifact(DIST_DIR, 'atom-shell/dist/{0}'.format(version), [node_lib]) # Upload the iojs.lib. - s3put(bucket, access_key, secret_key, DIST_DIR, - 'atom-shell/dist/{0}'.format(version), [iojs_lib]) + store_artifact(DIST_DIR, 'atom-shell/dist/{0}'.format(version), [iojs_lib]) # Upload the v4 node.lib. - s3put(bucket, access_key, secret_key, DIST_DIR, - 'atom-shell/dist/{0}'.format(version), [v4_node_lib]) + store_artifact(DIST_DIR, 'atom-shell/dist/{0}'.format(version), + [v4_node_lib]) if __name__ == '__main__': diff --git a/script/release/uploaders/upload-symbols.py b/script/release/uploaders/upload-symbols.py index 25952bc05d..3e877e6477 100755 --- a/script/release/uploaders/upload-symbols.py +++ b/script/release/uploaders/upload-symbols.py @@ -14,8 +14,8 @@ def is_fs_case_sensitive(): sys.path.append( os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + "/../..")) -from lib.config import PLATFORM, s3_config -from lib.util import get_electron_branding, execute, s3put, \ +from lib.config import PLATFORM +from lib.util import get_electron_branding, execute, store_artifact, \ get_out_dir, ELECTRON_DIR RELEASE_DIR = get_out_dir() @@ -76,16 +76,15 @@ def main(): for f in files: assert os.path.exists(f) - bucket, access_key, secret_key = s3_config() - upload_symbols(bucket, access_key, secret_key, files) + upload_symbols(files) def run_symstore(pdb, dest, product): execute(['symstore', 'add', '/r', '/f', pdb, '/s', dest, '/t', product]) -def upload_symbols(bucket, access_key, secret_key, files): - s3put(bucket, access_key, secret_key, SYMBOLS_DIR, 'atom-shell/symbols', +def upload_symbols(files): + store_artifact(SYMBOLS_DIR, 'atom-shell/symbols', files) diff --git a/script/release/uploaders/upload.py b/script/release/uploaders/upload.py index 88fbcc2423..51302d677e 100755 --- a/script/release/uploaders/upload.py +++ b/script/release/uploaders/upload.py @@ -16,10 +16,10 @@ sys.path.append( os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + "/../..")) from zipfile import ZipFile -from lib.config import PLATFORM, get_target_arch,s3_config, \ +from lib.config import PLATFORM, get_target_arch, \ get_zip_name, enable_verbose_mode, get_platform_key from lib.util import get_electron_branding, execute, get_electron_version, \ - s3put, get_electron_exec, get_out_dir, \ + store_artifact, get_electron_exec, get_out_dir, \ SRC_DIR, ELECTRON_DIR, TS_NODE @@ -342,14 +342,10 @@ def upload_electron(release, file_path, args): # if upload_to_s3 is set, skip github upload. if args.upload_to_s3: - bucket, access_key, secret_key = s3_config() key_prefix = 'electron-artifacts/{0}_{1}'.format(args.version, args.upload_timestamp) - s3put(bucket, access_key, secret_key, os.path.dirname(file_path), - key_prefix, [file_path]) + store_artifact(os.path.dirname(file_path), key_prefix, [file_path]) upload_sha256_checksum(args.version, file_path, key_prefix) - s3url = 'https://gh-contractor-zcbenz.s3.amazonaws.com' - print('{0} uploaded to {1}/{2}/{0}'.format(filename, s3url, key_prefix)) return # Upload the file. @@ -369,7 +365,6 @@ def upload_io_to_github(release, filename, filepath, version): def upload_sha256_checksum(version, file_path, key_prefix=None): - bucket, access_key, secret_key = s3_config() checksum_path = '{}.sha256sum'.format(file_path) if key_prefix is None: key_prefix = 'atom-shell/tmp/{0}'.format(version) @@ -380,8 +375,7 @@ def upload_sha256_checksum(version, file_path, key_prefix=None): filename = os.path.basename(file_path) with open(checksum_path, 'w') as checksum: checksum.write('{} *{}'.format(sha256.hexdigest(), filename)) - s3put(bucket, access_key, secret_key, os.path.dirname(checksum_path), - key_prefix, [checksum_path]) + store_artifact(os.path.dirname(checksum_path), key_prefix, [checksum_path]) def get_release(version): diff --git a/yarn.lock b/yarn.lock index 39af7f570d..ca7df59b03 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,94 @@ # yarn lockfile v1 +"@azure/abort-controller@^1.0.0": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.0.4.tgz#fd3c4d46c8ed67aace42498c8e2270960250eafd" + integrity sha512-lNUmDRVGpanCsiUN3NWxFTdwmdFI53xwhkTFfHDGTYk46ca7Ind3nanJc+U6Zj9Tv+9nTCWRBscWEW1DyKOpTw== + dependencies: + tslib "^2.0.0" + +"@azure/core-asynciterator-polyfill@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@azure/core-asynciterator-polyfill/-/core-asynciterator-polyfill-1.0.2.tgz#0dd3849fb8d97f062a39db0e5cadc9ffaf861fec" + integrity sha512-3rkP4LnnlWawl0LZptJOdXNrT/fHp2eQMadoasa6afspXdpGrtPZuAQc2PD0cpgyuoXtUWyC3tv7xfntjGS5Dw== + +"@azure/core-auth@^1.3.0": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.3.2.tgz#6a2c248576c26df365f6c7881ca04b7f6d08e3d0" + integrity sha512-7CU6DmCHIZp5ZPiZ9r3J17lTKMmYsm/zGvNkjArQwPkrLlZ1TZ+EUYfGgh2X31OLMVAQCTJZW4cXHJi02EbJnA== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + +"@azure/core-http@^2.0.0": + version "2.2.4" + resolved "https://registry.yarnpkg.com/@azure/core-http/-/core-http-2.2.4.tgz#df5a5b4138dbbc4299879f2fc6f257d0a5f0401e" + integrity sha512-QmmJmexXKtPyc3/rsZR/YTLDvMatzbzAypJmLzvlfxgz/SkgnqV/D4f6F2LsK6tBj1qhyp8BoXiOebiej0zz3A== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-asynciterator-polyfill" "^1.0.0" + "@azure/core-auth" "^1.3.0" + "@azure/core-tracing" "1.0.0-preview.13" + "@azure/logger" "^1.0.0" + "@types/node-fetch" "^2.5.0" + "@types/tunnel" "^0.0.3" + form-data "^4.0.0" + node-fetch "^2.6.7" + process "^0.11.10" + tough-cookie "^4.0.0" + tslib "^2.2.0" + tunnel "^0.0.6" + uuid "^8.3.0" + xml2js "^0.4.19" + +"@azure/core-lro@^2.2.0": + version "2.2.4" + resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-2.2.4.tgz#42fbf4ae98093c59005206a4437ddcd057c57ca1" + integrity sha512-e1I2v2CZM0mQo8+RSix0x091Av493e4bnT22ds2fcQGslTHzM2oTbswkB65nP4iEpCxBrFxOSDPKExmTmjCVtQ== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-tracing" "1.0.0-preview.13" + "@azure/logger" "^1.0.0" + tslib "^2.2.0" + +"@azure/core-paging@^1.1.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@azure/core-paging/-/core-paging-1.2.1.tgz#1b884f563b6e49971e9a922da3c7a20931867b54" + integrity sha512-UtH5iMlYsvg+nQYIl4UHlvvSrsBjOlRF4fs0j7mxd3rWdAStrKYrh2durOpHs5C9yZbVhsVDaisoyaf/lL1EVA== + dependencies: + "@azure/core-asynciterator-polyfill" "^1.0.0" + tslib "^2.2.0" + +"@azure/core-tracing@1.0.0-preview.13": + version "1.0.0-preview.13" + resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz#55883d40ae2042f6f1e12b17dd0c0d34c536d644" + integrity sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ== + dependencies: + "@opentelemetry/api" "^1.0.1" + tslib "^2.2.0" + +"@azure/logger@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" + integrity sha512-aK4s3Xxjrx3daZr3VylxejK3vG5ExXck5WOHDJ8in/k9AqlfIyFMMT1uG7u8mNjX+QRILTIn0/Xgschfh/dQ9g== + dependencies: + tslib "^2.2.0" + +"@azure/storage-blob@^12.9.0": + version "12.9.0" + resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.9.0.tgz#4cbd8b4c7a47dd064867430db892f4ef2d8f17ab" + integrity sha512-ank38FdCLfJ+EoeMzCz3hkYJuZAd63ARvDKkxZYRDb+beBYf+/+gx8jNTqkq/hfyUl4dJQ/a7tECU0Y0F98CHg== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-http" "^2.0.0" + "@azure/core-lro" "^2.2.0" + "@azure/core-paging" "^1.1.1" + "@azure/core-tracing" "1.0.0-preview.13" + "@azure/logger" "^1.0.0" + events "^3.0.0" + tslib "^2.2.0" + "@babel/code-frame@^7.0.0": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" @@ -181,6 +269,11 @@ dependencies: "@types/node" ">= 8" +"@opentelemetry/api@^1.0.1": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.0.4.tgz#a167e46c10d05a07ab299fc518793b0cff8f6924" + integrity sha512-BuJuXRSJNQ3QoKA6GWWDyuLpOUck+9hAXNMCnrloc1aWVoy6Xq6t9PUV08aBZ4Lutqq2LEHM486bpZqoViScog== + "@primer/octicons@^10.0.0": version "10.0.0" resolved "https://registry.yarnpkg.com/@primer/octicons/-/octicons-10.0.0.tgz#81e94ed32545dfd3472c8625a5b345f3ea4c153d" @@ -431,6 +524,14 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== +"@types/node-fetch@^2.5.0": + version "2.6.1" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.1.tgz#8f127c50481db65886800ef496f20bbf15518975" + integrity sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*": version "12.6.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.6.1.tgz#d5544f6de0aae03eefbb63d5120f6c8be0691946" @@ -554,6 +655,13 @@ dependencies: "@types/node" "*" +"@types/tunnel@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.3.tgz#f109e730b072b3136347561fc558c9358bb8c6e9" + integrity sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA== + dependencies: + "@types/node" "*" + "@types/uglify-js@*": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.4.tgz#96beae23df6f561862a830b4288a49e86baac082" @@ -1108,6 +1216,11 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" @@ -1685,6 +1798,13 @@ colors@^1.1.2: resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^2.20.0, commander@^2.9.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" @@ -2027,6 +2147,11 @@ deglob@^4.0.1: run-parallel "^1.1.2" uniq "^1.0.1" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" @@ -2980,6 +3105,24 @@ for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + format@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" @@ -4768,6 +4911,18 @@ mime-db@1.40.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mime-types@~2.1.24: version "2.1.24" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" @@ -4946,7 +5101,7 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-fetch@^2.3.0: +node-fetch@^2.3.0, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== @@ -5630,6 +5785,11 @@ prr@~1.0.1: resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= +psl@^1.1.33: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" @@ -5677,7 +5837,7 @@ punycode@^1.2.4: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== @@ -7354,6 +7514,15 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +tough-cookie@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" + integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.1.2" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -7404,6 +7573,11 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tslib@^2.0.0, tslib@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" @@ -7416,6 +7590,11 @@ tty-browserify@0.0.0: resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -7645,7 +7824,7 @@ universal-user-agent@^6.0.0: resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== -universalify@^0.1.0: +universalify@^0.1.0, universalify@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== @@ -7754,6 +7933,11 @@ uuid@3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== +uuid@^8.3.0: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" @@ -8024,6 +8208,19 @@ xml2js@0.4.19: sax ">=0.6.0" xmlbuilder "~9.0.1" +xml2js@^0.4.19: + version "0.4.23" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" + integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + xmlbuilder@~4.2.0: version "4.2.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-4.2.1.tgz#aa58a3041a066f90eaa16c2f5389ff19f3f461a5"