Documentation
¶
Overview ¶
Package prx provides a client for fetching pull request events from code hosting platforms. It supports GitHub, GitLab, and Codeberg (Gitea), with caching to improve performance and reduce API rate limit consumption.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/codeGROOVE-dev/prx/pkg/prx/pr"
)
func main() {
// The simplest way: just pass a URL
// Authentication is automatically resolved from environment or CLI tools
ctx := context.Background()
data, err := pr.Fetch(ctx, "https://github.com/owner/repo/pull/123")
if err != nil {
log.Fatal(err)
}
// Show PR metadata
fmt.Printf("PR #%d: %s\n", data.PullRequest.Number, data.PullRequest.Title)
fmt.Printf("Author: %s (write access: %d)\n", data.PullRequest.Author, data.PullRequest.AuthorWriteAccess)
fmt.Printf("Status: %s, Mergeable: %v\n", data.PullRequest.State, data.PullRequest.MergeableState)
// Process events
for i := range data.Events {
event := &data.Events[i]
fmt.Printf("%s: %s by %s\n",
event.Timestamp.Format("2006-01-02 15:04:05"),
event.Kind,
event.Actor,
)
}
}
Index ¶
- Constants
- func BuildCodebergURL(owner, repo string, number int) string
- func BuildGitHubURL(owner, repo string, number int) string
- func BuildGitLabURL(host, owner, repo string, number int) string
- func BuildGiteaURL(host, owner, repo string, number int) string
- func CalculateParticipantAccess(events []Event, pr *PullRequest) map[string]int
- func ContainsQuestion(text string) bool
- func DetectPlatform(host string) stringdeprecated
- func DetectPlatformFromHost(host string) string
- func ExtractShortRef(input string) (string, error)
- func FinalizePullRequest(pullRequest *PullRequest, events []Event, requiredChecks []string, ...)
- func FixTestState(pullRequest *PullRequest)
- func IsValidPRURL(input string) bool
- func NormalizeURL(input string) (string, error)
- func SetBlockedDescription(pullRequest *PullRequest)
- func SetMergeableDescription(pullRequest *PullRequest)
- func Truncate(s string) string
- func UpgradeWriteAccess(events []Event)
- type ApprovalSummary
- type CheckSummary
- type Client
- type Event
- type Option
- type PRStore
- type ParsedPR
- type ParsedURL
- type Platform
- type PullRequest
- type PullRequestData
- type ReviewState
- type ShortRef
Examples ¶
Constants ¶
const ( TestStateNone = "" // No tests or unknown state TestStateQueued = "queued" // Tests are queued to run TestStateRunning = "running" // Tests are currently executing TestStatePassing = "passing" // All tests passed TestStateFailing = "failing" // Some tests failed TestStatePending = "pending" // Some tests are pending )
TestState represents the overall testing status of a pull request.
const ( EventKindCommit = "commit" // EventKindCommit represents a commit event. EventKindComment = "comment" // EventKindComment represents a comment event. EventKindReview = "review" // EventKindReview represents a review event. EventKindReviewComment = "review_comment" // EventKindReviewComment represents a review comment event. EventKindLabeled = "labeled" // EventKindLabeled represents a label added event. EventKindUnlabeled = "unlabeled" // EventKindUnlabeled represents a label removed event. EventKindAssigned = "assigned" // EventKindAssigned represents an assignment event. EventKindUnassigned = "unassigned" // EventKindUnassigned represents an unassignment event. EventKindMilestoned = "milestoned" // EventKindMilestoned represents a milestone added event. EventKindDemilestoned = "demilestoned" // EventKindDemilestoned represents a milestone removed event. EventKindReviewRequested = "review_requested" // EventKindReviewRequested represents a review request event. EventKindReviewRequestRemoved = "review_request_removed" // EventKindReviewRequestRemoved represents a review request removed event. EventKindPROpened = "pr_opened" // EventKindPROpened represents a PR opened event. EventKindPRClosed = "pr_closed" // EventKindPRClosed represents a PR closed event. EventKindPRMerged = "pr_merged" // EventKindPRMerged represents a PR merge event. EventKindMerged = "merged" // EventKindMerged represents a merge event from timeline. EventKindReadyForReview = "ready_for_review" // EventKindReadyForReview represents a ready for review event. EventKindConvertToDraft = "convert_to_draft" // EventKindConvertToDraft represents a convert to draft event. EventKindClosed = "closed" // EventKindClosed represents a PR closed event. EventKindReopened = "reopened" // EventKindReopened represents a PR reopened event. EventKindRenamedTitle = "renamed_title" // EventKindRenamedTitle represents a title rename event. EventKindMentioned = "mentioned" // EventKindMentioned represents a mention event. EventKindReferenced = "referenced" // EventKindReferenced represents a reference event. EventKindCrossReferenced = "cross_referenced" // EventKindCrossReferenced represents a cross-reference event. EventKindPinned = "pinned" // EventKindPinned represents a pin event. EventKindUnpinned = "unpinned" // EventKindUnpinned represents an unpin event. EventKindTransferred = "transferred" // EventKindTransferred represents a transfer event. EventKindSubscribed = "subscribed" // EventKindSubscribed represents a subscription event. EventKindUnsubscribed = "unsubscribed" // EventKindUnsubscribed represents an unsubscription event. EventKindHeadRefDeleted = "head_ref_deleted" // EventKindHeadRefDeleted represents a head ref deletion event. EventKindHeadRefRestored = "head_ref_restored" // EventKindHeadRefRestored represents a head ref restoration event. EventKindHeadRefForcePushed = "head_ref_force_pushed" // EventKindHeadRefForcePushed represents a head ref force push event. EventKindBaseRefChanged = "base_ref_changed" // EventKindBaseRefChanged represents a base ref change event. EventKindBaseRefForcePushed = "base_ref_force_pushed" // EventKindBaseRefForcePushed represents a base ref force push event. EventKindReviewDismissed = "review_dismissed" // EventKindReviewDismissed represents a review dismissed event. EventKindLocked = "locked" // EventKindLocked represents a lock event. EventKindUnlocked = "unlocked" // EventKindUnlocked represents an unlock event. EventKindAutoMergeEnabled = "auto_merge_enabled" // EventKindAutoMergeEnabled represents an auto merge enabled event. EventKindAutoMergeDisabled = "auto_merge_disabled" // EventKindAutoMergeDisabled represents an auto merge disabled event. EventKindAddedToMergeQueue = "added_to_merge_queue" // EventKindAddedToMergeQueue represents an added to merge queue event. EventKindRemovedFromMergeQueue = "removed_from_merge_queue" // EventKindRemovedFromMergeQueue represents removal from merge queue. // EventKindAutomaticBaseChangeSucceeded represents a successful base change. EventKindAutomaticBaseChangeSucceeded = "automatic_base_change_succeeded" // EventKindAutomaticBaseChangeFailed represents a failed base change. EventKindAutomaticBaseChangeFailed = "automatic_base_change_failed" EventKindDeployed = "deployed" // EventKindDeployed represents a deployment event. // EventKindDeploymentEnvironmentChanged represents a deployment environment change event. EventKindDeploymentEnvironmentChanged = "deployment_environment_changed" EventKindConnected = "connected" // EventKindConnected represents a connected event. EventKindDisconnected = "disconnected" // EventKindDisconnected represents a disconnected event. EventKindUserBlocked = "user_blocked" // EventKindUserBlocked represents a user blocked event. EventKindStatusCheck = "status_check" // EventKindStatusCheck represents a status check event (from APIs). EventKindCheckRun = "check_run" // EventKindCheckRun represents a check run event (from APIs). )
Event kind constants for PR timeline events.
const ( WriteAccessNo = -2 // User confirmed to not have write access WriteAccessUnlikely = -1 // User unlikely to have write access (CONTRIBUTOR, NONE, etc.) WriteAccessNA = 0 // Not applicable/not set (omitted from JSON) WriteAccessLikely = 1 // User likely has write access but unable to confirm (MEMBER with 403 API response) WriteAccessDefinitely = 2 // User definitely has write access (OWNER, COLLABORATOR, or confirmed via API) )
WriteAccess constants for the Event.WriteAccess field.
const ( PlatformGitHub = "github" PlatformGitLab = "gitlab" PlatformCodeberg = "codeberg" )
Common platform hosts.
Variables ¶
This section is empty.
Functions ¶
func BuildCodebergURL ¶
BuildCodebergURL constructs a Codeberg PR URL from components.
func BuildGitHubURL ¶
BuildGitHubURL constructs a GitHub PR URL from components.
func BuildGitLabURL ¶
BuildGitLabURL constructs a GitLab MR URL from components.
func BuildGiteaURL ¶
BuildGiteaURL constructs a Gitea PR URL from components. For Codeberg, use BuildCodebergURL instead.
func CalculateParticipantAccess ¶
func CalculateParticipantAccess(events []Event, pr *PullRequest) map[string]int
CalculateParticipantAccess builds a map of all PR participants to their write access levels. Includes the PR author, assignees, reviewers, and all event actors.
func ContainsQuestion ¶
ContainsQuestion determines if text contains a question based on: 1. Presence of a question mark 2. Common question patterns with proper word boundaries.
func DetectPlatform
deprecated
func DetectPlatformFromHost ¶
DetectPlatformFromHost detects platform from hostname, defaulting to Gitea for unknown hosts.
func ExtractShortRef ¶
ExtractShortRef returns a short reference string like "owner/repo#123".
func FinalizePullRequest ¶
func FinalizePullRequest(pullRequest *PullRequest, events []Event, requiredChecks []string, testStateFromAPI string)
FinalizePullRequest applies final calculations and consistency fixes.
func FixTestState ¶
func FixTestState(pullRequest *PullRequest)
FixTestState ensures test_state is consistent with check_summary. If CheckSummary has data, it takes precedence. Otherwise, preserve the existing TestState (which may have been set from platform-specific data like GitLab pipelines).
func IsValidPRURL ¶
IsValidPRURL returns true if the input appears to be a valid PR/MR URL.
func NormalizeURL ¶
NormalizeURL takes any supported URL format and returns a normalized URL string.
func SetBlockedDescription ¶
func SetBlockedDescription(pullRequest *PullRequest)
SetBlockedDescription determines what's blocking the PR and sets appropriate description.
func SetMergeableDescription ¶
func SetMergeableDescription(pullRequest *PullRequest)
SetMergeableDescription adds human-readable description for mergeable state.
func UpgradeWriteAccess ¶
func UpgradeWriteAccess(events []Event)
UpgradeWriteAccess scans through events and upgrades write_access from 1 (likely) to 2 (definitely) for actors who have performed actions that require write access.
Types ¶
type ApprovalSummary ¶
type ApprovalSummary struct {
// Approvals from users confirmed to have write access (owners, collaborators, members with confirmed access)
ApprovalsWithWriteAccess int `json:"approvals_with_write_access"`
// Approvals from users with unknown or likely write access (members, uncertain cases)
ApprovalsWithUnknownAccess int `json:"approvals_with_unknown_access"`
// Approvals from users confirmed to not have write access (contributors, outside collaborators)
ApprovalsWithoutWriteAccess int `json:"approvals_without_write_access"`
// Outstanding change requests from any reviewer
ChangesRequested int `json:"changes_requested"`
}
ApprovalSummary tracks PR review approvals and change requests.
func CalculateApprovalSummary ¶
func CalculateApprovalSummary(events []Event) *ApprovalSummary
CalculateApprovalSummary analyzes review events and categorizes approvals by reviewer's write access.
type CheckSummary ¶
type CheckSummary struct {
Success map[string]string `json:"success"` // Map of successful check names to their status descriptions
Failing map[string]string `json:"failing"` // Map of failing check names to their status descriptions (excludes cancelled)
Pending map[string]string `json:"pending"` // Map of pending check names to their status descriptions
Cancelled map[string]string `json:"cancelled"` // Map of cancelled check names to their status descriptions
Skipped map[string]string `json:"skipped"` // Map of skipped check names to their status descriptions
Stale map[string]string `json:"stale"` // Map of stale check names to their status descriptions
Neutral map[string]string `json:"neutral"` // Map of neutral check names to their status descriptions
}
CheckSummary aggregates all status checks and check runs.
func CalculateCheckSummary ¶
func CalculateCheckSummary(events []Event, requiredChecks []string) *CheckSummary
CalculateCheckSummary analyzes check/status events and categorizes them by outcome.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client provides methods to fetch pull request events from various platforms.
func NewClient ¶
NewClient creates a new Client with the given platform. For GitHub: NewClient(github.NewPlatform(token), opts...) For GitLab: NewClient(gitlab.NewPlatform(token), opts...) For Gitea: NewClient(gitea.NewPlatform(token), opts...)
func (*Client) PullRequest ¶
func (c *Client) PullRequest(ctx context.Context, owner, repo string, prNumber int) (*PullRequestData, error)
PullRequest fetches a pull request with all its events and metadata.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/codeGROOVE-dev/prx/pkg/prx/pr"
)
func main() {
// For advanced use cases where you need to fetch multiple PRs from the same platform,
// you can still use the client-based API
ctx := context.Background()
// Fetch using the simple API
data, err := pr.Fetch(ctx, "https://github.com/golang/go/pull/123")
if err != nil {
log.Fatal(err)
}
// Show PR size
fmt.Printf("PR #%d: +%d -%d in %d files\n",
data.PullRequest.Number,
data.PullRequest.Additions,
data.PullRequest.Deletions,
data.PullRequest.ChangedFiles)
// Count events by type
eventCounts := make(map[string]int)
for i := range data.Events {
eventCounts[data.Events[i].Kind]++
}
// Print summary
fmt.Printf("Total events: %d\n", len(data.Events))
for eventKind, count := range eventCounts {
fmt.Printf("%s: %d\n", eventKind, count)
}
}
type Event ¶
type Event struct {
Timestamp time.Time `json:"timestamp"`
Kind string `json:"kind"`
Actor string `json:"actor"`
Target string `json:"target,omitempty"`
Outcome string `json:"outcome,omitempty"`
Body string `json:"body,omitempty"`
Description string `json:"description,omitempty"`
WriteAccess int `json:"write_access,omitempty"`
Bot bool `json:"bot,omitempty"`
TargetIsBot bool `json:"target_is_bot,omitempty"`
Question bool `json:"question,omitempty"`
Required bool `json:"required,omitempty"`
Outdated bool `json:"outdated,omitempty"` // For review comments: indicates comment is on outdated code
}
Event represents a single event that occurred on a pull request. Each event captures who did what and when, with additional context depending on the event type.
func FilterEvents ¶
FilterEvents removes non-essential events to reduce noise. Currently filters out successful status_check events (keeps failures).
type Option ¶
type Option func(*Client)
Option is a function that configures a Client.
func WithCacheStore ¶
WithCacheStore sets a custom cache store for PR data. Use null.New[string, prx.PullRequestData]() to disable persistence.
func WithLogger ¶
WithLogger sets a custom logger for the client.
type PRStore ¶
type PRStore = fido.Store[string, PullRequestData]
PRStore is the interface for PR cache storage backends. This is an alias for fido.Store with the appropriate type parameters.
func NewCacheStore ¶
NewCacheStore creates a cache store backed by the given directory. This is a convenience function for use with WithCacheStore.
type ParsedPR ¶
type ParsedPR struct {
Owner string
Repo string
Platform string // Empty if parsed from short ref
Number int
}
ParsedPR represents the result of parsing a PR reference in any format.
func ParseOwnerRepoPR ¶
ParseOwnerRepoPR is a convenience function that accepts multiple input formats: full URL, short ref with hash, or short ref with slash.
type ParsedURL ¶
type ParsedURL struct {
Platform string // "github", "gitlab", "codeberg"
Host string // e.g., "github.com", "gitlab.com"
Owner string
Repo string
Number int // PR or MR number
}
ParsedURL represents a parsed code hosting URL.
type Platform ¶
type Platform interface {
// FetchPR retrieves a pull request with all events and metadata.
// The refTime parameter is used for cache validation decisions.
FetchPR(ctx context.Context, owner, repo string, number int, refTime time.Time) (*PullRequestData, error)
// Name returns the platform identifier (e.g., "github", "gitlab", "codeberg").
Name() string
}
Platform fetches pull request data from a code hosting service. Each platform (GitHub, GitLab, Codeberg) implements its own fetching strategy.
type PullRequest ¶
type PullRequest struct {
// 16-byte fields (time.Time)
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// 8-byte pointer fields
ClosedAt *time.Time `json:"closed_at,omitempty"`
MergedAt *time.Time `json:"merged_at,omitempty"`
ApprovalSummary *ApprovalSummary `json:"approval_summary,omitempty"`
CheckSummary *CheckSummary `json:"check_summary,omitempty"`
Mergeable *bool `json:"mergeable,omitempty"`
// 24-byte slice/map fields
Assignees []string `json:"assignees,omitempty"`
Labels []string `json:"labels,omitempty"`
Commits []string `json:"commits,omitempty"` // List of commit SHAs in chronological order (oldest to newest)
Reviewers map[string]ReviewState `json:"reviewers,omitempty"`
ParticipantAccess map[string]int `json:"participant_access,omitempty"` // Map of username to WriteAccess level
// 16-byte string fields
MergeableState string `json:"mergeable_state"`
MergeableStateDescription string `json:"mergeable_state_description,omitempty"`
Author string `json:"author"`
Body string `json:"body"`
Title string `json:"title"`
MergedBy string `json:"merged_by,omitempty"`
State string `json:"state"`
TestState string `json:"test_state,omitempty"`
HeadSHA string `json:"head_sha,omitempty"`
// 8-byte int fields
Number int `json:"number"`
ChangedFiles int `json:"changed_files"`
Deletions int `json:"deletions"`
Additions int `json:"additions"`
AuthorWriteAccess int `json:"author_write_access,omitempty"`
// 1-byte bool fields
AuthorBot bool `json:"author_bot"`
Merged bool `json:"merged"`
Draft bool `json:"draft"`
}
PullRequest represents a GitHub pull request with its essential metadata.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/codeGROOVE-dev/prx/pkg/prx/pr"
)
func main() {
ctx := context.Background()
// Works with GitHub
data, err := pr.Fetch(ctx, "https://github.com/owner/repo/pull/123")
if err != nil {
log.Fatal(err)
}
fmt.Printf("GitHub PR #%d\n", data.PullRequest.Number)
// Works with GitLab
data, err = pr.Fetch(ctx, "https://gitlab.com/owner/repo/-/merge_requests/456")
if err != nil {
log.Fatal(err)
}
fmt.Printf("GitLab MR #%d\n", data.PullRequest.Number)
// Works with Codeberg
data, err = pr.Fetch(ctx, "https://codeberg.org/owner/repo/pulls/789")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Codeberg PR #%d\n", data.PullRequest.Number)
// Works with any Gitea instance
data, err = pr.Fetch(ctx, "https://gitea.example.com/owner/repo/pulls/100")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Gitea PR #%d\n", data.PullRequest.Number)
// URL fragments and query parameters are automatically stripped
data, err = pr.Fetch(ctx, "https://github.com/owner/repo/pull/123?tab=checks#issuecomment-456")
if err != nil {
log.Fatal(err)
}
fmt.Printf("PR #%d (cleaned URL)\n", data.PullRequest.Number)
}
type PullRequestData ¶
type PullRequestData struct {
CachedAt time.Time `json:"cached_at,omitzero"` // When this data was cached
Events []Event `json:"events"`
PullRequest PullRequest `json:"pull_request"`
}
PullRequestData contains a pull request and all its associated events.
type ReviewState ¶
type ReviewState string
ReviewState represents the current state of a reviewer's review.
const ( ReviewStatePending ReviewState = "pending" // Review requested but not yet submitted ReviewStateApproved ReviewState = "approved" // Approved ReviewStateChangesRequested ReviewState = "changes_requested" // Changes requested ReviewStateCommented ReviewState = "commented" // Reviewed with comments only )
Review state constants.
type ShortRef ¶
ShortRef represents a parsed short reference like "owner/repo#123".
func ParseShortRef ¶
ParseShortRef parses a short reference like "owner/repo#123" or "owner/repo/123". It does not include platform information - that must be provided separately.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package auth provides token resolution for different git hosting platforms.
|
Package auth provides token resolution for different git hosting platforms. |
|
Package gitea provides a Gitea/Codeberg platform implementation for fetching pull request data from Gitea-based forges.
|
Package gitea provides a Gitea/Codeberg platform implementation for fetching pull request data from Gitea-based forges. |
|
Package github provides a low-level client for the GitHub REST and GraphQL APIs.
|
Package github provides a low-level client for the GitHub REST and GraphQL APIs. |
|
Package gitlab provides a GitLab platform implementation for fetching merge request data from GitLab instances.
|
Package gitlab provides a GitLab platform implementation for fetching merge request data from GitLab instances. |
|
Package pr provides convenience functions for fetching pull requests with automatic platform detection and authentication resolution.
|
Package pr provides convenience functions for fetching pull requests with automatic platform detection and authentication resolution. |