diff --git a/packages/cli/test/integration/cli/cmd-ci.test.mts b/packages/cli/test/integration/cli/cmd-ci.test.mts index d68ab728fd..8409937a28 100644 --- a/packages/cli/test/integration/cli/cmd-ci.test.mts +++ b/packages/cli/test/integration/cli/cmd-ci.test.mts @@ -97,7 +97,7 @@ describe('socket ci', async () => { Details: autoManifest: false - branchName: "main" + branchName: "[BRANCH]" cwd: "[PROJECT]" organizationSlug: "(from API token)" repoName: "socket-cli" diff --git a/packages/cli/test/util/scrub-snapshot-data.mts b/packages/cli/test/util/scrub-snapshot-data.mts index 8429910104..e301366213 100644 --- a/packages/cli/test/util/scrub-snapshot-data.mts +++ b/packages/cli/test/util/scrub-snapshot-data.mts @@ -30,6 +30,10 @@ interface ScrubOptions { * Scrub IP addresses (default: true). */ ipAddresses?: boolean | undefined + /** + * Scrub git branch names in dry-run details (default: true). + */ + branches?: boolean | undefined /** * Scrub email addresses (default: false - usually stable in mocks). */ @@ -56,6 +60,7 @@ export function scrubSnapshotData( options: ScrubOptions = {}, ): string { const { + branches = true, custom = [], emails = false, ids = true, @@ -149,7 +154,26 @@ export function scrubSnapshotData( ) } - // Phase 7: Custom patterns. + // Phase 7: Git branch names in dry-run details. + if (branches) { + // The CLI resolves the branch from the ambient git checkout + // (`git symbolic-ref`) or the CI env (GITHUB_HEAD_REF / GITHUB_REF_NAME), + // so the rendered `branchName: "…"` is whatever branch the test happens to + // run on — "main" on a main push, the PR head branch on a PR build, the + // local feature branch when run from a worktree, or a short commit hash on + // a detached HEAD with no CI env. Pin it so the snapshot is branch-agnostic + // (this test failed on every non-main PR before). The branch-resolution + // logic itself stays covered by the unit tests that mock `gitBranch` + // (handle-ci / cmd-ci unit specs). Only matches the human-readable details + // form (`branchName: "…"`, space after the unquoted key), not JSON output + // (`"branchName":"…"`). + scrubbed = scrubbed.replace( + /branchName: "[^"]*"/g, + 'branchName: "[BRANCH]"', + ) + } + + // Phase 8: Custom patterns. for (const { pattern, replacement } of custom) { scrubbed = scrubbed.replace(pattern, replacement) } diff --git a/packages/cli/test/util/scrub-snapshot-data.test.mts b/packages/cli/test/util/scrub-snapshot-data.test.mts index c4a768a1fa..521ed11a60 100644 --- a/packages/cli/test/util/scrub-snapshot-data.test.mts +++ b/packages/cli/test/util/scrub-snapshot-data.test.mts @@ -173,6 +173,38 @@ describe('scrubSnapshotData', () => { }) }) + describe('git branch names', () => { + it('should scrub the auto-detected branch name in dry-run details', () => { + const input = ' branchName: "main"' + const result = scrubSnapshotData(input) + expect(result).toBe(' branchName: "[BRANCH]"') + }) + + it('should scrub a feature branch name with slashes', () => { + const input = ' branchName: "fix/cmd-ci-branch-snapshot"' + const result = scrubSnapshotData(input) + expect(result).toBe(' branchName: "[BRANCH]"') + }) + + it('should scrub a detached-HEAD commit-hash fallback', () => { + const input = ' branchName: "a0211c9"' + const result = scrubSnapshotData(input) + expect(result).toBe(' branchName: "[BRANCH]"') + }) + + it('should not scrub JSON-form branchName (quoted key)', () => { + const input = '"branchName":"develop"' + const result = scrubSnapshotData(input) + expect(result).toBe('"branchName":"develop"') + }) + + it('should preserve branch names when disabled', () => { + const input = ' branchName: "main"' + const result = scrubSnapshotData(input, { branches: false }) + expect(result).toBe(' branchName: "main"') + }) + }) + describe('custom patterns', () => { it('should apply custom scrubbing patterns', () => { const input = 'API key: abc-123-def and token: xyz-456-uvw'