@bensandee/tooling 0.62.0 → 0.62.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/bin.mjs +54 -39
  2. package/package.json +3 -3
package/dist/bin.mjs CHANGED
@@ -844,30 +844,27 @@ function parseGitUrl(urlStr) {
844
844
  }
845
845
  }
846
846
  /**
847
- * Configure the git remote origin to push as `token` regardless of what
848
- * `actions/checkout` left behind.
847
+ * Build per-invocation git auth for release pushes.
849
848
  *
850
- * `actions/checkout@v6` injects an HTTP Authorization header into git config
851
- * under `http.<serverUrl>/.extraheader`. That header overrides Basic auth
852
- * embedded in the remote URL, so a `git remote set-url` alone is not enough —
853
- * the runner's pseudo-user token still wins and the push authenticates as
854
- * uid=-2 on Forgejo (and as the runner identity on GitHub Enterprise with
855
- * custom pre-receive hooks). Unset the extraheader before rewriting the URL.
849
+ * Pure: no executor side effects, no `.git/config` mutation. Caller threads
850
+ * `auth.args` + `auth.url` through every `git push` / `git ls-remote` that
851
+ * needs to authenticate as the RELEASE_TOKEN owner.
852
+ *
853
+ * Background: `actions/checkout@v6` mounts its Authorization header through
854
+ * `includeIf.gitdir:<workspace>/.git.path → /tmp/git-credentials-*.config`
855
+ * (the file holds `http.<server>/.extraheader = Authorization: Basic <runner
856
+ * pseudo-user>`). That header overrides URL-embedded auth in the request,
857
+ * which is why pushes from CI authenticated as `uid: -2` and tripped the
858
+ * Forgejo pre-receive hook. Setting `extraheader=` to empty at the
859
+ * command-line layer wins over the include, so the only Authorization git
860
+ * sends is the one from `auth.url`.
856
861
  */
