diff --git a/.buildkite/.mocharc.json b/.buildkite/.mocharc.json new file mode 100644 index 000000000000..dd7fabf24eb9 --- /dev/null +++ b/.buildkite/.mocharc.json @@ -0,0 +1,5 @@ +{ + "extension": ["ts"], + "spec": "**/*.test.ts", + "require": "ts-node/register" +} diff --git a/.buildkite/.npmrc b/.buildkite/.npmrc new file mode 100644 index 000000000000..e9ee3cb4d04a --- /dev/null +++ b/.buildkite/.npmrc @@ -0,0 +1 @@ +legacy-peer-deps=true \ No newline at end of file diff --git a/.buildkite/README.md b/.buildkite/README.md index 6b9be00898d2..6b1e0384691a 100644 --- a/.buildkite/README.md +++ b/.buildkite/README.md @@ -3,6 +3,7 @@ ## Directory Structure - `hooks` - special directory used by Buildkite agents for [hooks](https://buildkite.com/docs/agent/v3/hooks) +- `pipeline-utils` - Shared TypeScript utils for use in pipeline scripts - `pipelines` - contains pipeline definitions - `scripts/common` - scripts that get `source`d by other scripts to set environment variables or import shared functions - `scripts/lifecycle` - general scripts for tasks that run before or after individual steps or the entire build diff --git a/.buildkite/package-lock.json b/.buildkite/package-lock.json index 2af4d143fde0..2bf8ce04b473 100644 --- a/.buildkite/package-lock.json +++ b/.buildkite/package-lock.json @@ -8,7 +8,61 @@ "name": "kibana-buildkite", "version": "1.0.0", "dependencies": { - "kibana-buildkite-library": "git+https://git@github.com/elastic/kibana-buildkite-library#6a73a417decc52f309ede3644577c9dca7b411a2" + "@octokit/rest": "^18.10.0", + "axios": "^0.21.4", + "globby": "^11.1.0", + "js-yaml": "^4.1.0", + "minimatch": "^5.0.1", + "tslib": "*" + }, + "devDependencies": { + "@types/chai": "^4.2.10", + "@types/js-yaml": "^4.0.5", + "@types/minimatch": "^3.0.5", + "@types/mocha": "^7.0.2", + "@types/node": "^15.12.2", + "chai": "^4.2.0", + "mocha": "^8.2.1", + "nock": "^12.0.2", + "ts-node": "^10.7.0", + "typescript": "^4.6.4" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@nodelib/fs.scandir": { @@ -163,6 +217,118 @@ "@octokit/openapi-types": "^11.2.0" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "node_modules/@types/chai": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.1.tgz", + "integrity": "sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==", + "dev": true + }, + "node_modules/@types/js-yaml": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", + "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", + "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "15.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz", + "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==", + "dev": true + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -176,6 +342,15 @@ "node": ">=8" } }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/axios": { "version": "0.21.4", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", @@ -194,6 +369,15 @@ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -213,11 +397,184 @@ "node": ">=8" } }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chai": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/deprecation": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -229,6 +586,33 @@ "node": ">=8" } }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/fast-glob": { "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", @@ -263,6 +647,31 @@ "node": ">=8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, "node_modules/follow-redirects": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", @@ -282,6 +691,44 @@ } } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -312,6 +759,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, "node_modules/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -320,6 +794,34 @@ "node": ">= 4" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -328,6 +830,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -347,6 +858,15 @@ "node": ">=0.12.0" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -355,6 +875,12 @@ "node": ">=0.10.0" } }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -366,19 +892,60 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/kibana-buildkite-library": { - "version": "1.0.0", - "resolved": "git+https://git@github.com/elastic/kibana-buildkite-library.git#6a73a417decc52f309ede3644577c9dca7b411a2", - "integrity": "sha512-SMW4Eoc/Tkg2lW63iB34obeiqCMhW4a7n3wWa7Ps63eI7+74QlIJha6K5Fa4fO/08ABZ6nEqsWeAOYAFnVLF7g==", - "license": "MIT", + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "dependencies": { - "@octokit/rest": "^18.10.0", - "axios": "^0.21.4", - "globby": "^11.1.0", - "js-yaml": "^4.1.0", - "minimatch": "^5.0.1" + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/loupe": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", + "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -410,6 +977,190 @@ "node": ">=10" } }, + "node_modules/mocha": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nock": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/nock/-/nock-12.0.3.tgz", + "integrity": "sha512-QNb/j8kbFnKCiyqi9C5DD0jH/FubFGj5rt9NQFONXwQm3IPB0CULECg/eS3AU1KgZb/6SwUa4/DTRKhVxkGABw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.13", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">= 10.13" + } + }, "node_modules/node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -429,6 +1180,15 @@ } } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -437,6 +1197,54 @@ "wrappy": "1" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -445,6 +1253,15 @@ "node": ">=8" } }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -456,6 +1273,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -475,6 +1301,36 @@ } ] }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -506,6 +1362,35 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -514,6 +1399,56 @@ "node": ">=8" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -530,11 +1465,108 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, + "node_modules/ts-node": { + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.1.tgz", + "integrity": "sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/universal-user-agent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -549,13 +1581,206 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } }, "dependencies": { + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -637,8 +1862,7 @@ "@octokit/plugin-request-log": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "requires": {} + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==" }, "@octokit/plugin-rest-endpoint-methods": { "version": "5.13.0", @@ -691,6 +1915,103 @@ "@octokit/openapi-types": "^11.2.0" } }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "@types/chai": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.1.tgz", + "integrity": "sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==", + "dev": true + }, + "@types/js-yaml": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", + "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "@types/mocha": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz", + "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==", + "dev": true + }, + "@types/node": { + "version": "15.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz", + "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==", + "dev": true + }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -701,6 +2022,12 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, "axios": { "version": "0.21.4", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", @@ -719,6 +2046,12 @@ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -735,11 +2068,138 @@ "fill-range": "^7.0.1" } }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "chai": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", + "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, "deprecation": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -748,6 +2208,24 @@ "path-type": "^4.0.0" } }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, "fast-glob": { "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", @@ -776,11 +2254,52 @@ "to-regex-range": "^5.0.1" } }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, "follow-redirects": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==" }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true + }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -802,16 +2321,65 @@ "slash": "^3.0.0" } }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -825,11 +2393,23 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, "is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -838,18 +2418,51 @@ "argparse": "^2.0.1" } }, - "kibana-buildkite-library": { - "version": "git+https://git@github.com/elastic/kibana-buildkite-library.git#6a73a417decc52f309ede3644577c9dca7b411a2", - "integrity": "sha512-SMW4Eoc/Tkg2lW63iB34obeiqCMhW4a7n3wWa7Ps63eI7+74QlIJha6K5Fa4fO/08ABZ6nEqsWeAOYAFnVLF7g==", - "from": "kibana-buildkite-library@git+https://git@github.com/elastic/kibana-buildkite-library#6a73a417decc52f309ede3644577c9dca7b411a2", + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "requires": { - "@octokit/rest": "^18.10.0", - "axios": "^0.21.4", - "globby": "^11.1.0", - "js-yaml": "^4.1.0", - "minimatch": "^5.0.1" + "p-locate": "^5.0.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "loupe": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", + "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "dev": true, + "requires": { + "get-func-name": "^2.0.0" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -872,6 +2485,145 @@ "brace-expansion": "^2.0.1" } }, + "mocha": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, + "requires": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true + }, + "nock": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/nock/-/nock-12.0.3.tgz", + "integrity": "sha512-QNb/j8kbFnKCiyqi9C5DD0jH/FubFGj5rt9NQFONXwQm3IPB0CULECg/eS3AU1KgZb/6SwUa4/DTRKhVxkGABw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.13", + "propagate": "^2.0.0" + } + }, "node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -880,6 +2632,12 @@ "whatwg-url": "^5.0.0" } }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -888,21 +2646,87 @@ "wrappy": "1" } }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true + }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, + "propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "dev": true + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -916,11 +2740,61 @@ "queue-microtask": "^1.2.2" } }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -934,11 +2808,69 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, + "ts-node": { + "version": "10.8.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.1.tgz", + "integrity": "sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "dependencies": { + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + } + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true + }, "universal-user-agent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -953,10 +2885,129 @@ "webidl-conversions": "^3.0.0" } }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + } + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/.buildkite/package.json b/.buildkite/package.json index d22b079c1ab4..c7255a565235 100644 --- a/.buildkite/package.json +++ b/.buildkite/package.json @@ -1,8 +1,33 @@ { "name": "kibana-buildkite", "version": "1.0.0", - "private": true, + "description": "Kibana Buildkite", + "scripts": { + "test": "mocha", + "test:watch": "mocha --watch" + }, "dependencies": { - "kibana-buildkite-library": "git+https://git@github.com/elastic/kibana-buildkite-library#6a73a417decc52f309ede3644577c9dca7b411a2" + "@octokit/rest": "^18.10.0", + "axios": "^0.21.4", + "globby": "^11.1.0", + "js-yaml": "^4.1.0", + "minimatch": "^5.0.1", + "tslib": "*" + }, + "devDependencies": { + "@types/chai": "^4.2.10", + "@types/js-yaml": "^4.0.5", + "@types/minimatch": "^3.0.5", + "@types/mocha": "^7.0.2", + "@types/node": "^15.12.2", + "chai": "^4.2.0", + "mocha": "^8.2.1", + "nock": "^12.0.2", + "ts-node": "^10.7.0", + "typescript": "^4.6.4" + }, + "imports": { + "#pipeline-utils": "./pipeline-utils/index.ts", + "#pipeline-utils/*": "./pipeline-utils/*" } } diff --git a/.buildkite/pipeline-utils/buildkite/client.test.ts b/.buildkite/pipeline-utils/buildkite/client.test.ts new file mode 100644 index 000000000000..ef70a0b3a462 --- /dev/null +++ b/.buildkite/pipeline-utils/buildkite/client.test.ts @@ -0,0 +1,267 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { expect } from 'chai'; +import { BuildkiteClient } from './client'; +import { Build } from './types/build'; +import { Job } from './types/job'; + +describe('BuildkiteClient', () => { + let buildkite: BuildkiteClient; + + beforeEach(() => { + buildkite = new BuildkiteClient(); + }); + + describe('getBuildStatus', () => { + it('does not have hasNonPreemptionRetries for preemption retries', async () => { + const job: Job = { + id: 'id-1', + retried_in_job_id: 'id-2', + state: 'failed', + agent: { + meta_data: ['spot=true'], + }, + retried: true, + exit_status: -1, + type: 'script', + } as Job; + + const retry: Job = { + id: 'id-2', + state: 'passed', + agent: { + meta_data: ['spot=true'], + }, + type: 'script', + } as Job; + + const build = { + id: 'id', + state: 'passed', + jobs: [job, retry], + } as Build; + + const buildStatus = buildkite.getBuildStatus(build); + expect(buildStatus.success).to.eql(true); + expect(buildStatus.hasRetries).to.eql(true); + expect(buildStatus.hasNonPreemptionRetries).to.eql(false); + }); + + it('has hasNonPreemptionRetries for spot non-preemption retries', async () => { + const job: Job = { + id: 'id-1', + retried_in_job_id: 'id-2', + state: 'failed', + agent: { + meta_data: ['spot=true'], + }, + retried: true, + exit_status: 1, + type: 'script', + } as Job; + + const retry: Job = { + id: 'id-2', + state: 'passed', + agent: { + meta_data: ['spot=true'], + }, + type: 'script', + } as Job; + + const build = { + id: 'id', + state: 'passed', + jobs: [job, retry], + } as Build; + + const buildStatus = buildkite.getBuildStatus(build); + expect(buildStatus.success).to.eql(true); + expect(buildStatus.hasRetries).to.eql(true); + expect(buildStatus.hasNonPreemptionRetries).to.eql(true); + }); + + it('has hasNonPreemptionRetries for non-spot retries with exit code -1', async () => { + const job: Job = { + id: 'id-1', + retried_in_job_id: 'id-2', + state: 'failed', + retried: true, + exit_status: -1, + type: 'script', + } as Job; + + const retry: Job = { + id: 'id-2', + state: 'passed', + type: 'script', + } as Job; + + const build = { + id: 'id', + state: 'passed', + jobs: [job, retry], + } as Build; + + const buildStatus = buildkite.getBuildStatus(build); + expect(buildStatus.success).to.eql(true); + expect(buildStatus.hasRetries).to.eql(true); + expect(buildStatus.hasNonPreemptionRetries).to.eql(true); + }); + + it('returns failure if build is failed and all jobs passed', async () => { + const job = { + id: 'id_1', + state: 'passed', + } as Job; + + const build = { + id: 'id', + state: 'failed', + jobs: [job], + } as Build; + + const result = buildkite.getBuildStatus(build); + expect(result.success).to.eql(false); + }); + }); + + describe('getJobStatus', () => { + it('returns success if job is successful', async () => { + const job = { + id: 'id', + state: 'passed', + type: 'script', + } as Job; + + const build = { + id: 'id', + state: 'passed', + jobs: [job], + } as Build; + + const result = buildkite.getJobStatus(build, job); + expect(result.success).to.eql(true); + }); + + it('returns failure if job is unsuccessful', async () => { + const job = { + id: 'id', + state: 'failed', + type: 'script', + } as Job; + + const build = { + id: 'id', + state: 'failed', + jobs: [job], + } as Build; + + const result = buildkite.getJobStatus(build, job); + expect(result.success).to.eql(false); + }); + + it('returns success if retried job is successful', async () => { + const job = { + id: 'id_1', + state: 'failed', + retried: true, + retried_in_job_id: 'id_2', + } as Job; + + const jobRetry = { + id: 'id_2', + state: 'passed', + } as Job; + + const build = { + id: 'id', + state: 'passed', + jobs: [job, jobRetry], + } as Build; + + const result = buildkite.getJobStatus(build, job); + expect(result.success).to.eql(true); + }); + + it('returns failure if retried job is unsuccessful', async () => { + const job = { + id: 'id_1', + state: 'failed', + retried: true, + retried_in_job_id: 'id_2', + } as Job; + + const jobRetry = { + id: 'id_2', + state: 'failed', + } as Job; + + const build = { + id: 'id', + state: 'failed', + jobs: [job, jobRetry], + } as Build; + + const result = buildkite.getJobStatus(build, job); + expect(result.success).to.eql(false); + }); + + it('returns failure if job is waiting_failed', async () => { + const job = { + id: 'id_1', + state: 'waiting_failed', + } as Job; + + const build = { + id: 'id', + state: 'failed', + jobs: [job], + } as Build; + + const result = buildkite.getJobStatus(build, job); + expect(result.success).to.eql(false); + }); + + it('returns success if job is broken but of type: manual', async () => { + const job = { + id: 'id', + state: 'broken', + type: 'manual', + } as Job; + + const build = { + id: 'id', + state: 'passed', + jobs: [job], + } as Build; + + const result = buildkite.getJobStatus(build, job); + expect(result.success).to.eql(true); + }); + + it('returns success if job is broken but has no exit status', async () => { + const job = { + id: 'id', + state: 'broken', + type: 'script', + exit_status: null, + } as Job; + + const build = { + id: 'id', + state: 'passed', + jobs: [job], + } as Build; + + const result = buildkite.getJobStatus(build, job); + expect(result.success).to.eql(true); + }); + }); +}); diff --git a/.buildkite/pipeline-utils/buildkite/client.ts b/.buildkite/pipeline-utils/buildkite/client.ts new file mode 100644 index 000000000000..fe3f2041646e --- /dev/null +++ b/.buildkite/pipeline-utils/buildkite/client.ts @@ -0,0 +1,267 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import axios, { AxiosInstance } from 'axios'; +import { execSync } from 'child_process'; +import { dump } from 'js-yaml'; +import { parseLinkHeader } from './parse_link_header'; +import { Artifact } from './types/artifact'; +import { Build, BuildStatus } from './types/build'; +import { Job, JobState } from './types/job'; + +export interface BuildkiteClientConfig { + baseUrl?: string; + token?: string; +} + +export interface BuildkiteGroup { + group: string; + steps: BuildkiteStep[]; +} + +export interface BuildkiteStep { + command: string; + label: string; + parallelism?: number; + agents: { + queue: string; + }; + timeout_in_minutes?: number; + key?: string; + depends_on?: string | string[]; + retry?: { + automatic: Array<{ + exit_status: string; + limit: number; + }>; + }; + env?: { [key: string]: string }; +} + +export interface BuildkiteTriggerBuildParams { + commit: string; + branch: string; + env?: Record; + author?: { + name: string; + email: string; + }; + ignore_pipeline_branch_filters?: boolean; + message?: string; + meta_data?: Record; + pull_request_base_branch?: string; + pull_request_id?: string | number; + pull_request_repository?: string; +} + +export class BuildkiteClient { + http: AxiosInstance; + + constructor(config: BuildkiteClientConfig = {}) { + const BUILDKITE_BASE_URL = + config.baseUrl ?? process.env.BUILDKITE_BASE_URL ?? 'https://api.buildkite.com'; + const BUILDKITE_TOKEN = config.token ?? process.env.BUILDKITE_TOKEN; + + // const BUILDKITE_AGENT_BASE_URL = + // process.env.BUILDKITE_AGENT_BASE_URL || 'https://agent.buildkite.com/v3'; + // const BUILDKITE_AGENT_TOKEN = process.env.BUILDKITE_AGENT_TOKEN; + + this.http = axios.create({ + baseURL: BUILDKITE_BASE_URL, + headers: { + Authorization: `Bearer ${BUILDKITE_TOKEN}`, + }, + }); + + // this.agentHttp = axios.create({ + // baseURL: BUILDKITE_AGENT_BASE_URL, + // headers: { + // Authorization: `Token ${BUILDKITE_AGENT_TOKEN}`, + // }, + // }); + } + + getBuild = async ( + pipelineSlug: string, + buildNumber: string | number, + includeRetriedJobs = false + ): Promise => { + // TODO properly assemble URL + const link = `v2/organizations/elastic/pipelines/${pipelineSlug}/builds/${buildNumber}?include_retried_jobs=${includeRetriedJobs.toString()}`; + const resp = await this.http.get(link); + return resp.data as Build; + }; + + getCurrentBuild = (includeRetriedJobs = false) => { + if (!process.env.BUILDKITE_PIPELINE_SLUG || !process.env.BUILDKITE_BUILD_NUMBER) { + throw new Error( + 'BUILDKITE_PIPELINE_SLUG and BUILDKITE_BUILD_NUMBER must be set to get current build' + ); + } + + return this.getBuild( + process.env.BUILDKITE_PIPELINE_SLUG, + process.env.BUILDKITE_BUILD_NUMBER, + includeRetriedJobs + ); + }; + + getJobStatus = (build: Build, job: Job): { success: boolean; state: JobState } => { + if (job.retried) { + const retriedJob = build.jobs.find((j) => j.id === job.retried_in_job_id); + if (!retriedJob) { + throw Error(`Couldn't find retried job ID ${job.retried_in_job_id} for job ${job.id}`); + } + + return this.getJobStatus(build, retriedJob); + } + + let success: boolean; + + // "Manual" steps are for input, when they are skipped, they have state: broken in the API + // So let's always mark them as successful, they can't really fail + // `broken` used to be in this list, but has been removed, it's essentially another type of skip status + // https://buildkite.com/docs/pipelines/defining-steps#job-states - See "Differentiating between broken, skipped and canceled states:" + success = + job.type === 'manual' || + ![ + 'failed', + 'timed_out', + 'timing_out', + 'waiting_failed', + 'unblocked_failed', + 'blocked_failed', + ].includes(job.state); + + if (job.soft_failed) { + success = true; + } + + return { + success, + state: job.state, + }; + }; + + getBuildStatus = (build: Build): BuildStatus => { + let hasRetries = false; + let hasNonPreemptionRetries = false; + let success = build.state !== 'failed'; + + for (const job of build.jobs) { + if (job.retried) { + hasRetries = true; + const isPreemptionFailure = + job.state === 'failed' && + job.agent?.meta_data?.includes('spot=true') && + job.exit_status === -1; + + if (!isPreemptionFailure) { + hasNonPreemptionRetries = true; + } + } + + const state = this.getJobStatus(build, job); + success = success && state.success; + } + + return { + state: build.state, + success, + hasRetries, + hasNonPreemptionRetries, + }; + }; + + getCurrentBuildStatus = async (includeRetriedJobs = false) => { + return this.getBuildStatus(await this.getCurrentBuild(includeRetriedJobs)); + }; + + getArtifacts = async ( + pipelineSlug: string, + buildNumber: string | number + ): Promise => { + let link = `v2/organizations/elastic/pipelines/${pipelineSlug}/builds/${buildNumber}/artifacts?per_page=100`; + const artifacts = []; + + // Don't get stuck in an infinite loop or follow more than 50 pages + for (let i = 0; i < 50; i++) { + if (!link) { + break; + } + + const resp = await this.http.get(link); + link = ''; + + artifacts.push(await resp.data); + + if (resp.headers.link) { + const result = parseLinkHeader(resp.headers.link as string); + if (result?.next) { + link = result.next; + } + } + } + + return artifacts.flat(); + }; + + getArtifactsForCurrentBuild = (): Promise => { + if (!process.env.BUILDKITE_PIPELINE_SLUG || !process.env.BUILDKITE_BUILD_NUMBER) { + throw new Error( + 'BUILDKITE_PIPELINE_SLUG and BUILDKITE_BUILD_NUMBER must be set to get current build' + ); + } + + return this.getArtifacts( + process.env.BUILDKITE_PIPELINE_SLUG, + process.env.BUILDKITE_BUILD_NUMBER + ); + }; + + // https://buildkite.com/docs/apis/rest-api/builds#create-a-build + triggerBuild = async ( + pipelineSlug: string, + options: BuildkiteTriggerBuildParams + ): Promise => { + const url = `v2/organizations/elastic/pipelines/${pipelineSlug}/builds`; + + return (await this.http.post(url, options)).data; + }; + + setMetadata = (key: string, value: string) => { + execSync(`buildkite-agent meta-data set '${key}'`, { + input: value, + stdio: ['pipe', 'inherit', 'inherit'], + }); + }; + + setAnnotation = ( + context: string, + style: 'info' | 'success' | 'warning' | 'error', + value: string + ) => { + execSync(`buildkite-agent annotate --context '${context}' --style '${style}'`, { + input: value, + stdio: ['pipe', 'inherit', 'inherit'], + }); + }; + + uploadArtifacts = (pattern: string) => { + execSync(`buildkite-agent artifact upload '${pattern}'`, { + stdio: ['ignore', 'inherit', 'inherit'], + }); + }; + + uploadSteps = (steps: Array) => { + execSync(`buildkite-agent pipeline upload`, { + input: dump({ steps }), + stdio: ['pipe', 'inherit', 'inherit'], + }); + }; +} diff --git a/.buildkite/scripts/steps/es_snapshots/bucket_config.js b/.buildkite/pipeline-utils/buildkite/index.ts similarity index 72% rename from .buildkite/scripts/steps/es_snapshots/bucket_config.js rename to .buildkite/pipeline-utils/buildkite/index.ts index 6bbe80b60e76..6b671bcc88a4 100644 --- a/.buildkite/scripts/steps/es_snapshots/bucket_config.js +++ b/.buildkite/pipeline-utils/buildkite/index.ts @@ -6,7 +6,5 @@ * Side Public License, v 1. */ -module.exports = { - BASE_BUCKET_DAILY: 'kibana-ci-es-snapshots-daily', - BASE_BUCKET_PERMANENT: 'kibana-ci-es-snapshots-permanent', -}; +export * from './client'; +export * from './types'; diff --git a/.buildkite/pipeline-utils/buildkite/parse_link_header.test.ts b/.buildkite/pipeline-utils/buildkite/parse_link_header.test.ts new file mode 100644 index 000000000000..92c72ebea8ba --- /dev/null +++ b/.buildkite/pipeline-utils/buildkite/parse_link_header.test.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { expect } from 'chai'; +import { parseLinkHeader } from './parse_link_header'; + +describe('parseLinkHeader', () => { + it('should parse link header', () => { + const result = parseLinkHeader( + '; rel="next", ; rel="last"' + ); + + expect(result).to.eql({ + last: 'https://api.buildkite.com/v2/organizations/elastic/agents?page=5&per_page=1', + next: 'https://api.buildkite.com/v2/organizations/elastic/agents?page=2&per_page=1', + }); + }); +}); diff --git a/.buildkite/pipeline-utils/buildkite/parse_link_header.ts b/.buildkite/pipeline-utils/buildkite/parse_link_header.ts new file mode 100644 index 000000000000..463f6405d068 --- /dev/null +++ b/.buildkite/pipeline-utils/buildkite/parse_link_header.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export function parseLinkHeader(header: string): null | Record { + if (!header) { + return null; + } + + const entries = header.split(',').map((p) => p.trim()); + + const parsed: Record = {}; + for (const entry of entries) { + const parts = entry.split(';', 2).map((p) => p.trim()); + const url = parts[0].slice(1, -1); + const rel = parts[1].replace(/rel="?([^"]+)"?$/, '$1'); + parsed[rel] = url; + } + + return parsed; +} diff --git a/.buildkite/pipeline-utils/buildkite/types/agent.ts b/.buildkite/pipeline-utils/buildkite/types/agent.ts new file mode 100644 index 000000000000..81a48e542780 --- /dev/null +++ b/.buildkite/pipeline-utils/buildkite/types/agent.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Agent { + id: string; + url: string; + web_url: string; + name: string; + connection_state: string; + ip_address: string; + hostname: string; + user_agent: string; + version: string; + creator?: string | null; + created_at: string; + last_job_finished_at?: string | null; + priority: number; + meta_data?: null | [string]; +} diff --git a/.buildkite/pipeline-utils/buildkite/types/artifact.ts b/.buildkite/pipeline-utils/buildkite/types/artifact.ts new file mode 100644 index 000000000000..a9bb49a45dab --- /dev/null +++ b/.buildkite/pipeline-utils/buildkite/types/artifact.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Artifact { + id: string; + job_id: string; + url: string; + download_url: string; + state: 'new' | 'error' | 'finished' | 'deleted'; + path: string; + dirname: string; + filename: string; + mime_type: string; + file_size: number; + glob_path?: string; + original_path?: string; + sha1sum: string; +} diff --git a/.buildkite/pipeline-utils/buildkite/types/build.ts b/.buildkite/pipeline-utils/buildkite/types/build.ts new file mode 100644 index 000000000000..cf41963bc339 --- /dev/null +++ b/.buildkite/pipeline-utils/buildkite/types/build.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Job } from './job'; +import { Pipeline } from './pipeline'; + +export type BuildState = + | 'running' + | 'scheduled' + | 'passed' + | 'failed' + | 'blocked' + | 'canceled' + | 'canceling' + | 'skipped' + | 'not_run' + | 'finished'; + +export interface BuildStatus { + state: BuildState; + success: boolean; + hasRetries: boolean; + hasNonPreemptionRetries: boolean; +} + +export interface Build { + id: string; + url: string; + web_url: string; + number: number; + state: BuildState; + blocked: boolean; + message: string; + commit: string; + branch: string; + author: { name: string; email: string }; + env: Record; + created_at: string; + scheduled_at: string; + started_at: string; + finished_at: string; + meta_data: Record; + creator: { + avatar_url: string; + created_at: string; + email: string; + id: string; + name: string; + }; + source: string; + + jobs: Job[]; + pipeline: Pipeline; + pull_request?: { + id: string; + base: string; + repository: string; + }; +} diff --git a/.buildkite/pipeline-utils/buildkite/types/index.ts b/.buildkite/pipeline-utils/buildkite/types/index.ts new file mode 100644 index 000000000000..5e31779ee509 --- /dev/null +++ b/.buildkite/pipeline-utils/buildkite/types/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './build'; +export * from './job'; +export * from './pipeline'; diff --git a/.buildkite/pipeline-utils/buildkite/types/job.ts b/.buildkite/pipeline-utils/buildkite/types/job.ts new file mode 100644 index 000000000000..b1b5a756ce89 --- /dev/null +++ b/.buildkite/pipeline-utils/buildkite/types/job.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Agent } from './agent'; + +export type JobState = + | 'pending' + | 'waiting' + | 'waiting_failed' + | 'blocked' + | 'blocked_failed' + | 'unblocked' + | 'unblocked_failed' + | 'limiting' + | 'limited' + | 'scheduled' + | 'assigned' + | 'accepted' + | 'running' + | 'passed' + | 'failed' + | 'canceling' + | 'canceled' + | 'timing_out' + | 'timed_out' + | 'skipped' + | 'broken'; + +export interface Job { + id: string; + type: string; + name: string; + step_key: string; + state: JobState; + logs_url: string; + raw_log_url: string; + command: string; + exit_status: null | number; + artifact_paths: string; + artifacts_url: string; + created_at: string; + scheduled_at: string; + runnable_at: string; + started_at: string; + finished_at: string; + agent: Agent; + agent_query_rules: string[]; + web_url: string; + retried: boolean; + retried_in_job_id: string; + retries_count: number; + soft_failed: boolean; + unblocked_by: { + id: string; + name: string; + email: string; + avatar_url: string; + created_at: string; + }; + unblockable: boolean; + unblock_url: string; + parallel_group_index?: null | number; + parallel_group_total?: null | number; +} diff --git a/.buildkite/pipeline-utils/buildkite/types/pipeline.ts b/.buildkite/pipeline-utils/buildkite/types/pipeline.ts new file mode 100644 index 000000000000..08255796c56c --- /dev/null +++ b/.buildkite/pipeline-utils/buildkite/types/pipeline.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface Pipeline { + id: string; + url: string; + web_url: string; + name: string; + slug: string; + repository: string; + builds_url: string; + badge_url: string; + created_at: string; + default_branch: string; + description: string; + branch_configuration: string; + skip_queued_branch_builds: boolean; + skip_queued_branch_builds_filter: string; + cancel_running_branch_builds: boolean; + cancel_running_branch_builds_filter: string; + cluster_id: string; + + scheduled_builds_count: number; + running_builds_count: number; + scheduled_jobs_count: number; + running_jobs_count: number; + waiting_jobs_count: number; + + provider: { + id: string; + webhook_url: string; + settings: Record; + }; + + steps: Step[]; + configuration: string; + env: Record; +} + +export interface Step { + type: string; + name: string; + command: string; + artifact_paths: string; + branch_configuration: string; + env: Record; + timeout_in_minutes: number; + agent_query_rules: string[]; +} diff --git a/.buildkite/pipeline-utils/ci-stats/client.ts b/.buildkite/pipeline-utils/ci-stats/client.ts new file mode 100644 index 000000000000..9011eb35a5ca --- /dev/null +++ b/.buildkite/pipeline-utils/ci-stats/client.ts @@ -0,0 +1,211 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import axios, { Method, AxiosRequestConfig } from 'axios'; + +export interface CiStatsClientConfig { + baseUrl?: string; + token?: string; +} + +export interface CiStatsBuild { + id: string; +} + +export interface CiStatsPrReport { + md: string; + success: boolean; +} + +export interface CompleteSuccessBuildSource { + jobName: string; + jobRunner: string; + completedAt: string; + commit: string; + startedAt: string; + branch: string; + result: 'SUCCESS'; + jobId: string; + targetBranch: string | null; + fromKibanaCiProduction: boolean; + requiresValidMetrics: boolean | null; + jobUrl: string; + mergeBase: string | null; +} + +export interface TestGroupRunOrderResponse { + sources: unknown; + types: Array<{ + type: string; + count: number; + groups: Array<{ + durationMin: number; + names: string[]; + }>; + tooLong?: Array<{ config: string; durationMin: number }>; + namesWithoutDurations: string[]; + }>; +} + +interface RequestOptions { + path: string; + method?: Method; + params?: AxiosRequestConfig['params']; + body?: AxiosRequestConfig['data']; + maxAttempts?: number; +} + +export class CiStatsClient { + private readonly baseUrl: string; + private readonly defaultHeaders: Record; + + constructor(config: CiStatsClientConfig = {}) { + const CI_STATS_HOST = config.baseUrl ?? process.env.CI_STATS_HOST; + const CI_STATS_TOKEN = config.token ?? process.env.CI_STATS_TOKEN; + + this.baseUrl = `https://${CI_STATS_HOST}`; + this.defaultHeaders = { + Authorization: `token ${CI_STATS_TOKEN}`, + }; + } + + createBuild = async () => { + const resp = await this.request({ + method: 'POST', + path: '/v1/build', + body: { + jenkinsJobName: process.env.BUILDKITE_PIPELINE_SLUG, + jenkinsJobId: process.env.BUILDKITE_BUILD_NUMBER, + jenkinsUrl: process.env.BUILDKITE_BUILD_URL, + prId: process.env.GITHUB_PR_NUMBER || null, + }, + }); + + return resp.data; + }; + + addGitInfo = async (buildId: string) => { + await this.request({ + method: 'POST', + path: '/v1/git_info', + params: { + buildId, + }, + body: { + branch: (process.env.BUILDKITE_BRANCH || '').replace(/^(refs\/heads\/|origin\/)/, ''), + commit: process.env.BUILDKITE_COMMIT, + targetBranch: + process.env.GITHUB_PR_TARGET_BRANCH || + process.env.BUILDKITE_PULL_REQUEST_BASE_BRANCH || + null, + mergeBase: process.env.GITHUB_PR_MERGE_BASE || null, + }, + }); + }; + + markBuildAsValidBaseline = async (buildId: string) => { + await this.request({ + method: 'POST', + path: `/v1/build/_is_valid_baseline`, + params: { + id: buildId, + }, + }); + }; + + completeBuild = async (buildStatus: string, buildId: string) => { + await this.request({ + method: 'POST', + path: `/v1/build/_complete`, + params: { + id: buildId, + }, + body: { + result: buildStatus, + }, + }); + }; + + getPrReport = async (buildId: string) => { + const resp = await this.request({ + path: `v2/pr_report`, + params: { + buildId, + }, + }); + + return resp.data; + }; + + pickTestGroupRunOrder = async (body: { + sources: Array< + | { + branch: string; + jobName: string; + } + | { + prId: string; + jobName: string; + } + | { + commit: string; + jobName: string; + } + >; + groups: Array<{ + type: string; + defaultMin?: number; + maxMin: number; + minimumIsolationMin?: number; + overheadMin?: number; + names: string[]; + }>; + }) => { + console.log('requesting test group run order from ci-stats:'); + console.log(JSON.stringify(body, null, 2)); + + const resp = await axios.request({ + method: 'POST', + baseURL: this.baseUrl, + headers: this.defaultHeaders, + url: '/v2/_pick_test_group_run_order', + data: body, + }); + + return resp.data; + }; + + private async request({ method, path, params, body, maxAttempts = 3 }: RequestOptions) { + let attempt = 0; + + while (true) { + attempt += 1; + try { + return await axios.request({ + method, + baseURL: this.baseUrl, + url: path, + params, + data: body, + headers: this.defaultHeaders, + }); + } catch (error) { + console.error('CI Stats request error:', error); + + if (attempt < maxAttempts) { + const sec = attempt * 3; + console.log('waiting', sec, 'seconds before retrying'); + await new Promise((resolve) => setTimeout(resolve, sec * 1000)); + continue; + } + + throw error; + } + } + } +} diff --git a/.buildkite/pipeline-utils/ci-stats/index.ts b/.buildkite/pipeline-utils/ci-stats/index.ts new file mode 100644 index 000000000000..6b1f8a67080b --- /dev/null +++ b/.buildkite/pipeline-utils/ci-stats/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './client'; +export * from './on_complete'; +export * from './on_metrics_viable'; +export * from './on_start'; +export * from './pick_test_group_run_order'; diff --git a/.buildkite/pipeline-utils/ci-stats/on_complete.ts b/.buildkite/pipeline-utils/ci-stats/on_complete.ts new file mode 100644 index 000000000000..0b93fd6b0673 --- /dev/null +++ b/.buildkite/pipeline-utils/ci-stats/on_complete.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { BuildkiteClient } from '../buildkite'; +import { CiStatsClient } from './client'; + +const buildkite = new BuildkiteClient(); +const ciStats = new CiStatsClient(); + +export async function onComplete() { + if (!process.env.CI_STATS_BUILD_ID) { + return; + } + + const result = buildkite.getBuildStatus(await buildkite.getCurrentBuild()); + const status = result.success ? 'SUCCESS' : 'FAILURE'; + console.log('Job Status:', result); + await ciStats.completeBuild(status, process.env.CI_STATS_BUILD_ID); + + if (!process.env.GITHUB_PR_NUMBER) { + return; + } + + const report = await ciStats.getPrReport(process.env.CI_STATS_BUILD_ID); + if (report?.md) { + buildkite.setMetadata('pr_comment:ci_stats_report:body', report.md); + + const annotationType = report?.success ? 'info' : 'error'; + buildkite.setAnnotation('ci-stats-report', annotationType, report.md); + } + + if (report && !report.success) { + console.log('+++ CI Stats Report'); + console.error('Failing build due to CI Stats report. See annotation at top of build.'); + process.exit(1); + } +} diff --git a/.buildkite/pipeline-utils/ci-stats/on_metrics_viable.ts b/.buildkite/pipeline-utils/ci-stats/on_metrics_viable.ts new file mode 100644 index 000000000000..50e9d7f3a577 --- /dev/null +++ b/.buildkite/pipeline-utils/ci-stats/on_metrics_viable.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { CiStatsClient } from './client'; + +const ciStats = new CiStatsClient(); + +export async function onMetricsViable() { + if (!process.env.CI_STATS_BUILD_ID) { + return; + } + + console.log('Marking build as a "valid baseline" so that it can be used to power PR reports'); + await ciStats.markBuildAsValidBaseline(process.env.CI_STATS_BUILD_ID); +} diff --git a/.buildkite/pipeline-utils/ci-stats/on_start.ts b/.buildkite/pipeline-utils/ci-stats/on_start.ts new file mode 100644 index 000000000000..beee04e0198d --- /dev/null +++ b/.buildkite/pipeline-utils/ci-stats/on_start.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { execSync } from 'child_process'; +import { CiStatsClient } from './client'; + +const ciStats = new CiStatsClient(); + +export async function onStart() { + const build = await ciStats.createBuild(); + execSync(`buildkite-agent meta-data set ci_stats_build_id "${build.id}"`); + await ciStats.addGitInfo(build.id); +} diff --git a/.buildkite/pipeline-utils/ci-stats/pick_test_group_run_order.ts b/.buildkite/pipeline-utils/ci-stats/pick_test_group_run_order.ts new file mode 100644 index 000000000000..9f18ba5c8972 --- /dev/null +++ b/.buildkite/pipeline-utils/ci-stats/pick_test_group_run_order.ts @@ -0,0 +1,397 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as Fs from 'fs'; + +import * as globby from 'globby'; +import minimatch from 'minimatch'; +import { load as loadYaml } from 'js-yaml'; + +import { BuildkiteClient, BuildkiteStep } from '../buildkite'; +import { CiStatsClient, TestGroupRunOrderResponse } from './client'; + +type RunGroup = TestGroupRunOrderResponse['types'][0]; + +const getRequiredEnv = (name: string) => { + const value = process.env[name]; + if (typeof value !== 'string' || !value) { + throw new Error(`Missing required environment variable "${name}"`); + } + return value; +}; + +function getRunGroup(bk: BuildkiteClient, types: RunGroup[], typeName: string): RunGroup { + const type = types.find((t) => t.type === typeName); + if (!type) { + throw new Error(`missing test group run order for group [${typeName}]`); + } + + const misses = type.namesWithoutDurations.length; + if (misses > 0) { + bk.setAnnotation( + `test-group-missing-durations:${typeName}`, + 'warning', + [ + misses === 1 + ? `The following "${typeName}" config doesn't have a recorded time in ci-stats so the automatically-determined test groups might be a little unbalanced.` + : `The following "${typeName}" configs don't have recorded times in ci-stats so the automatically-determined test groups might be a little unbalanced.`, + misses === 1 + ? `If this is a new config then this warning can be ignored as times will be reported soon.` + : `If these are new configs then this warning can be ignored as times will be reported soon.`, + misses === 1 + ? `The other possibility is that there aren't any tests in this config, so times are never reported.` + : `The other possibility is that there aren't any tests in these configs, so times are never reported.`, + 'Empty test configs should be removed', + '', + ...type.namesWithoutDurations.map((n) => ` - ${n}`), + ].join('\n') + ); + } + + const tooLongs = type.tooLong?.length ?? 0; + if (tooLongs > 0) { + bk.setAnnotation( + `test-group-too-long:${typeName}`, + 'error', + [ + tooLongs === 1 + ? `The following "${typeName}" config has a duration that exceeds the maximum amount of time desired for a single CI job. Please split it up.` + : `The following "${typeName}" configs have durations that exceed the maximum amount of time desired for a single CI job. Please split them up.`, + '', + ...(type.tooLong ?? []).map( + ({ config, durationMin }) => ` - ${config}: ${durationMin} minutes` + ), + ].join('\n') + ); + } + + return type; +} + +function getTrackedBranch(): string { + let pkg; + try { + pkg = JSON.parse(Fs.readFileSync('package.json', 'utf8')); + } catch (_) { + const error = _ instanceof Error ? _ : new Error(`${_} thrown`); + throw new Error(`unable to read kibana's package.json file: ${error.message}`); + } + + const branch = pkg.branch; + if (typeof branch !== 'string') { + throw new Error('missing `branch` field from package.json file'); + } + + return branch; +} + +function isObj(x: unknown): x is Record { + return typeof x === 'object' && x !== null; +} + +function getEnabledFtrConfigs(patterns?: string[]) { + try { + const configs = loadYaml(Fs.readFileSync('.buildkite/ftr_configs.yml', 'utf8')); + if (!isObj(configs)) { + throw new Error('expected yaml file to parse to an object'); + } + if (!configs.enabled) { + throw new Error('expected yaml file to have an "enabled" key'); + } + if ( + !Array.isArray(configs.enabled) || + !configs.enabled.every((p): p is string => typeof p === 'string') + ) { + throw new Error('expected "enabled" value to be an array of strings'); + } + + if (!patterns) { + return configs.enabled; + } + + return configs.enabled.filter((path) => patterns.some((pattern) => minimatch(path, pattern))); + } catch (_) { + const error = _ instanceof Error ? _ : new Error(`${_} thrown`); + throw new Error(`unable to parse ftr_configs.yml file: ${error.message}`); + } +} + +export async function pickTestGroupRunOrder() { + const bk = new BuildkiteClient(); + const ciStats = new CiStatsClient(); + + // these keys are synchronized in a few placed by storing them in the env during builds + const UNIT_TYPE = getRequiredEnv('TEST_GROUP_TYPE_UNIT'); + const INTEGRATION_TYPE = getRequiredEnv('TEST_GROUP_TYPE_INTEGRATION'); + const FUNCTIONAL_TYPE = getRequiredEnv('TEST_GROUP_TYPE_FUNCTIONAL'); + + const JEST_MAX_MINUTES = process.env.JEST_MAX_MINUTES + ? parseFloat(process.env.JEST_MAX_MINUTES) + : 50; + if (Number.isNaN(JEST_MAX_MINUTES)) { + throw new Error(`invalid JEST_MAX_MINUTES: ${process.env.JEST_MAX_MINUTES}`); + } + + const FUNCTIONAL_MAX_MINUTES = process.env.FUNCTIONAL_MAX_MINUTES + ? parseFloat(process.env.FUNCTIONAL_MAX_MINUTES) + : 37; + if (Number.isNaN(FUNCTIONAL_MAX_MINUTES)) { + throw new Error(`invalid FUNCTIONAL_MAX_MINUTES: ${process.env.FUNCTIONAL_MAX_MINUTES}`); + } + + const LIMIT_CONFIG_TYPE = process.env.LIMIT_CONFIG_TYPE + ? process.env.LIMIT_CONFIG_TYPE.split(',') + .map((t) => t.trim()) + .filter(Boolean) + : ['unit', 'integration', 'functional']; + + const FTR_CONFIG_PATTERNS = process.env.FTR_CONFIG_PATTERNS + ? process.env.FTR_CONFIG_PATTERNS.split(',') + .map((t) => t.trim()) + .filter(Boolean) + : undefined; + + const FUNCTIONAL_MINIMUM_ISOLATION_MIN = process.env.FUNCTIONAL_MINIMUM_ISOLATION_MIN + ? parseFloat(process.env.FUNCTIONAL_MINIMUM_ISOLATION_MIN) + : undefined; + if ( + FUNCTIONAL_MINIMUM_ISOLATION_MIN !== undefined && + Number.isNaN(FUNCTIONAL_MINIMUM_ISOLATION_MIN) + ) { + throw new Error( + `invalid FUNCTIONAL_MINIMUM_ISOLATION_MIN: ${process.env.FUNCTIONAL_MINIMUM_ISOLATION_MIN}` + ); + } + + const FTR_CONFIGS_RETRY_COUNT = process.env.FTR_CONFIGS_RETRY_COUNT + ? parseInt(process.env.FTR_CONFIGS_RETRY_COUNT, 10) + : 1; + if (Number.isNaN(FTR_CONFIGS_RETRY_COUNT)) { + throw new Error(`invalid FTR_CONFIGS_RETRY_COUNT: ${process.env.FTR_CONFIGS_RETRY_COUNT}`); + } + + const FTR_CONFIGS_DEPS = + process.env.FTR_CONFIGS_DEPS !== undefined + ? process.env.FTR_CONFIGS_DEPS.split(',') + .map((t) => t.trim()) + .filter(Boolean) + : ['build']; + + const ftrConfigs = LIMIT_CONFIG_TYPE.includes('functional') + ? getEnabledFtrConfigs(FTR_CONFIG_PATTERNS) + : []; + + const jestUnitConfigs = LIMIT_CONFIG_TYPE.includes('unit') + ? globby.sync(['**/jest.config.js', '!**/__fixtures__/**'], { + cwd: process.cwd(), + absolute: false, + }) + : []; + + const jestIntegrationConfigs = LIMIT_CONFIG_TYPE.includes('integration') + ? globby.sync(['**/jest.integration.config.js', '!**/__fixtures__/**'], { + cwd: process.cwd(), + absolute: false, + }) + : []; + + if (!ftrConfigs.length && !jestUnitConfigs.length && !jestIntegrationConfigs.length) { + throw new Error('unable to find any unit, integration, or FTR configs'); + } + + const trackedBranch = getTrackedBranch(); + const ownBranch = process.env.BUILDKITE_BRANCH as string; + const pipelineSlug = process.env.BUILDKITE_PIPELINE_SLUG as string; + const prNumber = process.env.GITHUB_PR_NUMBER as string | undefined; + + const { sources, types } = await ciStats.pickTestGroupRunOrder({ + sources: [ + // try to get times from a recent successful job on this PR + ...(prNumber + ? [ + { + prId: prNumber, + jobName: 'kibana-pull-request', + }, + ] + : []), + // if we are running on a external job, like kibana-code-coverage-main, try finding times that are specific to that job + ...(!prNumber && pipelineSlug !== 'kibana-on-merge' + ? [ + { + branch: ownBranch, + jobName: pipelineSlug, + }, + { + branch: trackedBranch, + jobName: pipelineSlug, + }, + ] + : []), + // try to get times from the mergeBase commit + ...(process.env.GITHUB_PR_MERGE_BASE + ? [ + { + commit: process.env.GITHUB_PR_MERGE_BASE, + jobName: 'kibana-on-merge', + }, + ] + : []), + // fallback to the latest times from the tracked branch + { + branch: trackedBranch, + jobName: 'kibana-on-merge', + }, + // finally fallback to the latest times from the main branch in case this branch is brand new + { + branch: 'main', + jobName: 'kibana-on-merge', + }, + ], + groups: [ + { + type: UNIT_TYPE, + defaultMin: 3, + maxMin: JEST_MAX_MINUTES, + overheadMin: 0.2, + names: jestUnitConfigs, + }, + { + type: INTEGRATION_TYPE, + defaultMin: 10, + maxMin: JEST_MAX_MINUTES, + overheadMin: 0.2, + names: jestIntegrationConfigs, + }, + { + type: FUNCTIONAL_TYPE, + defaultMin: 60, + maxMin: FUNCTIONAL_MAX_MINUTES, + minimumIsolationMin: FUNCTIONAL_MINIMUM_ISOLATION_MIN, + overheadMin: 1.5, + names: ftrConfigs, + }, + ], + }); + + console.log('test run order is determined by builds:'); + console.dir(sources, { depth: Infinity, maxArrayLength: Infinity }); + + const unit = getRunGroup(bk, types, UNIT_TYPE); + const integration = getRunGroup(bk, types, INTEGRATION_TYPE); + const functional = getRunGroup(bk, types, FUNCTIONAL_TYPE); + + // write the config for each step to an artifact that can be used by the individual jest jobs + Fs.writeFileSync('jest_run_order.json', JSON.stringify({ unit, integration }, null, 2)); + bk.uploadArtifacts('jest_run_order.json'); + + // write the config for functional steps to an artifact that can be used by the individual functional jobs + Fs.writeFileSync('ftr_run_order.json', JSON.stringify(functional, null, 2)); + bk.uploadArtifacts('ftr_run_order.json'); + + let smallFtrConfigsCounter = 0; + const getSmallFtrConfigsLabel = () => { + return `Super Quick FTR Configs #${++smallFtrConfigsCounter}`; + }; + + // upload the step definitions to Buildkite + bk.uploadSteps( + [ + unit.count > 0 + ? { + label: 'Jest Tests', + command: getRequiredEnv('JEST_UNIT_SCRIPT'), + parallelism: unit.count, + timeout_in_minutes: 90, + key: 'jest', + agents: { + queue: 'n2-4-spot', + }, + retry: { + automatic: [ + { + exit_status: '-1', + limit: 3, + }, + ], + }, + } + : [], + integration.count > 0 + ? { + label: 'Jest Integration Tests', + command: getRequiredEnv('JEST_INTEGRATION_SCRIPT'), + parallelism: integration.count, + timeout_in_minutes: 120, + key: 'jest-integration', + agents: { + queue: 'n2-4-spot', + }, + retry: { + automatic: [ + { + exit_status: '-1', + limit: 3, + }, + ], + }, + } + : [], + functional.count > 0 + ? FUNCTIONAL_MINIMUM_ISOLATION_MIN === undefined + ? { + label: 'FTR Configs', + key: 'ftr-configs', + depends_on: FTR_CONFIGS_DEPS, + parallelism: functional.count, + command: getRequiredEnv('FTR_CONFIGS_SCRIPT'), + timeout_in_minutes: 150, + agents: { + queue: 'n2-4-spot-2', + }, + retry: { + automatic: [ + { exit_status: '-1', limit: 3 }, + ...(FTR_CONFIGS_RETRY_COUNT > 0 + ? [{ exit_status: '*', limit: FTR_CONFIGS_RETRY_COUNT }] + : []), + ], + }, + } + : { + group: 'FTR Configs', + key: 'ftr-configs', + depends_on: FTR_CONFIGS_DEPS, + steps: functional.groups + .map( + (group, i): BuildkiteStep => ({ + label: group.names.length === 1 ? group.names[0] : getSmallFtrConfigsLabel(), + command: getRequiredEnv('FTR_CONFIGS_SCRIPT'), + timeout_in_minutes: 150, + agents: { + queue: 'n2-4-spot-2', + }, + env: { + FTR_CONFIG_GROUP_INDEX: `${i}`, + }, + retry: { + automatic: [ + { exit_status: '-1', limit: 3 }, + ...(FTR_CONFIGS_RETRY_COUNT > 0 + ? [{ exit_status: '*', limit: FTR_CONFIGS_RETRY_COUNT }] + : []), + ], + }, + }) + ) + .sort((a, b) => a.label.localeCompare(b.label)), + } + : [], + ].flat() + ); +} diff --git a/.buildkite/pipeline-utils/github/github.test.ts b/.buildkite/pipeline-utils/github/github.test.ts new file mode 100644 index 000000000000..31c0cdb4cd31 --- /dev/null +++ b/.buildkite/pipeline-utils/github/github.test.ts @@ -0,0 +1,132 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { RestEndpointMethodTypes } from '@octokit/rest'; +import { expect } from 'chai'; +import { areChangesSkippable, doAnyChangesMatch } from './github'; + +describe('github', () => { + const getMockChangedFile = (filename: string, previousFilename = '') => { + return { + filename, + previous_filename: previousFilename || undefined, + } as RestEndpointMethodTypes['pulls']['listFiles']['response']['data'][number]; + }; + + describe('doAnyChangesMatch', () => { + const required = [/^\/required/]; + + describe('should return true', () => { + it('when any file matches', async () => { + const match = await doAnyChangesMatch(required, [ + getMockChangedFile('/required/index.js'), + getMockChangedFile('/package.json'), + ]); + + expect(match).to.eql(true); + }); + + it('when all files match', async () => { + const match = await doAnyChangesMatch(required, [ + getMockChangedFile('/required/index.js'), + getMockChangedFile('/required/package.json'), + ]); + + expect(match).to.eql(true); + }); + }); + + describe('should return false', () => { + it('when no files match with one file', async () => { + const match = await doAnyChangesMatch(required, [getMockChangedFile('/index.js')]); + + expect(match).to.eql(false); + }); + + it('when no files match with multiple files', async () => { + const match = await doAnyChangesMatch(required, [ + getMockChangedFile('/index.js'), + getMockChangedFile('/package.json'), + ]); + + expect(match).to.eql(false); + }); + }); + }); + + describe('areChangesSkippable', () => { + const skippable = [/^docs\//, /^rfcs\//, /\.md$/]; + const required = [/required\.md$/]; + + describe('should not be skippable', () => { + it('when non-skippable files are present', async () => { + const execute = await areChangesSkippable(skippable, required, [ + getMockChangedFile('docs/required.md'), + getMockChangedFile('package.json'), + ]); + + expect(execute).to.eql(false); + }); + + it('when all files are non-skippable, non-required', async () => { + const execute = await areChangesSkippable(skippable, required, [ + getMockChangedFile('package.json'), + ]); + + expect(execute).to.eql(false); + }); + + it('when a required file is present', async () => { + const execute = await areChangesSkippable(skippable, required, [ + getMockChangedFile('docs/required.md'), + getMockChangedFile('docs/whatever.md'), + ]); + + expect(execute).to.eql(false); + }); + + it('when a required file is renamed', async () => { + const execute = await areChangesSkippable(skippable, required, [ + getMockChangedFile('docs/skipme.md', 'docs/required.md'), + ]); + + expect(execute).to.eql(false); + }); + }); + + describe('should be skippable', () => { + it('when all files are skippable', async () => { + const execute = await areChangesSkippable(skippable, required, [ + getMockChangedFile('docs/index.js'), + getMockChangedFile('README.md'), + ]); + + expect(execute).to.eql(true); + }); + + it('when all files are skippable and no required files are passed in', async () => { + const execute = await areChangesSkippable( + skippable, + [], + [getMockChangedFile('docs/index.js'), getMockChangedFile('README.md')] + ); + + expect(execute).to.eql(true); + }); + + it('when renamed files new and old locations are skippable', async () => { + const execute = await areChangesSkippable(skippable, required, [ + getMockChangedFile('docs/index.js', 'docs/old.js'), + getMockChangedFile('README.md', 'DOCS.md'), + ]); + + expect(execute).to.eql(true); + }); + }); + }); +}); diff --git a/.buildkite/pipeline-utils/github/github.ts b/.buildkite/pipeline-utils/github/github.ts new file mode 100644 index 000000000000..fc6ab42a69a5 --- /dev/null +++ b/.buildkite/pipeline-utils/github/github.ts @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Octokit, RestEndpointMethodTypes } from '@octokit/rest'; + +const github = new Octokit({ + auth: process.env.GITHUB_TOKEN, +}); + +let prChangesCache: null | RestEndpointMethodTypes['pulls']['listFiles']['response']['data'] = null; + +export const getPrChanges = async ( + owner = process.env.GITHUB_PR_BASE_OWNER, + repo = process.env.GITHUB_PR_BASE_REPO, + prNumber: undefined | string | number = process.env.GITHUB_PR_NUMBER +) => { + if (!owner || !repo || !prNumber) { + throw Error( + "Couldn't retrieve Github PR info from environment variables in order to retrieve PR changes" + ); + } + + const files = await github.paginate(github.pulls.listFiles, { + owner, + repo, + pull_number: typeof prNumber === 'number' ? prNumber : parseInt(prNumber, 10), + per_page: 100, + }); + + return files; +}; + +export const getPrChangesCached = async () => { + prChangesCache = prChangesCache || (await getPrChanges()); + return prChangesCache; +}; + +export const areChangesSkippable = async ( + skippablePaths: RegExp[], + requiredPaths: RegExp[] = [], + changes: null | RestEndpointMethodTypes['pulls']['listFiles']['response']['data'] = null +) => { + const prChanges = changes || (await getPrChangesCached()); + + if (prChanges.length >= 3000) { + return false; + } + + if (requiredPaths?.length) { + const someFilesMatchRequired = requiredPaths.some((path) => + prChanges.some( + (change) => change.filename.match(path) || change.previous_filename?.match(path) + ) + ); + + if (someFilesMatchRequired) { + return false; + } + } + + const someFilesNotSkippable = prChanges.some( + (change) => + !skippablePaths.some( + (path) => + change.filename.match(path) && + (!change.previous_filename || change.previous_filename.match(path)) + ) + ); + + return !someFilesNotSkippable; +}; + +export const doAnyChangesMatch = async ( + requiredPaths: RegExp[], + changes: null | RestEndpointMethodTypes['pulls']['listFiles']['response']['data'] = null +) => { + const prChanges = changes || (await getPrChangesCached()); + + if (prChanges.length >= 3000) { + return true; + } + + const anyFilesMatchRequired = requiredPaths.some((path) => + prChanges.some((change) => change.filename.match(path) || change.previous_filename?.match(path)) + ); + + return anyFilesMatchRequired; +}; diff --git a/.buildkite/pipeline-utils/github/index.ts b/.buildkite/pipeline-utils/github/index.ts new file mode 100644 index 000000000000..880a09668f82 --- /dev/null +++ b/.buildkite/pipeline-utils/github/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './github'; diff --git a/.buildkite/pipeline-utils/index.ts b/.buildkite/pipeline-utils/index.ts new file mode 100644 index 000000000000..113ab1ac2458 --- /dev/null +++ b/.buildkite/pipeline-utils/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './buildkite'; +export * as CiStats from './ci-stats'; +export * from './github'; +export * as TestFailures from './test-failures'; diff --git a/.buildkite/pipeline-utils/test-failures/annotate.test.ts b/.buildkite/pipeline-utils/test-failures/annotate.test.ts new file mode 100644 index 000000000000..1f3bf5eac871 --- /dev/null +++ b/.buildkite/pipeline-utils/test-failures/annotate.test.ts @@ -0,0 +1,110 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { expect } from 'chai'; +import { Artifact } from '../buildkite/types/artifact'; +import { TestFailure, getAnnotation, getSlackMessage, getPrComment } from './annotate'; + +let mockFailure: TestFailure; +let mockArtifacts: Record; + +describe('Annotate', () => { + beforeEach(() => { + mockFailure = { + url: 'https://buildkite.com/elastic/kibana-pull-request/builds/53', + jobId: 'job-id', + buildId: 'build-id', + hash: 'hash', + name: 'test should fail', + classname: 'Chrome UI Functional Tests.test/functional/apps/console/_consoleĀ·ts', + jobName: 'OSS CI Group #1', + } as TestFailure; + + mockArtifacts = { + 'job-idhash': { + id: 'artifact-id', + } as Artifact, + }; + }); + + describe('getAnnotation', () => { + it('should create an annotation without logs link if artifact is missing', () => { + const annotation = getAnnotation([mockFailure], {}); + + expect(annotation).to.eql( + '**Test Failures**
\n[[job]](https://buildkite.com/elastic/kibana-pull-request/builds/53#job-id) OSS CI Group #1 / test should fail' + ); + }); + + it('should create an annotation with logs link if artifact is present', () => { + const annotation = getAnnotation([mockFailure], mockArtifacts); + + expect(annotation).to.eql( + '**Test Failures**
\n[[job]](https://buildkite.com/elastic/kibana-pull-request/builds/53#job-id) [[logs]](https://buildkite.com/organizations/elastic/pipelines/kibana-pull-request/builds/53/jobs/job-id/artifacts/artifact-id) OSS CI Group #1 / test should fail' + ); + }); + }); + + describe('getSlackMessage', () => { + it('should create an annotation without logs link if artifact is missing', () => { + const annotation = getSlackMessage([mockFailure, mockFailure], {}); + + expect(annotation).to.eql( + '*Test Failures*\n' + + ' OSS CI Group #1 / test should fail\n' + + ' OSS CI Group #1 / test should fail' + ); + }); + + it('should create an annotation with logs link if artifact is present', () => { + const annotation = getSlackMessage([mockFailure], mockArtifacts); + + expect(annotation).to.eql( + '*Test Failures*\n OSS CI Group #1 / test should fail' + ); + }); + + it('should create an annotation with 1 failure count if count present', () => { + mockFailure.failureCount = 1; + mockFailure.githubIssue = 'https://github.com/some/failure/link/1234'; + const annotation = getSlackMessage([mockFailure], mockArtifacts); + + expect(annotation).to.eql( + '*Test Failures*\n OSS CI Group #1 / test should fail' + ); + }); + + it('should create an annotation with 2+ failures count if count present', () => { + mockFailure.failureCount = 2; + mockFailure.githubIssue = 'https://github.com/some/failure/link/1234'; + const annotation = getSlackMessage([mockFailure], mockArtifacts); + + expect(annotation).to.eql( + '*Test Failures*\n OSS CI Group #1 / test should fail' + ); + }); + }); + + describe('getPrComment', () => { + it('should create an annotation without logs link if artifact is missing', () => { + const annotation = getPrComment([mockFailure], {}); + + expect(annotation).to.eql( + '### Test Failures\n* [[job]](https://buildkite.com/elastic/kibana-pull-request/builds/53#job-id) OSS CI Group #1 / test should fail' + ); + }); + + it('should create an annotation with logs link if artifact is present', () => { + const annotation = getPrComment([mockFailure], mockArtifacts); + + expect(annotation).to.eql( + '### Test Failures\n* [[job]](https://buildkite.com/elastic/kibana-pull-request/builds/53#job-id) [[logs]](https://buildkite.com/organizations/elastic/pipelines/kibana-pull-request/builds/53/jobs/job-id/artifacts/artifact-id) OSS CI Group #1 / test should fail' + ); + }); + }); +}); diff --git a/.buildkite/pipeline-utils/test-failures/annotate.ts b/.buildkite/pipeline-utils/test-failures/annotate.ts new file mode 100644 index 000000000000..8ac896c99434 --- /dev/null +++ b/.buildkite/pipeline-utils/test-failures/annotate.ts @@ -0,0 +1,185 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { execSync } from 'child_process'; +import { mkdirSync, readdirSync, readFileSync, statSync } from 'fs'; +import { join } from 'path'; +import { BuildkiteClient } from '..'; +import { Artifact } from '../buildkite/types/artifact'; + +const buildkite = new BuildkiteClient(); + +export interface TestFailure { + name: string; + classname: string; + time: string; + 'metadata-json'?: string | undefined; + failure: string; + likelyIrrelevant: boolean; + 'system-out'?: string | undefined; + hash: string; + buildId: string; + jobId: string; + url: string; + jobName: string; + githubIssue?: string; + failureCount?: number; +} + +const recursiveReadDir = (dirPath: string, allFiles: string[] = []) => { + const files = readdirSync(dirPath); + + for (const file of files) { + if (statSync(join(dirPath, file)).isDirectory()) { + allFiles = recursiveReadDir(join(dirPath, file), allFiles); + } else { + allFiles.push(join(dirPath, file)); + } + } + + return allFiles; +}; + +export const getAnnotation = ( + failures: TestFailure[], + failureHtmlArtifacts: Record +): string => { + return ( + `**Test Failures**
\n` + + failures + .map((failure) => { + const lookup = failure.jobId + failure.hash; + const jobUrl = `${failure.url}#${failure.jobId}`; + const artifactUrl = + lookup in failureHtmlArtifacts + ? `${failure.url.replace( + 'https://buildkite.com/elastic', + 'https://buildkite.com/organizations/elastic/pipelines' + )}/jobs/${failure.jobId}/artifacts/${failureHtmlArtifacts[lookup].id}` + : ''; + + const logsLink = artifactUrl ? ` [[logs]](${artifactUrl})` : ''; + + return `[[job]](${jobUrl})${logsLink} ${failure.jobName} / ${failure.name}`; + }) + .join('
\n') + ); +}; + +export const getPrComment = ( + failures: TestFailure[], + failureHtmlArtifacts: Record +): string => { + return ( + `### Test Failures\n` + + failures + .map((failure) => { + const lookup = failure.jobId + failure.hash; + const jobUrl = `${failure.url}#${failure.jobId}`; + const artifactUrl = + lookup in failureHtmlArtifacts + ? `${failure.url.replace( + 'https://buildkite.com/elastic', + 'https://buildkite.com/organizations/elastic/pipelines' + )}/jobs/${failure.jobId}/artifacts/${failureHtmlArtifacts[lookup].id}` + : ''; + + const logsLink = artifactUrl ? ` [[logs]](${artifactUrl})` : ''; + + // job name could have # in it, which Github will link to an issue, so we need to "escape" it with spans + return `* [[job]](${jobUrl})${logsLink} ${failure.jobName.replace( + '#', + '#' + )} / ${failure.name}`; + }) + .join('\n') + ); +}; + +export const getSlackMessage = ( + failures: TestFailure[], + failureHtmlArtifacts: Record +): string => { + return ( + `*Test Failures*\n` + + failures + .map((failure) => { + const lookup = failure.jobId + failure.hash; + const jobUrl = `${failure.url}#${failure.jobId}`; + const artifactUrl = + lookup in failureHtmlArtifacts + ? `${failure.url.replace( + 'https://buildkite.com/elastic', + 'https://buildkite.com/organizations/elastic/pipelines' + )}/jobs/${failure.jobId}/artifacts/${failureHtmlArtifacts[lookup].id}` + : ''; + + const logsLink = artifactUrl ? ` <${artifactUrl}|[logs]>` : ''; + + const failuresCount = + failure.failureCount && failure.githubIssue + ? ` <${failure.githubIssue}|[${failure.failureCount} failure${ + failure.failureCount > 1 ? 's' : '' + }]>` + : ''; + + return `<${jobUrl}|[job]>${logsLink}${failuresCount} ${failure.jobName} / ${failure.name}`; + }) + .join('\n') + ); +}; + +export const annotateTestFailures = async () => { + const exec = (cmd: string) => execSync(cmd, { stdio: 'inherit' }); + + const failureDir = 'target/process-test-failures'; + mkdirSync(failureDir, { recursive: true }); + + const artifacts = await buildkite.getArtifactsForCurrentBuild(); + const failureHtmlArtifacts: Record = {}; + for (const artifact of artifacts) { + if (artifact.path.match(/test_failures\/.*?\.html$/)) { + const [jobId, hash] = artifact.filename.split(/_|\./); + failureHtmlArtifacts[jobId + hash] = artifact; + } + } + + exec( + `buildkite-agent artifact download --include-retried-jobs "target/test_failures/*.json" "${failureDir}"` + ); + + const failures: TestFailure[] = recursiveReadDir(failureDir) + .map((file) => { + try { + if (file.endsWith('.json')) { + return JSON.parse(readFileSync(file).toString()); + } + } catch (ex) { + console.error((ex as Error).message); + } + return null; + }) + .filter((f) => f) + .sort((a, b) => a.name.localeCompare(b.name)); + + buildkite.setAnnotation('test_failures', 'error', getAnnotation(failures, failureHtmlArtifacts)); + + if (process.env.PR_COMMENTS_ENABLED === 'true') { + buildkite.setMetadata( + 'pr_comment:test_failures:body', + getPrComment(failures, failureHtmlArtifacts) + ); + } + + if (process.env.SLACK_NOTIFICATIONS_ENABLED === 'true') { + buildkite.setMetadata( + 'slack:test_failures:body', + getSlackMessage(failures, failureHtmlArtifacts) + ); + } +}; diff --git a/.buildkite/pipeline-utils/test-failures/index.ts b/.buildkite/pipeline-utils/test-failures/index.ts new file mode 100644 index 000000000000..82622bac40b2 --- /dev/null +++ b/.buildkite/pipeline-utils/test-failures/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './annotate'; diff --git a/.buildkite/pipelines/flaky_tests/pipeline.sh b/.buildkite/pipelines/flaky_tests/pipeline.sh index 17fa0152e8b3..40c7ebb98f30 100755 --- a/.buildkite/pipelines/flaky_tests/pipeline.sh +++ b/.buildkite/pipelines/flaky_tests/pipeline.sh @@ -5,4 +5,4 @@ set -euo pipefail UUID="$(cat /proc/sys/kernel/random/uuid)" export UUID -node .buildkite/pipelines/flaky_tests/pipeline.js | buildkite-agent pipeline upload +ts-node .buildkite/pipelines/flaky_tests/pipeline.ts | buildkite-agent pipeline upload diff --git a/.buildkite/pipelines/flaky_tests/pipeline.js b/.buildkite/pipelines/flaky_tests/pipeline.ts similarity index 93% rename from .buildkite/pipelines/flaky_tests/pipeline.js rename to .buildkite/pipelines/flaky_tests/pipeline.ts index 56a6f6680683..ed3e64093a25 100644 --- a/.buildkite/pipelines/flaky_tests/pipeline.js +++ b/.buildkite/pipelines/flaky_tests/pipeline.ts @@ -6,6 +6,8 @@ * Side Public License, v 1. */ +import { groups } from './groups.json'; + const configJson = process.env.KIBANA_FLAKY_TEST_RUNNER_CONFIG; if (!configJson) { console.error('+++ Triggering directly is not supported anymore'); @@ -16,10 +18,6 @@ if (!configJson) { process.exit(1); } -const groups = /** @type {Array<{key: string, name: string, ciGroups: number }>} */ ( - require('./groups.json').groups -); - const concurrency = process.env.KIBANA_FLAKY_TEST_CONCURRENCY ? parseInt(process.env.KIBANA_FLAKY_TEST_CONCURRENCY, 10) : 25; @@ -33,8 +31,8 @@ if (Number.isNaN(concurrency)) { const BASE_JOBS = 1; const MAX_JOBS = 500; -function getTestSuitesFromJson(json) { - const fail = (errorMsg) => { +function getTestSuitesFromJson(json: string) { + const fail = (errorMsg: string) => { console.error('+++ Invalid test config provided'); console.error(`${errorMsg}: ${json}`); process.exit(1); @@ -108,7 +106,7 @@ if (totalJobs > MAX_JOBS) { process.exit(1); } -const steps = []; +const steps: any[] = []; const pipeline = { env: { IGNORE_SHIP_CI_STATS_ERROR: 'true', @@ -137,7 +135,7 @@ for (const testSuite of testSuites) { }, label: `FTR Config: ${testSuite.ftrConfig}`, parallelism: testSuite.count, - concurrency: concurrency, + concurrency, concurrency_group: process.env.UUID, concurrency_method: 'eager', agents: { @@ -159,7 +157,7 @@ for (const testSuite of testSuites) { switch (keyParts[0]) { case 'cypress': const CYPRESS_SUITE = keyParts[1]; - const group = groups.find((group) => group.key.includes(CYPRESS_SUITE)); + const group = groups.find((g) => g.key.includes(CYPRESS_SUITE)); if (!group) { throw new Error( `Group configuration was not found in groups.json for the following cypress suite: {${CYPRESS_SUITE}}.` @@ -171,7 +169,7 @@ for (const testSuite of testSuites) { agents: { queue: 'ci-group-6' }, depends_on: 'build', parallelism: testSuite.count, - concurrency: concurrency, + concurrency, concurrency_group: process.env.UUID, concurrency_method: 'eager', env: { diff --git a/.buildkite/pipelines/on_merge.yml b/.buildkite/pipelines/on_merge.yml index 153b99347046..7085bcaeedf7 100644 --- a/.buildkite/pipelines/on_merge.yml +++ b/.buildkite/pipelines/on_merge.yml @@ -23,7 +23,7 @@ steps: - path: - 'versions.json' config: - command: 'node .buildkite/scripts/steps/trigger_pipeline.js kibana-buildkite-pipelines-deploy main' + command: 'ts-node .buildkite/scripts/steps/trigger_pipeline.ts kibana-buildkite-pipelines-deploy main' label: 'Trigger pipeline deploy' agents: queue: 'kibana-default' diff --git a/.buildkite/scripts/lifecycle/annotate_test_failures.js b/.buildkite/scripts/lifecycle/annotate_test_failures.ts similarity index 91% rename from .buildkite/scripts/lifecycle/annotate_test_failures.js rename to .buildkite/scripts/lifecycle/annotate_test_failures.ts index 16af7ce78640..e73312a9e9bf 100644 --- a/.buildkite/scripts/lifecycle/annotate_test_failures.js +++ b/.buildkite/scripts/lifecycle/annotate_test_failures.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const { TestFailures } = require('kibana-buildkite-library'); +import { TestFailures } from '#pipeline-utils'; (async () => { try { diff --git a/.buildkite/scripts/lifecycle/build_status.js b/.buildkite/scripts/lifecycle/build_status.ts similarity index 92% rename from .buildkite/scripts/lifecycle/build_status.js rename to .buildkite/scripts/lifecycle/build_status.ts index e7599090d686..2fd9eda63b2b 100644 --- a/.buildkite/scripts/lifecycle/build_status.js +++ b/.buildkite/scripts/lifecycle/build_status.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const { BuildkiteClient } = require('kibana-buildkite-library'); +import { BuildkiteClient } from '#pipeline-utils'; (async () => { try { diff --git a/.buildkite/scripts/lifecycle/ci_stats_complete.js b/.buildkite/scripts/lifecycle/ci_stats_complete.ts similarity index 92% rename from .buildkite/scripts/lifecycle/ci_stats_complete.js rename to .buildkite/scripts/lifecycle/ci_stats_complete.ts index 5f1b59f51e34..bf42568126c6 100644 --- a/.buildkite/scripts/lifecycle/ci_stats_complete.js +++ b/.buildkite/scripts/lifecycle/ci_stats_complete.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const { CiStats } = require('kibana-buildkite-library'); +import { CiStats } from '#pipeline-utils'; (async () => { try { diff --git a/.buildkite/scripts/lifecycle/ci_stats_ready.js b/.buildkite/scripts/lifecycle/ci_stats_ready.ts similarity index 92% rename from .buildkite/scripts/lifecycle/ci_stats_ready.js rename to .buildkite/scripts/lifecycle/ci_stats_ready.ts index 6ff9454f521c..16b19478eb8b 100644 --- a/.buildkite/scripts/lifecycle/ci_stats_ready.js +++ b/.buildkite/scripts/lifecycle/ci_stats_ready.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const { CiStats } = require('kibana-buildkite-library'); +import { CiStats } from '#pipeline-utils'; (async () => { try { diff --git a/.buildkite/scripts/lifecycle/ci_stats_start.js b/.buildkite/scripts/lifecycle/ci_stats_start.ts similarity index 92% rename from .buildkite/scripts/lifecycle/ci_stats_start.js rename to .buildkite/scripts/lifecycle/ci_stats_start.ts index 25bc6c0b6ac4..f8c2696a6137 100644 --- a/.buildkite/scripts/lifecycle/ci_stats_start.js +++ b/.buildkite/scripts/lifecycle/ci_stats_start.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const { CiStats } = require('kibana-buildkite-library'); +import { CiStats } from '#pipeline-utils'; (async () => { try { diff --git a/.buildkite/scripts/lifecycle/post_build.sh b/.buildkite/scripts/lifecycle/post_build.sh index 5a181e8fa548..b5bdfd751a6e 100755 --- a/.buildkite/scripts/lifecycle/post_build.sh +++ b/.buildkite/scripts/lifecycle/post_build.sh @@ -2,14 +2,14 @@ set -euo pipefail -BUILD_SUCCESSFUL=$(node "$(dirname "${0}")/build_status.js") +BUILD_SUCCESSFUL=$(ts-node "$(dirname "${0}")/build_status.ts") export BUILD_SUCCESSFUL if [[ "${GITHUB_BUILD_COMMIT_STATUS_ENABLED:-}" != "true" ]]; then "$(dirname "${0}")/commit_status_complete.sh" fi -node "$(dirname "${0}")/ci_stats_complete.js" +ts-node "$(dirname "${0}")/ci_stats_complete.ts" if [[ "${GITHUB_PR_NUMBER:-}" ]]; then DOCS_CHANGES_URL="https://kibana_$GITHUB_PR_NUMBER}.docs-preview.app.elstc.co/diff" diff --git a/.buildkite/scripts/lifecycle/post_command.sh b/.buildkite/scripts/lifecycle/post_command.sh index 9cd342ff69fa..b5c85f9a926c 100755 --- a/.buildkite/scripts/lifecycle/post_command.sh +++ b/.buildkite/scripts/lifecycle/post_command.sh @@ -3,7 +3,7 @@ set -euo pipefail echo '--- Agent Debug Info' -node .buildkite/scripts/lifecycle/print_agent_links.js || true +ts-node .buildkite/scripts/lifecycle/print_agent_links.ts || true IS_TEST_EXECUTION_STEP="$(buildkite-agent meta-data get "${BUILDKITE_JOB_ID}_is_test_execution_step" --default '')" @@ -33,6 +33,6 @@ if [[ "$IS_TEST_EXECUTION_STEP" == "true" ]]; then if [[ -d 'target/test_failures' ]]; then buildkite-agent artifact upload 'target/test_failures/**/*' - node .buildkite/scripts/lifecycle/annotate_test_failures.js + ts-node .buildkite/scripts/lifecycle/annotate_test_failures.ts fi fi diff --git a/.buildkite/scripts/lifecycle/pre_build.sh b/.buildkite/scripts/lifecycle/pre_build.sh index 29da2d207dcc..107e555a430c 100755 --- a/.buildkite/scripts/lifecycle/pre_build.sh +++ b/.buildkite/scripts/lifecycle/pre_build.sh @@ -11,7 +11,7 @@ fi export CI_STATS_TOKEN="$(retry 5 5 vault read -field=api_token secret/kibana-issues/dev/kibana_ci_stats)" export CI_STATS_HOST="$(retry 5 5 vault read -field=api_host secret/kibana-issues/dev/kibana_ci_stats)" -node "$(dirname "${0}")/ci_stats_start.js" +ts-node "$(dirname "${0}")/ci_stats_start.ts" # We resolve the latest manifest URL at the beginning of the build to ensure that all steps in the build will use the same manifest # Otherwise, the manifest could change if a step is running around the time that a new one is promoted diff --git a/.buildkite/scripts/lifecycle/pre_command.sh b/.buildkite/scripts/lifecycle/pre_command.sh index b1f185720984..e95fa810f994 100755 --- a/.buildkite/scripts/lifecycle/pre_command.sh +++ b/.buildkite/scripts/lifecycle/pre_command.sh @@ -4,16 +4,21 @@ set -euo pipefail source .buildkite/scripts/common/util.sh +echo '--- Setup environment vars' +source .buildkite/scripts/common/env.sh +source .buildkite/scripts/common/setup_node.sh + BUILDKITE_TOKEN="$(retry 5 5 vault read -field=buildkite_token_all_jobs secret/kibana-issues/dev/buildkite-ci)" export BUILDKITE_TOKEN -echo '--- Install buildkite dependencies' +echo '--- Install/build buildkite dependencies' +npm install -g ts-node cd '.buildkite' retry 5 15 npm ci cd .. echo '--- Agent Debug/SSH Info' -node .buildkite/scripts/lifecycle/print_agent_links.js || true +ts-node .buildkite/scripts/lifecycle/print_agent_links.ts || true if [[ "$(curl -is metadata.google.internal || true)" ]]; then echo "" @@ -22,7 +27,6 @@ if [[ "$(curl -is metadata.google.internal || true)" ]]; then echo "" fi - echo '--- Job Environment Setup' # Set up a custom ES Snapshot Manifest if one has been specified for this build @@ -139,15 +143,6 @@ BAZEL_LOCAL_DEV_CACHE_CREDENTIALS_FILE="$HOME/.kibana-ci-bazel-remote-cache-loca export BAZEL_LOCAL_DEV_CACHE_CREDENTIALS_FILE retry 5 5 vault read -field=service_account_json secret/kibana-issues/dev/kibana-ci-bazel-remote-cache-local-dev > "$BAZEL_LOCAL_DEV_CACHE_CREDENTIALS_FILE" -# By default, all steps should set up these things to get a full environment before running -# It can be skipped for pipeline upload steps though, to make job start time a little faster -if [[ "${SKIP_CI_SETUP:-}" != "true" ]]; then - if [[ -d .buildkite/scripts && "${BUILDKITE_COMMAND:-}" != "buildkite-agent pipeline upload"* ]]; then - source .buildkite/scripts/common/env.sh - source .buildkite/scripts/common/setup_node.sh - fi -fi - PIPELINE_PRE_COMMAND=${PIPELINE_PRE_COMMAND:-".buildkite/scripts/lifecycle/pipelines/$BUILDKITE_PIPELINE_SLUG/pre_command.sh"} if [[ -f "$PIPELINE_PRE_COMMAND" ]]; then source "$PIPELINE_PRE_COMMAND" diff --git a/.buildkite/scripts/lifecycle/print_agent_links.js b/.buildkite/scripts/lifecycle/print_agent_links.ts similarity index 90% rename from .buildkite/scripts/lifecycle/print_agent_links.js rename to .buildkite/scripts/lifecycle/print_agent_links.ts index d720fcc82bbc..428ec3dc0aaf 100644 --- a/.buildkite/scripts/lifecycle/print_agent_links.js +++ b/.buildkite/scripts/lifecycle/print_agent_links.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const { BuildkiteClient } = require('kibana-buildkite-library'); +import { BuildkiteClient } from '#pipeline-utils'; (async () => { try { @@ -14,7 +14,9 @@ const { BuildkiteClient } = require('kibana-buildkite-library'); const build = await client.getCurrentBuild(); const job = build.jobs.find((j) => j.id === process.env.BUILDKITE_JOB_ID); - const startTime = job ? new Date(job.started_at) : new Date().getTime() - 60 * 60 * 1000; + const startTime = job + ? new Date(job.started_at) + : new Date(new Date().getTime() - 60 * 60 * 1000); const twoHours = new Date(startTime.getTime() + 2 * 60 * 60 * 1000); const METRICS_URL = [ diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.sh b/.buildkite/scripts/pipelines/pull_request/pipeline.sh index 02be2acdf858..442b5fea4c7b 100755 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.sh +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.sh @@ -2,4 +2,4 @@ set -euo pipefail -node .buildkite/scripts/pipelines/pull_request/pipeline.js +ts-node .buildkite/scripts/pipelines/pull_request/pipeline.ts diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.js b/.buildkite/scripts/pipelines/pull_request/pipeline.ts similarity index 81% rename from .buildkite/scripts/pipelines/pull_request/pipeline.js rename to .buildkite/scripts/pipelines/pull_request/pipeline.ts index f26349d1bdb2..0777eca88dca 100644 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.js +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.ts @@ -6,21 +6,27 @@ * Side Public License, v 1. */ -const execSync = require('child_process').execSync; -const fs = require('fs'); -const { areChangesSkippable, doAnyChangesMatch } = require('kibana-buildkite-library'); -const prConfigs = require('../../../pull_requests.json'); +import { execSync } from 'child_process'; +import fs from 'fs'; +import prConfigs from '../../../pull_requests.json'; +import { areChangesSkippable, doAnyChangesMatch } from '#pipeline-utils'; const prConfig = prConfigs.jobs.find((job) => job.pipelineSlug === 'kibana-pull-request'); +if (!prConfig) { + console.error(`'kibana-pull-request' pipeline not found in .buildkite/pull_requests.json`); + process.exit(1); +} + +const GITHUB_PR_LABELS = process.env.GITHUB_PR_LABELS ?? ''; const REQUIRED_PATHS = prConfig.always_require_ci_on_changed.map((r) => new RegExp(r, 'i')); const SKIPPABLE_PR_MATCHERS = prConfig.skip_ci_on_only_changed.map((r) => new RegExp(r, 'i')); -const getPipeline = (filename, removeSteps = true) => { +const getPipeline = (filename: string, removeSteps = true) => { const str = fs.readFileSync(filename).toString(); return removeSteps ? str.replace(/^steps:/, '') : str; }; -const uploadPipeline = (pipelineContent) => { +const uploadPipeline = (pipelineContent: string | object) => { const str = typeof pipelineContent === 'string' ? pipelineContent : JSON.stringify(pipelineContent); @@ -57,7 +63,7 @@ const uploadPipeline = (pipelineContent) => { /^x-pack\/plugins\/triggers_actions_ui\/public\/application\/context\/actions_connectors_context\.tsx/, /^x-pack\/test\/security_solution_cypress/, ])) || - process.env.GITHUB_PR_LABELS.includes('ci:all-cypress-suites') + GITHUB_PR_LABELS.includes('ci:all-cypress-suites') ) { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/security_solution.yml')); } @@ -71,35 +77,35 @@ const uploadPipeline = (pipelineContent) => { /^x-pack\/plugins\/rule_registry/, /^x-pack\/plugins\/task_manager/, ])) || - process.env.GITHUB_PR_LABELS.includes('ci:all-cypress-suites') + GITHUB_PR_LABELS.includes('ci:all-cypress-suites') ) { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/response_ops.yml')); } if ( (await doAnyChangesMatch([/^x-pack\/plugins\/cases/])) || - process.env.GITHUB_PR_LABELS.includes('ci:all-cypress-suites') + GITHUB_PR_LABELS.includes('ci:all-cypress-suites') ) { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/response_ops_cases.yml')); } if ( (await doAnyChangesMatch([/^x-pack\/plugins\/apm/])) || - process.env.GITHUB_PR_LABELS.includes('ci:all-cypress-suites') + GITHUB_PR_LABELS.includes('ci:all-cypress-suites') ) { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/apm_cypress.yml')); } if ( (await doAnyChangesMatch([/^x-pack\/plugins\/fleet/, /^x-pack\/test\/fleet_cypress/])) || - process.env.GITHUB_PR_LABELS.includes('ci:all-cypress-suites') + GITHUB_PR_LABELS.includes('ci:all-cypress-suites') ) { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/fleet_cypress.yml')); } if ( (await doAnyChangesMatch([/^x-pack\/plugins\/osquery/, /^x-pack\/test\/osquery_cypress/])) || - process.env.GITHUB_PR_LABELS.includes('ci:all-cypress-suites') + GITHUB_PR_LABELS.includes('ci:all-cypress-suites') ) { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/osquery_cypress.yml')); } @@ -116,7 +122,7 @@ const uploadPipeline = (pipelineContent) => { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/ux_plugin_e2e.yml')); } - if (process.env.GITHUB_PR_LABELS.includes('ci:deploy-cloud')) { + if (GITHUB_PR_LABELS.includes('ci:deploy-cloud')) { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/deploy_cloud.yml')); } diff --git a/.buildkite/scripts/steps/ci_stats_ready.sh b/.buildkite/scripts/steps/ci_stats_ready.sh index 92ea6a70fd77..bcb6f6adf03e 100755 --- a/.buildkite/scripts/steps/ci_stats_ready.sh +++ b/.buildkite/scripts/steps/ci_stats_ready.sh @@ -4,4 +4,4 @@ set -euo pipefail source .buildkite/scripts/common/util.sh -node .buildkite/scripts/lifecycle/ci_stats_ready.js +ts-node .buildkite/scripts/lifecycle/ci_stats_ready.ts diff --git a/.buildkite/scripts/steps/cloud/purge.sh b/.buildkite/scripts/steps/cloud/purge.sh index 265148c01340..a23d837f8329 100755 --- a/.buildkite/scripts/steps/cloud/purge.sh +++ b/.buildkite/scripts/steps/cloud/purge.sh @@ -2,4 +2,4 @@ set -euo pipefail -node .buildkite/scripts/steps/cloud/purge.js +ts-node .buildkite/scripts/steps/cloud/purge.ts diff --git a/.buildkite/scripts/steps/cloud/purge.js b/.buildkite/scripts/steps/cloud/purge.ts similarity index 89% rename from .buildkite/scripts/steps/cloud/purge.js rename to .buildkite/scripts/steps/cloud/purge.ts index 336f7daf736a..cbd058799d5b 100644 --- a/.buildkite/scripts/steps/cloud/purge.js +++ b/.buildkite/scripts/steps/cloud/purge.ts @@ -6,12 +6,14 @@ * Side Public License, v 1. */ -const { execSync } = require('child_process'); +import { execSync } from 'child_process'; const deploymentsListJson = execSync('ecctl deployment list --output json').toString(); const { deployments } = JSON.parse(deploymentsListJson); -const prDeployments = deployments.filter((deployment) => deployment.name.startsWith('kibana-pr-')); +const prDeployments = deployments.filter((deployment: any) => + deployment.name.startsWith('kibana-pr-') +); const deploymentsToPurge = []; @@ -29,7 +31,7 @@ for (const deployment of prDeployments) { if (pullRequest.state !== 'OPEN') { console.log(`Pull Request #${prNumber} is no longer open, will delete associated deployment`); deploymentsToPurge.push(deployment); - } else if (!pullRequest.labels.filter((label) => label.name === 'ci:deploy-cloud')) { + } else if (!pullRequest.labels.filter((label: any) => label.name === 'ci:deploy-cloud')) { console.log( `Pull Request #${prNumber} no longer has the ci:deploy-cloud label, will delete associated deployment` ); diff --git a/.buildkite/scripts/steps/code_coverage/clean_coverage_paths.js b/.buildkite/scripts/steps/code_coverage/clean_coverage_paths.ts similarity index 90% rename from .buildkite/scripts/steps/code_coverage/clean_coverage_paths.js rename to .buildkite/scripts/steps/code_coverage/clean_coverage_paths.ts index 77ac84a7bbd5..cf46cd6743af 100644 --- a/.buildkite/scripts/steps/code_coverage/clean_coverage_paths.js +++ b/.buildkite/scripts/steps/code_coverage/clean_coverage_paths.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const { readFileSync, writeFileSync } = require('fs'); +import { readFileSync, writeFileSync } from 'fs'; const file = process.argv[2]; const search = process.argv[3]; diff --git a/.buildkite/scripts/steps/code_coverage/util.sh b/.buildkite/scripts/steps/code_coverage/util.sh index cb48d6269585..163295522d3f 100755 --- a/.buildkite/scripts/steps/code_coverage/util.sh +++ b/.buildkite/scripts/steps/code_coverage/util.sh @@ -34,7 +34,7 @@ replacePaths() { local replace=$3 for x in $(find "$dirName" -maxdepth 1 -type f -name '*.json'); do - node .buildkite/scripts/steps/code_coverage/clean_coverage_paths.js \ + ts-node .buildkite/scripts/steps/code_coverage/clean_coverage_paths.ts \ "$x" \ "$search" \ "$replace" diff --git a/.buildkite/scripts/steps/es_snapshots/bucket_config.ts b/.buildkite/scripts/steps/es_snapshots/bucket_config.ts new file mode 100644 index 000000000000..85b77c37544a --- /dev/null +++ b/.buildkite/scripts/steps/es_snapshots/bucket_config.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const BASE_BUCKET_DAILY = 'kibana-ci-es-snapshots-daily'; +export const BASE_BUCKET_PERMANENT = 'kibana-ci-es-snapshots-permanent'; diff --git a/.buildkite/scripts/steps/es_snapshots/build.sh b/.buildkite/scripts/steps/es_snapshots/build.sh index 370ae275aa75..2e5e55c3f97b 100755 --- a/.buildkite/scripts/steps/es_snapshots/build.sh +++ b/.buildkite/scripts/steps/es_snapshots/build.sh @@ -111,7 +111,7 @@ cd "$destination" find ./* -exec bash -c "shasum -a 512 {} > {}.sha512" \; cd "$BUILDKITE_BUILD_CHECKOUT_PATH" -node "$(dirname "${0}")/create_manifest.js" "$destination" +ts-node "$(dirname "${0}")/create_manifest.ts" "$destination" ES_SNAPSHOT_MANIFEST="$(buildkite-agent meta-data get ES_SNAPSHOT_MANIFEST)" diff --git a/.buildkite/scripts/steps/es_snapshots/create_manifest.js b/.buildkite/scripts/steps/es_snapshots/create_manifest.ts similarity index 90% rename from .buildkite/scripts/steps/es_snapshots/create_manifest.js rename to .buildkite/scripts/steps/es_snapshots/create_manifest.ts index f71daed5c7f9..659a034d793b 100644 --- a/.buildkite/scripts/steps/es_snapshots/create_manifest.js +++ b/.buildkite/scripts/steps/es_snapshots/create_manifest.ts @@ -6,9 +6,19 @@ * Side Public License, v 1. */ -const fs = require('fs'); -const { execSync } = require('child_process'); -const { BASE_BUCKET_DAILY } = require('./bucket_config'); +import fs from 'fs'; +import { execSync } from 'child_process'; +import { BASE_BUCKET_DAILY } from './bucket_config'; + +interface ManifestEntry { + filename?: string; + checksum: string; + url: string; + version: string; + platform: string; + architecture: string; + license: string; +} (async () => { console.log('--- Create ES Snapshot Manifest'); @@ -40,7 +50,7 @@ const { BASE_BUCKET_DAILY } = require('./bucket_config'); try { const files = fs.readdirSync(destination); - const manifestEntries = files + const manifestEntries: ManifestEntry[] = files .filter((filename) => !filename.match(/.sha512$/)) .filter((filename) => !filename.match(/.json$/)) .map((filename) => { @@ -51,7 +61,7 @@ const { BASE_BUCKET_DAILY } = require('./bucket_config'); DESTINATION = DESTINATION || `${VERSION}/archives/${SNAPSHOT_ID}`; return { - filename: filename, + filename, checksum: filename + '.sha512', url: `https://storage.googleapis.com/${BASE_BUCKET_DAILY}/${DESTINATION}/${filename}`, version: parts[1], diff --git a/.buildkite/scripts/steps/es_snapshots/promote.sh b/.buildkite/scripts/steps/es_snapshots/promote.sh index 402f0964d21b..cf52f5e9ff65 100755 --- a/.buildkite/scripts/steps/es_snapshots/promote.sh +++ b/.buildkite/scripts/steps/es_snapshots/promote.sh @@ -11,9 +11,9 @@ cat << EOF | buildkite-agent annotate --style "info" $ES_SNAPSHOT_MANIFEST EOF -node "$(dirname "${0}")/promote_manifest.js" "$ES_SNAPSHOT_MANIFEST" +ts-node "$(dirname "${0}")/promote_manifest.ts" "$ES_SNAPSHOT_MANIFEST" if [[ "$BUILDKITE_BRANCH" == "main" ]]; then echo "--- Trigger agent packer cache pipeline" - node .buildkite/scripts/steps/trigger_pipeline.js kibana-agent-packer-cache main + ts-node .buildkite/scripts/steps/trigger_pipeline.ts kibana-agent-packer-cache main fi diff --git a/.buildkite/scripts/steps/es_snapshots/promote_manifest.js b/.buildkite/scripts/steps/es_snapshots/promote_manifest.ts similarity index 91% rename from .buildkite/scripts/steps/es_snapshots/promote_manifest.js rename to .buildkite/scripts/steps/es_snapshots/promote_manifest.ts index 5c352710c724..7b0f9b7a319a 100644 --- a/.buildkite/scripts/steps/es_snapshots/promote_manifest.js +++ b/.buildkite/scripts/steps/es_snapshots/promote_manifest.ts @@ -6,9 +6,9 @@ * Side Public License, v 1. */ -const fs = require('fs'); -const { execSync } = require('child_process'); -const { BASE_BUCKET_DAILY, BASE_BUCKET_PERMANENT } = require('./bucket_config'); +import fs from 'fs'; +import { execSync } from 'child_process'; +import { BASE_BUCKET_DAILY, BASE_BUCKET_PERMANENT } from './bucket_config'; (async () => { try { diff --git a/.buildkite/scripts/steps/storybooks/build_and_upload.sh b/.buildkite/scripts/steps/storybooks/build_and_upload.sh index 9f8343da18a7..e14b6896124d 100755 --- a/.buildkite/scripts/steps/storybooks/build_and_upload.sh +++ b/.buildkite/scripts/steps/storybooks/build_and_upload.sh @@ -4,4 +4,4 @@ set -euo pipefail .buildkite/scripts/bootstrap.sh -node .buildkite/scripts/steps/storybooks/build_and_upload.js +ts-node .buildkite/scripts/steps/storybooks/build_and_upload.ts diff --git a/.buildkite/scripts/steps/storybooks/build_and_upload.js b/.buildkite/scripts/steps/storybooks/build_and_upload.ts similarity index 89% rename from .buildkite/scripts/steps/storybooks/build_and_upload.js rename to .buildkite/scripts/steps/storybooks/build_and_upload.ts index ef790f79fff9..2609179380b9 100644 --- a/.buildkite/scripts/steps/storybooks/build_and_upload.js +++ b/.buildkite/scripts/steps/storybooks/build_and_upload.ts @@ -6,9 +6,9 @@ * Side Public License, v 1. */ -const execSync = require('child_process').execSync; -const fs = require('fs'); -const path = require('path'); +import { execSync } from 'child_process'; +import fs from 'fs'; +import path from 'path'; // TODO - how to generate this dynamically? const STORYBOOKS = [ @@ -47,14 +47,14 @@ const GITHUB_CONTEXT = 'Build and Publish Storybooks'; const STORYBOOK_DIRECTORY = process.env.BUILDKITE_PULL_REQUEST && process.env.BUILDKITE_PULL_REQUEST !== 'false' ? `pr-${process.env.BUILDKITE_PULL_REQUEST}` - : process.env.BUILDKITE_BRANCH.replace('/', '__'); + : (process.env.BUILDKITE_BRANCH ?? '').replace('/', '__'); const STORYBOOK_BUCKET = 'ci-artifacts.kibana.dev/storybooks'; const STORYBOOK_BUCKET_URL = `https://${STORYBOOK_BUCKET}/${STORYBOOK_DIRECTORY}`; const STORYBOOK_BASE_URL = `${STORYBOOK_BUCKET_URL}/${process.env.BUILDKITE_COMMIT}`; -const exec = (...args) => execSync(args.join(' '), { stdio: 'inherit' }); +const exec = (...args: string[]) => execSync(args.join(' '), { stdio: 'inherit' }); -const ghStatus = (state, description) => +const ghStatus = (state: string, description: string) => exec( `gh api "repos/elastic/kibana/statuses/${process.env.BUILDKITE_COMMIT}"`, `-f state=${state}`, @@ -84,8 +84,8 @@ const upload = () => { .toString() .trim() .split('\n') - .map((path) => path.replace('/', '')) - .filter((path) => path !== 'composite'); + .map((filePath) => filePath.replace('/', '')) + .filter((filePath) => filePath !== 'composite'); const listHtml = storybooks .map((storybook) => `
  • ${storybook}
  • `) diff --git a/.buildkite/scripts/steps/test/pick_test_group_run_order.sh b/.buildkite/scripts/steps/test/pick_test_group_run_order.sh index 56308b73c6fd..b28fd226c2fa 100644 --- a/.buildkite/scripts/steps/test/pick_test_group_run_order.sh +++ b/.buildkite/scripts/steps/test/pick_test_group_run_order.sh @@ -5,4 +5,4 @@ set -euo pipefail source .buildkite/scripts/common/util.sh echo '--- Pick Test Group Run Order' -node "$(dirname "${0}")/pick_test_group_run_order.js" +ts-node "$(dirname "${0}")/pick_test_group_run_order.ts" diff --git a/.buildkite/scripts/steps/test/pick_test_group_run_order.js b/.buildkite/scripts/steps/test/pick_test_group_run_order.ts similarity index 92% rename from .buildkite/scripts/steps/test/pick_test_group_run_order.js rename to .buildkite/scripts/steps/test/pick_test_group_run_order.ts index a5fa499419ab..0cd7c4508fae 100644 --- a/.buildkite/scripts/steps/test/pick_test_group_run_order.js +++ b/.buildkite/scripts/steps/test/pick_test_group_run_order.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const { CiStats } = require('kibana-buildkite-library'); +import { CiStats } from '#pipeline-utils'; (async () => { try { diff --git a/.buildkite/scripts/steps/trigger_pipeline.js b/.buildkite/scripts/steps/trigger_pipeline.ts similarity index 94% rename from .buildkite/scripts/steps/trigger_pipeline.js rename to .buildkite/scripts/steps/trigger_pipeline.ts index c52734f2be1a..f42a5b084353 100644 --- a/.buildkite/scripts/steps/trigger_pipeline.js +++ b/.buildkite/scripts/steps/trigger_pipeline.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const { BuildkiteClient } = require('kibana-buildkite-library'); +import { BuildkiteClient } from '#pipeline-utils'; const pipelineSlug = process.argv[2]; const branch = process.argv[3] || 'main'; diff --git a/.buildkite/scripts/steps/webpack_bundle_analyzer/build_and_upload.sh b/.buildkite/scripts/steps/webpack_bundle_analyzer/build_and_upload.sh index 8a978db6825d..4374cce2281f 100755 --- a/.buildkite/scripts/steps/webpack_bundle_analyzer/build_and_upload.sh +++ b/.buildkite/scripts/steps/webpack_bundle_analyzer/build_and_upload.sh @@ -12,4 +12,4 @@ find . -path "*target/public/*" -name "stats.json" | while read line; do ./node_modules/.bin/webpack-bundle-analyzer $line --report "built_assets/webpack_bundle_analyzer/$PLUGIN.html" --mode static --no-open done -node .buildkite/scripts/steps/webpack_bundle_analyzer/upload.js +ts-node .buildkite/scripts/steps/webpack_bundle_analyzer/upload.ts diff --git a/.buildkite/scripts/steps/webpack_bundle_analyzer/upload.js b/.buildkite/scripts/steps/webpack_bundle_analyzer/upload.ts similarity index 90% rename from .buildkite/scripts/steps/webpack_bundle_analyzer/upload.js rename to .buildkite/scripts/steps/webpack_bundle_analyzer/upload.ts index 6d61608973cb..73c24a82be6d 100644 --- a/.buildkite/scripts/steps/webpack_bundle_analyzer/upload.js +++ b/.buildkite/scripts/steps/webpack_bundle_analyzer/upload.ts @@ -6,23 +6,23 @@ * Side Public License, v 1. */ -const execSync = require('child_process').execSync; -const fs = require('fs'); -const path = require('path'); +import { execSync } from 'child_process'; +import fs from 'fs'; +import path from 'path'; const GITHUB_CONTEXT = 'Build and Publish Webpack bundle analyzer reports'; const WEBPACK_REPORTS = process.env.BUILDKITE_PULL_REQUEST && process.env.BUILDKITE_PULL_REQUEST !== 'false' ? `pr-${process.env.BUILDKITE_PULL_REQUEST}` - : process.env.BUILDKITE_BRANCH.replace('/', '__'); + : (process.env.BUILDKITE_BRANCH ?? '').replace('/', '__'); const WEBPACK_REPORTS_BUCKET = 'ci-artifacts.kibana.dev/webpack_bundle_analyzer'; const WEBPACK_REPORTS_BUCKET_URL = `https://${WEBPACK_REPORTS_BUCKET}/${WEBPACK_REPORTS}`; const WEBPACK_REPORTS_BASE_URL = `${WEBPACK_REPORTS_BUCKET_URL}/${process.env.BUILDKITE_COMMIT}`; -const exec = (...args) => execSync(args.join(' '), { stdio: 'inherit' }); +const exec = (...args: string[]) => execSync(args.join(' '), { stdio: 'inherit' }); -const ghStatus = (state, description) => +const ghStatus = (state: string, description: string) => exec( `gh api "repos/elastic/kibana/statuses/${process.env.BUILDKITE_COMMIT}"`, `-f state=${state}`, diff --git a/.buildkite/tsconfig.json b/.buildkite/tsconfig.json new file mode 100644 index 000000000000..f40776430f39 --- /dev/null +++ b/.buildkite/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "incremental": false, + "composite": false, + "emitDeclarationOnly": true, + "outDir": "./target/types", + "types": ["node", "mocha"], + "paths": { + "#pipeline-utils": [".buildkite/pipeline-utils/index.ts"], + "#pipeline-utils/*": [".buildkite/pipeline-utils/*"] + } + }, + "include": [ + "pipeline-utils/**/*", + "pipelines/**/*", + "scripts/**/*", + "pipelines/flaky_tests/groups.json", + "pull_requests.json" + ] +} diff --git a/.buildkite/tsconfig.test.json b/.buildkite/tsconfig.test.json new file mode 100644 index 000000000000..1c95372567c6 --- /dev/null +++ b/.buildkite/tsconfig.test.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "strict": true, + "module": "commonjs", + "moduleResolution": "node", + "resolveJsonModule": true, + "noEmit": true, + "lib": ["es2020"] + }, + "include": ["src/**/*.test.ts"] +} diff --git a/.eslintrc.js b/.eslintrc.js index 36927ac4219a..58345b3faaba 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1740,5 +1740,16 @@ module.exports = { quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: false }], }, }, + + /** + * Code inside .buildkite runs separately from everything else in CI, before bootstrap, with ts-node. It needs a few tweaks because of this. + */ + { + files: '.buildkite/**/*.{js,ts}', + rules: { + 'no-console': 'off', + '@kbn/imports/no_unresolvable_imports': 'off', + }, + }, ], }; diff --git a/src/dev/typescript/projects.ts b/src/dev/typescript/projects.ts index ac5ed7a6c265..520b96d261fd 100644 --- a/src/dev/typescript/projects.ts +++ b/src/dev/typescript/projects.ts @@ -31,6 +31,7 @@ export const PROJECTS = [ createProject('test/tsconfig.json', { name: 'kibana/test' }), createProject('x-pack/test/tsconfig.json', { name: 'x-pack/test' }), createProject('src/core/tsconfig.json'), + createProject('.buildkite/tsconfig.json'), createProject('x-pack/plugins/drilldowns/url_drilldown/tsconfig.json', { name: 'security_solution/cypress',