refactor: eliminate code duplication, remove duplicate types, add Dockerfile#29
Merged
refactor: eliminate code duplication, remove duplicate types, add Dockerfile#29
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cmdutil— replaces 5 duplicatetimeAgoimplementations, 6 duplicatetruncateStringfunctions, 2 duplicategetUserDisplayNamefunctions, 8 duplicate JSON marshal blocks, and 7 duplicate table header blocksPRUser,PRParticipant,PullRequest,PRComment) frominternal/cmd/pr/shared.go— all PR commands now use canonicalapi.*types directly.dockerignoreNew shared utilities in
cmdutilTimeAgo(time.Time)timeAgo/formatTimeAgo/formatUpdatedTimeAgoFromString(string)snippet/list.goformatTimeTruncateString(string, int)truncateString/truncateMessageGetUserDisplayName(*api.User)getUserDisplayNamePrintJSON(streams, any)json.MarshalIndentblocksPrintTableHeader(streams, w, header)ConfirmPrompt(reader)Notable behavioral changes
bb snippet listtime 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 commandsTimeAgonow returns"in the future"for future timestamps instead of"just now"api.Usernow includesNicknamefield from Bitbucket APITesting
go test ./...)go build ./...cleango vet ./...clean