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.
- package/bin/cli.js +302 -114
- package/dist/index.cjs +435 -247
- package/dist/index.js +418 -230
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4455,7 +4455,127 @@ import SemVer from "semver";
|
|
|
4455
4455
|
import { isCI as isCI2 } from "std-env";
|
|
4456
4456
|
import { exec as exec9 } from "tinyexec";
|
|
4457
4457
|
|
|
4458
|
+
// src/ecosystem/rust.ts
|
|
4459
|
+
import { readFile, stat as stat2, writeFile } from "node:fs/promises";
|
|
4460
|
+
import path2 from "node:path";
|
|
4461
|
+
import { parse, stringify } from "smol-toml";
|
|
4462
|
+
import { exec as exec2 } from "tinyexec";
|
|
4463
|
+
|
|
4464
|
+
// src/ecosystem/ecosystem.ts
|
|
4465
|
+
var Ecosystem = class {
|
|
4466
|
+
constructor(packagePath) {
|
|
4467
|
+
this.packagePath = packagePath;
|
|
4468
|
+
}
|
|
4469
|
+
};
|
|
4470
|
+
|
|
4471
|
+
// src/ecosystem/rust.ts
|
|
4472
|
+
var RustEcosystem = class extends Ecosystem {
|
|
4473
|
+
static async detect(packagePath) {
|
|
4474
|
+
try {
|
|
4475
|
+
return (await stat2(path2.join(packagePath, "Cargo.toml"))).isFile();
|
|
4476
|
+
} catch {
|
|
4477
|
+
return false;
|
|
4478
|
+
}
|
|
4479
|
+
}
|
|
4480
|
+
async readCargoToml() {
|
|
4481
|
+
const raw = await readFile(
|
|
4482
|
+
path2.join(this.packagePath, "Cargo.toml"),
|
|
4483
|
+
"utf-8"
|
|
4484
|
+
);
|
|
4485
|
+
return parse(raw);
|
|
4486
|
+
}
|
|
4487
|
+
async packageName() {
|
|
4488
|
+
const cargo = await this.readCargoToml();
|
|
4489
|
+
const pkg = cargo.package;
|
|
4490
|
+
return pkg.name;
|
|
4491
|
+
}
|
|
4492
|
+
async readVersion() {
|
|
4493
|
+
const cargo = await this.readCargoToml();
|
|
4494
|
+
const pkg = cargo.package;
|
|
4495
|
+
return pkg.version;
|
|
4496
|
+
}
|
|
4497
|
+
async writeVersion(newVersion) {
|
|
4498
|
+
const filePath = path2.join(this.packagePath, "Cargo.toml");
|
|
4499
|
+
const raw = await readFile(filePath, "utf-8");
|
|
4500
|
+
const cargo = parse(raw);
|
|
4501
|
+
const pkg = cargo.package;
|
|
4502
|
+
pkg.version = newVersion;
|
|
4503
|
+
await writeFile(filePath, stringify(cargo));
|
|
4504
|
+
}
|
|
4505
|
+
/**
|
|
4506
|
+
* Update the `version` field of dependencies that match sibling crate names.
|
|
4507
|
+
* This ensures `cargo publish` works when crates depend on each other via path.
|
|
4508
|
+
*/
|
|
4509
|
+
async updateSiblingDependencyVersions(siblingVersions) {
|
|
4510
|
+
const filePath = path2.join(this.packagePath, "Cargo.toml");
|
|
4511
|
+
const raw = await readFile(filePath, "utf-8");
|
|
4512
|
+
const cargo = parse(raw);
|
|
4513
|
+
let modified = false;
|
|
4514
|
+
for (const section of ["dependencies", "build-dependencies"]) {
|
|
4515
|
+
const sectionData = cargo[section];
|
|
4516
|
+
if (!sectionData) continue;
|
|
4517
|
+
for (const [depName, depValue] of Object.entries(sectionData)) {
|
|
4518
|
+
if (typeof depValue === "object" && depValue !== null && "path" in depValue && siblingVersions.has(depName)) {
|
|
4519
|
+
const dep = depValue;
|
|
4520
|
+
dep.version = siblingVersions.get(depName);
|
|
4521
|
+
modified = true;
|
|
4522
|
+
}
|
|
4523
|
+
}
|
|
4524
|
+
}
|
|
4525
|
+
if (modified) {
|
|
4526
|
+
await writeFile(filePath, stringify(cargo));
|
|
4527
|
+
}
|
|
4528
|
+
return modified;
|
|
4529
|
+
}
|
|
4530
|
+
async syncLockfile() {
|
|
4531
|
+
const lockfilePath = await this.findLockfile();
|
|
4532
|
+
if (!lockfilePath) return void 0;
|
|
4533
|
+
const name = await this.packageName();
|
|
4534
|
+
await exec2("cargo", ["update", "--package", name], {
|
|
4535
|
+
nodeOptions: { cwd: path2.dirname(lockfilePath) }
|
|
4536
|
+
});
|
|
4537
|
+
return lockfilePath;
|
|
4538
|
+
}
|
|
4539
|
+
async findLockfile() {
|
|
4540
|
+
let dir = this.packagePath;
|
|
4541
|
+
const { root } = path2.parse(dir);
|
|
4542
|
+
while (dir !== root) {
|
|
4543
|
+
const candidate = path2.join(dir, "Cargo.lock");
|
|
4544
|
+
try {
|
|
4545
|
+
if ((await stat2(candidate)).isFile()) return candidate;
|
|
4546
|
+
} catch {
|
|
4547
|
+
}
|
|
4548
|
+
dir = path2.dirname(dir);
|
|
4549
|
+
}
|
|
4550
|
+
return void 0;
|
|
4551
|
+
}
|
|
4552
|
+
async dependencies() {
|
|
4553
|
+
const cargo = await this.readCargoToml();
|
|
4554
|
+
const deps = [];
|
|
4555
|
+
for (const section of ["dependencies", "build-dependencies"]) {
|
|
4556
|
+
const sectionData = cargo[section];
|
|
4557
|
+
if (sectionData) {
|
|
4558
|
+
deps.push(...Object.keys(sectionData));
|
|
4559
|
+
}
|
|
4560
|
+
}
|
|
4561
|
+
return deps;
|
|
4562
|
+
}
|
|
4563
|
+
manifestFiles() {
|
|
4564
|
+
return ["Cargo.toml"];
|
|
4565
|
+
}
|
|
4566
|
+
defaultTestCommand() {
|
|
4567
|
+
return "cargo test";
|
|
4568
|
+
}
|
|
4569
|
+
defaultBuildCommand() {
|
|
4570
|
+
return "cargo build --release";
|
|
4571
|
+
}
|
|
4572
|
+
supportedRegistries() {
|
|
4573
|
+
return ["crates"];
|
|
4574
|
+
}
|
|
4575
|
+
};
|
|
4576
|
+
|
|
4458
4577
|
// src/error.ts
|
|
4578
|
+
import { NonZeroExitError } from "tinyexec";
|
|
4459
4579
|
var AbstractError = class extends Error {
|
|
4460
4580
|
constructor(message, { cause } = {}) {
|
|
4461
4581
|
super(message, { cause });
|
|
@@ -4466,20 +4586,49 @@ var AbstractError = class extends Error {
|
|
|
4466
4586
|
function replaceCode(code) {
|
|
4467
4587
|
return code.replace(/`([^`].+)`/g, color.bold(color.underline("$1")));
|
|
4468
4588
|
}
|
|
4589
|
+
function formatStderr(stderr) {
|
|
4590
|
+
return stderr.split("\n").map((line) => ` ${color.dim("\u2502")} ${line}`).join("\n");
|
|
4591
|
+
}
|
|
4592
|
+
function isNoisyCause(cause) {
|
|
4593
|
+
if (cause instanceof NonZeroExitError) return true;
|
|
4594
|
+
if (cause instanceof Error && /Process exited with non-zero status/i.test(cause.message))
|
|
4595
|
+
return true;
|
|
4596
|
+
return false;
|
|
4597
|
+
}
|
|
4469
4598
|
function formatError(error) {
|
|
4470
4599
|
if (!(error instanceof Error)) return `${error}`;
|
|
4471
|
-
const
|
|
4600
|
+
const rawMessage = typeof error.message === "string" ? error.message : (
|
|
4472
4601
|
/* v8 ignore next */
|
|
4473
|
-
|
|
4602
|
+
String(error)
|
|
4474
4603
|
);
|
|
4475
|
-
|
|
4604
|
+
const newlineIndex = rawMessage.indexOf("\n");
|
|
4605
|
+
let summary;
|
|
4606
|
+
let detail;
|
|
4607
|
+
if (newlineIndex !== -1) {
|
|
4608
|
+
summary = rawMessage.slice(0, newlineIndex);
|
|
4609
|
+
detail = rawMessage.slice(newlineIndex + 1);
|
|
4610
|
+
} else {
|
|
4611
|
+
summary = rawMessage;
|
|
4612
|
+
}
|
|
4613
|
+
let result = `${color.bgRed(` ${error.name} `)}${color.reset("")} ${replaceCode(summary)}
|
|
4614
|
+
`;
|
|
4615
|
+
if (detail) {
|
|
4616
|
+
result += `
|
|
4617
|
+
${formatStderr(detail)}
|
|
4476
4618
|
`;
|
|
4477
|
-
stringifyError += error.stack?.split("\n").slice(1).join("\n").replace(/at/g, color.dim("at")).replace(/\(([^(].+)\)/g, `(${color.blue("$1")})`);
|
|
4478
|
-
if (error.cause) {
|
|
4479
|
-
stringifyError += "\n\nCaused: ";
|
|
4480
|
-
stringifyError += formatError(error.cause);
|
|
4481
4619
|
}
|
|
4482
|
-
|
|
4620
|
+
if (process.env.DEBUG === "pubm" && error.stack) {
|
|
4621
|
+
result += error.stack.split("\n").slice(1).join("\n").replace(/at/g, color.dim("at")).replace(/\(([^(].+)\)/g, `(${color.blue("$1")})`);
|
|
4622
|
+
}
|
|
4623
|
+
if (error.cause && !isNoisyCause(error.cause)) {
|
|
4624
|
+
const causeMsg = error.cause instanceof Error ? error.cause.message : String(error.cause);
|
|
4625
|
+
if (causeMsg !== summary) {
|
|
4626
|
+
result += `
|
|
4627
|
+
${color.dim("Caused by:")} `;
|
|
4628
|
+
result += formatError(error.cause);
|
|
4629
|
+
}
|
|
4630
|
+
}
|
|
4631
|
+
return result;
|
|
4483
4632
|
}
|
|
4484
4633
|
function consoleError(error) {
|
|
4485
4634
|
let errorText = "\n";
|
|
@@ -4496,7 +4645,7 @@ function consoleError(error) {
|
|
|
4496
4645
|
|
|
4497
4646
|
// src/git.ts
|
|
4498
4647
|
import semver from "semver";
|
|
4499
|
-
import { exec as
|
|
4648
|
+
import { exec as exec3 } from "tinyexec";
|
|
4500
4649
|
var GitError = class extends AbstractError {
|
|
4501
4650
|
constructor() {
|
|
4502
4651
|
super(...arguments);
|
|
@@ -4505,7 +4654,7 @@ var GitError = class extends AbstractError {
|
|
|
4505
4654
|
};
|
|
4506
4655
|
var Git = class {
|
|
4507
4656
|
async git(args) {
|
|
4508
|
-
const { stdout } = await
|
|
4657
|
+
const { stdout } = await exec3("git", args, { throwOnError: true });
|
|
4509
4658
|
return stdout;
|
|
4510
4659
|
}
|
|
4511
4660
|
async userName() {
|
|
@@ -4759,7 +4908,7 @@ var Git = class {
|
|
|
4759
4908
|
async push(options) {
|
|
4760
4909
|
const args = ["push", options].filter((v) => v);
|
|
4761
4910
|
try {
|
|
4762
|
-
const { stderr } = await
|
|
4911
|
+
const { stderr } = await exec3("git", args, { throwOnError: true });
|
|
4763
4912
|
if (`${stderr}`.includes("GH006")) {
|
|
4764
4913
|
return false;
|
|
4765
4914
|
}
|
|
@@ -4781,125 +4930,6 @@ function link2(text, url) {
|
|
|
4781
4930
|
return `\x1B]8;;${url}\x07${text}\x1B]8;;\x07`;
|
|
4782
4931
|
}
|
|
4783
4932
|
|
|
4784
|
-
// src/ecosystem/rust.ts
|
|
4785
|
-
import { readFile, stat as stat2, writeFile } from "node:fs/promises";
|
|
4786
|
-
import path2 from "node:path";
|
|
4787
|
-
import { parse, stringify } from "smol-toml";
|
|
4788
|
-
import { exec as exec3 } from "tinyexec";
|
|
4789
|
-
|
|
4790
|
-
// src/ecosystem/ecosystem.ts
|
|
4791
|
-
var Ecosystem = class {
|
|
4792
|
-
constructor(packagePath) {
|
|
4793
|
-
this.packagePath = packagePath;
|
|
4794
|
-
}
|
|
4795
|
-
};
|
|
4796
|
-
|
|
4797
|
-
// src/ecosystem/rust.ts
|
|
4798
|
-
var RustEcosystem = class extends Ecosystem {
|
|
4799
|
-
static async detect(packagePath) {
|
|
4800
|
-
try {
|
|
4801
|
-
return (await stat2(path2.join(packagePath, "Cargo.toml"))).isFile();
|
|
4802
|
-
} catch {
|
|
4803
|
-
return false;
|
|
4804
|
-
}
|
|
4805
|
-
}
|
|
4806
|
-
async readCargoToml() {
|
|
4807
|
-
const raw = await readFile(
|
|
4808
|
-
path2.join(this.packagePath, "Cargo.toml"),
|
|
4809
|
-
"utf-8"
|
|
4810
|
-
);
|
|
4811
|
-
return parse(raw);
|
|
4812
|
-
}
|
|
4813
|
-
async packageName() {
|
|
4814
|
-
const cargo = await this.readCargoToml();
|
|
4815
|
-
const pkg = cargo.package;
|
|
4816
|
-
return pkg.name;
|
|
4817
|
-
}
|
|
4818
|
-
async readVersion() {
|
|
4819
|
-
const cargo = await this.readCargoToml();
|
|
4820
|
-
const pkg = cargo.package;
|
|
4821
|
-
return pkg.version;
|
|
4822
|
-
}
|
|
4823
|
-
async writeVersion(newVersion) {
|
|
4824
|
-
const filePath = path2.join(this.packagePath, "Cargo.toml");
|
|
4825
|
-
const raw = await readFile(filePath, "utf-8");
|
|
4826
|
-
const cargo = parse(raw);
|
|
4827
|
-
const pkg = cargo.package;
|
|
4828
|
-
pkg.version = newVersion;
|
|
4829
|
-
await writeFile(filePath, stringify(cargo));
|
|
4830
|
-
}
|
|
4831
|
-
/**
|
|
4832
|
-
* Update the `version` field of dependencies that match sibling crate names.
|
|
4833
|
-
* This ensures `cargo publish` works when crates depend on each other via path.
|
|
4834
|
-
*/
|
|
4835
|
-
async updateSiblingDependencyVersions(siblingVersions) {
|
|
4836
|
-
const filePath = path2.join(this.packagePath, "Cargo.toml");
|
|
4837
|
-
const raw = await readFile(filePath, "utf-8");
|
|
4838
|
-
const cargo = parse(raw);
|
|
4839
|
-
let modified = false;
|
|
4840
|
-
for (const section of ["dependencies", "build-dependencies"]) {
|
|
4841
|
-
const sectionData = cargo[section];
|
|
4842
|
-
if (!sectionData) continue;
|
|
4843
|
-
for (const [depName, depValue] of Object.entries(sectionData)) {
|
|
4844
|
-
if (typeof depValue === "object" && depValue !== null && "path" in depValue && siblingVersions.has(depName)) {
|
|
4845
|
-
const dep = depValue;
|
|
4846
|
-
dep.version = siblingVersions.get(depName);
|
|
4847
|
-
modified = true;
|
|
4848
|
-
}
|
|
4849
|
-
}
|
|
4850
|
-
}
|
|
4851
|
-
if (modified) {
|
|
4852
|
-
await writeFile(filePath, stringify(cargo));
|
|
4853
|
-
}
|
|
4854
|
-
return modified;
|
|
4855
|
-
}
|
|
4856
|
-
async syncLockfile() {
|
|
4857
|
-
const lockfilePath = await this.findLockfile();
|
|
4858
|
-
if (!lockfilePath) return void 0;
|
|
4859
|
-
const name = await this.packageName();
|
|
4860
|
-
await exec3("cargo", ["update", "--package", name], {
|
|
4861
|
-
nodeOptions: { cwd: path2.dirname(lockfilePath) }
|
|
4862
|
-
});
|
|
4863
|
-
return lockfilePath;
|
|
4864
|
-
}
|
|
4865
|
-
async findLockfile() {
|
|
4866
|
-
let dir = this.packagePath;
|
|
4867
|
-
const { root } = path2.parse(dir);
|
|
4868
|
-
while (dir !== root) {
|
|
4869
|
-
const candidate = path2.join(dir, "Cargo.lock");
|
|
4870
|
-
try {
|
|
4871
|
-
if ((await stat2(candidate)).isFile()) return candidate;
|
|
4872
|
-
} catch {
|
|
4873
|
-
}
|
|
4874
|
-
dir = path2.dirname(dir);
|
|
4875
|
-
}
|
|
4876
|
-
return void 0;
|
|
4877
|
-
}
|
|
4878
|
-
async dependencies() {
|
|
4879
|
-
const cargo = await this.readCargoToml();
|
|
4880
|
-
const deps = [];
|
|
4881
|
-
for (const section of ["dependencies", "build-dependencies"]) {
|
|
4882
|
-
const sectionData = cargo[section];
|
|
4883
|
-
if (sectionData) {
|
|
4884
|
-
deps.push(...Object.keys(sectionData));
|
|
4885
|
-
}
|
|
4886
|
-
}
|
|
4887
|
-
return deps;
|
|
4888
|
-
}
|
|
4889
|
-
manifestFiles() {
|
|
4890
|
-
return ["Cargo.toml"];
|
|
4891
|
-
}
|
|
4892
|
-
defaultTestCommand() {
|
|
4893
|
-
return "cargo test";
|
|
4894
|
-
}
|
|
4895
|
-
defaultBuildCommand() {
|
|
4896
|
-
return "cargo build --release";
|
|
4897
|
-
}
|
|
4898
|
-
supportedRegistries() {
|
|
4899
|
-
return ["crates"];
|
|
4900
|
-
}
|
|
4901
|
-
};
|
|
4902
|
-
|
|
4903
4933
|
// src/utils/crate-graph.ts
|
|
4904
4934
|
async function sortCratesByDependencyOrder(cratePaths) {
|
|
4905
4935
|
if (cratePaths.length <= 1) return cratePaths;
|
|
@@ -4952,12 +4982,19 @@ var rollbacks = [];
|
|
|
4952
4982
|
function addRollback(rollback2, context) {
|
|
4953
4983
|
rollbacks.push({ fn: rollback2, ctx: context });
|
|
4954
4984
|
}
|
|
4985
|
+
function rollbackLog(message) {
|
|
4986
|
+
console.log(` ${color.yellow("\u21A9")} ${message}`);
|
|
4987
|
+
}
|
|
4988
|
+
function rollbackError(message) {
|
|
4989
|
+
console.error(` ${color.red("\u2717")} ${message}`);
|
|
4990
|
+
}
|
|
4955
4991
|
var called = false;
|
|
4956
4992
|
async function rollback() {
|
|
4957
4993
|
if (called) return void 0;
|
|
4958
4994
|
called = true;
|
|
4959
4995
|
if (rollbacks.length <= 0) return void 0;
|
|
4960
|
-
console.log(
|
|
4996
|
+
console.log(`
|
|
4997
|
+
${color.yellow("\u27F2")} ${color.yellow("Rolling back...")}`);
|
|
4961
4998
|
const results = await Promise.allSettled(
|
|
4962
4999
|
rollbacks.map(({ fn, ctx }) => fn(ctx))
|
|
4963
5000
|
);
|
|
@@ -4966,15 +5003,15 @@ async function rollback() {
|
|
|
4966
5003
|
);
|
|
4967
5004
|
if (failures.length > 0) {
|
|
4968
5005
|
for (const failure of failures) {
|
|
4969
|
-
|
|
4970
|
-
|
|
5006
|
+
rollbackError(
|
|
5007
|
+
failure.reason instanceof Error ? failure.reason.message : failure.reason
|
|
4971
5008
|
);
|
|
4972
5009
|
}
|
|
4973
5010
|
console.log(
|
|
4974
|
-
"Rollback completed with errors. Some operations may require manual recovery
|
|
5011
|
+
`${color.red("\u2717")} ${color.red("Rollback completed with errors.")} Some operations may require manual recovery.`
|
|
4975
5012
|
);
|
|
4976
5013
|
} else {
|
|
4977
|
-
console.log("Rollback completed
|
|
5014
|
+
console.log(`${color.green("\u2713")} Rollback completed`);
|
|
4978
5015
|
}
|
|
4979
5016
|
}
|
|
4980
5017
|
|
|
@@ -5381,7 +5418,7 @@ function injectTokensToEnv(tokens) {
|
|
|
5381
5418
|
|
|
5382
5419
|
// src/registry/crates.ts
|
|
5383
5420
|
import path5 from "node:path";
|
|
5384
|
-
import { exec as exec4, NonZeroExitError } from "tinyexec";
|
|
5421
|
+
import { exec as exec4, NonZeroExitError as NonZeroExitError2 } from "tinyexec";
|
|
5385
5422
|
|
|
5386
5423
|
// src/registry/registry.ts
|
|
5387
5424
|
var Registry = class {
|
|
@@ -5401,6 +5438,14 @@ var CratesError = class extends AbstractError {
|
|
|
5401
5438
|
}
|
|
5402
5439
|
};
|
|
5403
5440
|
var USER_AGENT = "pubm (https://github.com/syi0808/pubm)";
|
|
5441
|
+
function cleanCargoStderr(stderr) {
|
|
5442
|
+
return stderr.split("\n").filter((line) => {
|
|
5443
|
+
const trimmed = line.trim();
|
|
5444
|
+
if (trimmed === "Updating crates.io index") return false;
|
|
5445
|
+
if (trimmed === "") return false;
|
|
5446
|
+
return true;
|
|
5447
|
+
}).join("\n");
|
|
5448
|
+
}
|
|
5404
5449
|
var CratesRegistry = class extends Registry {
|
|
5405
5450
|
constructor() {
|
|
5406
5451
|
super(...arguments);
|
|
@@ -5465,26 +5510,40 @@ var CratesRegistry = class extends Registry {
|
|
|
5465
5510
|
await exec4("cargo", args, { throwOnError: true });
|
|
5466
5511
|
return true;
|
|
5467
5512
|
} catch (error) {
|
|
5468
|
-
const stderr = error instanceof
|
|
5513
|
+
const stderr = error instanceof NonZeroExitError2 ? error.output?.stderr : void 0;
|
|
5469
5514
|
const message = stderr ? `Failed to run \`cargo publish\`:
|
|
5470
|
-
${stderr}` : "Failed to run `cargo publish`";
|
|
5515
|
+
${cleanCargoStderr(stderr)}` : "Failed to run `cargo publish`";
|
|
5471
5516
|
throw new CratesError(message, { cause: error });
|
|
5472
5517
|
}
|
|
5473
5518
|
}
|
|
5474
5519
|
async dryRunPublish(manifestDir) {
|
|
5475
5520
|
try {
|
|
5476
|
-
const args = ["publish", "--dry-run"
|
|
5521
|
+
const args = ["publish", "--dry-run"];
|
|
5477
5522
|
if (manifestDir) {
|
|
5478
5523
|
args.push("--manifest-path", path5.join(manifestDir, "Cargo.toml"));
|
|
5479
5524
|
}
|
|
5480
5525
|
await exec4("cargo", args, { throwOnError: true });
|
|
5481
5526
|
} catch (error) {
|
|
5482
|
-
const stderr = error instanceof
|
|
5527
|
+
const stderr = error instanceof NonZeroExitError2 ? error.output?.stderr : void 0;
|
|
5483
5528
|
const message = stderr ? `Failed to run \`cargo publish --dry-run\`:
|
|
5484
|
-
${stderr}` : "Failed to run `cargo publish --dry-run`";
|
|
5529
|
+
${cleanCargoStderr(stderr)}` : "Failed to run `cargo publish --dry-run`";
|
|
5485
5530
|
throw new CratesError(message, { cause: error });
|
|
5486
5531
|
}
|
|
5487
5532
|
}
|
|
5533
|
+
async isVersionPublished(version2) {
|
|
5534
|
+
try {
|
|
5535
|
+
const response = await fetch(
|
|
5536
|
+
`${this.registry}/api/v1/crates/${this.packageName}/${version2}`,
|
|
5537
|
+
{ headers: this.headers }
|
|
5538
|
+
);
|
|
5539
|
+
return response.ok;
|
|
5540
|
+
} catch (error) {
|
|
5541
|
+
throw new CratesError(
|
|
5542
|
+
`Failed to check version ${version2} for '${this.packageName}' on crates.io`,
|
|
5543
|
+
{ cause: error }
|
|
5544
|
+
);
|
|
5545
|
+
}
|
|
5546
|
+
}
|
|
5488
5547
|
async isPublished() {
|
|
5489
5548
|
try {
|
|
5490
5549
|
const response = await fetch(
|
|
@@ -5561,10 +5620,24 @@ function createCratesPublishTask(packagePath) {
|
|
|
5561
5620
|
const label = packagePath ? ` (${packagePath})` : "";
|
|
5562
5621
|
return {
|
|
5563
5622
|
title: `Publishing to crates.io${label}`,
|
|
5564
|
-
task: async () => {
|
|
5623
|
+
task: async (ctx, task) => {
|
|
5565
5624
|
const packageName = await getCrateName(packagePath);
|
|
5566
5625
|
const registry = new CratesRegistry(packageName);
|
|
5567
|
-
await registry.
|
|
5626
|
+
if (await registry.isVersionPublished(ctx.version)) {
|
|
5627
|
+
task.title = `[SKIPPED] crates.io${label}: v${ctx.version} already published`;
|
|
5628
|
+
task.output = `\u26A0 ${packageName}@${ctx.version} is already published on crates.io`;
|
|
5629
|
+
return task.skip();
|
|
5630
|
+
}
|
|
5631
|
+
try {
|
|
5632
|
+
await registry.publish(packagePath);
|
|
5633
|
+
} catch (error) {
|
|
5634
|
+
if (error instanceof Error && error.message.includes("is already uploaded")) {
|
|
5635
|
+
task.title = `[SKIPPED] crates.io${label}: v${ctx.version} already published`;
|
|
5636
|
+
task.output = `\u26A0 ${packageName}@${ctx.version} is already published on crates.io`;
|
|
5637
|
+
return task.skip();
|
|
5638
|
+
}
|
|
5639
|
+
throw error;
|
|
5640
|
+
}
|
|
5568
5641
|
}
|
|
5569
5642
|
};
|
|
5570
5643
|
}
|
|
@@ -5575,7 +5648,7 @@ var cratesPublishTasks = createCratesPublishTask();
|
|
|
5575
5648
|
import { ListrEnquirerPromptAdapter } from "@listr2/prompt-adapter-enquirer";
|
|
5576
5649
|
|
|
5577
5650
|
// src/registry/jsr.ts
|
|
5578
|
-
import { exec as exec5, NonZeroExitError as
|
|
5651
|
+
import { exec as exec5, NonZeroExitError as NonZeroExitError3 } from "tinyexec";
|
|
5579
5652
|
|
|
5580
5653
|
// src/utils/package-name.ts
|
|
5581
5654
|
import { builtinModules } from "node:module";
|
|
@@ -5683,7 +5756,7 @@ var JsrRegisry = class extends Registry {
|
|
|
5683
5756
|
this.packageCreationUrls = void 0;
|
|
5684
5757
|
return true;
|
|
5685
5758
|
} catch (error) {
|
|
5686
|
-
const stderr = error instanceof
|
|
5759
|
+
const stderr = error instanceof NonZeroExitError3 ? error.output?.stderr : void 0;
|
|
5687
5760
|
if (stderr?.includes("don't exist")) {
|
|
5688
5761
|
const urls = [...stderr.matchAll(/https:\/\/jsr\.io\/new\S+/g)].map(
|
|
5689
5762
|
(m) => m[0]
|
|
@@ -5735,6 +5808,20 @@ ${stderr}` : ""}`,
|
|
|
5735
5808
|
);
|
|
5736
5809
|
}
|
|
5737
5810
|
}
|
|
5811
|
+
async isVersionPublished(version2) {
|
|
5812
|
+
try {
|
|
5813
|
+
const [scope, name] = getScopeAndName(this.packageName);
|
|
5814
|
+
const response = await fetch(
|
|
5815
|
+
`${this.registry}/@${scope}/${name}/${version2}`
|
|
5816
|
+
);
|
|
5817
|
+
return response.status === 200;
|
|
5818
|
+
} catch (error) {
|
|
5819
|
+
throw new JsrError(
|
|
5820
|
+
`Failed to fetch \`${this.registry}/${this.packageName}/${version2}\``,
|
|
5821
|
+
{ cause: error }
|
|
5822
|
+
);
|
|
5823
|
+
}
|
|
5824
|
+
}
|
|
5738
5825
|
async hasPermission() {
|
|
5739
5826
|
return this.client.scopePermission(`${getScope(this.packageName)}`) !== null;
|
|
5740
5827
|
}
|
|
@@ -5964,7 +6051,7 @@ async function jsrRegistry() {
|
|
|
5964
6051
|
// src/registry/npm.ts
|
|
5965
6052
|
import { tmpdir } from "node:os";
|
|
5966
6053
|
import { join } from "node:path";
|
|
5967
|
-
import { exec as exec6, NonZeroExitError as
|
|
6054
|
+
import { exec as exec6, NonZeroExitError as NonZeroExitError4 } from "tinyexec";
|
|
5968
6055
|
var NpmError = class extends AbstractError {
|
|
5969
6056
|
constructor() {
|
|
5970
6057
|
super(...arguments);
|
|
@@ -6009,6 +6096,19 @@ var NpmRegistry = class extends Registry {
|
|
|
6009
6096
|
);
|
|
6010
6097
|
}
|
|
6011
6098
|
}
|
|
6099
|
+
async isVersionPublished(version2) {
|
|
6100
|
+
try {
|
|
6101
|
+
const response = await fetch(
|
|
6102
|
+
`${this.registry}/${this.packageName}/${version2}`
|
|
6103
|
+
);
|
|
6104
|
+
return response.status === 200;
|
|
6105
|
+
} catch (error) {
|
|
6106
|
+
throw new NpmError(
|
|
6107
|
+
`Failed to fetch \`${this.registry}/${this.packageName}/${version2}\``,
|
|
6108
|
+
{ cause: error }
|
|
6109
|
+
);
|
|
6110
|
+
}
|
|
6111
|
+
}
|
|
6012
6112
|
async userName() {
|
|
6013
6113
|
try {
|
|
6014
6114
|
return (await this.npm(["whoami"])).trim();
|
|
@@ -6021,7 +6121,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6021
6121
|
await this.npm(["whoami"]);
|
|
6022
6122
|
return true;
|
|
6023
6123
|
} catch (error) {
|
|
6024
|
-
if (error instanceof
|
|
6124
|
+
if (error instanceof NonZeroExitError4) {
|
|
6025
6125
|
return false;
|
|
6026
6126
|
}
|
|
6027
6127
|
throw new NpmError("Failed to run `npm whoami`", { cause: error });
|
|
@@ -6099,7 +6199,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6099
6199
|
await this.npm(["publish", "--provenance", "--access", "public"]);
|
|
6100
6200
|
return true;
|
|
6101
6201
|
} catch (error) {
|
|
6102
|
-
if (error instanceof
|
|
6202
|
+
if (error instanceof NonZeroExitError4 && error.output?.stderr.includes("EOTP")) {
|
|
6103
6203
|
return false;
|
|
6104
6204
|
}
|
|
6105
6205
|
throw this.classifyPublishError(error);
|
|
@@ -6111,7 +6211,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6111
6211
|
await this.npm(args);
|
|
6112
6212
|
return true;
|
|
6113
6213
|
} catch (error) {
|
|
6114
|
-
if (error instanceof
|
|
6214
|
+
if (error instanceof NonZeroExitError4 && error.output?.stderr.includes("EOTP")) {
|
|
6115
6215
|
return false;
|
|
6116
6216
|
}
|
|
6117
6217
|
throw this.classifyPublishError(error);
|
|
@@ -6129,7 +6229,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6129
6229
|
}
|
|
6130
6230
|
});
|
|
6131
6231
|
} catch (error) {
|
|
6132
|
-
const stderr = error instanceof
|
|
6232
|
+
const stderr = error instanceof NonZeroExitError4 ? error.output?.stderr : void 0;
|
|
6133
6233
|
throw new NpmError(
|
|
6134
6234
|
`Failed to run \`npm publish --dry-run\`${stderr ? `
|
|
6135
6235
|
${stderr}` : ""}`,
|
|
@@ -6156,7 +6256,7 @@ ${stderr}` : ""}`,
|
|
|
6156
6256
|
};
|
|
6157
6257
|
}
|
|
6158
6258
|
classifyPublishError(error) {
|
|
6159
|
-
if (error instanceof
|
|
6259
|
+
if (error instanceof NonZeroExitError4) {
|
|
6160
6260
|
const stderr = error.output?.stderr ?? "";
|
|
6161
6261
|
if (stderr.includes("EOTP")) {
|
|
6162
6262
|
return new NpmError("OTP required for publishing", { cause: error });
|
|
@@ -6214,20 +6314,30 @@ async function withTokenRetry(registryKey, task, action) {
|
|
|
6214
6314
|
}
|
|
6215
6315
|
var npmDryRunPublishTask = {
|
|
6216
6316
|
title: "Dry-run npm publish",
|
|
6217
|
-
task: async (
|
|
6317
|
+
task: async (ctx, task) => {
|
|
6318
|
+
const npm = await npmRegistry();
|
|
6319
|
+
if (await npm.isVersionPublished(ctx.version)) {
|
|
6320
|
+
task.title = `[SKIPPED] Dry-run npm publish: v${ctx.version} already published`;
|
|
6321
|
+
task.output = `\u26A0 ${npm.packageName}@${ctx.version} is already published on npm`;
|
|
6322
|
+
return task.skip();
|
|
6323
|
+
}
|
|
6218
6324
|
task.output = "Running npm publish --dry-run...";
|
|
6219
6325
|
await withTokenRetry("npm", task, async () => {
|
|
6220
|
-
const npm = await npmRegistry();
|
|
6221
6326
|
await npm.dryRunPublish();
|
|
6222
6327
|
});
|
|
6223
6328
|
}
|
|
6224
6329
|
};
|
|
6225
6330
|
var jsrDryRunPublishTask = {
|
|
6226
6331
|
title: "Dry-run jsr publish",
|
|
6227
|
-
task: async (
|
|
6332
|
+
task: async (ctx, task) => {
|
|
6333
|
+
const jsr = await jsrRegistry();
|
|
6334
|
+
if (await jsr.isVersionPublished(ctx.version)) {
|
|
6335
|
+
task.title = `[SKIPPED] Dry-run jsr publish: v${ctx.version} already published`;
|
|
6336
|
+
task.output = `\u26A0 ${jsr.packageName}@${ctx.version} is already published on jsr`;
|
|
6337
|
+
return task.skip();
|
|
6338
|
+
}
|
|
6228
6339
|
task.output = "Running jsr publish --dry-run...";
|
|
6229
6340
|
await withTokenRetry("jsr", task, async () => {
|
|
6230
|
-
const jsr = await jsrRegistry();
|
|
6231
6341
|
await jsr.dryRunPublish();
|
|
6232
6342
|
});
|
|
6233
6343
|
}
|
|
@@ -6236,17 +6346,58 @@ async function getCrateName2(packagePath) {
|
|
|
6236
6346
|
const eco = new RustEcosystem(packagePath ?? process.cwd());
|
|
6237
6347
|
return await eco.packageName();
|
|
6238
6348
|
}
|
|
6239
|
-
|
|
6349
|
+
var MISSING_CRATE_PATTERN = /no matching package named `([^`]+)` found/;
|
|
6350
|
+
async function findUnpublishedSiblingDeps(packagePath, siblingCrateNames) {
|
|
6351
|
+
const eco = new RustEcosystem(packagePath ?? process.cwd());
|
|
6352
|
+
const deps = await eco.dependencies();
|
|
6353
|
+
const siblingDeps = deps.filter((d2) => siblingCrateNames.includes(d2));
|
|
6354
|
+
const results = await Promise.all(
|
|
6355
|
+
siblingDeps.map(async (name) => {
|
|
6356
|
+
const registry = new CratesRegistry(name);
|
|
6357
|
+
const published = await registry.isPublished();
|
|
6358
|
+
return published ? null : name;
|
|
6359
|
+
})
|
|
6360
|
+
);
|
|
6361
|
+
return results.filter((name) => name !== null);
|
|
6362
|
+
}
|
|
6363
|
+
function createCratesDryRunPublishTask(packagePath, siblingCrateNames) {
|
|
6240
6364
|
const label = packagePath ? ` (${packagePath})` : "";
|
|
6241
6365
|
return {
|
|
6242
6366
|
title: `Dry-run crates.io publish${label}`,
|
|
6243
|
-
task: async (
|
|
6367
|
+
task: async (ctx, task) => {
|
|
6368
|
+
const packageName = await getCrateName2(packagePath);
|
|
6369
|
+
const registry = new CratesRegistry(packageName);
|
|
6370
|
+
if (await registry.isVersionPublished(ctx.version)) {
|
|
6371
|
+
task.title = `[SKIPPED] Dry-run crates.io publish${label}: v${ctx.version} already published`;
|
|
6372
|
+
task.output = `\u26A0 ${packageName}@${ctx.version} is already published on crates.io`;
|
|
6373
|
+
return task.skip();
|
|
6374
|
+
}
|
|
6375
|
+
if (siblingCrateNames?.length) {
|
|
6376
|
+
const unpublished = await findUnpublishedSiblingDeps(
|
|
6377
|
+
packagePath,
|
|
6378
|
+
siblingCrateNames
|
|
6379
|
+
);
|
|
6380
|
+
if (unpublished.length > 0) {
|
|
6381
|
+
task.title = `Dry-run crates.io publish${label} [skipped: sibling crate \`${unpublished.join("`, `")}\` not yet published]`;
|
|
6382
|
+
return;
|
|
6383
|
+
}
|
|
6384
|
+
}
|
|
6244
6385
|
task.output = "Running cargo publish --dry-run...";
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6386
|
+
try {
|
|
6387
|
+
await withTokenRetry("crates", task, async () => {
|
|
6388
|
+
const packageName2 = await getCrateName2(packagePath);
|
|
6389
|
+
const registry2 = new CratesRegistry(packageName2);
|
|
6390
|
+
await registry2.dryRunPublish(packagePath);
|
|
6391
|
+
});
|
|
6392
|
+
} catch (error) {
|
|
6393
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6394
|
+
const match = message.match(MISSING_CRATE_PATTERN);
|
|
6395
|
+
if (match && siblingCrateNames?.includes(match[1])) {
|
|
6396
|
+
task.title = `Dry-run crates.io publish${label} [skipped: sibling crate \`${match[1]}\` not yet published]`;
|
|
6397
|
+
return;
|
|
6398
|
+
}
|
|
6399
|
+
throw error;
|
|
6400
|
+
}
|
|
6250
6401
|
}
|
|
6251
6402
|
};
|
|
6252
6403
|
}
|
|
@@ -6427,48 +6578,62 @@ var jsrPublishTasks = {
|
|
|
6427
6578
|
title: "Running jsr publish",
|
|
6428
6579
|
task: async (ctx, task) => {
|
|
6429
6580
|
const jsr = await jsrRegistry();
|
|
6581
|
+
if (await jsr.isVersionPublished(ctx.version)) {
|
|
6582
|
+
task.title = `[SKIPPED] jsr: v${ctx.version} already published`;
|
|
6583
|
+
task.output = `\u26A0 ${jsr.packageName}@${ctx.version} is already published on jsr`;
|
|
6584
|
+
return task.skip();
|
|
6585
|
+
}
|
|
6430
6586
|
task.output = "Publishing on jsr...";
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6587
|
+
try {
|
|
6588
|
+
if (!JsrClient.token && !ctx.promptEnabled) {
|
|
6589
|
+
const jsrTokenEnv = process8.env.JSR_TOKEN;
|
|
6590
|
+
if (!jsrTokenEnv) {
|
|
6591
|
+
throw new JsrAvailableError(
|
|
6592
|
+
"JSR_TOKEN not found in the environment variables. Please set the token and try again."
|
|
6593
|
+
);
|
|
6594
|
+
}
|
|
6595
|
+
JsrClient.token = jsrTokenEnv;
|
|
6437
6596
|
}
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
const maxAttempts = 3;
|
|
6446
|
-
task.output = `Package doesn't exist on jsr. Create it at:
|
|
6597
|
+
let result = await jsr.publish();
|
|
6598
|
+
if (!result && jsr.packageCreationUrls) {
|
|
6599
|
+
if (ctx.promptEnabled) {
|
|
6600
|
+
task.title = "Running jsr publish (package creation needed)";
|
|
6601
|
+
const urls = jsr.packageCreationUrls;
|
|
6602
|
+
const maxAttempts = 3;
|
|
6603
|
+
task.output = `Package doesn't exist on jsr. Create it at:
|
|
6447
6604
|
${urls.map((url) => ` ${color.cyan(url)}`).join("\n")}`;
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6605
|
+
open(urls[0]);
|
|
6606
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6607
|
+
await task.prompt(ListrEnquirerPromptAdapter2).run({
|
|
6608
|
+
type: "input",
|
|
6609
|
+
message: `Press ${color.bold("enter")} after creating the package on jsr.io${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
|
|
6610
|
+
});
|
|
6611
|
+
result = await jsr.publish();
|
|
6612
|
+
if (result) break;
|
|
6613
|
+
if (attempt < maxAttempts) {
|
|
6614
|
+
task.output = "Package still doesn't exist. Please create it and try again.";
|
|
6615
|
+
}
|
|
6458
6616
|
}
|
|
6459
|
-
|
|
6460
|
-
|
|
6617
|
+
if (!result) {
|
|
6618
|
+
throw new JsrAvailableError(
|
|
6619
|
+
"Package creation not completed after 3 attempts."
|
|
6620
|
+
);
|
|
6621
|
+
}
|
|
6622
|
+
task.title = "Running jsr publish (package created)";
|
|
6623
|
+
} else {
|
|
6461
6624
|
throw new JsrAvailableError(
|
|
6462
|
-
|
|
6625
|
+
`Package doesn't exist on jsr. Create it at:
|
|
6626
|
+
${jsr.packageCreationUrls.join("\n")}`
|
|
6463
6627
|
);
|
|
6464
6628
|
}
|
|
6465
|
-
task.title = "Running jsr publish (package created)";
|
|
6466
|
-
} else {
|
|
6467
|
-
throw new JsrAvailableError(
|
|
6468
|
-
`Package doesn't exist on jsr. Create it at:
|
|
6469
|
-
${jsr.packageCreationUrls.join("\n")}`
|
|
6470
|
-
);
|
|
6471
6629
|
}
|
|
6630
|
+
} catch (error) {
|
|
6631
|
+
if (error instanceof Error && error.message.includes("already published")) {
|
|
6632
|
+
task.title = `[SKIPPED] jsr: v${ctx.version} already published`;
|
|
6633
|
+
task.output = `\u26A0 ${jsr.packageName}@${ctx.version} is already published on jsr`;
|
|
6634
|
+
return task.skip();
|
|
6635
|
+
}
|
|
6636
|
+
throw error;
|
|
6472
6637
|
}
|
|
6473
6638
|
}
|
|
6474
6639
|
};
|
|
@@ -6565,44 +6730,62 @@ var npmPublishTasks = {
|
|
|
6565
6730
|
skip: (ctx) => !!ctx.preview,
|
|
6566
6731
|
task: async (ctx, task) => {
|
|
6567
6732
|
const npm = await npmRegistry();
|
|
6733
|
+
if (await npm.isVersionPublished(ctx.version)) {
|
|
6734
|
+
task.title = `[SKIPPED] npm: v${ctx.version} already published`;
|
|
6735
|
+
task.output = `\u26A0 ${npm.packageName}@${ctx.version} is already published on npm`;
|
|
6736
|
+
return task.skip();
|
|
6737
|
+
}
|
|
6568
6738
|
task.output = "Publishing on npm...";
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
await
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6739
|
+
try {
|
|
6740
|
+
if (ctx.promptEnabled) {
|
|
6741
|
+
let result = await npm.publish();
|
|
6742
|
+
if (!result) {
|
|
6743
|
+
task.title = "Running npm publish (OTP code needed)";
|
|
6744
|
+
const maxAttempts = 3;
|
|
6745
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
6746
|
+
result = await npm.publish(
|
|
6747
|
+
await task.prompt(ListrEnquirerPromptAdapter3).run({
|
|
6748
|
+
type: "password",
|
|
6749
|
+
message: `npm OTP code${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
|
|
6750
|
+
})
|
|
6751
|
+
);
|
|
6752
|
+
if (result) break;
|
|
6753
|
+
if (attempt < maxAttempts) {
|
|
6754
|
+
task.output = "2FA failed. Please try again.";
|
|
6755
|
+
}
|
|
6756
|
+
}
|
|
6757
|
+
if (!result) {
|
|
6758
|
+
throw new NpmAvailableError(
|
|
6759
|
+
"OTP verification failed after 3 attempts."
|
|
6760
|
+
);
|
|
6584
6761
|
}
|
|
6762
|
+
task.title = "Running npm publish (2FA passed)";
|
|
6585
6763
|
}
|
|
6764
|
+
} else {
|
|
6765
|
+
const npmTokenEnv = process9.env.NODE_AUTH_TOKEN;
|
|
6766
|
+
if (!npmTokenEnv) {
|
|
6767
|
+
throw new NpmAvailableError(
|
|
6768
|
+
"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"
|
|
6769
|
+
);
|
|
6770
|
+
}
|
|
6771
|
+
const result = await npm.publishProvenance();
|
|
6586
6772
|
if (!result) {
|
|
6587
6773
|
throw new NpmAvailableError(
|
|
6588
|
-
|
|
6774
|
+
`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 `
|
|
6589
6775
|
);
|
|
6590
6776
|
}
|
|
6591
|
-
task.title = "Running npm publish (2FA passed)";
|
|
6592
|
-
}
|
|
6593
|
-
} else {
|
|
6594
|
-
const npmTokenEnv = process9.env.NODE_AUTH_TOKEN;
|
|
6595
|
-
if (!npmTokenEnv) {
|
|
6596
|
-
throw new NpmAvailableError(
|
|
6597
|
-
"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"
|
|
6598
|
-
);
|
|
6599
6777
|
}
|
|
6600
|
-
|
|
6601
|
-
if (
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6778
|
+
} catch (error) {
|
|
6779
|
+
if (error instanceof Error && (error.message.includes(
|
|
6780
|
+
"cannot publish over the previously published"
|
|
6781
|
+
) || error.message.includes(
|
|
6782
|
+
"You cannot publish over the previously published"
|
|
6783
|
+
))) {
|
|
6784
|
+
task.title = `[SKIPPED] npm: v${ctx.version} already published`;
|
|
6785
|
+
task.output = `\u26A0 ${npm.packageName}@${ctx.version} is already published on npm`;
|
|
6786
|
+
return task.skip();
|
|
6605
6787
|
}
|
|
6788
|
+
throw error;
|
|
6606
6789
|
}
|
|
6607
6790
|
}
|
|
6608
6791
|
};
|
|
@@ -7092,10 +7275,15 @@ async function collectDryRunPublishTasks(ctx) {
|
|
|
7092
7275
|
return nonCratesTasks;
|
|
7093
7276
|
}
|
|
7094
7277
|
const sortedPaths = await sortCratesByDependencyOrder(cratesPaths);
|
|
7278
|
+
const siblingCrateNames = await Promise.all(
|
|
7279
|
+
cratesPaths.map((p) => new RustEcosystem(p).packageName())
|
|
7280
|
+
);
|
|
7095
7281
|
const sequentialCratesTask = {
|
|
7096
7282
|
title: "Dry-run crates.io publish (sequential)",
|
|
7097
7283
|
task: (_ctx, task) => task.newListr(
|
|
7098
|
-
sortedPaths.map(
|
|
7284
|
+
sortedPaths.map(
|
|
7285
|
+
(p) => createCratesDryRunPublishTask(p, siblingCrateNames)
|
|
7286
|
+
),
|
|
7099
7287
|
{ concurrent: false }
|
|
7100
7288
|
)
|
|
7101
7289
|
};
|
|
@@ -7188,23 +7376,23 @@ async function run(options) {
|
|
|
7188
7376
|
addRollback(async () => {
|
|
7189
7377
|
if (tagCreated) {
|
|
7190
7378
|
try {
|
|
7191
|
-
|
|
7379
|
+
rollbackLog("Deleting tag");
|
|
7192
7380
|
await git.deleteTag(`${await git.latestTag()}`);
|
|
7193
7381
|
} catch (error) {
|
|
7194
|
-
|
|
7382
|
+
rollbackError(
|
|
7195
7383
|
`Failed to delete tag: ${error instanceof Error ? error.message : error}`
|
|
7196
7384
|
);
|
|
7197
7385
|
}
|
|
7198
7386
|
}
|
|
7199
7387
|
if (commited) {
|
|
7200
7388
|
try {
|
|
7201
|
-
|
|
7389
|
+
rollbackLog("Resetting commits");
|
|
7202
7390
|
await git.reset();
|
|
7203
7391
|
await git.stash();
|
|
7204
7392
|
await git.reset("HEAD^", "--hard");
|
|
7205
7393
|
await git.popStash();
|
|
7206
7394
|
} catch (error) {
|
|
7207
|
-
|
|
7395
|
+
rollbackError(
|
|
7208
7396
|
`Failed to reset commits: ${error instanceof Error ? error.message : error}`
|
|
7209
7397
|
);
|
|
7210
7398
|
}
|