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/bin/cli.js
CHANGED
|
@@ -4655,6 +4655,7 @@ var Listr = (_a23 = class {
|
|
|
4655
4655
|
}, __name(_a23, "Listr"), _a23);
|
|
4656
4656
|
|
|
4657
4657
|
// src/error.ts
|
|
4658
|
+
import { NonZeroExitError } from "tinyexec";
|
|
4658
4659
|
var AbstractError = class extends Error {
|
|
4659
4660
|
constructor(message, { cause } = {}) {
|
|
4660
4661
|
super(message, { cause });
|
|
@@ -4665,20 +4666,49 @@ var AbstractError = class extends Error {
|
|
|
4665
4666
|
function replaceCode(code) {
|
|
4666
4667
|
return code.replace(/`([^`].+)`/g, color.bold(color.underline("$1")));
|
|
4667
4668
|
}
|
|
4669
|
+
function formatStderr(stderr) {
|
|
4670
|
+
return stderr.split("\n").map((line) => ` ${color.dim("\u2502")} ${line}`).join("\n");
|
|
4671
|
+
}
|
|
4672
|
+
function isNoisyCause(cause) {
|
|
4673
|
+
if (cause instanceof NonZeroExitError) return true;
|
|
4674
|
+
if (cause instanceof Error && /Process exited with non-zero status/i.test(cause.message))
|
|
4675
|
+
return true;
|
|
4676
|
+
return false;
|
|
4677
|
+
}
|
|
4668
4678
|
function formatError(error) {
|
|
4669
4679
|
if (!(error instanceof Error)) return `${error}`;
|
|
4670
|
-
const
|
|
4680
|
+
const rawMessage = typeof error.message === "string" ? error.message : (
|
|
4671
4681
|
/* v8 ignore next */
|
|
4672
|
-
|
|
4682
|
+
String(error)
|
|
4673
4683
|
);
|
|
4674
|
-
|
|
4684
|
+
const newlineIndex = rawMessage.indexOf("\n");
|
|
4685
|
+
let summary;
|
|
4686
|
+
let detail;
|
|
4687
|
+
if (newlineIndex !== -1) {
|
|
4688
|
+
summary = rawMessage.slice(0, newlineIndex);
|
|
4689
|
+
detail = rawMessage.slice(newlineIndex + 1);
|
|
4690
|
+
} else {
|
|
4691
|
+
summary = rawMessage;
|
|
4692
|
+
}
|
|
4693
|
+
let result = `${color.bgRed(` ${error.name} `)}${color.reset("")} ${replaceCode(summary)}
|
|
4675
4694
|
`;
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
|
|
4695
|
+
if (detail) {
|
|
4696
|
+
result += `
|
|
4697
|
+
${formatStderr(detail)}
|
|
4698
|
+
`;
|
|
4699
|
+
}
|
|
4700
|
+
if (process.env.DEBUG === "pubm" && error.stack) {
|
|
4701
|
+
result += error.stack.split("\n").slice(1).join("\n").replace(/at/g, color.dim("at")).replace(/\(([^(].+)\)/g, `(${color.blue("$1")})`);
|
|
4680
4702
|
}
|
|
4681
|
-
|
|
4703
|
+
if (error.cause && !isNoisyCause(error.cause)) {
|
|
4704
|
+
const causeMsg = error.cause instanceof Error ? error.cause.message : String(error.cause);
|
|
4705
|
+
if (causeMsg !== summary) {
|
|
4706
|
+
result += `
|
|
4707
|
+
${color.dim("Caused by:")} `;
|
|
4708
|
+
result += formatError(error.cause);
|
|
4709
|
+
}
|
|
4710
|
+
}
|
|
4711
|
+
return result;
|
|
4682
4712
|
}
|
|
4683
4713
|
function consoleError(error) {
|
|
4684
4714
|
let errorText = "\n";
|
|
@@ -5468,12 +5498,6 @@ import SemVer from "semver";
|
|
|
5468
5498
|
import { isCI as isCI2 } from "std-env";
|
|
5469
5499
|
import { exec as exec9 } from "tinyexec";
|
|
5470
5500
|
|
|
5471
|
-
// src/utils/cli.ts
|
|
5472
|
-
var warningBadge = color.bgYellow(" Warning ");
|
|
5473
|
-
function link2(text, url) {
|
|
5474
|
-
return `\x1B]8;;${url}\x07${text}\x1B]8;;\x07`;
|
|
5475
|
-
}
|
|
5476
|
-
|
|
5477
5501
|
// src/ecosystem/rust.ts
|
|
5478
5502
|
import { readFile, stat as stat2, writeFile } from "node:fs/promises";
|
|
5479
5503
|
import path8 from "node:path";
|
|
@@ -5593,6 +5617,12 @@ var RustEcosystem = class extends Ecosystem {
|
|
|
5593
5617
|
}
|
|
5594
5618
|
};
|
|
5595
5619
|
|
|
5620
|
+
// src/utils/cli.ts
|
|
5621
|
+
var warningBadge = color.bgYellow(" Warning ");
|
|
5622
|
+
function link2(text, url) {
|
|
5623
|
+
return `\x1B]8;;${url}\x07${text}\x1B]8;;\x07`;
|
|
5624
|
+
}
|
|
5625
|
+
|
|
5596
5626
|
// src/utils/crate-graph.ts
|
|
5597
5627
|
async function sortCratesByDependencyOrder(cratePaths) {
|
|
5598
5628
|
if (cratePaths.length <= 1) return cratePaths;
|
|
@@ -5645,12 +5675,19 @@ var rollbacks = [];
|
|
|
5645
5675
|
function addRollback(rollback2, context) {
|
|
5646
5676
|
rollbacks.push({ fn: rollback2, ctx: context });
|
|
5647
5677
|
}
|
|
5678
|
+
function rollbackLog(message) {
|
|
5679
|
+
console.log(` ${color.yellow("\u21A9")} ${message}`);
|
|
5680
|
+
}
|
|
5681
|
+
function rollbackError(message) {
|
|
5682
|
+
console.error(` ${color.red("\u2717")} ${message}`);
|
|
5683
|
+
}
|
|
5648
5684
|
var called = false;
|
|
5649
5685
|
async function rollback() {
|
|
5650
5686
|
if (called) return void 0;
|
|
5651
5687
|
called = true;
|
|
5652
5688
|
if (rollbacks.length <= 0) return void 0;
|
|
5653
|
-
console.log(
|
|
5689
|
+
console.log(`
|
|
5690
|
+
${color.yellow("\u27F2")} ${color.yellow("Rolling back...")}`);
|
|
5654
5691
|
const results = await Promise.allSettled(
|
|
5655
5692
|
rollbacks.map(({ fn, ctx }) => fn(ctx))
|
|
5656
5693
|
);
|
|
@@ -5659,15 +5696,15 @@ async function rollback() {
|
|
|
5659
5696
|
);
|
|
5660
5697
|
if (failures.length > 0) {
|
|
5661
5698
|
for (const failure of failures) {
|
|
5662
|
-
|
|
5663
|
-
|
|
5699
|
+
rollbackError(
|
|
5700
|
+
failure.reason instanceof Error ? failure.reason.message : failure.reason
|
|
5664
5701
|
);
|
|
5665
5702
|
}
|
|
5666
5703
|
console.log(
|
|
5667
|
-
"Rollback completed with errors. Some operations may require manual recovery
|
|
5704
|
+
`${color.red("\u2717")} ${color.red("Rollback completed with errors.")} Some operations may require manual recovery.`
|
|
5668
5705
|
);
|
|
5669
5706
|
} else {
|
|
5670
|
-
console.log("Rollback completed
|
|
5707
|
+
console.log(`${color.green("\u2713")} Rollback completed`);
|
|
5671
5708
|
}
|
|
5672
5709
|
}
|
|
5673
5710
|
|
|
@@ -5952,7 +5989,7 @@ function collectRegistries(ctx) {
|
|
|
5952
5989
|
|
|
5953
5990
|
// src/registry/crates.ts
|
|
5954
5991
|
import path10 from "node:path";
|
|
5955
|
-
import { exec as exec5, NonZeroExitError } from "tinyexec";
|
|
5992
|
+
import { exec as exec5, NonZeroExitError as NonZeroExitError2 } from "tinyexec";
|
|
5956
5993
|
|
|
5957
5994
|
// src/registry/registry.ts
|
|
5958
5995
|
var Registry = class {
|
|
@@ -5972,6 +6009,14 @@ var CratesError = class extends AbstractError {
|
|
|
5972
6009
|
}
|
|
5973
6010
|
};
|
|
5974
6011
|
var USER_AGENT = "pubm (https://github.com/syi0808/pubm)";
|
|
6012
|
+
function cleanCargoStderr(stderr) {
|
|
6013
|
+
return stderr.split("\n").filter((line) => {
|
|
6014
|
+
const trimmed = line.trim();
|
|
6015
|
+
if (trimmed === "Updating crates.io index") return false;
|
|
6016
|
+
if (trimmed === "") return false;
|
|
6017
|
+
return true;
|
|
6018
|
+
}).join("\n");
|
|
6019
|
+
}
|
|
5975
6020
|
var CratesRegistry = class extends Registry {
|
|
5976
6021
|
constructor() {
|
|
5977
6022
|
super(...arguments);
|
|
@@ -6036,26 +6081,40 @@ var CratesRegistry = class extends Registry {
|
|
|
6036
6081
|
await exec5("cargo", args, { throwOnError: true });
|
|
6037
6082
|
return true;
|
|
6038
6083
|
} catch (error) {
|
|
6039
|
-
const stderr = error instanceof
|
|
6084
|
+
const stderr = error instanceof NonZeroExitError2 ? error.output?.stderr : void 0;
|
|
6040
6085
|
const message = stderr ? `Failed to run \`cargo publish\`:
|
|
6041
|
-
${stderr}` : "Failed to run `cargo publish`";
|
|
6086
|
+
${cleanCargoStderr(stderr)}` : "Failed to run `cargo publish`";
|
|
6042
6087
|
throw new CratesError(message, { cause: error });
|
|
6043
6088
|
}
|
|
6044
6089
|
}
|
|
6045
6090
|
async dryRunPublish(manifestDir) {
|
|
6046
6091
|
try {
|
|
6047
|
-
const args = ["publish", "--dry-run"
|
|
6092
|
+
const args = ["publish", "--dry-run"];
|
|
6048
6093
|
if (manifestDir) {
|
|
6049
6094
|
args.push("--manifest-path", path10.join(manifestDir, "Cargo.toml"));
|
|
6050
6095
|
}
|
|
6051
6096
|
await exec5("cargo", args, { throwOnError: true });
|
|
6052
6097
|
} catch (error) {
|
|
6053
|
-
const stderr = error instanceof
|
|
6098
|
+
const stderr = error instanceof NonZeroExitError2 ? error.output?.stderr : void 0;
|
|
6054
6099
|
const message = stderr ? `Failed to run \`cargo publish --dry-run\`:
|
|
6055
|
-
${stderr}` : "Failed to run `cargo publish --dry-run`";
|
|
6100
|
+
${cleanCargoStderr(stderr)}` : "Failed to run `cargo publish --dry-run`";
|
|
6056
6101
|
throw new CratesError(message, { cause: error });
|
|
6057
6102
|
}
|
|
6058
6103
|
}
|
|
6104
|
+
async isVersionPublished(version2) {
|
|
6105
|
+
try {
|
|
6106
|
+
const response = await fetch(
|
|
6107
|
+
`${this.registry}/api/v1/crates/${this.packageName}/${version2}`,
|
|
6108
|
+
{ headers: this.headers }
|
|
6109
|
+
);
|
|
6110
|
+
return response.ok;
|
|
6111
|
+
} catch (error) {
|
|
6112
|
+
throw new CratesError(
|
|
6113
|
+
`Failed to check version ${version2} for '${this.packageName}' on crates.io`,
|
|
6114
|
+
{ cause: error }
|
|
6115
|
+
);
|
|
6116
|
+
}
|
|
6117
|
+
}
|
|
6059
6118
|
async isPublished() {
|
|
6060
6119
|
try {
|
|
6061
6120
|
const response = await fetch(
|
|
@@ -6132,10 +6191,24 @@ function createCratesPublishTask(packagePath) {
|
|
|
6132
6191
|
const label = packagePath ? ` (${packagePath})` : "";
|
|
6133
6192
|
return {
|
|
6134
6193
|
title: `Publishing to crates.io${label}`,
|
|
6135
|
-
task: async () => {
|
|
6194
|
+
task: async (ctx, task) => {
|
|
6136
6195
|
const packageName = await getCrateName(packagePath);
|
|
6137
6196
|
const registry = new CratesRegistry(packageName);
|
|
6138
|
-
await registry.
|
|
6197
|
+
if (await registry.isVersionPublished(ctx.version)) {
|
|
6198
|
+
task.title = `[SKIPPED] crates.io${label}: v${ctx.version} already published`;
|
|
6199
|
+
task.output = `\u26A0 ${packageName}@${ctx.version} is already published on crates.io`;
|
|
6200
|
+
return task.skip();
|
|
6201
|
+
}
|
|
6202
|
+
try {
|
|
6203
|
+
await registry.publish(packagePath);
|
|
6204
|
+
} catch (error) {
|
|
6205
|
+
if (error instanceof Error && error.message.includes("is already uploaded")) {
|
|
6206
|
+
task.title = `[SKIPPED] crates.io${label}: v${ctx.version} already published`;
|
|
6207
|
+
task.output = `\u26A0 ${packageName}@${ctx.version} is already published on crates.io`;
|
|
6208
|
+
return task.skip();
|
|
6209
|
+
}
|
|
6210
|
+
throw error;
|
|
6211
|
+
}
|
|
6139
6212
|
}
|
|
6140
6213
|
};
|
|
6141
6214
|
}
|
|
@@ -6146,7 +6219,7 @@ var cratesPublishTasks = createCratesPublishTask();
|
|
|
6146
6219
|
import { ListrEnquirerPromptAdapter as ListrEnquirerPromptAdapter2 } from "@listr2/prompt-adapter-enquirer";
|
|
6147
6220
|
|
|
6148
6221
|
// src/registry/jsr.ts
|
|
6149
|
-
import { exec as exec6, NonZeroExitError as
|
|
6222
|
+
import { exec as exec6, NonZeroExitError as NonZeroExitError3 } from "tinyexec";
|
|
6150
6223
|
|
|
6151
6224
|
// src/utils/package-name.ts
|
|
6152
6225
|
import { builtinModules } from "node:module";
|
|
@@ -6254,7 +6327,7 @@ var JsrRegisry = class extends Registry {
|
|
|
6254
6327
|
this.packageCreationUrls = void 0;
|
|
6255
6328
|
return true;
|
|
6256
6329
|
} catch (error) {
|
|
6257
|
-
const stderr = error instanceof
|
|
6330
|
+
const stderr = error instanceof NonZeroExitError3 ? error.output?.stderr : void 0;
|
|
6258
6331
|
if (stderr?.includes("don't exist")) {
|
|
6259
6332
|
const urls = [...stderr.matchAll(/https:\/\/jsr\.io\/new\S+/g)].map(
|
|
6260
6333
|
(m) => m[0]
|
|
@@ -6306,6 +6379,20 @@ ${stderr}` : ""}`,
|
|
|
6306
6379
|
);
|
|
6307
6380
|
}
|
|
6308
6381
|
}
|
|
6382
|
+
async isVersionPublished(version2) {
|
|
6383
|
+
try {
|
|
6384
|
+
const [scope, name] = getScopeAndName(this.packageName);
|
|
6385
|
+
const response = await fetch(
|
|
6386
|
+
`${this.registry}/@${scope}/${name}/${version2}`
|
|
6387
|
+
);
|
|
6388
|
+
return response.status === 200;
|
|
6389
|
+
} catch (error) {
|
|
6390
|
+
throw new JsrError(
|
|
6391
|
+
`Failed to fetch \`${this.registry}/${this.packageName}/${version2}\``,
|
|
6392
|
+
{ cause: error }
|
|
6393
|
+
);
|
|
6394
|
+
}
|
|
6395
|
+
}
|
|
6309
6396
|
async hasPermission() {
|
|
6310
6397
|
return this.client.scopePermission(`${getScope(this.packageName)}`) !== null;
|
|
6311
6398
|
}
|
|
@@ -6535,7 +6622,7 @@ async function jsrRegistry() {
|
|
|
6535
6622
|
// src/registry/npm.ts
|
|
6536
6623
|
import { tmpdir } from "node:os";
|
|
6537
6624
|
import { join } from "node:path";
|
|
6538
|
-
import { exec as exec7, NonZeroExitError as
|
|
6625
|
+
import { exec as exec7, NonZeroExitError as NonZeroExitError4 } from "tinyexec";
|
|
6539
6626
|
var NpmError = class extends AbstractError {
|
|
6540
6627
|
constructor() {
|
|
6541
6628
|
super(...arguments);
|
|
@@ -6580,6 +6667,19 @@ var NpmRegistry = class extends Registry {
|
|
|
6580
6667
|
);
|
|
6581
6668
|
}
|
|
6582
6669
|
}
|
|
6670
|
+
async isVersionPublished(version2) {
|
|
6671
|
+
try {
|
|
6672
|
+
const response = await fetch(
|
|
6673
|
+
`${this.registry}/${this.packageName}/${version2}`
|
|
6674
|
+
);
|
|
6675
|
+
return response.status === 200;
|
|
6676
|
+
} catch (error) {
|
|
6677
|
+
throw new NpmError(
|
|
6678
|
+
`Failed to fetch \`${this.registry}/${this.packageName}/${version2}\``,
|
|
6679
|
+
{ cause: error }
|
|
6680
|
+
);
|
|
6681
|
+
}
|
|
6682
|
+
}
|
|
6583
6683
|
async userName() {
|
|
6584
6684
|
try {
|
|
6585
6685
|
return (await this.npm(["whoami"])).trim();
|
|
@@ -6592,7 +6692,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6592
6692
|
await this.npm(["whoami"]);
|
|
6593
6693
|
return true;
|
|
6594
6694
|
} catch (error) {
|
|
6595
|
-
if (error instanceof
|
|
6695
|
+
if (error instanceof NonZeroExitError4) {
|
|
6596
6696
|
return false;
|
|
6597
6697
|
}
|
|
6598
6698
|
throw new NpmError("Failed to run `npm whoami`", { cause: error });
|
|
@@ -6670,7 +6770,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6670
6770
|
await this.npm(["publish", "--provenance", "--access", "public"]);
|
|
6671
6771
|
return true;
|
|
6672
6772
|
} catch (error) {
|
|
6673
|
-
if (error instanceof
|
|
6773
|
+
if (error instanceof NonZeroExitError4 && error.output?.stderr.includes("EOTP")) {
|
|
6674
6774
|
return false;
|
|
6675
6775
|
}
|
|
6676
6776
|
throw this.classifyPublishError(error);
|
|
@@ -6682,7 +6782,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6682
6782
|
await this.npm(args);
|
|
6683
6783
|
return true;
|
|
6684
6784
|
} catch (error) {
|
|
6685
|
-
if (error instanceof
|
|
6785
|
+
if (error instanceof NonZeroExitError4 && error.output?.stderr.includes("EOTP")) {
|
|
6686
6786
|
return false;
|
|
6687
6787
|
}
|
|
6688
6788
|
throw this.classifyPublishError(error);
|
|
@@ -6700,7 +6800,7 @@ var NpmRegistry = class extends Registry {
|
|
|
6700
6800
|
}
|
|
6701
6801
|
});
|
|
6702
6802
|
} catch (error) {
|
|
6703
|
-
const stderr = error instanceof
|
|
6803
|
+
const stderr = error instanceof NonZeroExitError4 ? error.output?.stderr : void 0;
|
|
6704
6804
|
throw new NpmError(
|
|
6705
6805
|
`Failed to run \`npm publish --dry-run\`${stderr ? `
|
|
6706
6806
|
${stderr}` : ""}`,
|
|
@@ -6727,7 +6827,7 @@ ${stderr}` : ""}`,
|
|
|
6727
6827
|
};
|
|
6728
6828
|
}
|
|
6729
6829
|
classifyPublishError(error) {
|
|
6730
|
-
if (error instanceof
|
|
6830
|
+
if (error instanceof NonZeroExitError4) {
|
|
6731
6831
|
const stderr = error.output?.stderr ?? "";
|
|
6732
6832
|
if (stderr.includes("EOTP")) {
|
|
6733
6833
|
return new NpmError("OTP required for publishing", { cause: error });
|
|
@@ -6785,20 +6885,30 @@ async function withTokenRetry(registryKey, task, action) {
|
|
|
6785
6885
|
}
|
|
6786
6886
|
var npmDryRunPublishTask = {
|
|
6787
6887
|
title: "Dry-run npm publish",
|
|
6788
|
-
task: async (
|
|
6888
|
+
task: async (ctx, task) => {
|
|
6889
|
+
const npm = await npmRegistry();
|
|
6890
|
+
if (await npm.isVersionPublished(ctx.version)) {
|
|
6891
|
+
task.title = `[SKIPPED] Dry-run npm publish: v${ctx.version} already published`;
|
|
6892
|
+
task.output = `\u26A0 ${npm.packageName}@${ctx.version} is already published on npm`;
|
|
6893
|
+
return task.skip();
|
|
6894
|
+
}
|
|
6789
6895
|
task.output = "Running npm publish --dry-run...";
|
|
6790
6896
|
await withTokenRetry("npm", task, async () => {
|
|
6791
|
-
const npm = await npmRegistry();
|
|
6792
6897
|
await npm.dryRunPublish();
|
|
6793
6898
|
});
|
|
6794
6899
|
}
|
|
6795
6900
|
};
|
|
6796
6901
|
var jsrDryRunPublishTask = {
|
|
6797
6902
|
title: "Dry-run jsr publish",
|
|
6798
|
-
task: async (
|
|
6903
|
+
task: async (ctx, task) => {
|
|
6904
|
+
const jsr = await jsrRegistry();
|
|
6905
|
+
if (await jsr.isVersionPublished(ctx.version)) {
|
|
6906
|
+
task.title = `[SKIPPED] Dry-run jsr publish: v${ctx.version} already published`;
|
|
6907
|
+
task.output = `\u26A0 ${jsr.packageName}@${ctx.version} is already published on jsr`;
|
|
6908
|
+
return task.skip();
|
|
6909
|
+
}
|
|
6799
6910
|
task.output = "Running jsr publish --dry-run...";
|
|
6800
6911
|
await withTokenRetry("jsr", task, async () => {
|
|
6801
|
-
const jsr = await jsrRegistry();
|
|
6802
6912
|
await jsr.dryRunPublish();
|
|
6803
6913
|
});
|
|
6804
6914
|
}
|
|
@@ -6807,17 +6917,58 @@ async function getCrateName2(packagePath) {
|
|
|
6807
6917
|
const eco = new RustEcosystem(packagePath ?? process.cwd());
|
|
6808
6918
|
return await eco.packageName();
|
|
6809
6919
|
}
|
|
6810
|
-
|
|
6920
|
+
var MISSING_CRATE_PATTERN = /no matching package named `([^`]+)` found/;
|
|
6921
|
+
async function findUnpublishedSiblingDeps(packagePath, siblingCrateNames) {
|
|
6922
|
+
const eco = new RustEcosystem(packagePath ?? process.cwd());
|
|
6923
|
+
const deps = await eco.dependencies();
|
|
6924
|
+
const siblingDeps = deps.filter((d2) => siblingCrateNames.includes(d2));
|
|
6925
|
+
const results = await Promise.all(
|
|
6926
|
+
siblingDeps.map(async (name) => {
|
|
6927
|
+
const registry = new CratesRegistry(name);
|
|
6928
|
+
const published = await registry.isPublished();
|
|
6929
|
+
return published ? null : name;
|
|
6930
|
+
})
|
|
6931
|
+
);
|
|
6932
|
+
return results.filter((name) => name !== null);
|
|
6933
|
+
}
|
|
6934
|
+
function createCratesDryRunPublishTask(packagePath, siblingCrateNames) {
|
|
6811
6935
|
const label = packagePath ? ` (${packagePath})` : "";
|
|
6812
6936
|
return {
|
|
6813
6937
|
title: `Dry-run crates.io publish${label}`,
|
|
6814
|
-
task: async (
|
|
6938
|
+
task: async (ctx, task) => {
|
|
6939
|
+
const packageName = await getCrateName2(packagePath);
|
|
6940
|
+
const registry = new CratesRegistry(packageName);
|
|
6941
|
+
if (await registry.isVersionPublished(ctx.version)) {
|
|
6942
|
+
task.title = `[SKIPPED] Dry-run crates.io publish${label}: v${ctx.version} already published`;
|
|
6943
|
+
task.output = `\u26A0 ${packageName}@${ctx.version} is already published on crates.io`;
|
|
6944
|
+
return task.skip();
|
|
6945
|
+
}
|
|
6946
|
+
if (siblingCrateNames?.length) {
|
|
6947
|
+
const unpublished = await findUnpublishedSiblingDeps(
|
|
6948
|
+
packagePath,
|
|
6949
|
+
siblingCrateNames
|
|
6950
|
+
);
|
|
6951
|
+
if (unpublished.length > 0) {
|
|
6952
|
+
task.title = `Dry-run crates.io publish${label} [skipped: sibling crate \`${unpublished.join("`, `")}\` not yet published]`;
|
|
6953
|
+
return;
|
|
6954
|
+
}
|
|
6955
|
+
}
|
|
6815
6956
|
task.output = "Running cargo publish --dry-run...";
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6957
|
+
try {
|
|
6958
|
+
await withTokenRetry("crates", task, async () => {
|
|
6959
|
+
const packageName2 = await getCrateName2(packagePath);
|
|
6960
|
+
const registry2 = new CratesRegistry(packageName2);
|
|
6961
|
+
await registry2.dryRunPublish(packagePath);
|
|
6962
|
+
});
|
|
6963
|
+
} catch (error) {
|
|
6964
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6965
|
+
const match = message.match(MISSING_CRATE_PATTERN);
|
|
6966
|
+
if (match && siblingCrateNames?.includes(match[1])) {
|
|
6967
|
+
task.title = `Dry-run crates.io publish${label} [skipped: sibling crate \`${match[1]}\` not yet published]`;
|
|
6968
|
+
return;
|
|
6969
|
+
}
|
|
6970
|
+
throw error;
|
|
6971
|
+
}
|
|
6821
6972
|
}
|
|
6822
6973
|
};
|
|
6823
6974
|
}
|
|
@@ -6998,48 +7149,62 @@ var jsrPublishTasks = {
|
|
|
6998
7149
|
title: "Running jsr publish",
|
|
6999
7150
|
task: async (ctx, task) => {
|
|
7000
7151
|
const jsr = await jsrRegistry();
|
|
7152
|
+
if (await jsr.isVersionPublished(ctx.version)) {
|
|
7153
|
+
task.title = `[SKIPPED] jsr: v${ctx.version} already published`;
|
|
7154
|
+
task.output = `\u26A0 ${jsr.packageName}@${ctx.version} is already published on jsr`;
|
|
7155
|
+
return task.skip();
|
|
7156
|
+
}
|
|
7001
7157
|
task.output = "Publishing on jsr...";
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7158
|
+
try {
|
|
7159
|
+
if (!JsrClient.token && !ctx.promptEnabled) {
|
|
7160
|
+
const jsrTokenEnv = process12.env.JSR_TOKEN;
|
|
7161
|
+
if (!jsrTokenEnv) {
|
|
7162
|
+
throw new JsrAvailableError(
|
|
7163
|
+
"JSR_TOKEN not found in the environment variables. Please set the token and try again."
|
|
7164
|
+
);
|
|
7165
|
+
}
|
|
7166
|
+
JsrClient.token = jsrTokenEnv;
|
|
7008
7167
|
}
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
const maxAttempts = 3;
|
|
7017
|
-
task.output = `Package doesn't exist on jsr. Create it at:
|
|
7168
|
+
let result = await jsr.publish();
|
|
7169
|
+
if (!result && jsr.packageCreationUrls) {
|
|
7170
|
+
if (ctx.promptEnabled) {
|
|
7171
|
+
task.title = "Running jsr publish (package creation needed)";
|
|
7172
|
+
const urls = jsr.packageCreationUrls;
|
|
7173
|
+
const maxAttempts = 3;
|
|
7174
|
+
task.output = `Package doesn't exist on jsr. Create it at:
|
|
7018
7175
|
${urls.map((url) => ` ${color.cyan(url)}`).join("\n")}`;
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
|
|
7027
|
-
|
|
7028
|
-
|
|
7176
|
+
open(urls[0]);
|
|
7177
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
7178
|
+
await task.prompt(ListrEnquirerPromptAdapter3).run({
|
|
7179
|
+
type: "input",
|
|
7180
|
+
message: `Press ${color.bold("enter")} after creating the package on jsr.io${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
|
|
7181
|
+
});
|
|
7182
|
+
result = await jsr.publish();
|
|
7183
|
+
if (result) break;
|
|
7184
|
+
if (attempt < maxAttempts) {
|
|
7185
|
+
task.output = "Package still doesn't exist. Please create it and try again.";
|
|
7186
|
+
}
|
|
7029
7187
|
}
|
|
7030
|
-
|
|
7031
|
-
|
|
7188
|
+
if (!result) {
|
|
7189
|
+
throw new JsrAvailableError(
|
|
7190
|
+
"Package creation not completed after 3 attempts."
|
|
7191
|
+
);
|
|
7192
|
+
}
|
|
7193
|
+
task.title = "Running jsr publish (package created)";
|
|
7194
|
+
} else {
|
|
7032
7195
|
throw new JsrAvailableError(
|
|
7033
|
-
|
|
7196
|
+
`Package doesn't exist on jsr. Create it at:
|
|
7197
|
+
${jsr.packageCreationUrls.join("\n")}`
|
|
7034
7198
|
);
|
|
7035
7199
|
}
|
|
7036
|
-
task.title = "Running jsr publish (package created)";
|
|
7037
|
-
} else {
|
|
7038
|
-
throw new JsrAvailableError(
|
|
7039
|
-
`Package doesn't exist on jsr. Create it at:
|
|
7040
|
-
${jsr.packageCreationUrls.join("\n")}`
|
|
7041
|
-
);
|
|
7042
7200
|
}
|
|
7201
|
+
} catch (error) {
|
|
7202
|
+
if (error instanceof Error && error.message.includes("already published")) {
|
|
7203
|
+
task.title = `[SKIPPED] jsr: v${ctx.version} already published`;
|
|
7204
|
+
task.output = `\u26A0 ${jsr.packageName}@${ctx.version} is already published on jsr`;
|
|
7205
|
+
return task.skip();
|
|
7206
|
+
}
|
|
7207
|
+
throw error;
|
|
7043
7208
|
}
|
|
7044
7209
|
}
|
|
7045
7210
|
};
|
|
@@ -7136,44 +7301,62 @@ var npmPublishTasks = {
|
|
|
7136
7301
|
skip: (ctx) => !!ctx.preview,
|
|
7137
7302
|
task: async (ctx, task) => {
|
|
7138
7303
|
const npm = await npmRegistry();
|
|
7304
|
+
if (await npm.isVersionPublished(ctx.version)) {
|
|
7305
|
+
task.title = `[SKIPPED] npm: v${ctx.version} already published`;
|
|
7306
|
+
task.output = `\u26A0 ${npm.packageName}@${ctx.version} is already published on npm`;
|
|
7307
|
+
return task.skip();
|
|
7308
|
+
}
|
|
7139
7309
|
task.output = "Publishing on npm...";
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
await
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7310
|
+
try {
|
|
7311
|
+
if (ctx.promptEnabled) {
|
|
7312
|
+
let result = await npm.publish();
|
|
7313
|
+
if (!result) {
|
|
7314
|
+
task.title = "Running npm publish (OTP code needed)";
|
|
7315
|
+
const maxAttempts = 3;
|
|
7316
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
7317
|
+
result = await npm.publish(
|
|
7318
|
+
await task.prompt(ListrEnquirerPromptAdapter4).run({
|
|
7319
|
+
type: "password",
|
|
7320
|
+
message: `npm OTP code${attempt > 1 ? ` (attempt ${attempt}/${maxAttempts})` : ""}`
|
|
7321
|
+
})
|
|
7322
|
+
);
|
|
7323
|
+
if (result) break;
|
|
7324
|
+
if (attempt < maxAttempts) {
|
|
7325
|
+
task.output = "2FA failed. Please try again.";
|
|
7326
|
+
}
|
|
7327
|
+
}
|
|
7328
|
+
if (!result) {
|
|
7329
|
+
throw new NpmAvailableError(
|
|
7330
|
+
"OTP verification failed after 3 attempts."
|
|
7331
|
+
);
|
|
7155
7332
|
}
|
|
7333
|
+
task.title = "Running npm publish (2FA passed)";
|
|
7334
|
+
}
|
|
7335
|
+
} else {
|
|
7336
|
+
const npmTokenEnv = process13.env.NODE_AUTH_TOKEN;
|
|
7337
|
+
if (!npmTokenEnv) {
|
|
7338
|
+
throw new NpmAvailableError(
|
|
7339
|
+
"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"
|
|
7340
|
+
);
|
|
7156
7341
|
}
|
|
7342
|
+
const result = await npm.publishProvenance();
|
|
7157
7343
|
if (!result) {
|
|
7158
7344
|
throw new NpmAvailableError(
|
|
7159
|
-
|
|
7345
|
+
`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 `
|
|
7160
7346
|
);
|
|
7161
7347
|
}
|
|
7162
|
-
task.title = "Running npm publish (2FA passed)";
|
|
7163
7348
|
}
|
|
7164
|
-
}
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
throw new NpmAvailableError(
|
|
7174
|
-
`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 `
|
|
7175
|
-
);
|
|
7349
|
+
} catch (error) {
|
|
7350
|
+
if (error instanceof Error && (error.message.includes(
|
|
7351
|
+
"cannot publish over the previously published"
|
|
7352
|
+
) || error.message.includes(
|
|
7353
|
+
"You cannot publish over the previously published"
|
|
7354
|
+
))) {
|
|
7355
|
+
task.title = `[SKIPPED] npm: v${ctx.version} already published`;
|
|
7356
|
+
task.output = `\u26A0 ${npm.packageName}@${ctx.version} is already published on npm`;
|
|
7357
|
+
return task.skip();
|
|
7176
7358
|
}
|
|
7359
|
+
throw error;
|
|
7177
7360
|
}
|
|
7178
7361
|
}
|
|
7179
7362
|
};
|
|
@@ -7589,10 +7772,15 @@ async function collectDryRunPublishTasks(ctx) {
|
|
|
7589
7772
|
return nonCratesTasks;
|
|
7590
7773
|
}
|
|
7591
7774
|
const sortedPaths = await sortCratesByDependencyOrder(cratesPaths);
|
|
7775
|
+
const siblingCrateNames = await Promise.all(
|
|
7776
|
+
cratesPaths.map((p) => new RustEcosystem(p).packageName())
|
|
7777
|
+
);
|
|
7592
7778
|
const sequentialCratesTask = {
|
|
7593
7779
|
title: "Dry-run crates.io publish (sequential)",
|
|
7594
7780
|
task: (_ctx, task) => task.newListr(
|
|
7595
|
-
sortedPaths.map(
|
|
7781
|
+
sortedPaths.map(
|
|
7782
|
+
(p) => createCratesDryRunPublishTask(p, siblingCrateNames)
|
|
7783
|
+
),
|
|
7596
7784
|
{ concurrent: false }
|
|
7597
7785
|
)
|
|
7598
7786
|
};
|
|
@@ -7685,23 +7873,23 @@ async function run(options) {
|
|
|
7685
7873
|
addRollback(async () => {
|
|
7686
7874
|
if (tagCreated) {
|
|
7687
7875
|
try {
|
|
7688
|
-
|
|
7876
|
+
rollbackLog("Deleting tag");
|
|
7689
7877
|
await git.deleteTag(`${await git.latestTag()}`);
|
|
7690
7878
|
} catch (error) {
|
|
7691
|
-
|
|
7879
|
+
rollbackError(
|
|
7692
7880
|
`Failed to delete tag: ${error instanceof Error ? error.message : error}`
|
|
7693
7881
|
);
|
|
7694
7882
|
}
|
|
7695
7883
|
}
|
|
7696
7884
|
if (commited) {
|
|
7697
7885
|
try {
|
|
7698
|
-
|
|
7886
|
+
rollbackLog("Resetting commits");
|
|
7699
7887
|
await git.reset();
|
|
7700
7888
|
await git.stash();
|
|
7701
7889
|
await git.reset("HEAD^", "--hard");
|
|
7702
7890
|
await git.popStash();
|
|
7703
7891
|
} catch (error) {
|
|
7704
|
-
|
|
7892
|
+
rollbackError(
|
|
7705
7893
|
`Failed to reset commits: ${error instanceof Error ? error.message : error}`
|
|
7706
7894
|
);
|
|
7707
7895
|
}
|