pubm 0.2.7 → 0.2.9

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 (4) hide show
  1. package/bin/cli.js +302 -114
  2. package/dist/index.cjs +435 -247
  3. package/dist/index.js +418 -230
  4. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -4486,9 +4486,129 @@ var Listr = (_a23 = class {
4486
4486
  // src/tasks/runner.ts
4487
4487
  var import_semver3 = __toESM(require("semver"), 1);
4488
4488
  var import_std_env = require("std-env");
4489
- var import_tinyexec8 = require("tinyexec");
4489
+ var import_tinyexec9 = require("tinyexec");
4490
+
4491
+ // src/ecosystem/rust.ts
4492
+ var import_promises2 = require("fs/promises");
4493
+ var import_node_path2 = __toESM(require("path"), 1);
4494
+ var import_smol_toml = require("smol-toml");
4495
+ var import_tinyexec = require("tinyexec");
4496
+
4497
+ // src/ecosystem/ecosystem.ts
4498
+ var Ecosystem = class {
4499
+ constructor(packagePath) {
4500
+ this.packagePath = packagePath;
4501
+ }
4502
+ };
4503
+
4504
+ // src/ecosystem/rust.ts
4505
+ var RustEcosystem = class extends Ecosystem {
4506
+ static async detect(packagePath) {
4507
+ try {
4508
+ return (await (0, import_promises2.stat)(import_node_path2.default.join(packagePath, "Cargo.toml"))).isFile();
4509
+ } catch {
4510
+ return false;
4511
+ }
4512
+ }
4513
+ async readCargoToml() {
4514
+ const raw = await (0, import_promises2.readFile)(
4515
+ import_node_path2.default.join(this.packagePath, "Cargo.toml"),
4516
+ "utf-8"
4517
+ );
4518
+ return (0, import_smol_toml.parse)(raw);
4519
+ }
4520
+ async packageName() {
4521
+ const cargo = await this.readCargoToml();
4522
+ const pkg = cargo.package;
4523
+ return pkg.name;
4524
+ }
4525
+ async readVersion() {
4526
+ const cargo = await this.readCargoToml();
4527
+ const pkg = cargo.package;
4528
+ return pkg.version;
4529
+ }
4530
+ async writeVersion(newVersion) {
4531
+ const filePath = import_node_path2.default.join(this.packagePath, "Cargo.toml");
4532
+ const raw = await (0, import_promises2.readFile)(filePath, "utf-8");
4533
+ const cargo = (0, import_smol_toml.parse)(raw);
4534
+ const pkg = cargo.package;
4535
+ pkg.version = newVersion;
4536
+ await (0, import_promises2.writeFile)(filePath, (0, import_smol_toml.stringify)(cargo));
4537
+ }
4538
+ /**
4539
+ * Update the `version` field of dependencies that match sibling crate names.
4540
+ * This ensures `cargo publish` works when crates depend on each other via path.
4541
+ */
4542
+ async updateSiblingDependencyVersions(siblingVersions) {
4543
+ const filePath = import_node_path2.default.join(this.packagePath, "Cargo.toml");
4544
+ const raw = await (0, import_promises2.readFile)(filePath, "utf-8");
4545
+ const cargo = (0, import_smol_toml.parse)(raw);
4546
+ let modified = false;
4547
+ for (const section of ["dependencies", "build-dependencies"]) {
4548
+ const sectionData = cargo[section];
4549
+ if (!sectionData) continue;
4550
+ for (const [depName, depValue] of Object.entries(sectionData)) {
4551
+ if (typeof depValue === "object" && depValue !== null && "path" in depValue && siblingVersions.has(depName)) {
4552
+ const dep = depValue;
4553
+ dep.version = siblingVersions.get(depName);
4554
+ modified = true;
4555
+ }
4556
+ }
4557
+ }
4558
+ if (modified) {
4559
+ await (0, import_promises2.writeFile)(filePath, (0, import_smol_toml.stringify)(cargo));
4560
+ }
4561
+ return modified;
4562
+ }
4563
+ async syncLockfile() {
4564
+ const lockfilePath = await this.findLockfile();
4565
+ if (!lockfilePath) return void 0;
4566
+ const name = await this.packageName();
4567
+ await (0, import_tinyexec.exec)("cargo", ["update", "--package", name], {
4568
+ nodeOptions: { cwd: import_node_path2.default.dirname(lockfilePath) }
4569
+ });
4570
+ return lockfilePath;
4571
+ }
4572
+ async findLockfile() {
4573
+ let dir = this.packagePath;
4574
+ const { root } = import_node_path2.default.parse(dir);
4575
+ while (dir !== root) {
4576
+ const candidate = import_node_path2.default.join(dir, "Cargo.lock");
4577
+ try {
4578
+ if ((await (0, import_promises2.stat)(candidate)).isFile()) return candidate;
4579
+ } catch {
4580
+ }
4581
+ dir = import_node_path2.default.dirname(dir);
4582
+ }
4583
+ return void 0;
4584
+ }
4585
+ async dependencies() {
4586
+ const cargo = await this.readCargoToml();
4587
+ const deps = [];
4588
+ for (const section of ["dependencies", "build-dependencies"]) {
4589
+ const sectionData = cargo[section];
4590
+ if (sectionData) {
4591
+ deps.push(...Object.keys(sectionData));
4592
+ }
4593
+ }
4594
+ return deps;
4595
+ }
4596
+ manifestFiles() {
4597
+ return ["Cargo.toml"];
4598
+ }
4599
+ defaultTestCommand() {
4600
+ return "cargo test";
4601
+ }
4602
+ defaultBuildCommand() {
4603
+ return "cargo build --release";
4604
+ }
4605
+ supportedRegistries() {
4606
+ return ["crates"];
4607
+ }
4608
+ };
4490
4609
 
4491
4610
  // src/error.ts
4611
+ var import_tinyexec2 = require("tinyexec");
4492
4612
  var AbstractError = class extends Error {
4493
4613
  constructor(message, { cause } = {}) {
4494
4614
  super(message, { cause });
@@ -4499,20 +4619,49 @@ var AbstractError = class extends Error {
4499
4619
  function replaceCode(code) {
4500
4620
  return code.replace(/`([^`].+)`/g, color.bold(color.underline("$1")));
4501
4621
  }
4622
+ function formatStderr(stderr) {
4623
+ return stderr.split("\n").map((line) => ` ${color.dim("\u2502")} ${line}`).join("\n");
4624
+ }
4625
+ function isNoisyCause(cause) {
4626
+ if (cause instanceof import_tinyexec2.NonZeroExitError) return true;
4627
+ if (cause instanceof Error && /Process exited with non-zero status/i.test(cause.message))
4628
+ return true;
4629
+ return false;
4630
+ }
4502
4631
  function formatError(error) {
4503
4632
  if (!(error instanceof Error)) return `${error}`;
4504
- const message = typeof error.message === "string" ? replaceCode(error.message) : (
4633
+ const rawMessage = typeof error.message === "string" ? error.message : (
4505
4634
  /* v8 ignore next */
4506
- formatError(error)
4635
+ String(error)
4507
4636
  );
4508
- let stringifyError = `${color.bgRed(` ${error.name} `)}${color.reset("")} ${message}
4637
+ const newlineIndex = rawMessage.indexOf("\n");
4638
+ let summary;
4639
+ let detail;
4640
+ if (newlineIndex !== -1) {
4641
+ summary = rawMessage.slice(0, newlineIndex);
4642
+ detail = rawMessage.slice(newlineIndex + 1);
4643
+ } else {
4644
+ summary = rawMessage;
4645
+ }
4646
+ let result = `${color.bgRed(` ${error.name} `)}${color.reset("")} ${replaceCode(summary)}
4647
+ `;
4648
+ if (detail) {
4649
+ result += `
4650
+ ${formatStderr(detail)}
4509
4651
  `;
4510
- stringifyError += error.stack?.split("\n").slice(1).join("\n").replace(/at/g, color.dim("at")).replace(/\(([^(].+)\)/g, `(${color.blue("$1")})`);
4511
- if (error.cause) {
4512
- stringifyError += "\n\nCaused: ";
4513
- stringifyError += formatError(error.cause);
4514
4652
  }
4515
- return stringifyError;
4653
+ if (process.env.DEBUG === "pubm" && error.stack) {
4654
+ result += error.stack.split("\n").slice(1).join("\n").replace(/at/g, color.dim("at")).replace(/\(([^(].+)\)/g, `(${color.blue("$1")})`);
4655
+ }
4656
+ if (error.cause && !isNoisyCause(error.cause)) {
4657
+ const causeMsg = error.cause instanceof Error ? error.cause.message : String(error.cause);
4658
+ if (causeMsg !== summary) {
4659
+ result += `
4660
+ ${color.dim("Caused by:")} `;
4661
+ result += formatError(error.cause);
4662
+ }
4663
+ }
4664
+ return result;
4516
4665
  }
4517
4666
  function consoleError(error) {
4518
4667
  let errorText = "\n";
@@ -4529,7 +4678,7 @@ function consoleError(error) {
4529
4678
 
4530
4679
  // src/git.ts
4531
4680
  var import_semver = __toESM(require("semver"), 1);
4532
- var import_tinyexec = require("tinyexec");
4681
+ var import_tinyexec3 = require("tinyexec");
4533
4682
  var GitError = class extends AbstractError {
4534
4683
  constructor() {
4535
4684
  super(...arguments);
@@ -4538,7 +4687,7 @@ var GitError = class extends AbstractError {
4538
4687
  };
4539
4688
  var Git = class {
4540
4689
  async git(args) {
4541
- const { stdout } = await (0, import_tinyexec.exec)("git", args, { throwOnError: true });
4690
+ const { stdout } = await (0, import_tinyexec3.exec)("git", args, { throwOnError: true });
4542
4691
  return stdout;
4543
4692
  }
4544
4693
  async userName() {
@@ -4792,7 +4941,7 @@ var Git = class {
4792
4941
  async push(options) {
4793
4942
  const args = ["push", options].filter((v) => v);
4794
4943
  try {
4795
- const { stderr } = await (0, import_tinyexec.exec)("git", args, { throwOnError: true });
4944
+ const { stderr } = await (0, import_tinyexec3.exec)("git", args, { throwOnError: true });
4796
4945
  if (`${stderr}`.includes("GH006")) {
4797
4946
  return false;
4798
4947
  }
@@ -4814,125 +4963,6 @@ function link2(text, url) {
4814
4963
  return `\x1B]8;;${url}\x07${text}\x1B]8;;\x07`;
4815
4964
  }
4816
4965
 
4817
- // src/ecosystem/rust.ts
4818
- var import_promises2 = require("fs/promises");
4819
- var import_node_path2 = __toESM(require("path"), 1);
4820
- var import_smol_toml = require("smol-toml");
4821
- var import_tinyexec2 = require("tinyexec");
4822
-
4823
- // src/ecosystem/ecosystem.ts
4824
- var Ecosystem = class {
4825
- constructor(packagePath) {
4826
- this.packagePath = packagePath;
4827
- }
4828
- };
4829
-
4830
- // src/ecosystem/rust.ts
4831
- var RustEcosystem = class extends Ecosystem {
4832
- static async detect(packagePath) {
4833
- try {
4834
- return (await (0, import_promises2.stat)(import_node_path2.default.join(packagePath, "Cargo.toml"))).isFile();
4835
- } catch {
4836
- return false;
4837
- }
4838
- }
4839
- async readCargoToml() {
4840
- const raw = await (0, import_promises2.readFile)(
4841
- import_node_path2.default.join(this.packagePath, "Cargo.toml"),
4842
- "utf-8"
4843
- );
4844
- return (0, import_smol_toml.parse)(raw);
4845
- }
4846
- async packageName() {
4847
- const cargo = await this.readCargoToml();
4848
- const pkg = cargo.package;
4849
- return pkg.name;
4850
- }
4851
- async readVersion() {
4852
- const cargo = await this.readCargoToml();
4853
- const pkg = cargo.package;
4854
- return pkg.version;
4855
- }
4856
- async writeVersion(newVersion) {
4857
- const filePath = import_node_path2.default.join(this.packagePath, "Cargo.toml");
4858
- const raw = await (0, import_promises2.readFile)(filePath, "utf-8");
4859
- const cargo = (0, import_smol_toml.parse)(raw);
4860
- const pkg = cargo.package;
4861
- pkg.version = newVersion;
4862
- await (0, import_promises2.writeFile)(filePath, (0, import_smol_toml.stringify)(cargo));
4863
- }
4864
- /**
4865
- * Update the `version` field of dependencies that match sibling crate names.
4866
- * This ensures `cargo publish` works when crates depend on each other via path.
4867
- */
4868
- async updateSiblingDependencyVersions(siblingVersions) {
4869
- const filePath = import_node_path2.default.join(this.packagePath, "Cargo.toml");
4870
- const raw = await (0, import_promises2.readFile)(filePath, "utf-8");
4871
- const cargo = (0, import_smol_toml.parse)(raw);
4872
- let modified = false;
4873
- for (const section of ["dependencies", "build-dependencies"]) {
4874
- const sectionData = cargo[section];
4875
- if (!sectionData) continue;
4876
- for (const [depName, depValue] of Object.entries(sectionData)) {
4877
- if (typeof depValue === "object" && depValue !== null && "path" in depValue && siblingVersions.has(depName)) {
4878
- const dep = depValue;
4879
- dep.version = siblingVersions.get(depName);
4880
- modified = true;
4881
- }
4882
- }
4883
- }
4884
- if (modified) {
4885
- await (0, import_promises2.writeFile)(filePath, (0, import_smol_toml.stringify)(cargo));
4886
- }
4887
- return modified;
4888
- }
4889
- async syncLockfile() {
4890
- const lockfilePath = await this.findLockfile();
4891
- if (!lockfilePath) return void 0;
4892
- const name = await this.packageName();
4893
- await (0, import_tinyexec2.exec)("cargo", ["update", "--package", name], {
4894
- nodeOptions: { cwd: import_node_path2.default.dirname(lockfilePath) }
4895
- });
4896
- return lockfilePath;
4897
- }
4898
- async findLockfile() {
4899
- let dir = this.packagePath;
4900
- const { root } = import_node_path2.default.parse(dir);
4901
- while (dir !== root) {
4902
- const candidate = import_node_path2.default.join(dir, "Cargo.lock");
4903
- try {
4904
- if ((await (0, import_promises2.stat)(candidate)).isFile()) return candidate;
4905
- } catch {
4906
- }
4907
- dir = import_node_path2.default.dirname(dir);
4908
- }
4909
- return void 0;
4910
- }
4911
- async dependencies() {
4912
- const cargo = await this.readCargoToml();
4913
- const deps = [];
4914
- for (const section of ["dependencies", "build-dependencies"]) {
4915
- const sectionData = cargo[section];
4916
- if (sectionData) {
4917
- deps.push(...Object.keys(sectionData));
4918
- }
4919
- }
4920
- return deps;
4921
- }
4922
- manifestFiles() {
4923
- return ["Cargo.toml"];
4924
- }
4925
- defaultTestCommand() {
4926
- return "cargo test";
4927
- }
4928
- defaultBuildCommand() {
4929
- return "cargo build --release";
4930
- }
4931
- supportedRegistries() {
4932
- return ["crates"];
4933
- }
4934
- };
4935
-
4936
4966
  // src/utils/crate-graph.ts
4937
4967
  async function sortCratesByDependencyOrder(cratePaths) {
4938
4968
  if (cratePaths.length <= 1) return cratePaths;
@@ -4985,12 +5015,19 @@ var rollbacks = [];
4985
5015
  function addRollback(rollback2, context) {
4986
5016
  rollbacks.push({ fn: rollback2, ctx: context });
4987
5017
  }
5018
+ function rollbackLog(message) {
5019
+ console.log(` ${color.yellow("\u21A9")} ${message}`);
5020
+ }
5021
+ function rollbackError(message) {
5022
+ console.error(` ${color.red("\u2717")} ${message}`);
5023
+ }
4988
5024
  var called = false;
4989
5025
  async function rollback() {
4990
5026
  if (called) return void 0;
4991
5027
  called = true;
4992
5028
  if (rollbacks.length <= 0) return void 0;
4993
- console.log("Rollback...");
5029
+ console.log(`
5030
+ ${color.yellow("\u27F2")} ${color.yellow("Rolling back...")}`);
4994
5031
  const results = await Promise.allSettled(
4995
5032
  rollbacks.map(({ fn, ctx }) => fn(ctx))
4996
5033
  );
@@ -4999,15 +5036,15 @@ async function rollback() {
4999
5036
  );
5000
5037
  if (failures.length > 0) {
5001
5038
  for (const failure of failures) {
5002
- console.error(
5003
- `Rollback operation failed: ${failure.reason instanceof Error ? failure.reason.message : failure.reason}`
5039
+ rollbackError(
5040
+ failure.reason instanceof Error ? failure.reason.message : failure.reason
5004
5041
  );
5005
5042
  }
5006
5043
  console.log(
5007
- "Rollback completed with errors. Some operations may require manual recovery."
5044
+ `${color.red("\u2717")} ${color.red("Rollback completed with errors.")} Some operations may require manual recovery.`
5008
5045
  );
5009
5046
  } else {
5010
- console.log("Rollback completed");
5047
+ console.log(`${color.green("\u2713")} Rollback completed`);
5011
5048
  }
5012
5049
  }
5013
5050
 
@@ -5415,7 +5452,7 @@ function injectTokensToEnv(tokens) {
5415
5452
 
5416
5453
  // src/registry/crates.ts
5417
5454
  var import_node_path5 = __toESM(require("path"), 1);
5418
- var import_tinyexec3 = require("tinyexec");
5455
+ var import_tinyexec4 = require("tinyexec");
5419
5456
 
5420
5457
  // src/registry/registry.ts
5421
5458
  var Registry = class {
@@ -5435,6 +5472,14 @@ var CratesError = class extends AbstractError {
5435
5472
  }
5436
5473
  };
5437
5474
  var USER_AGENT = "pubm (https://github.com/syi0808/pubm)";
5475
+ function cleanCargoStderr(stderr) {
5476
+ return stderr.split("\n").filter((line) => {
5477
+ const trimmed = line.trim();
5478
+ if (trimmed === "Updating crates.io index") return false;
5479
+ if (trimmed === "") return false;
5480
+ return true;
5481
+ }).join("\n");
5482
+ }
5438
5483
  var CratesRegistry = class extends Registry {
5439
5484
  constructor() {
5440
5485
  super(...arguments);
@@ -5455,7 +5500,7 @@ var CratesRegistry = class extends Registry {
5455
5500
  }
5456
5501
  async isInstalled() {
5457
5502
  try {
5458
- await (0, import_tinyexec3.exec)("cargo", ["--version"]);
5503
+ await (0, import_tinyexec4.exec)("cargo", ["--version"]);
5459
5504
  return true;
5460
5505
  } catch {
5461
5506
  return false;
@@ -5496,29 +5541,43 @@ var CratesRegistry = class extends Registry {
5496
5541
  if (manifestDir) {
5497
5542
  args.push("--manifest-path", import_node_path5.default.join(manifestDir, "Cargo.toml"));
5498
5543
  }
5499
- await (0, import_tinyexec3.exec)("cargo", args, { throwOnError: true });
5544
+ await (0, import_tinyexec4.exec)("cargo", args, { throwOnError: true });
5500
5545
  return true;
5501
5546
  } catch (error) {
5502
- const stderr = error instanceof import_tinyexec3.NonZeroExitError ? error.output?.stderr : void 0;
5547
+ const stderr = error instanceof import_tinyexec4.NonZeroExitError ? error.output?.stderr : void 0;
5503
5548
  const message = stderr ? `Failed to run \`cargo publish\`:
5504
- ${stderr}` : "Failed to run `cargo publish`";
5549
+ ${cleanCargoStderr(stderr)}` : "Failed to run `cargo publish`";
5505
5550
  throw new CratesError(message, { cause: error });
5506
5551
  }
5507
5552
  }
5508
5553
  async dryRunPublish(manifestDir) {
5509
5554
  try {
5510
- const args = ["publish", "--dry-run", "--no-verify"];
5555
+ const args = ["publish", "--dry-run"];
5511
5556
  if (manifestDir) {
5512
5557
  args.push("--manifest-path", import_node_path5.default.join(manifestDir, "Cargo.toml"));
5513
5558
  }
5514
- await (0, import_tinyexec3.exec)("cargo", args, { throwOnError: true });
5559
+ await (0, import_tinyexec4.exec)("cargo", args, { throwOnError: true });
5515
5560
  } catch (error) {
5516
- const stderr = error instanceof import_tinyexec3.NonZeroExitError ? error.output?.stderr : void 0;
5561
+ const stderr = error instanceof import_tinyexec4.NonZeroExitError ? error.output?.stderr : void 0;
5517
5562
  const message = stderr ? `Failed to run \`cargo publish --dry-run\`:
5518
- ${stderr}` : "Failed to run `cargo publish --dry-run`";
5563
+ ${cleanCargoStderr(stderr)}` : "Failed to run `cargo publish --dry-run`";
5519
5564
  throw new CratesError(message, { cause: error });
5520
5565
  }
5521
5566
  }
5567
+ async isVersionPublished(version2) {
5568
+ try {
5569
+ const response = await fetch(
5570
+ `${this.registry}/api/v1/crates/${this.packageName}/${version2}`,
5571
+ { headers: this.headers }
5572
+ );
5573
+ return response.ok;
5574
+ } catch (error) {
5575
+ throw new CratesError(
5576
+ `Failed to check version ${version2} for '${this.packageName}' on crates.io`,
5577
+ { cause: error }
5578
+ );
5579
+ }
5580
+ }
5522
5581
  async isPublished() {
5523
5582
  try {
5524
5583
  const response = await fetch(
@@ -5595,10 +5654,24 @@ function createCratesPublishTask(packagePath) {
5595
5654
  const label = packagePath ? ` (${packagePath})` : "";
5596
5655
  return {
5597
5656
  title: `Publishing to crates.io${label}`,
5598
- task: async () => {
5657
+ task: async (ctx, task) => {
5599
5658
  const packageName = await getCrateName(packagePath);
5600
5659
  const registry = new CratesRegistry(packageName);
5601
- await registry.publish(packagePath);
5660
+ if (await registry.isVersionPublished(ctx.version)) {
5661
+ task.title = `[SKIPPED] crates.io${label}: v${ctx.version} already published`;
5662
+ task.output = `\u26A0 ${packageName}@${ctx.version} is already published on crates.io`;
5663
+ return task.skip();
5664
+ }
5665
+ try {
5666
+ await registry.publish(packagePath);
5667
+ } catch (error) {
5668
+ if (error instanceof Error && error.message.includes("is already uploaded")) {
5669
+ task.title = `[SKIPPED] crates.io${label}: v${ctx.version} already published`;
5670
+ task.output = `\u26A0 ${packageName}@${ctx.version} is already published on crates.io`;
5671
+ return task.skip();
5672
+ }
5673
+ throw error;
5674
+ }
5602
5675
  }
5603
5676
  };
5604
5677
  }
@@ -5609,7 +5682,7 @@ var cratesPublishTasks = createCratesPublishTask();
5609
5682
  var import_prompt_adapter_enquirer = require("@listr2/prompt-adapter-enquirer");
5610
5683
 
5611
5684
  // src/registry/jsr.ts
5612
- var import_tinyexec4 = require("tinyexec");
5685
+ var import_tinyexec5 = require("tinyexec");
5613
5686
 
5614
5687
  // src/utils/package-name.ts
5615
5688
  var import_node_module = require("module");
@@ -5677,7 +5750,7 @@ var JsrRegisry = class extends Registry {
5677
5750
  this.client = new JsrClient(getApiEndpoint(this.registry));
5678
5751
  }
5679
5752
  async jsr(args) {
5680
- const { stdout } = await (0, import_tinyexec4.exec)("jsr", args, { throwOnError: true });
5753
+ const { stdout } = await (0, import_tinyexec5.exec)("jsr", args, { throwOnError: true });
5681
5754
  return stdout;
5682
5755
  }
5683
5756
  async isInstalled() {
@@ -5693,7 +5766,7 @@ var JsrRegisry = class extends Registry {
5693
5766
  }
5694
5767
  async ping() {
5695
5768
  try {
5696
- const { stdout } = await (0, import_tinyexec4.exec)(
5769
+ const { stdout } = await (0, import_tinyexec5.exec)(
5697
5770
  "ping",
5698
5771
  [new URL(this.registry).hostname, "-c", "1"],
5699
5772
  { throwOnError: true }
@@ -5708,7 +5781,7 @@ var JsrRegisry = class extends Registry {
5708
5781
  }
5709
5782
  async publish() {
5710
5783
  try {
5711
- await (0, import_tinyexec4.exec)(
5784
+ await (0, import_tinyexec5.exec)(
5712
5785
  "jsr",
5713
5786
  ["publish", "--allow-dirty", "--token", `${JsrClient.token}`],
5714
5787
  {
@@ -5718,7 +5791,7 @@ var JsrRegisry = class extends Registry {
5718
5791
  this.packageCreationUrls = void 0;
5719
5792
  return true;
5720
5793
  } catch (error) {
5721
- const stderr = error instanceof import_tinyexec4.NonZeroExitError ? error.output?.stderr : void 0;
5794
+ const stderr = error instanceof import_tinyexec5.NonZeroExitError ? error.output?.stderr : void 0;
5722
5795
  if (stderr?.includes("don't exist")) {
5723
5796
  const urls = [...stderr.matchAll(/https:\/\/jsr\.io\/new\S+/g)].map(
5724
5797
  (m) => m[0]
@@ -5739,7 +5812,7 @@ ${stderr}` : ""}`,
5739
5812
  }
5740
5813
  async dryRunPublish() {
5741
5814
  try {
5742
- await (0, import_tinyexec4.exec)(
5815
+ await (0, import_tinyexec5.exec)(
5743
5816
  "jsr",
5744
5817
  [
5745
5818
  "publish",
@@ -5770,6 +5843,20 @@ ${stderr}` : ""}`,
5770
5843
  );
5771
5844
  }
5772
5845
  }
5846
+ async isVersionPublished(version2) {
5847
+ try {
5848
+ const [scope, name] = getScopeAndName(this.packageName);
5849
+ const response = await fetch(
5850
+ `${this.registry}/@${scope}/${name}/${version2}`
5851
+ );
5852
+ return response.status === 200;
5853
+ } catch (error) {
5854
+ throw new JsrError(
5855
+ `Failed to fetch \`${this.registry}/${this.packageName}/${version2}\``,
5856
+ { cause: error }
5857
+ );
5858
+ }
5859
+ }
5773
5860
  async hasPermission() {
5774
5861
  return this.client.scopePermission(`${getScope(this.packageName)}`) !== null;
5775
5862
  }
@@ -5999,7 +6086,7 @@ async function jsrRegistry() {
5999
6086
  // src/registry/npm.ts
6000
6087
  var import_node_os = require("os");
6001
6088
  var import_node_path6 = require("path");
6002
- var import_tinyexec5 = require("tinyexec");
6089
+ var import_tinyexec6 = require("tinyexec");
6003
6090
  var NpmError = class extends AbstractError {
6004
6091
  constructor() {
6005
6092
  super(...arguments);
@@ -6012,7 +6099,7 @@ var NpmRegistry = class extends Registry {
6012
6099
  __publicField(this, "registry", "https://registry.npmjs.org");
6013
6100
  }
6014
6101
  async npm(args) {
6015
- const { stdout } = await (0, import_tinyexec5.exec)("npm", args, { throwOnError: true });
6102
+ const { stdout } = await (0, import_tinyexec6.exec)("npm", args, { throwOnError: true });
6016
6103
  return stdout;
6017
6104
  }
6018
6105
  async isInstalled() {
@@ -6044,6 +6131,19 @@ var NpmRegistry = class extends Registry {
6044
6131
  );
6045
6132
  }
6046
6133
  }
6134
+ async isVersionPublished(version2) {
6135
+ try {
6136
+ const response = await fetch(
6137
+ `${this.registry}/${this.packageName}/${version2}`
6138
+ );
6139
+ return response.status === 200;
6140
+ } catch (error) {
6141
+ throw new NpmError(
6142
+ `Failed to fetch \`${this.registry}/${this.packageName}/${version2}\``,
6143
+ { cause: error }
6144
+ );
6145
+ }
6146
+ }
6047
6147
  async userName() {
6048
6148
  try {
6049
6149
  return (await this.npm(["whoami"])).trim();
@@ -6056,7 +6156,7 @@ var NpmRegistry = class extends Registry {
6056
6156
  await this.npm(["whoami"]);
6057
6157
  return true;
6058
6158
  } catch (error) {
6059
- if (error instanceof import_tinyexec5.NonZeroExitError) {
6159
+ if (error instanceof import_tinyexec6.NonZeroExitError) {
6060
6160
  return false;
6061
6161
  }
6062
6162
  throw new NpmError("Failed to run `npm whoami`", { cause: error });
@@ -6123,7 +6223,7 @@ var NpmRegistry = class extends Registry {
6123
6223
  }
6124
6224
  async ping() {
6125
6225
  try {
6126
- await (0, import_tinyexec5.exec)("npm", ["ping"], { throwOnError: true });
6226
+ await (0, import_tinyexec6.exec)("npm", ["ping"], { throwOnError: true });
6127
6227
  return true;
6128
6228
  } catch (error) {
6129
6229
  throw new NpmError("Failed to run `npm ping`", { cause: error });
@@ -6134,7 +6234,7 @@ var NpmRegistry = class extends Registry {
6134
6234
  await this.npm(["publish", "--provenance", "--access", "public"]);
6135
6235
  return true;
6136
6236
  } catch (error) {
6137
- if (error instanceof import_tinyexec5.NonZeroExitError && error.output?.stderr.includes("EOTP")) {
6237
+ if (error instanceof import_tinyexec6.NonZeroExitError && error.output?.stderr.includes("EOTP")) {
6138
6238
  return false;
6139
6239
  }
6140
6240
  throw this.classifyPublishError(error);
@@ -6146,7 +6246,7 @@ var NpmRegistry = class extends Registry {
6146
6246
  await this.npm(args);
6147
6247
  return true;
6148
6248
  } catch (error) {
6149
- if (error instanceof import_tinyexec5.NonZeroExitError && error.output?.stderr.includes("EOTP")) {
6249
+ if (error instanceof import_tinyexec6.NonZeroExitError && error.output?.stderr.includes("EOTP")) {
6150
6250
  return false;
6151
6251
  }
6152
6252
  throw this.classifyPublishError(error);
@@ -6154,7 +6254,7 @@ var NpmRegistry = class extends Registry {
6154
6254
  }
6155
6255
  async dryRunPublish() {
6156
6256
  try {
6157
- await (0, import_tinyexec5.exec)("npm", ["publish", "--dry-run"], {
6257
+ await (0, import_tinyexec6.exec)("npm", ["publish", "--dry-run"], {
6158
6258
  throwOnError: true,
6159
6259
  nodeOptions: {
6160
6260
  env: {
@@ -6164,7 +6264,7 @@ var NpmRegistry = class extends Registry {
6164
6264
  }
6165
6265
  });
6166
6266
  } catch (error) {
6167
- const stderr = error instanceof import_tinyexec5.NonZeroExitError ? error.output?.stderr : void 0;
6267
+ const stderr = error instanceof import_tinyexec6.NonZeroExitError ? error.output?.stderr : void 0;
6168
6268
  throw new NpmError(
6169
6269
  `Failed to run \`npm publish --dry-run\`${stderr ? `
6170
6270
  ${stderr}` : ""}`,
@@ -6191,7 +6291,7 @@ ${stderr}` : ""}`,
6191
6291
  };
6192
6292
  }
6193
6293
  classifyPublishError(error) {
6194
- if (error instanceof import_tinyexec5.NonZeroExitError) {
6294
+ if (error instanceof import_tinyexec6.NonZeroExitError) {
6195
6295
  const stderr = error.output?.stderr ?? "";
6196
6296
  if (stderr.includes("EOTP")) {
6197
6297
  return new NpmError("OTP required for publishing", { cause: error });
@@ -6249,20 +6349,30 @@ async function withTokenRetry(registryKey, task, action) {
6249
6349
  }
6250
6350
  var npmDryRunPublishTask = {
6251
6351
  title: "Dry-run npm publish",
6252
- task: async (_, task) => {
6352
+ task: async (ctx, task) => {
6353
+ const npm = await npmRegistry();
6354
+ if (await npm.isVersionPublished(ctx.version)) {
6355
+ task.title = `[SKIPPED] Dry-run npm publish: v${ctx.version} already published`;
6356
+ task.output = `\u26A0 ${npm.packageName}@${ctx.version} is already published on npm`;
6357
+ return task.skip();
6358
+ }
6253
6359
  task.output = "Running npm publish --dry-run...";
6254
6360
  await withTokenRetry("npm", task, async () => {
6255
- const npm = await npmRegistry();
6256
6361
  await npm.dryRunPublish();
6257
6362
  });
6258
6363
  }
6259
6364
  };
6260
6365
  var jsrDryRunPublishTask = {
6261
6366
  title: "Dry-run jsr publish",
6262
- task: async (_, task) => {
6367
+ task: async (ctx, task) => {
6368
+ const jsr = await jsrRegistry();
6369
+ if (await jsr.isVersionPublished(ctx.version)) {
6370
+ task.title = `[SKIPPED] Dry-run jsr publish: v${ctx.version} already published`;
6371
+ task.output = `\u26A0 ${jsr.packageName}@${ctx.version} is already published on jsr`;
6372
+ return task.skip();
6373
+ }
6263
6374
  task.output = "Running jsr publish --dry-run...";
6264
6375
  await withTokenRetry("jsr", task, async () => {
6265
- const jsr = await jsrRegistry();
6266
6376
  await jsr.dryRunPublish();
6267
6377
  });
6268
6378
  }
@@ -6271,17 +6381,58 @@ async function getCrateName2(packagePath) {
6271
6381
  const eco = new RustEcosystem(packagePath ?? process.cwd());
6272
6382
  return await eco.packageName();
6273
6383
  }
6274
- function createCratesDryRunPublishTask(packagePath) {
6384
+ var MISSING_CRATE_PATTERN = /no matching package named `([^`]+)` found/;
6385
+ async function findUnpublishedSiblingDeps(packagePath, siblingCrateNames) {
6386
+ const eco = new RustEcosystem(packagePath ?? process.cwd());
6387
+ const deps = await eco.dependencies();
6388
+ const siblingDeps = deps.filter((d2) => siblingCrateNames.includes(d2));
6389
+ const results = await Promise.all(
6390
+ siblingDeps.map(async (name) => {
6391
+ const registry = new CratesRegistry(name);
6392
+ const published = await registry.isPublished();
6393
+ return published ? null : name;
6394
+ })
6395
+ );
6396
+ return results.filter((name) => name !== null);
6397
+ }
6398
+ function createCratesDryRunPublishTask(packagePath, siblingCrateNames) {
6275
6399
  const label = packagePath ? ` (${packagePath})` : "";
6276
6400
  return {
6277
6401
  title: `Dry-run crates.io publish${label}`,
6278
- task: async (_, task) => {
6402
+ task: async (ctx, task) => {
6403
+ const packageName = await getCrateName2(packagePath);
6404
+ const registry = new CratesRegistry(packageName);
6405
+ if (await registry.isVersionPublished(ctx.version)) {
6406
+ task.title = `[SKIPPED] Dry-run crates.io publish${label}: v${ctx.version} already published`;
6407
+ task.output = `\u26A0 ${packageName}@${ctx.version} is already published on crates.io`;
6408
+ return task.skip();
6409
+ }
6410
+ if (siblingCrateNames?.length) {
6411
+ const unpublished = await findUnpublishedSiblingDeps(
6412
+ packagePath,
6413
+ siblingCrateNames
6414
+ );
6415
+ if (unpublished.length > 0) {
6416
+ task.title = `Dry-run crates.io publish${label} [skipped: sibling crate \`${unpublished.join("`, `")}\` not yet published]`;
6417
+ return;
6418
+ }
6419
+ }
6279
6420
  task.output = "Running cargo publish --dry-run...";
6280
- await withTokenRetry("crates", task, async () => {
6281
- const packageName = await getCrateName2(packagePath);
6282
- const registry = new CratesRegistry(packageName);
6283
- await registry.dryRunPublish(packagePath);
6284
- });
6421
+ try {
6422
+ await withTokenRetry("crates", task, async () => {
6423
+ const packageName2 = await getCrateName2(packagePath);
6424
+ const registry2 = new CratesRegistry(packageName2);
6425
+ await registry2.dryRunPublish(packagePath);
6426
+ });
6427
+ } catch (error) {
6428
+ const message = error instanceof Error ? error.message : String(error);
6429
+ const match = message.match(MISSING_CRATE_PATTERN);
6430
+ if (match && siblingCrateNames?.includes(match[1])) {
6431
+ task.title = `Dry-run crates.io publish${label} [skipped: sibling crate \`${match[1]}\` not yet published]`;
6432
+ return;
6433
+ }
6434
+ throw error;
6435
+ }
6285
6436
  }
6286
6437
  };
6287
6438
  }
@@ -6462,48 +6613,62 @@ var jsrPublishTasks = {
6462
6613
  title: "Running jsr publish",
6463
6614
  task: async (ctx, task) => {
6464
6615
  const jsr = await jsrRegistry();
6616
+ if (await jsr.isVersionPublished(ctx.version)) {
6617
+ task.title = `[SKIPPED] jsr: v${ctx.version} already published`;
6618
+ task.output = `\u26A0 ${jsr.packageName}@${ctx.version} is already published on jsr`;
6619
+ return task.skip();
6620
+ }
6465
6621
  task.output = "Publishing on jsr...";
6466
- if (!JsrClient.token && !ctx.promptEnabled) {
6467
- const jsrTokenEnv = import_node_process6.default.env.JSR_TOKEN;
6468
- if (!jsrTokenEnv) {
6469
- throw new JsrAvailableError(
6470
- "JSR_TOKEN not found in the environment variables. Please set the token and try again."
6471
- );
6622
+ try {
6623
+ if (!JsrClient.token && !ctx.promptEnabled) {
6624
+ const jsrTokenEnv = import_node_process6.default.env.JSR_TOKEN;
6625
+ if (!jsrTokenEnv) {
6626
+ throw new JsrAvailableError(
6627
+ "JSR_TOKEN not found in the environment variables. Please set the token and try again."
6628
+ );
6629
+ }
6630
+ JsrClient.token = jsrTokenEnv;
6472
6631
  }
6473
- JsrClient.token = jsrTokenEnv;
6474
- }
6475
- let result = await jsr.publish();
6476
- if (!result && jsr.packageCreationUrls) {
6477
- if (ctx.promptEnabled) {
6478
- task.title = "Running jsr publish (package creation needed)";
6479
- const urls = jsr.packageCreationUrls;
6480
- const maxAttempts = 3;
6481
- task.output = `Package doesn't exist on jsr. Create it at:
6632
+ let result = await jsr.publish();
6633
+ if (!result && jsr.packageCreationUrls) {
6634
+ if (ctx.promptEnabled) {
6635
+ task.title = "Running jsr publish (package creation needed)";
6636
+ const urls = jsr.packageCreationUrls;
6637
+ const maxAttempts = 3;
6638
+ task.output = `Package doesn't exist on jsr. Create it at:
6482
6639
  ${urls.map((url) => ` ${color.cyan(url)}`).join("\n")}`;
6483
- open(urls[0]);
6484
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
6485
- await task.prompt(import_prompt_adapter_enquirer2.ListrEnquirerPromptAdapter).run({
6486
- type: "input",
6487
- message: `Press ${color.bold("enter")} after creating the package on jsr.io${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
6488
- });
6489
- result = await jsr.publish();
6490
- if (result) break;
6491
- if (attempt < maxAttempts) {
6492
- task.output = "Package still doesn't exist. Please create it and try again.";
6640
+ open(urls[0]);
6641
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
6642
+ await task.prompt(import_prompt_adapter_enquirer2.ListrEnquirerPromptAdapter).run({
6643
+ type: "input",
6644
+ message: `Press ${color.bold("enter")} after creating the package on jsr.io${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
6645
+ });
6646
+ result = await jsr.publish();
6647
+ if (result) break;
6648
+ if (attempt < maxAttempts) {
6649
+ task.output = "Package still doesn't exist. Please create it and try again.";
6650
+ }
6493
6651
  }
6494
- }
6495
- if (!result) {
6652
+ if (!result) {
6653
+ throw new JsrAvailableError(
6654
+ "Package creation not completed after 3 attempts."
6655
+ );
6656
+ }
6657
+ task.title = "Running jsr publish (package created)";
6658
+ } else {
6496
6659
  throw new JsrAvailableError(
6497
- "Package creation not completed after 3 attempts."
6660
+ `Package doesn't exist on jsr. Create it at:
6661
+ ${jsr.packageCreationUrls.join("\n")}`
6498
6662
  );
6499
6663
  }
6500
- task.title = "Running jsr publish (package created)";
6501
- } else {
6502
- throw new JsrAvailableError(
6503
- `Package doesn't exist on jsr. Create it at:
6504
- ${jsr.packageCreationUrls.join("\n")}`
6505
- );
6506
6664
  }
6665
+ } catch (error) {
6666
+ if (error instanceof Error && error.message.includes("already published")) {
6667
+ task.title = `[SKIPPED] jsr: v${ctx.version} already published`;
6668
+ task.output = `\u26A0 ${jsr.packageName}@${ctx.version} is already published on jsr`;
6669
+ return task.skip();
6670
+ }
6671
+ throw error;
6507
6672
  }
6508
6673
  }
6509
6674
  };
@@ -6600,44 +6765,62 @@ var npmPublishTasks = {
6600
6765
  skip: (ctx) => !!ctx.preview,
6601
6766
  task: async (ctx, task) => {
6602
6767
  const npm = await npmRegistry();
6768
+ if (await npm.isVersionPublished(ctx.version)) {
6769
+ task.title = `[SKIPPED] npm: v${ctx.version} already published`;
6770
+ task.output = `\u26A0 ${npm.packageName}@${ctx.version} is already published on npm`;
6771
+ return task.skip();
6772
+ }
6603
6773
  task.output = "Publishing on npm...";
6604
- if (ctx.promptEnabled) {
6605
- let result = await npm.publish();
6606
- if (!result) {
6607
- task.title = "Running npm publish (OTP code needed)";
6608
- const maxAttempts = 3;
6609
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
6610
- result = await npm.publish(
6611
- await task.prompt(import_prompt_adapter_enquirer3.ListrEnquirerPromptAdapter).run({
6612
- type: "password",
6613
- message: `npm OTP code${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
6614
- })
6615
- );
6616
- if (result) break;
6617
- if (attempt < maxAttempts) {
6618
- task.output = "2FA failed. Please try again.";
6774
+ try {
6775
+ if (ctx.promptEnabled) {
6776
+ let result = await npm.publish();
6777
+ if (!result) {
6778
+ task.title = "Running npm publish (OTP code needed)";
6779
+ const maxAttempts = 3;
6780
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
6781
+ result = await npm.publish(
6782
+ await task.prompt(import_prompt_adapter_enquirer3.ListrEnquirerPromptAdapter).run({
6783
+ type: "password",
6784
+ message: `npm OTP code${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
6785
+ })
6786
+ );
6787
+ if (result) break;
6788
+ if (attempt < maxAttempts) {
6789
+ task.output = "2FA failed. Please try again.";
6790
+ }
6791
+ }
6792
+ if (!result) {
6793
+ throw new NpmAvailableError(
6794
+ "OTP verification failed after 3 attempts."
6795
+ );
6619
6796
  }
6797
+ task.title = "Running npm publish (2FA passed)";
6798
+ }
6799
+ } else {
6800
+ const npmTokenEnv = import_node_process7.default.env.NODE_AUTH_TOKEN;
6801
+ if (!npmTokenEnv) {
6802
+ throw new NpmAvailableError(
6803
+ "NODE_AUTH_TOKEN not found in environment variables. Set it in your CI configuration:\n GitHub Actions: Add NODE_AUTH_TOKEN as a repository secret\n Other CI: Export NODE_AUTH_TOKEN with your npm access token"
6804
+ );
6620
6805
  }
6806
+ const result = await npm.publishProvenance();
6621
6807
  if (!result) {
6622
6808
  throw new NpmAvailableError(
6623
- "OTP verification failed after 3 attempts."
6809
+ `In CI environment, publishing with 2FA is not allowed. Please disable 2FA when accessing with a token from https://www.npmjs.com/package/${npm.packageName}/access `
6624
6810
  );
6625
6811
  }
6626
- task.title = "Running npm publish (2FA passed)";
6627
- }
6628
- } else {
6629
- const npmTokenEnv = import_node_process7.default.env.NODE_AUTH_TOKEN;
6630
- if (!npmTokenEnv) {
6631
- throw new NpmAvailableError(
6632
- "NODE_AUTH_TOKEN not found in environment variables. Set it in your CI configuration:\n GitHub Actions: Add NODE_AUTH_TOKEN as a repository secret\n Other CI: Export NODE_AUTH_TOKEN with your npm access token"
6633
- );
6634
6812
  }
6635
- const result = await npm.publishProvenance();
6636
- if (!result) {
6637
- throw new NpmAvailableError(
6638
- `In CI environment, publishing with 2FA is not allowed. Please disable 2FA when accessing with a token from https://www.npmjs.com/package/${npm.packageName}/access `
6639
- );
6813
+ } catch (error) {
6814
+ if (error instanceof Error && (error.message.includes(
6815
+ "cannot publish over the previously published"
6816
+ ) || error.message.includes(
6817
+ "You cannot publish over the previously published"
6818
+ ))) {
6819
+ task.title = `[SKIPPED] npm: v${ctx.version} already published`;
6820
+ task.output = `\u26A0 ${npm.packageName}@${ctx.version} is already published on npm`;
6821
+ return task.skip();
6640
6822
  }
6823
+ throw error;
6641
6824
  }
6642
6825
  }
6643
6826
  };
@@ -6645,7 +6828,7 @@ var npmPublishTasks = {
6645
6828
  // src/tasks/preflight.ts
6646
6829
  var import_node_crypto2 = require("crypto");
6647
6830
  var import_prompt_adapter_enquirer4 = require("@listr2/prompt-adapter-enquirer");
6648
- var import_tinyexec6 = require("tinyexec");
6831
+ var import_tinyexec7 = require("tinyexec");
6649
6832
  var PreflightError = class extends AbstractError {
6650
6833
  constructor() {
6651
6834
  super(...arguments);
@@ -6672,7 +6855,7 @@ async function syncGhSecrets(tokens) {
6672
6855
  for (const [registry, token] of Object.entries(tokens)) {
6673
6856
  const config = TOKEN_CONFIG[registry];
6674
6857
  if (!config) continue;
6675
- const result = (0, import_tinyexec6.exec)("gh", ["secret", "set", config.ghSecretName], {
6858
+ const result = (0, import_tinyexec7.exec)("gh", ["secret", "set", config.ghSecretName], {
6676
6859
  throwOnError: true
6677
6860
  });
6678
6861
  const proc = result.process;
@@ -6866,10 +7049,10 @@ var prerequisitesCheckTask = (options) => {
6866
7049
  var import_prompt_adapter_enquirer6 = require("@listr2/prompt-adapter-enquirer");
6867
7050
 
6868
7051
  // src/registry/custom-registry.ts
6869
- var import_tinyexec7 = require("tinyexec");
7052
+ var import_tinyexec8 = require("tinyexec");
6870
7053
  var CustomRegistry = class extends NpmRegistry {
6871
7054
  async npm(args) {
6872
- const { stdout } = await (0, import_tinyexec7.exec)(
7055
+ const { stdout } = await (0, import_tinyexec8.exec)(
6873
7056
  "npm",
6874
7057
  args.concat("--registry", this.registry),
6875
7058
  { throwOnError: true }
@@ -7128,10 +7311,15 @@ async function collectDryRunPublishTasks(ctx) {
7128
7311
  return nonCratesTasks;
7129
7312
  }
7130
7313
  const sortedPaths = await sortCratesByDependencyOrder(cratesPaths);
7314
+ const siblingCrateNames = await Promise.all(
7315
+ cratesPaths.map((p) => new RustEcosystem(p).packageName())
7316
+ );
7131
7317
  const sequentialCratesTask = {
7132
7318
  title: "Dry-run crates.io publish (sequential)",
7133
7319
  task: (_ctx, task) => task.newListr(
7134
- sortedPaths.map((p) => createCratesDryRunPublishTask(p)),
7320
+ sortedPaths.map(
7321
+ (p) => createCratesDryRunPublishTask(p, siblingCrateNames)
7322
+ ),
7135
7323
  { concurrent: false }
7136
7324
  )
7137
7325
  };
@@ -7186,7 +7374,7 @@ async function run(options) {
7186
7374
  task: async (ctx2) => {
7187
7375
  const packageManager = await getPackageManager();
7188
7376
  try {
7189
- await (0, import_tinyexec8.exec)(packageManager, ["run", ctx2.testScript], {
7377
+ await (0, import_tinyexec9.exec)(packageManager, ["run", ctx2.testScript], {
7190
7378
  throwOnError: true
7191
7379
  });
7192
7380
  } catch (error) {
@@ -7203,7 +7391,7 @@ async function run(options) {
7203
7391
  task: async (ctx2) => {
7204
7392
  const packageManager = await getPackageManager();
7205
7393
  try {
7206
- await (0, import_tinyexec8.exec)(packageManager, ["run", ctx2.buildScript], {
7394
+ await (0, import_tinyexec9.exec)(packageManager, ["run", ctx2.buildScript], {
7207
7395
  throwOnError: true
7208
7396
  });
7209
7397
  } catch (error) {
@@ -7224,23 +7412,23 @@ async function run(options) {
7224
7412
  addRollback(async () => {
7225
7413
  if (tagCreated) {
7226
7414
  try {
7227
- console.log("Deleting tag...");
7415
+ rollbackLog("Deleting tag");
7228
7416
  await git.deleteTag(`${await git.latestTag()}`);
7229
7417
  } catch (error) {
7230
- console.error(
7418
+ rollbackError(
7231
7419
  `Failed to delete tag: ${error instanceof Error ? error.message : error}`
7232
7420
  );
7233
7421
  }
7234
7422
  }
7235
7423
  if (commited) {
7236
7424
  try {
7237
- console.log("Reset commits...");
7425
+ rollbackLog("Resetting commits");
7238
7426
  await git.reset();
7239
7427
  await git.stash();
7240
7428
  await git.reset("HEAD^", "--hard");
7241
7429
  await git.popStash();
7242
7430
  } catch (error) {
7243
- console.error(
7431
+ rollbackError(
7244
7432
  `Failed to reset commits: ${error instanceof Error ? error.message : error}`
7245
7433
  );
7246
7434
  }