@debugbundle/cli 0.1.5 → 0.1.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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/dist/main.cjs +56 -24
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -21,6 +21,7 @@ debugbundle setup --non-interactive
21
21
  debugbundle doctor --privacy
22
22
  debugbundle verify local
23
23
  debugbundle verify cloud --project-id <id> --trigger-5xx
24
+ debugbundle verify cloud --project-id <id> --trigger-4xx 403
24
25
  debugbundle process
25
26
  debugbundle incidents
26
27
  debugbundle explain <incident-id> --source cloud
package/dist/main.cjs CHANGED
@@ -24590,7 +24590,7 @@ function formatResult(input, exitCode, checks, errors, incidentId) {
24590
24590
  };
24591
24591
  }
24592
24592
  function buildCloudSuggestedActions(status, incidentId, mode = "passive_recent_incident") {
24593
- if (status === "healthy" && incidentId !== void 0 && mode === "active_5xx") {
24593
+ if (status === "healthy" && incidentId !== void 0 && (mode === "active_5xx" || mode === "active_4xx")) {
24594
24594
  return [
24595
24595
  `Run debugbundle inspect ${incidentId} --source cloud to inspect why the incident fired.`,
24596
24596
  `Run debugbundle bundle ${incidentId} --source cloud to fetch the generated debug bundle.`
@@ -24660,11 +24660,11 @@ function localFailureStepName(checks) {
24660
24660
  function cloudVerificationRunId(now) {
24661
24661
  return now.toISOString().replace(/[-:.TZ]/g, "").slice(0, 14);
24662
24662
  }
24663
- function requestFailureReason() {
24663
+ function requestFailureReason(responseStatus) {
24664
24664
  const incidentReason = deriveIncidentReasonFromSignal({
24665
24665
  event_type: "request_event",
24666
24666
  event_class: "incident_signal",
24667
- response_status: 503
24667
+ response_status: responseStatus
24668
24668
  });
24669
24669
  if (incidentReason === null) {
24670
24670
  throw new Error("request_failure_reason_unavailable");
@@ -24673,6 +24673,9 @@ function requestFailureReason() {
24673
24673
  }
24674
24674
  function buildCloudVerificationEvent(input) {
24675
24675
  const runId = cloudVerificationRunId(input.now);
24676
+ const is5xxVerification = input.responseStatus >= 500;
24677
+ const routeTemplate = is5xxVerification ? "/debugbundle/verify/cloud" : `/debugbundle/verify/cloud/client-error/${input.responseStatus}`;
24678
+ const verificationLabel = is5xxVerification ? "true" : `client-error-${input.responseStatus}`;
24676
24679
  return createEventEnvelope({
24677
24680
  event_type: "request_event",
24678
24681
  sdk_name: "debugbundle-cli",
@@ -24686,28 +24689,39 @@ function buildCloudVerificationEvent(input) {
24686
24689
  occurred_at: input.now.toISOString(),
24687
24690
  payload: {
24688
24691
  method: "GET",
24689
- path: "/debugbundle/verify/cloud",
24690
- route_template: "/debugbundle/verify/cloud",
24692
+ path: routeTemplate,
24693
+ route_template: routeTemplate,
24691
24694
  query: {
24692
24695
  debugbundle_verification: true,
24693
- run_id: runId
24696
+ run_id: runId,
24697
+ synthetic_status: input.responseStatus
24694
24698
  },
24695
24699
  headers: {
24696
- "x-debugbundle-verification": "true"
24700
+ "x-debugbundle-verification": verificationLabel
24697
24701
  },
24698
- response_status: 503,
24702
+ response_status: input.responseStatus,
24699
24703
  duration_ms: 37,
24700
24704
  response_headers: {
24701
- "x-debugbundle-verification": "true"
24705
+ "x-debugbundle-verification": verificationLabel
24702
24706
  },
24703
24707
  response_body: {
24704
- error: "debugbundle_cloud_verification",
24708
+ error: is5xxVerification ? "debugbundle_cloud_verification" : "debugbundle_cloud_client_error_verification",
24705
24709
  synthetic: true,
24706
- run_id: runId
24710
+ run_id: runId,
24711
+ response_status: input.responseStatus
24707
24712
  }
24708
24713
  }
24709
24714
  });
24710
24715
  }
24716
+ function validateActiveCloudVerificationInput(input) {
24717
+ if (input.trigger5xx === true && input.trigger4xxStatus !== void 0) {
24718
+ return "Choose either --trigger-5xx or --trigger-4xx, not both.";
24719
+ }
24720
+ if (input.trigger4xxStatus !== void 0 && (input.trigger4xxStatus < 400 || input.trigger4xxStatus > 499)) {
24721
+ return "--trigger-4xx must be an integer status between 400 and 499.";
24722
+ }
24723
+ return null;
24724
+ }
24711
24725
  async function sendEventsToApi2(input, dependencies = {}) {
24712
24726
  const fetchImpl = dependencies.fetchImpl ?? fetch;
24713
24727
  const baseUrl = input.baseUrl.endsWith("/") ? input.baseUrl.slice(0, -1) : input.baseUrl;
@@ -24899,6 +24913,15 @@ async function verifyCloudCommand(input, dependencies = {}) {
24899
24913
  const checks = [];
24900
24914
  const environment = input.environment ?? "production";
24901
24915
  const maxAgeMinutes = input.maxAgeMinutes ?? 15;
24916
+ const activeInputError = validateActiveCloudVerificationInput(input);
24917
+ if (activeInputError !== null) {
24918
+ checks.push({
24919
+ name: "trigger-input",
24920
+ status: "error",
24921
+ message: activeInputError
24922
+ });
24923
+ return formatCloudResult(input, 4, checks, [activeInputError]);
24924
+ }
24902
24925
  const readAuthState = dependencies.readAuthState ?? readCliAuthState;
24903
24926
  let authState;
24904
24927
  try {
@@ -24931,7 +24954,7 @@ async function verifyCloudCommand(input, dependencies = {}) {
24931
24954
  requestInput,
24932
24955
  dependencies.fetchImpl === void 0 ? {} : { fetchImpl: dependencies.fetchImpl }
24933
24956
  ));
24934
- if (input.trigger5xx === true) {
24957
+ if (input.trigger5xx === true || input.trigger4xxStatus !== void 0) {
24935
24958
  const verificationStartedAt = now();
24936
24959
  const runId = cloudVerificationRunId(verificationStartedAt);
24937
24960
  const serviceName = input.service ?? `debugbundle-verify-cloud-${runId}`;
@@ -24939,16 +24962,20 @@ async function verifyCloudCommand(input, dependencies = {}) {
24939
24962
  const pollAttempts = dependencies.pollAttempts ?? 6;
24940
24963
  const pollIntervalMs = dependencies.pollIntervalMs ?? 2e3;
24941
24964
  const sleep = dependencies.sleep ?? ((milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)));
24965
+ const responseStatus = input.trigger4xxStatus ?? 503;
24966
+ const activeMode = input.trigger4xxStatus !== void 0 ? "active_4xx" : "active_5xx";
24967
+ const activeCheckName = input.trigger4xxStatus !== void 0 ? "active-4xx-event" : "active-5xx-event";
24968
+ const statusLabel = input.trigger4xxStatus !== void 0 ? `${responseStatus}` : "5xx";
24942
24969
  const verification = {
24943
- mode: "active_5xx",
24970
+ mode: activeMode,
24944
24971
  bundle_status: "unknown",
24945
- classification_reason: requestFailureReason()
24972
+ classification_reason: requestFailureReason(responseStatus)
24946
24973
  };
24947
24974
  const errors = [];
24948
24975
  let exitCode = 0;
24949
24976
  let tokenId = null;
24950
24977
  let incidentId;
24951
- let activeStep = "active-5xx-event";
24978
+ let activeStep = activeCheckName;
24952
24979
  try {
24953
24980
  const token = await createProjectToken({
24954
24981
  bearerToken: authState.bearer_token,
@@ -24962,7 +24989,8 @@ async function verifyCloudCommand(input, dependencies = {}) {
24962
24989
  const event = buildCloudVerificationEvent({
24963
24990
  now: verificationStartedAt,
24964
24991
  serviceName,
24965
- environment
24992
+ environment,
24993
+ responseStatus
24966
24994
  });
24967
24995
  const ingestion = await sendEvents({
24968
24996
  baseUrl: authState.base_url,
@@ -24971,12 +24999,12 @@ async function verifyCloudCommand(input, dependencies = {}) {
24971
24999
  });
24972
25000
  verification.accepted_event_count = ingestion.accepted;
24973
25001
  if (ingestion.accepted < 1 || ingestion.rejected > 0 || ingestion.errors.length > 0) {
24974
- throw new Error(`Synthetic 5xx ingestion was not fully accepted: accepted=${ingestion.accepted}, rejected=${ingestion.rejected}.`);
25002
+ throw new Error(`Synthetic ${statusLabel} ingestion was not fully accepted: accepted=${ingestion.accepted}, rejected=${ingestion.rejected}.`);
24975
25003
  }
24976
25004
  checks.push({
24977
- name: "active-5xx-event",
25005
+ name: activeCheckName,
24978
25006
  status: "ok",
24979
- message: "Sent synthetic 5xx request_event through cloud ingestion."
25007
+ message: `Sent synthetic ${statusLabel} request_event through cloud ingestion.`
24980
25008
  });
24981
25009
  activeStep = "incident-retrieval";
24982
25010
  for (let attempt = 1; attempt <= pollAttempts; attempt += 1) {
@@ -24994,7 +25022,7 @@ async function verifyCloudCommand(input, dependencies = {}) {
24994
25022
  if (candidate !== void 0) {
24995
25023
  incidentId = candidate.incident_id;
24996
25024
  verification.incident_id = candidate.incident_id;
24997
- verification.classification_reason = candidate.incident_reason ?? requestFailureReason();
25025
+ verification.classification_reason = candidate.incident_reason ?? requestFailureReason(responseStatus);
24998
25026
  break;
24999
25027
  }
25000
25028
  if (attempt < pollAttempts) {
@@ -25002,12 +25030,12 @@ async function verifyCloudCommand(input, dependencies = {}) {
25002
25030
  }
25003
25031
  }
25004
25032
  if (incidentId === void 0) {
25005
- throw new Error("Synthetic 5xx request was accepted but no matching cloud incident was visible yet.");
25033
+ throw new Error(`Synthetic ${statusLabel} request was accepted but no matching cloud incident was visible yet.`);
25006
25034
  }
25007
25035
  checks.push({
25008
25036
  name: "incident-retrieval",
25009
25037
  status: "ok",
25010
- message: `Retrieved cloud incident ${incidentId} for the synthetic 5xx request.`
25038
+ message: `Retrieved cloud incident ${incidentId} for the synthetic ${statusLabel} request.`
25011
25039
  });
25012
25040
  activeStep = "bundle-status";
25013
25041
  const bundle = await getBundle({
@@ -25273,7 +25301,7 @@ var CLI_USAGE_LINES = [
25273
25301
  " debugbundle clean [--events] [--bundles] [--all] [--older-than <Nd>] [--json]",
25274
25302
  " debugbundle validate [--fix] [--json]",
25275
25303
  " debugbundle verify local [--json]",
25276
- " debugbundle verify cloud --project-id <id> [--trigger-5xx] [--service <name>] [--environment <name>] [--max-age-minutes <n>] [--auth-file <path>] [--json]",
25304
+ " debugbundle verify cloud --project-id <id> [--trigger-5xx | --trigger-4xx <400-499>] [--service <name>] [--environment <name>] [--max-age-minutes <n>] [--auth-file <path>] [--json]",
25277
25305
  " debugbundle smoke --project-id <id> [--service <name>] [--environment <name>] [--max-age-minutes <n>] [--auth-file <path>] [--json]",
25278
25306
  " debugbundle login [--base-url <url>] [--auth-file <path>] [--json]",
25279
25307
  " debugbundle login <member-token> [--base-url <url>] [--auth-file <path>] [--json]",
@@ -29519,7 +29547,7 @@ ${formatUsage()}`
29519
29547
  return await (dependencies.verifyLocalCommand ?? verifyLocalCommand)(readBooleanOption(parsedArgv, "json") === true ? { json: true } : {});
29520
29548
  }
29521
29549
  if (subcommand === "cloud") {
29522
- expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "service", "environment", "max-age-minutes", "trigger-5xx"]);
29550
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "service", "environment", "max-age-minutes", "trigger-5xx", "trigger-4xx"]);
29523
29551
  ensureNoExtraPositionals(parsedArgv, 2);
29524
29552
  const projectId = readStringOption(parsedArgv, "project-id");
29525
29553
  if (projectId === void 0) {
@@ -29537,6 +29565,10 @@ ${formatUsage()}`
29537
29565
  if (readBooleanOption(parsedArgv, "trigger-5xx") === true) {
29538
29566
  input.trigger5xx = true;
29539
29567
  }
29568
+ const trigger4xxStatus = readIntegerOption(parsedArgv, "trigger-4xx");
29569
+ if (trigger4xxStatus !== void 0) {
29570
+ input.trigger4xxStatus = trigger4xxStatus;
29571
+ }
29540
29572
  return await (dependencies.verifyCloudCommand ?? verifyCloudCommand)(input);
29541
29573
  }
29542
29574
  throw new CliInputError("Unknown verify command.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@debugbundle/cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "private": false,
5
5
  "description": "Command-line interface for DebugBundle",
6
6
  "license": "AGPL-3.0-only",