feat: add close/reply aliases and --format/--destination flags#160
feat: add close/reply aliases and --format/--destination flags#160avivsinai merged 6 commits intoavivsinai:masterfrom
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
avivsinai
left a comment
There was a problem hiding this comment.
I think the new --target / --destination aliasing still leaves one ambiguous case.
Evidence:
pkg/cmd/pr/pr.go:980-981binds both--targetand--destinationto&opts.Target.- There is no validation when both flags are supplied together.
pflagsilently lets the last one win in this setup; I reproduced that behavior locally.
I think either of these resolutions would be acceptable:
- Mark
targetanddestinationmutually exclusive. - Keep both accepted together, but normalize one into the other and document the precedence explicitly (for example, last-set wins).
Whichever route you choose, please add a test in pkg/cmd/pr/alias_test.go that asserts the behavior when both flags are supplied in the same invocation.
The rest of the PR looks good to me: --format conflict handling is fine, close / reply are implemented as Cobra aliases on shared command objects, and the doc regeneration looks mechanical.
|
Added |
avivsinai
left a comment
There was a problem hiding this comment.
Nice direction overall. The alias work is in the right spirit, but I think one issue is blocking before merge.
--formatis validated after the side effect, not before.pkg/cmdutil/output.go:42-47is where invalid values are rejected, butpkg/cmd/pr/pr.go:1042-1056and1097-1111create the PR beforecmdutil.WriteOutput(...)runs. Sobkt pr create --format xml ...can create a pull request and only then fail. From a CLI UX standpoint, formatting flags need to fail fast before any mutation.ghis careful about this because users should never have to wonder whether a failed formatting option still performed the action.
Two follow-ups I would treat as non-blocking, but worth tightening while this is open:
- The
--jq/--templatemessaging still says they require--json(pkg/cmd/root/root.go:52,pkg/cmdutil/output.go:54-55), even though--format jsonis now also valid. That makes the output model read inconsistent. replyis a narrower word than the behavior it maps to here.pkg/cmd/pr/pr.go:2725-2755still exposes the fullcommentsurface, including new top-level comments and inline comments. That feels lessgh-style thancomment, which is explicit about the breadth of the command.
avivsinai
left a comment
There was a problem hiding this comment.
One blocking issue still stands for me:
--formatvalidation still happens insidecmdutil.WriteOutput(...)(pkg/cmdutil/output.go:86-89), which means the CLI only rejects bad output flags after the mutation has already happened.pkg/cmd/pr/pr.go:1042-1056and1097-1111still create the pull request beforeResolveOutputSettingsruns, sobkt pr create --format xml ...can succeed server-side and only then exit with a formatting error. Because--formatis global, this is broader thanpr create/edit:pkg/cmd/issue/issue.go:532-562has the same ordering forissue create, and any other mutation that returns throughWriteOutputinherits it. I think the fix wants to validate output settings before command execution (for example in a rootPersistentPreRunEor an equivalent shared preflight), not just at individual call sites.
Two smaller follow-ups while this is open:
--jqhelp still saysrequires --json(pkg/cmd/root/root.go:52, plus the regenerated rules), even though--format jsonis now also valid. That wording will confuse users once--formatships.replyis a narrower alias than the command surface it exposes.pkg/cmd/pr/pr.go:2725-2744still supports new top-level comments and inline comments, socommentis precise butreplyreads as if it only targets existing threads.
|
Addressed all three points in 4a1f659:
|
- bkt pr close → alias for bkt pr decline - bkt pr reply → alias for bkt pr comment - --destination → visible alias for --target on pr create - --format json|yaml → global alternative to --json/--yaml - regenerate skill rules
Separate backing field for --destination, validate in RunE matching the existing --body/--description pattern. Errors when both supplied.
- Add PersistentPreRunE to root that calls ResolveOutputSettings, so --format/--jq/--template errors fail fast before any mutation runs - Update --jq help text and error message to say "requires --json or --format json" - Remove 'reply' alias from pr comment; 'comment' is the precise name for a command that creates top-level, threaded, and inline comments
4a1f659 to
4ef1220
Compare
avivsinai
left a comment
There was a problem hiding this comment.
Thanks for the follow-ups — the --target/--destination mutual-exclusion and the reply removal look good. One blocker remains, and one small test gap.
-
Blocker: root output validation is still skipped for every
bkt issue *command. The rootPersistentPreRunEyou added atpkg/cmd/root/root.go:55-58doesn't run for anyissuesubcommand becausepkg/cmd/issue/issue.go:25-39defines its ownPersistentPreRunE(the Bitbucket Cloud issues-sunset warning). Cobra traverses from leaf upward and invokes only the first persistent hook it finds unlesscobra.EnableTraverseRunHooks = true.Independent repro on the PR head with a fresh
BKT_CONFIG_DIR:$ bkt repo create foo --jq '.x' Error: --jq requires --json or --format json ✓ root pre-flight ran $ bkt pr create --title x --jq '.x' Error: --jq requires --json or --format json ✓ $ bkt issue create --title x --jq '.x' Error: no active context; run `bkt context use <name>` ✗ root pre-flight skippedOn a real Cloud context that means
bkt issue create --title x --format xmlwill reach the API and create the issue before--formatis validated — exactly the mutate-then-fail pattern this PR set out to remove.Cleanest fix:
cobra.EnableTraverseRunHooks = trueat root wiring. I swept the repo and found no otherPersistentPreRunE/PersistentPostRunEhooks apart fromissue.go's, so the blast radius is essentially zero — it just lets both hooks run in theissuesubtree, restoring the root pre-flight everywhere. -
Test gap: no positive runtime equivalence test for
--destination.pkg/cmd/pr/alias_test.go:55-65only exercises--destination --help, and :68-76 covers the mutual-exclusion case. Neither proves that--destination mainactually populatesopts.Targeton the real code path — the flag could be orphaned and the test would still pass. Please add a case that runspr createthrough the create path (with a mocked factory) and asserts the destination value reaches the same field--targetwould.
Nothing else changed my read; everything else is green and go test ./... passes on the PR head.
|
Refining the fix recommendation in my prior review — after checking against Recommended fix (one line, matches // pkg/cmd/issue/issue.go
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if cmd.Parent() != nil && cmd.Parent().PersistentPreRunE != nil {
if err := cmd.Parent().PersistentPreRunE(cmd, args); err != nil {
return err
}
}
// existing Cloud issues-sunset warning
...
return nil
}Why this over
Blocker and test-gap from the prior review still stand; only the suggested fix changes. Non-blocking aside on |
- issue.go PersistentPreRunE shadows the root hook; now calls ResolveOutputSettings directly so --format/--jq/--template fail fast before any 'bkt issue *' mutation hits the API - add positive runtime test asserting --destination main populates toRef.id=refs/heads/main in the DC create PR request
|
Addressed both in 84e6276: Root pre-flight skipped for
|
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Adds
closeandreplyas aliases forbkt pr declineandbkt pr commentrespectively, improving discoverability for users coming from GitHub CLI conventions.
Also adds
--destinationas a visible alias for--targetonbkt pr create, anda global
--formatflag as an alternative to--json/--yaml.Changes
bkt pr close→bkt pr decline;bkt pr reply→bkt pr comment--destinationadded as visible alias for--targetonpr create--format json|yamladded as alternative to--json/--yaml; conflicts with both, validated case-insensitively--formatvariants, conflict/invalid-value cases; alias smoke tests forclose/reply/--destinationTesting
go test ./...— 1182 tests passpre-commit run— all hooks passbkt pr close --help,bkt pr reply --help,bkt pr create --destination main --helpall render correctlyRisks