Skip to content

refactor: eliminate code duplication, remove duplicate types, add Dockerfile#29

Merged
rbansal42 merged 27 commits intodevfrom
refactor/dedup-and-dockerfile
Feb 6, 2026
Merged

refactor: eliminate code duplication, remove duplicate types, add Dockerfile#29
rbansal42 merged 27 commits intodevfrom
refactor/dedup-and-dockerfile

Conversation

@rbansal42
Copy link
Owner

Summary

  • Phase 1: Extract shared utilities into cmdutil — replaces 5 duplicate timeAgo implementations, 6 duplicate truncateString functions, 2 duplicate getUserDisplayName functions, 8 duplicate JSON marshal blocks, and 7 duplicate table header blocks
  • Phase 2: Remove duplicate type definitions (PRUser, PRParticipant, PullRequest, PRComment) from internal/cmd/pr/shared.go — all PR commands now use canonical api.* types directly
  • Phase 3: Add production-ready multi-stage Dockerfile with non-root user, OCI labels, and comprehensive .dockerignore

New shared utilities in cmdutil

Function Replaces Call sites
TimeAgo(time.Time) 5 duplicate timeAgo/formatTimeAgo/formatUpdated 15+
TimeAgoFromString(string) snippet/list.go formatTime 1
TruncateString(string, int) 6 duplicate truncateString/truncateMessage 12+
GetUserDisplayName(*api.User) 2 duplicate getUserDisplayName 10+
PrintJSON(streams, any) 8 inline json.MarshalIndent blocks 9
PrintTableHeader(streams, w, header) 7 inline if/else blocks 8
ConfirmPrompt(reader) 2 duplicate confirmation prompts shared

Notable behavioral changes

  • bb snippet list time formatting normalized from abbreviated (5m ago, yesterday, Jan 2, 2006) to consistent relative format (5 minutes ago, 1 day ago, 2 months ago) matching all other commands
  • TimeAgo now returns "in the future" for future timestamps instead of "just now"
  • api.User now includes Nickname field from Bitbucket API

Testing

  • All existing tests pass (go test ./...)
  • go build ./... clean
  • go vet ./... clean

rbansal42 and others added 27 commits February 5, 2026 19:01
Merge dev to main: Phase 6 Additional PR Commands
The combination of -race and -coverprofile was causing 'no such tool covdata'
errors in GitHub Actions for packages without test files.
- Created internal/cmdutil/ package with shared utilities:
  - GetAPIClient() - authenticated API client creation
  - ParseRepository() - parse WORKSPACE/REPO format or detect from git
  - ParseWorkspace() - validate workspace string
  - TruncateString() - truncate strings for display

- Updated all command packages to use cmdutil:
  - pr, branch, issue, pipeline, repo, snippet, project, workspace

- Reduces code duplication across 8 command packages
- Removed parseRepoArg function from repo/shared.go
- Updated clone.go, delete.go, setdefault.go to use cmdutil.ParseRepository
- Updated delete_test.go to use cmdutil.ParseRepository

This consolidates the duplicate repository parsing functions into a single
well-documented function in the cmdutil package, as requested in issue #3.
- Enhanced README.md with:
  - Feature highlights and badges
  - Common workflow examples (PR, code review, CI/CD, issues)
  - Complete command reference tables
  - Shell completion setup for all shells
  - gh CLI comparison table

- Added user guides (docs/guide/):
  - authentication.md - OAuth, App Passwords, token storage
  - configuration.md - config files, env vars, settings
  - scripting.md - automation, JSON output, CI/CD integration
  - troubleshooting.md - common issues and solutions

- Added command reference (docs/commands/):
  - bb_auth.md, bb_pr.md, bb_repo.md, bb_issue.md
  - bb_pipeline.md, bb_branch.md, bb_workspace.md
  - bb_project.md, bb_snippet.md

- Added CONTRIBUTING.md with:
  - Development setup instructions
  - Project structure overview
  - Code style and testing guidelines
  - PR process and commit message format