857
- function configureGitAuth(executor, coords, cwd) {
862
+ function buildGitAuth(coords) {
858
863
  const host = coords.serverUrl.replace(/^https?:\/\//, "");
859
- executor.exec("git", [
860
- "config",
861
- "--unset-all",
862
- `http.${coords.serverUrl}/.extraheader`
863
- ], { cwd });
864
- const authUrl = `https://x-access-token:${coords.token}@${host}/${coords.repository}`;
865
- executor.exec("git", [
866
- "remote",
867
- "set-url",
868
- "origin",
869
- authUrl
870
- ], { cwd });
864
+ return {
865
+ args: ["-c", `http.${coords.serverUrl}/.extraheader=`],
866
+ url: `https://x-access-token:${coords.token}@${host}/${coords.repository}`
867
+ };
871
868
  }
872
869
  /** Resolve the CI bot actor name for the given platform. */
873
870
  function ciActorName(platform) {
@@ -2225,7 +2222,7 @@ async function generatePackageJson(ctx) {
2225
2222
  const devDeps = { ...ROOT_DEV_DEPS };
2226
2223
  if (!isMonorepo) Object.assign(devDeps, PER_PACKAGE_DEV_DEPS);
2227
2224
  devDeps["@bensandee/config"] = isWorkspacePackage(ctx, "@bensandee/config") ? "workspace:*" : "0.11.3";
2228
- devDeps["@bensandee/tooling"] = isWorkspacePackage(ctx, "@bensandee/tooling") ? "workspace:*" : "0.62.0";
2225
+ devDeps["@bensandee/tooling"] = isWorkspacePackage(ctx, "@bensandee/tooling") ? "workspace:*" : "0.62.1";
2229
2226
  if (ctx.config.useEslintPlugin) devDeps["@bensandee/eslint-plugin"] = isWorkspacePackage(ctx, "@bensandee/eslint-plugin") ? "workspace:*" : "0.13.0";
2230
2227
  if (ctx.config.formatter === "oxfmt") devDeps["oxfmt"] = {
2231
2228
  "@changesets/cli": "2.31.0",
@@ -5425,7 +5422,7 @@ async function runGenerators(ctx) {
5425
5422
  function generateMigratePrompt(results, config, detected) {
5426
5423
  const sections = [];
5427
5424
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
5428
- sections.push(`# Migration Prompt\n\n_Generated by \`@bensandee/tooling@0.62.0 repo:sync\` on ${timestamp}_\n`);
5425
+ sections.push(`# Migration Prompt\n\n_Generated by \`@bensandee/tooling@0.62.1 repo:sync\` on ${timestamp}_\n`);
5429
5426
  const changed = results.filter((r) => r.action === "created" || r.action === "updated" || r.action === "archived");
5430
5427
  if (changed.length > 0) {
5431
5428
  const items = changed.map((r) => {
@@ -6090,9 +6087,11 @@ async function runVersionMode(executor, config) {
6090
6087
  };
6091
6088
  }
6092
6089
  debug(config, `Force-pushing version commit to ${BRANCH}`);
6090
+ const auth = buildGitAuth(config);
6093
6091
  const pushResult = executor.exec("git", [
6092
+ ...auth.args,
6094
6093
  "push",
6095
- "origin",
6094
+ auth.url,
6096
6095
  `HEAD:refs/heads/${BRANCH}`,
6097
6096
  "--force"
6098
6097
  ], { cwd: config.cwd });
@@ -6153,10 +6152,12 @@ async function runPublishMode(executor, config) {
6153
6152
  debug(config, `Tags from publish stdout: ${stdoutTags.length > 0 ? stdoutTags.join(", ") : "(none)"}`);
6154
6153
  const expectedTags = computeExpectedTags(executor.listWorkspacePackages(config.cwd));
6155
6154
  debug(config, `Expected tags from workspace packages: ${expectedTags.length > 0 ? expectedTags.join(", ") : "(none)"}`);
6155
+ const auth = buildGitAuth(config);
6156
6156
  const remoteTags = parseRemoteTags(executor.exec("git", [
6157
+ ...auth.args,
6157
6158
  "ls-remote",
6158
6159
  "--tags",
6159
- "origin"
6160
+ auth.url
6160
6161
  ], { cwd: config.cwd }).stdout);
6161
6162
  debug(config, `Remote tags: ${remoteTags.length > 0 ? remoteTags.join(", ") : "(none)"}`);
6162
6163
  const remoteSet = new Set(remoteTags);
@@ -6205,8 +6206,9 @@ async function runPublishMode(executor, config) {
6205
6206
  if (tagResult.exitCode !== 0) throw new FatalError(`Failed to create tag ${tag}: ${tagResult.stderr || tagResult.stdout}`);
6206
6207
  }
6207
6208
  const pushTagResult = executor.exec("git", [
6209
+ ...auth.args,
6208
6210
  "push",
6209
- "origin",
6211
+ auth.url,
6210
6212
  `refs/tags/${tag}`
6211
6213
  ], { cwd: config.cwd });
6212
6214
  if (pushTagResult.exitCode !== 0) throw new FatalError(`Failed to push tag ${tag}: ${pushTagResult.stderr || pushTagResult.stdout}`);
@@ -6316,8 +6318,6 @@ async function runRelease(config, executor) {
6316
6318
  }
6317
6319
  const identity = await configureGitIdentity(executor, "forgejo", config.cwd, config);
6318
6320
  log.info(`Git identity: ${identity.name} <${identity.email}>`);
6319
- configureGitAuth(executor, config, config.cwd);
6320
- debug(config, `Configured git remote auth for ${config.repository}`);
6321
6321
  const changesetFiles = executor.listChangesetFiles(config.cwd);
6322
6322
  debug(config, `Changeset files found: ${changesetFiles.length > 0 ? changesetFiles.join(", ") : "(none)"}`);
6323
6323
  if (changesetFiles.length > 0) {
@@ -6716,24 +6716,32 @@ async function runSimpleRelease(executor, config) {
6716
6716
  };
6717
6717
  }
6718
6718
  let pushed = false;
6719
+ const authCoords = resolveAuthCoordinates(executor, config, releaseToken);
6720
+ let auth;
6721
+ if (authCoords) {
6722
+ auth = buildGitAuth(authCoords);
6723
+ debug(config, `Built git auth for ${authCoords.repository}`);
6724
+ } else debug(config, "Skipping git auth: could not resolve server URL / repository");
6719
6725
  if (!config.noPush) {
6720
- const authCoords = resolveAuthCoordinates(executor, config, releaseToken);
6721
- if (authCoords) {
6722
- configureGitAuth(executor, authCoords, config.cwd);
6723
- debug(config, `Configured git remote auth for ${authCoords.repository}`);
6724
- } else debug(config, "Skipping git remote auth: could not resolve server URL / repository");
6725
6726
  const branch = executor.exec("git", [
6726
6727
  "rev-parse",
6727
6728
  "--abbrev-ref",
6728
6729
  "HEAD"
6729
6730
  ], { cwd: config.cwd }).stdout.trim() || "main";
6730
6731
  debug(config, `Pushing ${tag} to origin/${branch} with --follow-tags`);
6731
- const pushResult = executor.exec("git", [
6732
+ const pushArgs = auth ? [
6733
+ ...auth.args,
6734
+ "push",
6735
+ "--follow-tags",
6736
+ auth.url,
6737
+ branch
6738
+ ] : [
6732
6739
  "push",
6733
6740
  "--follow-tags",
6734
6741
  "origin",
6735
6742
  branch
6736
- ], { cwd: config.cwd });
6743
+ ];
6744
+ const pushResult = executor.exec("git", pushArgs, { cwd: config.cwd });
6737
6745
  debugExec(config, "git push", pushResult);
6738
6746
  if (pushResult.exitCode !== 0) throw new FatalError(`git push failed (exit code ${String(pushResult.exitCode)}):\n${pushResult.stderr || pushResult.stdout}`);
6739
6747
  pushed = true;
@@ -6751,12 +6759,19 @@ async function runSimpleRelease(executor, config) {
6751
6759
  ], { cwd: config.cwd });
6752
6760
  if (slidingTagResult.exitCode !== 0) throw new FatalError(`Failed to create sliding tag ${slidingTag}: ${slidingTagResult.stderr || slidingTagResult.stdout}`);
6753
6761
  }
6754
- const forcePushResult = executor.exec("git", [
6762
+ const forcePushArgs = auth ? [
6763
+ ...auth.args,
6764
+ "push",
6765
+ auth.url,
6766
+ ...slidingTags,
6767
+ "--force"
6768
+ ] : [
6755
6769
  "push",
6756
6770
  "origin",
6757
6771
  ...slidingTags,
6758
6772
  "--force"
6759
- ], { cwd: config.cwd });
6773
+ ];
6774
+ const forcePushResult = executor.exec("git", forcePushArgs, { cwd: config.cwd });
6760
6775
  debugExec(config, "force-push sliding tags", forcePushResult);
6761
6776
  if (forcePushResult.exitCode !== 0) log.warn(`Warning: Failed to push sliding tags: ${forcePushResult.stderr || forcePushResult.stdout}`);
6762
6777
  else log.info(`Created sliding tags: ${slidingTags.join(", ")}`);
@@ -9122,7 +9137,7 @@ const out = (msg) => console.log(msg);
9122
9137
  const main = defineCommand({
9123
9138
  meta: {
9124
9139
  name: "bst",
9125
- version: "0.62.0",
9140
+ version: "0.62.1",
9126
9141
  description: "Bootstrap and maintain standardized TypeScript project tooling"
9127
9142
  },
9128
9143
  subCommands: {
@@ -9195,7 +9210,7 @@ const main = defineCommand({
9195
9210
  })
9196
9211
  }
9197
9212
  });
9198
- console.log(`@bensandee/tooling v0.62.0`);
9213
+ console.log(`@bensandee/tooling v0.62.1`);
9199
9214
  async function run() {
9200
9215
  await runMain(main);
9201
9216
  process.exit(process.exitCode ?? 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bensandee/tooling",
3
- "version": "0.62.0",
3
+ "version": "0.62.1",
4
4
  "description": "CLI tool to bootstrap and maintain standardized TypeScript project tooling",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -54,8 +54,8 @@
54
54
  "prettier": "3.8.3",
55
55
  "release-it": "20.0.1",
56
56
  "tsdown": "0.22.0",
57
- "@bensandee/claude-hooks": "0.8.1",
58
- "@bensandee/config": "0.11.3"
57
+ "@bensandee/config": "0.11.3",
58
+ "@bensandee/claude-hooks": "0.8.1"
59
59
  },
60
60
  "scripts": {
61
61
  "build": "tsdown",