@bugbug-io/cli 13.39.2 → 14.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/dist/index.js CHANGED
@@ -1,10 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- render
4
- } from "./chunk-UZVYEMEZ.js";
5
- import {
6
- BaseSuiteRunDetails,
7
- BaseTestRunDetails,
8
3
  EXIT_GENERAL_ERROR,
9
4
  EXIT_USAGE_ERROR,
10
5
  PLUGIN_PACKAGE_NAME,
@@ -23,6 +18,7 @@ import {
23
18
  formatErrorMessage,
24
19
  formatInlineRunReport,
25
20
  getCliConfig,
21
+ getIdentity,
26
22
  getSuite,
27
23
  getSuiteRun,
28
24
  getSuiteRunJunitReport,
@@ -36,6 +32,7 @@ import {
36
32
  importTest,
37
33
  initProject,
38
34
  initSentry,
35
+ isCompletedStatus,
39
36
  listProfiles,
40
37
  listSuites,
41
38
  listTests,
@@ -54,7 +51,7 @@ import {
54
51
  waitForSuiteRun,
55
52
  waitForTestRun,
56
53
  writeReportXml
57
- } from "./chunk-GNCJ7Y4W.js";
54
+ } from "./chunk-4IJVD32G.js";
58
55
  import "./chunk-BSHFIPEX.js";
59
56
  import "./chunk-PR4QN5HX.js";
60
57
 
@@ -78,7 +75,8 @@ var registerLoginCommand = (program2, commandName = "login") => program2.command
78
75
  if (mode === "json") {
79
76
  printJson(result);
80
77
  } else {
81
- process.stdout.write(`Logged in. Token saved to "${result.credentialsFile}"
78
+ process.stdout.write(`
79
+ Logged in. Token saved to "${result.credentialsFile}"
82
80
  `);
83
81
  }
84
82
  const shouldBackfillSessionStart = !analytics.get().isEnabled;
@@ -154,6 +152,7 @@ var CLIENTS = {
154
152
  pluginsTarget: "codex",
155
153
  postInstallAuth: {
156
154
  command: "codex",
155
+ resetCheckArgs: ["mcp", "get", "bugbug"],
157
156
  resetArgs: ["mcp", "logout", "bugbug"],
158
157
  args: ["mcp", "login", "bugbug"]
159
158
  }
@@ -211,10 +210,14 @@ var runPostInstallAuth = (ctx, auth) => {
211
210
  const fullCommand = resetCommand ? `${resetCommand} && ${command}` : command;
212
211
  if (ctx.dryRun)
213
212
  return { command: fullCommand };
214
- if (auth.resetArgs) {
215
- runClientCommand([auth.command, ...auth.resetArgs], { ...ctx.runnerOptions, stdio: "inherit" });
213
+ const shouldReset = auth.resetArgs && (!auth.resetCheckArgs || runClientCommand([auth.command, ...auth.resetCheckArgs], {
214
+ ...ctx.runnerOptions,
215
+ stdio: "ignore"
216
+ }).ok);
217
+ if (shouldReset) {
218
+ runClientCommand([auth.command, ...auth.resetArgs], { ...ctx.runnerOptions, stdio: "ignore" });
216
219
  }
217
- const { ok, code } = runClientCommand(argv, { ...ctx.runnerOptions, stdio: "inherit" });
220
+ const { ok, code } = runClientCommand(argv, { ...ctx.runnerOptions, stdio: "ignore" });
218
221
  if (!ok) {
219
222
  return { command: fullCommand, message: `\`${command}\` failed (exit ${code}).` };
220
223
  }
@@ -302,7 +305,7 @@ var describeResult = (result) => {
302
305
  case "updated":
303
306
  return `\u2713 ${name}: updated ${result.path}`;
304
307
  case "executed":
305
- return `\u2713 ${name}: installed via CLI`;
308
+ return `\u2713 ${name}: installed via CLI${result.message ? ` \u2014 ${result.message}` : ""}`;
306
309
  case "skipped":
307
310
  return `\u2022 ${name}: already configured (${result.path})`;
308
311
  case "unsupported":
@@ -588,7 +591,6 @@ var registerSuiteRunsCommand = (program2) => {
588
591
  };
589
592
 
590
593
  // src/utils/runAction.ts
591
- import { createElement } from "react";
592
594
  var collectRunVariableOption = (val, prev = []) => prev.concat(val);
593
595
  var parseTimeoutMinutes = (value) => {
594
596
  const minutes = Number(value);
@@ -598,14 +600,11 @@ var parseTimeoutMinutes = (value) => {
598
600
  return minutes * 6e4;
599
601
  };
600
602
  var runResourceAction = async (resourceId, opts, adapter) => {
601
- const mode = resolveOutputMode();
603
+ const configuredMode = resolveOutputMode();
604
+ const mode = configuredMode === "interactive" ? "plain" : configuredMode;
602
605
  try {
603
606
  const reporter = validateReporterOptions(opts);
604
607
  const variables = getVariablesMap(opts.variables ?? []);
605
- const runResult = await adapter.runResource(resourceId, {
606
- profile: opts.profile,
607
- variables: Object.keys(variables).length ? variables : void 0
608
- });
609
608
  if (mode === "plain") {
610
609
  process.stdout.write(
611
610
  `Starting ${adapter.runLabel} for ${adapter.entityLabel} id: ${resourceId}
@@ -617,6 +616,12 @@ var runResourceAction = async (resourceId, opts, adapter) => {
617
616
  process.stdout.write(`Variables: ${JSON.stringify(variables)}
618
617
  `);
619
618
  }
619
+ }
620
+ const runResult = await adapter.runResource(resourceId, {
621
+ profile: opts.profile,
622
+ variables: Object.keys(variables).length ? variables : void 0
623
+ });
624
+ if (mode === "plain") {
620
625
  process.stdout.write(`${capitalize(adapter.runLabel)} id: ${runResult.id}
621
626
  `);
622
627
  }
@@ -626,52 +631,21 @@ var runResourceAction = async (resourceId, opts, adapter) => {
626
631
  }
627
632
  return;
628
633
  }
629
- let finalState;
630
- if (mode === "interactive") {
631
- let interactiveState;
632
- let interactiveError;
633
- const RunDetailsComponent = adapter.kind === "suite" ? BaseSuiteRunDetails : BaseTestRunDetails;
634
- const { waitUntilExit } = await render(
635
- createElement(RunDetailsComponent, {
636
- runId: runResult.id,
637
- headless: true,
638
- timeoutMs: opts.timeout,
639
- onComplete: (status) => {
640
- interactiveState = status;
641
- },
642
- onError: (err) => {
643
- interactiveError = err;
644
- }
645
- })
646
- );
647
- await waitUntilExit();
648
- if (interactiveError) {
649
- const error = interactiveError;
650
- throw error;
651
- }
652
- if (!interactiveState) {
653
- throw new Error(
654
- `${capitalize(adapter.runLabel)} ${runResult.id} finished without a final status.`
655
- );
656
- }
657
- finalState = interactiveState;
658
- } else {
659
- let lastStatus = "";
660
- finalState = await adapter.waitForRun(
661
- runResult.id,
662
- 4e3,
663
- (status) => {
664
- if (status.status !== lastStatus) {
665
- lastStatus = status.status;
666
- if (mode === "plain") {
667
- process.stdout.write(`[${(/* @__PURE__ */ new Date()).toISOString()}] status: ${status.status}
634
+ let lastStatus = "";
635
+ const finalState = await adapter.waitForRun(
636
+ runResult.id,
637
+ 4e3,
638
+ (status) => {
639
+ if (status.status !== lastStatus) {
640
+ lastStatus = status.status;
641
+ if (mode === "plain" && !isCompletedStatus(status.status)) {
642
+ process.stdout.write(`Status changed to: ${status.status}
668
643
  `);
669
- }
670
644
  }
671
- },
672
- opts.timeout
673
- );
674
- }
645
+ }
646
+ },
647
+ opts.timeout
648
+ );
675
649
  let reportResult;
676
650
  if (reporter === "junit") {
677
651
  const xml = await adapter.getJunitReport(runResult.id);
@@ -684,20 +658,18 @@ var runResourceAction = async (resourceId, opts, adapter) => {
684
658
  if (mode === "json") {
685
659
  const payload = reportResult ? { ...finalState, report: { kind: "junit", ...reportResult } } : finalState;
686
660
  printJson(payload);
687
- } else if (mode === "plain" || mode === "interactive") {
661
+ } else if (mode === "plain") {
662
+ process.stdout.write(`Final status: ${finalState.status}
663
+ ----
664
+ `);
688
665
  if (reportResult?.outPath) {
689
666
  process.stdout.write(
690
667
  `Saved JUnit report for ${adapter.runLabel} ${runResult.id} to ${reportResult.outPath} (${reportResult.size} chars)
691
668
  `
692
669
  );
693
670
  }
694
- if (mode === "plain") {
695
- if (reporter === "inline") {
696
- process.stdout.write(formatInlineRunReport(adapter.kind, finalState));
697
- } else {
698
- process.stdout.write(`Final status: ${finalState.status}
699
- `);
700
- }
671
+ if (mode === "plain" && reporter === "inline") {
672
+ process.stdout.write(formatInlineRunReport(adapter.kind, finalState));
701
673
  }
702
674
  }
703
675
  const code = exitCodeForStatus(finalState.status);
@@ -1019,6 +991,25 @@ var getFullCommandPath = (command) => {
1019
991
  return names.join(" ");
1020
992
  };
1021
993
 
994
+ // src/utils/prompt.ts
995
+ import { createInterface } from "readline";
996
+
997
+ // src/utils/sessionAuth.ts
998
+ var resolveTokenProjectId = async () => {
999
+ try {
1000
+ const identity = await getIdentity();
1001
+ return identity.tokenType === "project" ? identity.projectId ?? void 0 : void 0;
1002
+ } catch {
1003
+ return void 0;
1004
+ }
1005
+ };
1006
+ var hasUsableSession = async () => {
1007
+ const config = getCliConfig();
1008
+ if (!config.token?.trim()) return false;
1009
+ if (config.projectId?.trim()) return true;
1010
+ return await resolveTokenProjectId() !== void 0;
1011
+ };
1012
+
1022
1013
  // src/utils/startup.ts
1023
1014
  var GLOBAL_FLAGS_WITH_VALUE = /* @__PURE__ */ new Set(["-t", "--token", "-p", "--project-id"]);
1024
1015
  var GLOBAL_FLAGS = /* @__PURE__ */ new Set(["-v", "--verbose", "--disable-telemetry", "--ci", "--json"]);
@@ -1139,13 +1130,12 @@ var isAuthRedirectExemptCommand = (positionals) => {
1139
1130
  if (AUTH_REDIRECT_EXEMPT_TOP_LEVEL_COMMANDS.has(command)) return true;
1140
1131
  return command === "project" && subcommand === "init";
1141
1132
  };
1142
- var shouldRedirectUnauthenticatedCommandToInit = (argv, authenticated) => {
1143
- if (authenticated) return false;
1133
+ var shouldRedirectUnauthenticatedCommandToInit = async (argv, hasSession) => {
1144
1134
  const args = parseStartupArgs(argv);
1145
1135
  if (args.hasExplicitHelpOrVersion || !isInteractiveStartup(args)) return false;
1146
1136
  if (args.positionals.length === 0) return false;
1147
1137
  if (isAuthRedirectExemptCommand(args.positionals)) return false;
1148
- return true;
1138
+ return !await hasSession();
1149
1139
  };
1150
1140
  var getStartupMode = (argv) => {
1151
1141
  const args = parseStartupArgs(argv);
@@ -1217,11 +1207,8 @@ program.exitOverride();
1217
1207
  startupMode: startupMode.type
1218
1208
  });
1219
1209
  analytics.trackEvent("cli_session_started");
1220
- if (startupMode.type === "commandline" && shouldRedirectUnauthenticatedCommandToInit(
1221
- process.argv,
1222
- Boolean(config.token && config.projectId)
1223
- )) {
1224
- const { startNavigator } = await import("./app-L5OYLEKP.js");
1210
+ if (startupMode.type === "commandline" && await shouldRedirectUnauthenticatedCommandToInit(process.argv, hasUsableSession)) {
1211
+ const { startNavigator } = await import("./app-UMUDDKR3.js");
1225
1212
  await startNavigator({
1226
1213
  initialRoute: "/init",
1227
1214
  initialRouteState: {
@@ -1233,7 +1220,7 @@ program.exitOverride();
1233
1220
  return;
1234
1221
  }
1235
1222
  if (startupMode.type === "navigator") {
1236
- const { startNavigator } = await import("./app-L5OYLEKP.js");
1223
+ const { startNavigator } = await import("./app-UMUDDKR3.js");
1237
1224
  await startNavigator({
1238
1225
  initialRoute: startupMode.route,
1239
1226
  token: config.token,
@@ -1,3 +1,5 @@
1
+ import "./chunk-PR4QN5HX.js";
2
+
1
3
  // src/features/tui/render.ts
2
4
  var ENTER_ALTERNATIVE_SCREEN = "\x1B[?1049h";
3
5
  var EXIT_ALTERNATIVE_SCREEN = "\x1B[?1049l";
@@ -30,8 +32,7 @@ var render = async (node) => {
30
32
  clear: instance.clear
31
33
  };
32
34
  };
33
-
34
35
  export {
35
36
  render
36
37
  };
37
- //# sourceMappingURL=chunk-UZVYEMEZ.js.map
38
+ //# sourceMappingURL=render-U36YSDSA.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bugbug-io/cli",
3
- "version": "13.39.2",
3
+ "version": "14.0.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "bugbug": "bin/bugbug.mjs"
@@ -59,4 +59,4 @@
59
59
  "engines": {
60
60
  "node": ">=24"
61
61
  }
62
- }
62
+ }
@@ -1,8 +0,0 @@
1
- import {
2
- render
3
- } from "./chunk-UZVYEMEZ.js";
4
- import "./chunk-PR4QN5HX.js";
5
- export {
6
- render
7
- };
8
- //# sourceMappingURL=render-RAJK5JCO.js.map