- Updated go.mod module path to github.com/rbansal42/bitbucket-cli
- Updated all import statements (83 files)
- Updated documentation references
- Added GitHub topics for discoverability
Bitbucket deprecated App Passwords. Updated:
- login.go error message to point to OAuth consumers (not app-passwords URL)
- docs/guide/authentication.md - complete rewrite for OAuth + Repository Access Tokens
- docs/commands/bb_auth.md - remove App Password references

OAuth requires BB_OAUTH_CLIENT_ID and BB_OAUTH_CLIENT_SECRET env vars.
Repository Access Tokens work with --with-token flag.
Updated scripting.md, troubleshooting.md, configuration.md, and README.md
to use 'access token' or 'Repository Access Token' instead of 'App Password'
- Ask user to choose between API Token or OAuth
- Ask for workspace name to construct correct URLs
- Open browser directly to the right settings page
- Guide user through the setup process step by step
- For OAuth, prompt for Key and Secret, then proceed with flow
- Show instructions to save OAuth credentials to shell profile
When a token validation fails:
- Show clear error message
- Explain required permissions (Account: Read, Repositories: Read)
- Remind user to check for extra spaces and expiration
- Ask if they want to try again with a new token
- Add WithBasicAuth option to API client for email:api_token auth
- Update login flow to ask for email when using API tokens
- Use correct URL: https://id.atlassian.com/manage-profile/security/api-tokens
- Store Basic Auth credentials with 'basic:' prefix to distinguish from Bearer tokens
- Update cmdutil.GetAPIClient to handle both auth methods
- API Token: 'Logged in as: John Doe (john@example.com)'
- OAuth/Bearer: 'Logged in as: John Doe (johndoe)'
- Add 'bb workspace set-default' command to set/view/unset default workspace
- Prompt for default workspace after successful interactive login
- Store default workspace in config.yml
- List available workspaces for easy selection during login
- Add AGENTS.md guide for LLMs and autonomous agents at repo root
- Update 11 commands to fall back to default workspace when --workspace not specified:
  - repo: list, create, fork
  - project: list, view, create
  - snippet: list, view, create, edit, delete
- Improved error messages to suggest 'bb workspace set-default' as an option
- Removed MarkFlagRequired for workspace flags that now have fallback
…cation

- Add cmdutil.TimeAgo() and TimeAgoFromString() replacing 5 duplicate timeAgo implementations
- Add cmdutil.GetUserDisplayName() replacing 2 duplicate getUserDisplayName functions
- Add cmdutil.PrintJSON() replacing 8 duplicate JSON marshal/print blocks
- Add cmdutil.PrintTableHeader() replacing 7 duplicate table header blocks
- Add cmdutil.ConfirmPrompt() for shared confirmation logic
- Replace all local truncateString/truncateMessage with existing cmdutil.TruncateString
- Clean up unused imports across all modified files
- Add future timestamp guard in TimeAgo (returns 'in the future')
- Migrate project/list.go: replace truncateString, JSON, table header boilerplate
- Migrate issue/view.go: replace JSON output with cmdutil.PrintJSON
- Use 'any' instead of 'interface{}' in output.go
- Remove PRUser, PRParticipant, PullRequest, PRComment from pr/shared.go
- Remove getPullRequest helper, use api.Client.GetPullRequest directly
- Update pr/view.go to use api.PullRequest, api.User, cmdutil.GetUserDisplayName
- Update pr/reopen.go, pr/diff.go, pr/merge.go, pr/checkout.go, pr/comment.go
- Update pr/pr_test.go to use api types
- Fix type conversions: int64 PR IDs, PRState to string casts
- Multi-stage build: golang:1.25-alpine builder + alpine:3.21 runtime
- Supports VERSION and BUILD_DATE build args for ldflags
- Minimal runtime image with git + ca-certificates
- .dockerignore excludes .git, .worktrees, bin/, docs/, .github/
- Add Nickname field to api.User, add Nickname fallback in GetUserDisplayName
- Use api.PRStateOpen/PRStateDeclined constants instead of raw strings
- Dockerfile: add non-root user, OCI labels, BUILD_DATE default
- .dockerignore: add Dockerfile, Makefile, .goreleaser.yml, dist/, *.test
@rbansal42 rbansal42 merged commit 91feb29 into dev Feb 6, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants