@sentry/bundler-plugin-core 2.1.0 → 2.2.1

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.
@@ -12,6 +12,7 @@ import childProcess from 'child_process';
12
12
  import { glob } from 'glob';
13
13
  import * as util from 'util';
14
14
  import { promisify } from 'util';
15
+ import { dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils';
15
16
  import { NodeClient, defaultStackParser, makeNodeTransport, Hub } from '@sentry/node';
16
17
 
17
18
  function ownKeys(object, enumerableOnly) {
@@ -671,16 +672,22 @@ function createDebugIdUploadFunction(_ref) {
671
672
  deleteFilesAfterUpload = _ref.deleteFilesAfterUpload;
672
673
  return /*#__PURE__*/function () {
673
674
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(buildArtifactPaths) {
674
- var folderToCleanUp, cliInstance, tmpUploadFolder, globAssets, debugIdChunkFilePaths, filePathsToDelete;
675
+ var artifactBundleUploadTransaction, folderToCleanUp, mkdtempSpan, tmpUploadFolder, globAssets, globSpan, globResult, debugIdChunkFilePaths, prepareSpan, files, stats, uploadSize, uploadSpan, cliInstance, deleteGlobSpan, filePathsToDelete, deleteSpan, cleanupSpan;
675
676
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
676
677
  while (1) switch (_context2.prev = _context2.next) {
677
678
  case 0:
678
- cliInstance = new SentryCli(null, sentryCliOptions);
679
+ artifactBundleUploadTransaction = sentryHub.startTransaction({
680
+ name: "debug-id-sourcemap-upload"
681
+ });
679
682
  _context2.prev = 1;
680
- _context2.next = 4;
683
+ mkdtempSpan = artifactBundleUploadTransaction.startChild({
684
+ description: "mkdtemp"
685
+ });
686
+ _context2.next = 5;
681
687
  return fs__default.promises.mkdtemp(path__default.join(os.tmpdir(), "sentry-bundler-plugin-upload-"));
682
- case 4:
688
+ case 5:
683
689
  tmpUploadFolder = _context2.sent;
690
+ mkdtempSpan.finish();
684
691
  folderToCleanUp = tmpUploadFolder;
685
692
  if (assets) {
686
693
  globAssets = assets;
@@ -688,33 +695,41 @@ function createDebugIdUploadFunction(_ref) {
688
695
  logger.debug("No `sourcemaps.assets` option provided, falling back to uploading detected build artifacts.");
689
696
  globAssets = buildArtifactPaths;
690
697
  }
691
- _context2.next = 9;
698
+ globSpan = artifactBundleUploadTransaction.startChild({
699
+ description: "glob"
700
+ });
701
+ _context2.next = 12;
692
702
  return glob(globAssets, {
693
703
  absolute: true,
694
704
  nodir: true,
695
705
  ignore: ignore
696
706
  });
697
- case 9:
698
- debugIdChunkFilePaths = _context2.sent.filter(function (debugIdChunkFilePath) {
707
+ case 12:
708
+ globResult = _context2.sent;
709
+ globSpan.finish();
710
+ debugIdChunkFilePaths = globResult.filter(function (debugIdChunkFilePath) {
699
711
  return debugIdChunkFilePath.endsWith(".js") || debugIdChunkFilePath.endsWith(".mjs") || debugIdChunkFilePath.endsWith(".cjs");
700
712
  });
701
713
  if (!(Array.isArray(assets) && assets.length === 0)) {
702
- _context2.next = 14;
714
+ _context2.next = 19;
703
715
  break;
704
716
  }
705
717
  logger.debug("Empty `sourcemaps.assets` option provided. Will not upload sourcemaps with debug ID.");
706
- _context2.next = 22;
718
+ _context2.next = 41;
707
719
  break;
708
- case 14:
720
+ case 19:
709
721
  if (!(debugIdChunkFilePaths.length === 0)) {
710
- _context2.next = 18;
722
+ _context2.next = 23;
711
723
  break;
712
724
  }
713
725
  logger.warn("Didn't find any matching sources for debug ID upload. Please check the `sourcemaps.assets` option.");
714
- _context2.next = 22;
726
+ _context2.next = 41;
715
727
  break;
716
- case 18:
717
- _context2.next = 20;
728
+ case 23:
729
+ prepareSpan = artifactBundleUploadTransaction.startChild({
730
+ description: "prepare-bundles"
731
+ });
732
+ _context2.next = 26;
718
733
  return Promise.all(debugIdChunkFilePaths.map( /*#__PURE__*/function () {
719
734
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(chunkFilePath, chunkIndex) {
720
735
  return _regeneratorRuntime().wrap(function _callee$(_context) {
@@ -732,8 +747,35 @@ function createDebugIdUploadFunction(_ref) {
732
747
  return _ref3.apply(this, arguments);
733
748
  };
734
749
  }()));
735
- case 20:
736
- _context2.next = 22;
750
+ case 26:
751
+ prepareSpan.finish();
752
+ _context2.next = 29;
753
+ return fs__default.promises.readdir(tmpUploadFolder);
754
+ case 29:
755
+ files = _context2.sent;
756
+ stats = files.map(function (file) {
757
+ return fs__default.promises.stat(path__default.join(tmpUploadFolder, file));
758
+ });
759
+ _context2.next = 33;
760
+ return Promise.all(stats);
761
+ case 33:
762
+ uploadSize = _context2.sent.reduce(function (accumulator, _ref4) {
763
+ var size = _ref4.size;
764
+ return accumulator + size;
765
+ }, 0);
766
+ artifactBundleUploadTransaction.setMeasurement("files", files.length, "none");
767
+ artifactBundleUploadTransaction.setMeasurement("upload_size", uploadSize, "byte");
768
+ uploadSpan = artifactBundleUploadTransaction.startChild({
769
+ description: "upload"
770
+ });
771
+ cliInstance = new SentryCli(null, _objectSpread2(_objectSpread2({}, sentryCliOptions), {}, {
772
+ headers: _objectSpread2({
773
+ "sentry-trace": uploadSpan.toTraceparent(),
774
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
775
+ baggage: dynamicSamplingContextToSentryBaggageHeader(artifactBundleUploadTransaction.getDynamicSamplingContext())
776
+ }, sentryCliOptions.headers)
777
+ }));
778
+ _context2.next = 40;
737
779
  return cliInstance.releases.uploadSourceMaps(releaseName !== null && releaseName !== void 0 ? releaseName : "undefined",
738
780
  // unfortunetly this needs a value for now but it will not matter since debug IDs overpower releases anyhow
739
781
  {
@@ -744,52 +786,71 @@ function createDebugIdUploadFunction(_ref) {
744
786
  }],
745
787
  useArtifactBundle: true
746
788
  });
747
- case 22:
789
+ case 40:
790
+ uploadSpan.finish();
791
+ case 41:
748
792
  if (!deleteFilesAfterUpload) {
749
- _context2.next = 29;
793
+ _context2.next = 52;
750
794
  break;
751
795
  }
752
- _context2.next = 25;
796
+ deleteGlobSpan = artifactBundleUploadTransaction.startChild({
797
+ description: "delete-glob"
798
+ });
799
+ _context2.next = 45;
753
800
  return glob(deleteFilesAfterUpload, {
754
801
  absolute: true,
755
802
  nodir: true
756
803
  });
757
- case 25:
804
+ case 45:
758
805
  filePathsToDelete = _context2.sent;
806
+ deleteGlobSpan.finish();
759
807
  filePathsToDelete.forEach(function (filePathToDelete) {
760
808
  logger.debug("Deleting asset after upload: ".concat(filePathToDelete));
761
809
  });
762
- _context2.next = 29;
810
+ deleteSpan = artifactBundleUploadTransaction.startChild({
811
+ description: "delete-files-after-upload"
812
+ });
813
+ _context2.next = 51;
763
814
  return Promise.all(filePathsToDelete.map(function (filePathToDelete) {
764
815
  return fs__default.promises.rm(filePathToDelete, {
765
816
  force: true
766
817
  });
767
818
  }));
768
- case 29:
769
- _context2.next = 37;
819
+ case 51:
820
+ deleteSpan.finish();
821
+ case 52:
822
+ _context2.next = 58;
770
823
  break;
771
- case 31:
772
- _context2.prev = 31;
824
+ case 54:
825
+ _context2.prev = 54;
773
826
  _context2.t0 = _context2["catch"](1);
774
- sentryHub.captureException('Error in "debugIdUploadPlugin" writeBundle hook');
775
- _context2.next = 36;
776
- return sentryClient.flush();
777
- case 36:
827
+ sentryHub.withScope(function (scope) {
828
+ scope.setSpan(artifactBundleUploadTransaction);
829
+ sentryHub.captureException('Error in "debugIdUploadPlugin" writeBundle hook');
830
+ });
778
831
  handleRecoverableError(_context2.t0);
779
- case 37:
780
- _context2.prev = 37;
832
+ case 58:
833
+ _context2.prev = 58;
781
834
  if (folderToCleanUp) {
835
+ cleanupSpan = artifactBundleUploadTransaction.startChild({
836
+ description: "cleanup"
837
+ });
782
838
  void fs__default.promises.rm(folderToCleanUp, {
783
839
  recursive: true,
784
840
  force: true
785
841
  });
842
+ cleanupSpan.finish();
786
843
  }
787
- return _context2.finish(37);
788
- case 40:
844
+ artifactBundleUploadTransaction.finish();
845
+ _context2.next = 63;
846
+ return sentryClient.flush();
847
+ case 63:
848
+ return _context2.finish(58);
849
+ case 64:
789
850
  case "end":
790
851
  return _context2.stop();
791
852
  }
792
- }, _callee2, null, [[1, 31, 37, 40]]);
853
+ }, _callee2, null, [[1, 54, 58, 64]]);
793
854
  }));
794
855
  return function (_x) {
795
856
  return _ref2.apply(this, arguments);
@@ -837,7 +898,7 @@ function _prepareBundleForDebugIdUpload() {
837
898
  bundleContent += "\n//# debugId=".concat(debugId);
838
899
  writeSourceFilePromise = fs__default.promises.writeFile(path__default.join(uploadFolder, "".concat(uniqueUploadName, ".js")), bundleContent, "utf-8");
839
900
  writeSourceMapFilePromise = determineSourceMapPathFromBundle(bundleFilePath, bundleContent, logger).then( /*#__PURE__*/function () {
840
- var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(sourceMapPath) {
901
+ var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(sourceMapPath) {
841
902
  return _regeneratorRuntime().wrap(function _callee3$(_context3) {
842
903
  while (1) switch (_context3.prev = _context3.next) {
843
904
  case 0:
@@ -856,7 +917,7 @@ function _prepareBundleForDebugIdUpload() {
856
917
  }, _callee3);
857
918
  }));
858
919
  return function (_x17) {
859
- return _ref4.apply(this, arguments);
920
+ return _ref5.apply(this, arguments);
860
921
  };
861
922
  }());
862
923
  return _context4.abrupt("return", Promise.all([writeSourceFilePromise, writeSourceMapFilePromise]));
@@ -920,7 +981,7 @@ function _determineSourceMapPathFromBundle() {
920
981
  _context5.t0 = _context5["catch"](8);
921
982
  case 17:
922
983
  // This is just a debug message because it can be quite spammy for some frameworks
923
- logger.debug("Could not determine source map path for bundle: ".concat(bundlePath));
984
+ logger.debug("Could not determine source map path for bundle: ".concat(bundlePath, " - Did you turn on source map generation in your bundler?"));
924
985
  return _context5.abrupt("return", undefined);
925
986
  case 19:
926
987
  case "end":
@@ -1105,29 +1166,31 @@ function releaseManagementPlugin(_ref) {
1105
1166
  }
1106
1167
 
1107
1168
  function telemetryPlugin(_ref) {
1108
- var sentryClient = _ref.sentryClient,
1109
- pluginExecutionTransaction = _ref.pluginExecutionTransaction,
1169
+ var sentryHub = _ref.sentryHub,
1170
+ sentryClient = _ref.sentryClient,
1110
1171
  shouldSendTelemetry = _ref.shouldSendTelemetry,
1111
1172
  logger = _ref.logger;
1112
1173
  return {
1113
1174
  name: "sentry-telemetry-plugin",
1114
1175
  buildStart: function buildStart() {
1115
- void shouldSendTelemetry.then(function (willSendTelemetry) {
1116
- if (willSendTelemetry) {
1117
- logger.info("Sending error and performance telemetry data to Sentry. To disable telemetry, set `options.telemetry` to `false`.");
1118
- }
1119
- });
1120
- pluginExecutionTransaction.startTimestamp = Date.now() / 1000;
1121
- },
1122
- writeBundle: function writeBundle() {
1123
1176
  return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
1124
1177
  return _regeneratorRuntime().wrap(function _callee$(_context) {
1125
1178
  while (1) switch (_context.prev = _context.next) {
1126
1179
  case 0:
1127
- pluginExecutionTransaction.finish();
1128
- _context.next = 3;
1129
- return sentryClient.flush();
1130
- case 3:
1180
+ _context.next = 2;
1181
+ return shouldSendTelemetry;
1182
+ case 2:
1183
+ if (!_context.sent) {
1184
+ _context.next = 7;
1185
+ break;
1186
+ }
1187
+ logger.info("Sending error and performance telemetry data to Sentry. To disable telemetry, set `options.telemetry` to `false`.");
1188
+ sentryHub.startTransaction({
1189
+ name: "Sentry Bundler Plugin execution"
1190
+ }).finish();
1191
+ _context.next = 7;
1192
+ return sentryClient.flush(3000);
1193
+ case 7:
1131
1194
  case "end":
1132
1195
  return _context.stop();
1133
1196
  }
@@ -1188,7 +1251,7 @@ function createSentryInstance(options, shouldSendTelemetry, bundler) {
1188
1251
  dsn: "https://4c2bae7d9fbc413e8f7385f55c515d51@o1.ingest.sentry.io/6690737",
1189
1252
  tracesSampleRate: 1,
1190
1253
  sampleRate: 1,
1191
- release: "2.1.0",
1254
+ release: "2.2.1",
1192
1255
  integrations: [],
1193
1256
  tracePropagationTargets: ["sentry.io/api"],
1194
1257
  stackParser: defaultStackParser,
@@ -1254,35 +1317,27 @@ function setTelemetryDataOnHub(options, hub, bundler) {
1254
1317
  release = options.release,
1255
1318
  errorHandler = options.errorHandler,
1256
1319
  sourcemaps = options.sourcemaps;
1320
+ hub.setTag("upload-legacy-sourcemaps", !!release.uploadLegacySourcemaps);
1257
1321
  if (release.uploadLegacySourcemaps) {
1258
1322
  hub.setTag("uploadLegacySourcemapsEntries", Array.isArray(release.uploadLegacySourcemaps) ? release.uploadLegacySourcemaps.length : 1);
1259
1323
  }
1260
1324
 
1261
1325
  // Optional release pipeline steps
1262
- if (release.cleanArtifacts) {
1263
- hub.setTag("clean-artifacts", true);
1264
- }
1326
+ hub.setTag("clean-artifacts", release.cleanArtifacts);
1265
1327
  if (release.setCommits) {
1266
1328
  hub.setTag("set-commits", release.setCommits.auto === true ? "auto" : "manual");
1329
+ } else {
1330
+ hub.setTag("set-commits", "undefined");
1267
1331
  }
1268
- if (release.finalize) {
1269
- hub.setTag("finalize-release", true);
1270
- }
1271
- if (release.deploy) {
1272
- hub.setTag("add-deploy", true);
1273
- }
1332
+ hub.setTag("finalize-release", release.finalize);
1333
+ hub.setTag("deploy-options", !!release.deploy);
1274
1334
 
1275
1335
  // Miscelaneous options
1276
- if (errorHandler) {
1277
- hub.setTag("error-handler", "custom");
1278
- }
1279
- if (sourcemaps !== null && sourcemaps !== void 0 && sourcemaps.assets) {
1280
- hub.setTag("debug-id-upload", true);
1281
- }
1282
- if (sourcemaps !== null && sourcemaps !== void 0 && sourcemaps.deleteFilesAfterUpload) {
1283
- hub.setTag("delete-after-upload", true);
1284
- }
1336
+ hub.setTag("custom-error-handler", !!errorHandler);
1337
+ hub.setTag("sourcemaps-assets", !!(sourcemaps !== null && sourcemaps !== void 0 && sourcemaps.assets));
1338
+ hub.setTag("delete-after-upload", !!(sourcemaps !== null && sourcemaps !== void 0 && sourcemaps.deleteFilesAfterUpload));
1285
1339
  hub.setTag("node", process.version);
1340
+ hub.setTag("platform", process.platform);
1286
1341
  hub.setTags({
1287
1342
  organization: org,
1288
1343
  project: project,
@@ -1395,25 +1450,44 @@ function sentryUnpluginFactory(_ref) {
1395
1450
  var _createSentryInstance = createSentryInstance(options, shouldSendTelemetry, unpluginMetaContext.framework),
1396
1451
  sentryHub = _createSentryInstance.sentryHub,
1397
1452
  sentryClient = _createSentryInstance.sentryClient;
1398
- var pluginExecutionTransaction = sentryHub.startTransaction({
1399
- name: "Sentry Bundler Plugin execution"
1453
+ var sentrySession = sentryHub.startSession();
1454
+ sentryHub.captureSession();
1455
+ var sentEndSession = false; // Just to prevent infinite loops with beforeExit, which is called whenever the event loop empties out
1456
+ // We also need to manually end sesisons on errors because beforeExit is not called on crashes
1457
+ process.on("beforeExit", function () {
1458
+ if (!sentEndSession) {
1459
+ sentryHub.endSession();
1460
+ sentEndSession = true;
1461
+ }
1400
1462
  });
1401
- sentryHub.getScope().setSpan(pluginExecutionTransaction);
1402
1463
  var logger = createLogger({
1403
1464
  prefix: "[sentry-".concat(unpluginMetaContext.framework, "-plugin]"),
1404
1465
  silent: options.silent,
1405
1466
  debug: options.debug
1406
1467
  });
1468
+
1469
+ // Set the User-Agent that Sentry CLI will use when interacting with Sentry
1470
+ process.env["SENTRY_PIPELINE"] = "".concat(unpluginMetaContext.framework, "-plugin/", "2.2.1");
1407
1471
  function handleRecoverableError(unknownError) {
1408
- pluginExecutionTransaction.setStatus("internal_error");
1409
- if (options.errorHandler) {
1410
- if (unknownError instanceof Error) {
1411
- options.errorHandler(unknownError);
1472
+ sentrySession.status = "abnormal";
1473
+ try {
1474
+ if (options.errorHandler) {
1475
+ try {
1476
+ if (unknownError instanceof Error) {
1477
+ options.errorHandler(unknownError);
1478
+ } else {
1479
+ options.errorHandler(new Error("An unknown error occured"));
1480
+ }
1481
+ } catch (e) {
1482
+ sentrySession.status = "crashed";
1483
+ throw e;
1484
+ }
1412
1485
  } else {
1413
- options.errorHandler(new Error("An unknown error occured"));
1486
+ sentrySession.status = "crashed";
1487
+ throw unknownError;
1414
1488
  }
1415
- } else {
1416
- throw unknownError;
1489
+ } finally {
1490
+ sentryHub.endSession();
1417
1491
  }
1418
1492
  }
1419
1493
  if (!validateOptions(options, logger)) {
@@ -1424,10 +1498,10 @@ function sentryUnpluginFactory(_ref) {
1424
1498
  }
1425
1499
  var plugins = [];
1426
1500
  plugins.push(telemetryPlugin({
1427
- pluginExecutionTransaction: pluginExecutionTransaction,
1501
+ sentryClient: sentryClient,
1502
+ sentryHub: sentryHub,
1428
1503
  logger: logger,
1429
- shouldSendTelemetry: shouldSendTelemetry,
1430
- sentryClient: sentryClient
1504
+ shouldSendTelemetry: shouldSendTelemetry
1431
1505
  }));
1432
1506
  if (!options.release.inject) {
1433
1507
  logger.debug("Release injection disabled via `release.inject` option. Will not inject release.");
@@ -1597,11 +1671,10 @@ function createRollupDebugIdInjectionHooks() {
1597
1671
  var commentUseStrictRegex =
1598
1672
  // Note: CodeQL complains that this regex potentially has n^2 runtime. This likely won't affect realistic files.
1599
1673
  /^(?:\s*|\/\*(?:.|\r|\n)*\*\/|\/\/.*[\n\r])*(?:"[^"]*";|'[^']*';)?/;
1600
- if ((_code$match = code.match(commentUseStrictRegex)) !== null && _code$match !== void 0 && _code$match[0]) {
1674
+ var match = (_code$match = code.match(commentUseStrictRegex)) === null || _code$match === void 0 ? void 0 : _code$match[0];
1675
+ if (match) {
1601
1676
  // Add injected code after any comments or "use strict" at the beginning of the bundle.
1602
- ms.replace(commentUseStrictRegex, function (match) {
1603
- return "".concat(match).concat(codeToInject);
1604
- });
1677
+ ms.appendLeft(match.length, codeToInject);
1605
1678
  } else {
1606
1679
  // ms.replace() doesn't work when there is an empty string match (which happens if
1607
1680
  // there is neither, a comment, nor a "use strict" at the top of the chunk) so we