Remove setup-git-user in favor of setting fallback only when identity is missing (#688)

* Experiment with skipping setup-git-user more often

* drop setup-git-user

* fix tests
This commit is contained in:
Mateusz Burzyński
2026-07-27 05:02:39 +00:00
committed by GitHub
parent 469993ce57
commit 219ea82e52
10 changed files with 52 additions and 26 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@changesets/action": patch
---
Remove the `setup-git-user` input. Complete custom Git identities are now preserved automatically, while `github-actions[bot]` is configured as a fallback before creating local release commits or tags.
-1
View File
@@ -75,7 +75,6 @@ jobs:
uses: ./version
with:
github-token: ${{ steps.bot-auth.outputs.token }}
setup-git-user: false
script: pnpm bump
publish:
+5 -1
View File
@@ -18,7 +18,6 @@ There are also sub-actions hosted in this repository. Check out their respective
- version-script - The command to update version, edit CHANGELOG, read and delete changesets. Default to `changeset version` if not provided
- commit-message - The commit message to use. Default to `Version Packages`
- pr-title - The pull request title. Default to `Version Packages`
- setup-git-user - Sets up the git user for commits as `"github-actions[bot]"`. Default to `true`
- create-github-releases - A boolean value to indicate whether to create Github releases after `publish` or not. Default to `true`
- push-git-tags - A boolean value to indicate whether to create git tags after `publish` or not. Default to `true`
- commit-mode - Specifies the commit mode. Use `"git-cli"` to push changes using the Git CLI, or `"github-api"` to push changes via the GitHub API. When using `"github-api"`, all commits and tags are GPG-signed and attributed to the user or app who owns the `GITHUB_TOKEN`. Default to `git-cli`
@@ -26,6 +25,11 @@ There are also sub-actions hosted in this repository. Check out their respective
- pr-draft - Controls draft PR behavior. Use `create` to create new version PRs as draft, or `always` to also convert existing version PRs back to draft when updating them. By default, version PRs are not forced into draft mode
- github-token - Passes a custom GitHub token
Before creating local commits or annotated tags, the action preserves complete
Git author and committer identities configured through the environment or Git
configuration. If either identity is unavailable, it configures
`github-actions[bot]` as a fallback.
### Outputs
- published - A boolean value to indicate whether a publishing has happened or not
-4
View File
@@ -46,10 +46,6 @@ inputs:
or app who owns the GITHUB_TOKEN.
required: false
default: "git-cli"
setup-git-user:
description: Sets up the git user for commits as `"github-actions[bot]"`. Default to `true`
required: false
default: true
outputs:
published:
description: A boolean value to indicate whether a publishing is happened or not
+28 -2
View File
@@ -93,10 +93,35 @@ export class GitHub {
};
}
async setupUser() {
if (this.commitMode === "github-api") {
async ensureGitUser() {
// Check the exact identities that Git would use for commits without
// allowing Git to fall back to auto-detected values like user@hostname.
// This covers explicit GIT_AUTHOR_* / GIT_COMMITTER_* env vars, local
// config, and global config. A partial identity, with only a name or only
// an email, does not pass this check. If either identity is missing,
// configure our default bot user as a fallback.
const authorIdentity = await getExecOutput(
"git",
["-c", "user.useConfigOnly=true", "var", "GIT_AUTHOR_IDENT"],
{
cwd: this.cwd,
ignoreReturnCode: true,
silent: true,
},
);
const committerIdentity = await getExecOutput(
"git",
["-c", "user.useConfigOnly=true", "var", "GIT_COMMITTER_IDENT"],
{
cwd: this.cwd,
ignoreReturnCode: true,
silent: true,
},
);
if (authorIdentity.exitCode === 0 && committerIdentity.exitCode === 0) {
return;
}
core.info("Setting Git user to github-actions[bot]");
await exec("git", ["config", "user.name", `"github-actions[bot]"`], {
cwd: this.cwd,
});
@@ -159,6 +184,7 @@ export class GitHub {
return;
}
if (!(await checkIfClean({ cwd: this.cwd }))) {
await this.ensureGitUser();
await commitAll(message, { cwd: this.cwd });
}
await push(branch, {
-8
View File
@@ -23,7 +23,6 @@ import {
prDraft: "pr-draft",
createGithubReleases: "create-github-releases",
commitMode: "commit-mode",
setupGitUser: "setup-git-user",
});
const githubToken = getRequiredInput("github-token");
@@ -51,13 +50,6 @@ import {
commitMode,
});
let setupGitUser = core.getBooleanInput("setup-git-user");
if (setupGitUser) {
core.info("setting git user");
await github.setupUser();
}
let { changesets } = await readChangesetState(cwd);
let publishScript = core.getInput("publish-script");
+10
View File
@@ -3,6 +3,7 @@ import * as core from "@actions/core";
import type { Changeset } from "@changesets/types";
import { writeChangeset } from "@changesets/write";
import { createFixture } from "fs-fixture";
import { exec } from "tinyexec";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { GitHub } from "./github.ts";
import { runPublish, runVersion } from "./run.ts";
@@ -101,6 +102,13 @@ const createGithub = (cwd: string) =>
commitMode: "github-api",
});
async function initializeGitRepository(cwd: string) {
await exec("git", ["init"], {
nodeOptions: { cwd },
throwOnError: true,
});
}
beforeEach(() => {
vi.clearAllMocks();
});
@@ -113,6 +121,7 @@ describe("publish", () => {
it("warns when a custom publish script does not create the output file", async () => {
await using fixture = await createSimpleProjectFixture();
const cwd = fixture.path;
await initializeGitRepository(cwd);
vi.stubEnv("RUNNER_TEMP", cwd);
const result = await runPublish({
@@ -145,6 +154,7 @@ describe("publish", () => {
"package-lock.json": "",
});
const cwd = fixture.path;
await initializeGitRepository(cwd);
vi.stubEnv("RUNNER_TEMP", cwd);
await expect(
+4
View File
@@ -164,6 +164,10 @@ export async function runPublish({
cwd,
}: PublishOptions): Promise<PublishResult> {
const { octokit } = github;
// Changesets creates annotated tags locally, including when the action pushes those tags through the GitHub API.
// It might also be important for custom publish scripts to have a valid git user configured.
await github.ensureGitUser();
let changesetPublishOutput: ExecOutput;
const outputFile = path.join(
process.env.RUNNER_TEMP ?? (await fs.realpath(os.tmpdir())),
-6
View File
@@ -25,7 +25,6 @@ async function main() {
const prDraft = getOptionalInput("pr-draft");
const prBaseBranch = getOptionalInput("pr-base-branch");
const commitMode = getOptionalInput("commit-mode") ?? "git-cli";
const setupGitUser = core.getBooleanInput("setup-git-user");
// Validations
if (prDraft !== undefined && prDraft !== "always" && prDraft !== "create") {
@@ -41,11 +40,6 @@ async function main() {
commitMode,
});
if (setupGitUser) {
core.info("setting git user");
await github.setupUser();
}
const { pullRequestNumber } = await runVersion({
script,
github,
-4
View File
@@ -33,10 +33,6 @@ inputs:
or app who owns the GITHUB_TOKEN.
required: false
default: "git-cli"
setup-git-user:
description: Sets up the git user for commits as `"github-actions[bot]"`. Default to `true`
required: false
default: true
outputs:
pr-number:
description: The pull request number that was created or updated