diff --git a/.circleci/config.yml b/.circleci/config.yml
index 224a004ba..e47a54191 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -71,7 +71,7 @@ commands:
steps:
- run:
name: Copy JUnit test reports to central folder for upload
- command: node .circleci/copy-junit-reports.js
+ command: yarn -s ng-dev ci gather-test-results
when: always
- store_test_results:
path: ./test-results
diff --git a/.circleci/copy-junit-reports.js b/.circleci/copy-junit-reports.js
deleted file mode 100644
index cbee23827..000000000
--- a/.circleci/copy-junit-reports.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * @license
- * Copyright Google LLC All Rights Reserved.
- *
- * Use of this source code is governed by an MIT-style license that can be
- * found in the LICENSE file at https://angular.io/license
- */
-
-const {loadSync} = require('protobufjs');
-const {execSync} = require('child_process');
-const {join, dirname, extname} = require('path');
-const {
- mkdirSync,
- rmSync,
- readFileSync,
- statSync,
- readdirSync,
- copyFileSync,
- writeFileSync,
-} = require('fs');
-
-const proto = loadSync(join(__dirname, '../tools/protos/test_status.proto'));
-const TestResultData = proto.lookupType('blaze.TestResultData');
-
-/**
- * A JUnit test report to always include signaling to CircleCI that tests were requested.
- *
- * `testsuite` and `testcase` elements are required for CircleCI to properly parse the report.
- */
-const baseTestReport = `
-
-
-
-
-
-
-`.trim();
-
-/**
- * Discover all test results, which @bazel/jasmine stores as `test.xml` files, in the directory and
- * return back the list of absolute file paths.
- */
-const findTestResultsInDir = function (dirPath, files) {
- for (const file of readdirSync(dirPath)) {
- const filePath = join(dirPath, file);
- if (statSync(filePath).isDirectory()) {
- files = findTestResultsInDir(filePath, files);
- } else {
- // Only the test result files, which are XML with the .xml extension, should be discovered.
- if (extname(file) === '.xml') {
- files.push([filePath, join(dirname(filePath), 'test.cache_status')]);
- }
- }
- }
- return files;
-};
-
-/** Absolute path to the bazel instance's testlog directory. */
-const testLogPath = execSync('yarn -s bazel info bazel-testlogs', {encoding: 'utf8'}).trim();
-/** List of test result files. */
-const testResultPaths = findTestResultsInDir(testLogPath, []);
-/**
- * Absolute path to a directory to contain the JUnit test result files.
- *
- * Note: The directory created needs to contain a subdirectory which contains the test results in
- * order for CircleCI to properly discover the test results.
- */
-const destDirPath = join(__dirname, '../test-results/jasmine');
-
-// Ensure that an empty directory exists to contain the test results reports for upload.
-rmSync(destDirPath, {recursive: true, force: true});
-mkdirSync(destDirPath, {recursive: true});
-
-// By always uploading at least one result file, CircleCI will understand that a tests actions were
-// called for in the bazel test run, even if not tests were actually executed due to cache hits. By
-// always making sure to upload at least one test result report, CircleCI always include the
-// workflow in its aggregated data and provide better metrics about the number of executed tests per
-// run.
-writeFileSync(join(destDirPath, `results.xml`), baseTestReport);
-console.debug('Added base test report to test-results directory.');
-
-/** Total number of files copied, also used as a index to number copied files. */
-let copiedFileCount = 0;
-// Copy each of the test result files to the central test result directory which CircleCI discovers
-// test results in.
-testResultPaths.forEach(([xmlFilePath, cacheStatusFilePath]) => {
- const shortFilePath = xmlFilePath.substr(testLogPath.length + 1);
- const testResultData = TestResultData.decode(readFileSync(cacheStatusFilePath));
-
- if (testResultData.remotelyCached && testResultData.testPassed) {
- console.debug(`Skipping copy of ${shortFilePath} as it was a passing remote cache hit`);
- } else {
- const destFilePath = join(destDirPath, `results-${copiedFileCount++}.xml`);
- copyFileSync(xmlFilePath, destFilePath);
- console.debug(`Copying ${shortFilePath}`);
- }
-});
-
-console.info(`Copied ${copiedFileCount} test result file(s) for upload.`);
diff --git a/.ng-dev/commit-message.ts b/.ng-dev/commit-message.ts
index c6a80aa8e..2292e6826 100644
--- a/.ng-dev/commit-message.ts
+++ b/.ng-dev/commit-message.ts
@@ -9,7 +9,13 @@ export const commitMessage: CommitMessageConfig = {
maxLineLength: Infinity,
minBodyLength: 0,
scopes: [
- ...buildScopesFor('bazel', ['api-golden', 'benchmark', 'browsers', 'remote-execution']),
+ ...buildScopesFor('bazel', [
+ 'api-golden',
+ 'benchmark',
+ 'browsers',
+ 'protos',
+ 'remote-execution',
+ ]),
...buildScopesFor('github-actions', [
'breaking-changes-label',
'feature-request',
@@ -18,6 +24,7 @@ export const commitMessage: CommitMessageConfig = {
'rerun-circleci',
]),
...buildScopesFor('ng-dev', [
+ 'ci',
'caretaker',
'commit-message',
'format',
diff --git a/.prettierignore b/.prettierignore
index 05749f54e..c3559f194 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,3 +1,5 @@
+bazel/protos/*.d.ts
+bazel/protos/*.js
github-actions/feature-request/post.js
github-actions/feature-request/main.js
github-actions/lock-closed/main.js
diff --git a/WORKSPACE b/WORKSPACE
index 3fffc853d..642c274dd 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,7 @@ workspace(
managed_directories = {"@npm": ["node_modules"]},
)
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
# Fetch rules_nodejs so we can install our npm dependencies
http_archive(
@@ -46,3 +46,9 @@ register_toolchains(
"//tools/git-toolchain:git_macos_arm64_toolchain",
"//tools/git-toolchain:git_windows_toolchain",
)
+
+http_file(
+ name = "bazel_test_status_proto",
+ sha256 = "61ce1dc62fdcfd6d68624a403e0f04c5fd5136d933b681467aad1ad2d00dbb03",
+ urls = ["https://raw.githubusercontent.com/bazelbuild/bazel/4.2.1/src/main/protobuf/test_status.proto"],
+)
diff --git a/bazel/protos/BUILD.bazel b/bazel/protos/BUILD.bazel
new file mode 100644
index 000000000..5244df397
--- /dev/null
+++ b/bazel/protos/BUILD.bazel
@@ -0,0 +1,6 @@
+load("//tools:generate_ts_proto_module.bzl", "generate_ts_proto_module")
+
+generate_ts_proto_module(
+ name = "test_status",
+ protofile = "@bazel_test_status_proto//file",
+)
diff --git a/bazel/protos/test_status_pb.d.ts b/bazel/protos/test_status_pb.d.ts
new file mode 100644
index 000000000..735fb9e2a
--- /dev/null
+++ b/bazel/protos/test_status_pb.d.ts
@@ -0,0 +1,355 @@
+import * as $protobuf from "protobufjs";
+/** Namespace blaze. */
+export namespace blaze {
+
+ /** FailedTestCasesStatus enum. */
+ enum FailedTestCasesStatus {
+ FULL = 1,
+ PARTIAL = 2,
+ NOT_AVAILABLE = 3,
+ EMPTY = 4
+ }
+
+ /** BlazeTestStatus enum. */
+ enum BlazeTestStatus {
+ NO_STATUS = 0,
+ PASSED = 1,
+ FLAKY = 2,
+ TIMEOUT = 3,
+ FAILED = 4,
+ INCOMPLETE = 5,
+ REMOTE_FAILURE = 6,
+ FAILED_TO_BUILD = 7,
+ BLAZE_HALTED_BEFORE_TESTING = 8
+ }
+
+ /** Properties of a TestCase. */
+ interface ITestCase {
+
+ /** TestCase child */
+ child?: (blaze.ITestCase[]|null);
+
+ /** TestCase name */
+ name?: (string|null);
+
+ /** TestCase className */
+ className?: (string|null);
+
+ /** TestCase runDurationMillis */
+ runDurationMillis?: (number|Long|null);
+
+ /** TestCase result */
+ result?: (string|null);
+
+ /** TestCase type */
+ type?: (blaze.TestCase.Type|null);
+
+ /** TestCase status */
+ status?: (blaze.TestCase.Status|null);
+
+ /** TestCase run */
+ run?: (boolean|null);
+ }
+
+ /** Represents a TestCase. */
+ class TestCase implements ITestCase {
+
+ /**
+ * Constructs a new TestCase.
+ * @param [properties] Properties to set
+ */
+ constructor(properties?: blaze.ITestCase);
+
+ /** TestCase child. */
+ public child: blaze.ITestCase[];
+
+ /** TestCase name. */
+ public name: string;
+
+ /** TestCase className. */
+ public className: string;
+
+ /** TestCase runDurationMillis. */
+ public runDurationMillis: (number|Long);
+
+ /** TestCase result. */
+ public result: string;
+
+ /** TestCase type. */
+ public type: blaze.TestCase.Type;
+
+ /** TestCase status. */
+ public status: blaze.TestCase.Status;
+
+ /** TestCase run. */
+ public run: boolean;
+
+ /**
+ * Creates a new TestCase instance using the specified properties.
+ * @param [properties] Properties to set
+ * @returns TestCase instance
+ */
+ public static create(properties?: blaze.ITestCase): blaze.TestCase;
+
+ /**
+ * Encodes the specified TestCase message. Does not implicitly {@link blaze.TestCase.verify|verify} messages.
+ * @param message TestCase message or plain object to encode
+ * @param [writer] Writer to encode to
+ * @returns Writer
+ */
+ public static encode(message: blaze.ITestCase, writer?: $protobuf.Writer): $protobuf.Writer;
+
+ /**
+ * Encodes the specified TestCase message, length delimited. Does not implicitly {@link blaze.TestCase.verify|verify} messages.
+ * @param message TestCase message or plain object to encode
+ * @param [writer] Writer to encode to
+ * @returns Writer
+ */
+ public static encodeDelimited(message: blaze.ITestCase, writer?: $protobuf.Writer): $protobuf.Writer;
+
+ /**
+ * Decodes a TestCase message from the specified reader or buffer.
+ * @param reader Reader or buffer to decode from
+ * @param [length] Message length if known beforehand
+ * @returns TestCase
+ * @throws {Error} If the payload is not a reader or valid buffer
+ * @throws {$protobuf.util.ProtocolError} If required fields are missing
+ */
+ public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): blaze.TestCase;
+
+ /**
+ * Decodes a TestCase message from the specified reader or buffer, length delimited.
+ * @param reader Reader or buffer to decode from
+ * @returns TestCase
+ * @throws {Error} If the payload is not a reader or valid buffer
+ * @throws {$protobuf.util.ProtocolError} If required fields are missing
+ */
+ public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): blaze.TestCase;
+
+ /**
+ * Verifies a TestCase message.
+ * @param message Plain object to verify
+ * @returns `null` if valid, otherwise the reason why it is not
+ */
+ public static verify(message: { [k: string]: any }): (string|null);
+
+ /**
+ * Creates a TestCase message from a plain object. Also converts values to their respective internal types.
+ * @param object Plain object
+ * @returns TestCase
+ */
+ public static fromObject(object: { [k: string]: any }): blaze.TestCase;
+
+ /**
+ * Creates a plain object from a TestCase message. Also converts values to other types if specified.
+ * @param message TestCase
+ * @param [options] Conversion options
+ * @returns Plain object
+ */
+ public static toObject(message: blaze.TestCase, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+ /**
+ * Converts this TestCase to JSON.
+ * @returns JSON object
+ */
+ public toJSON(): { [k: string]: any };
+ }
+
+ namespace TestCase {
+
+ /** Type enum. */
+ enum Type {
+ TEST_CASE = 0,
+ TEST_SUITE = 1,
+ TEST_DECORATOR = 2,
+ UNKNOWN = 3
+ }
+
+ /** Status enum. */
+ enum Status {
+ PASSED = 0,
+ FAILED = 1,
+ ERROR = 2
+ }
+ }
+
+ /** Properties of a TestResultData. */
+ interface ITestResultData {
+
+ /** TestResultData cachable */
+ cachable?: (boolean|null);
+
+ /** TestResultData testPassed */
+ testPassed?: (boolean|null);
+
+ /** TestResultData status */
+ status?: (blaze.BlazeTestStatus|null);
+
+ /** TestResultData statusDetails */
+ statusDetails?: (string|null);
+
+ /** TestResultData failedLogs */
+ failedLogs?: (string[]|null);
+
+ /** TestResultData warning */
+ warning?: (string[]|null);
+
+ /** TestResultData hasCoverage */
+ hasCoverage?: (boolean|null);
+
+ /** TestResultData remotelyCached */
+ remotelyCached?: (boolean|null);
+
+ /** TestResultData isRemoteStrategy */
+ isRemoteStrategy?: (boolean|null);
+
+ /** TestResultData testTimes */
+ testTimes?: ((number|Long)[]|null);
+
+ /** TestResultData passedLog */
+ passedLog?: (string|null);
+
+ /** TestResultData testProcessTimes */
+ testProcessTimes?: ((number|Long)[]|null);
+
+ /** TestResultData runDurationMillis */
+ runDurationMillis?: (number|Long|null);
+
+ /** TestResultData startTimeMillisEpoch */
+ startTimeMillisEpoch?: (number|Long|null);
+
+ /** TestResultData testCase */
+ testCase?: (blaze.ITestCase|null);
+
+ /** TestResultData failedStatus */
+ failedStatus?: (blaze.FailedTestCasesStatus|null);
+ }
+
+ /** Represents a TestResultData. */
+ class TestResultData implements ITestResultData {
+
+ /**
+ * Constructs a new TestResultData.
+ * @param [properties] Properties to set
+ */
+ constructor(properties?: blaze.ITestResultData);
+
+ /** TestResultData cachable. */
+ public cachable: boolean;
+
+ /** TestResultData testPassed. */
+ public testPassed: boolean;
+
+ /** TestResultData status. */
+ public status: blaze.BlazeTestStatus;
+
+ /** TestResultData statusDetails. */
+ public statusDetails: string;
+
+ /** TestResultData failedLogs. */
+ public failedLogs: string[];
+
+ /** TestResultData warning. */
+ public warning: string[];
+
+ /** TestResultData hasCoverage. */
+ public hasCoverage: boolean;
+
+ /** TestResultData remotelyCached. */
+ public remotelyCached: boolean;
+
+ /** TestResultData isRemoteStrategy. */
+ public isRemoteStrategy: boolean;
+
+ /** TestResultData testTimes. */
+ public testTimes: (number|Long)[];
+
+ /** TestResultData passedLog. */
+ public passedLog: string;
+
+ /** TestResultData testProcessTimes. */
+ public testProcessTimes: (number|Long)[];
+
+ /** TestResultData runDurationMillis. */
+ public runDurationMillis: (number|Long);
+
+ /** TestResultData startTimeMillisEpoch. */
+ public startTimeMillisEpoch: (number|Long);
+
+ /** TestResultData testCase. */
+ public testCase?: (blaze.ITestCase|null);
+
+ /** TestResultData failedStatus. */
+ public failedStatus: blaze.FailedTestCasesStatus;
+
+ /**
+ * Creates a new TestResultData instance using the specified properties.
+ * @param [properties] Properties to set
+ * @returns TestResultData instance
+ */
+ public static create(properties?: blaze.ITestResultData): blaze.TestResultData;
+
+ /**
+ * Encodes the specified TestResultData message. Does not implicitly {@link blaze.TestResultData.verify|verify} messages.
+ * @param message TestResultData message or plain object to encode
+ * @param [writer] Writer to encode to
+ * @returns Writer
+ */
+ public static encode(message: blaze.ITestResultData, writer?: $protobuf.Writer): $protobuf.Writer;
+
+ /**
+ * Encodes the specified TestResultData message, length delimited. Does not implicitly {@link blaze.TestResultData.verify|verify} messages.
+ * @param message TestResultData message or plain object to encode
+ * @param [writer] Writer to encode to
+ * @returns Writer
+ */
+ public static encodeDelimited(message: blaze.ITestResultData, writer?: $protobuf.Writer): $protobuf.Writer;
+
+ /**
+ * Decodes a TestResultData message from the specified reader or buffer.
+ * @param reader Reader or buffer to decode from
+ * @param [length] Message length if known beforehand
+ * @returns TestResultData
+ * @throws {Error} If the payload is not a reader or valid buffer
+ * @throws {$protobuf.util.ProtocolError} If required fields are missing
+ */
+ public static decode(reader: ($protobuf.Reader|Uint8Array), length?: number): blaze.TestResultData;
+
+ /**
+ * Decodes a TestResultData message from the specified reader or buffer, length delimited.
+ * @param reader Reader or buffer to decode from
+ * @returns TestResultData
+ * @throws {Error} If the payload is not a reader or valid buffer
+ * @throws {$protobuf.util.ProtocolError} If required fields are missing
+ */
+ public static decodeDelimited(reader: ($protobuf.Reader|Uint8Array)): blaze.TestResultData;
+
+ /**
+ * Verifies a TestResultData message.
+ * @param message Plain object to verify
+ * @returns `null` if valid, otherwise the reason why it is not
+ */
+ public static verify(message: { [k: string]: any }): (string|null);
+
+ /**
+ * Creates a TestResultData message from a plain object. Also converts values to their respective internal types.
+ * @param object Plain object
+ * @returns TestResultData
+ */
+ public static fromObject(object: { [k: string]: any }): blaze.TestResultData;
+
+ /**
+ * Creates a plain object from a TestResultData message. Also converts values to other types if specified.
+ * @param message TestResultData
+ * @param [options] Conversion options
+ * @returns Plain object
+ */
+ public static toObject(message: blaze.TestResultData, options?: $protobuf.IConversionOptions): { [k: string]: any };
+
+ /**
+ * Converts this TestResultData to JSON.
+ * @returns JSON object
+ */
+ public toJSON(): { [k: string]: any };
+ }
+}
diff --git a/bazel/protos/test_status_pb.js b/bazel/protos/test_status_pb.js
new file mode 100644
index 000000000..d168e3a7a
--- /dev/null
+++ b/bazel/protos/test_status_pb.js
@@ -0,0 +1,1241 @@
+/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/
+"use strict";
+
+var $protobuf = require("protobufjs/minimal");
+
+// Common aliases
+var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
+
+// Exported root namespace
+var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
+
+$root.blaze = (function() {
+
+ /**
+ * Namespace blaze.
+ * @exports blaze
+ * @namespace
+ */
+ var blaze = {};
+
+ /**
+ * FailedTestCasesStatus enum.
+ * @name blaze.FailedTestCasesStatus
+ * @enum {number}
+ * @property {number} FULL=1 Information about every test case is available.
+ * @property {number} PARTIAL=2 Information about some test cases may be missing.
+ * @property {number} NOT_AVAILABLE=3 No information about individual test cases.
+ * @property {number} EMPTY=4 This is an empty object still without data.
+ */
+ blaze.FailedTestCasesStatus = (function() {
+ var valuesById = {}, values = Object.create(valuesById);
+ values[valuesById[1] = "FULL"] = 1;
+ values[valuesById[2] = "PARTIAL"] = 2;
+ values[valuesById[3] = "NOT_AVAILABLE"] = 3;
+ values[valuesById[4] = "EMPTY"] = 4;
+ return values;
+ })();
+
+ /**
+ * BlazeTestStatus enum.
+ * @name blaze.BlazeTestStatus
+ * @enum {number}
+ * @property {number} NO_STATUS=0 NO_STATUS value
+ * @property {number} PASSED=1 PASSED value
+ * @property {number} FLAKY=2 FLAKY value
+ * @property {number} TIMEOUT=3 TIMEOUT value
+ * @property {number} FAILED=4 FAILED value
+ * @property {number} INCOMPLETE=5 INCOMPLETE value
+ * @property {number} REMOTE_FAILURE=6 REMOTE_FAILURE value
+ * @property {number} FAILED_TO_BUILD=7 FAILED_TO_BUILD value
+ * @property {number} BLAZE_HALTED_BEFORE_TESTING=8 BLAZE_HALTED_BEFORE_TESTING value
+ */
+ blaze.BlazeTestStatus = (function() {
+ var valuesById = {}, values = Object.create(valuesById);
+ values[valuesById[0] = "NO_STATUS"] = 0;
+ values[valuesById[1] = "PASSED"] = 1;
+ values[valuesById[2] = "FLAKY"] = 2;
+ values[valuesById[3] = "TIMEOUT"] = 3;
+ values[valuesById[4] = "FAILED"] = 4;
+ values[valuesById[5] = "INCOMPLETE"] = 5;
+ values[valuesById[6] = "REMOTE_FAILURE"] = 6;
+ values[valuesById[7] = "FAILED_TO_BUILD"] = 7;
+ values[valuesById[8] = "BLAZE_HALTED_BEFORE_TESTING"] = 8;
+ return values;
+ })();
+
+ blaze.TestCase = (function() {
+
+ /**
+ * Properties of a TestCase.
+ * @memberof blaze
+ * @interface ITestCase
+ * @property {Array.|null} [child] TestCase child
+ * @property {string|null} [name] TestCase name
+ * @property {string|null} [className] TestCase className
+ * @property {number|Long|null} [runDurationMillis] TestCase runDurationMillis
+ * @property {string|null} [result] TestCase result
+ * @property {blaze.TestCase.Type|null} [type] TestCase type
+ * @property {blaze.TestCase.Status|null} [status] TestCase status
+ * @property {boolean|null} [run] TestCase run
+ */
+
+ /**
+ * Constructs a new TestCase.
+ * @memberof blaze
+ * @classdesc Represents a TestCase.
+ * @implements ITestCase
+ * @constructor
+ * @param {blaze.ITestCase=} [properties] Properties to set
+ */
+ function TestCase(properties) {
+ this.child = [];
+ if (properties)
+ for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+ if (properties[keys[i]] != null)
+ this[keys[i]] = properties[keys[i]];
+ }
+
+ /**
+ * TestCase child.
+ * @member {Array.} child
+ * @memberof blaze.TestCase
+ * @instance
+ */
+ TestCase.prototype.child = $util.emptyArray;
+
+ /**
+ * TestCase name.
+ * @member {string} name
+ * @memberof blaze.TestCase
+ * @instance
+ */
+ TestCase.prototype.name = "";
+
+ /**
+ * TestCase className.
+ * @member {string} className
+ * @memberof blaze.TestCase
+ * @instance
+ */
+ TestCase.prototype.className = "";
+
+ /**
+ * TestCase runDurationMillis.
+ * @member {number|Long} runDurationMillis
+ * @memberof blaze.TestCase
+ * @instance
+ */
+ TestCase.prototype.runDurationMillis = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
+
+ /**
+ * TestCase result.
+ * @member {string} result
+ * @memberof blaze.TestCase
+ * @instance
+ */
+ TestCase.prototype.result = "";
+
+ /**
+ * TestCase type.
+ * @member {blaze.TestCase.Type} type
+ * @memberof blaze.TestCase
+ * @instance
+ */
+ TestCase.prototype.type = 0;
+
+ /**
+ * TestCase status.
+ * @member {blaze.TestCase.Status} status
+ * @memberof blaze.TestCase
+ * @instance
+ */
+ TestCase.prototype.status = 0;
+
+ /**
+ * TestCase run.
+ * @member {boolean} run
+ * @memberof blaze.TestCase
+ * @instance
+ */
+ TestCase.prototype.run = true;
+
+ /**
+ * Creates a new TestCase instance using the specified properties.
+ * @function create
+ * @memberof blaze.TestCase
+ * @static
+ * @param {blaze.ITestCase=} [properties] Properties to set
+ * @returns {blaze.TestCase} TestCase instance
+ */
+ TestCase.create = function create(properties) {
+ return new TestCase(properties);
+ };
+
+ /**
+ * Encodes the specified TestCase message. Does not implicitly {@link blaze.TestCase.verify|verify} messages.
+ * @function encode
+ * @memberof blaze.TestCase
+ * @static
+ * @param {blaze.ITestCase} message TestCase message or plain object to encode
+ * @param {$protobuf.Writer} [writer] Writer to encode to
+ * @returns {$protobuf.Writer} Writer
+ */
+ TestCase.encode = function encode(message, writer) {
+ if (!writer)
+ writer = $Writer.create();
+ if (message.child != null && message.child.length)
+ for (var i = 0; i < message.child.length; ++i)
+ $root.blaze.TestCase.encode(message.child[i], writer.uint32(/* id 1, wireType 2 =*/10).fork()).ldelim();
+ if (message.name != null && Object.hasOwnProperty.call(message, "name"))
+ writer.uint32(/* id 2, wireType 2 =*/18).string(message.name);
+ if (message.className != null && Object.hasOwnProperty.call(message, "className"))
+ writer.uint32(/* id 3, wireType 2 =*/26).string(message.className);
+ if (message.runDurationMillis != null && Object.hasOwnProperty.call(message, "runDurationMillis"))
+ writer.uint32(/* id 4, wireType 0 =*/32).int64(message.runDurationMillis);
+ if (message.result != null && Object.hasOwnProperty.call(message, "result"))
+ writer.uint32(/* id 5, wireType 2 =*/42).string(message.result);
+ if (message.type != null && Object.hasOwnProperty.call(message, "type"))
+ writer.uint32(/* id 6, wireType 0 =*/48).int32(message.type);
+ if (message.status != null && Object.hasOwnProperty.call(message, "status"))
+ writer.uint32(/* id 7, wireType 0 =*/56).int32(message.status);
+ if (message.run != null && Object.hasOwnProperty.call(message, "run"))
+ writer.uint32(/* id 8, wireType 0 =*/64).bool(message.run);
+ return writer;
+ };
+
+ /**
+ * Encodes the specified TestCase message, length delimited. Does not implicitly {@link blaze.TestCase.verify|verify} messages.
+ * @function encodeDelimited
+ * @memberof blaze.TestCase
+ * @static
+ * @param {blaze.ITestCase} message TestCase message or plain object to encode
+ * @param {$protobuf.Writer} [writer] Writer to encode to
+ * @returns {$protobuf.Writer} Writer
+ */
+ TestCase.encodeDelimited = function encodeDelimited(message, writer) {
+ return this.encode(message, writer).ldelim();
+ };
+
+ /**
+ * Decodes a TestCase message from the specified reader or buffer.
+ * @function decode
+ * @memberof blaze.TestCase
+ * @static
+ * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+ * @param {number} [length] Message length if known beforehand
+ * @returns {blaze.TestCase} TestCase
+ * @throws {Error} If the payload is not a reader or valid buffer
+ * @throws {$protobuf.util.ProtocolError} If required fields are missing
+ */
+ TestCase.decode = function decode(reader, length) {
+ if (!(reader instanceof $Reader))
+ reader = $Reader.create(reader);
+ var end = length === undefined ? reader.len : reader.pos + length, message = new $root.blaze.TestCase();
+ while (reader.pos < end) {
+ var tag = reader.uint32();
+ switch (tag >>> 3) {
+ case 1:
+ if (!(message.child && message.child.length))
+ message.child = [];
+ message.child.push($root.blaze.TestCase.decode(reader, reader.uint32()));
+ break;
+ case 2:
+ message.name = reader.string();
+ break;
+ case 3:
+ message.className = reader.string();
+ break;
+ case 4:
+ message.runDurationMillis = reader.int64();
+ break;
+ case 5:
+ message.result = reader.string();
+ break;
+ case 6:
+ message.type = reader.int32();
+ break;
+ case 7:
+ message.status = reader.int32();
+ break;
+ case 8:
+ message.run = reader.bool();
+ break;
+ default:
+ reader.skipType(tag & 7);
+ break;
+ }
+ }
+ return message;
+ };
+
+ /**
+ * Decodes a TestCase message from the specified reader or buffer, length delimited.
+ * @function decodeDelimited
+ * @memberof blaze.TestCase
+ * @static
+ * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+ * @returns {blaze.TestCase} TestCase
+ * @throws {Error} If the payload is not a reader or valid buffer
+ * @throws {$protobuf.util.ProtocolError} If required fields are missing
+ */
+ TestCase.decodeDelimited = function decodeDelimited(reader) {
+ if (!(reader instanceof $Reader))
+ reader = new $Reader(reader);
+ return this.decode(reader, reader.uint32());
+ };
+
+ /**
+ * Verifies a TestCase message.
+ * @function verify
+ * @memberof blaze.TestCase
+ * @static
+ * @param {Object.} message Plain object to verify
+ * @returns {string|null} `null` if valid, otherwise the reason why it is not
+ */
+ TestCase.verify = function verify(message) {
+ if (typeof message !== "object" || message === null)
+ return "object expected";
+ if (message.child != null && message.hasOwnProperty("child")) {
+ if (!Array.isArray(message.child))
+ return "child: array expected";
+ for (var i = 0; i < message.child.length; ++i) {
+ var error = $root.blaze.TestCase.verify(message.child[i]);
+ if (error)
+ return "child." + error;
+ }
+ }
+ if (message.name != null && message.hasOwnProperty("name"))
+ if (!$util.isString(message.name))
+ return "name: string expected";
+ if (message.className != null && message.hasOwnProperty("className"))
+ if (!$util.isString(message.className))
+ return "className: string expected";
+ if (message.runDurationMillis != null && message.hasOwnProperty("runDurationMillis"))
+ if (!$util.isInteger(message.runDurationMillis) && !(message.runDurationMillis && $util.isInteger(message.runDurationMillis.low) && $util.isInteger(message.runDurationMillis.high)))
+ return "runDurationMillis: integer|Long expected";
+ if (message.result != null && message.hasOwnProperty("result"))
+ if (!$util.isString(message.result))
+ return "result: string expected";
+ if (message.type != null && message.hasOwnProperty("type"))
+ switch (message.type) {
+ default:
+ return "type: enum value expected";
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ break;
+ }
+ if (message.status != null && message.hasOwnProperty("status"))
+ switch (message.status) {
+ default:
+ return "status: enum value expected";
+ case 0:
+ case 1:
+ case 2:
+ break;
+ }
+ if (message.run != null && message.hasOwnProperty("run"))
+ if (typeof message.run !== "boolean")
+ return "run: boolean expected";
+ return null;
+ };
+
+ /**
+ * Creates a TestCase message from a plain object. Also converts values to their respective internal types.
+ * @function fromObject
+ * @memberof blaze.TestCase
+ * @static
+ * @param {Object.} object Plain object
+ * @returns {blaze.TestCase} TestCase
+ */
+ TestCase.fromObject = function fromObject(object) {
+ if (object instanceof $root.blaze.TestCase)
+ return object;
+ var message = new $root.blaze.TestCase();
+ if (object.child) {
+ if (!Array.isArray(object.child))
+ throw TypeError(".blaze.TestCase.child: array expected");
+ message.child = [];
+ for (var i = 0; i < object.child.length; ++i) {
+ if (typeof object.child[i] !== "object")
+ throw TypeError(".blaze.TestCase.child: object expected");
+ message.child[i] = $root.blaze.TestCase.fromObject(object.child[i]);
+ }
+ }
+ if (object.name != null)
+ message.name = String(object.name);
+ if (object.className != null)
+ message.className = String(object.className);
+ if (object.runDurationMillis != null)
+ if ($util.Long)
+ (message.runDurationMillis = $util.Long.fromValue(object.runDurationMillis)).unsigned = false;
+ else if (typeof object.runDurationMillis === "string")
+ message.runDurationMillis = parseInt(object.runDurationMillis, 10);
+ else if (typeof object.runDurationMillis === "number")
+ message.runDurationMillis = object.runDurationMillis;
+ else if (typeof object.runDurationMillis === "object")
+ message.runDurationMillis = new $util.LongBits(object.runDurationMillis.low >>> 0, object.runDurationMillis.high >>> 0).toNumber();
+ if (object.result != null)
+ message.result = String(object.result);
+ switch (object.type) {
+ case "TEST_CASE":
+ case 0:
+ message.type = 0;
+ break;
+ case "TEST_SUITE":
+ case 1:
+ message.type = 1;
+ break;
+ case "TEST_DECORATOR":
+ case 2:
+ message.type = 2;
+ break;
+ case "UNKNOWN":
+ case 3:
+ message.type = 3;
+ break;
+ }
+ switch (object.status) {
+ case "PASSED":
+ case 0:
+ message.status = 0;
+ break;
+ case "FAILED":
+ case 1:
+ message.status = 1;
+ break;
+ case "ERROR":
+ case 2:
+ message.status = 2;
+ break;
+ }
+ if (object.run != null)
+ message.run = Boolean(object.run);
+ return message;
+ };
+
+ /**
+ * Creates a plain object from a TestCase message. Also converts values to other types if specified.
+ * @function toObject
+ * @memberof blaze.TestCase
+ * @static
+ * @param {blaze.TestCase} message TestCase
+ * @param {$protobuf.IConversionOptions} [options] Conversion options
+ * @returns {Object.} Plain object
+ */
+ TestCase.toObject = function toObject(message, options) {
+ if (!options)
+ options = {};
+ var object = {};
+ if (options.arrays || options.defaults)
+ object.child = [];
+ if (options.defaults) {
+ object.name = "";
+ object.className = "";
+ if ($util.Long) {
+ var long = new $util.Long(0, 0, false);
+ object.runDurationMillis = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
+ } else
+ object.runDurationMillis = options.longs === String ? "0" : 0;
+ object.result = "";
+ object.type = options.enums === String ? "TEST_CASE" : 0;
+ object.status = options.enums === String ? "PASSED" : 0;
+ object.run = true;
+ }
+ if (message.child && message.child.length) {
+ object.child = [];
+ for (var j = 0; j < message.child.length; ++j)
+ object.child[j] = $root.blaze.TestCase.toObject(message.child[j], options);
+ }
+ if (message.name != null && message.hasOwnProperty("name"))
+ object.name = message.name;
+ if (message.className != null && message.hasOwnProperty("className"))
+ object.className = message.className;
+ if (message.runDurationMillis != null && message.hasOwnProperty("runDurationMillis"))
+ if (typeof message.runDurationMillis === "number")
+ object.runDurationMillis = options.longs === String ? String(message.runDurationMillis) : message.runDurationMillis;
+ else
+ object.runDurationMillis = options.longs === String ? $util.Long.prototype.toString.call(message.runDurationMillis) : options.longs === Number ? new $util.LongBits(message.runDurationMillis.low >>> 0, message.runDurationMillis.high >>> 0).toNumber() : message.runDurationMillis;
+ if (message.result != null && message.hasOwnProperty("result"))
+ object.result = message.result;
+ if (message.type != null && message.hasOwnProperty("type"))
+ object.type = options.enums === String ? $root.blaze.TestCase.Type[message.type] : message.type;
+ if (message.status != null && message.hasOwnProperty("status"))
+ object.status = options.enums === String ? $root.blaze.TestCase.Status[message.status] : message.status;
+ if (message.run != null && message.hasOwnProperty("run"))
+ object.run = message.run;
+ return object;
+ };
+
+ /**
+ * Converts this TestCase to JSON.
+ * @function toJSON
+ * @memberof blaze.TestCase
+ * @instance
+ * @returns {Object.} JSON object
+ */
+ TestCase.prototype.toJSON = function toJSON() {
+ return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+ };
+
+ /**
+ * Type enum.
+ * @name blaze.TestCase.Type
+ * @enum {number}
+ * @property {number} TEST_CASE=0 TEST_CASE value
+ * @property {number} TEST_SUITE=1 TEST_SUITE value
+ * @property {number} TEST_DECORATOR=2 TEST_DECORATOR value
+ * @property {number} UNKNOWN=3 UNKNOWN value
+ */
+ TestCase.Type = (function() {
+ var valuesById = {}, values = Object.create(valuesById);
+ values[valuesById[0] = "TEST_CASE"] = 0;
+ values[valuesById[1] = "TEST_SUITE"] = 1;
+ values[valuesById[2] = "TEST_DECORATOR"] = 2;
+ values[valuesById[3] = "UNKNOWN"] = 3;
+ return values;
+ })();
+
+ /**
+ * Status enum.
+ * @name blaze.TestCase.Status
+ * @enum {number}
+ * @property {number} PASSED=0 PASSED value
+ * @property {number} FAILED=1 FAILED value
+ * @property {number} ERROR=2 ERROR value
+ */
+ TestCase.Status = (function() {
+ var valuesById = {}, values = Object.create(valuesById);
+ values[valuesById[0] = "PASSED"] = 0;
+ values[valuesById[1] = "FAILED"] = 1;
+ values[valuesById[2] = "ERROR"] = 2;
+ return values;
+ })();
+
+ return TestCase;
+ })();
+
+ blaze.TestResultData = (function() {
+
+ /**
+ * Properties of a TestResultData.
+ * @memberof blaze
+ * @interface ITestResultData
+ * @property {boolean|null} [cachable] TestResultData cachable
+ * @property {boolean|null} [testPassed] TestResultData testPassed
+ * @property {blaze.BlazeTestStatus|null} [status] TestResultData status
+ * @property {string|null} [statusDetails] TestResultData statusDetails
+ * @property {Array.|null} [failedLogs] TestResultData failedLogs
+ * @property {Array.|null} [warning] TestResultData warning
+ * @property {boolean|null} [hasCoverage] TestResultData hasCoverage
+ * @property {boolean|null} [remotelyCached] TestResultData remotelyCached
+ * @property {boolean|null} [isRemoteStrategy] TestResultData isRemoteStrategy
+ * @property {Array.|null} [testTimes] TestResultData testTimes
+ * @property {string|null} [passedLog] TestResultData passedLog
+ * @property {Array.|null} [testProcessTimes] TestResultData testProcessTimes
+ * @property {number|Long|null} [runDurationMillis] TestResultData runDurationMillis
+ * @property {number|Long|null} [startTimeMillisEpoch] TestResultData startTimeMillisEpoch
+ * @property {blaze.ITestCase|null} [testCase] TestResultData testCase
+ * @property {blaze.FailedTestCasesStatus|null} [failedStatus] TestResultData failedStatus
+ */
+
+ /**
+ * Constructs a new TestResultData.
+ * @memberof blaze
+ * @classdesc Represents a TestResultData.
+ * @implements ITestResultData
+ * @constructor
+ * @param {blaze.ITestResultData=} [properties] Properties to set
+ */
+ function TestResultData(properties) {
+ this.failedLogs = [];
+ this.warning = [];
+ this.testTimes = [];
+ this.testProcessTimes = [];
+ if (properties)
+ for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+ if (properties[keys[i]] != null)
+ this[keys[i]] = properties[keys[i]];
+ }
+
+ /**
+ * TestResultData cachable.
+ * @member {boolean} cachable
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.cachable = false;
+
+ /**
+ * TestResultData testPassed.
+ * @member {boolean} testPassed
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.testPassed = false;
+
+ /**
+ * TestResultData status.
+ * @member {blaze.BlazeTestStatus} status
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.status = 0;
+
+ /**
+ * TestResultData statusDetails.
+ * @member {string} statusDetails
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.statusDetails = "";
+
+ /**
+ * TestResultData failedLogs.
+ * @member {Array.} failedLogs
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.failedLogs = $util.emptyArray;
+
+ /**
+ * TestResultData warning.
+ * @member {Array.} warning
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.warning = $util.emptyArray;
+
+ /**
+ * TestResultData hasCoverage.
+ * @member {boolean} hasCoverage
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.hasCoverage = false;
+
+ /**
+ * TestResultData remotelyCached.
+ * @member {boolean} remotelyCached
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.remotelyCached = false;
+
+ /**
+ * TestResultData isRemoteStrategy.
+ * @member {boolean} isRemoteStrategy
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.isRemoteStrategy = false;
+
+ /**
+ * TestResultData testTimes.
+ * @member {Array.} testTimes
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.testTimes = $util.emptyArray;
+
+ /**
+ * TestResultData passedLog.
+ * @member {string} passedLog
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.passedLog = "";
+
+ /**
+ * TestResultData testProcessTimes.
+ * @member {Array.} testProcessTimes
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.testProcessTimes = $util.emptyArray;
+
+ /**
+ * TestResultData runDurationMillis.
+ * @member {number|Long} runDurationMillis
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.runDurationMillis = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
+
+ /**
+ * TestResultData startTimeMillisEpoch.
+ * @member {number|Long} startTimeMillisEpoch
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.startTimeMillisEpoch = $util.Long ? $util.Long.fromBits(0,0,false) : 0;
+
+ /**
+ * TestResultData testCase.
+ * @member {blaze.ITestCase|null|undefined} testCase
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.testCase = null;
+
+ /**
+ * TestResultData failedStatus.
+ * @member {blaze.FailedTestCasesStatus} failedStatus
+ * @memberof blaze.TestResultData
+ * @instance
+ */
+ TestResultData.prototype.failedStatus = 1;
+
+ /**
+ * Creates a new TestResultData instance using the specified properties.
+ * @function create
+ * @memberof blaze.TestResultData
+ * @static
+ * @param {blaze.ITestResultData=} [properties] Properties to set
+ * @returns {blaze.TestResultData} TestResultData instance
+ */
+ TestResultData.create = function create(properties) {
+ return new TestResultData(properties);
+ };
+
+ /**
+ * Encodes the specified TestResultData message. Does not implicitly {@link blaze.TestResultData.verify|verify} messages.
+ * @function encode
+ * @memberof blaze.TestResultData
+ * @static
+ * @param {blaze.ITestResultData} message TestResultData message or plain object to encode
+ * @param {$protobuf.Writer} [writer] Writer to encode to
+ * @returns {$protobuf.Writer} Writer
+ */
+ TestResultData.encode = function encode(message, writer) {
+ if (!writer)
+ writer = $Writer.create();
+ if (message.cachable != null && Object.hasOwnProperty.call(message, "cachable"))
+ writer.uint32(/* id 1, wireType 0 =*/8).bool(message.cachable);
+ if (message.testPassed != null && Object.hasOwnProperty.call(message, "testPassed"))
+ writer.uint32(/* id 2, wireType 0 =*/16).bool(message.testPassed);
+ if (message.status != null && Object.hasOwnProperty.call(message, "status"))
+ writer.uint32(/* id 3, wireType 0 =*/24).int32(message.status);
+ if (message.failedLogs != null && message.failedLogs.length)
+ for (var i = 0; i < message.failedLogs.length; ++i)
+ writer.uint32(/* id 4, wireType 2 =*/34).string(message.failedLogs[i]);
+ if (message.warning != null && message.warning.length)
+ for (var i = 0; i < message.warning.length; ++i)
+ writer.uint32(/* id 5, wireType 2 =*/42).string(message.warning[i]);
+ if (message.hasCoverage != null && Object.hasOwnProperty.call(message, "hasCoverage"))
+ writer.uint32(/* id 6, wireType 0 =*/48).bool(message.hasCoverage);
+ if (message.remotelyCached != null && Object.hasOwnProperty.call(message, "remotelyCached"))
+ writer.uint32(/* id 7, wireType 0 =*/56).bool(message.remotelyCached);
+ if (message.isRemoteStrategy != null && Object.hasOwnProperty.call(message, "isRemoteStrategy"))
+ writer.uint32(/* id 8, wireType 0 =*/64).bool(message.isRemoteStrategy);
+ if (message.testTimes != null && message.testTimes.length)
+ for (var i = 0; i < message.testTimes.length; ++i)
+ writer.uint32(/* id 9, wireType 0 =*/72).int64(message.testTimes[i]);
+ if (message.passedLog != null && Object.hasOwnProperty.call(message, "passedLog"))
+ writer.uint32(/* id 10, wireType 2 =*/82).string(message.passedLog);
+ if (message.testProcessTimes != null && message.testProcessTimes.length)
+ for (var i = 0; i < message.testProcessTimes.length; ++i)
+ writer.uint32(/* id 11, wireType 0 =*/88).int64(message.testProcessTimes[i]);
+ if (message.runDurationMillis != null && Object.hasOwnProperty.call(message, "runDurationMillis"))
+ writer.uint32(/* id 12, wireType 0 =*/96).int64(message.runDurationMillis);
+ if (message.testCase != null && Object.hasOwnProperty.call(message, "testCase"))
+ $root.blaze.TestCase.encode(message.testCase, writer.uint32(/* id 13, wireType 2 =*/106).fork()).ldelim();
+ if (message.failedStatus != null && Object.hasOwnProperty.call(message, "failedStatus"))
+ writer.uint32(/* id 14, wireType 0 =*/112).int32(message.failedStatus);
+ if (message.startTimeMillisEpoch != null && Object.hasOwnProperty.call(message, "startTimeMillisEpoch"))
+ writer.uint32(/* id 15, wireType 0 =*/120).int64(message.startTimeMillisEpoch);
+ if (message.statusDetails != null && Object.hasOwnProperty.call(message, "statusDetails"))
+ writer.uint32(/* id 16, wireType 2 =*/130).string(message.statusDetails);
+ return writer;
+ };
+
+ /**
+ * Encodes the specified TestResultData message, length delimited. Does not implicitly {@link blaze.TestResultData.verify|verify} messages.
+ * @function encodeDelimited
+ * @memberof blaze.TestResultData
+ * @static
+ * @param {blaze.ITestResultData} message TestResultData message or plain object to encode
+ * @param {$protobuf.Writer} [writer] Writer to encode to
+ * @returns {$protobuf.Writer} Writer
+ */
+ TestResultData.encodeDelimited = function encodeDelimited(message, writer) {
+ return this.encode(message, writer).ldelim();
+ };
+
+ /**
+ * Decodes a TestResultData message from the specified reader or buffer.
+ * @function decode
+ * @memberof blaze.TestResultData
+ * @static
+ * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+ * @param {number} [length] Message length if known beforehand
+ * @returns {blaze.TestResultData} TestResultData
+ * @throws {Error} If the payload is not a reader or valid buffer
+ * @throws {$protobuf.util.ProtocolError} If required fields are missing
+ */
+ TestResultData.decode = function decode(reader, length) {
+ if (!(reader instanceof $Reader))
+ reader = $Reader.create(reader);
+ var end = length === undefined ? reader.len : reader.pos + length, message = new $root.blaze.TestResultData();
+ while (reader.pos < end) {
+ var tag = reader.uint32();
+ switch (tag >>> 3) {
+ case 1:
+ message.cachable = reader.bool();
+ break;
+ case 2:
+ message.testPassed = reader.bool();
+ break;
+ case 3:
+ message.status = reader.int32();
+ break;
+ case 16:
+ message.statusDetails = reader.string();
+ break;
+ case 4:
+ if (!(message.failedLogs && message.failedLogs.length))
+ message.failedLogs = [];
+ message.failedLogs.push(reader.string());
+ break;
+ case 5:
+ if (!(message.warning && message.warning.length))
+ message.warning = [];
+ message.warning.push(reader.string());
+ break;
+ case 6:
+ message.hasCoverage = reader.bool();
+ break;
+ case 7:
+ message.remotelyCached = reader.bool();
+ break;
+ case 8:
+ message.isRemoteStrategy = reader.bool();
+ break;
+ case 9:
+ if (!(message.testTimes && message.testTimes.length))
+ message.testTimes = [];
+ if ((tag & 7) === 2) {
+ var end2 = reader.uint32() + reader.pos;
+ while (reader.pos < end2)
+ message.testTimes.push(reader.int64());
+ } else
+ message.testTimes.push(reader.int64());
+ break;
+ case 10:
+ message.passedLog = reader.string();
+ break;
+ case 11:
+ if (!(message.testProcessTimes && message.testProcessTimes.length))
+ message.testProcessTimes = [];
+ if ((tag & 7) === 2) {
+ var end2 = reader.uint32() + reader.pos;
+ while (reader.pos < end2)
+ message.testProcessTimes.push(reader.int64());
+ } else
+ message.testProcessTimes.push(reader.int64());
+ break;
+ case 12:
+ message.runDurationMillis = reader.int64();
+ break;
+ case 15:
+ message.startTimeMillisEpoch = reader.int64();
+ break;
+ case 13:
+ message.testCase = $root.blaze.TestCase.decode(reader, reader.uint32());
+ break;
+ case 14:
+ message.failedStatus = reader.int32();
+ break;
+ default:
+ reader.skipType(tag & 7);
+ break;
+ }
+ }
+ return message;
+ };
+
+ /**
+ * Decodes a TestResultData message from the specified reader or buffer, length delimited.
+ * @function decodeDelimited
+ * @memberof blaze.TestResultData
+ * @static
+ * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+ * @returns {blaze.TestResultData} TestResultData
+ * @throws {Error} If the payload is not a reader or valid buffer
+ * @throws {$protobuf.util.ProtocolError} If required fields are missing
+ */
+ TestResultData.decodeDelimited = function decodeDelimited(reader) {
+ if (!(reader instanceof $Reader))
+ reader = new $Reader(reader);
+ return this.decode(reader, reader.uint32());
+ };
+
+ /**
+ * Verifies a TestResultData message.
+ * @function verify
+ * @memberof blaze.TestResultData
+ * @static
+ * @param {Object.} message Plain object to verify
+ * @returns {string|null} `null` if valid, otherwise the reason why it is not
+ */
+ TestResultData.verify = function verify(message) {
+ if (typeof message !== "object" || message === null)
+ return "object expected";
+ if (message.cachable != null && message.hasOwnProperty("cachable"))
+ if (typeof message.cachable !== "boolean")
+ return "cachable: boolean expected";
+ if (message.testPassed != null && message.hasOwnProperty("testPassed"))
+ if (typeof message.testPassed !== "boolean")
+ return "testPassed: boolean expected";
+ if (message.status != null && message.hasOwnProperty("status"))
+ switch (message.status) {
+ default:
+ return "status: enum value expected";
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ break;
+ }
+ if (message.statusDetails != null && message.hasOwnProperty("statusDetails"))
+ if (!$util.isString(message.statusDetails))
+ return "statusDetails: string expected";
+ if (message.failedLogs != null && message.hasOwnProperty("failedLogs")) {
+ if (!Array.isArray(message.failedLogs))
+ return "failedLogs: array expected";
+ for (var i = 0; i < message.failedLogs.length; ++i)
+ if (!$util.isString(message.failedLogs[i]))
+ return "failedLogs: string[] expected";
+ }
+ if (message.warning != null && message.hasOwnProperty("warning")) {
+ if (!Array.isArray(message.warning))
+ return "warning: array expected";
+ for (var i = 0; i < message.warning.length; ++i)
+ if (!$util.isString(message.warning[i]))
+ return "warning: string[] expected";
+ }
+ if (message.hasCoverage != null && message.hasOwnProperty("hasCoverage"))
+ if (typeof message.hasCoverage !== "boolean")
+ return "hasCoverage: boolean expected";
+ if (message.remotelyCached != null && message.hasOwnProperty("remotelyCached"))
+ if (typeof message.remotelyCached !== "boolean")
+ return "remotelyCached: boolean expected";
+ if (message.isRemoteStrategy != null && message.hasOwnProperty("isRemoteStrategy"))
+ if (typeof message.isRemoteStrategy !== "boolean")
+ return "isRemoteStrategy: boolean expected";
+ if (message.testTimes != null && message.hasOwnProperty("testTimes")) {
+ if (!Array.isArray(message.testTimes))
+ return "testTimes: array expected";
+ for (var i = 0; i < message.testTimes.length; ++i)
+ if (!$util.isInteger(message.testTimes[i]) && !(message.testTimes[i] && $util.isInteger(message.testTimes[i].low) && $util.isInteger(message.testTimes[i].high)))
+ return "testTimes: integer|Long[] expected";
+ }
+ if (message.passedLog != null && message.hasOwnProperty("passedLog"))
+ if (!$util.isString(message.passedLog))
+ return "passedLog: string expected";
+ if (message.testProcessTimes != null && message.hasOwnProperty("testProcessTimes")) {
+ if (!Array.isArray(message.testProcessTimes))
+ return "testProcessTimes: array expected";
+ for (var i = 0; i < message.testProcessTimes.length; ++i)
+ if (!$util.isInteger(message.testProcessTimes[i]) && !(message.testProcessTimes[i] && $util.isInteger(message.testProcessTimes[i].low) && $util.isInteger(message.testProcessTimes[i].high)))
+ return "testProcessTimes: integer|Long[] expected";
+ }
+ if (message.runDurationMillis != null && message.hasOwnProperty("runDurationMillis"))
+ if (!$util.isInteger(message.runDurationMillis) && !(message.runDurationMillis && $util.isInteger(message.runDurationMillis.low) && $util.isInteger(message.runDurationMillis.high)))
+ return "runDurationMillis: integer|Long expected";
+ if (message.startTimeMillisEpoch != null && message.hasOwnProperty("startTimeMillisEpoch"))
+ if (!$util.isInteger(message.startTimeMillisEpoch) && !(message.startTimeMillisEpoch && $util.isInteger(message.startTimeMillisEpoch.low) && $util.isInteger(message.startTimeMillisEpoch.high)))
+ return "startTimeMillisEpoch: integer|Long expected";
+ if (message.testCase != null && message.hasOwnProperty("testCase")) {
+ var error = $root.blaze.TestCase.verify(message.testCase);
+ if (error)
+ return "testCase." + error;
+ }
+ if (message.failedStatus != null && message.hasOwnProperty("failedStatus"))
+ switch (message.failedStatus) {
+ default:
+ return "failedStatus: enum value expected";
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ break;
+ }
+ return null;
+ };
+
+ /**
+ * Creates a TestResultData message from a plain object. Also converts values to their respective internal types.
+ * @function fromObject
+ * @memberof blaze.TestResultData
+ * @static
+ * @param {Object.} object Plain object
+ * @returns {blaze.TestResultData} TestResultData
+ */
+ TestResultData.fromObject = function fromObject(object) {
+ if (object instanceof $root.blaze.TestResultData)
+ return object;
+ var message = new $root.blaze.TestResultData();
+ if (object.cachable != null)
+ message.cachable = Boolean(object.cachable);
+ if (object.testPassed != null)
+ message.testPassed = Boolean(object.testPassed);
+ switch (object.status) {
+ case "NO_STATUS":
+ case 0:
+ message.status = 0;
+ break;
+ case "PASSED":
+ case 1:
+ message.status = 1;
+ break;
+ case "FLAKY":
+ case 2:
+ message.status = 2;
+ break;
+ case "TIMEOUT":
+ case 3:
+ message.status = 3;
+ break;
+ case "FAILED":
+ case 4:
+ message.status = 4;
+ break;
+ case "INCOMPLETE":
+ case 5:
+ message.status = 5;
+ break;
+ case "REMOTE_FAILURE":
+ case 6:
+ message.status = 6;
+ break;
+ case "FAILED_TO_BUILD":
+ case 7:
+ message.status = 7;
+ break;
+ case "BLAZE_HALTED_BEFORE_TESTING":
+ case 8:
+ message.status = 8;
+ break;
+ }
+ if (object.statusDetails != null)
+ message.statusDetails = String(object.statusDetails);
+ if (object.failedLogs) {
+ if (!Array.isArray(object.failedLogs))
+ throw TypeError(".blaze.TestResultData.failedLogs: array expected");
+ message.failedLogs = [];
+ for (var i = 0; i < object.failedLogs.length; ++i)
+ message.failedLogs[i] = String(object.failedLogs[i]);
+ }
+ if (object.warning) {
+ if (!Array.isArray(object.warning))
+ throw TypeError(".blaze.TestResultData.warning: array expected");
+ message.warning = [];
+ for (var i = 0; i < object.warning.length; ++i)
+ message.warning[i] = String(object.warning[i]);
+ }
+ if (object.hasCoverage != null)
+ message.hasCoverage = Boolean(object.hasCoverage);
+ if (object.remotelyCached != null)
+ message.remotelyCached = Boolean(object.remotelyCached);
+ if (object.isRemoteStrategy != null)
+ message.isRemoteStrategy = Boolean(object.isRemoteStrategy);
+ if (object.testTimes) {
+ if (!Array.isArray(object.testTimes))
+ throw TypeError(".blaze.TestResultData.testTimes: array expected");
+ message.testTimes = [];
+ for (var i = 0; i < object.testTimes.length; ++i)
+ if ($util.Long)
+ (message.testTimes[i] = $util.Long.fromValue(object.testTimes[i])).unsigned = false;
+ else if (typeof object.testTimes[i] === "string")
+ message.testTimes[i] = parseInt(object.testTimes[i], 10);
+ else if (typeof object.testTimes[i] === "number")
+ message.testTimes[i] = object.testTimes[i];
+ else if (typeof object.testTimes[i] === "object")
+ message.testTimes[i] = new $util.LongBits(object.testTimes[i].low >>> 0, object.testTimes[i].high >>> 0).toNumber();
+ }
+ if (object.passedLog != null)
+ message.passedLog = String(object.passedLog);
+ if (object.testProcessTimes) {
+ if (!Array.isArray(object.testProcessTimes))
+ throw TypeError(".blaze.TestResultData.testProcessTimes: array expected");
+ message.testProcessTimes = [];
+ for (var i = 0; i < object.testProcessTimes.length; ++i)
+ if ($util.Long)
+ (message.testProcessTimes[i] = $util.Long.fromValue(object.testProcessTimes[i])).unsigned = false;
+ else if (typeof object.testProcessTimes[i] === "string")
+ message.testProcessTimes[i] = parseInt(object.testProcessTimes[i], 10);
+ else if (typeof object.testProcessTimes[i] === "number")
+ message.testProcessTimes[i] = object.testProcessTimes[i];
+ else if (typeof object.testProcessTimes[i] === "object")
+ message.testProcessTimes[i] = new $util.LongBits(object.testProcessTimes[i].low >>> 0, object.testProcessTimes[i].high >>> 0).toNumber();
+ }
+ if (object.runDurationMillis != null)
+ if ($util.Long)
+ (message.runDurationMillis = $util.Long.fromValue(object.runDurationMillis)).unsigned = false;
+ else if (typeof object.runDurationMillis === "string")
+ message.runDurationMillis = parseInt(object.runDurationMillis, 10);
+ else if (typeof object.runDurationMillis === "number")
+ message.runDurationMillis = object.runDurationMillis;
+ else if (typeof object.runDurationMillis === "object")
+ message.runDurationMillis = new $util.LongBits(object.runDurationMillis.low >>> 0, object.runDurationMillis.high >>> 0).toNumber();
+ if (object.startTimeMillisEpoch != null)
+ if ($util.Long)
+ (message.startTimeMillisEpoch = $util.Long.fromValue(object.startTimeMillisEpoch)).unsigned = false;
+ else if (typeof object.startTimeMillisEpoch === "string")
+ message.startTimeMillisEpoch = parseInt(object.startTimeMillisEpoch, 10);
+ else if (typeof object.startTimeMillisEpoch === "number")
+ message.startTimeMillisEpoch = object.startTimeMillisEpoch;
+ else if (typeof object.startTimeMillisEpoch === "object")
+ message.startTimeMillisEpoch = new $util.LongBits(object.startTimeMillisEpoch.low >>> 0, object.startTimeMillisEpoch.high >>> 0).toNumber();
+ if (object.testCase != null) {
+ if (typeof object.testCase !== "object")
+ throw TypeError(".blaze.TestResultData.testCase: object expected");
+ message.testCase = $root.blaze.TestCase.fromObject(object.testCase);
+ }
+ switch (object.failedStatus) {
+ case "FULL":
+ case 1:
+ message.failedStatus = 1;
+ break;
+ case "PARTIAL":
+ case 2:
+ message.failedStatus = 2;
+ break;
+ case "NOT_AVAILABLE":
+ case 3:
+ message.failedStatus = 3;
+ break;
+ case "EMPTY":
+ case 4:
+ message.failedStatus = 4;
+ break;
+ }
+ return message;
+ };
+
+ /**
+ * Creates a plain object from a TestResultData message. Also converts values to other types if specified.
+ * @function toObject
+ * @memberof blaze.TestResultData
+ * @static
+ * @param {blaze.TestResultData} message TestResultData
+ * @param {$protobuf.IConversionOptions} [options] Conversion options
+ * @returns {Object.} Plain object
+ */
+ TestResultData.toObject = function toObject(message, options) {
+ if (!options)
+ options = {};
+ var object = {};
+ if (options.arrays || options.defaults) {
+ object.failedLogs = [];
+ object.warning = [];
+ object.testTimes = [];
+ object.testProcessTimes = [];
+ }
+ if (options.defaults) {
+ object.cachable = false;
+ object.testPassed = false;
+ object.status = options.enums === String ? "NO_STATUS" : 0;
+ object.hasCoverage = false;
+ object.remotelyCached = false;
+ object.isRemoteStrategy = false;
+ object.passedLog = "";
+ if ($util.Long) {
+ var long = new $util.Long(0, 0, false);
+ object.runDurationMillis = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
+ } else
+ object.runDurationMillis = options.longs === String ? "0" : 0;
+ object.testCase = null;
+ object.failedStatus = options.enums === String ? "FULL" : 1;
+ if ($util.Long) {
+ var long = new $util.Long(0, 0, false);
+ object.startTimeMillisEpoch = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
+ } else
+ object.startTimeMillisEpoch = options.longs === String ? "0" : 0;
+ object.statusDetails = "";
+ }
+ if (message.cachable != null && message.hasOwnProperty("cachable"))
+ object.cachable = message.cachable;
+ if (message.testPassed != null && message.hasOwnProperty("testPassed"))
+ object.testPassed = message.testPassed;
+ if (message.status != null && message.hasOwnProperty("status"))
+ object.status = options.enums === String ? $root.blaze.BlazeTestStatus[message.status] : message.status;
+ if (message.failedLogs && message.failedLogs.length) {
+ object.failedLogs = [];
+ for (var j = 0; j < message.failedLogs.length; ++j)
+ object.failedLogs[j] = message.failedLogs[j];
+ }
+ if (message.warning && message.warning.length) {
+ object.warning = [];
+ for (var j = 0; j < message.warning.length; ++j)
+ object.warning[j] = message.warning[j];
+ }
+ if (message.hasCoverage != null && message.hasOwnProperty("hasCoverage"))
+ object.hasCoverage = message.hasCoverage;
+ if (message.remotelyCached != null && message.hasOwnProperty("remotelyCached"))
+ object.remotelyCached = message.remotelyCached;
+ if (message.isRemoteStrategy != null && message.hasOwnProperty("isRemoteStrategy"))
+ object.isRemoteStrategy = message.isRemoteStrategy;
+ if (message.testTimes && message.testTimes.length) {
+ object.testTimes = [];
+ for (var j = 0; j < message.testTimes.length; ++j)
+ if (typeof message.testTimes[j] === "number")
+ object.testTimes[j] = options.longs === String ? String(message.testTimes[j]) : message.testTimes[j];
+ else
+ object.testTimes[j] = options.longs === String ? $util.Long.prototype.toString.call(message.testTimes[j]) : options.longs === Number ? new $util.LongBits(message.testTimes[j].low >>> 0, message.testTimes[j].high >>> 0).toNumber() : message.testTimes[j];
+ }
+ if (message.passedLog != null && message.hasOwnProperty("passedLog"))
+ object.passedLog = message.passedLog;
+ if (message.testProcessTimes && message.testProcessTimes.length) {
+ object.testProcessTimes = [];
+ for (var j = 0; j < message.testProcessTimes.length; ++j)
+ if (typeof message.testProcessTimes[j] === "number")
+ object.testProcessTimes[j] = options.longs === String ? String(message.testProcessTimes[j]) : message.testProcessTimes[j];
+ else
+ object.testProcessTimes[j] = options.longs === String ? $util.Long.prototype.toString.call(message.testProcessTimes[j]) : options.longs === Number ? new $util.LongBits(message.testProcessTimes[j].low >>> 0, message.testProcessTimes[j].high >>> 0).toNumber() : message.testProcessTimes[j];
+ }
+ if (message.runDurationMillis != null && message.hasOwnProperty("runDurationMillis"))
+ if (typeof message.runDurationMillis === "number")
+ object.runDurationMillis = options.longs === String ? String(message.runDurationMillis) : message.runDurationMillis;
+ else
+ object.runDurationMillis = options.longs === String ? $util.Long.prototype.toString.call(message.runDurationMillis) : options.longs === Number ? new $util.LongBits(message.runDurationMillis.low >>> 0, message.runDurationMillis.high >>> 0).toNumber() : message.runDurationMillis;
+ if (message.testCase != null && message.hasOwnProperty("testCase"))
+ object.testCase = $root.blaze.TestCase.toObject(message.testCase, options);
+ if (message.failedStatus != null && message.hasOwnProperty("failedStatus"))
+ object.failedStatus = options.enums === String ? $root.blaze.FailedTestCasesStatus[message.failedStatus] : message.failedStatus;
+ if (message.startTimeMillisEpoch != null && message.hasOwnProperty("startTimeMillisEpoch"))
+ if (typeof message.startTimeMillisEpoch === "number")
+ object.startTimeMillisEpoch = options.longs === String ? String(message.startTimeMillisEpoch) : message.startTimeMillisEpoch;
+ else
+ object.startTimeMillisEpoch = options.longs === String ? $util.Long.prototype.toString.call(message.startTimeMillisEpoch) : options.longs === Number ? new $util.LongBits(message.startTimeMillisEpoch.low >>> 0, message.startTimeMillisEpoch.high >>> 0).toNumber() : message.startTimeMillisEpoch;
+ if (message.statusDetails != null && message.hasOwnProperty("statusDetails"))
+ object.statusDetails = message.statusDetails;
+ return object;
+ };
+
+ /**
+ * Converts this TestResultData to JSON.
+ * @function toJSON
+ * @memberof blaze.TestResultData
+ * @instance
+ * @returns {Object.} JSON object
+ */
+ TestResultData.prototype.toJSON = function toJSON() {
+ return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+ };
+
+ return TestResultData;
+ })();
+
+ return blaze;
+})();
+
+module.exports = $root;
diff --git a/ng-dev/BUILD.bazel b/ng-dev/BUILD.bazel
index 88775ac20..8ce71e445 100644
--- a/ng-dev/BUILD.bazel
+++ b/ng-dev/BUILD.bazel
@@ -19,6 +19,7 @@ ts_library(
],
deps = [
"//ng-dev/caretaker",
+ "//ng-dev/ci",
"//ng-dev/commit-message",
"//ng-dev/format",
"//ng-dev/misc",
diff --git a/ng-dev/ci/BUILD.bazel b/ng-dev/ci/BUILD.bazel
new file mode 100644
index 000000000..0be672ec4
--- /dev/null
+++ b/ng-dev/ci/BUILD.bazel
@@ -0,0 +1,13 @@
+load("//tools:defaults.bzl", "ts_library")
+
+ts_library(
+ name = "ci",
+ srcs = [
+ "cli.ts",
+ ],
+ visibility = ["//ng-dev:__subpackages__"],
+ deps = [
+ "//ng-dev/ci/gather-test-results",
+ "@npm//@types/yargs",
+ ],
+)
diff --git a/ng-dev/ci/cli.ts b/ng-dev/ci/cli.ts
new file mode 100644
index 000000000..76b147d84
--- /dev/null
+++ b/ng-dev/ci/cli.ts
@@ -0,0 +1,14 @@
+/**
+ * @license
+ * Copyright Google LLC All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+import {Argv} from 'yargs';
+import {GatherTestResultsModule} from './gather-test-results/cli';
+
+/** Build the parser for the ci commands. */
+export function buildCiParser(yargs: Argv) {
+ return yargs.help().strict().command(GatherTestResultsModule);
+}
diff --git a/ng-dev/ci/gather-test-results/BUILD.bazel b/ng-dev/ci/gather-test-results/BUILD.bazel
new file mode 100644
index 000000000..052d5278e
--- /dev/null
+++ b/ng-dev/ci/gather-test-results/BUILD.bazel
@@ -0,0 +1,16 @@
+load("//tools:defaults.bzl", "ts_library")
+
+ts_library(
+ name = "gather-test-results",
+ srcs = [
+ "cli.ts",
+ "index.ts",
+ ],
+ visibility = ["//ng-dev:__subpackages__"],
+ deps = [
+ "//bazel/protos:test_status",
+ "//ng-dev/utils",
+ "@npm//@types/node",
+ "@npm//@types/yargs",
+ ],
+)
diff --git a/ng-dev/ci/gather-test-results/cli.ts b/ng-dev/ci/gather-test-results/cli.ts
new file mode 100644
index 000000000..bf5b9a76f
--- /dev/null
+++ b/ng-dev/ci/gather-test-results/cli.ts
@@ -0,0 +1,41 @@
+/**
+ * @license
+ * Copyright Google LLC All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import {Arguments, Argv, CommandModule} from 'yargs';
+import {copyTestResultFiles} from '.';
+import {error, red} from '../../utils/console';
+/** Command line options. */
+export interface Options {
+ force: boolean;
+}
+
+/** Yargs command builder for the command. */
+function builder(argv: Argv): Argv {
+ return argv.option('force', {
+ type: 'boolean',
+ default: false,
+ description: 'Whether to force the command to run, ignoring the CI environment check',
+ });
+}
+
+/** Yargs command handler for the command. */
+async function handler({force}: Arguments) {
+ if (force === false && process.env['CI'] === undefined) {
+ error(red('Aborting, `gather-test-results` is only meant to be run on CI.'));
+ process.exit(1);
+ }
+ copyTestResultFiles();
+}
+
+/** CLI command module. */
+export const GatherTestResultsModule: CommandModule<{}, Options> = {
+ builder,
+ handler,
+ command: 'gather-test-results',
+ describe: 'Gather test result files into single directory for consumption by CircleCI',
+};
diff --git a/ng-dev/ci/gather-test-results/index.ts b/ng-dev/ci/gather-test-results/index.ts
new file mode 100644
index 000000000..386906b20
--- /dev/null
+++ b/ng-dev/ci/gather-test-results/index.ts
@@ -0,0 +1,116 @@
+/**
+ * @license
+ * Copyright Google LLC All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import {blaze} from '../../../bazel/protos/test_status_pb';
+import {spawnSync} from '../../utils/child-process';
+import {join, extname} from 'path';
+import {
+ mkdirSync,
+ rmSync,
+ readFileSync,
+ statSync,
+ readdirSync,
+ copyFileSync,
+ writeFileSync,
+} from 'fs';
+import {debug, info} from '../../utils/console';
+import {GitClient} from '../../utils/git/git-client';
+
+/** Bazel's TestResultData proto Message. */
+const TestResultData = blaze.TestResultData;
+
+type TestResultFiles = [xmlFile: string, cacheProtoFile: string];
+
+/**
+ * A JUnit test report to always include signaling to CircleCI that tests were requested.
+ *
+ * `testsuite` and `testcase` elements are required for CircleCI to properly parse the report.
+ */
+const baseTestReport = `
+
+
+
+
+
+
+ `.trim();
+
+function getTestLogsDirectoryPath() {
+ const {stdout, status} = spawnSync('yarn', ['-s', 'bazel', 'info', 'bazel-testlogs']);
+
+ if (status === 0) {
+ return stdout.trim();
+ }
+ throw Error(`Unable to determine the path to the directory containing Bazel's testlog.`);
+}
+
+/**
+ * Discover all test results, which @bazel/jasmine stores as `test.xml` files, in the directory and
+ * return back the list of absolute file paths.
+ */
+function findAllTestResultFiles(dirPath: string, files: TestResultFiles[]) {
+ for (const file of readdirSync(dirPath)) {
+ const filePath = join(dirPath, file);
+ if (statSync(filePath).isDirectory()) {
+ files = findAllTestResultFiles(filePath, files);
+ } else {
+ // Only the test result files, which are XML with the .xml extension, should be discovered.
+ if (extname(file) === '.xml') {
+ files.push([filePath, join(dirPath, 'test.cache_status')]);
+ }
+ }
+ }
+ return files;
+}
+
+export function copyTestResultFiles() {
+ /** Total number of files copied, also used as a index to number copied files. */
+ let copiedFileCount = 0;
+ /** The absolute path to the directory containing test logs from bazel tests. */
+ const testLogsDir = getTestLogsDirectoryPath();
+ /** List of test result files. */
+ const testResultPaths = findAllTestResultFiles(testLogsDir, []);
+ /** The full path to the root of the repository base. */
+ const projectBaseDir = GitClient.get().baseDir;
+ /**
+ * Absolute path to a directory to contain the JUnit test result files.
+ *
+ * Note: The directory created needs to contain a subdirectory which contains the test results in
+ * order for CircleCI to properly discover the test results.
+ */
+ const destDirPath = join(projectBaseDir, 'test-results/_');
+
+ // Ensure that an empty directory exists to contain the test results reports for upload.
+ rmSync(destDirPath, {recursive: true, force: true});
+ mkdirSync(destDirPath, {recursive: true});
+
+ // By always uploading at least one result file, CircleCI will understand that a tests actions were
+ // called for in the bazel test run, even if not tests were actually executed due to cache hits. By
+ // always making sure to upload at least one test result report, CircleCI always include the
+ // workflow in its aggregated data and provide better metrics about the number of executed tests per
+ // run.
+ writeFileSync(join(destDirPath, `results.xml`), baseTestReport);
+ debug('Added base test report to test-results directory.');
+
+ // Copy each of the test result files to the central test result directory which CircleCI discovers
+ // test results in.
+ testResultPaths.forEach(([xmlFilePath, cacheStatusFilePath]) => {
+ const shortFilePath = xmlFilePath.substr(testLogsDir.length + 1);
+ const testResultData = TestResultData.decode(readFileSync(cacheStatusFilePath));
+
+ if (testResultData.remotelyCached && testResultData.testPassed) {
+ debug(`Skipping copy of ${shortFilePath} as it was a passing remote cache hit`);
+ } else {
+ const destFilePath = join(destDirPath, `results-${copiedFileCount++}.xml`);
+ copyFileSync(xmlFilePath, destFilePath);
+ debug(`Copying ${shortFilePath}`);
+ }
+ });
+
+ info(`Copied ${copiedFileCount} test result file(s) for upload.`);
+}
diff --git a/ng-dev/cli.ts b/ng-dev/cli.ts
index c619bc987..6a3c58051 100644
--- a/ng-dev/cli.ts
+++ b/ng-dev/cli.ts
@@ -18,6 +18,7 @@ import {buildReleaseParser} from './release/cli';
import {tsCircularDependenciesBuilder} from './ts-circular-dependencies/index';
import {captureLogOutputForCommand} from './utils/console';
import {buildMiscParser} from './misc/cli';
+import {buildCiParser} from './ci/cli';
yargs
.scriptName('ng-dev')
@@ -33,6 +34,7 @@ yargs
.command('caretaker ', '', buildCaretakerParser)
.command('misc ', '', buildMiscParser)
.command('ngbot ', false, buildNgbotParser)
+ .command('ci ', false, buildCiParser)
.wrap(120)
.strict()
.parse();
diff --git a/package.json b/package.json
index e3bce0ccd..869f46106 100644
--- a/package.json
+++ b/package.json
@@ -77,6 +77,9 @@
"@types/shelljs": "^0.8.8",
"@types/uuid": "^8.3.1",
"@types/yargs": "^17.0.0",
- "protobufjs": "^6.11.2"
+ "jsdoc": "^3.6.7",
+ "minimist": "^1.2.5",
+ "protobufjs": "^6.11.2",
+ "uglify-js": "^3.14.2"
}
}
diff --git a/tools/generate_ts_proto_module.bzl b/tools/generate_ts_proto_module.bzl
new file mode 100644
index 000000000..235f0da13
--- /dev/null
+++ b/tools/generate_ts_proto_module.bzl
@@ -0,0 +1,77 @@
+load("@build_bazel_rules_nodejs//:index.bzl", "generated_file_test", "js_library", "npm_package_bin")
+
+def generate_ts_proto_module(name, protofile, visibility = ["//visibility:public"]):
+ """
+ Generate a typescript module for decoding a proto binary file based on a provided .proto file.
+ """
+
+ # Runtime dependencies, if not already installed, are installed by protobufjs via `npm install`
+ # during the execution. As `npm_package_bin` isolates the execution from the rest of
+ # node_modules, these expected dependencies must be provided.
+ # The check and install of the dependencies is performed in this code block:
+ # https://github.com/protobufjs/protobuf.js/blob/v6.11.2/cli/util.js#L135
+ protobufjs_dependencies = [
+ "@npm//semver",
+ "@npm//chalk",
+ "@npm//jsdoc",
+ "@npm//minimist",
+ "@npm//uglify-js",
+ ]
+ js_file = name + "_pb.js"
+ d_ts_file = name + "_pb.d.ts"
+
+ npm_package_bin(
+ name = "generate_js_" + name,
+ tool = "@npm//protobufjs/bin:pbjs",
+ data = protobufjs_dependencies + [
+ protofile,
+ ],
+ testonly = True,
+ args = [
+ "-t",
+ "static-module",
+ "-w",
+ "commonjs",
+ "$(rootpath %s)" % protofile,
+ ],
+ stdout = "generated_" + js_file,
+ )
+
+ npm_package_bin(
+ name = "generate_ts_" + name,
+ tool = "@npm//protobufjs/bin:pbts",
+ data = protobufjs_dependencies + [
+ ":generate_js_%s" % name,
+ ],
+ testonly = True,
+ args = [
+ "$(execpath :generate_js_%s)" % name,
+ ],
+ stdout = "generated_" + d_ts_file,
+ )
+
+ generated_file_test(
+ name = name + "_dts",
+ src = d_ts_file,
+ testonly = True,
+ generated = "generated_" + d_ts_file,
+ )
+
+ generated_file_test(
+ name = name + "_js",
+ testonly = True,
+ src = js_file,
+ generated = "generated_" + js_file,
+ )
+
+ js_library(
+ name = name,
+ srcs = [
+ d_ts_file,
+ js_file,
+ ],
+ deps = [
+ "@npm//protobufjs",
+ ],
+ visibility = visibility,
+ )
diff --git a/tools/protos/test_status.proto b/tools/protos/test_status.proto
deleted file mode 100644
index 2819ab392..000000000
--- a/tools/protos/test_status.proto
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copied from `external/@bazel_tools/src/main/protobuf/test_status.proto`.
-// https://github.com/bazelbuild/bazel/blob/4.2.1/src/main/protobuf/test_status.proto
-// Bazel Version: 4.2.1
-
-// Copyright 2014 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-syntax = "proto2";
-
-package blaze;
-
-option java_package = "com.google.devtools.build.lib.view.test";
-
-// Status data of test cases which failed (used only for printing test summary)
-enum FailedTestCasesStatus {
- /** Information about every test case is available. */
- FULL = 1;
- /** Information about some test cases may be missing. */
- PARTIAL = 2;
- /** No information about individual test cases. */
- NOT_AVAILABLE = 3;
- /** This is an empty object still without data. */
- EMPTY = 4;
-};
-
-// Detailed status data for a TestRunnerAction execution.
-enum BlazeTestStatus {
- NO_STATUS = 0;
- PASSED = 1;
- FLAKY = 2;
- TIMEOUT = 3;
- FAILED = 4;
- INCOMPLETE = 5;
- REMOTE_FAILURE = 6;
- FAILED_TO_BUILD = 7;
- BLAZE_HALTED_BEFORE_TESTING = 8;
-};
-
-// TestCase contains detailed data about all tests (cases/suites/decorators)
-// ran, structured in a tree. This data will be later used to present the tests
-// by the web status server.
-message TestCase {
- enum Type {
- TEST_CASE = 0;
- TEST_SUITE = 1;
- TEST_DECORATOR = 2;
- UNKNOWN = 3;
- }
-
- enum Status {
- PASSED = 0;
- FAILED = 1;
- ERROR = 2;
- }
-
- repeated TestCase child = 1;
- optional string name = 2;
- optional string class_name = 3;
- optional int64 run_duration_millis = 4;
- optional string result = 5;
- optional Type type = 6;
- optional Status status = 7;
- optional bool run = 8 [default = true];
-};
-
-// TestResultData holds the outcome data for a single test action (A
-// single test rule can result in multiple actions due to sharding and
-// runs_per_test settings.)
-message TestResultData {
- // The following two fields are used for TestRunnerAction caching.
- // This reflects the fact that failing tests are successful
- // actions that might be cached, depending on option settings.
- optional bool cachable = 1;
- optional bool test_passed = 2;
-
- // Following data is informational.
- optional BlazeTestStatus status = 3 [default = NO_STATUS];
- optional string status_details = 16;
- repeated string failed_logs = 4;
- repeated string warning = 5;
- optional bool has_coverage = 6;
-
- // Returns if this was cached in remote execution.
- optional bool remotely_cached = 7;
-
- // Returns true if this was executed remotely
- optional bool is_remote_strategy = 8;
-
- // All associated test times (in ms).
- repeated int64 test_times = 9;
-
- // Passed log paths. Set if the test passed.
- optional string passed_log = 10;
-
- // Test times, without remote execution overhead (in ms).
- repeated int64 test_process_times = 11;
-
- // Total time in ms.
- optional int64 run_duration_millis = 12;
-
- // Start time of the test action in ms since the epoch.
- optional int64 start_time_millis_epoch = 15;
-
- // Additional build info
- optional TestCase test_case = 13;
- optional FailedTestCasesStatus failed_status = 14;
-};
diff --git a/yarn.lock b/yarn.lock
index 3853d16c3..af4db4da8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -69,6 +69,11 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
+"@babel/parser@^7.9.4":
+ version "7.15.7"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.7.tgz#0c3ed4a2eb07b165dfa85b3cc45c727334c4edae"
+ integrity sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g==
+
"@bazel/bazelisk@^1.10.1":
version "1.10.1"
resolved "https://registry.yarnpkg.com/@bazel/bazelisk/-/bazelisk-1.10.1.tgz#46236a43ad58e310c55247f866da0dc6083c3d8b"
@@ -888,6 +893,11 @@ blocking-proxy@^1.0.0:
dependencies:
minimist "^1.2.0"
+bluebird@^3.7.2:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
+ integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
+
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -974,6 +984,13 @@ caseless@~0.12.0:
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
+catharsis@^0.9.0:
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/catharsis/-/catharsis-0.9.0.tgz#40382a168be0e6da308c277d3a2b3eb40c7d2121"
+ integrity sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==
+ dependencies:
+ lodash "^4.17.15"
+
chalk@^1.1.1, chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@@ -1274,6 +1291,11 @@ emoji-regex@^8.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+entities@~2.0.0:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f"
+ integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==
+
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
@@ -1303,6 +1325,11 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+escape-string-regexp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
+ integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
+
esprima@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
@@ -1514,7 +1541,7 @@ google-protobuf@^3.6.1:
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.18.0.tgz#687449d8e858305d658dc1145852c306d8222f5a"
integrity sha512-WlaQWRkUOo/lm9uTgNH6nk9IQt814RggWPzKBfnAVewOFzSzRUSmS1yUWRT6ixW1vS7er5p6tmLSmwzpPpmc8A==
-graceful-fs@^4.1.2, graceful-fs@^4.1.6:
+graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
version "4.2.8"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
@@ -1855,11 +1882,38 @@ js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
+js2xmlparser@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/js2xmlparser/-/js2xmlparser-4.0.1.tgz#670ef71bc5661f089cc90481b99a05a1227ae3bd"
+ integrity sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==
+ dependencies:
+ xmlcreate "^2.0.3"
+
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
+jsdoc@^3.6.7:
+ version "3.6.7"
+ resolved "https://registry.yarnpkg.com/jsdoc/-/jsdoc-3.6.7.tgz#00431e376bed7f9de4716c6f15caa80e64492b89"
+ integrity sha512-sxKt7h0vzCd+3Y81Ey2qinupL6DpRSZJclS04ugHDNmRUXGzqicMJ6iwayhSA0S0DwwX30c5ozyUthr1QKF6uw==
+ dependencies:
+ "@babel/parser" "^7.9.4"
+ bluebird "^3.7.2"
+ catharsis "^0.9.0"
+ escape-string-regexp "^2.0.0"
+ js2xmlparser "^4.0.1"
+ klaw "^3.0.0"
+ markdown-it "^10.0.0"
+ markdown-it-anchor "^5.2.7"
+ marked "^2.0.3"
+ mkdirp "^1.0.4"
+ requizzle "^0.2.3"
+ strip-json-comments "^3.1.0"
+ taffydb "2.6.2"
+ underscore "~1.13.1"
+
json-parse-even-better-errors@^2.3.0:
version "2.3.1"
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
@@ -1950,6 +2004,13 @@ kind-of@^6.0.3:
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+klaw@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/klaw/-/klaw-3.0.0.tgz#b11bec9cf2492f06756d6e809ab73a2910259146"
+ integrity sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==
+ dependencies:
+ graceful-fs "^4.1.9"
+
lie@~3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
@@ -1962,6 +2023,13 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
+linkify-it@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf"
+ integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==
+ dependencies:
+ uc.micro "^1.0.1"
+
locate-path@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
@@ -2026,7 +2094,7 @@ lodash.set@^4.3.2:
resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=
-lodash@^4.17.15, lodash@^4.17.21, lodash@~4.17.15:
+lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21, lodash@~4.17.15:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -2080,6 +2148,32 @@ map-obj@^4.0.0:
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==
+markdown-it-anchor@^5.2.7:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz#d549acd64856a8ecd1bea58365ef385effbac744"
+ integrity sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==
+
+markdown-it@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc"
+ integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==
+ dependencies:
+ argparse "^1.0.7"
+ entities "~2.0.0"
+ linkify-it "^2.0.0"
+ mdurl "^1.0.1"
+ uc.micro "^1.0.5"
+
+marked@^2.0.3:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/marked/-/marked-2.1.3.tgz#bd017cef6431724fd4b27e0657f5ceb14bff3753"
+ integrity sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==
+
+mdurl@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
+ integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
+
meow@^8.0.0:
version "8.1.2"
resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897"
@@ -2147,6 +2241,11 @@ mkdirp@^0.5.1, mkdirp@^0.5.3:
dependencies:
minimist "^1.2.5"
+mkdirp@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
+ integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
+
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
@@ -2546,6 +2645,13 @@ require-main-filename@^2.0.0:
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+requizzle@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/requizzle/-/requizzle-0.2.3.tgz#4675c90aacafb2c036bd39ba2daa4a1cb777fded"
+ integrity sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==
+ dependencies:
+ lodash "^4.17.14"
+
resolve@^1.1.6, resolve@^1.10.0, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.3.2:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
@@ -2859,7 +2965,7 @@ strip-indent@^3.0.0:
dependencies:
min-indent "^1.0.0"
-strip-json-comments@~3.1.1:
+strip-json-comments@^3.1.0, strip-json-comments@~3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
@@ -2883,6 +2989,11 @@ supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
+taffydb@2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268"
+ integrity sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=
+
test-exclude@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
@@ -3064,6 +3175,21 @@ typescript@~4.4.0, typescript@~4.4.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
+uc.micro@^1.0.1, uc.micro@^1.0.5:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
+ integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
+
+uglify-js@^3.14.2:
+ version "3.14.2"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.2.tgz#d7dd6a46ca57214f54a2d0a43cad0f35db82ac99"
+ integrity sha512-rtPMlmcO4agTUfz10CbgJ1k6UAoXM2gWb3GoMPPZB/+/Ackf8lNWk11K4rYi2D0apgoFRLtQOZhb+/iGNJq26A==
+
+underscore@~1.13.1:
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.1.tgz#0c1c6bd2df54b6b69f2314066d65b6cde6fcf9d1"
+ integrity sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==
+
universal-github-app-jwt@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-1.1.0.tgz#0abaa876101cdf1d3e4c546be2768841c0c1b514"
@@ -3215,6 +3341,11 @@ xmlbuilder@~11.0.0:
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
+xmlcreate@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-2.0.3.tgz#df9ecd518fd3890ab3548e1b811d040614993497"
+ integrity sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==
+
xmldom@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.5.0.tgz#193cb96b84aa3486127ea6272c4596354cb4962e"