What
Refactor both cfl and jtk to import and use the shared atlassian-go module instead of their duplicated internal implementations.
Changes per Tool
confluence-cli (tools/cfl)
| Current |
Replace With |
api/client.go auth logic |
atlassian-go/auth |
api/client.go HTTP methods |
atlassian-go/client |
internal/config/config.go env fallback |
atlassian-go/config |
internal/view/view.go |
atlassian-go/view |
Keep tool-specific:
api/pages.go, api/spaces.go, etc. (Confluence-specific endpoints)
pkg/md/ (Markdown ↔ XHTML conversion)
internal/cmd/ (Cobra commands)
jira-ticket-cli (tools/jtk)
| Current |
Replace With |
api/client.go auth logic |
atlassian-go/auth |
api/client.go HTTP methods |
atlassian-go/client |
api/errors.go |
atlassian-go/errors |
internal/config/config.go env fallback |
atlassian-go/config |
internal/view/view.go |
atlassian-go/view |
Keep tool-specific:
api/issues.go, api/sprints.go, etc. (Jira-specific endpoints)
api/markdown.go (Markdown → ADF conversion)
internal/cmd/ (Cobra commands)
Example Refactor
Before (cfl):
// api/client.go
type Client struct {
baseURL string
email string
apiToken string
httpClient *http.Client
}
func (c *Client) do(ctx context.Context, method, path string, body interface{}) ([]byte, error) {
// ... 50 lines of HTTP logic
}
After (cfl):
// api/client.go
import "github.com/open-cli-collective/atlassian-go/client"
type Client struct {
*client.Client // Embed shared client
}
func NewClient(baseURL, email, apiToken string) *Client {
return &Client{
Client: client.New(baseURL, email, apiToken, nil),
}
}
// Tool-specific methods use embedded client
func (c *Client) GetPage(ctx context.Context, pageID string) (*Page, error) {
resp, err := c.Get(ctx, "/api/v2/pages/"+pageID)
// ...
}
Why
Reduces maintenance burden
After this refactor:
- HTTP client bugs are fixed once in
atlassian-go
- Auth logic is tested once, used everywhere
- Output formatting improvements benefit both tools automatically
Enables consistent behavior
Users of both tools get:
- Same environment variable patterns (
ATLASSIAN_* fallbacks)
- Same output format options (
--output table|json|plain)
- Same error messages for common failures (401, 403, 404)
Validates the shared API design
This phase proves the shared module API is practical:
- If refactoring is painful, we adjust the shared API
- If something can't be shared, we document why
- Real usage reveals edge cases tests might miss
Acceptance Criteria
Dependencies
What
Refactor both
cflandjtkto import and use the sharedatlassian-gomodule instead of their duplicated internal implementations.Changes per Tool
confluence-cli (tools/cfl)
api/client.goauth logicatlassian-go/authapi/client.goHTTP methodsatlassian-go/clientinternal/config/config.goenv fallbackatlassian-go/configinternal/view/view.goatlassian-go/viewKeep tool-specific:
api/pages.go,api/spaces.go, etc. (Confluence-specific endpoints)pkg/md/(Markdown ↔ XHTML conversion)internal/cmd/(Cobra commands)jira-ticket-cli (tools/jtk)
api/client.goauth logicatlassian-go/authapi/client.goHTTP methodsatlassian-go/clientapi/errors.goatlassian-go/errorsinternal/config/config.goenv fallbackatlassian-go/configinternal/view/view.goatlassian-go/viewKeep tool-specific:
api/issues.go,api/sprints.go, etc. (Jira-specific endpoints)api/markdown.go(Markdown → ADF conversion)internal/cmd/(Cobra commands)Example Refactor
Before (cfl):
After (cfl):
Why
Reduces maintenance burden
After this refactor:
atlassian-goEnables consistent behavior
Users of both tools get:
ATLASSIAN_*fallbacks)--output table|json|plain)Validates the shared API design
This phase proves the shared module API is practical:
Acceptance Criteria
tools/cfl/go.modrequiresgithub.com/open-cli-collective/atlassian-gotools/jtk/go.modrequiresgithub.com/open-cli-collective/atlassian-gogo build ./tools/cfl/cmd/cflsucceedsgo build ./tools/jtk/cmd/jtksucceedsgo test ./tools/cfl/...passes (no regressions)go test ./tools/jtk/...passes (no regressions)cfl page listworksjtk issue getworksDependencies