@releasekit/publish 0.2.0-next.9 → 0.3.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +13 -1
- package/dist/{chunk-Y7Y6GQ6R.js → chunk-GOBII36Q.js} +297 -112
- package/dist/cli.cjs +317 -134
- package/dist/cli.js +1 -1
- package/dist/index.cjs +311 -128
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +1 -1
- package/package.json +38 -28
package/dist/cli.cjs
CHANGED
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/cli.ts
|
|
27
|
-
var
|
|
27
|
+
var import_core13 = require("@releasekit/core");
|
|
28
28
|
var import_commander = require("commander");
|
|
29
29
|
|
|
30
30
|
// src/config.ts
|
|
@@ -52,14 +52,16 @@ function getDefaultConfig() {
|
|
|
52
52
|
push: true,
|
|
53
53
|
pushMethod: "auto",
|
|
54
54
|
remote: "origin",
|
|
55
|
-
branch: "main"
|
|
55
|
+
branch: "main",
|
|
56
|
+
httpsTokenEnv: void 0,
|
|
57
|
+
skipHooks: false
|
|
56
58
|
},
|
|
57
59
|
githubRelease: {
|
|
58
60
|
enabled: true,
|
|
59
61
|
draft: true,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
perPackage: true,
|
|
63
|
+
prerelease: "auto",
|
|
64
|
+
releaseNotes: "auto"
|
|
63
65
|
},
|
|
64
66
|
verify: {
|
|
65
67
|
npm: {
|
|
@@ -100,15 +102,16 @@ function toPublishConfig(config) {
|
|
|
100
102
|
push: config.git.push ?? defaults.git.push,
|
|
101
103
|
pushMethod: config.git.pushMethod ?? defaults.git.pushMethod,
|
|
102
104
|
remote: config.git.remote ?? defaults.git.remote,
|
|
103
|
-
branch: config.git.branch ?? defaults.git.branch
|
|
105
|
+
branch: config.git.branch ?? defaults.git.branch,
|
|
106
|
+
httpsTokenEnv: config.git.httpsTokenEnv ?? defaults.git.httpsTokenEnv,
|
|
107
|
+
skipHooks: config.git.skipHooks ?? defaults.git.skipHooks
|
|
104
108
|
} : defaults.git,
|
|
105
109
|
githubRelease: {
|
|
106
110
|
enabled: config.githubRelease?.enabled ?? defaults.githubRelease.enabled,
|
|
107
111
|
draft: config.githubRelease?.draft ?? defaults.githubRelease.draft,
|
|
108
|
-
generateNotes: config.githubRelease?.generateNotes ?? defaults.githubRelease.generateNotes,
|
|
109
112
|
perPackage: config.githubRelease?.perPackage ?? defaults.githubRelease.perPackage,
|
|
110
113
|
prerelease: config.githubRelease?.prerelease ?? defaults.githubRelease.prerelease,
|
|
111
|
-
|
|
114
|
+
releaseNotes: config.githubRelease?.releaseNotes ?? defaults.githubRelease.releaseNotes
|
|
112
115
|
},
|
|
113
116
|
verify: {
|
|
114
117
|
npm: {
|
|
@@ -261,8 +264,20 @@ var import_core3 = require("@releasekit/core");
|
|
|
261
264
|
// src/utils/exec.ts
|
|
262
265
|
var import_node_child_process = require("child_process");
|
|
263
266
|
var import_core2 = require("@releasekit/core");
|
|
267
|
+
function redactArg(arg) {
|
|
268
|
+
try {
|
|
269
|
+
const url = new URL(arg);
|
|
270
|
+
if (url.username || url.password) {
|
|
271
|
+
url.username = url.username ? "***" : "";
|
|
272
|
+
url.password = url.password ? "***" : "";
|
|
273
|
+
return url.toString();
|
|
274
|
+
}
|
|
275
|
+
} catch {
|
|
276
|
+
}
|
|
277
|
+
return arg;
|
|
278
|
+
}
|
|
264
279
|
async function execCommand(file, args, options = {}) {
|
|
265
|
-
const displayCommand = options.label ?? [file, ...args].join(" ");
|
|
280
|
+
const displayCommand = options.label ?? [file, ...args.map(redactArg)].join(" ");
|
|
266
281
|
if (options.dryRun) {
|
|
267
282
|
(0, import_core2.info)(`[DRY RUN] Would execute: ${displayCommand}`);
|
|
268
283
|
return { stdout: "", stderr: "", exitCode: 0 };
|
|
@@ -318,7 +333,7 @@ function detectNpmAuth() {
|
|
|
318
333
|
if (process.env.ACTIONS_ID_TOKEN_REQUEST_URL) {
|
|
319
334
|
return "oidc";
|
|
320
335
|
}
|
|
321
|
-
if (process.env.NPM_TOKEN) {
|
|
336
|
+
if (process.env.NPM_TOKEN || process.env.NODE_AUTH_TOKEN) {
|
|
322
337
|
return "token";
|
|
323
338
|
}
|
|
324
339
|
return null;
|
|
@@ -527,13 +542,17 @@ function topologicalSort(crates) {
|
|
|
527
542
|
var path2 = __toESM(require("path"), 1);
|
|
528
543
|
var import_core4 = require("@releasekit/core");
|
|
529
544
|
async function runGitCommitStage(ctx) {
|
|
530
|
-
const { input, cliOptions, cwd } = ctx;
|
|
545
|
+
const { input, config, cliOptions, cwd } = ctx;
|
|
531
546
|
const dryRun = cliOptions.dryRun;
|
|
547
|
+
const skipHooks = config.git.skipHooks ?? false;
|
|
532
548
|
if (!input.commitMessage) {
|
|
533
549
|
(0, import_core4.info)("No commit message provided, skipping git commit");
|
|
534
550
|
return;
|
|
535
551
|
}
|
|
536
552
|
const filePaths = input.updates.map((u) => path2.resolve(cwd, u.filePath));
|
|
553
|
+
if (ctx.additionalFiles) {
|
|
554
|
+
filePaths.push(...ctx.additionalFiles.map((f) => path2.resolve(cwd, f)));
|
|
555
|
+
}
|
|
537
556
|
if (filePaths.length === 0) {
|
|
538
557
|
(0, import_core4.info)("No files to commit");
|
|
539
558
|
return;
|
|
@@ -550,8 +569,13 @@ async function runGitCommitStage(ctx) {
|
|
|
550
569
|
`git add failed: ${error instanceof Error ? error.message : String(error)}`
|
|
551
570
|
);
|
|
552
571
|
}
|
|
572
|
+
const commitArgs = ["commit"];
|
|
573
|
+
if (skipHooks) {
|
|
574
|
+
commitArgs.push("--no-verify");
|
|
575
|
+
}
|
|
576
|
+
commitArgs.push("-m", input.commitMessage);
|
|
553
577
|
try {
|
|
554
|
-
await execCommand("git",
|
|
578
|
+
await execCommand("git", commitArgs, {
|
|
555
579
|
cwd,
|
|
556
580
|
dryRun,
|
|
557
581
|
label: `git commit -m "${input.commitMessage}"`
|
|
@@ -589,6 +613,18 @@ async function runGitCommitStage(ctx) {
|
|
|
589
613
|
|
|
590
614
|
// src/stages/git-push.ts
|
|
591
615
|
var import_core5 = require("@releasekit/core");
|
|
616
|
+
function toGithubAuthedUrl(remoteUrl, token) {
|
|
617
|
+
try {
|
|
618
|
+
const url = new URL(remoteUrl);
|
|
619
|
+
if (url.protocol !== "https:") return void 0;
|
|
620
|
+
if (url.host !== "github.com") return void 0;
|
|
621
|
+
url.username = "x-access-token";
|
|
622
|
+
url.password = token;
|
|
623
|
+
return url.toString();
|
|
624
|
+
} catch {
|
|
625
|
+
return void 0;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
592
628
|
async function runGitPushStage(ctx) {
|
|
593
629
|
const { config, cliOptions, cwd, output } = ctx;
|
|
594
630
|
const dryRun = cliOptions.dryRun;
|
|
@@ -609,16 +645,26 @@ async function runGitPushStage(ctx) {
|
|
|
609
645
|
pushMethod = "https";
|
|
610
646
|
}
|
|
611
647
|
}
|
|
648
|
+
const httpsTokenEnv = config.git.httpsTokenEnv;
|
|
649
|
+
const httpsToken = httpsTokenEnv ? process.env[httpsTokenEnv] : void 0;
|
|
612
650
|
try {
|
|
651
|
+
let pushRemote = remote;
|
|
652
|
+
if (pushMethod === "https" && httpsToken) {
|
|
653
|
+
const remoteUrlResult = await execCommand("git", ["remote", "get-url", remote], { cwd, dryRun: false });
|
|
654
|
+
const authed = toGithubAuthedUrl(remoteUrlResult.stdout.trim(), httpsToken);
|
|
655
|
+
if (authed) {
|
|
656
|
+
pushRemote = authed;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
613
659
|
if (output.git.committed) {
|
|
614
|
-
await execCommand("git", ["push",
|
|
660
|
+
await execCommand("git", ["push", pushRemote, branch], {
|
|
615
661
|
cwd,
|
|
616
662
|
dryRun,
|
|
617
663
|
label: `git push ${remote} ${branch}`
|
|
618
664
|
});
|
|
619
665
|
}
|
|
620
666
|
if (output.git.tags.length > 0) {
|
|
621
|
-
await execCommand("git", ["push",
|
|
667
|
+
await execCommand("git", ["push", pushRemote, "--tags"], {
|
|
622
668
|
cwd,
|
|
623
669
|
dryRun,
|
|
624
670
|
label: `git push ${remote} --tags`
|
|
@@ -655,6 +701,62 @@ function getDistTag(version, defaultTag = "latest") {
|
|
|
655
701
|
}
|
|
656
702
|
|
|
657
703
|
// src/stages/github-release.ts
|
|
704
|
+
function resolveNotes(notesSetting, tag, changelogs, pipelineNotes) {
|
|
705
|
+
if (notesSetting === "none") {
|
|
706
|
+
return { useGithubNotes: false };
|
|
707
|
+
}
|
|
708
|
+
if (notesSetting === "github") {
|
|
709
|
+
return { useGithubNotes: true };
|
|
710
|
+
}
|
|
711
|
+
if (notesSetting !== "auto") {
|
|
712
|
+
const body = readFileIfExists(notesSetting);
|
|
713
|
+
if (body) return { body, useGithubNotes: false };
|
|
714
|
+
(0, import_core6.debug)(`Notes file not found: ${notesSetting}, falling back to GitHub auto-notes`);
|
|
715
|
+
return { useGithubNotes: true };
|
|
716
|
+
}
|
|
717
|
+
if (pipelineNotes) {
|
|
718
|
+
const body = findNotesForTag(tag, pipelineNotes);
|
|
719
|
+
if (body) return { body, useGithubNotes: false };
|
|
720
|
+
}
|
|
721
|
+
const packageBody = formatChangelogForTag(tag, changelogs);
|
|
722
|
+
if (packageBody) {
|
|
723
|
+
return { body: packageBody, useGithubNotes: false };
|
|
724
|
+
}
|
|
725
|
+
return { useGithubNotes: true };
|
|
726
|
+
}
|
|
727
|
+
function isVersionOnlyTag(tag) {
|
|
728
|
+
return /^v?\d+\.\d+\.\d+/.test(tag);
|
|
729
|
+
}
|
|
730
|
+
function findNotesForTag(tag, notes) {
|
|
731
|
+
for (const [packageName, body] of Object.entries(notes)) {
|
|
732
|
+
if (tag.startsWith(`${packageName}@`) && body.trim()) {
|
|
733
|
+
return body;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
const entries = Object.values(notes).filter((b) => b.trim());
|
|
737
|
+
if (entries.length === 1 && isVersionOnlyTag(tag)) return entries[0];
|
|
738
|
+
return void 0;
|
|
739
|
+
}
|
|
740
|
+
function readFileIfExists(filePath) {
|
|
741
|
+
try {
|
|
742
|
+
const content = fs3.readFileSync(filePath, "utf-8").trim();
|
|
743
|
+
return content || void 0;
|
|
744
|
+
} catch {
|
|
745
|
+
return void 0;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
function formatChangelogForTag(tag, changelogs) {
|
|
749
|
+
if (changelogs.length === 0) return void 0;
|
|
750
|
+
const changelog = changelogs.find((c) => tag.startsWith(`${c.packageName}@`));
|
|
751
|
+
const target = changelog ?? (changelogs.length === 1 && isVersionOnlyTag(tag) ? changelogs[0] : void 0);
|
|
752
|
+
if (!target || target.entries.length === 0) return void 0;
|
|
753
|
+
const lines = [];
|
|
754
|
+
for (const entry of target.entries) {
|
|
755
|
+
const scope = entry.scope ? `**${entry.scope}:** ` : "";
|
|
756
|
+
lines.push(`- ${scope}${entry.description}`);
|
|
757
|
+
}
|
|
758
|
+
return lines.join("\n");
|
|
759
|
+
}
|
|
658
760
|
async function runGithubReleaseStage(ctx) {
|
|
659
761
|
const { config, cliOptions, output } = ctx;
|
|
660
762
|
const dryRun = cliOptions.dryRun;
|
|
@@ -667,19 +769,13 @@ async function runGithubReleaseStage(ctx) {
|
|
|
667
769
|
(0, import_core6.info)("No tags available for GitHub release");
|
|
668
770
|
return;
|
|
669
771
|
}
|
|
670
|
-
let notesBody;
|
|
671
|
-
if (config.githubRelease.notesFile) {
|
|
672
|
-
try {
|
|
673
|
-
notesBody = fs3.readFileSync(config.githubRelease.notesFile, "utf-8");
|
|
674
|
-
} catch {
|
|
675
|
-
(0, import_core6.debug)(`Could not read notes file: ${config.githubRelease.notesFile}`);
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
772
|
const firstTag = tags[0];
|
|
679
773
|
if (!firstTag) return;
|
|
680
774
|
const tagsToRelease = config.githubRelease.perPackage ? tags : [firstTag];
|
|
681
775
|
for (const tag of tagsToRelease) {
|
|
682
|
-
const
|
|
776
|
+
const MAX_TAG_LENGTH = 1e3;
|
|
777
|
+
const truncatedTag = tag.length > MAX_TAG_LENGTH ? tag.slice(0, MAX_TAG_LENGTH) : tag;
|
|
778
|
+
const versionMatch = truncatedTag.match(/(\d{1,20}\.\d{1,20}\.\d{1,20}(?:[-+.]?[a-zA-Z0-9.-]{0,100})?)$/);
|
|
683
779
|
const version = versionMatch?.[1] ?? "";
|
|
684
780
|
const isPreRel = config.githubRelease.prerelease === "auto" ? version ? isPrerelease(version) : false : config.githubRelease.prerelease;
|
|
685
781
|
const result = {
|
|
@@ -695,9 +791,15 @@ async function runGithubReleaseStage(ctx) {
|
|
|
695
791
|
if (isPreRel) {
|
|
696
792
|
ghArgs.push("--prerelease");
|
|
697
793
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
794
|
+
const { body, useGithubNotes } = resolveNotes(
|
|
795
|
+
config.githubRelease.releaseNotes,
|
|
796
|
+
tag,
|
|
797
|
+
ctx.input.changelogs,
|
|
798
|
+
ctx.releaseNotes
|
|
799
|
+
);
|
|
800
|
+
if (body) {
|
|
801
|
+
ghArgs.push("--notes", body);
|
|
802
|
+
} else if (useGithubNotes) {
|
|
701
803
|
ghArgs.push("--generate-notes");
|
|
702
804
|
}
|
|
703
805
|
try {
|
|
@@ -721,16 +823,82 @@ async function runGithubReleaseStage(ctx) {
|
|
|
721
823
|
}
|
|
722
824
|
|
|
723
825
|
// src/stages/npm-publish.ts
|
|
724
|
-
var
|
|
725
|
-
var
|
|
726
|
-
var
|
|
826
|
+
var fs6 = __toESM(require("fs"), 1);
|
|
827
|
+
var path5 = __toESM(require("path"), 1);
|
|
828
|
+
var import_core8 = require("@releasekit/core");
|
|
727
829
|
|
|
728
|
-
// src/utils/
|
|
830
|
+
// src/utils/npm-env.ts
|
|
729
831
|
var fs4 = __toESM(require("fs"), 1);
|
|
832
|
+
var os = __toESM(require("os"), 1);
|
|
730
833
|
var path3 = __toESM(require("path"), 1);
|
|
834
|
+
var import_core7 = require("@releasekit/core");
|
|
835
|
+
function writeTempNpmrc(contents) {
|
|
836
|
+
const dir = fs4.mkdtempSync(path3.join(os.tmpdir(), "releasekit-npmrc-"));
|
|
837
|
+
const npmrcPath = path3.join(dir, ".npmrc");
|
|
838
|
+
fs4.writeFileSync(npmrcPath, contents, "utf-8");
|
|
839
|
+
return {
|
|
840
|
+
npmrcPath,
|
|
841
|
+
cleanup: () => {
|
|
842
|
+
try {
|
|
843
|
+
fs4.rmSync(dir, { recursive: true, force: true });
|
|
844
|
+
} catch {
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
function createNpmSubprocessIsolation(options) {
|
|
850
|
+
const { authMethod, registryUrl } = options;
|
|
851
|
+
const baseEnv = {};
|
|
852
|
+
if (!authMethod) return { env: baseEnv, cleanup: () => {
|
|
853
|
+
} };
|
|
854
|
+
const token = process.env.NPM_TOKEN ?? process.env.NODE_AUTH_TOKEN;
|
|
855
|
+
const registryHost = (() => {
|
|
856
|
+
try {
|
|
857
|
+
return new URL(registryUrl).host;
|
|
858
|
+
} catch {
|
|
859
|
+
return "registry.npmjs.org";
|
|
860
|
+
}
|
|
861
|
+
})();
|
|
862
|
+
const lines = [`registry=${registryUrl}`];
|
|
863
|
+
if (authMethod === "oidc") {
|
|
864
|
+
lines.push("always-auth=false");
|
|
865
|
+
}
|
|
866
|
+
if (authMethod === "token" && token) {
|
|
867
|
+
lines.push(`//${registryHost}/:_authToken=${token}`);
|
|
868
|
+
}
|
|
869
|
+
lines.push("");
|
|
870
|
+
const { npmrcPath, cleanup } = writeTempNpmrc(lines.join("\n"));
|
|
871
|
+
(0, import_core7.debug)(`Using isolated npm userconfig: ${npmrcPath}`);
|
|
872
|
+
const isOidc = authMethod === "oidc";
|
|
873
|
+
return {
|
|
874
|
+
env: {
|
|
875
|
+
...baseEnv,
|
|
876
|
+
// Ensure npm and tools that read npm_config_* pick up our temp file
|
|
877
|
+
NPM_CONFIG_USERCONFIG: npmrcPath,
|
|
878
|
+
npm_config_userconfig: npmrcPath,
|
|
879
|
+
// Auth-specific hardening
|
|
880
|
+
...isOidc ? {
|
|
881
|
+
// Prevent setup-node's always-auth from forcing token lookups
|
|
882
|
+
NPM_CONFIG_ALWAYS_AUTH: "false",
|
|
883
|
+
npm_config_always_auth: "false",
|
|
884
|
+
// Explicitly prevent token-based publishing from being selected implicitly
|
|
885
|
+
NODE_AUTH_TOKEN: void 0,
|
|
886
|
+
NPM_TOKEN: void 0
|
|
887
|
+
} : {
|
|
888
|
+
// Ensure CLIs that expect NODE_AUTH_TOKEN can still work
|
|
889
|
+
NODE_AUTH_TOKEN: token
|
|
890
|
+
}
|
|
891
|
+
},
|
|
892
|
+
cleanup
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// src/utils/package-manager.ts
|
|
897
|
+
var fs5 = __toESM(require("fs"), 1);
|
|
898
|
+
var path4 = __toESM(require("path"), 1);
|
|
731
899
|
function detectPackageManager(cwd) {
|
|
732
|
-
if (
|
|
733
|
-
if (
|
|
900
|
+
if (fs5.existsSync(path4.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
901
|
+
if (fs5.existsSync(path4.join(cwd, "yarn.lock"))) return "yarn";
|
|
734
902
|
return "npm";
|
|
735
903
|
}
|
|
736
904
|
function buildPublishCommand(pm, packageName, _packageDir, options) {
|
|
@@ -759,7 +927,7 @@ async function runNpmPublishStage(ctx) {
|
|
|
759
927
|
const { input, config, cliOptions, cwd } = ctx;
|
|
760
928
|
const dryRun = cliOptions.dryRun;
|
|
761
929
|
if (!config.npm.enabled) {
|
|
762
|
-
(0,
|
|
930
|
+
(0, import_core8.info)("NPM publishing disabled in config");
|
|
763
931
|
return;
|
|
764
932
|
}
|
|
765
933
|
const authMethod = config.npm.auth === "auto" ? detectNpmAuth() : config.npm.auth;
|
|
@@ -767,107 +935,117 @@ async function runNpmPublishStage(ctx) {
|
|
|
767
935
|
throw createPublishError("NPM_AUTH_ERROR" /* NPM_AUTH_ERROR */, "No NPM authentication method detected");
|
|
768
936
|
}
|
|
769
937
|
const useProvenance = config.npm.provenance && authMethod === "oidc";
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
(
|
|
788
|
-
|
|
938
|
+
const npmIsolation = createNpmSubprocessIsolation({
|
|
939
|
+
authMethod,
|
|
940
|
+
registryUrl: config.npm.registry
|
|
941
|
+
});
|
|
942
|
+
try {
|
|
943
|
+
for (const update of input.updates) {
|
|
944
|
+
const result = {
|
|
945
|
+
packageName: update.packageName,
|
|
946
|
+
version: update.newVersion,
|
|
947
|
+
registry: "npm",
|
|
948
|
+
success: false,
|
|
949
|
+
skipped: false
|
|
950
|
+
};
|
|
951
|
+
const pkgJsonPath = path5.resolve(cwd, update.filePath);
|
|
952
|
+
try {
|
|
953
|
+
const pkgContent = fs6.readFileSync(pkgJsonPath, "utf-8");
|
|
954
|
+
const pkgJson = JSON.parse(pkgContent);
|
|
955
|
+
if (pkgJson.private) {
|
|
956
|
+
result.skipped = true;
|
|
957
|
+
result.success = true;
|
|
958
|
+
result.reason = "Package is private";
|
|
959
|
+
ctx.output.npm.push(result);
|
|
960
|
+
(0, import_core8.debug)(`Skipping private package: ${update.packageName}`);
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
} catch {
|
|
964
|
+
if (update.filePath.endsWith("Cargo.toml")) {
|
|
965
|
+
result.skipped = true;
|
|
966
|
+
result.success = true;
|
|
967
|
+
result.reason = "Not an npm package";
|
|
968
|
+
ctx.output.npm.push(result);
|
|
969
|
+
continue;
|
|
970
|
+
}
|
|
789
971
|
}
|
|
790
|
-
|
|
791
|
-
|
|
972
|
+
const { file: viewFile, args: viewArgs } = buildViewCommand(
|
|
973
|
+
ctx.packageManager,
|
|
974
|
+
update.packageName,
|
|
975
|
+
update.newVersion
|
|
976
|
+
);
|
|
977
|
+
const viewResult = await execCommandSafe(viewFile, viewArgs, {
|
|
978
|
+
cwd,
|
|
979
|
+
dryRun: false,
|
|
980
|
+
// Always check, even in dry-run
|
|
981
|
+
env: npmIsolation.env
|
|
982
|
+
});
|
|
983
|
+
if (viewResult.exitCode === 0 && viewResult.stdout.trim()) {
|
|
984
|
+
result.alreadyPublished = true;
|
|
792
985
|
result.skipped = true;
|
|
793
986
|
result.success = true;
|
|
794
|
-
result.reason = "
|
|
987
|
+
result.reason = "Already published";
|
|
795
988
|
ctx.output.npm.push(result);
|
|
989
|
+
(0, import_core8.warn)(`${update.packageName}@${update.newVersion} is already published, skipping`);
|
|
796
990
|
continue;
|
|
797
991
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
ctx.packageManager,
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
cwd,
|
|
806
|
-
dryRun: false
|
|
807
|
-
// Always check, even in dry-run
|
|
808
|
-
});
|
|
809
|
-
if (viewResult.exitCode === 0 && viewResult.stdout.trim()) {
|
|
810
|
-
result.alreadyPublished = true;
|
|
811
|
-
result.skipped = true;
|
|
812
|
-
result.success = true;
|
|
813
|
-
result.reason = "Already published";
|
|
814
|
-
ctx.output.npm.push(result);
|
|
815
|
-
(0, import_core7.warn)(`${update.packageName}@${update.newVersion} is already published, skipping`);
|
|
816
|
-
continue;
|
|
817
|
-
}
|
|
818
|
-
const distTag = getDistTag(update.newVersion, config.npm.tag);
|
|
819
|
-
const pkgDir = path4.dirname(path4.resolve(cwd, update.filePath));
|
|
820
|
-
const { file: pubFile, args: pubArgs } = buildPublishCommand(ctx.packageManager, update.packageName, pkgDir, {
|
|
821
|
-
access: config.npm.access,
|
|
822
|
-
tag: distTag,
|
|
823
|
-
provenance: useProvenance,
|
|
824
|
-
noGitChecks: true
|
|
825
|
-
});
|
|
826
|
-
try {
|
|
827
|
-
await execCommand(pubFile, pubArgs, {
|
|
828
|
-
cwd,
|
|
829
|
-
dryRun,
|
|
830
|
-
label: `npm publish ${update.packageName}@${update.newVersion}`
|
|
992
|
+
const distTag = getDistTag(update.newVersion, config.npm.tag);
|
|
993
|
+
const pkgDir = path5.dirname(path5.resolve(cwd, update.filePath));
|
|
994
|
+
const { file: pubFile, args: pubArgs } = buildPublishCommand(ctx.packageManager, update.packageName, pkgDir, {
|
|
995
|
+
access: config.npm.access,
|
|
996
|
+
tag: distTag,
|
|
997
|
+
provenance: useProvenance,
|
|
998
|
+
noGitChecks: true
|
|
831
999
|
});
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
1000
|
+
try {
|
|
1001
|
+
await execCommand(pubFile, pubArgs, {
|
|
1002
|
+
cwd,
|
|
1003
|
+
dryRun,
|
|
1004
|
+
label: `npm publish ${update.packageName}@${update.newVersion}`,
|
|
1005
|
+
env: npmIsolation.env
|
|
1006
|
+
});
|
|
1007
|
+
result.success = true;
|
|
1008
|
+
if (!dryRun) {
|
|
1009
|
+
(0, import_core8.success)(`Published ${update.packageName}@${update.newVersion} to npm`);
|
|
1010
|
+
}
|
|
1011
|
+
} catch (error) {
|
|
1012
|
+
result.reason = error instanceof Error ? error.message : String(error);
|
|
1013
|
+
(0, import_core8.warn)(`Failed to publish ${update.packageName}: ${result.reason}`);
|
|
835
1014
|
}
|
|
836
|
-
|
|
837
|
-
result.reason = error instanceof Error ? error.message : String(error);
|
|
838
|
-
(0, import_core7.warn)(`Failed to publish ${update.packageName}: ${result.reason}`);
|
|
1015
|
+
ctx.output.npm.push(result);
|
|
839
1016
|
}
|
|
840
|
-
|
|
1017
|
+
} finally {
|
|
1018
|
+
npmIsolation.cleanup();
|
|
841
1019
|
}
|
|
842
1020
|
}
|
|
843
1021
|
|
|
844
1022
|
// src/stages/prepare.ts
|
|
845
|
-
var
|
|
846
|
-
var
|
|
847
|
-
var
|
|
1023
|
+
var fs7 = __toESM(require("fs"), 1);
|
|
1024
|
+
var path6 = __toESM(require("path"), 1);
|
|
1025
|
+
var import_core9 = require("@releasekit/core");
|
|
848
1026
|
async function runPrepareStage(ctx) {
|
|
849
1027
|
const { input, config, cliOptions, cwd } = ctx;
|
|
850
1028
|
if (config.npm.enabled && config.npm.copyFiles.length > 0) {
|
|
851
1029
|
for (const update of input.updates) {
|
|
852
|
-
const pkgDir =
|
|
1030
|
+
const pkgDir = path6.dirname(path6.resolve(cwd, update.filePath));
|
|
853
1031
|
for (const file of config.npm.copyFiles) {
|
|
854
|
-
const src =
|
|
855
|
-
const dest =
|
|
856
|
-
if (!
|
|
857
|
-
(0,
|
|
1032
|
+
const src = path6.resolve(cwd, file);
|
|
1033
|
+
const dest = path6.join(pkgDir, file);
|
|
1034
|
+
if (!fs7.existsSync(src)) {
|
|
1035
|
+
(0, import_core9.debug)(`Source file not found, skipping copy: ${src}`);
|
|
858
1036
|
continue;
|
|
859
1037
|
}
|
|
860
|
-
if (
|
|
861
|
-
(0,
|
|
1038
|
+
if (path6.resolve(path6.dirname(src)) === path6.resolve(pkgDir)) {
|
|
1039
|
+
(0, import_core9.debug)(`Skipping copy of ${file} - same directory as source`);
|
|
862
1040
|
continue;
|
|
863
1041
|
}
|
|
864
1042
|
if (cliOptions.dryRun) {
|
|
865
|
-
(0,
|
|
1043
|
+
(0, import_core9.info)(`[DRY RUN] Would copy ${src} \u2192 ${dest}`);
|
|
866
1044
|
continue;
|
|
867
1045
|
}
|
|
868
1046
|
try {
|
|
869
|
-
|
|
870
|
-
(0,
|
|
1047
|
+
fs7.copyFileSync(src, dest);
|
|
1048
|
+
(0, import_core9.debug)(`Copied ${file} \u2192 ${pkgDir}`);
|
|
871
1049
|
} catch (error) {
|
|
872
1050
|
throw createPublishError(
|
|
873
1051
|
"FILE_COPY_ERROR" /* FILE_COPY_ERROR */,
|
|
@@ -879,26 +1057,26 @@ async function runPrepareStage(ctx) {
|
|
|
879
1057
|
}
|
|
880
1058
|
if (config.cargo.enabled) {
|
|
881
1059
|
for (const update of input.updates) {
|
|
882
|
-
const pkgDir =
|
|
883
|
-
const cargoPath =
|
|
884
|
-
if (!
|
|
1060
|
+
const pkgDir = path6.dirname(path6.resolve(cwd, update.filePath));
|
|
1061
|
+
const cargoPath = path6.join(pkgDir, "Cargo.toml");
|
|
1062
|
+
if (!fs7.existsSync(cargoPath)) {
|
|
885
1063
|
continue;
|
|
886
1064
|
}
|
|
887
1065
|
if (cliOptions.dryRun) {
|
|
888
|
-
(0,
|
|
1066
|
+
(0, import_core9.info)(`[DRY RUN] Would update ${cargoPath} to version ${update.newVersion}`);
|
|
889
1067
|
continue;
|
|
890
1068
|
}
|
|
891
1069
|
updateCargoVersion(cargoPath, update.newVersion);
|
|
892
|
-
(0,
|
|
1070
|
+
(0, import_core9.debug)(`Updated ${cargoPath} to version ${update.newVersion}`);
|
|
893
1071
|
}
|
|
894
1072
|
}
|
|
895
1073
|
}
|
|
896
1074
|
|
|
897
1075
|
// src/stages/verify.ts
|
|
898
|
-
var
|
|
1076
|
+
var import_core11 = require("@releasekit/core");
|
|
899
1077
|
|
|
900
1078
|
// src/utils/retry.ts
|
|
901
|
-
var
|
|
1079
|
+
var import_core10 = require("@releasekit/core");
|
|
902
1080
|
async function withRetry(fn, options, shouldRetry) {
|
|
903
1081
|
let lastError;
|
|
904
1082
|
let delay = options.initialDelay;
|
|
@@ -911,7 +1089,7 @@ async function withRetry(fn, options, shouldRetry) {
|
|
|
911
1089
|
throw error;
|
|
912
1090
|
}
|
|
913
1091
|
if (attempt < options.maxAttempts) {
|
|
914
|
-
(0,
|
|
1092
|
+
(0, import_core10.debug)(`Attempt ${attempt}/${options.maxAttempts} failed, retrying in ${delay}ms...`);
|
|
915
1093
|
await sleep(delay);
|
|
916
1094
|
delay = Math.floor(delay * options.backoffMultiplier);
|
|
917
1095
|
}
|
|
@@ -937,7 +1115,7 @@ async function runVerifyStage(ctx) {
|
|
|
937
1115
|
attempts: 0
|
|
938
1116
|
};
|
|
939
1117
|
if (cliOptions.dryRun) {
|
|
940
|
-
(0,
|
|
1118
|
+
(0, import_core11.info)(`[DRY RUN] Would verify ${pkg.packageName}@${pkg.version} on npm`);
|
|
941
1119
|
result.verified = true;
|
|
942
1120
|
ctx.output.verification.push(result);
|
|
943
1121
|
continue;
|
|
@@ -953,12 +1131,12 @@ async function runVerifyStage(ctx) {
|
|
|
953
1131
|
if (viewResult.exitCode !== 0 || !viewResult.stdout.trim()) {
|
|
954
1132
|
throw new Error(`${pkg.packageName}@${pkg.version} not yet available on npm`);
|
|
955
1133
|
}
|
|
956
|
-
(0,
|
|
1134
|
+
(0, import_core11.debug)(`Verified ${pkg.packageName}@${pkg.version} on npm`);
|
|
957
1135
|
}, config.verify.npm);
|
|
958
1136
|
result.verified = true;
|
|
959
|
-
(0,
|
|
1137
|
+
(0, import_core11.success)(`Verified ${pkg.packageName}@${pkg.version} on npm`);
|
|
960
1138
|
} catch {
|
|
961
|
-
(0,
|
|
1139
|
+
(0, import_core11.warn)(`Failed to verify ${pkg.packageName}@${pkg.version} on npm after ${result.attempts} attempts`);
|
|
962
1140
|
}
|
|
963
1141
|
ctx.output.verification.push(result);
|
|
964
1142
|
}
|
|
@@ -974,7 +1152,7 @@ async function runVerifyStage(ctx) {
|
|
|
974
1152
|
attempts: 0
|
|
975
1153
|
};
|
|
976
1154
|
if (cliOptions.dryRun) {
|
|
977
|
-
(0,
|
|
1155
|
+
(0, import_core11.info)(`[DRY RUN] Would verify ${crate.packageName}@${crate.version} on crates.io`);
|
|
978
1156
|
result.verified = true;
|
|
979
1157
|
ctx.output.verification.push(result);
|
|
980
1158
|
continue;
|
|
@@ -986,12 +1164,12 @@ async function runVerifyStage(ctx) {
|
|
|
986
1164
|
if (!response.ok) {
|
|
987
1165
|
throw new Error(`${crate.packageName}@${crate.version} not yet available on crates.io`);
|
|
988
1166
|
}
|
|
989
|
-
(0,
|
|
1167
|
+
(0, import_core11.debug)(`Verified ${crate.packageName}@${crate.version} on crates.io`);
|
|
990
1168
|
}, config.verify.cargo);
|
|
991
1169
|
result.verified = true;
|
|
992
|
-
(0,
|
|
1170
|
+
(0, import_core11.success)(`Verified ${crate.packageName}@${crate.version} on crates.io`);
|
|
993
1171
|
} catch {
|
|
994
|
-
(0,
|
|
1172
|
+
(0, import_core11.warn)(`Failed to verify ${crate.packageName}@${crate.version} on crates.io after ${result.attempts} attempts`);
|
|
995
1173
|
}
|
|
996
1174
|
ctx.output.verification.push(result);
|
|
997
1175
|
}
|
|
@@ -1026,6 +1204,8 @@ async function runPipeline(input, config, options) {
|
|
|
1026
1204
|
cliOptions: options,
|
|
1027
1205
|
packageManager: detectPackageManager(cwd),
|
|
1028
1206
|
cwd,
|
|
1207
|
+
releaseNotes: options.releaseNotes,
|
|
1208
|
+
additionalFiles: options.additionalFiles,
|
|
1029
1209
|
output: {
|
|
1030
1210
|
dryRun: options.dryRun,
|
|
1031
1211
|
git: { committed: false, tags: [], pushed: false },
|
|
@@ -1037,7 +1217,10 @@ async function runPipeline(input, config, options) {
|
|
|
1037
1217
|
};
|
|
1038
1218
|
try {
|
|
1039
1219
|
await runPrepareStage(ctx);
|
|
1040
|
-
if (!options.skipGit) {
|
|
1220
|
+
if (options.skipGitCommit && !options.skipGit) {
|
|
1221
|
+
ctx.output.git.committed = !!input.commitMessage;
|
|
1222
|
+
ctx.output.git.tags = [...input.tags];
|
|
1223
|
+
} else if (!options.skipGit) {
|
|
1041
1224
|
await runGitCommitStage(ctx);
|
|
1042
1225
|
}
|
|
1043
1226
|
if (!options.skipPublish) {
|
|
@@ -1066,8 +1249,8 @@ async function runPipeline(input, config, options) {
|
|
|
1066
1249
|
}
|
|
1067
1250
|
|
|
1068
1251
|
// src/stages/input.ts
|
|
1069
|
-
var
|
|
1070
|
-
var
|
|
1252
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
1253
|
+
var import_core12 = require("@releasekit/core");
|
|
1071
1254
|
var import_zod = require("zod");
|
|
1072
1255
|
var VersionChangelogEntrySchema = import_zod.z.object({
|
|
1073
1256
|
type: import_zod.z.string(),
|
|
@@ -1100,7 +1283,7 @@ async function parseInput(inputPath) {
|
|
|
1100
1283
|
let raw;
|
|
1101
1284
|
if (inputPath) {
|
|
1102
1285
|
try {
|
|
1103
|
-
raw =
|
|
1286
|
+
raw = fs8.readFileSync(inputPath, "utf-8");
|
|
1104
1287
|
} catch {
|
|
1105
1288
|
throw createPublishError("INPUT_PARSE_ERROR" /* INPUT_PARSE_ERROR */, `Could not read file: ${inputPath}`);
|
|
1106
1289
|
}
|
|
@@ -1120,7 +1303,7 @@ async function parseInput(inputPath) {
|
|
|
1120
1303
|
${issues}`);
|
|
1121
1304
|
}
|
|
1122
1305
|
if (result.data.updates.length === 0) {
|
|
1123
|
-
(0,
|
|
1306
|
+
(0, import_core12.info)("No package updates in version output \u2014 pipeline will be a no-op");
|
|
1124
1307
|
}
|
|
1125
1308
|
return result.data;
|
|
1126
1309
|
}
|
|
@@ -1135,8 +1318,8 @@ async function readStdin() {
|
|
|
1135
1318
|
// src/cli.ts
|
|
1136
1319
|
var program = new import_commander.Command();
|
|
1137
1320
|
program.name("releasekit-publish").description("Publish packages to registries with git tagging and GitHub releases").version("0.1.0").option("--input <path>", "Path to version output JSON (default: stdin)").option("--config <path>", "Path to releasekit config").option("--registry <type>", "Registry to publish to (npm, cargo, all)", "all").option("--npm-auth <method>", "NPM auth method (oidc, token, auto)", "auto").option("--dry-run", "Simulate all operations", false).option("--skip-git", "Skip git commit/tag/push", false).option("--skip-publish", "Skip registry publishing", false).option("--skip-github-release", "Skip GitHub Release creation", false).option("--skip-verification", "Skip post-publish verification", false).option("--json", "Output results as JSON", false).option("--verbose", "Verbose logging", false).action(async (options) => {
|
|
1138
|
-
if (options.verbose) (0,
|
|
1139
|
-
if (options.json) (0,
|
|
1321
|
+
if (options.verbose) (0, import_core13.setLogLevel)("debug");
|
|
1322
|
+
if (options.json) (0, import_core13.setJsonMode)(true);
|
|
1140
1323
|
try {
|
|
1141
1324
|
const config = loadConfig({ configPath: options.config });
|
|
1142
1325
|
const input = await parseInput(options.input);
|
|
@@ -1173,14 +1356,14 @@ program.name("releasekit-publish").description("Publish packages to registries w
|
|
|
1173
1356
|
2
|
|
1174
1357
|
)
|
|
1175
1358
|
);
|
|
1176
|
-
process.exit(
|
|
1359
|
+
process.exit(import_core13.EXIT_CODES.PUBLISH_ERROR);
|
|
1177
1360
|
}
|
|
1178
1361
|
if (BasePublishError.isPublishError(err)) {
|
|
1179
1362
|
err.logError();
|
|
1180
|
-
process.exit(
|
|
1363
|
+
process.exit(import_core13.EXIT_CODES.PUBLISH_ERROR);
|
|
1181
1364
|
}
|
|
1182
1365
|
console.error(err instanceof Error ? err.message : String(err));
|
|
1183
|
-
process.exit(
|
|
1366
|
+
process.exit(import_core13.EXIT_CODES.GENERAL_ERROR);
|
|
1184
1367
|
}
|
|
1185
1368
|
});
|
|
1186
1369
|
program.parse();
|