testit-js-commons 3.7.9 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/types/config.type.d.ts +8 -0
- package/lib/common/utils/index.d.ts +1 -0
- package/lib/common/utils/index.js +1 -0
- package/lib/common/utils/tms-load-test-run-debug.d.ts +3 -0
- package/lib/common/utils/tms-load-test-run-debug.js +20 -0
- package/lib/helpers/config/config.helper.js +14 -6
- package/lib/helpers/config/config.helper.test.d.ts +1 -0
- package/lib/helpers/config/config.helper.test.js +40 -0
- package/lib/services/attachments/attachments.service.js +89 -22
- package/lib/services/index.d.ts +1 -0
- package/lib/services/index.js +1 -0
- package/lib/services/syncstorage/index.d.ts +2 -0
- package/lib/services/syncstorage/index.js +18 -0
- package/lib/services/syncstorage/syncstorage.runner.d.ts +49 -0
- package/lib/services/syncstorage/syncstorage.runner.js +350 -0
- package/lib/services/syncstorage/syncstorage.runner.test.d.ts +1 -0
- package/lib/services/syncstorage/syncstorage.runner.test.js +78 -0
- package/lib/services/syncstorage/syncstorage.type.d.ts +21 -0
- package/lib/services/syncstorage/syncstorage.type.js +19 -0
- package/lib/services/testruns/testruns.converter.d.ts +2 -0
- package/lib/services/testruns/testruns.converter.js +3 -0
- package/lib/services/testruns/testruns.service.d.ts +2 -0
- package/lib/services/testruns/testruns.service.js +62 -1
- package/lib/services/testruns/testruns.type.d.ts +2 -0
- package/lib/strategy/base.strategy.d.ts +4 -0
- package/lib/strategy/base.strategy.js +97 -2
- package/lib/sync-storage/dist/ApiClient.js +655 -0
- package/lib/sync-storage/dist/api/CompletionApi.js +114 -0
- package/lib/sync-storage/dist/api/HealthApi.js +69 -0
- package/lib/sync-storage/dist/api/SystemApi.js +69 -0
- package/lib/sync-storage/dist/api/TestResultsApi.js +122 -0
- package/lib/sync-storage/dist/api/WorkersApi.js +113 -0
- package/lib/sync-storage/dist/index.js +118 -0
- package/lib/sync-storage/dist/model/CompletionResponse.js +86 -0
- package/lib/sync-storage/dist/model/HealthStatusResponse.js +86 -0
- package/lib/sync-storage/dist/model/InProgressPublishedResponse.js +74 -0
- package/lib/sync-storage/dist/model/RegisterRequest.js +114 -0
- package/lib/sync-storage/dist/model/RegisterResponse.js +122 -0
- package/lib/sync-storage/dist/model/SetWorkerStatusRequest.js +102 -0
- package/lib/sync-storage/dist/model/SetWorkerStatusResponse.js +90 -0
- package/lib/sync-storage/dist/model/ShutdownResponse.js +90 -0
- package/lib/sync-storage/dist/model/TestResultCutApiModel.js +122 -0
- package/lib/sync-storage/dist/model/TestResultSaveResponse.js +90 -0
- package/lib/sync-storage/index.d.ts +772 -0
- package/package.json +7 -4
|
@@ -10,6 +10,8 @@ export interface CliOptions {
|
|
|
10
10
|
tmsConfigFile: string;
|
|
11
11
|
tmsAutomaticCreationTestCases: boolean;
|
|
12
12
|
tmsAutomaticUpdationLinksToTestCases: boolean;
|
|
13
|
+
tmsSyncStorageEnabled: boolean;
|
|
14
|
+
tmsSyncStoragePort: string;
|
|
13
15
|
}
|
|
14
16
|
export interface EnvironmentOptions {
|
|
15
17
|
TMS_URL: string;
|
|
@@ -23,6 +25,8 @@ export interface EnvironmentOptions {
|
|
|
23
25
|
TMS_AUTOMATIC_CREATION_TEST_CASES: string;
|
|
24
26
|
TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES: string;
|
|
25
27
|
TMS_CERT_VALIDATION: string;
|
|
28
|
+
TMS_SYNC_STORAGE_ENABLED: string;
|
|
29
|
+
TMS_SYNC_STORAGE_PORT: string;
|
|
26
30
|
}
|
|
27
31
|
export interface ProcessEnvOptions {
|
|
28
32
|
TMS_URL?: string;
|
|
@@ -36,6 +40,8 @@ export interface ProcessEnvOptions {
|
|
|
36
40
|
TMS_AUTOMATIC_CREATION_TEST_CASES?: string;
|
|
37
41
|
TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES?: string;
|
|
38
42
|
TMS_CERT_VALIDATION?: string;
|
|
43
|
+
TMS_SYNC_STORAGE_ENABLED?: string;
|
|
44
|
+
TMS_SYNC_STORAGE_PORT?: string;
|
|
39
45
|
}
|
|
40
46
|
export interface AdapterConfig {
|
|
41
47
|
url: string;
|
|
@@ -48,4 +54,6 @@ export interface AdapterConfig {
|
|
|
48
54
|
automaticCreationTestCases?: boolean;
|
|
49
55
|
automaticUpdationLinksToTestCases?: boolean;
|
|
50
56
|
certValidation?: boolean;
|
|
57
|
+
syncStorageEnabled?: boolean;
|
|
58
|
+
syncStoragePort?: string;
|
|
51
59
|
}
|
|
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./utils"), exports);
|
|
18
18
|
__exportStar(require("./html-escape.util"), exports);
|
|
19
|
+
__exportStar(require("./tms-load-test-run-debug"), exports);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Set `TMS_DEBUG_LOAD_TEST_RUN=1` (or `true`) for loadTestRun / TMS result POST tracing. */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.isTmsLoadTestRunDebug = isTmsLoadTestRunDebug;
|
|
5
|
+
exports.logTmsLoadTestRun = logTmsLoadTestRun;
|
|
6
|
+
function isTmsLoadTestRunDebug() {
|
|
7
|
+
const v = process.env.TMS_DEBUG_LOAD_TEST_RUN;
|
|
8
|
+
return v === "1" || (v === null || v === void 0 ? void 0 : v.toLowerCase()) === "true";
|
|
9
|
+
}
|
|
10
|
+
function logTmsLoadTestRun(message, data) {
|
|
11
|
+
if (!isTmsLoadTestRunDebug()) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (data && Object.keys(data).length > 0) {
|
|
15
|
+
console.log(`[testit-js-commons:loadTestRun] ${message}`, data);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
console.log(`[testit-js-commons:loadTestRun] ${message}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -61,7 +61,7 @@ class ConfigComposer {
|
|
|
61
61
|
return config;
|
|
62
62
|
}
|
|
63
63
|
mergeAll(file, env, base) {
|
|
64
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
64
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
65
65
|
return {
|
|
66
66
|
url: this.resolveAllProperties(file.url, env === null || env === void 0 ? void 0 : env.TMS_URL, base === null || base === void 0 ? void 0 : base.url),
|
|
67
67
|
projectId: this.resolveAllProperties(file.projectId, env === null || env === void 0 ? void 0 : env.TMS_PROJECT_ID, base === null || base === void 0 ? void 0 : base.projectId),
|
|
@@ -72,11 +72,13 @@ class ConfigComposer {
|
|
|
72
72
|
configurationId: this.resolveAllProperties(file.configurationId, env === null || env === void 0 ? void 0 : env.TMS_CONFIGURATION_ID, base === null || base === void 0 ? void 0 : base.configurationId),
|
|
73
73
|
automaticCreationTestCases: (_f = (_e = (_d = file.automaticCreationTestCases) !== null && _d !== void 0 ? _d : stringToBoolean(env === null || env === void 0 ? void 0 : env.TMS_AUTOMATIC_CREATION_TEST_CASES)) !== null && _e !== void 0 ? _e : base === null || base === void 0 ? void 0 : base.automaticCreationTestCases) !== null && _f !== void 0 ? _f : false,
|
|
74
74
|
automaticUpdationLinksToTestCases: (_j = (_h = (_g = file.automaticUpdationLinksToTestCases) !== null && _g !== void 0 ? _g : stringToBoolean(env === null || env === void 0 ? void 0 : env.TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES)) !== null && _h !== void 0 ? _h : base === null || base === void 0 ? void 0 : base.automaticUpdationLinksToTestCases) !== null && _j !== void 0 ? _j : false,
|
|
75
|
-
certValidation: (_m = (_l = (_k = file.certValidation) !== null && _k !== void 0 ? _k : stringToBoolean(env === null || env === void 0 ? void 0 : env.TMS_CERT_VALIDATION)) !== null && _l !== void 0 ? _l : base === null || base === void 0 ? void 0 : base.certValidation) !== null && _m !== void 0 ? _m : true
|
|
75
|
+
certValidation: (_m = (_l = (_k = file.certValidation) !== null && _k !== void 0 ? _k : stringToBoolean(env === null || env === void 0 ? void 0 : env.TMS_CERT_VALIDATION)) !== null && _l !== void 0 ? _l : base === null || base === void 0 ? void 0 : base.certValidation) !== null && _m !== void 0 ? _m : true,
|
|
76
|
+
syncStorageEnabled: (_q = (_p = (_o = file.syncStorageEnabled) !== null && _o !== void 0 ? _o : stringToBoolean(env === null || env === void 0 ? void 0 : env.TMS_SYNC_STORAGE_ENABLED)) !== null && _p !== void 0 ? _p : base === null || base === void 0 ? void 0 : base.syncStorageEnabled) !== null && _q !== void 0 ? _q : true,
|
|
77
|
+
syncStoragePort: this.resolveAllProperties(file.syncStoragePort, env === null || env === void 0 ? void 0 : env.TMS_SYNC_STORAGE_PORT, base === null || base === void 0 ? void 0 : base.syncStoragePort) || "49152",
|
|
76
78
|
};
|
|
77
79
|
}
|
|
78
80
|
merge(env, base) {
|
|
79
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
81
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
80
82
|
return {
|
|
81
83
|
url: this.resolveProperties(env === null || env === void 0 ? void 0 : env.TMS_URL, base === null || base === void 0 ? void 0 : base.url),
|
|
82
84
|
projectId: this.resolveProperties(env === null || env === void 0 ? void 0 : env.TMS_PROJECT_ID, base === null || base === void 0 ? void 0 : base.projectId),
|
|
@@ -87,11 +89,13 @@ class ConfigComposer {
|
|
|
87
89
|
configurationId: this.resolveProperties(env === null || env === void 0 ? void 0 : env.TMS_CONFIGURATION_ID, base === null || base === void 0 ? void 0 : base.configurationId),
|
|
88
90
|
automaticCreationTestCases: (_d = (_c = stringToBoolean(env === null || env === void 0 ? void 0 : env.TMS_AUTOMATIC_CREATION_TEST_CASES)) !== null && _c !== void 0 ? _c : base === null || base === void 0 ? void 0 : base.automaticCreationTestCases) !== null && _d !== void 0 ? _d : false,
|
|
89
91
|
automaticUpdationLinksToTestCases: (_f = (_e = stringToBoolean(env === null || env === void 0 ? void 0 : env.TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES)) !== null && _e !== void 0 ? _e : base === null || base === void 0 ? void 0 : base.automaticUpdationLinksToTestCases) !== null && _f !== void 0 ? _f : false,
|
|
90
|
-
certValidation: (_h = (_g = stringToBoolean(env === null || env === void 0 ? void 0 : env.TMS_CERT_VALIDATION)) !== null && _g !== void 0 ? _g : base === null || base === void 0 ? void 0 : base.certValidation) !== null && _h !== void 0 ? _h : true
|
|
92
|
+
certValidation: (_h = (_g = stringToBoolean(env === null || env === void 0 ? void 0 : env.TMS_CERT_VALIDATION)) !== null && _g !== void 0 ? _g : base === null || base === void 0 ? void 0 : base.certValidation) !== null && _h !== void 0 ? _h : true,
|
|
93
|
+
syncStorageEnabled: (_k = (_j = stringToBoolean(env === null || env === void 0 ? void 0 : env.TMS_SYNC_STORAGE_ENABLED)) !== null && _j !== void 0 ? _j : base === null || base === void 0 ? void 0 : base.syncStorageEnabled) !== null && _k !== void 0 ? _k : true,
|
|
94
|
+
syncStoragePort: this.resolveProperties(env === null || env === void 0 ? void 0 : env.TMS_SYNC_STORAGE_PORT, base === null || base === void 0 ? void 0 : base.syncStoragePort) || "49152",
|
|
91
95
|
};
|
|
92
96
|
}
|
|
93
97
|
mergeEnv(dotEnv, processEnv) {
|
|
94
|
-
var _a, _b, _c, _d;
|
|
98
|
+
var _a, _b, _c, _d, _e;
|
|
95
99
|
return {
|
|
96
100
|
TMS_URL: this.resolveProperties(dotEnv === null || dotEnv === void 0 ? void 0 : dotEnv.TMS_URL, processEnv === null || processEnv === void 0 ? void 0 : processEnv.TMS_URL),
|
|
97
101
|
TMS_PROJECT_ID: this.resolveProperties(dotEnv === null || dotEnv === void 0 ? void 0 : dotEnv.TMS_PROJECT_ID, processEnv === null || processEnv === void 0 ? void 0 : processEnv.TMS_PROJECT_ID),
|
|
@@ -102,7 +106,9 @@ class ConfigComposer {
|
|
|
102
106
|
TMS_CONFIGURATION_ID: this.resolveProperties(dotEnv === null || dotEnv === void 0 ? void 0 : dotEnv.TMS_CONFIGURATION_ID, processEnv === null || processEnv === void 0 ? void 0 : processEnv.TMS_CONFIGURATION_ID),
|
|
103
107
|
TMS_AUTOMATIC_CREATION_TEST_CASES: (_b = dotEnv === null || dotEnv === void 0 ? void 0 : dotEnv.TMS_AUTOMATIC_CREATION_TEST_CASES) !== null && _b !== void 0 ? _b : processEnv === null || processEnv === void 0 ? void 0 : processEnv.TMS_AUTOMATIC_CREATION_TEST_CASES,
|
|
104
108
|
TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES: (_c = dotEnv === null || dotEnv === void 0 ? void 0 : dotEnv.TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES) !== null && _c !== void 0 ? _c : processEnv === null || processEnv === void 0 ? void 0 : processEnv.TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES,
|
|
105
|
-
TMS_CERT_VALIDATION: (_d = dotEnv === null || dotEnv === void 0 ? void 0 : dotEnv.TMS_CERT_VALIDATION) !== null && _d !== void 0 ? _d : processEnv === null || processEnv === void 0 ? void 0 : processEnv.TMS_CERT_VALIDATION
|
|
109
|
+
TMS_CERT_VALIDATION: (_d = dotEnv === null || dotEnv === void 0 ? void 0 : dotEnv.TMS_CERT_VALIDATION) !== null && _d !== void 0 ? _d : processEnv === null || processEnv === void 0 ? void 0 : processEnv.TMS_CERT_VALIDATION,
|
|
110
|
+
TMS_SYNC_STORAGE_ENABLED: (_e = dotEnv === null || dotEnv === void 0 ? void 0 : dotEnv.TMS_SYNC_STORAGE_ENABLED) !== null && _e !== void 0 ? _e : processEnv === null || processEnv === void 0 ? void 0 : processEnv.TMS_SYNC_STORAGE_ENABLED,
|
|
111
|
+
TMS_SYNC_STORAGE_PORT: this.resolveProperties(dotEnv === null || dotEnv === void 0 ? void 0 : dotEnv.TMS_SYNC_STORAGE_PORT, processEnv === null || processEnv === void 0 ? void 0 : processEnv.TMS_SYNC_STORAGE_PORT),
|
|
106
112
|
};
|
|
107
113
|
}
|
|
108
114
|
resolveAllProperties(file, env, base) {
|
|
@@ -180,6 +186,8 @@ function parseProcessEnvConfig() {
|
|
|
180
186
|
TMS_AUTOMATIC_CREATION_TEST_CASES: process.env.TMS_AUTOMATIC_CREATION_TEST_CASES,
|
|
181
187
|
TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES: process.env.TMS_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES,
|
|
182
188
|
TMS_CONFIG_FILE: process.env.TMS_PRIVATE_TOKEN,
|
|
189
|
+
TMS_SYNC_STORAGE_ENABLED: process.env.TMS_SYNC_STORAGE_ENABLED,
|
|
190
|
+
TMS_SYNC_STORAGE_PORT: process.env.TMS_SYNC_STORAGE_PORT,
|
|
183
191
|
};
|
|
184
192
|
}
|
|
185
193
|
function stringToAdapterMode(str) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const config_helper_1 = require("./config.helper");
|
|
4
|
+
describe("ConfigComposer sync-storage defaults", () => {
|
|
5
|
+
const env = process.env;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
jest.resetModules();
|
|
8
|
+
process.env = Object.assign({}, env);
|
|
9
|
+
delete process.env.TMS_SYNC_STORAGE_ENABLED;
|
|
10
|
+
delete process.env.TMS_SYNC_STORAGE_PORT;
|
|
11
|
+
});
|
|
12
|
+
afterAll(() => {
|
|
13
|
+
process.env = env;
|
|
14
|
+
});
|
|
15
|
+
it("should enable sync-storage by default", () => {
|
|
16
|
+
const config = new config_helper_1.ConfigComposer().merge(undefined, {
|
|
17
|
+
url: "http://localhost:8080",
|
|
18
|
+
privateToken: "token",
|
|
19
|
+
projectId: "11111111-1111-1111-1111-111111111111",
|
|
20
|
+
configurationId: "22222222-2222-2222-2222-222222222222",
|
|
21
|
+
testRunId: "33333333-3333-3333-3333-333333333333",
|
|
22
|
+
});
|
|
23
|
+
expect(config.syncStorageEnabled).toBe(true);
|
|
24
|
+
expect(config.syncStoragePort).toBe("49152");
|
|
25
|
+
});
|
|
26
|
+
it("should allow disabling sync-storage via env", () => {
|
|
27
|
+
const config = new config_helper_1.ConfigComposer().merge({
|
|
28
|
+
TMS_SYNC_STORAGE_ENABLED: "false",
|
|
29
|
+
TMS_SYNC_STORAGE_PORT: "59999",
|
|
30
|
+
}, {
|
|
31
|
+
url: "http://localhost:8080",
|
|
32
|
+
privateToken: "token",
|
|
33
|
+
projectId: "11111111-1111-1111-1111-111111111111",
|
|
34
|
+
configurationId: "22222222-2222-2222-2222-222222222222",
|
|
35
|
+
testRunId: "33333333-3333-3333-3333-333333333333",
|
|
36
|
+
});
|
|
37
|
+
expect(config.syncStorageEnabled).toBe(false);
|
|
38
|
+
expect(config.syncStoragePort).toBe("59999");
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -48,42 +48,103 @@ const TestitApiClient = __importStar(require("testit-api-client"));
|
|
|
48
48
|
const common_1 = require("../../common");
|
|
49
49
|
const buffer_1 = require("buffer");
|
|
50
50
|
const fs = __importStar(require("fs"));
|
|
51
|
+
const UPLOAD_MAX_ATTEMPTS = 5;
|
|
52
|
+
const UPLOAD_RETRY_BASE_MS = 500;
|
|
53
|
+
/** Minimum HTTP timeout for attachment POST (ms); reduces false timeouts on slow TLS. */
|
|
54
|
+
const UPLOAD_CLIENT_TIMEOUT_MS = 120000;
|
|
55
|
+
function sleep(ms) {
|
|
56
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
57
|
+
}
|
|
58
|
+
function unwrapAttachmentError(err) {
|
|
59
|
+
if (!err || typeof err !== "object") {
|
|
60
|
+
return err;
|
|
61
|
+
}
|
|
62
|
+
const nested = err.error;
|
|
63
|
+
if (nested instanceof Error || (nested && typeof nested === "object")) {
|
|
64
|
+
return nested;
|
|
65
|
+
}
|
|
66
|
+
const cause = err.cause;
|
|
67
|
+
if (cause instanceof Error || (cause && typeof cause === "object")) {
|
|
68
|
+
return cause;
|
|
69
|
+
}
|
|
70
|
+
return err;
|
|
71
|
+
}
|
|
72
|
+
function isTransientAttachmentError(err) {
|
|
73
|
+
var _a, _b, _c, _d, _e;
|
|
74
|
+
const e = unwrapAttachmentError(err);
|
|
75
|
+
const status = (_b = (_a = e === null || e === void 0 ? void 0 : e.response) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : (_c = err === null || err === void 0 ? void 0 : err.response) === null || _c === void 0 ? void 0 : _c.status;
|
|
76
|
+
if (typeof status === "number" && status >= 400 && status < 500)
|
|
77
|
+
return false;
|
|
78
|
+
if (typeof status === "number" && status >= 500)
|
|
79
|
+
return true;
|
|
80
|
+
const code = (_d = e === null || e === void 0 ? void 0 : e.code) !== null && _d !== void 0 ? _d : err === null || err === void 0 ? void 0 : err.code;
|
|
81
|
+
if (code === "ECONNRESET" || code === "ETIMEDOUT" || code === "EPIPE" || code === "ECONNABORTED")
|
|
82
|
+
return true;
|
|
83
|
+
if ((e === null || e === void 0 ? void 0 : e.errno) === -104 || (err === null || err === void 0 ? void 0 : err.errno) === -104)
|
|
84
|
+
return true;
|
|
85
|
+
const msg = (_e = e === null || e === void 0 ? void 0 : e.message) !== null && _e !== void 0 ? _e : err === null || err === void 0 ? void 0 : err.message;
|
|
86
|
+
if (typeof msg === "string" && /socket hang up|ECONNRESET|ETIMEDOUT|ECONNREFUSED|read ECONNRESET/i.test(msg)) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
function withUploadRetry(fn) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
let last;
|
|
94
|
+
for (let attempt = 1; attempt <= UPLOAD_MAX_ATTEMPTS; attempt++) {
|
|
95
|
+
try {
|
|
96
|
+
return yield fn();
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
last = e;
|
|
100
|
+
if (!isTransientAttachmentError(e) || attempt === UPLOAD_MAX_ATTEMPTS) {
|
|
101
|
+
throw e;
|
|
102
|
+
}
|
|
103
|
+
yield sleep(UPLOAD_RETRY_BASE_MS * attempt);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
throw last;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
51
109
|
class AttachmentsService extends common_1.BaseService {
|
|
52
110
|
constructor(config) {
|
|
53
111
|
super(config);
|
|
54
112
|
this.config = config;
|
|
55
113
|
this._client = new TestitApiClient.AttachmentsApi();
|
|
56
|
-
// Set the base path from config if provided
|
|
57
114
|
if (this.config.url) {
|
|
58
115
|
this._client.apiClient.basePath = this.config.url.replace(/\/+$/, "");
|
|
59
116
|
}
|
|
117
|
+
const t = this._client.apiClient.timeout;
|
|
118
|
+
this._client.apiClient.timeout = Math.max(typeof t === "number" ? t : 60000, UPLOAD_CLIENT_TIMEOUT_MS);
|
|
60
119
|
}
|
|
61
120
|
uploadTextAttachment(content, filename) {
|
|
62
121
|
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
-
// Create a Buffer for the content
|
|
64
122
|
const bufferContent = typeof content === "string" ? buffer_1.Buffer.from(content, "utf-8") : content;
|
|
65
123
|
const fileName = filename !== null && filename !== void 0 ? filename : common_1.Utils.generateFileName();
|
|
66
124
|
try {
|
|
67
|
-
// Try to create a temporary file with the correct name to workaround filename issue
|
|
68
125
|
const tempDir = common_1.Utils.createTempDir();
|
|
69
126
|
const tempFilePath = `${tempDir}/${fileName}`;
|
|
70
127
|
try {
|
|
71
|
-
// Write buffer to temporary file
|
|
72
128
|
fs.writeFileSync(tempFilePath, bufferContent);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
129
|
+
const id = yield withUploadRetry(() => __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
const fileStream = fs.createReadStream(tempFilePath);
|
|
131
|
+
try {
|
|
132
|
+
// @ts-ignore
|
|
133
|
+
const response = yield this._client.apiV2AttachmentsPost({ file: fileStream });
|
|
134
|
+
const data = response.body || response;
|
|
135
|
+
return data.id;
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
fileStream.destroy();
|
|
139
|
+
}
|
|
140
|
+
}));
|
|
141
|
+
return [{ id }];
|
|
79
142
|
}
|
|
80
143
|
finally {
|
|
81
|
-
// Clean up temporary file and directory
|
|
82
144
|
try {
|
|
83
145
|
if (fs.existsSync(tempFilePath)) {
|
|
84
146
|
fs.unlinkSync(tempFilePath);
|
|
85
147
|
}
|
|
86
|
-
// Try to remove the temp directory
|
|
87
148
|
if (fs.existsSync(tempDir)) {
|
|
88
149
|
fs.rmdirSync(tempDir);
|
|
89
150
|
}
|
|
@@ -107,18 +168,25 @@ class AttachmentsService extends common_1.BaseService {
|
|
|
107
168
|
}
|
|
108
169
|
uploadAttachments(paths) {
|
|
109
170
|
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
-
const attachmentIds =
|
|
171
|
+
const attachmentIds = [];
|
|
172
|
+
for (const path of paths) {
|
|
111
173
|
try {
|
|
112
|
-
// Verify file exists
|
|
113
174
|
if (!fs.existsSync(path)) {
|
|
114
175
|
throw new Error(`File not found: ${path}`);
|
|
115
176
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
177
|
+
const id = yield withUploadRetry(() => __awaiter(this, void 0, void 0, function* () {
|
|
178
|
+
const fileStream = common_1.Utils.readStream(path);
|
|
179
|
+
try {
|
|
180
|
+
// @ts-ignore
|
|
181
|
+
const response = yield this._client.apiV2AttachmentsPost({ file: fileStream });
|
|
182
|
+
const data = response.body || response;
|
|
183
|
+
return data.id;
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
fileStream.destroy();
|
|
187
|
+
}
|
|
188
|
+
}));
|
|
189
|
+
attachmentIds.push(id);
|
|
122
190
|
}
|
|
123
191
|
catch (error) {
|
|
124
192
|
console.error(`Error uploading attachment ${path}:`, error);
|
|
@@ -130,8 +198,7 @@ class AttachmentsService extends common_1.BaseService {
|
|
|
130
198
|
}
|
|
131
199
|
throw error;
|
|
132
200
|
}
|
|
133
|
-
}
|
|
134
|
-
// Convert array of IDs to array of Attachment objects
|
|
201
|
+
}
|
|
135
202
|
return attachmentIds.map((id) => ({ id }));
|
|
136
203
|
});
|
|
137
204
|
}
|
package/lib/services/index.d.ts
CHANGED
package/lib/services/index.js
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./syncstorage.runner"), exports);
|
|
18
|
+
__exportStar(require("./syncstorage.type"), exports);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { AdapterConfig } from "../../common";
|
|
2
|
+
import { ISyncStorageRunner, TestResultCutModel, WorkerStatus } from "./syncstorage.type";
|
|
3
|
+
export declare class SyncStorageRunner implements ISyncStorageRunner {
|
|
4
|
+
private readonly testRunId;
|
|
5
|
+
private readonly config;
|
|
6
|
+
private static readonly VERSION;
|
|
7
|
+
private static readonly STARTUP_TIMEOUT_MS;
|
|
8
|
+
private static readonly STARTUP_POLL_MS;
|
|
9
|
+
private static readonly PROCESS_WARMUP_MS;
|
|
10
|
+
private static readonly REQUEST_TIMEOUT_MS;
|
|
11
|
+
private static readonly RETRY_COUNT;
|
|
12
|
+
private static readonly IN_PROGRESS_POLL_MS;
|
|
13
|
+
private static readonly REPO_BASE;
|
|
14
|
+
private readonly workerPid;
|
|
15
|
+
private readonly baseUrl;
|
|
16
|
+
private readonly serviceUrl;
|
|
17
|
+
private readonly port;
|
|
18
|
+
private isMaster;
|
|
19
|
+
private alreadyInProgress;
|
|
20
|
+
private inProgressPublishing;
|
|
21
|
+
private running;
|
|
22
|
+
private syncStorageProcess?;
|
|
23
|
+
private readonly healthApi;
|
|
24
|
+
private readonly workersApi;
|
|
25
|
+
private readonly testResultsApi;
|
|
26
|
+
private readonly completionApi;
|
|
27
|
+
private readonly registerRequestModel;
|
|
28
|
+
private readonly setWorkerStatusRequestModel;
|
|
29
|
+
private readonly testResultCutModel;
|
|
30
|
+
constructor(testRunId: string, config: AdapterConfig);
|
|
31
|
+
start(): Promise<boolean>;
|
|
32
|
+
isActive(): boolean;
|
|
33
|
+
isMasterWorker(): boolean;
|
|
34
|
+
isAlreadyInProgress(): boolean;
|
|
35
|
+
waitForInProgressPublished(timeoutMs: number): Promise<boolean>;
|
|
36
|
+
sendInProgressTestResult(model: TestResultCutModel): Promise<boolean>;
|
|
37
|
+
setWorkerStatus(status: WorkerStatus): Promise<void>;
|
|
38
|
+
completeProcessing(): Promise<void>;
|
|
39
|
+
private healthcheck;
|
|
40
|
+
private startLocalProcess;
|
|
41
|
+
private waitForStartup;
|
|
42
|
+
private prepareExecutable;
|
|
43
|
+
private getBinaryName;
|
|
44
|
+
private getOsPart;
|
|
45
|
+
private getArchPart;
|
|
46
|
+
private downloadFile;
|
|
47
|
+
private delay;
|
|
48
|
+
private withRetry;
|
|
49
|
+
}
|