testdriverai 7.2.57 → 7.2.59
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/.github/workflows/publish.yaml +59 -43
- package/CHANGELOG.md +14 -0
- package/lib/sentry.js +91 -71
- package/package.json +1 -1
|
@@ -1,52 +1,68 @@
|
|
|
1
1
|
name: Publish
|
|
2
2
|
permissions:
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
contents: write
|
|
4
|
+
id-token: write # Required for OIDC
|
|
5
5
|
on:
|
|
6
6
|
push:
|
|
7
|
-
branches: [
|
|
7
|
+
branches: [main]
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
10
|
publish:
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
steps:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
with:
|
|
16
|
+
fetch-depth: 0
|
|
17
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
18
|
+
|
|
19
|
+
- name: Setup Node.js
|
|
20
|
+
uses: actions/setup-node@v4
|
|
21
|
+
with:
|
|
22
|
+
node-version: "20"
|
|
23
|
+
registry-url: "https://registry.npmjs.org/"
|
|
24
|
+
|
|
25
|
+
- name: Configure Git
|
|
26
|
+
run: |
|
|
27
|
+
git config user.name "github-actions[bot]"
|
|
28
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
29
|
+
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: npm ci
|
|
32
|
+
|
|
33
|
+
- name: Bump version (patch)
|
|
34
|
+
run: npm version patch --no-git-tag-version
|
|
35
|
+
|
|
36
|
+
- name: Generate Changelog
|
|
37
|
+
run: |
|
|
38
|
+
npx conventional-changelog-cli -p angular -i CHANGELOG.md -s
|
|
39
|
+
git add CHANGELOG.md
|
|
40
|
+
|
|
41
|
+
- name: Commit and push version bump
|
|
42
|
+
run: |
|
|
43
|
+
git add package.json package-lock.json
|
|
44
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
45
|
+
git commit -m "chore(release): ${VERSION}"
|
|
46
|
+
git tag "v${VERSION}"
|
|
47
|
+
git push origin main
|
|
48
|
+
git push origin "v${VERSION}"
|
|
49
|
+
echo "VERSION=${VERSION}" >> $GITHUB_ENV
|
|
50
|
+
|
|
51
|
+
- name: Create GitHub Release
|
|
52
|
+
uses: softprops/action-gh-release@v1
|
|
53
|
+
with:
|
|
54
|
+
tag_name: v${{ env.VERSION }}
|
|
55
|
+
generate_release_notes: true
|
|
56
|
+
prerelease: false
|
|
57
|
+
|
|
58
|
+
- name: Debug NPM Token
|
|
59
|
+
run: |
|
|
60
|
+
echo "NPM_TOKEN is set: ${{ secrets.NPM_TOKEN != '' }}"
|
|
61
|
+
echo "NPM_TOKEN first 4 chars: ${NPM_TOKEN:0:4}..."
|
|
62
|
+
env:
|
|
63
|
+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
64
|
+
|
|
65
|
+
- name: Publish to npm
|
|
66
|
+
run: npm publish --tag beta
|
|
67
|
+
env:
|
|
68
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
## [7.2.59](https://github.com/testdriverai/testdriverai/compare/v7.2.58...v7.2.59) (2026-01-27)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
## [7.2.58](https://github.com/testdriverai/testdriverai/compare/v6.1.8...v7.2.58) (2026-01-27)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Reverts
|
|
9
|
+
|
|
10
|
+
* Revert "list dashcam version g" ([5037571](https://github.com/testdriverai/testdriverai/commit/5037571440c33f8966104874c542c6c57a809510))
|
|
11
|
+
* Revert "update discord invite" ([b5a9b99](https://github.com/testdriverai/testdriverai/commit/b5a9b9955cf2b0b07fd0ebeb6abf65f89cd3d5a8))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
package/lib/sentry.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* This module initializes Sentry for error tracking and performance monitoring.
|
|
5
5
|
* It should be required at the very beginning of the CLI entry point.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* Distributed Tracing:
|
|
8
8
|
* The CLI uses session-based trace IDs (MD5 hash of session ID) to link
|
|
9
9
|
* CLI traces with API traces. Call setSessionTraceContext() after establishing
|
|
@@ -23,7 +23,6 @@ let currentSessionId = null;
|
|
|
23
23
|
let emitterAttached = false;
|
|
24
24
|
|
|
25
25
|
const isEnabled = () => {
|
|
26
|
-
|
|
27
26
|
// Disable if explicitly disabled
|
|
28
27
|
if (process.env.TD_TELEMETRY === "false") {
|
|
29
28
|
return false;
|
|
@@ -32,19 +31,17 @@ const isEnabled = () => {
|
|
|
32
31
|
};
|
|
33
32
|
|
|
34
33
|
if (isEnabled()) {
|
|
34
|
+
console.log("Analytics enabled. Set TD_TELEMETRY=false to disable.");
|
|
35
35
|
Sentry.init({
|
|
36
36
|
dsn:
|
|
37
37
|
process.env.SENTRY_DSN ||
|
|
38
38
|
"https://452bd5a00dbd83a38ee8813e11c57694@o4510262629236736.ingest.us.sentry.io/4510480443637760",
|
|
39
|
-
environment:
|
|
39
|
+
environment: "sdk",
|
|
40
40
|
release: `testdriverai@${version}`,
|
|
41
41
|
sampleRate: 1.0,
|
|
42
42
|
tracesSampleRate: 1.0, // Sample 20% of transactions for performance
|
|
43
43
|
enableLogs: true,
|
|
44
|
-
integrations: [
|
|
45
|
-
Sentry.httpIntegration(),
|
|
46
|
-
Sentry.nodeContextIntegration(),
|
|
47
|
-
],
|
|
44
|
+
integrations: [Sentry.httpIntegration(), Sentry.nodeContextIntegration()],
|
|
48
45
|
// Set initial context
|
|
49
46
|
initialScope: {
|
|
50
47
|
tags: {
|
|
@@ -55,9 +52,6 @@ if (isEnabled()) {
|
|
|
55
52
|
},
|
|
56
53
|
// Filter out common non-errors
|
|
57
54
|
beforeSend(event, hint) {
|
|
58
|
-
|
|
59
|
-
console.log('sending sentry event', event);
|
|
60
|
-
|
|
61
55
|
const error = hint.originalException;
|
|
62
56
|
|
|
63
57
|
// Don't send user-initiated exits
|
|
@@ -116,7 +110,7 @@ function captureException(error, context = {}) {
|
|
|
116
110
|
session_id: currentSessionId,
|
|
117
111
|
});
|
|
118
112
|
}
|
|
119
|
-
|
|
113
|
+
|
|
120
114
|
if (context.tags) {
|
|
121
115
|
Object.entries(context.tags).forEach(([key, value]) => {
|
|
122
116
|
scope.setTag(key, value);
|
|
@@ -138,7 +132,7 @@ function captureException(error, context = {}) {
|
|
|
138
132
|
*/
|
|
139
133
|
function captureMessage(message, level = "info") {
|
|
140
134
|
if (!isEnabled()) return;
|
|
141
|
-
|
|
135
|
+
|
|
142
136
|
Sentry.withScope((scope) => {
|
|
143
137
|
// Link to session trace if available
|
|
144
138
|
if (currentTraceId && currentSessionId) {
|
|
@@ -159,19 +153,19 @@ function captureMessage(message, level = "info") {
|
|
|
159
153
|
*/
|
|
160
154
|
function setSessionTraceContext(sessionId) {
|
|
161
155
|
if (!isEnabled() || !sessionId) return;
|
|
162
|
-
|
|
156
|
+
|
|
163
157
|
// Derive trace ID from session ID (same algorithm as API)
|
|
164
158
|
currentTraceId = crypto.createHash("md5").update(sessionId).digest("hex");
|
|
165
159
|
currentSessionId = sessionId;
|
|
166
|
-
|
|
160
|
+
|
|
167
161
|
// Set as global tag so all events include it
|
|
168
162
|
Sentry.setTag("session", sessionId);
|
|
169
163
|
Sentry.setTag("trace_id", currentTraceId);
|
|
170
|
-
|
|
164
|
+
|
|
171
165
|
// Try to set propagation context for trace linking (may not be available in all versions)
|
|
172
166
|
try {
|
|
173
167
|
const scope = Sentry.getCurrentScope();
|
|
174
|
-
if (scope && typeof scope.setPropagationContext ===
|
|
168
|
+
if (scope && typeof scope.setPropagationContext === "function") {
|
|
175
169
|
scope.setPropagationContext({
|
|
176
170
|
traceId: currentTraceId,
|
|
177
171
|
spanId: currentTraceId.substring(0, 16),
|
|
@@ -180,7 +174,7 @@ function setSessionTraceContext(sessionId) {
|
|
|
180
174
|
}
|
|
181
175
|
} catch (e) {
|
|
182
176
|
// Ignore errors - propagation context may not be supported
|
|
183
|
-
console.log(
|
|
177
|
+
console.log("Could not set propagation context:", e.message);
|
|
184
178
|
}
|
|
185
179
|
}
|
|
186
180
|
|
|
@@ -205,104 +199,130 @@ function getTraceId() {
|
|
|
205
199
|
* @param {EventEmitter} emitter - The event emitter to listen to
|
|
206
200
|
*/
|
|
207
201
|
function attachLogListeners(emitter) {
|
|
208
|
-
|
|
209
202
|
if (!isEnabled() || !emitter || emitterAttached) return;
|
|
210
|
-
|
|
203
|
+
|
|
211
204
|
// Check if Sentry.logger is available
|
|
212
205
|
if (!Sentry.logger) {
|
|
213
|
-
console.log(
|
|
206
|
+
console.log("Sentry.logger not available, skipping log listeners");
|
|
214
207
|
return;
|
|
215
208
|
}
|
|
216
|
-
|
|
209
|
+
|
|
217
210
|
emitterAttached = true;
|
|
218
211
|
|
|
219
212
|
// Helper to strip ANSI codes for cleaner logs
|
|
220
213
|
const stripAnsi = (str) => {
|
|
221
|
-
if (typeof str !==
|
|
222
|
-
return str.replace(/\x1B[[(?);]{0,2}(;?\d)*./g,
|
|
214
|
+
if (typeof str !== "string") return String(str);
|
|
215
|
+
return str.replace(/\x1B[[(?);]{0,2}(;?\d)*./g, "");
|
|
223
216
|
};
|
|
224
217
|
|
|
225
218
|
// Helper to get current log attributes with trace context
|
|
226
219
|
const getLogAttributes = (extra = {}) => {
|
|
227
220
|
const attrs = { ...extra };
|
|
228
221
|
if (currentSessionId) {
|
|
229
|
-
attrs[
|
|
222
|
+
attrs["session.id"] = currentSessionId;
|
|
230
223
|
}
|
|
231
224
|
if (currentTraceId) {
|
|
232
|
-
attrs[
|
|
225
|
+
attrs["sentry.trace.trace_id"] = currentTraceId;
|
|
233
226
|
}
|
|
234
227
|
// Get current user from Sentry scope
|
|
235
228
|
try {
|
|
236
229
|
const user = Sentry.getCurrentScope().getUser();
|
|
237
230
|
if (user) {
|
|
238
|
-
if (user.id) attrs[
|
|
239
|
-
if (user.email) attrs[
|
|
240
|
-
if (user.username) attrs[
|
|
231
|
+
if (user.id) attrs["user.id"] = user.id;
|
|
232
|
+
if (user.email) attrs["user.email"] = user.email;
|
|
233
|
+
if (user.username) attrs["user.name"] = user.username;
|
|
241
234
|
}
|
|
242
235
|
} catch (e) {
|
|
243
236
|
// Ignore errors getting user
|
|
244
237
|
}
|
|
245
238
|
return attrs;
|
|
246
239
|
};
|
|
247
|
-
|
|
240
|
+
|
|
248
241
|
// Capture log:log as info logs
|
|
249
|
-
emitter.on(
|
|
250
|
-
Sentry.logger.info(
|
|
242
|
+
emitter.on("log:log", (message) => {
|
|
243
|
+
Sentry.logger.info(
|
|
244
|
+
stripAnsi(message),
|
|
245
|
+
getLogAttributes({ category: "cli.log" }),
|
|
246
|
+
);
|
|
251
247
|
});
|
|
252
|
-
|
|
248
|
+
|
|
253
249
|
// Capture log:warn as warning logs
|
|
254
|
-
emitter.on(
|
|
255
|
-
Sentry.logger.warn(
|
|
250
|
+
emitter.on("log:warn", (message) => {
|
|
251
|
+
Sentry.logger.warn(
|
|
252
|
+
stripAnsi(message),
|
|
253
|
+
getLogAttributes({ category: "cli.warn" }),
|
|
254
|
+
);
|
|
256
255
|
});
|
|
257
|
-
|
|
256
|
+
|
|
258
257
|
// Capture log:debug as debug logs (only in verbose mode)
|
|
259
258
|
if (process.env.VERBOSE || process.env.DEBUG || process.env.TD_DEBUG) {
|
|
260
|
-
emitter.on(
|
|
261
|
-
Sentry.logger.debug(
|
|
259
|
+
emitter.on("log:debug", (message) => {
|
|
260
|
+
Sentry.logger.debug(
|
|
261
|
+
stripAnsi(message),
|
|
262
|
+
getLogAttributes({ category: "cli.debug" }),
|
|
263
|
+
);
|
|
262
264
|
});
|
|
263
265
|
}
|
|
264
|
-
|
|
266
|
+
|
|
265
267
|
// Capture command events
|
|
266
|
-
emitter.on(
|
|
267
|
-
Sentry.logger.info(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
268
|
+
emitter.on("command:start", (data) => {
|
|
269
|
+
Sentry.logger.info(
|
|
270
|
+
`Command started: ${data?.command || data?.name || "unknown"}`,
|
|
271
|
+
getLogAttributes({
|
|
272
|
+
category: "cli.command",
|
|
273
|
+
...data,
|
|
274
|
+
}),
|
|
275
|
+
);
|
|
271
276
|
});
|
|
272
|
-
|
|
273
|
-
emitter.on(
|
|
274
|
-
Sentry.logger.error(
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
277
|
+
|
|
278
|
+
emitter.on("command:error", (data) => {
|
|
279
|
+
Sentry.logger.error(
|
|
280
|
+
`Command error: ${data?.message || data?.error || "unknown"}`,
|
|
281
|
+
getLogAttributes({
|
|
282
|
+
category: "cli.command",
|
|
283
|
+
...data,
|
|
284
|
+
}),
|
|
285
|
+
);
|
|
278
286
|
});
|
|
279
|
-
|
|
287
|
+
|
|
280
288
|
// Capture step events
|
|
281
|
-
emitter.on(
|
|
282
|
-
Sentry.logger.info(
|
|
283
|
-
|
|
284
|
-
|
|
289
|
+
emitter.on("step:start", (data) => {
|
|
290
|
+
Sentry.logger.info(
|
|
291
|
+
`Step started: ${data?.step || data?.name || "unknown"}`,
|
|
292
|
+
getLogAttributes({
|
|
293
|
+
category: "cli.step",
|
|
294
|
+
}),
|
|
295
|
+
);
|
|
285
296
|
});
|
|
286
|
-
|
|
287
|
-
emitter.on(
|
|
288
|
-
Sentry.logger.error(
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
297
|
+
|
|
298
|
+
emitter.on("step:error", (data) => {
|
|
299
|
+
Sentry.logger.error(
|
|
300
|
+
`Step error: ${data?.message || data?.error || "unknown"}`,
|
|
301
|
+
getLogAttributes({
|
|
302
|
+
category: "cli.step",
|
|
303
|
+
...data,
|
|
304
|
+
}),
|
|
305
|
+
);
|
|
292
306
|
});
|
|
293
|
-
|
|
307
|
+
|
|
294
308
|
// Capture test events
|
|
295
|
-
emitter.on(
|
|
296
|
-
Sentry.logger.info(
|
|
297
|
-
|
|
298
|
-
|
|
309
|
+
emitter.on("test:start", (data) => {
|
|
310
|
+
Sentry.logger.info(
|
|
311
|
+
`Test started: ${data?.name || "unknown"}`,
|
|
312
|
+
getLogAttributes({
|
|
313
|
+
category: "cli.test",
|
|
314
|
+
}),
|
|
315
|
+
);
|
|
299
316
|
});
|
|
300
|
-
|
|
301
|
-
emitter.on(
|
|
302
|
-
Sentry.logger.error(
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
317
|
+
|
|
318
|
+
emitter.on("test:error", (data) => {
|
|
319
|
+
Sentry.logger.error(
|
|
320
|
+
`Test error: ${data?.message || data?.error || "unknown"}`,
|
|
321
|
+
getLogAttributes({
|
|
322
|
+
category: "cli.test",
|
|
323
|
+
...data,
|
|
324
|
+
}),
|
|
325
|
+
);
|
|
306
326
|
});
|
|
307
327
|
}
|
|
308
328
|
|