@teamscale/coverage-collector 0.1.0-beta.4 → 0.1.0-beta.6
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/dist/package.json +11 -11
- package/dist/src/App.d.ts +5 -0
- package/dist/src/App.js +26 -3
- package/dist/src/receiver/CollectingServer.d.ts +15 -0
- package/dist/src/receiver/CollectingServer.js +15 -2
- package/dist/src/storage/DataStorage.js +2 -2
- package/dist/src/upload/ArtifactoryUpload.d.ts +1 -1
- package/dist/src/upload/ArtifactoryUpload.js +1 -1
- package/dist/src/upload/CommonUpload.js +19 -12
- package/dist/src/upload/TeamscaleUpload.js +1 -1
- package/package.json +11 -11
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamscale/coverage-collector",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.6",
|
|
4
4
|
"description": "Collector for JavaScript code coverage information",
|
|
5
5
|
"main": "dist/src/main.js",
|
|
6
6
|
"bin": "dist/src/main.js",
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
"dist/**/*"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@cqse/commons": "0.1.0-beta.
|
|
25
|
+
"@cqse/commons": "0.1.0-beta.5",
|
|
26
26
|
"argparse": "^2.0.1",
|
|
27
27
|
"async": "^3.2.5",
|
|
28
|
-
"axios": "^1.6.
|
|
28
|
+
"axios": "^1.6.7",
|
|
29
29
|
"bunyan": "^1.8.15",
|
|
30
|
-
"date-and-time": "^3.1.
|
|
31
|
-
"dotenv": "^16.
|
|
30
|
+
"date-and-time": "^3.1.1",
|
|
31
|
+
"dotenv": "^16.4.5",
|
|
32
32
|
"express": "^4.18.2",
|
|
33
33
|
"form-data": "^4.0.0",
|
|
34
34
|
"mkdirp": "^3.0.1",
|
|
@@ -39,22 +39,22 @@
|
|
|
39
39
|
"ws": "^8.16.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@babel/core": "^7.23.
|
|
43
|
-
"@babel/preset-env": "^7.23.
|
|
42
|
+
"@babel/core": "^7.23.9",
|
|
43
|
+
"@babel/preset-env": "^7.23.9",
|
|
44
44
|
"@types/argparse": "^2.0.14",
|
|
45
45
|
"@types/async": "^3.2.24",
|
|
46
46
|
"@types/bunyan": "^1.8.11",
|
|
47
47
|
"@types/express": "^4.17.21",
|
|
48
|
-
"@types/jest": "^29.5.
|
|
49
|
-
"@types/node": "^20.11.
|
|
48
|
+
"@types/jest": "^29.5.12",
|
|
49
|
+
"@types/node": "^20.11.19",
|
|
50
50
|
"@types/tmp": "^0.2.6",
|
|
51
51
|
"@types/ws": "^8.5.10",
|
|
52
52
|
"babel-jest": "^29.7.0",
|
|
53
|
-
"esbuild": "^0.
|
|
53
|
+
"esbuild": "^0.20.1",
|
|
54
54
|
"jest": "^29.7.0",
|
|
55
55
|
"mockttp": "^3.10.1",
|
|
56
56
|
"rimraf": "^5.0.5",
|
|
57
|
-
"ts-jest": "^29.1.
|
|
57
|
+
"ts-jest": "^29.1.2",
|
|
58
58
|
"ts-node": "^10.9.2",
|
|
59
59
|
"typescript": "^5.3.3"
|
|
60
60
|
},
|
package/dist/src/App.d.ts
CHANGED
|
@@ -25,6 +25,11 @@ export declare class App {
|
|
|
25
25
|
static runWithConfig(config: ConfigParameters): {
|
|
26
26
|
stop: () => Promise<void>;
|
|
27
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* Starts a timer that shows a message every min that no coverage
|
|
30
|
+
* was received until the opposite is the case.
|
|
31
|
+
*/
|
|
32
|
+
private static startNoMessageTimer;
|
|
28
33
|
/**
|
|
29
34
|
* Start a timer for dumping the data, depending on the configuration.
|
|
30
35
|
*
|
package/dist/src/App.js
CHANGED
|
@@ -101,8 +101,10 @@ class App {
|
|
|
101
101
|
// Start the server socket.
|
|
102
102
|
// ATTENTION: The server is executed asynchronously
|
|
103
103
|
const serverState = server.start();
|
|
104
|
-
// Optionally, start a timer that dumps the coverage after
|
|
105
|
-
const
|
|
104
|
+
// Optionally, start a timer that dumps the coverage after N seconds
|
|
105
|
+
const dumpTimerState = this.maybeStartDumpTimer(config, storage, logger);
|
|
106
|
+
// Start a timer that informs if no coverage was received within the last minute
|
|
107
|
+
const statsTimerState = this.startNoMessageTimer(logger, server);
|
|
106
108
|
// Say bye bye on CTRL+C and exit the process
|
|
107
109
|
process.on('SIGINT', async () => {
|
|
108
110
|
// ... and do a final dump before.
|
|
@@ -113,12 +115,33 @@ class App {
|
|
|
113
115
|
return {
|
|
114
116
|
async stop() {
|
|
115
117
|
logger.info('Stopping the collector.');
|
|
116
|
-
|
|
118
|
+
dumpTimerState.stop();
|
|
119
|
+
statsTimerState.stop();
|
|
117
120
|
await controlServerState.stop();
|
|
118
121
|
serverState.stop();
|
|
119
122
|
}
|
|
120
123
|
};
|
|
121
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Starts a timer that shows a message every min that no coverage
|
|
127
|
+
* was received until the opposite is the case.
|
|
128
|
+
*/
|
|
129
|
+
static startNoMessageTimer(logger, server) {
|
|
130
|
+
const startTime = Date.now();
|
|
131
|
+
const timer = setInterval(async () => {
|
|
132
|
+
const stats = server.getStatistics();
|
|
133
|
+
if (stats.totalCoverageMessages === 0) {
|
|
134
|
+
logger.info(`No coverage received for ${((Date.now() - startTime) / 1000.0).toFixed(0)}s.`);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// We can stop running the timer after we have received the first coverage.
|
|
138
|
+
clearInterval(timer);
|
|
139
|
+
}
|
|
140
|
+
}, 1000 * 60);
|
|
141
|
+
return {
|
|
142
|
+
stop: () => clearInterval(timer)
|
|
143
|
+
};
|
|
144
|
+
}
|
|
122
145
|
/**
|
|
123
146
|
* Start a timer for dumping the data, depending on the configuration.
|
|
124
147
|
*
|
|
@@ -17,6 +17,14 @@ export declare class WebSocketCollectingServer {
|
|
|
17
17
|
* The logger to use.
|
|
18
18
|
*/
|
|
19
19
|
private readonly logger;
|
|
20
|
+
/**
|
|
21
|
+
* The number of messages that have been received.
|
|
22
|
+
*/
|
|
23
|
+
private totalNumMessagesReceived;
|
|
24
|
+
/**
|
|
25
|
+
* The number of coverage messages that have been received.
|
|
26
|
+
*/
|
|
27
|
+
private totalNumCoverageMessagesReceived;
|
|
20
28
|
/**
|
|
21
29
|
* Constructor.
|
|
22
30
|
*
|
|
@@ -55,4 +63,11 @@ export declare class WebSocketCollectingServer {
|
|
|
55
63
|
* A file name is a token; a range (start to end line) is a token.
|
|
56
64
|
*/
|
|
57
65
|
private handleCoverageMessage;
|
|
66
|
+
/**
|
|
67
|
+
* Returns a statistic on the number of messages received.
|
|
68
|
+
*/
|
|
69
|
+
getStatistics(): {
|
|
70
|
+
totalMessages: number;
|
|
71
|
+
totalCoverageMessages: number;
|
|
72
|
+
};
|
|
58
73
|
}
|
|
@@ -46,6 +46,8 @@ class WebSocketCollectingServer {
|
|
|
46
46
|
this.storage = commons_1.Contract.requireDefined(storage);
|
|
47
47
|
this.logger = commons_1.Contract.requireDefined(logger);
|
|
48
48
|
this.server = new WebSocket.Server({ port });
|
|
49
|
+
this.totalNumMessagesReceived = 0;
|
|
50
|
+
this.totalNumCoverageMessagesReceived = 0;
|
|
49
51
|
}
|
|
50
52
|
/**
|
|
51
53
|
* Start the server socket, handle sessions and dispatch messages.
|
|
@@ -56,16 +58,17 @@ class WebSocketCollectingServer {
|
|
|
56
58
|
// Handle new connections from clients
|
|
57
59
|
(_b = this.server) === null || _b === void 0 ? void 0 : _b.on('connection', (webSocket, req) => {
|
|
58
60
|
let session = new Session_1.Session(req.socket, this.storage, this.logger);
|
|
59
|
-
this.logger.
|
|
61
|
+
this.logger.trace(`Connection from: ${req.socket.remoteAddress}`);
|
|
60
62
|
// Handle disconnecting clients
|
|
61
63
|
webSocket.on('close', code => {
|
|
62
64
|
if (session) {
|
|
63
65
|
session = null;
|
|
64
|
-
this.logger.
|
|
66
|
+
this.logger.trace(`Closing with code ${code}`);
|
|
65
67
|
}
|
|
66
68
|
});
|
|
67
69
|
// Handle incoming messages
|
|
68
70
|
webSocket.on('message', (message) => {
|
|
71
|
+
this.totalNumMessagesReceived += 1;
|
|
69
72
|
if (session && Buffer.isBuffer(message)) {
|
|
70
73
|
void this.handleMessage(session, message);
|
|
71
74
|
}
|
|
@@ -93,6 +96,7 @@ class WebSocketCollectingServer {
|
|
|
93
96
|
try {
|
|
94
97
|
const messageType = message.toString('utf8', 0, 1);
|
|
95
98
|
if (messageType.startsWith(MESSAGE_TYPE_COVERAGE)) {
|
|
99
|
+
this.totalNumCoverageMessagesReceived += 1;
|
|
96
100
|
await this.handleCoverageMessage(session, message.subarray(1));
|
|
97
101
|
}
|
|
98
102
|
}
|
|
@@ -140,5 +144,14 @@ class WebSocketCollectingServer {
|
|
|
140
144
|
}
|
|
141
145
|
});
|
|
142
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Returns a statistic on the number of messages received.
|
|
149
|
+
*/
|
|
150
|
+
getStatistics() {
|
|
151
|
+
return {
|
|
152
|
+
totalMessages: this.totalNumMessagesReceived,
|
|
153
|
+
totalCoverageMessages: this.totalNumCoverageMessagesReceived
|
|
154
|
+
};
|
|
155
|
+
}
|
|
143
156
|
}
|
|
144
157
|
exports.WebSocketCollectingServer = WebSocketCollectingServer;
|
|
@@ -109,7 +109,7 @@ class DataStorage {
|
|
|
109
109
|
this.coverageByProject.set(project, projectCoverage);
|
|
110
110
|
}
|
|
111
111
|
coveredOriginalLines.forEach(line => projectCoverage === null || projectCoverage === void 0 ? void 0 : projectCoverage.putLine(sourceFilePath, line));
|
|
112
|
-
this.logger.
|
|
112
|
+
this.logger.trace(`Mapped Coverage: ${project} ${uniformPath} ${coveredOriginalLines}`);
|
|
113
113
|
}
|
|
114
114
|
/**
|
|
115
115
|
* Normalize the source file names provided by the Web browsers / from the
|
|
@@ -127,7 +127,7 @@ class DataStorage {
|
|
|
127
127
|
// Currently only implemented to log the missing information.
|
|
128
128
|
this.timesUnmappedCoverage++;
|
|
129
129
|
if (this.timesUnmappedCoverage === 1) {
|
|
130
|
-
this.logger.
|
|
130
|
+
this.logger.trace(`Received unmapped coverage for project "${project}"`);
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
/**
|
|
@@ -17,7 +17,7 @@ async function uploadToArtifactory(config, logger, coverageFile, lines) {
|
|
|
17
17
|
if (lines === 0) {
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
|
-
logger.
|
|
20
|
+
logger.debug('Preparing upload to Artifactory');
|
|
21
21
|
const form = (0, CommonUpload_1.prepareFormData)(coverageFile);
|
|
22
22
|
await performArtifactoryUpload(config, form, logger);
|
|
23
23
|
}
|
|
@@ -27,28 +27,35 @@ exports.prepareFormData = prepareFormData;
|
|
|
27
27
|
* Uploads a coverage file with the provided configuration.
|
|
28
28
|
*/
|
|
29
29
|
async function performUpload(url, form, config, uploadFunction, logger) {
|
|
30
|
+
var _a, _b;
|
|
30
31
|
try {
|
|
31
32
|
const response = await uploadFunction(url, form, config);
|
|
32
|
-
logger.
|
|
33
|
+
logger.debug(`Upload finished with code ${response.status}.`);
|
|
33
34
|
}
|
|
34
35
|
catch (error) {
|
|
35
36
|
if (axios_1.default.isAxiosError(error)) {
|
|
37
|
+
let userMessage;
|
|
38
|
+
if (error.message) {
|
|
39
|
+
logger.error(`Upload error ${(_a = error.status) !== null && _a !== void 0 ? _a : 'UNDEFINED'}: ${error.message}`);
|
|
40
|
+
}
|
|
36
41
|
if (error.response) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
42
|
+
// The request was made and the server responded with a status code
|
|
43
|
+
// that falls out of the range of 2xx
|
|
44
|
+
logger.error('Upload error response data:', error.response.data);
|
|
45
|
+
logger.error('Upload error response status:', error.response.status);
|
|
46
|
+
logger.error('Upload error response headers:', JSON.stringify(error.response.headers));
|
|
47
|
+
userMessage = `Request failed with status ${error.response.status}: ${(_b = error.response.data) !== null && _b !== void 0 ? _b : ''}`;
|
|
44
48
|
}
|
|
45
49
|
else if (error.request) {
|
|
46
|
-
|
|
50
|
+
// The request was made but no response was received
|
|
51
|
+
userMessage = 'No response received for the request.';
|
|
47
52
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
else {
|
|
54
|
+
// Something happened in setting up the request that triggered an Error
|
|
55
|
+
userMessage = 'Request setup failed.';
|
|
51
56
|
}
|
|
57
|
+
// Provide a more specific message if possible
|
|
58
|
+
throw new UploadError(`Something went wrong when uploading data: ${userMessage}`);
|
|
52
59
|
}
|
|
53
60
|
throw new UploadError(`Something went wrong when uploading data: ${(0, util_1.inspect)(error)}`);
|
|
54
61
|
}
|
|
@@ -18,7 +18,7 @@ async function uploadToTeamscale(config, logger, coverageFile, lines) {
|
|
|
18
18
|
if (lines === 0) {
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
-
logger.
|
|
21
|
+
logger.debug('Preparing upload to Teamscale');
|
|
22
22
|
const form = (0, CommonUpload_1.prepareFormData)(coverageFile);
|
|
23
23
|
const queryParameters = prepareQueryParameters(config);
|
|
24
24
|
await performTeamscaleUpload(config, queryParameters, form, logger);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamscale/coverage-collector",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.6",
|
|
4
4
|
"description": "Collector for JavaScript code coverage information",
|
|
5
5
|
"main": "dist/src/main.js",
|
|
6
6
|
"bin": "dist/src/main.js",
|
|
@@ -15,13 +15,13 @@
|
|
|
15
15
|
"dist/**/*"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@cqse/commons": "0.1.0-beta.
|
|
18
|
+
"@cqse/commons": "0.1.0-beta.5",
|
|
19
19
|
"argparse": "^2.0.1",
|
|
20
20
|
"async": "^3.2.5",
|
|
21
|
-
"axios": "^1.6.
|
|
21
|
+
"axios": "^1.6.7",
|
|
22
22
|
"bunyan": "^1.8.15",
|
|
23
|
-
"date-and-time": "^3.1.
|
|
24
|
-
"dotenv": "^16.
|
|
23
|
+
"date-and-time": "^3.1.1",
|
|
24
|
+
"dotenv": "^16.4.5",
|
|
25
25
|
"express": "^4.18.2",
|
|
26
26
|
"form-data": "^4.0.0",
|
|
27
27
|
"mkdirp": "^3.0.1",
|
|
@@ -32,22 +32,22 @@
|
|
|
32
32
|
"ws": "^8.16.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@babel/core": "^7.23.
|
|
36
|
-
"@babel/preset-env": "^7.23.
|
|
35
|
+
"@babel/core": "^7.23.9",
|
|
36
|
+
"@babel/preset-env": "^7.23.9",
|
|
37
37
|
"@types/argparse": "^2.0.14",
|
|
38
38
|
"@types/async": "^3.2.24",
|
|
39
39
|
"@types/bunyan": "^1.8.11",
|
|
40
40
|
"@types/express": "^4.17.21",
|
|
41
|
-
"@types/jest": "^29.5.
|
|
42
|
-
"@types/node": "^20.11.
|
|
41
|
+
"@types/jest": "^29.5.12",
|
|
42
|
+
"@types/node": "^20.11.19",
|
|
43
43
|
"@types/tmp": "^0.2.6",
|
|
44
44
|
"@types/ws": "^8.5.10",
|
|
45
45
|
"babel-jest": "^29.7.0",
|
|
46
|
-
"esbuild": "^0.
|
|
46
|
+
"esbuild": "^0.20.1",
|
|
47
47
|
"jest": "^29.7.0",
|
|
48
48
|
"mockttp": "^3.10.1",
|
|
49
49
|
"rimraf": "^5.0.5",
|
|
50
|
-
"ts-jest": "^29.1.
|
|
50
|
+
"ts-jest": "^29.1.2",
|
|
51
51
|
"ts-node": "^10.9.2",
|
|
52
52
|
"typescript": "^5.3.3"
|
|
53
53
|
},
|