3d860290da
* feat(github): add merge button when PR is ready to merge Surfaces a one-click merge action in the PR detail panel header and as a compact green pill in the PR topbar hover popover, gated by the existing isPRReadyToMerge predicate (open, CI success, mergeable_state=clean, and either approved or no review process). Backend adds MergePR to the Client interface, implements it across PAT/gh/Noop/Mock clients, exposes PUT /api/v1/github/prs/:owner/:repo/:number/merge, and maps GitHub 405/409 to HTTP 409 so the UI can show a clear error. * fix(github): address PR review feedback on merge endpoint - Map gh CLI 404/403/405/409 stderr to *GitHubAPIError via a new ghMergeStatusCode helper, so merge conflicts surface as HTTP 409 for gh CLI users (previously only PAT users got the right status). - Service.MergePR returns ErrNoClient when unconfigured; httpMergePR translates that to HTTP 503 with github_not_configured, matching httpListRepoBranches. - httpMergePR distinguishes empty body (io.EOF, fall through to default merge method) from malformed JSON (HTTP 400 invalid payload). - PRMergeButton tracks a local merged flag so the button stays hidden across the async refresh window after a successful merge. * test(github): cover merge helpers and extract PRMergeButton - TestGhMergeStatusCode locks in the gh CLI stderr → status-code parser for nil, unrelated errors, the HTTP / status: / bare-phrase forms of 404/403/405/409, and a 500 non-match guard. - Broaden ghMergeStatusCode to also match "405 Method Not Allowed" / "409 Conflict" phrase forms so the merge endpoint's 409 mapping does not depend on the gh CLI keeping its current "HTTP <code>" prefix. - TestHttpMergePR_MalformedJSON covers the new non-EOF bind-error branch (truncated body → 400). TestHttpMergePR_NoClient_Returns503 covers the ErrNoClient → 503 path on Service.MergePR. - Document the post/put error-type divergence on PATClient.post so a future caller does not silently lose per-status mapping. - Move PRMergeButton out of pr-shared.tsx into its own file, and reset the local "merged" flag when taskPR.id changes so an instance that re-renders for a different PR does not stay hidden. --------- Co-authored-by: Kandev Agent <agent@kandev.dev>
107 lines
3.0 KiB
Go
107 lines
3.0 KiB
Go
package github
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
)
|
|
|
|
// ErrNoClient is returned by NoopClient methods that cannot provide meaningful data.
|
|
var ErrNoClient = errors.New("github client not configured")
|
|
|
|
// NoopClient is a GitHub client that returns empty results for all operations.
|
|
// Used when GitHub integration is not configured or not needed.
|
|
type NoopClient struct{}
|
|
|
|
func (c *NoopClient) IsAuthenticated(context.Context) (bool, error) {
|
|
return false, nil
|
|
}
|
|
|
|
func (c *NoopClient) GetAuthenticatedUser(context.Context) (string, error) {
|
|
return "", nil
|
|
}
|
|
|
|
func (c *NoopClient) GetPR(context.Context, string, string, int) (*PR, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) FindPRByBranch(context.Context, string, string, string) (*PR, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) ListAuthoredPRs(context.Context, string, string) ([]*PR, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) ListReviewRequestedPRs(context.Context, string, string, string) ([]*PR, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) ListUserOrgs(context.Context) ([]GitHubOrg, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) SearchOrgRepos(context.Context, string, string, int) ([]GitHubRepo, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) ListPRReviews(context.Context, string, string, int) ([]PRReview, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) ListPRComments(context.Context, string, string, int, *time.Time) ([]PRComment, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) ListCheckRuns(context.Context, string, string, string) ([]CheckRun, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) GetPRFeedback(context.Context, string, string, int) (*PRFeedback, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) GetPRStatus(context.Context, string, string, int) (*PRStatus, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) ListPRFiles(context.Context, string, string, int) ([]PRFile, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) ListPRCommits(context.Context, string, string, int) ([]PRCommitInfo, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) ListRepoBranches(context.Context, string, string) ([]RepoBranch, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) SubmitReview(context.Context, string, string, int, string, string) error {
|
|
return ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) MergePR(context.Context, string, string, int, string) error {
|
|
return ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) ListIssues(context.Context, string, string) ([]*Issue, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) ListIssuesPaged(context.Context, string, string, int, int) (*IssueSearchPage, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) SearchPRs(context.Context, string, string) ([]*PR, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) SearchPRsPaged(context.Context, string, string, int, int) (*PRSearchPage, error) {
|
|
return nil, ErrNoClient
|
|
}
|
|
|
|
func (c *NoopClient) GetIssueState(context.Context, string, string, int) (string, error) {
|
|
return "", ErrNoClient
|
|
}
|