@releasekit/publish 0.2.0-next.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -75,7 +75,9 @@ function getDefaultConfig() {
75
75
  push: true,
76
76
  pushMethod: "auto",
77
77
  remote: "origin",
78
- branch: "main"
78
+ branch: "main",
79
+ httpsTokenEnv: void 0,
80
+ skipHooks: false
79
81
  },
80
82
  githubRelease: {
81
83
  enabled: true,
@@ -123,7 +125,9 @@ function toPublishConfig(config) {
123
125
  push: config.git.push ?? defaults.git.push,
124
126
  pushMethod: config.git.pushMethod ?? defaults.git.pushMethod,
125
127
  remote: config.git.remote ?? defaults.git.remote,
126
- branch: config.git.branch ?? defaults.git.branch
128
+ branch: config.git.branch ?? defaults.git.branch,
129
+ httpsTokenEnv: config.git.httpsTokenEnv ?? defaults.git.httpsTokenEnv,
130
+ skipHooks: config.git.skipHooks ?? defaults.git.skipHooks
127
131
  } : defaults.git,
128
132
  githubRelease: {
129
133
  enabled: config.githubRelease?.enabled ?? defaults.githubRelease.enabled,
@@ -305,8 +309,20 @@ var import_core3 = require("@releasekit/core");
305
309
  // src/utils/exec.ts
306
310
  var import_node_child_process = require("child_process");
307
311
  var import_core2 = require("@releasekit/core");
312
+ function redactArg(arg) {
313
+ try {
314
+ const url = new URL(arg);
315
+ if (url.username || url.password) {
316
+ url.username = url.username ? "***" : "";
317
+ url.password = url.password ? "***" : "";
318
+ return url.toString();
319
+ }
320
+ } catch {
321
+ }
322
+ return arg;
323
+ }
308
324
  async function execCommand(file, args, options = {}) {
309
- const displayCommand = options.label ?? [file, ...args].join(" ");
325
+ const displayCommand = options.label ?? [file, ...args.map(redactArg)].join(" ");
310
326
  if (options.dryRun) {
311
327
  (0, import_core2.info)(`[DRY RUN] Would execute: ${displayCommand}`);
312
328
  return { stdout: "", stderr: "", exitCode: 0 };
@@ -362,7 +378,7 @@ function detectNpmAuth() {
362
378
  if (process.env.ACTIONS_ID_TOKEN_REQUEST_URL) {
363
379
  return "oidc";
364
380
  }
365
- if (process.env.NPM_TOKEN) {
381
+ if (process.env.NPM_TOKEN || process.env.NODE_AUTH_TOKEN) {
366
382
  return "token";
367
383
  }
368
384
  return null;
@@ -571,8 +587,9 @@ function topologicalSort(crates) {
571
587
  var path2 = __toESM(require("path"), 1);
572
588
  var import_core4 = require("@releasekit/core");
573
589
  async function runGitCommitStage(ctx) {
574
- const { input, cliOptions, cwd } = ctx;
590
+ const { input, config, cliOptions, cwd } = ctx;
575
591
  const dryRun = cliOptions.dryRun;
592
+ const skipHooks = config.git.skipHooks ?? false;
576
593
  if (!input.commitMessage) {
577
594
  (0, import_core4.info)("No commit message provided, skipping git commit");
578
595
  return;
@@ -594,8 +611,13 @@ async function runGitCommitStage(ctx) {
594
611
  `git add failed: ${error instanceof Error ? error.message : String(error)}`
595
612
  );
596
613
  }
614
+ const commitArgs = ["commit"];
615
+ if (skipHooks) {
616
+ commitArgs.push("--no-verify");
617
+ }
618
+ commitArgs.push("-m", input.commitMessage);
597
619
  try {
598
- await execCommand("git", ["commit", "-m", input.commitMessage], {
620
+ await execCommand("git", commitArgs, {
599
621
  cwd,
600
622
  dryRun,
601
623
  label: `git commit -m "${input.commitMessage}"`
@@ -633,6 +655,18 @@ async function runGitCommitStage(ctx) {
633
655
 
634
656
  // src/stages/git-push.ts
635
657
  var import_core5 = require("@releasekit/core");
658
+ function toGithubAuthedUrl(remoteUrl, token) {
659
+ try {
660
+ const url = new URL(remoteUrl);
661
+ if (url.protocol !== "https:") return void 0;
662
+ if (url.host !== "github.com") return void 0;
663
+ url.username = "x-access-token";
664
+ url.password = token;
665
+ return url.toString();
666
+ } catch {
667
+ return void 0;
668
+ }
669
+ }
636
670
  async function runGitPushStage(ctx) {
637
671
  const { config, cliOptions, cwd, output } = ctx;
638
672
  const dryRun = cliOptions.dryRun;
@@ -653,16 +687,26 @@ async function runGitPushStage(ctx) {
653
687
  pushMethod = "https";
654
688
  }
655
689
  }
690
+ const httpsTokenEnv = config.git.httpsTokenEnv;
691
+ const httpsToken = httpsTokenEnv ? process.env[httpsTokenEnv] : void 0;
656
692
  try {
693
+ let pushRemote = remote;
694
+ if (pushMethod === "https" && httpsToken) {
695
+ const remoteUrlResult = await execCommand("git", ["remote", "get-url", remote], { cwd, dryRun: false });
696
+ const authed = toGithubAuthedUrl(remoteUrlResult.stdout.trim(), httpsToken);
697
+ if (authed) {
698
+ pushRemote = authed;
699
+ }
700
+ }
657
701
  if (output.git.committed) {
658
- await execCommand("git", ["push", remote, branch], {
702
+ await execCommand("git", ["push", pushRemote, branch], {
659
703
  cwd,
660
704
  dryRun,
661
705
  label: `git push ${remote} ${branch}`
662
706
  });
663
707
  }
664
708
  if (output.git.tags.length > 0) {
665
- await execCommand("git", ["push", remote, "--tags"], {
709
+ await execCommand("git", ["push", pushRemote, "--tags"], {
666
710
  cwd,
667
711
  dryRun,
668
712
  label: `git push ${remote} --tags`
@@ -723,7 +767,9 @@ async function runGithubReleaseStage(ctx) {
723
767
  if (!firstTag) return;
724
768
  const tagsToRelease = config.githubRelease.perPackage ? tags : [firstTag];
725
769
  for (const tag of tagsToRelease) {
726
- const versionMatch = tag.match(/(\d+\.\d+\.\d+.*)$/);
770
+ const MAX_TAG_LENGTH = 1e3;
771
+ const truncatedTag = tag.length > MAX_TAG_LENGTH ? tag.slice(0, MAX_TAG_LENGTH) : tag;
772
+ const versionMatch = truncatedTag.match(/(\d{1,20}\.\d{1,20}\.\d{1,20}(?:[-+.]?[a-zA-Z0-9.-]{0,100})?)$/);
727
773
  const version = versionMatch?.[1] ?? "";
728
774
  const isPreRel = config.githubRelease.prerelease === "auto" ? version ? isPrerelease(version) : false : config.githubRelease.prerelease;
729
775
  const result = {
@@ -765,16 +811,82 @@ async function runGithubReleaseStage(ctx) {
765
811
  }
766
812
 
767
813
  // src/stages/npm-publish.ts
768
- var fs5 = __toESM(require("fs"), 1);
769
- var path4 = __toESM(require("path"), 1);
770
- var import_core7 = require("@releasekit/core");
814
+ var fs6 = __toESM(require("fs"), 1);
815
+ var path5 = __toESM(require("path"), 1);
816
+ var import_core8 = require("@releasekit/core");
771
817
 
772
- // src/utils/package-manager.ts
818
+ // src/utils/npm-env.ts
773
819
  var fs4 = __toESM(require("fs"), 1);
820
+ var os = __toESM(require("os"), 1);
774
821
  var path3 = __toESM(require("path"), 1);
822
+ var import_core7 = require("@releasekit/core");
823
+ function writeTempNpmrc(contents) {
824
+ const dir = fs4.mkdtempSync(path3.join(os.tmpdir(), "releasekit-npmrc-"));
825
+ const npmrcPath = path3.join(dir, ".npmrc");
826
+ fs4.writeFileSync(npmrcPath, contents, "utf-8");
827
+ return {
828
+ npmrcPath,
829
+ cleanup: () => {
830
+ try {
831
+ fs4.rmSync(dir, { recursive: true, force: true });
832
+ } catch {
833
+ }
834
+ }
835
+ };
836
+ }
837
+ function createNpmSubprocessIsolation(options) {
838
+ const { authMethod, registryUrl } = options;
839
+ const baseEnv = {};
840
+ if (!authMethod) return { env: baseEnv, cleanup: () => {
841
+ } };
842
+ const token = process.env.NPM_TOKEN ?? process.env.NODE_AUTH_TOKEN;
843
+ const registryHost = (() => {
844
+ try {
845
+ return new URL(registryUrl).host;
846
+ } catch {
847
+ return "registry.npmjs.org";
848
+ }
849
+ })();
850
+ const lines = [`registry=${registryUrl}`];
851
+ if (authMethod === "oidc") {
852
+ lines.push("always-auth=false");
853
+ }
854
+ if (authMethod === "token" && token) {
855
+ lines.push(`//${registryHost}/:_authToken=${token}`);
856
+ }
857
+ lines.push("");
858
+ const { npmrcPath, cleanup } = writeTempNpmrc(lines.join("\n"));
859
+ (0, import_core7.debug)(`Using isolated npm userconfig: ${npmrcPath}`);
860
+ const isOidc = authMethod === "oidc";
861
+ return {
862
+ env: {
863
+ ...baseEnv,
864
+ // Ensure npm and tools that read npm_config_* pick up our temp file
865
+ NPM_CONFIG_USERCONFIG: npmrcPath,
866
+ npm_config_userconfig: npmrcPath,
867
+ // Auth-specific hardening
868
+ ...isOidc ? {
869
+ // Prevent setup-node's always-auth from forcing token lookups
870
+ NPM_CONFIG_ALWAYS_AUTH: "false",
871
+ npm_config_always_auth: "false",
872
+ // Explicitly prevent token-based publishing from being selected implicitly
873
+ NODE_AUTH_TOKEN: void 0,
874
+ NPM_TOKEN: void 0
875
+ } : {
876
+ // Ensure CLIs that expect NODE_AUTH_TOKEN can still work
877
+ NODE_AUTH_TOKEN: token
878
+ }
879
+ },
880
+ cleanup
881
+ };
882
+ }
883
+
884
+ // src/utils/package-manager.ts
885
+ var fs5 = __toESM(require("fs"), 1);
886
+ var path4 = __toESM(require("path"), 1);
775
887
  function detectPackageManager(cwd) {
776
- if (fs4.existsSync(path3.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
777
- if (fs4.existsSync(path3.join(cwd, "yarn.lock"))) return "yarn";
888
+ if (fs5.existsSync(path4.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
889
+ if (fs5.existsSync(path4.join(cwd, "yarn.lock"))) return "yarn";
778
890
  return "npm";
779
891
  }
780
892
  function buildPublishCommand(pm, packageName, _packageDir, options) {
@@ -803,7 +915,7 @@ async function runNpmPublishStage(ctx) {
803
915
  const { input, config, cliOptions, cwd } = ctx;
804
916
  const dryRun = cliOptions.dryRun;
805
917
  if (!config.npm.enabled) {
806
- (0, import_core7.info)("NPM publishing disabled in config");
918
+ (0, import_core8.info)("NPM publishing disabled in config");
807
919
  return;
808
920
  }
809
921
  const authMethod = config.npm.auth === "auto" ? detectNpmAuth() : config.npm.auth;
@@ -811,107 +923,117 @@ async function runNpmPublishStage(ctx) {
811
923
  throw createPublishError("NPM_AUTH_ERROR" /* NPM_AUTH_ERROR */, "No NPM authentication method detected");
812
924
  }
813
925
  const useProvenance = config.npm.provenance && authMethod === "oidc";
814
- for (const update of input.updates) {
815
- const result = {
816
- packageName: update.packageName,
817
- version: update.newVersion,
818
- registry: "npm",
819
- success: false,
820
- skipped: false
821
- };
822
- const pkgJsonPath = path4.resolve(cwd, update.filePath);
823
- try {
824
- const pkgContent = fs5.readFileSync(pkgJsonPath, "utf-8");
825
- const pkgJson = JSON.parse(pkgContent);
826
- if (pkgJson.private) {
827
- result.skipped = true;
828
- result.success = true;
829
- result.reason = "Package is private";
830
- ctx.output.npm.push(result);
831
- (0, import_core7.debug)(`Skipping private package: ${update.packageName}`);
832
- continue;
926
+ const npmIsolation = createNpmSubprocessIsolation({
927
+ authMethod,
928
+ registryUrl: config.npm.registry
929
+ });
930
+ try {
931
+ for (const update of input.updates) {
932
+ const result = {
933
+ packageName: update.packageName,
934
+ version: update.newVersion,
935
+ registry: "npm",
936
+ success: false,
937
+ skipped: false
938
+ };
939
+ const pkgJsonPath = path5.resolve(cwd, update.filePath);
940
+ try {
941
+ const pkgContent = fs6.readFileSync(pkgJsonPath, "utf-8");
942
+ const pkgJson = JSON.parse(pkgContent);
943
+ if (pkgJson.private) {
944
+ result.skipped = true;
945
+ result.success = true;
946
+ result.reason = "Package is private";
947
+ ctx.output.npm.push(result);
948
+ (0, import_core8.debug)(`Skipping private package: ${update.packageName}`);
949
+ continue;
950
+ }
951
+ } catch {
952
+ if (update.filePath.endsWith("Cargo.toml")) {
953
+ result.skipped = true;
954
+ result.success = true;
955
+ result.reason = "Not an npm package";
956
+ ctx.output.npm.push(result);
957
+ continue;
958
+ }
833
959
  }
834
- } catch {
835
- if (update.filePath.endsWith("Cargo.toml")) {
960
+ const { file: viewFile, args: viewArgs } = buildViewCommand(
961
+ ctx.packageManager,
962
+ update.packageName,
963
+ update.newVersion
964
+ );
965
+ const viewResult = await execCommandSafe(viewFile, viewArgs, {
966
+ cwd,
967
+ dryRun: false,
968
+ // Always check, even in dry-run
969
+ env: npmIsolation.env
970
+ });
971
+ if (viewResult.exitCode === 0 && viewResult.stdout.trim()) {
972
+ result.alreadyPublished = true;
836
973
  result.skipped = true;
837
974
  result.success = true;
838
- result.reason = "Not an npm package";
975
+ result.reason = "Already published";
839
976
  ctx.output.npm.push(result);
977
+ (0, import_core8.warn)(`${update.packageName}@${update.newVersion} is already published, skipping`);
840
978
  continue;
841
979
  }
842
- }
843
- const { file: viewFile, args: viewArgs } = buildViewCommand(
844
- ctx.packageManager,
845
- update.packageName,
846
- update.newVersion
847
- );
848
- const viewResult = await execCommandSafe(viewFile, viewArgs, {
849
- cwd,
850
- dryRun: false
851
- // Always check, even in dry-run
852
- });
853
- if (viewResult.exitCode === 0 && viewResult.stdout.trim()) {
854
- result.alreadyPublished = true;
855
- result.skipped = true;
856
- result.success = true;
857
- result.reason = "Already published";
858
- ctx.output.npm.push(result);
859
- (0, import_core7.warn)(`${update.packageName}@${update.newVersion} is already published, skipping`);
860
- continue;
861
- }
862
- const distTag = getDistTag(update.newVersion, config.npm.tag);
863
- const pkgDir = path4.dirname(path4.resolve(cwd, update.filePath));
864
- const { file: pubFile, args: pubArgs } = buildPublishCommand(ctx.packageManager, update.packageName, pkgDir, {
865
- access: config.npm.access,
866
- tag: distTag,
867
- provenance: useProvenance,
868
- noGitChecks: true
869
- });
870
- try {
871
- await execCommand(pubFile, pubArgs, {
872
- cwd,
873
- dryRun,
874
- label: `npm publish ${update.packageName}@${update.newVersion}`
980
+ const distTag = getDistTag(update.newVersion, config.npm.tag);
981
+ const pkgDir = path5.dirname(path5.resolve(cwd, update.filePath));
982
+ const { file: pubFile, args: pubArgs } = buildPublishCommand(ctx.packageManager, update.packageName, pkgDir, {
983
+ access: config.npm.access,
984
+ tag: distTag,
985
+ provenance: useProvenance,
986
+ noGitChecks: true
875
987
  });
876
- result.success = true;
877
- if (!dryRun) {
878
- (0, import_core7.success)(`Published ${update.packageName}@${update.newVersion} to npm`);
988
+ try {
989
+ await execCommand(pubFile, pubArgs, {
990
+ cwd,
991
+ dryRun,
992
+ label: `npm publish ${update.packageName}@${update.newVersion}`,
993
+ env: npmIsolation.env
994
+ });
995
+ result.success = true;
996
+ if (!dryRun) {
997
+ (0, import_core8.success)(`Published ${update.packageName}@${update.newVersion} to npm`);
998
+ }
999
+ } catch (error) {
1000
+ result.reason = error instanceof Error ? error.message : String(error);
1001
+ (0, import_core8.warn)(`Failed to publish ${update.packageName}: ${result.reason}`);
879
1002
  }
880
- } catch (error) {
881
- result.reason = error instanceof Error ? error.message : String(error);
882
- (0, import_core7.warn)(`Failed to publish ${update.packageName}: ${result.reason}`);
1003
+ ctx.output.npm.push(result);
883
1004
  }
884
- ctx.output.npm.push(result);
1005
+ } finally {
1006
+ npmIsolation.cleanup();
885
1007
  }
886
1008
  }
887
1009
 
888
1010
  // src/stages/prepare.ts
889
- var fs6 = __toESM(require("fs"), 1);
890
- var path5 = __toESM(require("path"), 1);
891
- var import_core8 = require("@releasekit/core");
1011
+ var fs7 = __toESM(require("fs"), 1);
1012
+ var path6 = __toESM(require("path"), 1);
1013
+ var import_core9 = require("@releasekit/core");
892
1014
  async function runPrepareStage(ctx) {
893
1015
  const { input, config, cliOptions, cwd } = ctx;
894
1016
  if (config.npm.enabled && config.npm.copyFiles.length > 0) {
895
1017
  for (const update of input.updates) {
896
- const pkgDir = path5.dirname(path5.resolve(cwd, update.filePath));
1018
+ const pkgDir = path6.dirname(path6.resolve(cwd, update.filePath));
897
1019
  for (const file of config.npm.copyFiles) {
898
- const src = path5.resolve(cwd, file);
899
- const dest = path5.join(pkgDir, file);
900
- if (!fs6.existsSync(src)) {
901
- (0, import_core8.debug)(`Source file not found, skipping copy: ${src}`);
1020
+ const src = path6.resolve(cwd, file);
1021
+ const dest = path6.join(pkgDir, file);
1022
+ if (!fs7.existsSync(src)) {
1023
+ (0, import_core9.debug)(`Source file not found, skipping copy: ${src}`);
902
1024
  continue;
903
1025
  }
904
- if (path5.resolve(path5.dirname(src)) === path5.resolve(pkgDir)) {
905
- (0, import_core8.debug)(`Skipping copy of ${file} - same directory as source`);
1026
+ if (path6.resolve(path6.dirname(src)) === path6.resolve(pkgDir)) {
1027
+ (0, import_core9.debug)(`Skipping copy of ${file} - same directory as source`);
906
1028
  continue;
907
1029
  }
908
1030
  if (cliOptions.dryRun) {
909
- (0, import_core8.info)(`[DRY RUN] Would copy ${src} \u2192 ${dest}`);
1031
+ (0, import_core9.info)(`[DRY RUN] Would copy ${src} \u2192 ${dest}`);
910
1032
  continue;
911
1033
  }
912
1034
  try {
913
- fs6.copyFileSync(src, dest);
914
- (0, import_core8.debug)(`Copied ${file} \u2192 ${pkgDir}`);
1035
+ fs7.copyFileSync(src, dest);
1036
+ (0, import_core9.debug)(`Copied ${file} \u2192 ${pkgDir}`);
915
1037
  } catch (error) {
916
1038
  throw createPublishError(
917
1039
  "FILE_COPY_ERROR" /* FILE_COPY_ERROR */,
@@ -923,26 +1045,26 @@ async function runPrepareStage(ctx) {
923
1045
  }
924
1046
  if (config.cargo.enabled) {
925
1047
  for (const update of input.updates) {
926
- const pkgDir = path5.dirname(path5.resolve(cwd, update.filePath));
927
- const cargoPath = path5.join(pkgDir, "Cargo.toml");
928
- if (!fs6.existsSync(cargoPath)) {
1048
+ const pkgDir = path6.dirname(path6.resolve(cwd, update.filePath));
1049
+ const cargoPath = path6.join(pkgDir, "Cargo.toml");
1050
+ if (!fs7.existsSync(cargoPath)) {
929
1051
  continue;
930
1052
  }
931
1053
  if (cliOptions.dryRun) {
932
- (0, import_core8.info)(`[DRY RUN] Would update ${cargoPath} to version ${update.newVersion}`);
1054
+ (0, import_core9.info)(`[DRY RUN] Would update ${cargoPath} to version ${update.newVersion}`);
933
1055
  continue;
934
1056
  }
935
1057
  updateCargoVersion(cargoPath, update.newVersion);
936
- (0, import_core8.debug)(`Updated ${cargoPath} to version ${update.newVersion}`);
1058
+ (0, import_core9.debug)(`Updated ${cargoPath} to version ${update.newVersion}`);
937
1059
  }
938
1060
  }
939
1061
  }
940
1062
 
941
1063
  // src/stages/verify.ts
942
- var import_core10 = require("@releasekit/core");
1064
+ var import_core11 = require("@releasekit/core");
943
1065
 
944
1066
  // src/utils/retry.ts
945
- var import_core9 = require("@releasekit/core");
1067
+ var import_core10 = require("@releasekit/core");
946
1068
  async function withRetry(fn, options, shouldRetry) {
947
1069
  let lastError;
948
1070
  let delay = options.initialDelay;
@@ -955,7 +1077,7 @@ async function withRetry(fn, options, shouldRetry) {
955
1077
  throw error;
956
1078
  }
957
1079
  if (attempt < options.maxAttempts) {
958
- (0, import_core9.debug)(`Attempt ${attempt}/${options.maxAttempts} failed, retrying in ${delay}ms...`);
1080
+ (0, import_core10.debug)(`Attempt ${attempt}/${options.maxAttempts} failed, retrying in ${delay}ms...`);
959
1081
  await sleep(delay);
960
1082
  delay = Math.floor(delay * options.backoffMultiplier);
961
1083
  }
@@ -981,7 +1103,7 @@ async function runVerifyStage(ctx) {
981
1103
  attempts: 0
982
1104
  };
983
1105
  if (cliOptions.dryRun) {
984
- (0, import_core10.info)(`[DRY RUN] Would verify ${pkg.packageName}@${pkg.version} on npm`);
1106
+ (0, import_core11.info)(`[DRY RUN] Would verify ${pkg.packageName}@${pkg.version} on npm`);
985
1107
  result.verified = true;
986
1108
  ctx.output.verification.push(result);
987
1109
  continue;
@@ -997,12 +1119,12 @@ async function runVerifyStage(ctx) {
997
1119
  if (viewResult.exitCode !== 0 || !viewResult.stdout.trim()) {
998
1120
  throw new Error(`${pkg.packageName}@${pkg.version} not yet available on npm`);
999
1121
  }
1000
- (0, import_core10.debug)(`Verified ${pkg.packageName}@${pkg.version} on npm`);
1122
+ (0, import_core11.debug)(`Verified ${pkg.packageName}@${pkg.version} on npm`);
1001
1123
  }, config.verify.npm);
1002
1124
  result.verified = true;
1003
- (0, import_core10.success)(`Verified ${pkg.packageName}@${pkg.version} on npm`);
1125
+ (0, import_core11.success)(`Verified ${pkg.packageName}@${pkg.version} on npm`);
1004
1126
  } catch {
1005
- (0, import_core10.warn)(`Failed to verify ${pkg.packageName}@${pkg.version} on npm after ${result.attempts} attempts`);
1127
+ (0, import_core11.warn)(`Failed to verify ${pkg.packageName}@${pkg.version} on npm after ${result.attempts} attempts`);
1006
1128
  }
1007
1129
  ctx.output.verification.push(result);
1008
1130
  }
@@ -1018,7 +1140,7 @@ async function runVerifyStage(ctx) {
1018
1140
  attempts: 0
1019
1141
  };
1020
1142
  if (cliOptions.dryRun) {
1021
- (0, import_core10.info)(`[DRY RUN] Would verify ${crate.packageName}@${crate.version} on crates.io`);
1143
+ (0, import_core11.info)(`[DRY RUN] Would verify ${crate.packageName}@${crate.version} on crates.io`);
1022
1144
  result.verified = true;
1023
1145
  ctx.output.verification.push(result);
1024
1146
  continue;
@@ -1030,12 +1152,12 @@ async function runVerifyStage(ctx) {
1030
1152
  if (!response.ok) {
1031
1153
  throw new Error(`${crate.packageName}@${crate.version} not yet available on crates.io`);
1032
1154
  }
1033
- (0, import_core10.debug)(`Verified ${crate.packageName}@${crate.version} on crates.io`);
1155
+ (0, import_core11.debug)(`Verified ${crate.packageName}@${crate.version} on crates.io`);
1034
1156
  }, config.verify.cargo);
1035
1157
  result.verified = true;
1036
- (0, import_core10.success)(`Verified ${crate.packageName}@${crate.version} on crates.io`);
1158
+ (0, import_core11.success)(`Verified ${crate.packageName}@${crate.version} on crates.io`);
1037
1159
  } catch {
1038
- (0, import_core10.warn)(`Failed to verify ${crate.packageName}@${crate.version} on crates.io after ${result.attempts} attempts`);
1160
+ (0, import_core11.warn)(`Failed to verify ${crate.packageName}@${crate.version} on crates.io after ${result.attempts} attempts`);
1039
1161
  }
1040
1162
  ctx.output.verification.push(result);
1041
1163
  }
@@ -1081,7 +1203,10 @@ async function runPipeline(input, config, options) {
1081
1203
  };
1082
1204
  try {
1083
1205
  await runPrepareStage(ctx);
1084
- if (!options.skipGit) {
1206
+ if (options.skipGitCommit && !options.skipGit) {
1207
+ ctx.output.git.committed = !!input.commitMessage;
1208
+ ctx.output.git.tags = [...input.tags];
1209
+ } else if (!options.skipGit) {
1085
1210
  await runGitCommitStage(ctx);
1086
1211
  }
1087
1212
  if (!options.skipPublish) {
@@ -1110,8 +1235,8 @@ async function runPipeline(input, config, options) {
1110
1235
  }
1111
1236
 
1112
1237
  // src/stages/input.ts
1113
- var fs7 = __toESM(require("fs"), 1);
1114
- var import_core11 = require("@releasekit/core");
1238
+ var fs8 = __toESM(require("fs"), 1);
1239
+ var import_core12 = require("@releasekit/core");
1115
1240
  var import_zod = require("zod");
1116
1241
  var VersionChangelogEntrySchema = import_zod.z.object({
1117
1242
  type: import_zod.z.string(),
@@ -1144,7 +1269,7 @@ async function parseInput(inputPath) {
1144
1269
  let raw;
1145
1270
  if (inputPath) {
1146
1271
  try {
1147
- raw = fs7.readFileSync(inputPath, "utf-8");
1272
+ raw = fs8.readFileSync(inputPath, "utf-8");
1148
1273
  } catch {
1149
1274
  throw createPublishError("INPUT_PARSE_ERROR" /* INPUT_PARSE_ERROR */, `Could not read file: ${inputPath}`);
1150
1275
  }
@@ -1164,7 +1289,7 @@ async function parseInput(inputPath) {
1164
1289
  ${issues}`);
1165
1290
  }
1166
1291
  if (result.data.updates.length === 0) {
1167
- (0, import_core11.info)("No package updates in version output \u2014 pipeline will be a no-op");
1292
+ (0, import_core12.info)("No package updates in version output \u2014 pipeline will be a no-op");
1168
1293
  }
1169
1294
  return result.data;
1170
1295
  }
package/dist/index.d.cts CHANGED
@@ -25,6 +25,8 @@ interface GitConfig {
25
25
  pushMethod: 'auto' | 'ssh' | 'https';
26
26
  remote: string;
27
27
  branch: string;
28
+ httpsTokenEnv?: string;
29
+ skipHooks?: boolean;
28
30
  }
29
31
  interface GitHubReleaseConfig {
30
32
  enabled: boolean;
@@ -58,6 +60,7 @@ interface PublishCliOptions {
58
60
  npmAuth: 'auto' | 'oidc' | 'token';
59
61
  dryRun: boolean;
60
62
  skipGit: boolean;
63
+ skipGitCommit?: boolean;
61
64
  skipPublish: boolean;
62
65
  skipGithubRelease: boolean;
63
66
  skipVerification: boolean;
package/dist/index.d.ts CHANGED
@@ -25,6 +25,8 @@ interface GitConfig {
25
25
  pushMethod: 'auto' | 'ssh' | 'https';
26
26
  remote: string;
27
27
  branch: string;
28
+ httpsTokenEnv?: string;
29
+ skipHooks?: boolean;
28
30
  }
29
31
  interface GitHubReleaseConfig {
30
32
  enabled: boolean;
@@ -58,6 +60,7 @@ interface PublishCliOptions {
58
60
  npmAuth: 'auto' | 'oidc' | 'token';
59
61
  dryRun: boolean;
60
62
  skipGit: boolean;
63
+ skipGitCommit?: boolean;
61
64
  skipPublish: boolean;
62
65
  skipGithubRelease: boolean;
63
66
  skipVerification: boolean;
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  parseInput,
17
17
  runPipeline,
18
18
  updateCargoVersion
19
- } from "./chunk-Y7Y6GQ6R.js";
19
+ } from "./chunk-H7AKSLZP.js";
20
20
  export {
21
21
  BasePublishError,
22
22
  PipelineError,